mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-12-26 09:20:34 +05:00
22359: Body Fitting algorithm: grid orientation
22358: Body Fitting algorithm: origin point of grid defined by spacing
This commit is contained in:
parent
fee6909125
commit
cd3ffac3fa
@ -50,3 +50,40 @@ print "nb hexahedra",mesh.NbHexas()
|
||||
print "nb tetrahedra",mesh.NbTetras()
|
||||
print "nb polyhedra",mesh.NbPolyhedrons()
|
||||
print
|
||||
|
||||
# Example of customization of dirtections of the grid axes
|
||||
|
||||
# make a box with non-orthogonal edges
|
||||
xDir = geompy.MakeVectorDXDYDZ( 1.0, 0.1, 0.0, "xDir" )
|
||||
yDir = geompy.MakeVectorDXDYDZ(-0.1, 1.0, 0.0, "yDir" )
|
||||
zDir = geompy.MakeVectorDXDYDZ( 0.2, 0.3, 1.0, "zDir" )
|
||||
face = geompy.MakePrismVecH( xDir, yDir, 1.0 )
|
||||
box = geompy.MakePrismVecH( face, zDir, 1.0, theName="box" )
|
||||
|
||||
spc = "0.1" # spacing
|
||||
|
||||
# default axes
|
||||
mesh = smesh.Mesh( box, "custom axes")
|
||||
algo = mesh.BodyFitted()
|
||||
algo.SetGrid( spc, spc, spc, 10000 )
|
||||
mesh.Compute()
|
||||
print "Default axes"
|
||||
print " nb hex:",mesh.NbHexas()
|
||||
|
||||
# set axes using edges of the box
|
||||
algo.SetAxesDirs( xDir, [-0.1,1,0], zDir )
|
||||
mesh.Compute()
|
||||
print "Manual axes"
|
||||
print " nb hex:",mesh.NbHexas()
|
||||
|
||||
# set optimal orthogonal axes
|
||||
algo.SetOptimalAxesDirs( isOrthogonal=True )
|
||||
mesh.Compute()
|
||||
print "Optimal orthogonal axes"
|
||||
print " nb hex:",mesh.NbHexas()
|
||||
|
||||
# set optimal non-orthogonal axes
|
||||
algo.SetOptimalAxesDirs( isOrthogonal=False )
|
||||
mesh.Compute()
|
||||
print "Optimal non-orthogonal axes"
|
||||
print " nb hex:",mesh.NbHexas()
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 59 KiB |
BIN
doc/salome/gui/SMESH/images/cartesian_implement_edge.png
Normal file
BIN
doc/salome/gui/SMESH/images/cartesian_implement_edge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.3 KiB |
@ -31,7 +31,7 @@ nodes are inside and some outside. </li>
|
||||
To apply this algorithm when you define your mesh, select <b>Body
|
||||
Fitting</b> in the list of 3D algorithms and click <em> "Add
|
||||
Hypothesis" </em> button and <em>"Body Fitting Parameters"</em>" menu
|
||||
item. Dialog of <b>Body Fitting Parameters
|
||||
item. Dialog of <b>Body Fitting Parameters
|
||||
hypothesis</b> will appear.
|
||||
|
||||
<br>
|
||||
@ -42,30 +42,60 @@ To apply this algorithm when you define your mesh, select <b>Body
|
||||
|
||||
This dialog allows to define
|
||||
<ul>
|
||||
<li>\b Name of the algorithm </li>
|
||||
<li> Minimal size of a cell truncated by the geometry boundary. If the
|
||||
size of a truncated grid cell is \b Threshold times less than a
|
||||
initial cell size, then a mesh element is not created. </li>
|
||||
<li> Cartesian structured grid. Each grid axis is defined
|
||||
individually. <b> Definition mode </b> chooses a way of grid
|
||||
definition: <ul>
|
||||
<li> You can specify the \b Coordinates of grid nodes. \b Insert button
|
||||
inserts a node at distance \b Step (negative or positive) from a
|
||||
selected node. \b Delete button removes a selected node. Double
|
||||
click on a coordinate in the list enables its edition. A grid
|
||||
defined by \b Coordinates should enclose the geometry, else the
|
||||
algorithm will fail. </li>
|
||||
<li> You can define the \b Spacing of a grid as an algebraic formula
|
||||
<em>f(t)</em> where \a t is a position along a grid axis
|
||||
normalized at [0.0,1.0]. The whole range of geometry can be
|
||||
divided into sub-ranges with their own spacing formulas to apply;
|
||||
<li>\b Name of the algorithm. </li>
|
||||
<li> Minimal size of a cell truncated by the geometry boundary. If the
|
||||
size of a truncated grid cell is \b Threshold times less than a
|
||||
initial cell size, then a mesh element is not created. </li>
|
||||
<li> <b> Implement Edges </b> check-box activates incorporation of
|
||||
geometrical edges in the mesh.
|
||||
\image html cartesian_implement_edge.png "'Implement Edges' switched off (left) and on (right)"
|
||||
<li> Cartesian structured grid. Location of nodes along each grid axis
|
||||
is defined individually. <b> Definition mode </b> chooses a way of
|
||||
grid definition:
|
||||
<ul>
|
||||
<li> You can specify the \b Coordinates of grid nodes. \b Insert button
|
||||
inserts a node at distance \b Step (negative or positive) from a
|
||||
selected node. \b Delete button removes a selected node. Double
|
||||
click on a coordinate in the list enables its edition.
|
||||
\b Note that node coordinates are measured along directions of
|
||||
axes that can differ from the directions of the Global Coordinate
|
||||
System.</li>
|
||||
<li> You can define the \b Spacing of a grid as an algebraic formula
|
||||
<em>f(t)</em> where \a t is a position along a grid axis
|
||||
normalized at [0.0,1.0]. The whole range of geometry can be
|
||||
divided into sub-ranges with their own spacing formulas to apply;
|
||||
\a t varies between 0.0 and 1.0 within each sub-range. \b Insert button
|
||||
divides a selected range into two ones. \b Delete button adds the
|
||||
selected sub-range to the previous one. Double click on a range in
|
||||
the list enables edition of its right boundary. Double click on a
|
||||
function in the list enables its edition.
|
||||
</li> </ul>
|
||||
</li>
|
||||
divides a selected range into two ones. \b Delete button adds the
|
||||
selected sub-range to the previous one. Double click on a range in
|
||||
the list enables edition of its right boundary. Double click on a
|
||||
function in the list enables its edition.
|
||||
</li> </ul>
|
||||
</li>
|
||||
<li> Coordinates of a <b> Fixed Point</b>. They allow to exactly
|
||||
locate a grid node in a direction defined by spacing. If all the three
|
||||
directions are defined by spacing, then there will be a mesh node at
|
||||
the <b> Fixed Point</b>. If two directions are defined by spacing,
|
||||
then there will be at least a link between mesh nodes passing through
|
||||
the <b> Fixed Point</b>. If only one direction is defined by spacing,
|
||||
then there will be at least an element facet passing through
|
||||
the <b> Fixed Point</b>. If no directions are defined by spacing,
|
||||
<b> Fixed Point</b> is disabled.</li>
|
||||
<li> <b> Directions of Axes</b>. You can set up almost any
|
||||
directions of grid axes that can help in generation as many as
|
||||
possible hexahedral elements.
|
||||
<ul>
|
||||
<li><b> Orthogonal Axes </b> check-box, if activated, keeps the
|
||||
axes orthogonal during their modification. </li>
|
||||
<li> Selection buttons enable snapping corresponding axes to
|
||||
direction of a geometrical edge selected in the Object
|
||||
Browser. Edge direction is defined by coordinates of its end
|
||||
points.</li>
|
||||
<li><b> Optimal Axes</b> button runs an algorithm that tries to
|
||||
set the axes so that a number of generated hexahedra to be
|
||||
maximal.</li>
|
||||
<li><b> Reset </b> button returns the axes in a default position
|
||||
parallel to the axes of the Global Coordinate System.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
@ -942,8 +942,9 @@ module StdMeshers
|
||||
/*!
|
||||
* interface of "Body fitting Parameters" hypothesis.
|
||||
* This hypothesis specifies
|
||||
* - Definition of the Cartesian grid
|
||||
* - Size threshold
|
||||
* - Definition of the Cartesian grid
|
||||
* - Direction of grid axes
|
||||
*/
|
||||
interface StdMeshers_CartesianParameters3D : SMESH::SMESH_Hypothesis
|
||||
{
|
||||
@ -965,8 +966,8 @@ module StdMeshers
|
||||
/*!
|
||||
* Set coordinates of nodes along an axis (countered from zero)
|
||||
*/
|
||||
void SetGrid(in SMESH::double_array coords,
|
||||
in short axis) raises (SALOME::SALOME_Exception);
|
||||
void SetGrid(in SMESH::double_array coords,
|
||||
in short axis) raises (SALOME::SALOME_Exception);
|
||||
SMESH::double_array GetGrid(in short axis) raises (SALOME::SALOME_Exception);
|
||||
|
||||
/*!
|
||||
@ -985,6 +986,22 @@ module StdMeshers
|
||||
void GetGridSpacing(out SMESH::string_array spaceFunctions,
|
||||
out SMESH::double_array internalPoints,
|
||||
in short axis) raises (SALOME::SALOME_Exception);
|
||||
/*!
|
||||
* Set custom direction of axes
|
||||
*/
|
||||
void SetAxesDirs(in SMESH::DirStruct x,
|
||||
in SMESH::DirStruct y,
|
||||
in SMESH::DirStruct z ) raises (SALOME::SALOME_Exception);
|
||||
void GetAxesDirs(out SMESH::DirStruct x,
|
||||
out SMESH::DirStruct y,
|
||||
out SMESH::DirStruct z );
|
||||
/*!
|
||||
* Set/unset a fixed point, at which a node will be created provided that grid
|
||||
* is defined by spacing in all directions
|
||||
*/
|
||||
void SetFixedPoint(in SMESH::PointStruct p, in boolean toUnset);
|
||||
boolean GetFixedPoint(out SMESH::PointStruct p);
|
||||
|
||||
/*!
|
||||
* Enables implementation of geometrical edges into the mesh. If this feature
|
||||
* is disabled, sharp edges of the shape are lost ("smoothed") in the mesh if
|
||||
@ -993,6 +1010,16 @@ module StdMeshers
|
||||
void SetToAddEdges(in boolean toAdd);
|
||||
boolean GetToAddEdges();
|
||||
|
||||
/*!
|
||||
* Returns axes at which a number of generated hexahedra is maximal
|
||||
*/
|
||||
void ComputeOptimalAxesDirs(in GEOM::GEOM_Object shape,
|
||||
in boolean isOrthogonal,
|
||||
out SMESH::DirStruct x,
|
||||
out SMESH::DirStruct y,
|
||||
out SMESH::DirStruct z )
|
||||
raises (SALOME::SALOME_Exception);
|
||||
|
||||
/*!
|
||||
* \brief Computes node coordinates by spacing functions
|
||||
* \param x0 - lower coordinate
|
||||
|
@ -2632,6 +2632,8 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th
|
||||
hyp->SetConvMethodAndType( "SetGrid", "Cartesian_3D");
|
||||
for ( int iArg = 0; iArg < 4; ++iArg )
|
||||
hyp->setCreationArg( iArg+1, "[]");
|
||||
hyp->AddAccumulativeMethod( "SetGrid" );
|
||||
hyp->AddAccumulativeMethod( "SetGridSpacing" );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3114,7 +3116,9 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
|
||||
myCurCrMethod->myArgs[ iArg ] += "]";
|
||||
}
|
||||
myArgCommands.push_back( theCommand );
|
||||
rememberCmdOfParameter( theCommand );
|
||||
//rememberCmdOfParameter( theCommand ); -- these commands are marked as
|
||||
// accumulative, else, if the creation
|
||||
// is not converted, commands for axes 1 and 2 are lost
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ class StdMeshersBuilder_Quadrangle(Mesh_Algorithm):
|
||||
# must be created by the mesher. Shapes can be of any type,
|
||||
# vertices of given shapes define positions of enforced nodes.
|
||||
# Only vertices successfully projected to the face are used.
|
||||
# @param enfPoint: list of points giving positions of enforced nodes.
|
||||
# @param enfPoints: list of points giving positions of enforced nodes.
|
||||
# Point can be defined either as SMESH.PointStruct's
|
||||
# ([SMESH.PointStruct(x1,y1,z1), SMESH.PointStruct(x2,y2,z2),...])
|
||||
# or triples of values ([[x1,y1,z1], [x2,y2,z2], ...]).
|
||||
@ -1415,7 +1415,7 @@ class StdMeshersBuilder_Cartesian_3D(Mesh_Algorithm):
|
||||
if not self.mesh.IsUsedHypothesis( self.hyp, self.geom ):
|
||||
self.mesh.AddHypothesis( self.hyp, self.geom )
|
||||
|
||||
for axis, gridDef in enumerate( [xGridDef, yGridDef, zGridDef]):
|
||||
for axis, gridDef in enumerate( [xGridDef, yGridDef, zGridDef] ):
|
||||
if not gridDef: raise ValueError, "Empty grid definition"
|
||||
if isinstance( gridDef, str ):
|
||||
self.hyp.SetGridSpacing( [gridDef], [], axis )
|
||||
@ -1429,6 +1429,64 @@ class StdMeshersBuilder_Cartesian_3D(Mesh_Algorithm):
|
||||
self.hyp.SetSizeThreshold( sizeThreshold )
|
||||
return self.hyp
|
||||
|
||||
## Defines custom directions of axes of the grid
|
||||
# @param xAxis either SMESH.DirStruct or a vector, or 3 vector components
|
||||
# @param yAxis either SMESH.DirStruct or a vector, or 3 vector components
|
||||
# @param zAxis either SMESH.DirStruct or a vector, or 3 vector components
|
||||
def SetAxesDirs( self, xAxis, yAxis, zAxis ):
|
||||
import GEOM
|
||||
if hasattr( xAxis, "__getitem__" ):
|
||||
xAxis = self.mesh.smeshpyD.MakeDirStruct( xAxis[0],xAxis[1],xAxis[2] )
|
||||
elif isinstance( xAxis, GEOM._objref_GEOM_Object ):
|
||||
xAxis = self.mesh.smeshpyD.GetDirStruct( xAxis )
|
||||
if hasattr( yAxis, "__getitem__" ):
|
||||
yAxis = self.mesh.smeshpyD.MakeDirStruct( yAxis[0],yAxis[1],yAxis[2] )
|
||||
elif isinstance( yAxis, GEOM._objref_GEOM_Object ):
|
||||
yAxis = self.mesh.smeshpyD.GetDirStruct( yAxis )
|
||||
if hasattr( zAxis, "__getitem__" ):
|
||||
zAxis = self.mesh.smeshpyD.MakeDirStruct( zAxis[0],zAxis[1],zAxis[2] )
|
||||
elif isinstance( zAxis, GEOM._objref_GEOM_Object ):
|
||||
zAxis = self.mesh.smeshpyD.GetDirStruct( zAxis )
|
||||
if not self.hyp:
|
||||
self.hyp = self.Hypothesis("CartesianParameters3D")
|
||||
if not self.mesh.IsUsedHypothesis( self.hyp, self.geom ):
|
||||
self.mesh.AddHypothesis( self.hyp, self.geom )
|
||||
self.hyp.SetAxesDirs( xAxis, yAxis, zAxis )
|
||||
return self.hyp
|
||||
|
||||
## Automatically defines directions of axes of the grid at which
|
||||
# a number of generated hexahedra is maximal
|
||||
# @param isOrthogonal defines whether the axes mush be orthogonal
|
||||
def SetOptimalAxesDirs(self, isOrthogonal=True):
|
||||
if not self.hyp:
|
||||
self.hyp = self.Hypothesis("CartesianParameters3D")
|
||||
if not self.mesh.IsUsedHypothesis( self.hyp, self.geom ):
|
||||
self.mesh.AddHypothesis( self.hyp, self.geom )
|
||||
x,y,z = self.hyp.ComputeOptimalAxesDirs( self.geom, isOrthogonal )
|
||||
self.hyp.SetAxesDirs( x,y,z )
|
||||
return self.hyp
|
||||
|
||||
## Sets/unsets a fixed point. The algorithm makes a plane of the grid pass
|
||||
# through the fixed point in each direction at which the grid is defined
|
||||
# by spacing
|
||||
# @param p coordinates of the fixed point. Either SMESH.PointStruct or
|
||||
# 3 components of coordinates.
|
||||
# @param toUnset defines whether the fixed point is defined or removed.
|
||||
def SetFixedPoint( self, p, toUnset=False ):
|
||||
import SMESH
|
||||
if toUnset:
|
||||
if not self.hyp: return
|
||||
p = SMESH.PointStruct(0,0,0)
|
||||
if hasattr( p, "__getitem__" ):
|
||||
p = SMESH.PointStruct( p[0],p[1],p[2] )
|
||||
if not self.hyp:
|
||||
self.hyp = self.Hypothesis("CartesianParameters3D")
|
||||
if not self.mesh.IsUsedHypothesis( self.hyp, self.geom ):
|
||||
self.mesh.AddHypothesis( self.hyp, self.geom )
|
||||
self.hyp.SetFixedPoint( p, toUnset )
|
||||
return self.hyp
|
||||
|
||||
|
||||
pass # end of StdMeshersBuilder_Cartesian_3D class
|
||||
|
||||
## Defines a stub 1D algorithm, which enables "manual" creation of nodes and
|
||||
|
@ -32,10 +32,24 @@
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#include <map>
|
||||
#include <limits>
|
||||
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <GeomLib_IsPlanarSurface.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <TopTools_MapIteratorOfMapOfShape.hxx>
|
||||
#include <TopTools_MapOfShape.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
|
||||
using namespace std;
|
||||
@ -66,6 +80,11 @@ StdMeshers_CartesianParameters3D::StdMeshers_CartesianParameters3D(int h
|
||||
_axisDirs[6] = 0.;
|
||||
_axisDirs[7] = 0.;
|
||||
_axisDirs[8] = 1.;
|
||||
|
||||
_fixedPoint[0] = 0.;
|
||||
_fixedPoint[1] = 0.;
|
||||
_fixedPoint[2] = 0.;
|
||||
SetFixedPoint( _fixedPoint, /*toUnset=*/true );
|
||||
}
|
||||
|
||||
|
||||
@ -73,6 +92,22 @@ namespace
|
||||
{
|
||||
const char* axisName[3] = { "X", "Y", "Z" };
|
||||
|
||||
typedef std::pair< double, std::pair< double, double > > TCooTriple;
|
||||
|
||||
#define gpXYZ( cTriple ) gp_XYZ( (cTriple).first, (cTriple).second.first, (cTriple).second.second )
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Compare two normals
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool sameDir( const TCooTriple& n1, const TCooTriple& n2 )
|
||||
{
|
||||
gp_XYZ xyz1 = gpXYZ( n1 ), xyz2 = gpXYZ( n2 );
|
||||
return ( xyz1 - xyz2 ).Modulus() < 0.01;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Checks validity of an axis index, throws in case of invalidity
|
||||
@ -177,6 +212,36 @@ void StdMeshers_CartesianParameters3D::SetGridSpacing(std::vector<string>& xSpac
|
||||
NotifySubMeshesHypothesisModification();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetFixedPoint
|
||||
//purpose : * Set/unset a fixed point, at which a node will be created provided that grid
|
||||
// * is defined by spacing in all directions
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D::SetFixedPoint(const double p[3], bool toUnset)
|
||||
{
|
||||
if ( toUnset != Precision::IsInfinite( _fixedPoint[0] ))
|
||||
NotifySubMeshesHypothesisModification();
|
||||
|
||||
if ( toUnset )
|
||||
_fixedPoint[0] = Precision::Infinite();
|
||||
else
|
||||
std::copy( &p[0], &p[0]+3, &_fixedPoint[0] );
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetFixedPoint
|
||||
//purpose : Returns either false or (true + point coordinates)
|
||||
//=======================================================================
|
||||
|
||||
bool StdMeshers_CartesianParameters3D::GetFixedPoint(double p[3])
|
||||
{
|
||||
if ( Precision::IsInfinite( _fixedPoint[0] ))
|
||||
return false;
|
||||
std::copy( &_fixedPoint[0], &_fixedPoint[0]+3, &p[0] );
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//function : SetSizeThreshold
|
||||
//purpose : Set size threshold
|
||||
@ -322,9 +387,199 @@ void StdMeshers_CartesianParameters3D::GetCoordinates(std::vector<double>& xNode
|
||||
zNodes = _coords[2];
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ComputeOptimalAxesDirs
|
||||
//purpose : Returns axes at which number of hexahedra is maximal
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D::
|
||||
ComputeOptimalAxesDirs(const TopoDS_Shape& shape,
|
||||
const bool isOrthogonal,
|
||||
double dirCoords[9])
|
||||
{
|
||||
for ( int i = 0; i < 9; ++i ) dirCoords[i] = 0.;
|
||||
dirCoords[0] = dirCoords[4] = dirCoords[8] = 1.;
|
||||
|
||||
if ( shape.IsNull() ) return;
|
||||
|
||||
TopLoc_Location loc;
|
||||
TopExp_Explorer exp;
|
||||
|
||||
// get external FACEs of the shape
|
||||
TopTools_MapOfShape faceMap;
|
||||
for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() )
|
||||
if ( !faceMap.Add( exp.Current() ))
|
||||
faceMap.Remove( exp.Current() );
|
||||
|
||||
// sort areas of planar faces by normal direction
|
||||
|
||||
std::multimap< TCooTriple, double > areasByNormal;
|
||||
|
||||
TopTools_MapIteratorOfMapOfShape fIt ( faceMap );
|
||||
for ( ; fIt.More(); fIt.Next() )
|
||||
{
|
||||
const TopoDS_Face& face = TopoDS::Face( fIt.Key() );
|
||||
Handle(Geom_Surface) surf = BRep_Tool::Surface( face, loc );
|
||||
if ( surf.IsNull() ) continue;
|
||||
|
||||
GeomLib_IsPlanarSurface check( surf, 1e-5 );
|
||||
if ( !check.IsPlanar() ) continue;
|
||||
|
||||
GProp_GProps SProps;
|
||||
BRepGProp::SurfaceProperties( face, SProps );
|
||||
double area = SProps.Mass();
|
||||
|
||||
gp_Pln pln = check.Plan();
|
||||
gp_Dir norm = pln.Axis().Direction().Transformed( loc );
|
||||
if ( norm.X() < -1e-3 ) { // negative X
|
||||
norm.Reverse();
|
||||
} else if ( norm.X() < 1e-3 ) { // zero X
|
||||
if ( norm.Y() < -1e-3 ) { // negative Y
|
||||
norm.Reverse();
|
||||
} else if ( norm.Y() < 1e-3 ) { // zero X && zero Y
|
||||
if ( norm.Y() < -1e-3 ) // negative Z
|
||||
norm.Reverse();
|
||||
}
|
||||
}
|
||||
TCooTriple coo3( norm.X(), make_pair( norm.Y(), norm.Z() ));
|
||||
areasByNormal.insert( make_pair( coo3, area ));
|
||||
}
|
||||
|
||||
// group coplanar normals and sort groups by sum area
|
||||
|
||||
std::multimap< double, vector< const TCooTriple* > > normsByArea;
|
||||
std::multimap< TCooTriple, double >::iterator norm2a = areasByNormal.begin();
|
||||
const TCooTriple* norm1 = 0;
|
||||
double sumArea = 0;
|
||||
vector< const TCooTriple* > norms;
|
||||
for ( int iF = 1; norm2a != areasByNormal.end(); ++norm2a, ++iF )
|
||||
{
|
||||
|
||||
if ( !norm1 || !sameDir( *norm1, norm2a->first ))
|
||||
{
|
||||
if ( !norms.empty() )
|
||||
{
|
||||
normsByArea.insert( make_pair( sumArea, norms ));
|
||||
norms.clear();
|
||||
}
|
||||
norm1 = & norm2a->first;
|
||||
sumArea = norm2a->second;
|
||||
norms.push_back( norm1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sumArea += norm2a->second;
|
||||
norms.push_back( & norm2a->first );
|
||||
}
|
||||
if ( iF == areasByNormal.size() )
|
||||
normsByArea.insert( make_pair( sumArea, norms ));
|
||||
}
|
||||
|
||||
// try to set dirs by planar faces
|
||||
|
||||
gp_XYZ normDirs[3]; // normals to largest planes
|
||||
|
||||
if ( !normsByArea.empty() )
|
||||
{
|
||||
norm1 = normsByArea.rbegin()->second[0];
|
||||
normDirs[0] = gpXYZ( *norm1 );
|
||||
|
||||
if ( normsByArea.size() == 1 )
|
||||
{
|
||||
normDirs[1] = normDirs[0];
|
||||
if ( Abs( normDirs[0].Y() ) < 1e-100 &&
|
||||
Abs( normDirs[0].Z() ) < 1e-100 ) // normDirs[0] || OX
|
||||
normDirs[1].SetY( normDirs[0].Y() + 1. );
|
||||
else
|
||||
normDirs[1].SetX( normDirs[0].X() + 1. );
|
||||
}
|
||||
else
|
||||
{
|
||||
// look for 2 other directions
|
||||
gp_XYZ testDir = normDirs[0], minDir, maxDir;
|
||||
for ( int is2nd = 0; is2nd < 2; ++is2nd )
|
||||
{
|
||||
double maxMetric = 0, minMetric = 1e100;
|
||||
std::multimap< double, vector< const TCooTriple* > >::iterator a2n;
|
||||
for ( a2n = normsByArea.begin(); a2n != normsByArea.end(); ++a2n )
|
||||
{
|
||||
gp_XYZ n = gpXYZ( *( a2n->second[0]) );
|
||||
double dot = Abs( n * testDir );
|
||||
double metric = ( 1. - dot ) * ( isOrthogonal ? 1 : a2n->first );
|
||||
if ( metric > maxMetric )
|
||||
{
|
||||
maxDir = n;
|
||||
maxMetric = metric;
|
||||
}
|
||||
if ( metric < minMetric )
|
||||
{
|
||||
minDir = n;
|
||||
minMetric = metric;
|
||||
}
|
||||
}
|
||||
if ( is2nd )
|
||||
{
|
||||
normDirs[2] = minDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
normDirs[1] = maxDir;
|
||||
normDirs[2] = normDirs[0] ^ normDirs[1];
|
||||
if ( isOrthogonal || normsByArea.size() < 3 )
|
||||
break;
|
||||
testDir = normDirs[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( isOrthogonal || normsByArea.size() == 1 )
|
||||
{
|
||||
normDirs[2] = normDirs[0] ^ normDirs[1];
|
||||
normDirs[1] = normDirs[2] ^ normDirs[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gp_XYZ dirs[3];
|
||||
dirs[0] = normDirs[0] ^ normDirs[1];
|
||||
dirs[1] = normDirs[1] ^ normDirs[2];
|
||||
dirs[2] = normDirs[2] ^ normDirs[0];
|
||||
|
||||
dirs[0].Normalize();
|
||||
dirs[1].Normalize();
|
||||
dirs[2].Normalize();
|
||||
|
||||
// Select dirs for X, Y and Z axes
|
||||
int iX = ( Abs( dirs[0].X() ) > Abs( dirs[1].X() )) ? 0 : 1;
|
||||
if ( Abs( dirs[iX].X() ) < Abs( dirs[2].X() ))
|
||||
iX = 2;
|
||||
int iY = ( iX == 0 ) ? 1 : (( Abs( dirs[0].Y() ) > Abs( dirs[1].Y() )) ? 0 : 1 );
|
||||
if ( Abs( dirs[iY].Y() ) < Abs( dirs[2].Y() ) && iX != 2 )
|
||||
iY = 2;
|
||||
int iZ = 3 - iX - iY;
|
||||
|
||||
if ( dirs[iX].X() < 0 ) dirs[iX].Reverse();
|
||||
if ( dirs[iY].Y() < 0 ) dirs[iY].Reverse();
|
||||
gp_XYZ zDir = dirs[iX] ^ dirs[iY];
|
||||
if ( dirs[iZ] * zDir < 0 )
|
||||
dirs[iZ].Reverse();
|
||||
|
||||
dirCoords[0] = dirs[iX].X();
|
||||
dirCoords[1] = dirs[iX].Y();
|
||||
dirCoords[2] = dirs[iX].Z();
|
||||
dirCoords[3] = dirs[iY].X();
|
||||
dirCoords[4] = dirs[iY].Y();
|
||||
dirCoords[5] = dirs[iY].Z();
|
||||
dirCoords[6] = dirs[iZ].X();
|
||||
dirCoords[7] = dirs[iZ].Y();
|
||||
dirCoords[8] = dirs[iZ].Z();
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetAxisDirs
|
||||
//purpose : Sets directions of axes
|
||||
//purpose : Sets custom direction of axes
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
|
||||
@ -349,6 +604,10 @@ void StdMeshers_CartesianParameters3D::SetAxisDirs(const double* the9DirComps)
|
||||
y.IsParallel( z, M_PI / 180. ))
|
||||
throw SALOME_Exception("Parallel axis directions");
|
||||
|
||||
gp_Vec normXY = x ^ y, normYZ = y ^ z;
|
||||
if ( normXY.IsParallel( normYZ, M_PI / 180. ))
|
||||
throw SALOME_Exception("Axes lie in one plane");
|
||||
|
||||
bool isChanged = false;
|
||||
for ( int i = 0; i < 9; ++i )
|
||||
{
|
||||
@ -450,6 +709,14 @@ std::ostream & StdMeshers_CartesianParameters3D::SaveTo(std::ostream & save)
|
||||
}
|
||||
save << _toAddEdges << " ";
|
||||
|
||||
save.setf( save.scientific );
|
||||
save.precision( 12 );
|
||||
for ( int i = 0; i < 9; ++i )
|
||||
save << _axisDirs[i] << " ";
|
||||
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
save << _fixedPoint[i] << " ";
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
@ -500,7 +767,13 @@ std::istream & StdMeshers_CartesianParameters3D::LoadFrom(std::istream & load)
|
||||
}
|
||||
}
|
||||
|
||||
load >> _toAddEdges;
|
||||
ok = ( load >> _toAddEdges );
|
||||
|
||||
for ( int i = 0; i < 9 && ok; ++i )
|
||||
ok = ( load >> _axisDirs[i]);
|
||||
|
||||
for ( int i = 0; i < 3 && ok ; ++i )
|
||||
ok = ( load >> _fixedPoint[i]);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
@ -78,6 +78,13 @@ public:
|
||||
|
||||
bool IsGridBySpacing(const int axis) const throw ( SALOME_Exception );
|
||||
|
||||
/*!
|
||||
* Set/unset a fixed point, at which a node will be created provided that grid
|
||||
* is defined by spacing in all directions
|
||||
*/
|
||||
void SetFixedPoint(const double p[3], bool toUnset);
|
||||
bool GetFixedPoint(double p[3]);
|
||||
|
||||
/*!
|
||||
* \brief Computes node coordinates by spacing functions
|
||||
* \param x0 - lower coordinate
|
||||
@ -101,9 +108,17 @@ public:
|
||||
std::vector<double>& zNodes,
|
||||
const Bnd_Box& bndBox) const throw ( SALOME_Exception );
|
||||
|
||||
/*!
|
||||
* \brief Set custom direction of axes
|
||||
*/
|
||||
void SetAxisDirs(const double* the9DirComps) throw ( SALOME_Exception );
|
||||
const double* GetAxisDirs() const { return _axisDirs; }
|
||||
|
||||
/*!
|
||||
* \brief Returns axes at which number of hexahedra is maximal
|
||||
*/
|
||||
static void ComputeOptimalAxesDirs(const TopoDS_Shape& shape,
|
||||
const bool isOrthogonal,
|
||||
double dirCoords[9]);
|
||||
/*!
|
||||
* Set size threshold. A polyhedral cell got by cutting an initial
|
||||
* hexahedron by geometry boundary is considered small and is removed if
|
||||
@ -150,7 +165,8 @@ public:
|
||||
std::vector<std::string> _spaceFunctions[3];
|
||||
std::vector<double> _internalPoints[3];
|
||||
|
||||
double _axisDirs[9];
|
||||
double _axisDirs [9];
|
||||
double _fixedPoint[3];
|
||||
|
||||
double _sizeThreshold;
|
||||
bool _toAddEdges;
|
||||
|
@ -37,12 +37,17 @@
|
||||
#include <Utils_ExceptHandlers.hxx>
|
||||
#include <Basics_OCCTVersion.hxx>
|
||||
|
||||
#include <GEOMUtils.hxx>
|
||||
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepBuilderAPI_Copy.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Bnd_B3d.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <ElSLib.hxx>
|
||||
#include <GCPnts_UniformDeflection.hxx>
|
||||
@ -67,6 +72,7 @@
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <TopTools_MapOfShape.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_TShape.hxx>
|
||||
#include <gp_Cone.hxx>
|
||||
@ -218,12 +224,9 @@ namespace
|
||||
*/
|
||||
struct GridPlanes
|
||||
{
|
||||
double _factor;
|
||||
gp_XYZ _uNorm, _vNorm, _zNorm;
|
||||
vector< gp_XYZ > _origins; // origin points of all planes in one direction
|
||||
vector< double > _zProjs; // projections of origins to _zNorm
|
||||
|
||||
gp_XY GetUV( const gp_Pnt& p, const gp_Pnt& origin );
|
||||
};
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
@ -276,6 +279,9 @@ namespace
|
||||
gp_XYZ _axes [3]; // axis directions
|
||||
vector< GridLine > _lines [3]; // in 3 directions
|
||||
double _tol, _minCellSize;
|
||||
gp_XYZ _origin;
|
||||
gp_Mat _invB; // inverted basis of _axes
|
||||
//bool _isOrthogonalAxes;
|
||||
|
||||
vector< const SMDS_MeshNode* > _nodes; // mesh nodes at grid nodes
|
||||
vector< const F_IntersectPoint* > _gridIntP; // grid node intersection with geometry
|
||||
@ -301,7 +307,8 @@ namespace
|
||||
const vector<double>& yCoords,
|
||||
const vector<double>& zCoords,
|
||||
const double* axesDirs,
|
||||
const TopoDS_Shape& shape );
|
||||
const Bnd_Box& bndBox );
|
||||
void ComputeUVW(const gp_XYZ& p, double uvw[3]);
|
||||
void ComputeNodes(SMESH_MesherHelper& helper);
|
||||
};
|
||||
#ifdef ELLIPSOLID_WORKAROUND
|
||||
@ -646,7 +653,7 @@ namespace
|
||||
inline void locateValue( int & i, double val, const vector<double>& values,
|
||||
int& di, double tol )
|
||||
{
|
||||
val += values[0]; // input \a val is measured from 0.
|
||||
//val += values[0]; // input \a val is measured from 0.
|
||||
if ( i > values.size()-2 )
|
||||
i = values.size()-2;
|
||||
else
|
||||
@ -721,16 +728,6 @@ namespace
|
||||
return prevIsOut; // _transition == Trans_TANGENT
|
||||
}
|
||||
//================================================================================
|
||||
/*
|
||||
* Returns parameters of a point in i-th plane
|
||||
*/
|
||||
gp_XY GridPlanes::GetUV( const gp_Pnt& p, const gp_Pnt& origin )
|
||||
{
|
||||
gp_Vec v( origin, p );
|
||||
return gp_XY( v.Dot( _uNorm ) * _factor,
|
||||
v.Dot( _vNorm ) * _factor );
|
||||
}
|
||||
//================================================================================
|
||||
/*
|
||||
* Adds face IDs
|
||||
*/
|
||||
@ -793,11 +790,12 @@ namespace
|
||||
const vector<double>& yCoords,
|
||||
const vector<double>& zCoords,
|
||||
const double* axesDirs,
|
||||
const TopoDS_Shape& shape)
|
||||
const Bnd_Box& shapeBox)
|
||||
{
|
||||
_coords[0] = xCoords;
|
||||
_coords[1] = yCoords;
|
||||
_coords[2] = zCoords;
|
||||
|
||||
_axes[0].SetCoord( axesDirs[0],
|
||||
axesDirs[1],
|
||||
axesDirs[2]);
|
||||
@ -807,6 +805,16 @@ namespace
|
||||
_axes[2].SetCoord( axesDirs[6],
|
||||
axesDirs[7],
|
||||
axesDirs[8]);
|
||||
_axes[0].Normalize();
|
||||
_axes[1].Normalize();
|
||||
_axes[2].Normalize();
|
||||
|
||||
_invB.SetCols( _axes[0], _axes[1], _axes[2] );
|
||||
_invB.Invert();
|
||||
|
||||
// _isOrthogonalAxes = ( Abs( _axes[0] * _axes[1] ) < 1e-20 &&
|
||||
// Abs( _axes[1] * _axes[2] ) < 1e-20 &&
|
||||
// Abs( _axes[2] * _axes[0] ) < 1e-20 );
|
||||
|
||||
// compute tolerance
|
||||
_minCellSize = Precision::Infinite();
|
||||
@ -821,13 +829,10 @@ namespace
|
||||
}
|
||||
if ( _minCellSize < Precision::Confusion() )
|
||||
throw SMESH_ComputeError (COMPERR_ALGO_FAILED,
|
||||
SMESH_Comment("Too small cell size: ") << _tol );
|
||||
SMESH_Comment("Too small cell size: ") << _minCellSize );
|
||||
_tol = _minCellSize / 1000.;
|
||||
|
||||
// attune grid extremities to shape bounding box computed by vertices
|
||||
Bnd_Box shapeBox;
|
||||
for ( TopExp_Explorer vExp( shape, TopAbs_VERTEX ); vExp.More(); vExp.Next() )
|
||||
shapeBox.Add( BRep_Tool::Pnt( TopoDS::Vertex( vExp.Current() )));
|
||||
// attune grid extremities to shape bounding box
|
||||
|
||||
double sP[6]; // aXmin, aYmin, aZmin, aXmax, aYmax, aZmax
|
||||
shapeBox.Get(sP[0],sP[1],sP[2],sP[3],sP[4],sP[5]);
|
||||
@ -835,7 +840,26 @@ namespace
|
||||
&_coords[0].back(), &_coords[1].back(), &_coords[2].back() };
|
||||
for ( int i = 0; i < 6; ++i )
|
||||
if ( fabs( sP[i] - *cP[i] ) < _tol )
|
||||
*cP[i] = sP[i] + _tol/1000. * ( i < 3 ? +1 : -1 );
|
||||
*cP[i] = sP[i];// + _tol/1000. * ( i < 3 ? +1 : -1 );
|
||||
|
||||
for ( int iDir = 0; iDir < 3; ++iDir )
|
||||
{
|
||||
if ( _coords[iDir][0] - sP[iDir] > _tol )
|
||||
{
|
||||
_minCellSize = Min( _minCellSize, _coords[iDir][0] - sP[iDir] );
|
||||
_coords[iDir].insert( _coords[iDir].begin(), sP[iDir] + _tol/1000.);
|
||||
}
|
||||
if ( sP[iDir+3] - _coords[iDir].back() > _tol )
|
||||
{
|
||||
_minCellSize = Min( _minCellSize, sP[iDir+3] - _coords[iDir].back() );
|
||||
_coords[iDir].push_back( sP[iDir+3] - _tol/1000.);
|
||||
}
|
||||
}
|
||||
_tol = _minCellSize / 1000.;
|
||||
|
||||
_origin = ( _coords[0][0] * _axes[0] +
|
||||
_coords[1][0] * _axes[1] +
|
||||
_coords[2][0] * _axes[2] );
|
||||
|
||||
// create lines
|
||||
for ( int iDir = 0; iDir < 3; ++iDir ) // loop on 3 line directions
|
||||
@ -843,17 +867,34 @@ namespace
|
||||
LineIndexer li = GetLineIndexer( iDir );
|
||||
_lines[iDir].resize( li.NbLines() );
|
||||
double len = _coords[ iDir ].back() - _coords[iDir].front();
|
||||
gp_Vec dir( iDir==0, iDir==1, iDir==2 );
|
||||
for ( ; li.More(); ++li )
|
||||
{
|
||||
GridLine& gl = _lines[iDir][ li.LineIndex() ];
|
||||
gl._line.SetLocation(gp_Pnt(_coords[0][li.I()], _coords[1][li.J()], _coords[2][li.K()]));
|
||||
gl._line.SetDirection( dir );
|
||||
gl._line.SetLocation( _coords[0][li.I()] * _axes[0] +
|
||||
_coords[1][li.J()] * _axes[1] +
|
||||
_coords[2][li.K()] * _axes[2] );
|
||||
gl._line.SetDirection( _axes[ iDir ]);
|
||||
gl._length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
//================================================================================
|
||||
/*
|
||||
* Computes coordinates of a point in the grid CS
|
||||
*/
|
||||
void Grid::ComputeUVW(const gp_XYZ& P, double UVW[3])
|
||||
{
|
||||
// gp_XYZ p = P - _origin;
|
||||
// UVW[ 0 ] = p.X() * _invB( 1, 1 ) + p.Y() * _invB( 1, 2 ) + p.Z() * _invB( 1, 3 );
|
||||
// UVW[ 1 ] = p.X() * _invB( 2, 1 ) + p.Y() * _invB( 2, 2 ) + p.Z() * _invB( 2, 3 );
|
||||
// UVW[ 2 ] = p.X() * _invB( 3, 1 ) + p.Y() * _invB( 3, 2 ) + p.Z() * _invB( 3, 3 );
|
||||
// UVW[ 0 ] += _coords[0][0];
|
||||
// UVW[ 1 ] += _coords[1][0];
|
||||
// UVW[ 2 ] += _coords[2][0];
|
||||
gp_XYZ p = P * _invB;
|
||||
p.Coord( UVW[0], UVW[1], UVW[2] );
|
||||
}
|
||||
//================================================================================
|
||||
/*
|
||||
* Creates all nodes
|
||||
*/
|
||||
@ -882,12 +923,16 @@ namespace
|
||||
nIndex0 = NodeIndex( li.I(), li.J(), li.K() );
|
||||
|
||||
GridLine& line = _lines[ iDir ][ li.LineIndex() ];
|
||||
const gp_XYZ lineLoc = line._line.Location().XYZ();
|
||||
const gp_XYZ lineDir = line._line.Direction().XYZ();
|
||||
line.RemoveExcessIntPoints( _tol );
|
||||
multiset< F_IntersectPoint >& intPnts = _lines[ iDir ][ li.LineIndex() ]._intPoints;
|
||||
multiset< F_IntersectPoint >::iterator ip = intPnts.begin();
|
||||
|
||||
bool isOut = true;
|
||||
const double* nodeCoord = & coords[0], *coord0 = nodeCoord, *coordEnd = coord0 + coords.size();
|
||||
const double* nodeCoord = & coords[0];
|
||||
const double* coord0 = nodeCoord;
|
||||
const double* coordEnd = coord0 + coords.size();
|
||||
double nodeParam = 0;
|
||||
for ( ; ip != intPnts.end(); ++ip )
|
||||
{
|
||||
@ -910,10 +955,11 @@ namespace
|
||||
// create a mesh node on a GridLine at ip if it does not coincide with a grid node
|
||||
if ( nodeParam > ip->_paramOnLine + _tol )
|
||||
{
|
||||
li.SetIndexOnLine( 0 );
|
||||
double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
|
||||
xyz[ li._iConst ] += ip->_paramOnLine;
|
||||
ip->_node = helper.AddNode( xyz[0], xyz[1], xyz[2] );
|
||||
// li.SetIndexOnLine( 0 );
|
||||
// double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
|
||||
// xyz[ li._iConst ] += ip->_paramOnLine;
|
||||
gp_XYZ xyz = lineLoc + ip->_paramOnLine * lineDir;
|
||||
ip->_node = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
|
||||
ip->_indexOnLine = nodeCoord-coord0-1;
|
||||
}
|
||||
// create a mesh node at ip concident with a grid node
|
||||
@ -922,9 +968,10 @@ namespace
|
||||
int nodeIndex = nIndex0 + nShift * ( nodeCoord-coord0 );
|
||||
if ( !_nodes[ nodeIndex ] )
|
||||
{
|
||||
li.SetIndexOnLine( nodeCoord-coord0 );
|
||||
double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
|
||||
_nodes [ nodeIndex ] = helper.AddNode( xyz[0], xyz[1], xyz[2] );
|
||||
//li.SetIndexOnLine( nodeCoord-coord0 );
|
||||
//double xyz[3] = { _coords[0][ li.I() ], _coords[1][ li.J() ], _coords[2][ li.K() ]};
|
||||
gp_XYZ xyz = lineLoc + nodeParam * lineDir;
|
||||
_nodes [ nodeIndex ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
|
||||
_gridIntP[ nodeIndex ] = & * ip;
|
||||
}
|
||||
if ( _gridIntP[ nodeIndex ] )
|
||||
@ -951,7 +998,13 @@ namespace
|
||||
{
|
||||
size_t nodeIndex = NodeIndex( x, y, z );
|
||||
if ( !isNodeOut[ nodeIndex ] && !_nodes[ nodeIndex] )
|
||||
_nodes[ nodeIndex ] = helper.AddNode( _coords[0][x], _coords[1][y], _coords[2][z] );
|
||||
{
|
||||
//_nodes[ nodeIndex ] = helper.AddNode( _coords[0][x], _coords[1][y], _coords[2][z] );
|
||||
gp_XYZ xyz = ( _coords[0][x] * _axes[0] +
|
||||
_coords[1][y] * _axes[1] +
|
||||
_coords[2][z] * _axes[2] );
|
||||
_nodes[ nodeIndex ] = helper.AddNode( xyz.X(), xyz.Y(), xyz.Z() );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _MY_DEBUG_
|
||||
@ -1000,72 +1053,72 @@ namespace
|
||||
*/
|
||||
bool FaceGridIntersector::IsInGrid(const Bnd_Box& gridBox)
|
||||
{
|
||||
double x0,y0,z0, x1,y1,z1;
|
||||
const Bnd_Box& faceBox = GetFaceBndBox();
|
||||
faceBox.Get(x0,y0,z0, x1,y1,z1);
|
||||
// double x0,y0,z0, x1,y1,z1;
|
||||
// const Bnd_Box& faceBox = GetFaceBndBox();
|
||||
// faceBox.Get(x0,y0,z0, x1,y1,z1);
|
||||
|
||||
if ( !gridBox.IsOut( gp_Pnt( x0,y0,z0 )) &&
|
||||
!gridBox.IsOut( gp_Pnt( x1,y1,z1 )))
|
||||
return true;
|
||||
// if ( !gridBox.IsOut( gp_Pnt( x0,y0,z0 )) &&
|
||||
// !gridBox.IsOut( gp_Pnt( x1,y1,z1 )))
|
||||
// return true;
|
||||
|
||||
double X0,Y0,Z0, X1,Y1,Z1;
|
||||
gridBox.Get(X0,Y0,Z0, X1,Y1,Z1);
|
||||
double faceP[6] = { x0,y0,z0, x1,y1,z1 };
|
||||
double gridP[6] = { X0,Y0,Z0, X1,Y1,Z1 };
|
||||
gp_Dir axes[3] = { gp::DX(), gp::DY(), gp::DZ() };
|
||||
for ( int iDir = 0; iDir < 6; ++iDir )
|
||||
{
|
||||
if ( iDir < 3 && gridP[ iDir ] <= faceP[ iDir ] ) continue;
|
||||
if ( iDir >= 3 && gridP[ iDir ] >= faceP[ iDir ] ) continue;
|
||||
// double X0,Y0,Z0, X1,Y1,Z1;
|
||||
// gridBox.Get(X0,Y0,Z0, X1,Y1,Z1);
|
||||
// double faceP[6] = { x0,y0,z0, x1,y1,z1 };
|
||||
// double gridP[6] = { X0,Y0,Z0, X1,Y1,Z1 };
|
||||
// gp_Dir axes[3] = { gp::DX(), gp::DY(), gp::DZ() };
|
||||
// for ( int iDir = 0; iDir < 6; ++iDir )
|
||||
// {
|
||||
// if ( iDir < 3 && gridP[ iDir ] <= faceP[ iDir ] ) continue;
|
||||
// if ( iDir >= 3 && gridP[ iDir ] >= faceP[ iDir ] ) continue;
|
||||
|
||||
// check if the face intersects a side of a gridBox
|
||||
// // check if the face intersects a side of a gridBox
|
||||
|
||||
gp_Pnt p = iDir < 3 ? gp_Pnt( X0,Y0,Z0 ) : gp_Pnt( X1,Y1,Z1 );
|
||||
gp_Ax1 norm( p, axes[ iDir % 3 ] );
|
||||
if ( iDir < 3 ) norm.Reverse();
|
||||
// gp_Pnt p = iDir < 3 ? gp_Pnt( X0,Y0,Z0 ) : gp_Pnt( X1,Y1,Z1 );
|
||||
// gp_Ax1 norm( p, axes[ iDir % 3 ] );
|
||||
// if ( iDir < 3 ) norm.Reverse();
|
||||
|
||||
gp_XYZ O = norm.Location().XYZ(), N = norm.Direction().XYZ();
|
||||
// gp_XYZ O = norm.Location().XYZ(), N = norm.Direction().XYZ();
|
||||
|
||||
TopLoc_Location loc = _face.Location();
|
||||
Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(_face,loc);
|
||||
if ( !aPoly.IsNull() )
|
||||
{
|
||||
if ( !loc.IsIdentity() )
|
||||
{
|
||||
norm.Transform( loc.Transformation().Inverted() );
|
||||
O = norm.Location().XYZ(), N = norm.Direction().XYZ();
|
||||
}
|
||||
const double deflection = aPoly->Deflection();
|
||||
// TopLoc_Location loc = _face.Location();
|
||||
// Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(_face,loc);
|
||||
// if ( !aPoly.IsNull() )
|
||||
// {
|
||||
// if ( !loc.IsIdentity() )
|
||||
// {
|
||||
// norm.Transform( loc.Transformation().Inverted() );
|
||||
// O = norm.Location().XYZ(), N = norm.Direction().XYZ();
|
||||
// }
|
||||
// const double deflection = aPoly->Deflection();
|
||||
|
||||
const TColgp_Array1OfPnt& nodes = aPoly->Nodes();
|
||||
for ( int i = nodes.Lower(); i <= nodes.Upper(); ++i )
|
||||
if (( nodes( i ).XYZ() - O ) * N > _grid->_tol + deflection )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
BRepAdaptor_Surface surf( _face );
|
||||
double u0, u1, v0, v1, du, dv, u, v;
|
||||
BRepTools::UVBounds( _face, u0, u1, v0, v1);
|
||||
if ( surf.GetType() == GeomAbs_Plane ) {
|
||||
du = u1 - u0, dv = v1 - v0;
|
||||
}
|
||||
else {
|
||||
du = surf.UResolution( _grid->_minCellSize / 10. );
|
||||
dv = surf.VResolution( _grid->_minCellSize / 10. );
|
||||
}
|
||||
for ( u = u0, v = v0; u <= u1 && v <= v1; u += du, v += dv )
|
||||
{
|
||||
gp_Pnt p = surf.Value( u, v );
|
||||
if (( p.XYZ() - O ) * N > _grid->_tol )
|
||||
{
|
||||
TopAbs_State state = GetCurveFaceIntersector()->ClassifyUVPoint(gp_Pnt2d( u, v ));
|
||||
if ( state == TopAbs_IN || state == TopAbs_ON )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// const TColgp_Array1OfPnt& nodes = aPoly->Nodes();
|
||||
// for ( int i = nodes.Lower(); i <= nodes.Upper(); ++i )
|
||||
// if (( nodes( i ).XYZ() - O ) * N > _grid->_tol + deflection )
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// BRepAdaptor_Surface surf( _face );
|
||||
// double u0, u1, v0, v1, du, dv, u, v;
|
||||
// BRepTools::UVBounds( _face, u0, u1, v0, v1);
|
||||
// if ( surf.GetType() == GeomAbs_Plane ) {
|
||||
// du = u1 - u0, dv = v1 - v0;
|
||||
// }
|
||||
// else {
|
||||
// du = surf.UResolution( _grid->_minCellSize / 10. );
|
||||
// dv = surf.VResolution( _grid->_minCellSize / 10. );
|
||||
// }
|
||||
// for ( u = u0, v = v0; u <= u1 && v <= v1; u += du, v += dv )
|
||||
// {
|
||||
// gp_Pnt p = surf.Value( u, v );
|
||||
// if (( p.XYZ() - O ) * N > _grid->_tol )
|
||||
// {
|
||||
// TopAbs_State state = GetCurveFaceIntersector()->ClassifyUVPoint(gp_Pnt2d( u, v ));
|
||||
// if ( state == TopAbs_IN || state == TopAbs_ON )
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
//=============================================================================
|
||||
@ -1139,7 +1192,7 @@ namespace
|
||||
if ( _bndBox.IsOut( gridLine._line )) continue;
|
||||
|
||||
intersector._intPoints.clear();
|
||||
(intersector.*interFunction)( gridLine );
|
||||
(intersector.*interFunction)( gridLine ); // <- intersection with gridLine
|
||||
for ( size_t i = 0; i < intersector._intPoints.size(); ++i )
|
||||
_intersections.push_back( make_pair( &gridLine, intersector._intPoints[i] ));
|
||||
}
|
||||
@ -1188,7 +1241,7 @@ namespace
|
||||
*/
|
||||
void FaceLineIntersector::IntersectWithCylinder(const GridLine& gridLine)
|
||||
{
|
||||
IntAna_IntConicQuad linCylinder( gridLine._line,_cylinder);
|
||||
IntAna_IntConicQuad linCylinder( gridLine._line, _cylinder );
|
||||
if ( linCylinder.IsDone() && linCylinder.NbPoints() > 0 )
|
||||
{
|
||||
_w = linCylinder.ParamOnConic(1);
|
||||
@ -1644,6 +1697,23 @@ namespace
|
||||
|
||||
} // loop on _edgeIntPnts
|
||||
}
|
||||
else if ( 3 < _nbCornerNodes && _nbCornerNodes < 8 ) // _nbIntNodes == 0
|
||||
{
|
||||
_Link split;
|
||||
// create sub-links (_splits) of whole links
|
||||
for ( int iLink = 0; iLink < 12; ++iLink )
|
||||
{
|
||||
_Link& link = _hexLinks[ iLink ];
|
||||
link._splits.clear();
|
||||
if ( link._nodes[ 0 ]->Node() && link._nodes[ 1 ]->Node() )
|
||||
{
|
||||
split._nodes[ 0 ] = link._nodes[0];
|
||||
split._nodes[ 1 ] = link._nodes[1];
|
||||
link._splits.push_back( split );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//================================================================================
|
||||
/*!
|
||||
@ -1877,8 +1947,8 @@ namespace
|
||||
{
|
||||
curLink = freeLinks[ iL ];
|
||||
freeLinks[ iL ] = 0;
|
||||
polygon._links.push_back( *curLink );
|
||||
--nbFreeLinks;
|
||||
polygon._links.push_back( *curLink );
|
||||
}
|
||||
} while ( curLink );
|
||||
}
|
||||
@ -1983,16 +2053,23 @@ namespace
|
||||
|
||||
} // if there are intersections with EDGEs
|
||||
|
||||
if ( polygon._links.size() < 3 ||
|
||||
if ( polygon._links.size() < 2 ||
|
||||
polygon._links[0].LastNode() != polygon._links.back().FirstNode() )
|
||||
return; // closed polygon not found -> invalid polyhedron
|
||||
|
||||
// add polygon to its links
|
||||
for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
|
||||
if ( polygon._links.size() == 2 )
|
||||
{
|
||||
polygon._links[ iL ]._link->_faces.reserve( 2 );
|
||||
polygon._links[ iL ]._link->_faces.push_back( &polygon );
|
||||
polygon._links[ iL ].Reverse();
|
||||
_polygons.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
// add polygon to its links
|
||||
for ( size_t iL = 0; iL < polygon._links.size(); ++iL )
|
||||
{
|
||||
polygon._links[ iL ]._link->_faces.reserve( 2 );
|
||||
polygon._links[ iL ]._link->_faces.push_back( &polygon );
|
||||
polygon._links[ iL ].Reverse();
|
||||
}
|
||||
}
|
||||
} // while ( nbFreeLinks > 0 )
|
||||
|
||||
@ -2096,12 +2173,12 @@ namespace
|
||||
if ( hex )
|
||||
{
|
||||
intHexInd[ nbIntHex++ ] = i;
|
||||
if ( hex->_nbIntNodes > 0 ) continue;
|
||||
init( hex->_i, hex->_j, hex->_k );
|
||||
if ( hex->_nbIntNodes > 0 ) continue; // treat intersected hex later
|
||||
this->init( hex->_i, hex->_j, hex->_k );
|
||||
}
|
||||
else
|
||||
{
|
||||
init( i );
|
||||
this->init( i );
|
||||
}
|
||||
if ( _nbCornerNodes == 8 && ( _nbBndNodes < _nbCornerNodes || !isInHole() ))
|
||||
{
|
||||
@ -2124,7 +2201,10 @@ namespace
|
||||
{
|
||||
// all intersection of hex with geometry are at grid nodes
|
||||
hex = new Hexahedron( *this );
|
||||
hex->init( i );
|
||||
//hex->init( i );
|
||||
hex->_i = _i;
|
||||
hex->_j = _j;
|
||||
hex->_k = _k;
|
||||
intHexInd.push_back(0);
|
||||
intHexInd[ nbIntHex++ ] = i;
|
||||
}
|
||||
@ -2168,39 +2248,27 @@ namespace
|
||||
// Prepare planes for intersecting with EDGEs
|
||||
GridPlanes pln[3];
|
||||
{
|
||||
gp_XYZ origPnt = ( _grid->_coords[0][0] * _grid->_axes[0] +
|
||||
_grid->_coords[1][0] * _grid->_axes[1] +
|
||||
_grid->_coords[2][0] * _grid->_axes[2] );
|
||||
for ( int iDirZ = 0; iDirZ < 3; ++iDirZ ) // iDirZ gives normal direction to planes
|
||||
{
|
||||
GridPlanes& planes = pln[ iDirZ ];
|
||||
int iDirX = ( iDirZ + 1 ) % 3;
|
||||
int iDirY = ( iDirZ + 2 ) % 3;
|
||||
planes._uNorm = ( _grid->_axes[ iDirY ] ^ _grid->_axes[ iDirZ ] ).Normalized();
|
||||
planes._vNorm = ( _grid->_axes[ iDirZ ] ^ _grid->_axes[ iDirX ] ).Normalized();
|
||||
// planes._uNorm = ( _grid->_axes[ iDirY ] ^ _grid->_axes[ iDirZ ] ).Normalized();
|
||||
// planes._vNorm = ( _grid->_axes[ iDirZ ] ^ _grid->_axes[ iDirX ] ).Normalized();
|
||||
planes._zNorm = ( _grid->_axes[ iDirX ] ^ _grid->_axes[ iDirY ] ).Normalized();
|
||||
double uvDot = planes._uNorm * planes._vNorm;
|
||||
planes._factor = sqrt( 1. - uvDot * uvDot );
|
||||
planes._origins.resize( _grid->_coords[ iDirZ ].size() );
|
||||
planes._zProjs.resize ( _grid->_coords[ iDirZ ].size() );
|
||||
planes._origins[0] = origPnt;
|
||||
planes._zProjs [0] = 0;
|
||||
const double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
|
||||
const vector< double > & u = _grid->_coords[ iDirZ ];
|
||||
for ( int i = 1; i < planes._origins.size(); ++i )
|
||||
for ( int i = 1; i < planes._zProjs.size(); ++i )
|
||||
{
|
||||
planes._origins[i] = origPnt + _grid->_axes[ iDirZ ] * ( u[i] - u[0] );
|
||||
planes._zProjs [i] = zFactor * ( u[i] - u[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
const double deflection = _grid->_minCellSize / 20.;
|
||||
const double tol = _grid->_tol;
|
||||
// int facets[6] = { SMESH_Block::ID_F0yz, SMESH_Block::ID_F1yz,
|
||||
// SMESH_Block::ID_Fx0z, SMESH_Block::ID_Fx1z,
|
||||
// SMESH_Block::ID_Fxy0, SMESH_Block::ID_Fxy1 };
|
||||
E_IntersectPoint ip;
|
||||
//ip._faceIDs.reserve(2);
|
||||
|
||||
// Intersect EDGEs with the planes
|
||||
map< TGeomID, vector< TGeomID > >::const_iterator e2fIt = edge2faceIDsMap.begin();
|
||||
@ -2209,6 +2277,8 @@ namespace
|
||||
const TGeomID edgeID = e2fIt->first;
|
||||
const TopoDS_Edge & E = TopoDS::Edge( _grid->_shapes( edgeID ));
|
||||
BRepAdaptor_Curve curve( E );
|
||||
TopoDS_Vertex v1 = helper.IthVertex( 0, E, false );
|
||||
TopoDS_Vertex v2 = helper.IthVertex( 1, E, false );
|
||||
|
||||
ip._faceIDs = e2fIt->second;
|
||||
ip._shapeID = edgeID;
|
||||
@ -2226,34 +2296,34 @@ namespace
|
||||
int iDirY = ( iDirZ + 2 ) % 3;
|
||||
double xLen = _grid->_coords[ iDirX ].back() - _grid->_coords[ iDirX ][0];
|
||||
double yLen = _grid->_coords[ iDirY ].back() - _grid->_coords[ iDirY ][0];
|
||||
double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
|
||||
double zLen = _grid->_coords[ iDirZ ].back() - _grid->_coords[ iDirZ ][0];
|
||||
//double zFactor = _grid->_axes[ iDirZ ] * planes._zNorm;
|
||||
int dIJK[3], d000[3] = { 0,0,0 };
|
||||
double o[3] = { _grid->_coords[0][0],
|
||||
_grid->_coords[1][0],
|
||||
_grid->_coords[2][0] };
|
||||
|
||||
// locate the 1st point of a segment within the grid
|
||||
gp_XYZ p1 = discret.Value( 1 ).XYZ();
|
||||
double u1 = discret.Parameter( 1 );
|
||||
double zProj1 = planes._zNorm * ( p1 - planes._origins[0] );
|
||||
gp_Pnt orig = planes._origins[0] + planes._zNorm * zProj1;
|
||||
gp_XY uv = planes.GetUV( p1, orig );
|
||||
int iX1 = int( uv.X() / xLen * ( _grid->_coords[ iDirX ].size() - 1. ));
|
||||
int iY1 = int( uv.Y() / yLen * ( _grid->_coords[ iDirY ].size() - 1. ));
|
||||
int iZ1 = int( zProj1 / planes._zProjs.back() * ( planes._zProjs.size() - 1. ));
|
||||
locateValue( iX1, uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
|
||||
locateValue( iY1, uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
|
||||
locateValue( iZ1, zProj1, planes._zProjs , dIJK[ iDirZ ], tol );
|
||||
double zProj1 = planes._zNorm * ( p1 - _grid->_origin );
|
||||
|
||||
_grid->ComputeUVW( p1, ip._uvw );
|
||||
int iX1 = int(( ip._uvw[iDirX] - o[iDirX]) / xLen * (_grid->_coords[ iDirX ].size() - 1));
|
||||
int iY1 = int(( ip._uvw[iDirY] - o[iDirY]) / yLen * (_grid->_coords[ iDirY ].size() - 1));
|
||||
int iZ1 = int(( ip._uvw[iDirZ] - o[iDirZ]) / zLen * (_grid->_coords[ iDirZ ].size() - 1));
|
||||
locateValue( iX1, ip._uvw[iDirX], _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
|
||||
locateValue( iY1, ip._uvw[iDirY], _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
|
||||
locateValue( iZ1, ip._uvw[iDirZ], _grid->_coords[ iDirZ ], dIJK[ iDirZ ], tol );
|
||||
|
||||
int ijk[3]; // grid index where a segment intersect a plane
|
||||
ijk[ iDirX ] = iX1;
|
||||
ijk[ iDirY ] = iY1;
|
||||
ijk[ iDirZ ] = iZ1;
|
||||
ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
|
||||
ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
|
||||
ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
|
||||
|
||||
// add the 1st vertex point to a hexahedron
|
||||
if ( iDirZ == 0 )
|
||||
{
|
||||
//ip._shapeID = _grid->_shapes.Add( helper.IthVertex( 0, curve.Edge(),/*CumOri=*/false));
|
||||
ip._point = p1;
|
||||
_grid->_edgeIntP.push_back( ip );
|
||||
if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
|
||||
@ -2264,7 +2334,7 @@ namespace
|
||||
// locate the 2nd point of a segment within the grid
|
||||
gp_XYZ p2 = discret.Value( iP ).XYZ();
|
||||
double u2 = discret.Parameter( iP );
|
||||
double zProj2 = planes._zNorm * ( p2 - planes._origins[0] );
|
||||
double zProj2 = planes._zNorm * ( p2 - _grid->_origin );
|
||||
int iZ2 = iZ1;
|
||||
locateValue( iZ2, zProj2, planes._zProjs, dIJK[ iDirZ ], tol );
|
||||
|
||||
@ -2275,14 +2345,11 @@ namespace
|
||||
{
|
||||
ip._point = findIntPoint( u1, zProj1, u2, zProj2,
|
||||
planes._zProjs[ iZ ],
|
||||
curve, planes._zNorm, planes._origins[0] );
|
||||
gp_XY uv = planes.GetUV( ip._point, planes._origins[ iZ ]);
|
||||
locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
|
||||
locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
|
||||
curve, planes._zNorm, _grid->_origin );
|
||||
_grid->ComputeUVW( ip._point.XYZ(), ip._uvw );
|
||||
locateValue( ijk[iDirX], ip._uvw[iDirX], _grid->_coords[iDirX], dIJK[iDirX], tol );
|
||||
locateValue( ijk[iDirY], ip._uvw[iDirY], _grid->_coords[iDirY], dIJK[iDirY], tol );
|
||||
ijk[ iDirZ ] = iZ;
|
||||
ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
|
||||
ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
|
||||
ip._uvw[ iDirZ ] = planes._zProjs[ iZ ] / zFactor + _grid->_coords[ iDirZ ][0];
|
||||
|
||||
// add ip to hex "above" the plane
|
||||
_grid->_edgeIntP.push_back( ip );
|
||||
@ -2303,15 +2370,11 @@ namespace
|
||||
// add the 2nd vertex point to a hexahedron
|
||||
if ( iDirZ == 0 )
|
||||
{
|
||||
orig = planes._origins[0] + planes._zNorm * zProj1;
|
||||
uv = planes.GetUV( p1, orig );
|
||||
locateValue( ijk[ iDirX ], uv.X(), _grid->_coords[ iDirX ], dIJK[ iDirX ], tol );
|
||||
locateValue( ijk[ iDirY ], uv.Y(), _grid->_coords[ iDirY ], dIJK[ iDirY ], tol );
|
||||
ijk[ iDirZ ] = iZ1;
|
||||
ip._uvw[ iDirX ] = uv.X() + _grid->_coords[ iDirX ][0];
|
||||
ip._uvw[ iDirY ] = uv.Y() + _grid->_coords[ iDirY ][0];
|
||||
ip._uvw[ iDirZ ] = zProj1 / zFactor + _grid->_coords[ iDirZ ][0];
|
||||
ip._point = p1;
|
||||
_grid->ComputeUVW( p1, ip._uvw );
|
||||
locateValue( ijk[iDirX], ip._uvw[iDirX], _grid->_coords[iDirX], dIJK[iDirX], tol );
|
||||
locateValue( ijk[iDirY], ip._uvw[iDirY], _grid->_coords[iDirY], dIJK[iDirY], tol );
|
||||
ijk[ iDirZ ] = iZ1;
|
||||
_grid->_edgeIntP.push_back( ip );
|
||||
if ( !addIntersection( _grid->_edgeIntP.back(), hexes, ijk, d000 ))
|
||||
_grid->_edgeIntP.pop_back();
|
||||
@ -2356,8 +2419,6 @@ namespace
|
||||
* \param [in] origin - the plane origin
|
||||
* \return gp_Pnt - the found intersection point
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
gp_Pnt Hexahedron::findIntPoint( double u1, double proj1,
|
||||
double u2, double proj2,
|
||||
double proj,
|
||||
@ -2381,7 +2442,7 @@ namespace
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Returns index of a hexahedron sub-entities holding a point
|
||||
* \brief Returns indices of a hexahedron sub-entities holding a point
|
||||
* \param [in] ip - intersection point
|
||||
* \param [out] facets - 0-3 facets holding a point
|
||||
* \param [out] sub - index of a vertex or an edge holding a point
|
||||
@ -2466,7 +2527,7 @@ namespace
|
||||
};
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
if ( 0 <= hexIndex[i] && hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
|
||||
if ( /*0 <= hexIndex[i] &&*/ hexIndex[i] < hexes.size() && hexes[ hexIndex[i] ] )
|
||||
{
|
||||
Hexahedron* h = hexes[ hexIndex[i] ];
|
||||
// check if ip is really inside the hex
|
||||
@ -2789,6 +2850,90 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief computes exact bounding box with axes parallel to given ones
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void getExactBndBox( const vector< TopoDS_Shape >& faceVec,
|
||||
const double* axesDirs,
|
||||
Bnd_Box& shapeBox )
|
||||
{
|
||||
BRep_Builder b;
|
||||
TopoDS_Compound allFacesComp;
|
||||
b.MakeCompound( allFacesComp );
|
||||
for ( size_t iF = 0; iF < faceVec.size(); ++iF )
|
||||
b.Add( allFacesComp, faceVec[ iF ] );
|
||||
|
||||
double sP[6]; // aXmin, aYmin, aZmin, aXmax, aYmax, aZmax
|
||||
shapeBox.Get(sP[0],sP[1],sP[2],sP[3],sP[4],sP[5]);
|
||||
double farDist = 0;
|
||||
for ( int i = 0; i < 6; ++i )
|
||||
farDist = Max( farDist, 10 * sP[i] );
|
||||
|
||||
gp_XYZ axis[3] = { gp_XYZ( axesDirs[0], axesDirs[1], axesDirs[2] ),
|
||||
gp_XYZ( axesDirs[3], axesDirs[4], axesDirs[5] ),
|
||||
gp_XYZ( axesDirs[6], axesDirs[7], axesDirs[8] ) };
|
||||
axis[0].Normalize();
|
||||
axis[1].Normalize();
|
||||
axis[2].Normalize();
|
||||
|
||||
gp_Mat basis( axis[0], axis[1], axis[2] );
|
||||
gp_Mat bi = basis.Inverted();
|
||||
|
||||
gp_Pnt pMin, pMax;
|
||||
for ( int iDir = 0; iDir < 3; ++iDir )
|
||||
{
|
||||
gp_XYZ axis0 = axis[ iDir ];
|
||||
gp_XYZ axis1 = axis[ ( iDir + 1 ) % 3 ];
|
||||
gp_XYZ axis2 = axis[ ( iDir + 2 ) % 3 ];
|
||||
for ( int isMax = 0; isMax < 2; ++isMax )
|
||||
{
|
||||
double shift = isMax ? farDist : -farDist;
|
||||
gp_XYZ orig = shift * axis0;
|
||||
gp_XYZ norm = axis1 ^ axis2;
|
||||
gp_Pln pln( orig, norm );
|
||||
norm = pln.Axis().Direction().XYZ();
|
||||
BRepBuilderAPI_MakeFace plane( pln, -farDist, farDist, -farDist, farDist );
|
||||
|
||||
gp_Pnt& pAxis = isMax ? pMax : pMin;
|
||||
gp_Pnt pPlane, pFaces;
|
||||
double dist = GEOMUtils::GetMinDistance( plane, allFacesComp, pPlane, pFaces );
|
||||
if ( dist < 0 )
|
||||
{
|
||||
Bnd_B3d bb;
|
||||
gp_XYZ corner;
|
||||
for ( int i = 0; i < 2; ++i ) {
|
||||
corner.SetCoord( 1, sP[ i*3 ]);
|
||||
for ( int j = 0; j < 2; ++j ) {
|
||||
corner.SetCoord( 2, sP[ i*3 + 1 ]);
|
||||
for ( int k = 0; k < 2; ++k )
|
||||
{
|
||||
corner.SetCoord( 3, sP[ i*3 + 2 ]);
|
||||
corner *= bi;
|
||||
bb.Add( corner );
|
||||
}
|
||||
}
|
||||
}
|
||||
corner = isMax ? bb.CornerMax() : bb.CornerMin();
|
||||
pAxis.SetCoord( iDir+1, corner.Coord( iDir+1 ));
|
||||
}
|
||||
else
|
||||
{
|
||||
gp_XYZ pf = pFaces.XYZ() * bi;
|
||||
pAxis.SetCoord( iDir+1, pf.Coord( iDir+1 ) );
|
||||
}
|
||||
}
|
||||
} // loop on 3 axes
|
||||
|
||||
shapeBox.SetVoid();
|
||||
shapeBox.Add( pMin );
|
||||
shapeBox.Add( pMax );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//=============================================================================
|
||||
@ -2826,14 +2971,19 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
|
||||
vector< TopoDS_Shape > faceVec;
|
||||
{
|
||||
TopTools_MapOfShape faceMap;
|
||||
for ( TopExp_Explorer fExp( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
|
||||
if ( faceMap.Add( fExp.Current() )) // skip a face shared by two solids
|
||||
TopExp_Explorer fExp;
|
||||
for ( fExp.Init( theShape, TopAbs_FACE ); fExp.More(); fExp.Next() )
|
||||
if ( !faceMap.Add( fExp.Current() ))
|
||||
faceMap.Remove( fExp.Current() ); // remove a face shared by two solids
|
||||
|
||||
for ( fExp.ReInit(); fExp.More(); fExp.Next() )
|
||||
if ( faceMap.Contains( fExp.Current() ))
|
||||
faceVec.push_back( fExp.Current() );
|
||||
}
|
||||
Bnd_Box shapeBox;
|
||||
vector<FaceGridIntersector> facesItersectors( faceVec.size() );
|
||||
map< TGeomID, vector< TGeomID > > edge2faceIDsMap;
|
||||
TopExp_Explorer eExp;
|
||||
Bnd_Box shapeBox;
|
||||
for ( int i = 0; i < faceVec.size(); ++i )
|
||||
{
|
||||
facesItersectors[i]._face = TopoDS::Face ( faceVec[i] );
|
||||
@ -2850,32 +3000,13 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
|
||||
}
|
||||
}
|
||||
|
||||
getExactBndBox( faceVec, _hyp->GetAxisDirs(), shapeBox );
|
||||
|
||||
vector<double> xCoords, yCoords, zCoords;
|
||||
_hyp->GetCoordinates( xCoords, yCoords, zCoords, shapeBox );
|
||||
|
||||
grid.SetCoordinates( xCoords, yCoords, zCoords, _hyp->GetAxisDirs(), theShape );
|
||||
grid.SetCoordinates( xCoords, yCoords, zCoords, _hyp->GetAxisDirs(), shapeBox );
|
||||
|
||||
// check if the grid encloses the shape
|
||||
if ( !_hyp->IsGridBySpacing(0) ||
|
||||
!_hyp->IsGridBySpacing(1) ||
|
||||
!_hyp->IsGridBySpacing(2) )
|
||||
{
|
||||
Bnd_Box gridBox;
|
||||
gridBox.Add( gp_Pnt( xCoords[0], yCoords[0], zCoords[0] ));
|
||||
gridBox.Add( gp_Pnt( xCoords.back(), yCoords.back(), zCoords.back() ));
|
||||
double x0,y0,z0, x1,y1,z1;
|
||||
shapeBox.Get(x0,y0,z0, x1,y1,z1);
|
||||
if ( gridBox.IsOut( gp_Pnt( x0,y0,z0 )) ||
|
||||
gridBox.IsOut( gp_Pnt( x1,y1,z1 )))
|
||||
for ( size_t i = 0; i < facesItersectors.size(); ++i )
|
||||
{
|
||||
if ( !facesItersectors[i].IsInGrid( gridBox ))
|
||||
return error("The grid doesn't enclose the geometry");
|
||||
#ifdef ELLIPSOLID_WORKAROUND
|
||||
delete facesItersectors[i]._surfaceInt, facesItersectors[i]._surfaceInt = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if ( _computeCanceled ) return false;
|
||||
|
||||
#ifdef WITH_TBB
|
||||
|
@ -25,18 +25,33 @@
|
||||
// SMESH includes
|
||||
#include "StdMeshersGUI_CartesianParamCreator.h"
|
||||
|
||||
#include <SMESHGUI.h>
|
||||
#include <SMESHGUI_Utils.h>
|
||||
#include <SMESHGUI_HypothesesUtils.h>
|
||||
#include <SMESHGUI_SpinBox.h>
|
||||
#include "SMESHGUI.h"
|
||||
#include "SMESHGUI_Utils.h"
|
||||
#include "SMESHGUI_VTKUtils.h"
|
||||
#include "SMESHGUI_HypothesesUtils.h"
|
||||
#include "SMESHGUI_SpinBox.h"
|
||||
#include "SMESHGUI_MeshEditPreview.h"
|
||||
|
||||
// IDL includes
|
||||
#include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
|
||||
|
||||
// SALOME GUI includes
|
||||
#include <SalomeApp_Tools.h>
|
||||
#include <SalomeApp_IntSpinBox.h>
|
||||
#include <LightApp_SelectionMgr.h>
|
||||
#include <QtxComboBox.h>
|
||||
#include <SALOME_InteractiveObject.hxx>
|
||||
#include <SALOME_ListIO.hxx>
|
||||
#include <SALOME_ListIteratorOfListIO.hxx>
|
||||
#include <SUIT_ResourceMgr.h>
|
||||
#include <SalomeApp_IntSpinBox.h>
|
||||
#include <SalomeApp_Tools.h>
|
||||
|
||||
#include <GEOMBase.h>
|
||||
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
// Qt includes
|
||||
#include <QAbstractItemModel>
|
||||
@ -201,11 +216,18 @@ namespace StdMeshersGUI
|
||||
connect( myInsertBtn, SIGNAL( clicked() ), SLOT( onInsert() ));
|
||||
connect( myDeleteBtn, SIGNAL( clicked() ), SLOT( onDelete() ));
|
||||
connect( myModeGroup, SIGNAL( buttonClicked ( int )), SLOT( onMode(int)));
|
||||
connect( myModeGroup, SIGNAL( buttonClicked ( int )), SIGNAL( gridModeChanged(int)));
|
||||
connect( mySpacingTreeWdg, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() ));
|
||||
connect( myCoordList, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() ));
|
||||
connect( myStepSpin, SIGNAL( valueChanged(double)), SLOT( onStepChange() ));
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT onInsert
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::onInsert()
|
||||
{
|
||||
if ( isGridBySpacing() )
|
||||
@ -254,6 +276,12 @@ namespace StdMeshersGUI
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT onDelete
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::onDelete()
|
||||
{
|
||||
if ( isGridBySpacing() )
|
||||
@ -283,6 +311,12 @@ namespace StdMeshersGUI
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT onMode
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::onMode(int isSpacing)
|
||||
{
|
||||
mySpacingTreeWdg->setShown( isSpacing );
|
||||
@ -313,6 +347,12 @@ namespace StdMeshersGUI
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT onStepChange
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::onStepChange()
|
||||
{
|
||||
if ( fabs( myStepSpin->GetValue() ) < 1e-100 )
|
||||
@ -323,6 +363,12 @@ namespace StdMeshersGUI
|
||||
myStep = myStepSpin->GetValue();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Enables/disables buttons
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::updateButtons()
|
||||
{
|
||||
bool insertEnable = false, deleteEnable = false;
|
||||
@ -347,6 +393,12 @@ namespace StdMeshersGUI
|
||||
myDeleteBtn->setEnabled( deleteEnable );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Inserts coordinates into myCoordList
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::setCoordinates( SMESH::double_array_var coords )
|
||||
{
|
||||
myCoordList->clear();
|
||||
@ -357,6 +409,12 @@ namespace StdMeshersGUI
|
||||
onMode( COORD_BUT );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Sets spacing got from hypothesis
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::setSpacing( SMESH::string_array_var funs, SMESH::double_array_var points )
|
||||
{
|
||||
mySpacingTreeWdg->clear();
|
||||
@ -370,11 +428,23 @@ namespace StdMeshersGUI
|
||||
onMode( SPACING_BUT );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Checks grid definintion mode
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool GridAxisTab::isGridBySpacing() const
|
||||
{
|
||||
return ( myModeGroup->checkedId() == SPACING_BUT );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Returns coordinates to set to a hypothesis
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
SMESH::double_array* GridAxisTab::getCoordinates()
|
||||
{
|
||||
SMESH::double_array_var coords = new SMESH::double_array;
|
||||
@ -385,6 +455,12 @@ namespace StdMeshersGUI
|
||||
return coords._retn();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Returms spacing to set to a hypothesis
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void GridAxisTab::getSpacing(SMESH::string_array_out funs,
|
||||
SMESH::double_array_out points) const
|
||||
{
|
||||
@ -404,6 +480,12 @@ namespace StdMeshersGUI
|
||||
}
|
||||
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Verifies parameters
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool GridAxisTab::checkParams(QString& msg, SMESH::SMESH_Hypothesis_var& hyp) const
|
||||
{
|
||||
if ( isGridBySpacing() )
|
||||
@ -432,6 +514,12 @@ namespace StdMeshersGUI
|
||||
return true;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief LineDelegate constructor
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
LineDelegate::LineDelegate( QWidget* parent ):
|
||||
QItemDelegate( parent ),
|
||||
mySpacingTreeWdg( qobject_cast<QTreeWidget*>( parent )),
|
||||
@ -439,6 +527,12 @@ namespace StdMeshersGUI
|
||||
{
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Creates an editor depending on a current item
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
QWidget* LineDelegate::createEditor( QWidget* parent,
|
||||
const QStyleOptionViewItem& opt,
|
||||
const QModelIndex& index) const
|
||||
@ -472,6 +566,12 @@ namespace StdMeshersGUI
|
||||
return w;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Limit value range in the spin of a neighbor range
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void LineDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const
|
||||
{
|
||||
if ( mySpacingTreeWdg && index.column() == 0 )
|
||||
@ -494,6 +594,13 @@ namespace StdMeshersGUI
|
||||
QItemDelegate::setEditorData( editor, index );
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void LineDelegate::setModelData( QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index ) const
|
||||
@ -530,6 +637,53 @@ namespace StdMeshersGUI
|
||||
|
||||
} // namespace StdMeshersGUI
|
||||
|
||||
namespace
|
||||
{
|
||||
const double theAngTol = M_PI / 180.;
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Set variables to groups of spin boxes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void setText( const QString& vars, SMESHGUI_SpinBox** spins )
|
||||
{
|
||||
QStringList varList = vars.split( ':' );
|
||||
for ( int i = 0; i < 3 && i < varList.count(); ++i )
|
||||
if ( !varList[i].isEmpty() )
|
||||
spins[i]->setText( varList[i] );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Computes more 2 axes by one
|
||||
* \param [in] iOk - index of a given axis
|
||||
* \param [in,out] dirs - directions of 3 axes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void get3Dirs( int iOk, gp_XYZ dirs[3] )
|
||||
{
|
||||
dirs[ ( iOk+1 ) % 3 ] = dirs[ iOk ];
|
||||
|
||||
if ( Abs( dirs[ iOk ].Y() ) < 1e-100 &&
|
||||
Abs( dirs[ iOk ].Z() ) < 1e-100 )
|
||||
// dirs[ iOk ] || OX
|
||||
dirs[ ( iOk+1 ) % 3 ].SetY( dirs[ iOk ].Y() + 1. );
|
||||
else
|
||||
dirs[ ( iOk+1 ) % 3 ].SetX( dirs[ iOk ].X() + 1. );
|
||||
|
||||
dirs[( iOk+2 ) % 3] = dirs[ iOk ] ^ dirs[ ( iOk+1 ) % 3 ];
|
||||
dirs[( iOk+1 ) % 3] = dirs[ ( iOk+2 ) % 3 ] ^ dirs[ iOk ];
|
||||
}
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief StdMeshersGUI_CartesianParamCreator constructor
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
StdMeshersGUI_CartesianParamCreator::StdMeshersGUI_CartesianParamCreator(const QString& aHypType)
|
||||
: StdMeshersGUI_StdHypothesisCreator( aHypType ),
|
||||
@ -538,8 +692,23 @@ StdMeshersGUI_CartesianParamCreator::StdMeshersGUI_CartesianParamCreator(const Q
|
||||
myAxisTabs[0] = 0;
|
||||
myAxisTabs[1] = 0;
|
||||
myAxisTabs[2] = 0;
|
||||
|
||||
myAxesPreview = new SMESHGUI_MeshEditPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ));
|
||||
myAxesPreview->SetArrowShapeAndNb( /*nbArrows=*/3,
|
||||
/*headLength=*/0.1,
|
||||
/*headRadius=*/0.01,
|
||||
/*start=*/0.,
|
||||
/*labels=*/"XYZ");
|
||||
|
||||
myDirTic[0] = myDirTic[1] = myDirTic[2] = 0;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief StdMeshersGUI_CartesianParamCreator destructor
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
StdMeshersGUI_CartesianParamCreator::~StdMeshersGUI_CartesianParamCreator()
|
||||
{
|
||||
if ( myAxisTabs[0] ) delete myAxisTabs[0];
|
||||
@ -548,8 +717,16 @@ StdMeshersGUI_CartesianParamCreator::~StdMeshersGUI_CartesianParamCreator()
|
||||
myAxisTabs[0] = 0;
|
||||
myAxisTabs[1] = 0;
|
||||
myAxisTabs[2] = 0;
|
||||
|
||||
delete myAxesPreview;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Validate parameters
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool StdMeshersGUI_CartesianParamCreator::checkParams( QString& msg ) const
|
||||
{
|
||||
if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) )
|
||||
@ -568,9 +745,22 @@ bool StdMeshersGUI_CartesianParamCreator::checkParams( QString& msg ) const
|
||||
if ( !myAxisTabs[1]->checkParams( msg, hyp )) return false;
|
||||
if ( !myAxisTabs[2]->checkParams( msg, hyp )) return false;
|
||||
|
||||
StdMeshersGUI_CartesianParamCreator* me = (StdMeshersGUI_CartesianParamCreator*) this;
|
||||
if ( !me->updateAxesPreview() )
|
||||
{
|
||||
msg = tr("INVALID_AXES_DIR");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Create widgets
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
|
||||
{
|
||||
QFrame* fr = new QFrame();
|
||||
@ -625,10 +815,154 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
|
||||
tabWdg->addTab( myAxisTabs[ 1 ], tr( "AXIS_Y" ) );
|
||||
tabWdg->addTab( myAxisTabs[ 2 ], tr( "AXIS_Z" ) );
|
||||
argGroupLayout->addWidget( tabWdg, row, 0, 1, 2 );
|
||||
row++;
|
||||
|
||||
QPixmap aPix = SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT"));
|
||||
|
||||
// 4) Fixed point
|
||||
myFixedPointGrp = new QGroupBox( tr("FIXED_POINT"), fr );
|
||||
myFixedPointGrp->setCheckable( true );
|
||||
//QPushButton* pointBtn = new QPushButton( QIcon(aPix), "", myFixedPointGrp );
|
||||
QLabel* pXLbl = new QLabel( tr("SMESH_X"), myFixedPointGrp );
|
||||
QLabel* pYLbl = new QLabel( tr("SMESH_Y"), myFixedPointGrp );
|
||||
QLabel* pZLbl = new QLabel( tr("SMESH_Z"), myFixedPointGrp );
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
myPointSpin[i] = new SMESHGUI_SpinBox( myFixedPointGrp );
|
||||
myPointSpin[i]->RangeStepAndValidator( -1e20, 1e20, 10 );
|
||||
myPointSpin[i]->SetValue( 0. );
|
||||
}
|
||||
QHBoxLayout* aFixedPointLay = new QHBoxLayout( myFixedPointGrp );
|
||||
aFixedPointLay->addWidget( pXLbl, 0, Qt::AlignRight );
|
||||
aFixedPointLay->addWidget( myPointSpin[0], 1 );
|
||||
aFixedPointLay->addWidget( pYLbl, 0, Qt::AlignRight );
|
||||
aFixedPointLay->addWidget( myPointSpin[1], 1 );
|
||||
aFixedPointLay->addWidget( pZLbl, 0, Qt::AlignRight );
|
||||
aFixedPointLay->addWidget( myPointSpin[2], 1 );
|
||||
argGroupLayout->addWidget( myFixedPointGrp, row, 0, 1, 2 );
|
||||
row++;
|
||||
|
||||
// 5) Axes direction
|
||||
QGroupBox* axesDirGrp = new QGroupBox( tr("AXES_DIRECTION"), fr );
|
||||
QGridLayout* axisDirLay = new QGridLayout( axesDirGrp );
|
||||
axisDirLay->setSpacing( SPACING );
|
||||
axisDirLay->setMargin( MARGIN );
|
||||
axisDirLay->setColumnStretch( 0, 2 );
|
||||
// is orthogonal
|
||||
myOrthogonalChk = new QCheckBox( tr("ORTHOGONAL_AXES"), axesDirGrp );
|
||||
axisDirLay->addWidget( myOrthogonalChk, 0, 0, 1, 7 );
|
||||
// axes
|
||||
QLabel* axisLbl[3];
|
||||
axisLbl[0] = new QLabel( tr( "AXIS_X"), axesDirGrp );
|
||||
axisLbl[1] = new QLabel( tr( "AXIS_Y"), axesDirGrp );
|
||||
axisLbl[2] = new QLabel( tr( "AXIS_Z"), axesDirGrp );
|
||||
QLabel* dLbl[3];
|
||||
myAxisBtnGrp = new QButtonGroup( axesDirGrp );
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
QPushButton* axisBtn = new QPushButton( QIcon(aPix), "", axesDirGrp );
|
||||
axisBtn->setCheckable( true );
|
||||
myAxisBtnGrp->addButton( axisBtn, i );
|
||||
myXDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
|
||||
myYDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
|
||||
myZDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp );
|
||||
myXDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
|
||||
myYDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
|
||||
myZDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, "len_tol_precision" );
|
||||
dLbl[0] = new QLabel( tr("SMESH_DX"), axesDirGrp );
|
||||
dLbl[1] = new QLabel( tr("SMESH_DY"), axesDirGrp );
|
||||
dLbl[2] = new QLabel( tr("SMESH_DZ"), axesDirGrp );
|
||||
axisDirLay->addWidget( axisLbl[i], i+1, 0 );
|
||||
axisDirLay->addWidget( axisBtn, i+1, 1 );
|
||||
axisDirLay->addWidget( dLbl[0], i+1, 2 );
|
||||
axisDirLay->addWidget( dLbl[1], i+1, 4 );
|
||||
axisDirLay->addWidget( dLbl[2], i+1, 6 );
|
||||
axisDirLay->addWidget( myXDirSpin[i], 1, 3+i*2 );
|
||||
axisDirLay->addWidget( myYDirSpin[i], 2, 3+i*2 );
|
||||
axisDirLay->addWidget( myZDirSpin[i], 3, 3+i*2 );
|
||||
}
|
||||
axisDirLay->setColumnStretch( 3, 10 );
|
||||
axisDirLay->setColumnStretch( 5, 10 );
|
||||
axisDirLay->setColumnStretch( 7, 10 );
|
||||
|
||||
// set optimal axes
|
||||
QPushButton* optimBtn = new QPushButton( tr("OPTIMAL_AXES"), axesDirGrp );
|
||||
QPushButton* resetBtn = new QPushButton( tr("RESET_AXES"), axesDirGrp );
|
||||
axisDirLay->addWidget( optimBtn, 4, 0, 1, 4 );
|
||||
axisDirLay->addWidget( resetBtn, 4, 4, 1, 4 );
|
||||
|
||||
argGroupLayout->addWidget( axesDirGrp, row, 0, 1, 2 );
|
||||
row++;
|
||||
|
||||
// Signals
|
||||
|
||||
LightApp_SelectionMgr* selMgr = SMESH::GetSelectionMgr( SMESHGUI::GetSMESHGUI() );
|
||||
|
||||
connect( selMgr, SIGNAL( currentSelectionChanged()), SLOT( onSelectionChange()));
|
||||
connect( myOrthogonalChk, SIGNAL( toggled(bool)), SLOT( onOrthogonalAxes(bool)));
|
||||
connect( optimBtn, SIGNAL( clicked(bool)), SLOT( onOptimalAxes(bool)));
|
||||
connect( resetBtn, SIGNAL( clicked(bool)), SLOT( onResetAxes(bool)));
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
connect( myXDirSpin[i], SIGNAL(valueChanged (const QString&)),
|
||||
this, SLOT (onAxisDirChange(const QString&)) );
|
||||
connect( myYDirSpin[i], SIGNAL(valueChanged (const QString&)),
|
||||
this, SLOT (onAxisDirChange(const QString&)) );
|
||||
connect( myZDirSpin[i], SIGNAL(valueChanged (const QString&)),
|
||||
this, SLOT (onAxisDirChange(const QString&)) );
|
||||
connect( myAxisTabs[i], SIGNAL(gridModeChanged(int)),
|
||||
this, SLOT (onGridModeChanged(int)));
|
||||
}
|
||||
|
||||
// Show axes
|
||||
myAxesLen = 1;
|
||||
myOrigin[0] = myOrigin[1] = myOrigin[2] = 0.;
|
||||
TopoDS_Shape shape;
|
||||
QString shapeEntry = getMainShapeEntry();
|
||||
if ( !shapeEntry.isEmpty() )
|
||||
{
|
||||
// find origin
|
||||
Handle(SALOME_InteractiveObject) io =
|
||||
new SALOME_InteractiveObject( shapeEntry.toStdString().c_str(), "GEOM" );
|
||||
GEOM::GEOM_Object_var geomObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>( io );
|
||||
if ( GEOMBase::GetShape( geomObj, shape ) && !shape.IsNull())
|
||||
{
|
||||
Bnd_Box box;
|
||||
BRepBndLib::Add( shape, box );
|
||||
double max[3];
|
||||
if ( !box.IsVoid() )
|
||||
{
|
||||
box.Get( myOrigin[0], myOrigin[1], myOrigin[2], max[0], max[1], max[2] );
|
||||
gp_Pnt o( myOrigin[0], myOrigin[1], myOrigin[2] );
|
||||
gp_Pnt x( max[0], max[1], max[2] );
|
||||
myAxesLen = o.Distance( x );
|
||||
|
||||
double step = 1e20;
|
||||
while ( step > myAxesLen / 5 )
|
||||
step /= 10;
|
||||
myPointSpin[0]->SetStep( step );
|
||||
myPointSpin[1]->SetStep( step );
|
||||
myPointSpin[2]->SetStep( step );
|
||||
}
|
||||
}
|
||||
}
|
||||
myAxisBtnGrp->button(0)->setEnabled( !shape.IsNull() );
|
||||
myAxisBtnGrp->button(1)->setEnabled( !shape.IsNull() );
|
||||
myAxisBtnGrp->button(2)->setEnabled( !shape.IsNull() );
|
||||
optimBtn->setEnabled( !shape.IsNull() );
|
||||
|
||||
updateAxesPreview();
|
||||
|
||||
return fr;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Tranfer parameters from hypothesis to widgets
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
|
||||
{
|
||||
StdMeshers::StdMeshers_CartesianParameters3D_var h =
|
||||
@ -645,6 +979,7 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
|
||||
|
||||
myAddEdges->setChecked( h->GetToAddEdges() );
|
||||
|
||||
// grid definition
|
||||
for ( int ax = 0; ax < 3; ++ax )
|
||||
{
|
||||
if ( h->IsGridBySpacing( ax ))
|
||||
@ -660,11 +995,62 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
|
||||
myAxisTabs[ax]->setCoordinates( coords );
|
||||
}
|
||||
}
|
||||
|
||||
// fixed point
|
||||
SMESH::PointStruct fp;
|
||||
StdMeshersGUI_CartesianParamCreator* me = (StdMeshersGUI_CartesianParamCreator*) this;
|
||||
if ( h->GetFixedPoint( fp ))
|
||||
{
|
||||
me->myPointSpin[0]->SetValue( fp.x );
|
||||
me->myPointSpin[1]->SetValue( fp.y );
|
||||
me->myPointSpin[2]->SetValue( fp.z );
|
||||
setText( getVariableName("GetFixedPoint"), &me->myPointSpin[0] );
|
||||
myFixedPointGrp->setChecked( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
myFixedPointGrp->setChecked( false );
|
||||
}
|
||||
|
||||
// axes directions
|
||||
SMESHGUI_SpinBox** spins[3] = { &me->myXDirSpin[0], &me->myYDirSpin[0], &me->myZDirSpin[0] };
|
||||
SMESH::DirStruct axisDir[3];
|
||||
h->GetAxesDirs( axisDir[0],
|
||||
axisDir[1],
|
||||
axisDir[2]);
|
||||
QString vars = getVariableName("GetAxesDirs");
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
spins[i][0]->SetValue( axisDir[i].PS.x );
|
||||
spins[i][1]->SetValue( axisDir[i].PS.y );
|
||||
spins[i][2]->SetValue( axisDir[i].PS.z );
|
||||
setText( vars, spins[i] );
|
||||
|
||||
// cut off 3 used vars
|
||||
if ( !vars.isEmpty() )
|
||||
{
|
||||
int ind = -1;
|
||||
for ( int j = 0; j < 3; ++j )
|
||||
if (( ind = vars.indexOf(':', ind+1 )) < 0 )
|
||||
break;
|
||||
if ( ind < 0 )
|
||||
vars.clear();
|
||||
else
|
||||
vars.remove( 0, ind+1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dlg() )
|
||||
dlg()->setMinimumSize( dlg()->minimumSizeHint().width(),
|
||||
dlg()->minimumSizeHint().height() );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Tranfer parameters from widgets to hypothesis
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
QString StdMeshersGUI_CartesianParamCreator::storeParams() const
|
||||
{
|
||||
StdMeshers::StdMeshers_CartesianParameters3D_var h =
|
||||
@ -675,10 +1061,12 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
|
||||
if( isCreation() )
|
||||
SMESH::SetName( SMESH::FindSObject( h ), myName->text().toLatin1().constData() );
|
||||
|
||||
// threshold
|
||||
h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" );
|
||||
h->SetSizeThreshold( myThreshold->text().toDouble() );
|
||||
h->SetToAddEdges( myAddEdges->isChecked() );
|
||||
|
||||
// grid
|
||||
for ( int ax = 0; ax < 3; ++ax )
|
||||
{
|
||||
if ( myAxisTabs[ax]->isGridBySpacing())
|
||||
@ -694,6 +1082,40 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
|
||||
h->SetGrid( coords, ax );
|
||||
}
|
||||
}
|
||||
|
||||
// fixed point
|
||||
QStringList params;
|
||||
params << myPointSpin[0]->text();
|
||||
params << myPointSpin[1]->text();
|
||||
params << myPointSpin[2]->text();
|
||||
h->SetVarParameter( params.join(":").toLatin1().constData(), "SetFixedPoint" );
|
||||
params.clear();
|
||||
|
||||
SMESH::PointStruct ps;
|
||||
ps.x = myPointSpin[0]->GetValue();
|
||||
ps.y = myPointSpin[1]->GetValue();
|
||||
ps.z = myPointSpin[2]->GetValue();
|
||||
h->SetFixedPoint( ps, !myFixedPointGrp->isEnabled() || !myFixedPointGrp->isChecked() );
|
||||
|
||||
// axes directions
|
||||
SMESHGUI_SpinBox* const * spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int ax = 0; ax < 3; ++ax )
|
||||
{
|
||||
params << spins[ax][0]->text();
|
||||
params << spins[ax][1]->text();
|
||||
params << spins[ax][2]->text();
|
||||
}
|
||||
h->SetVarParameter( params.join(":").toLatin1().constData(), "SetAxesDirs" );
|
||||
|
||||
SMESH::DirStruct axDir[3];
|
||||
for ( int ax = 0; ax < 3; ++ax )
|
||||
{
|
||||
axDir[ax].PS.x = spins[ax][0]->GetValue();
|
||||
axDir[ax].PS.y = spins[ax][1]->GetValue();
|
||||
axDir[ax].PS.z = spins[ax][2]->GetValue();
|
||||
}
|
||||
h->SetAxesDirs( axDir[0], axDir[1], axDir[2] );
|
||||
|
||||
}
|
||||
catch(const SALOME::SALOME_Exception& ex)
|
||||
{
|
||||
@ -702,7 +1124,298 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const
|
||||
return "";
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Returns a name of help page
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
QString StdMeshersGUI_CartesianParamCreator::helpPage() const
|
||||
{
|
||||
return "cartesian_algo_page.html#cartesian_hyp_anchor";
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Show axes if they are OK
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool StdMeshersGUI_CartesianParamCreator::updateAxesPreview()
|
||||
{
|
||||
bool isOk = true;
|
||||
gp_Ax1 axes[3];
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int i = 0; i < 3 && isOk; ++i )
|
||||
{
|
||||
gp_XYZ dir( spins[i][0]->GetValue(),
|
||||
spins[i][1]->GetValue(),
|
||||
spins[i][2]->GetValue());
|
||||
if (( isOk = ( dir.Modulus() > 1e-100 )))
|
||||
axes[i].SetDirection( gp_Dir( dir ));
|
||||
|
||||
axes[i].SetLocation ( gp_Pnt( myOrigin[0],
|
||||
myOrigin[1],
|
||||
myOrigin[2]));
|
||||
}
|
||||
gp_Vec norm01 = axes[0].Direction().XYZ() ^ axes[1].Direction().XYZ();
|
||||
gp_Vec norm12 = axes[1].Direction().XYZ() ^ axes[2].Direction().XYZ();
|
||||
if ( isOk )
|
||||
isOk = ( !axes[0].Direction().IsParallel( axes[1].Direction(), theAngTol ) &&
|
||||
!axes[1].Direction().IsParallel( axes[2].Direction(), theAngTol ) &&
|
||||
!axes[2].Direction().IsParallel( axes[0].Direction(), theAngTol ) &&
|
||||
!norm01.IsParallel( norm12, theAngTol ) );
|
||||
if ( isOk )
|
||||
myAxesPreview->SetArrows( axes, myAxesLen );
|
||||
|
||||
myAxesPreview->SetVisibility( isOk );
|
||||
|
||||
return isOk;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Makes axes orthogonal if necessary
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onOrthogonalAxes(bool isOrtho)
|
||||
{
|
||||
if ( !isOrtho )
|
||||
{
|
||||
updateAxesPreview();
|
||||
return;
|
||||
}
|
||||
|
||||
std::multimap< int, int > ageOfAxis;
|
||||
gp_XYZ dirs[3];
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
int nbOk = 0, isOk;
|
||||
for ( int iAx = 0; iAx < 3; ++iAx )
|
||||
{
|
||||
dirs[iAx].SetCoord( spins[iAx][0]->GetValue(),
|
||||
spins[iAx][1]->GetValue(),
|
||||
spins[iAx][2]->GetValue());
|
||||
if (( isOk = ( dirs[iAx].Modulus() > 1e-100 )))
|
||||
ageOfAxis.insert( std::make_pair( myDirTic[iAx], iAx ));
|
||||
else
|
||||
ageOfAxis.insert( std::make_pair( -1, iAx ));
|
||||
nbOk += isOk;
|
||||
}
|
||||
switch ( nbOk )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
dirs[0].SetCoord( 1, 0, 0 );
|
||||
dirs[1].SetCoord( 0, 1, 0 );
|
||||
dirs[2].SetCoord( 0, 0, 1 );
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
int iOk = ageOfAxis.rbegin()->second;
|
||||
get3Dirs( iOk, dirs );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::multimap< int, int >::reverse_iterator ag2ax = ageOfAxis.rbegin();
|
||||
int iOk1 = ag2ax->second;
|
||||
int iOk2 = (++ag2ax)->second;
|
||||
int iKo = (++ag2ax)->second;
|
||||
if ( gp_Vec( dirs[ iOk1 ]).IsParallel( gp_Vec( dirs[ iOk2 ]), theAngTol ))
|
||||
std::swap( iOk2, iKo );
|
||||
if ( gp_Vec( dirs[ iOk1 ]).IsParallel( gp_Vec( dirs[ iOk2 ]), theAngTol ))
|
||||
{
|
||||
get3Dirs( iOk1, dirs );
|
||||
}
|
||||
else
|
||||
{
|
||||
dirs[ iKo ] = dirs[ iOk1 ] ^ dirs[ iOk2 ];
|
||||
dirs[ iOk2 ] = dirs[ iKo ] ^ dirs[ iOk1 ];
|
||||
if ( ( iOk1+1 ) % 3 != iOk2 )
|
||||
dirs[ iKo ].Reverse();
|
||||
}
|
||||
}
|
||||
|
||||
for ( int iAx = 0; iAx < 3; ++iAx )
|
||||
{
|
||||
double size = dirs[iAx].Modulus();
|
||||
if ( size > 1e-100 )
|
||||
dirs[iAx] /= size;
|
||||
for (int i = 0; i < 3; ++i )
|
||||
{
|
||||
bool isBlocked = spins[iAx][i]->blockSignals( true );
|
||||
spins[iAx][i]->SetValue( dirs[iAx].Coord( i+1 ));
|
||||
spins[iAx][i]->blockSignals( isBlocked );
|
||||
}
|
||||
}
|
||||
|
||||
updateAxesPreview();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Increment myDirTic and update the preview of axes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onAxisDirChange(const QString&)
|
||||
{
|
||||
QObject* changedSpin = sender();
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int iAx = 0; iAx < 3; ++iAx )
|
||||
if ( spins[iAx][0] == changedSpin ||
|
||||
spins[iAx][1] == changedSpin ||
|
||||
spins[iAx][2] == changedSpin )
|
||||
{
|
||||
myDirTic[ iAx ] = 1 + Max( Max( myDirTic[0], myDirTic[1] ), myDirTic[2] );
|
||||
break;
|
||||
}
|
||||
|
||||
onOrthogonalAxes( myOrthogonalChk->isChecked() );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Sets axis direction by a selected EDGE
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onSelectionChange()
|
||||
{
|
||||
int iAxis = myAxisBtnGrp->checkedId();
|
||||
if ( iAxis < 0 )
|
||||
return;
|
||||
|
||||
SALOME_ListIO aList;
|
||||
SMESHGUI::GetSMESHGUI()->selectionMgr()->selectedObjects(aList);
|
||||
|
||||
TopoDS_Shape edge, shape;
|
||||
for( SALOME_ListIteratorOfListIO anIt( aList ); anIt.More(); anIt.Next() )
|
||||
{
|
||||
GEOM::GEOM_Object_var go = SMESH::IObjectToInterface<GEOM::GEOM_Object>( anIt.Value() );
|
||||
if ( GEOMBase::GetShape( go, shape ) && shape.ShapeType() == TopAbs_EDGE )
|
||||
{
|
||||
if ( !edge.IsNull() )
|
||||
return; // several EDGEs selected
|
||||
edge = shape;
|
||||
}
|
||||
}
|
||||
if ( edge.IsNull() )
|
||||
return;
|
||||
|
||||
TopoDS_Shape vv[2];
|
||||
TopoDS_Iterator vIt( edge );
|
||||
for ( ; vIt.More() && vv[1].IsNull(); vIt.Next() )
|
||||
vv[ !vv[0].IsNull() ] = vIt.Value();
|
||||
|
||||
gp_Pnt pp[2];
|
||||
if ( !GEOMBase::VertexToPoint( vv[0], pp[0] ) ||
|
||||
!GEOMBase::VertexToPoint( vv[1], pp[1] ))
|
||||
return;
|
||||
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
|
||||
gp_Vec newDir( pp[0], pp[1] );
|
||||
gp_Vec curDir( spins[iAxis][0]->GetValue(),
|
||||
spins[iAxis][1]->GetValue(),
|
||||
spins[iAxis][2]->GetValue());
|
||||
if ( newDir * curDir < 0 )
|
||||
newDir.Reverse();
|
||||
|
||||
double size = newDir.Magnitude();
|
||||
if ( size < 1e-100 )
|
||||
return;
|
||||
newDir /= size;
|
||||
|
||||
for (int i = 0; i < 3; ++i )
|
||||
{
|
||||
bool isBlocked = spins[iAxis][i]->blockSignals( true );
|
||||
spins[iAxis][i]->SetValue( newDir.Coord( i+1 ));
|
||||
spins[iAxis][i]->blockSignals( isBlocked );
|
||||
}
|
||||
myDirTic[ iAxis ] = 1 + Max( Max( myDirTic[0], myDirTic[1] ), myDirTic[2] );
|
||||
|
||||
onOrthogonalAxes( myOrthogonalChk->isChecked() );
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Sets axes at which number of hexahedra is maximal
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onOptimalAxes(bool)
|
||||
{
|
||||
StdMeshers::StdMeshers_CartesianParameters3D_var h =
|
||||
StdMeshers::StdMeshers_CartesianParameters3D::_narrow( hypothesis() );
|
||||
if ( h->_is_nil() )
|
||||
return;
|
||||
|
||||
QString shapeEntry = getMainShapeEntry();
|
||||
if ( shapeEntry.isEmpty() )
|
||||
return;
|
||||
|
||||
Handle(SALOME_InteractiveObject) io =
|
||||
new SALOME_InteractiveObject( shapeEntry.toStdString().c_str(), "GEOM" );
|
||||
GEOM::GEOM_Object_var geomObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>( io );
|
||||
if ( geomObj->_is_nil() )
|
||||
return;
|
||||
|
||||
SMESH::DirStruct axDirs[3];
|
||||
h->ComputeOptimalAxesDirs( geomObj,
|
||||
myOrthogonalChk->isChecked(),
|
||||
axDirs[0],
|
||||
axDirs[1],
|
||||
axDirs[2]);
|
||||
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int iAx = 0; iAx < 3; ++iAx )
|
||||
{
|
||||
double coords[3] = { axDirs[iAx].PS.x, axDirs[iAx].PS.y, axDirs[iAx].PS.z };
|
||||
for (int i = 0; i < 3; ++i )
|
||||
{
|
||||
bool isBlocked = spins[iAx][i]->blockSignals( true );
|
||||
spins[iAx][i]->SetValue( coords[ i ]);
|
||||
spins[iAx][i]->blockSignals( isBlocked );
|
||||
}
|
||||
}
|
||||
updateAxesPreview();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Sets axes || to the axes of global CS
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onResetAxes(bool)
|
||||
{
|
||||
SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] };
|
||||
for ( int iAx = 0; iAx < 3; ++iAx )
|
||||
{
|
||||
for (int i = 0; i < 3; ++i )
|
||||
{
|
||||
bool isBlocked = spins[iAx][i]->blockSignals( true );
|
||||
spins[iAx][i]->SetValue( iAx == i ? 1. : 0. );
|
||||
spins[iAx][i]->blockSignals( isBlocked );
|
||||
}
|
||||
myDirTic[iAx] = 0;
|
||||
}
|
||||
updateAxesPreview();
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief SLOT called when the grid definintion mode changes
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
void StdMeshersGUI_CartesianParamCreator::onGridModeChanged(int)
|
||||
{
|
||||
bool haveSpacing = ( myAxisTabs[0]->isGridBySpacing() ||
|
||||
myAxisTabs[1]->isGridBySpacing() ||
|
||||
myAxisTabs[2]->isGridBySpacing() );
|
||||
|
||||
myFixedPointGrp->setEnabled( haveSpacing );
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
class QAbstractItemModel;
|
||||
class QButtonGroup;
|
||||
class QCheckBox;
|
||||
class QGroupBox;
|
||||
class QLineEdit;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
@ -51,6 +52,7 @@ class QStyleOptionViewItem;
|
||||
class QTreeWidget;
|
||||
class QTreeWidgetItem;
|
||||
class QWidget;
|
||||
class SMESHGUI_MeshEditPreview;
|
||||
class SMESHGUI_SpinBox;
|
||||
|
||||
namespace StdMeshersGUI
|
||||
@ -79,6 +81,9 @@ namespace StdMeshersGUI
|
||||
SMESH::double_array* getCoordinates();
|
||||
void getSpacing(SMESH::string_array_out funs, SMESH::double_array_out points) const;
|
||||
|
||||
signals:
|
||||
void gridModeChanged(int);
|
||||
|
||||
private slots:
|
||||
void onInsert();
|
||||
void onDelete();
|
||||
@ -126,19 +131,40 @@ public:
|
||||
StdMeshersGUI_CartesianParamCreator( const QString& aHypType );
|
||||
virtual ~StdMeshersGUI_CartesianParamCreator();
|
||||
|
||||
virtual bool checkParams( QString& ) const;
|
||||
virtual QString helpPage() const;
|
||||
virtual bool checkParams( QString& ) const;
|
||||
virtual QString helpPage() const;
|
||||
|
||||
protected:
|
||||
virtual QFrame* buildFrame();
|
||||
virtual void retrieveParams() const;
|
||||
virtual QString storeParams() const;
|
||||
|
||||
private slots:
|
||||
bool updateAxesPreview();
|
||||
void onOrthogonalAxes(bool);
|
||||
void onAxisDirChange(const QString&);
|
||||
void onSelectionChange();
|
||||
void onOptimalAxes(bool);
|
||||
void onResetAxes(bool);
|
||||
void onGridModeChanged(int);
|
||||
|
||||
private:
|
||||
QLineEdit* myName;
|
||||
SMESHGUI_SpinBox* myThreshold;
|
||||
QCheckBox* myAddEdges;
|
||||
|
||||
StdMeshersGUI::GridAxisTab* myAxisTabs[3];
|
||||
QGroupBox* myFixedPointGrp;
|
||||
SMESHGUI_SpinBox* myPointSpin[3];
|
||||
QCheckBox* myOrthogonalChk;
|
||||
QButtonGroup* myAxisBtnGrp;
|
||||
SMESHGUI_SpinBox* myXDirSpin[3];
|
||||
SMESHGUI_SpinBox* myYDirSpin[3];
|
||||
SMESHGUI_SpinBox* myZDirSpin[3];
|
||||
SMESHGUI_MeshEditPreview* myAxesPreview;
|
||||
double myOrigin[3];
|
||||
double myAxesLen;
|
||||
int myDirTic[3];
|
||||
};
|
||||
|
||||
#endif // STDMESHERSGUI_CartesianParamCreator_H
|
||||
|
@ -529,6 +529,30 @@
|
||||
<source>AXIS_Z</source>
|
||||
<translation>Axis Z</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>INVALID_AXES_DIR</source>
|
||||
<translation>Invalid directions of axes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>FIXED_POINT</source>
|
||||
<translation>Fixed Point</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>AXES_DIRECTION</source>
|
||||
<translation>Directions of Axes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ORTHOGONAL_AXES</source>
|
||||
<translation>Orthogonal Axes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>OPTIMAL_AXES</source>
|
||||
<translation>Optimal Axes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RESET_AXES</source>
|
||||
<translation>Reset</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>StdMeshersGUI::GridAxisTab</name>
|
||||
|
@ -224,6 +224,102 @@ void StdMeshers_CartesianParameters3D_i::GetGridSpacing(SMESH::string_array_out
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetAxesDirs
|
||||
//purpose : Set custom direction of axes
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D_i::SetAxesDirs(const SMESH::DirStruct& xDir,
|
||||
const SMESH::DirStruct& yDir,
|
||||
const SMESH::DirStruct& zDir)
|
||||
throw (SALOME::SALOME_Exception)
|
||||
{
|
||||
double coords[9];
|
||||
coords[0] = xDir.PS.x;
|
||||
coords[1] = xDir.PS.y;
|
||||
coords[2] = xDir.PS.z;
|
||||
coords[3] = yDir.PS.x;
|
||||
coords[4] = yDir.PS.y;
|
||||
coords[5] = yDir.PS.z;
|
||||
coords[6] = zDir.PS.x;
|
||||
coords[7] = zDir.PS.y;
|
||||
coords[8] = zDir.PS.z;
|
||||
try {
|
||||
this->GetImpl()->SetAxisDirs(coords);
|
||||
|
||||
SMESH::TPythonDump() << _this() << ".SetAxesDirs( "
|
||||
<< xDir << ", "
|
||||
<< yDir << ", "
|
||||
<< zDir << " )";
|
||||
}
|
||||
catch ( SALOME_Exception& S_ex ) {
|
||||
THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetAxesDirs
|
||||
//purpose : Returns direction of axes
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D_i::GetAxesDirs(SMESH::DirStruct& xDir,
|
||||
SMESH::DirStruct& yDir,
|
||||
SMESH::DirStruct& zDir)
|
||||
{
|
||||
const double* coords = GetImpl()->GetAxisDirs();
|
||||
xDir.PS.x = coords[0];
|
||||
xDir.PS.y = coords[1];
|
||||
xDir.PS.z = coords[2];
|
||||
yDir.PS.x = coords[3];
|
||||
yDir.PS.y = coords[4];
|
||||
yDir.PS.z = coords[5];
|
||||
zDir.PS.x = coords[6];
|
||||
zDir.PS.y = coords[7];
|
||||
zDir.PS.z = coords[8];
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetFixedPoint
|
||||
//purpose : * Set/unset a fixed point, at which a node will be created provided that grid
|
||||
// * is defined by spacing in all directions
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D_i::SetFixedPoint(const SMESH::PointStruct& ps,
|
||||
CORBA::Boolean toUnset)
|
||||
{
|
||||
double p[3] = { ps.x, ps.y, ps.z };
|
||||
GetImpl()->SetFixedPoint( p, toUnset );
|
||||
|
||||
if ( toUnset )
|
||||
SMESH::TPythonDump() << _this() << ".SetFixedPoint([0,0,0], True)";
|
||||
else
|
||||
SMESH::TPythonDump() << _this() << ".SetFixedPoint(" << p << ", " << toUnset << " )";
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : GetFixedPoint
|
||||
//purpose : Returns a fixed point
|
||||
//=======================================================================
|
||||
|
||||
CORBA::Boolean StdMeshers_CartesianParameters3D_i::GetFixedPoint(SMESH::PointStruct& ps)
|
||||
{
|
||||
double p[3];
|
||||
if ( GetImpl()->GetFixedPoint( p ) )
|
||||
{
|
||||
ps.x = p[0];
|
||||
ps.y = p[1];
|
||||
ps.z = p[2];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ps.x = 0.;
|
||||
ps.y = 0.;
|
||||
ps.z = 0.;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetToAddEdges
|
||||
//purpose : Enables implementation of geometrical edges into the mesh.
|
||||
@ -257,6 +353,37 @@ CORBA::Boolean StdMeshers_CartesianParameters3D_i::IsGridBySpacing(CORBA::Short
|
||||
return this->GetImpl()->IsGridBySpacing(axis);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ComputeOptimalAxesDirs
|
||||
//purpose : Returns axes at which number of hexahedra is maximal
|
||||
//=======================================================================
|
||||
|
||||
void StdMeshers_CartesianParameters3D_i::
|
||||
ComputeOptimalAxesDirs(GEOM::GEOM_Object_ptr go,
|
||||
CORBA::Boolean isOrthogonal,
|
||||
SMESH::DirStruct& xDir,
|
||||
SMESH::DirStruct& yDir,
|
||||
SMESH::DirStruct& zDir)
|
||||
throw (SALOME::SALOME_Exception)
|
||||
{
|
||||
TopoDS_Shape shape = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( go );
|
||||
if ( shape.IsNull() )
|
||||
THROW_SALOME_CORBA_EXCEPTION( "Null shape", SALOME::BAD_PARAM );
|
||||
|
||||
double c[9];
|
||||
::StdMeshers_CartesianParameters3D::ComputeOptimalAxesDirs( shape, isOrthogonal, c );
|
||||
|
||||
xDir.PS.x = c[0];
|
||||
xDir.PS.y = c[1];
|
||||
xDir.PS.z = c[2];
|
||||
yDir.PS.x = c[3];
|
||||
yDir.PS.y = c[4];
|
||||
yDir.PS.z = c[5];
|
||||
zDir.PS.x = c[6];
|
||||
zDir.PS.y = c[7];
|
||||
zDir.PS.z = c[8];
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : ComputeCoordinates
|
||||
//purpose : Computes node coordinates by spacing functions
|
||||
@ -268,7 +395,7 @@ StdMeshers_CartesianParameters3D_i::ComputeCoordinates(CORBA::Double
|
||||
const SMESH::string_array& spaceFuns,
|
||||
const SMESH::double_array& points,
|
||||
const char* axisName )
|
||||
throw (SALOME::SALOME_Exception)
|
||||
throw (SALOME::SALOME_Exception)
|
||||
{
|
||||
vector<string> xFuns;
|
||||
vector<double> xPoints, coords;
|
||||
|
@ -83,6 +83,22 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
|
||||
void GetGridSpacing(SMESH::string_array_out xSpaceFunctions,
|
||||
SMESH::double_array_out xInternalPoints,
|
||||
CORBA::Short axis) throw (SALOME::SALOME_Exception);
|
||||
/*!
|
||||
* Set custom direction of axes
|
||||
*/
|
||||
void SetAxesDirs(const SMESH::DirStruct& x,
|
||||
const SMESH::DirStruct& y,
|
||||
const SMESH::DirStruct& z) throw (SALOME::SALOME_Exception);
|
||||
void GetAxesDirs(SMESH::DirStruct& x,
|
||||
SMESH::DirStruct& y,
|
||||
SMESH::DirStruct& z);
|
||||
/*!
|
||||
* Set/unset a fixed point, at which a node will be created provided that grid
|
||||
* is defined by spacing in all directions
|
||||
*/
|
||||
void SetFixedPoint(const ::SMESH::PointStruct& p, CORBA::Boolean toUnset);
|
||||
CORBA::Boolean GetFixedPoint(::SMESH::PointStruct& p);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Enables implementation of geometrical edges into the mesh. If this feature
|
||||
@ -98,6 +114,14 @@ class STDMESHERS_I_EXPORT StdMeshers_CartesianParameters3D_i:
|
||||
*/
|
||||
CORBA::Boolean IsGridBySpacing(CORBA::Short axis);
|
||||
|
||||
/*!
|
||||
* Returns axes at which number of hexahedra is maximal
|
||||
*/
|
||||
void ComputeOptimalAxesDirs(GEOM::GEOM_Object_ptr shape,
|
||||
CORBA::Boolean isOrthogonal,
|
||||
SMESH::DirStruct& x,
|
||||
SMESH::DirStruct& y,
|
||||
SMESH::DirStruct& z) throw (SALOME::SALOME_Exception);
|
||||
/*!
|
||||
* \brief Computes node coordinates by spacing functions
|
||||
* \param x0 - lower coordinate
|
||||
|
Loading…
Reference in New Issue
Block a user