# Ensure a proper linker behavior:
CMAKE_POLICY(SET CMP0003 NEW)
+IF(WIN32)
+ CMAKE_POLICY(SET CMP0020 OLD) # disable automatic linking to qtmain.lib
+ENDIF(WIN32)
# Versioning
# ===========
IF(SALOME_BUILD_GUI)
LIST(APPEND _${PROJECT_NAME}_exposed_targets
- SMESHObject SMESHFiltersSelection SMESH GeomSelectionTools StdMeshersGUI
+ SMESHObject SMESHFiltersSelection SMESH PluginUtils StdMeshersGUI
)
ENDIF(SALOME_BUILD_GUI)
SET(SMESH_MEFISTO2D MEFISTO2D)
ENDIF(SALOME_SMESH_ENABLE_MEFISTO)
SET(SMESH_SMESHObject SMESHObject)
-SET(SMESH_GeomSelectionTools GeomSelectionTools)
+SET(SMESH_PluginUtils PluginUtils)
SET(SMESH_SMDS SMDS)
SET(SMESH_SMESHimpl SMESHimpl)
SET(SMESH_SMESHEngine SMESHEngine)
algo_local.Arithmetic1D(1, 4)
# define "Propagation" hypothesis that propagates algo_local and "Arithmetic1D" hypothesis
-# on all parallel edges of the box
+# from EdgeX to all parallel edges
algo_local.Propagation()
# assign a hexahedral algorithm
mesh.Hexahedron()
-# compute the mesh
+
+# any sub-shape can be meshed individually --
+# compute mesh on two surfaces using different methods
+
+# get surfaces
+surfaces = geompy.SubShapeAll(box, geompy.ShapeType["FACE"])
+
+# method 1: no sub-mesh is created
+mesh.Compute( surfaces[0] )
+
+# method 2: a sub-mesh is created
+submesh = mesh.GetSubMesh( surfaces[2], "submesh 2" )
+submesh.Compute()
+
+
+
+# compute the whole mesh
mesh.Compute()
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
-#ADD_DEPENDENCIES(usr_docs html_docs)
-
INSTALL(CODE "EXECUTE_PROCESS(COMMAND \"${CMAKE_COMMAND}\" --build ${PROJECT_BINARY_DIR} --target usr_docs)")
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/SMESH DESTINATION ${SALOME_INSTALL_DOC}/gui)
INSTALL(FILES images/head.png DESTINATION ${SALOME_INSTALL_DOC}/gui/SMESH)
\page constructing_submeshes_page Constructing sub-meshes
+\tableofcontents
+
By purpose, the sub-mesh is an object used to assign to a sub-shape
different meshing parameters than those assigned to the main shape.
certain sub-shape, thus to get a locally coarser or finer mesh, to get
elements of different types in the same mesh, etc.
+A sub-mesh can be meshed individually. To achieve this, select a
+sub-mesh and either invoke <b>Compute Sub-mesh</b> vai the contextual
+menu in the Object Browser or invoke <b> Mesh > Compute </b> menu.
+
+\section submesh_shape_section How to get a sub-shape for sub-mesh construction
+
A sub-shape to create a sub-mesh on should be retrieved from the main shape
in one of the following ways: <ul>
<li> In Geometry module, via <em>New Entity > Explode</em> menu.</li>
dialog showing \ref meshing_failed_anchor "meshing errors".</li>
</ul>
+\section submesh_priority How hypotheses are selected among sub-meshes
+
Internally, definition of meshing parameters to apply for
discretization of a certain sub-shape, for example an edge of a
compound of solids, starts from searching an algorithm, 1D as for the
be used for meshing. You can \ref submesh_order_anchor "change" mutual
priority of such concurrent sub-meshes.
+\section submesh_definition How to construct a sub-mesh
+
\n Construction of a sub-mesh consists of:
<ul>
<li>Selecting a mesh which will encapsulate the sub-mesh</li>
with which the sub-shape will appear in the Object Browser (if not yet
there).
+\section submesh_tree Sub-mesh in the Object Browser
+
In the Object Browser the structure of the new sub-mesh will be
displayed as follows:
<li>a sub-mesh name (\a SubMeshFace1)
<li>a reference to the geometrical object on the basis of which the
sub-mesh has been constructed (<em>Cylindrical Face_1</em>);</li>
-<li><em>Applied hypotheses</em> folder containing the references to the
+<li><em>Applied hypotheses</em> folder containing references to
hypotheses assigned to the sub-mesh;</li>
-<li><em>Applied algorithms</em> folder containing the references to the
+<li><em>Applied algorithms</em> folder containing references to
algorithms assigned to the sub-mesh.</li>
</ul>
</ul>
<li>Specify the <b>Number of steps</b>.</li>
+
+ <li>Optionally specify <b>Scale Factors</b>. Each scale factor in
+ the list is applied to nodes of a corresponding extrusion step
+ unless <b>Linear Variation of Scale Factors</b> is checked, is
+ which case the scale factors are spread over all extrusion steps.</li>
+ <ul>
+ <li><b>Scaling Center</b> can be defined either using spin boxes
+ or by picking a node in the Viewer or by picking a geometrical
+ vertex in the Object Browser.</li>
+ <li>\b Add button adds a scale factor to the list.
+ \image html add.png
+ <center><em>"Add" button</em></center>
+ </li>
+ <li>\b Remove button removes selected scale factors from the list.
+ \image html remove.png
+ <center><em>"Remove" button</em></center>
+ </li>
+ </ul>
+
<li>If you activate <b>Generate Groups</b> check-box, the <em>result elements</em>
created from <em>selected elements</em> contained in groups will be
included into new groups named by pattern "<old group
\ref constructing_submeshes_page "Construction of sub-meshes" are:
<ul>
<li> 1D and 2D algorithms and hypotheses that will be applied for
- meshing the top and the base prism faces. These faces can be meshed
+ meshing the top and the base prism
+ \ref submesh_shape_section "faces". These faces can be meshed
with any type of 2D elements: quadrangles, triangles, polygons or
- their mix. It is enough to define a sub-mesh on either the top or the base
- face. In the sample picture above, "NETGEN_1D2D" algorithm meshes
- "bottom disk" face with triangles. (1D algorithm is not
- assigned as "NETGEN_1D2D" does not require divided edges to create a 2D mesh.)
+ their mix. It is enough to define a sub-mesh on either the top or
+ the base face. In the sample picture above, "NETGEN_1D2D"
+ algorithm meshes "bottom disk" face with triangles. (1D algorithm
+ is not assigned as "NETGEN_1D2D" does not require divided edges to
+ create a 2D mesh.)
</li>
- <li> Optionally you can define a 1D sub-mesh on some vertical edges
- of stacked prisms, which will override the global 1D hypothesis mentioned
- above. In the <b>Prism stacks</b> picture, the
- vertical division is not equidistant on the whole length because
- a "Number Of Segments" hypothesis with Scale Factor=3 is assigned to
- the highlighted edge.
+ <li> Optionally you can define a 1D sub-mesh on some vertical
+ \ref submesh_shape_section "edges" of stacked prisms, which will
+ override the global 1D hypothesis mentioned above. In the <b>Prism
+ stacks</b> picture, the vertical division is not equidistant on
+ the whole length because a "Number Of Segments" hypothesis with
+ Scale Factor=3 is assigned to the highlighted edge.
</li></ul>
+If <em>3D extrusion</em> algorithm is assigned to a sub-mesh in a mesh
+with multiple sub-meshes, the described above approach may not work as
+expected. For example the bottom face may be meshed by other algorithm
+before <em>3D extrusion</em> have a chance to project a mesh from the
+base face. This thing can happen with vertical edges as well. All
+these can lead to either a meshing failure or to an incorrect meshing.
+
+In such a case, it's necessary to explicitly define algorithms
+that <em>3D extrusion</em> implicitly applies in a simple case:
+- assign \ref projection_1D2D algorithm to the top face and
+- assign a 1D algorithm to a group of all vertical edges.
+
\image html image157.gif "Prism with 3D extrusion meshing. Vertical division is different on neighbor edges because several local 1D hypotheses are assigned."
\sa a sample TUI Script of
\page projection_algos_page Projection Algorithms
-\n Projection algorithms allow to define the mesh of a geometrical
+\tableofcontents
+
+Projection algorithms allow to define the mesh of a geometrical
object by the projection of another already meshed geometrical object.
+\note Source and target geometrical objects mush be topologically
+equal, i.e. they must have same number of sub-shapes, connected to
+corresponding counterparts.
+
+\image html topo_equality.png Topologically equal faces suitable for 2D projection.
+
+
+\section projection_1D Projection 1D
+
<b>Projection 1D</b> algorithm allows to define the mesh of an edge
(or group of edges)
by the projection of another already meshed edge (or group of edges).
The source and target groups must contain equal number of edges
and they must form topologically equal structures.
+\section projection_2D Projection 2D
+
\n <b>Projection 2D</b> algorithm allows to define the mesh of a face
(or group of faces) by the projection of another already meshed face
(or group of faces). This algorithm works only if all edges of the
contain an equal number of faces and form topologically equal
structures.
-\n <b>Projection 1D-2D</b> algorithm differs from <b>Projection 2D</b>
-algorithm in one aspect: it generates mesh segments on edges of
-the face according to the projected 2D elements; thus it does not
-require the edges to be meshed by any other 1D algorithm; moreover it
-does not allow to mesh edges of the face using another algorithm via
-definition of sub-meshes.
+\section projection_1D2D Projection 1D-2D
+
+\n <b>Projection 1D-2D</b> algorithm differs from
+\ref projection_2D algorithm in one aspect: it generates mesh segments
+on edges of the face according to the projected 2D elements; thus it
+does not require the edges to be meshed by any other 1D algorithm;
+moreover it does not allow to mesh edges of the face using another
+algorithm via definition of sub-meshes.
+
+\section projection_3D Projection 3D
\n <b>Projection 3D</b> algorithm allows to define the mesh of a shape by
the projection of another already meshed shape. This algorithm works
\page radial_quadrangle_1D2D_algo_page Radial Quadrangle 1D2D
\n This algorithm applies to the meshing of 2D shapes under the
-following conditions: the face must be a full circle or a part of circle
-(i.e. the number of edges is less or equal to 3 and one of them is a circle curve).
+following conditions: the face must be a full ellipse or a part of ellipse
+(i.e. the number of edges is less or equal to 3 and one of them is an ellipse curve).
The resulting mesh consists of triangles (near the center point) and
quadrangles.
-This algorithm is optionally parametrized by the hypothesis indicating the number
-of mesh layers along the radius. The distribution of layers can be set with any 1D Hypothesis.
+This algorithm is optionally parametrized by the hypothesis indicating
+the number of mesh layers along the radius. The distribution of layers
+can be set with any 1D Hypothesis. If the face boundary includes
+radial edges, this distribution is applied to the longest radial
+edge. If the face boundary does not include radial edges, this
+distribution is applied to the longest virtual radial edge. The
+distribution is applied to the longest radial edge starting from its
+end lying on the elliptic curve.
-If no own hypothesis of the algorithm is assigned, any local or global hypothesis is used
-by the algorithm to discretize edges. Note that if the geometrical face has two radial edges,
-they must be meshed with equal number of segments.
-If no 1D hypothesis is assigned to an edge, "Default Number of Segments" preferences parameter
-is used to discretize the edge.
+If no own hypothesis of the algorithm is assigned, any local or global
+hypothesis is used by the algorithm to discretize edges.
+
+If no 1D hypothesis is assigned to an edge, "Default Number of
+Segments" preferences parameter is used to discretize the edge.
\image html hypo_radquad_dlg.png
in ListOfIDSources faces,
in DirStruct stepVector,
in long nbOfSteps,
+ in double_array scaleFactors,
+ in boolean linearVariation,
+ in double_array basePoint,
in boolean toMakeGroups)
raises (SALOME::SALOME_Exception);
myDoGroupOfVolumes (false),
myDoGroupOf0DElems(false),
myDoGroupOfBalls(false),
- myAutoDimension(true),
+ myAutoDimension(false),
myAddODOnVertices(false)
{}
}
// Mesh dimension definition
+
+ TInt aMeshDimension = 0;
+ if ( myMesh->NbEdges() > 0 )
+ aMeshDimension = 1;
+ if ( myMesh->NbFaces() > 0 )
+ aMeshDimension = 2;
+ if ( myMesh->NbVolumes() > 0 )
+ aMeshDimension = 3;
+
TInt aSpaceDimension = 3;
TCoordHelperPtr aCoordHelperPtr;
{
bool anIsXDimension = false;
bool anIsYDimension = false;
bool anIsZDimension = false;
- if ( myAutoDimension )
+ if ( myAutoDimension && aMeshDimension < 3 )
{
SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
double aBounds[6];
anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
- aSpaceDimension = anIsXDimension + anIsYDimension + anIsZDimension;
+ aSpaceDimension = Max( aMeshDimension, anIsXDimension + anIsYDimension + anIsZDimension );
if ( !aSpaceDimension )
aSpaceDimension = 3;
// PAL16857(SMESH not conform to the MED convention):
break;
}
}
- TInt aMeshDimension = 0;
- if ( myMesh->NbEdges() > 0 )
- aMeshDimension = 1;
- if ( myMesh->NbFaces() > 0 )
- aMeshDimension = 2;
- if ( myMesh->NbVolumes() > 0 )
- aMeshDimension = 3;
MED::PWrapper myMed = CrWrapper(myFile,myMedVersion);
PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName);
vtkUnstructuredGrid* aGrid = myControlActor->GetUnstructuredGrid();
vtkIdType aNbCells = aGrid->GetNumberOfCells();
+ bool aShowOnlyScalarBarTitle = false;
if(aNbCells){
myControlMode = theMode;
switch(myControlMode){
case eFreeNodes:
case eCoincidentNodes:
myNodeExtActor->SetExtControlMode(myFunctor);
+ aShowOnlyScalarBarTitle = true;
break;
case eFreeEdges:
case eFreeBorders:
case eCoincidentElems1D:
my1DExtActor->SetExtControlMode(myFunctor);
+ aShowOnlyScalarBarTitle = true;
break;
case eFreeFaces:
case eBareBorderFace:
case eOverConstrainedFace:
case eCoincidentElems2D:
my2DExtActor->SetExtControlMode(myFunctor);
+ aShowOnlyScalarBarTitle = true;
break;
case eBareBorderVolume:
case eOverConstrainedVolume:
case eCoincidentElems3D:
my3DExtActor->SetExtControlMode(myFunctor);
+ aShowOnlyScalarBarTitle = true;
break;
case eLength2D:
case eMultiConnection2D:
myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable);
UpdateDistribution();
}
+ myScalarBarActor->SetTitleOnlyVisibility(aShowOnlyScalarBarTitle);
}
if(theCheckEntityMode) {
SetEntityMode(eVolumes);
}
}
+ QString aTitle = QString(myScalarBarActor->GetTitle());
+ aTitle.replace(QRegExp("(:\\s).*"),"\\1"+ QString::number(GetNumberControlEntities()));
+ myScalarBarActor->SetTitle(aTitle.toLatin1().constData());
}
else {
Update();
}
+int
+SMESH_ActorDef::
+GetNumberControlEntities(){
+ SMESH_DeviceActor* anAct = NULL;
+ switch(myControlMode){
+ case eFreeNodes:
+ case eCoincidentNodes:
+ anAct = myNodeExtActor;
+ break;
+ case eFreeEdges:
+ case eFreeBorders:
+ case eCoincidentElems1D:
+ anAct = my1DExtActor;
+ break;
+ case eFreeFaces:
+ case eBareBorderFace:
+ case eOverConstrainedFace:
+ case eCoincidentElems2D:
+ anAct = my2DExtActor;
+ break;
+ case eBareBorderVolume:
+ case eOverConstrainedVolume:
+ case eCoincidentElems3D:
+ anAct = my3DExtActor;
+ break;
+ }
+ return (anAct) ? anAct->GetUnstructuredGrid()->GetNumberOfCells() : -1;
+}
void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){
case eLength2D:
case eMultiConnection2D:
my1DExtActor->VisibilityOn();
- default:
- if(myControlActor->GetUnstructuredGrid()->GetNumberOfCells())
- myScalarBarActor->VisibilityOn();
+ break;
}
+ if(myControlActor->GetUnstructuredGrid()->GetNumberOfCells())
+ myScalarBarActor->VisibilityOn();
}
if(myRepresentation != ePoint)
virtual void SetControlMode(eControl theMode) = 0;
virtual eControl GetControlMode() = 0;
virtual SMESH::Controls::FunctorPtr GetFunctor() = 0;
+ virtual int GetNumberControlEntities() = 0;
virtual SMESH_ScalarBarActor* GetScalarBarActor() = 0;
virtual bool GetFacesOrientation3DVectors();
virtual void SetControlMode(eControl theMode);
+ virtual int GetNumberControlEntities();
virtual eControl GetControlMode(){ return myControlMode;}
virtual SMESH::Controls::FunctorPtr GetFunctor() { return myFunctor; }
if(MYDEBUG) MESSAGE("~SMESH_DeviceActor - "<<this);
myMapper->Delete();
-
+ myPlaneCollection->Delete();
myProperty->Delete();
myExtractGeometry->Delete();
// By default monocolor
myDistributionColoringType = SMESH_MONOCOLOR_TYPE;
+
+ // By default scalar map is shown
+ myTitleOnlyVisibility = false;
// rnv end
}
{
renderedSomething += this->TitleActor->RenderOverlay(viewport);
}
- this->ScalarBarActor->RenderOverlay(viewport);
- this->myDistributionActor->RenderOverlay(viewport);
- if( this->TextActors == NULL)
- {
- vtkWarningMacro(<<"Need a mapper to render a scalar bar");
- return renderedSomething;
- }
+ if (!myTitleOnlyVisibility) {
+ this->ScalarBarActor->RenderOverlay(viewport);
+ this->myDistributionActor->RenderOverlay(viewport);
+ if( this->TextActors == NULL)
+ {
+ vtkWarningMacro(<<"Need a mapper to render a scalar bar");
+ return renderedSomething;
+ }
- for (i=0; i<this->NumberOfLabels; i++)
- {
- renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
- }
-
+ for (i=0; i<this->NumberOfLabels; i++)
+ {
+ renderedSomething += this->TextActors[i]->RenderOverlay(viewport);
+ }
+ }
renderedSomething = (renderedSomething > 0)?(1):(0);
return renderedSomething;
// rnv begin
// Customization of the vtkScalarBarActor to show distribution histogram.
- if(myNbValues[i] && myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
+ if(myDistributionColoringType == SMESH_MULTICOLOR_TYPE && GetDistributionVisibility() && distrVisibility)
{
rgb = distColors->GetPointer(3*dcCount); //write into array directly
rgb[0] = rgba[0];
void SMESH_ScalarBarActor::GetDistributionColor (double rgb[3]) {
myDistributionActor->GetProperty()->GetColor(rgb);
}
+
+void SMESH_ScalarBarActor::SetTitleOnlyVisibility( bool theTitleOnlyVisibility) {
+ myTitleOnlyVisibility = theTitleOnlyVisibility;
+}
+
+bool SMESH_ScalarBarActor::GetTitleOnlyVisibility() {
+ return myTitleOnlyVisibility;
+}
// Get Distribution Color
void GetDistributionColor (double rgb[3]);
+ // Description:
+ // Set visibility status of scalar map
+ void SetTitleOnlyVisibility( bool );
+ // Description:
+ // Get visibility status of scalar map
+ bool GetTitleOnlyVisibility();
protected:
SMESH_ScalarBarActor();
vtkPolyDataMapper2D* myDistributionMapper; //Distribution mapper
std::vector<int> myNbValues; //Nb values for the range
int myDistributionColoringType; //Distribution color type (monocolor or multicolor)
+ bool myTitleOnlyVisibility; //Show scalar map or not
private:
SMESH_ScalarBarActor(const SMESH_ScalarBarActor&); // Not implemented.
# additional preprocessor / compiler flags
ADD_DEFINITIONS(
+ ${QT_DEFINITIONS}
${CAS_DEFINITIONS}
${BOOST_DEFINITIONS}
${OMNIORB_DEFINITIONS}
${KERNEL_SalomeLifeCycleCORBA}
${CAS_TKBRep}
${CAS_TKV3d}
+ ${QT_LIBRARIES}
+ ${QT_MT_LIBS}
${GUI_SalomeObject}
${GUI_suit}
${GUI_LightApp}
# --- headers ---
# header files / to be processed by moc
-SET(GeomSelectionTools_HEADERS
+SET(PluginUtils_HEADERS
GeomSelectionTools.h
+ SMESH_PluginUtils.h
+ SMESH_AdvOptionsWdg.h
)
# --- sources ---
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES SMESH_AdvOptionsWdg.h)
+
# sources / static
-SET(GeomSelectionTools_SOURCES
+SET(PluginUtils_SOURCES
GeomSelectionTools.cxx
+ SMESH_AdvOptionsWdg.cxx
+ ${_moc_SOURCES}
)
# --- rules ---
-ADD_LIBRARY(GeomSelectionTools ${GeomSelectionTools_SOURCES})
-TARGET_LINK_LIBRARIES(GeomSelectionTools ${_link_LIBRARIES} )
-INSTALL(TARGETS GeomSelectionTools EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+ADD_LIBRARY(PluginUtils ${PluginUtils_SOURCES})
+TARGET_LINK_LIBRARIES(PluginUtils ${_link_LIBRARIES} )
+INSTALL(TARGETS PluginUtils EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
-INSTALL(FILES ${GeomSelectionTools_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
+INSTALL(FILES ${PluginUtils_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
#ifndef _GEOMSELECTIONTOOLS_H_
#define _GEOMSELECTIONTOOLS_H_
-#ifdef WIN32
-# ifdef GeomSelectionTools_EXPORTS
-# define GEOMSELECTIONTOOLS_EXPORT __declspec( dllexport )
-# else
-# define GEOMSELECTIONTOOLS_EXPORT __declspec( dllimport )
-# endif
-#else
-# define GEOMSELECTIONTOOLS_EXPORT
-#endif
-
-#include "SALOMEDSClient.hxx"
-#include "SALOME_InteractiveObject.hxx"
+#include "SMESH_PluginUtils.h"
+
+#include <SALOMEDSClient.hxx>
+#include <SALOME_InteractiveObject.hxx>
#include <SALOME_ListIO.hxx>
#include <SalomeApp_Application.h>
*
*/
-class GEOMSELECTIONTOOLS_EXPORT GeomSelectionTools
+class PLUGINUTILS_EXPORT GeomSelectionTools
{
private:
namespace PluginUtils
{
- GEOMSELECTIONTOOLS_EXPORT QString PrintDoubleValue( double, int = 16 );
+ PLUGINUTILS_EXPORT QString PrintDoubleValue( double, int = 16 );
};
#endif // _GEOMSELECTIONTOOLS_H_
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File : SMESH_AdvOptionsWdg.h
+// Author : Open CASCADE S.A.S.
+
+#include "SMESH_AdvOptionsWdg.h"
+
+#include <QTableWidget>
+#include <QPushButton>
+#include <QGridLayout>
+#include <QCheckBox>
+#include <QHeaderView>
+
+#define SPACING 6
+#define MARGIN 11
+
+namespace
+{
+ const int IS_CUSTOM = Qt::UserRole;
+}
+
+SMESH_AdvOptionsWdg::SMESH_AdvOptionsWdg( QWidget* parent )
+ : QWidget( parent )
+{
+ myTable = new QTableWidget( /*nbrows=*/0, /*nbcol=*/3, this );
+ QPushButton* addBtn = new QPushButton( tr("ADD_OPTION_BTN"), this );
+
+ myTable->setHorizontalHeaderLabels
+ ( QStringList() << tr("CHOICE") << tr("OPTION_NAME") << tr("OPTION_VALUE") );
+ QHeaderView * header = myTable->horizontalHeader();
+ header->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
+ header->setSectionResizeMode( 1, QHeaderView::Stretch );
+ header->setSectionResizeMode( 2, QHeaderView::ResizeToContents );
+
+ QGridLayout* lay = new QGridLayout( this );
+ lay->setMargin( MARGIN );
+ lay->setSpacing( SPACING );
+ lay->addWidget( myTable, 0,0, 1,3 );
+ lay->addWidget( addBtn, 1,0 );
+
+ connect( addBtn, SIGNAL( clicked() ), SLOT( onAdd() ));
+}
+
+SMESH_AdvOptionsWdg::~SMESH_AdvOptionsWdg()
+{
+}
+
+void SMESH_AdvOptionsWdg::AddOption( QString name, QString value, bool isDefault, bool isCustom )
+{
+ int row = myTable->rowCount();
+ myTable->insertRow( row );
+
+ QTableWidgetItem* nameItem = new QTableWidgetItem( name );
+ QTableWidgetItem* valueItem = new QTableWidgetItem( value );
+ if ( !name.isEmpty() )
+ nameItem->setFlags( nameItem->flags() & ~Qt::ItemIsEditable );
+ myTable->setItem( row, 1, nameItem );
+ myTable->setItem( row, 2, valueItem );
+ nameItem->setData( IS_CUSTOM, isCustom );
+
+ QCheckBox* chkBox = new QCheckBox();
+ QWidget* wdg = new QWidget();
+ QHBoxLayout* lay = new QHBoxLayout( wdg );
+ lay->setContentsMargins(0,0,0,0);
+ lay->addStretch();
+ lay->addWidget(chkBox);
+ lay->addStretch();
+ myTable->setCellWidget( row, 0, wdg );
+ connect( chkBox, SIGNAL(toggled(bool)), this, SLOT(onToggle()));
+ myTable->setCurrentCell( row, 1, QItemSelectionModel::NoUpdate );
+ chkBox->setChecked( !isDefault );
+
+ if ( name.isEmpty() )
+ myTable->editItem( nameItem );
+}
+
+void SMESH_AdvOptionsWdg::SetCustomOptions( const QString& text )
+{
+ QStringList nameVals = text.split(" ");
+ for ( int i = 1; i < nameVals.count(); i += 2 )
+ AddOption( nameVals[i-1], nameVals[i], false, true );
+}
+
+void SMESH_AdvOptionsWdg::onAdd()
+{
+ AddOption( "", "", false, true );
+
+}
+void SMESH_AdvOptionsWdg::onToggle()
+{
+ int row = myTable->currentRow();
+ QTableWidgetItem* valueItem = myTable->item( row, 2 );
+
+ bool isActive = isChecked( row );
+ int c = isActive ? 0 : 150;
+ valueItem->setForeground( QBrush( QColor( c, c, c )));
+ if ( isActive )
+ valueItem->setFlags( valueItem->flags() | Qt::ItemIsEditable );
+ else
+ valueItem->setFlags( valueItem->flags() & ~Qt::ItemIsEditable );
+}
+
+void SMESH_AdvOptionsWdg::GetOption( int row,
+ QString& name,
+ QString& value,
+ bool& isDefault,
+ bool & isCustom)
+{
+ if ( row < myTable->rowCount() )
+ {
+ name = myTable->item( row, 1 )->text();
+ value = myTable->item( row, 2 )->text();
+ isDefault = !isChecked( row );
+ isCustom = myTable->item( row, 1 )->data( IS_CUSTOM ).toInt();
+ }
+}
+
+QString SMESH_AdvOptionsWdg::GetCustomOptions()
+{
+ QString text, value, name;
+ bool isDefault, isCustom;
+ for ( int row = 0; row < myTable->rowCount(); ++row )
+ {
+ GetOption( row, name, value, isDefault, isCustom );
+ if ( !name.isEmpty() && !value.isEmpty() && isCustom && !isDefault )
+ text += name + " " + value + " ";
+ }
+ return text;
+}
+
+bool SMESH_AdvOptionsWdg::isChecked( int row )
+{
+ QCheckBox* cb = myTable->cellWidget( row, 0 )->findChild<QCheckBox *>();
+ return cb->isChecked();
+}
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File : SMESH_AdvOptionsWdg.h
+// Author : Open CASCADE S.A.S.
+//
+#ifndef SMESH_ADVOPTIONSWDG_H
+#define SMESH_ADVOPTIONSWDG_H
+
+#include "SMESH_PluginUtils.h"
+
+// Qt includes
+#include <QWidget>
+
+class QTableWidget;
+
+/*!
+ * \brief Widget for entering options as strings
+ */
+class PLUGINUTILS_EXPORT SMESH_AdvOptionsWdg : public QWidget
+{
+ Q_OBJECT
+
+public:
+ SMESH_AdvOptionsWdg( QWidget* parent = 0 );
+ ~SMESH_AdvOptionsWdg();
+
+ void AddOption( QString name, QString value, bool isDefault, bool isCustom );
+ void SetCustomOptions( const QString& text );
+
+ int GetNbRows();
+ void GetOption( int row, QString& name, QString& value, bool& isDefault, bool &isCustom);
+ QString GetCustomOptions();
+
+private slots:
+
+ void onAdd();
+ void onToggle();
+
+private:
+
+ bool isChecked( int row );
+
+ QTableWidget* myTable;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File : SMESH_StdMeshersGUI.hxx
+// Author : Alexander BORODIN, Open CASCADE S.A.S.
+//
+#ifndef SMESH_PLUGINUTILS_HXX
+#define SMESH_PLUGINUTILS_HXX
+
+#ifdef WIN32
+ #if defined PLUGINUTILS_EXPORTS || defined PluginUtils_EXPORTS
+ #define PLUGINUTILS_EXPORT __declspec( dllexport )
+ #else
+ #define PLUGINUTILS_EXPORT __declspec( dllimport )
+ #endif
+#else
+ #define PLUGINUTILS_EXPORT
+#endif
+
+#endif // SMESH_PLUGINUTILS_HXX
//purpose : standard construction
//=======================================================================
-SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep,
- const int theNbSteps,
- const int theFlags,
- const double theTolerance):
+SMESH_MeshEditor::ExtrusParam::ExtrusParam( const gp_Vec& theStep,
+ const int theNbSteps,
+ const std::list<double>& theScales,
+ const gp_XYZ* theBasePoint,
+ const int theFlags,
+ const double theTolerance):
myDir( theStep ),
+ myBaseP( Precision::Infinite(), 0, 0 ),
myFlags( theFlags ),
myTolerance( theTolerance ),
myElemsToUse( NULL )
for (int i=1; i<=theNbSteps; i++ )
mySteps->Append( stepSize );
+ int nbScales = theScales.size();
+ if ( nbScales > 0 )
+ {
+ if ( IsLinearVariation() && nbScales < theNbSteps )
+ {
+ myScales.reserve( theNbSteps );
+ std::list<double>::const_iterator scale = theScales.begin();
+ double prevScale = 1.0;
+ for ( int iSc = 1; scale != theScales.end(); ++scale, ++iSc )
+ {
+ int iStep = int( iSc / double( nbScales ) * theNbSteps + 0.5 );
+ int stDelta = Max( 1, iStep - myScales.size());
+ double scDelta = ( *scale - prevScale ) / stDelta;
+ for ( int iStep = 0; iStep < stDelta; ++iStep )
+ {
+ myScales.push_back( prevScale + scDelta );
+ prevScale = myScales.back();
+ }
+ prevScale = *scale;
+ }
+ }
+ else
+ {
+ myScales.assign( theScales.begin(), theScales.end() );
+ }
+ }
+ if ( theBasePoint )
+ {
+ myBaseP = *theBasePoint;
+ }
+
if (( theFlags & EXTRUSION_FLAG_SEW ) &&
( theTolerance > 0 ))
{
//=======================================================================
//function : ExtrusParam::SetElementsToUse
//purpose : stores elements to use for extrusion by normal, depending on
-// state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag
+// state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag;
+// define myBaseP for scaling
//=======================================================================
-void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems )
+void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& elems,
+ const TIDSortedElemSet& nodes )
{
myElemsToUse = ToUseInpElemsOnly() ? & elems : 0;
+
+ if ( Precision::IsInfinite( myBaseP.X() )) // myBaseP not defined
+ {
+ myBaseP.SetCoord( 0.,0.,0. );
+ TIDSortedElemSet newNodes;
+
+ const TIDSortedElemSet* elemSets[] = { &elems, &nodes };
+ for ( int is2ndSet = 0; is2ndSet < 2; ++is2ndSet )
+ {
+ const TIDSortedElemSet& elements = *( elemSets[ is2ndSet ]);
+ TIDSortedElemSet::const_iterator itElem = elements.begin();
+ for ( ; itElem != elements.end(); itElem++ )
+ {
+ const SMDS_MeshElement* elem = *itElem;
+ SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+ while ( itN->more() ) {
+ const SMDS_MeshElement* node = itN->next();
+ if ( newNodes.insert( node ).second )
+ myBaseP += SMESH_TNodeXYZ( node );
+ }
+ }
+ }
+ myBaseP /= newNodes.size();
+ }
}
//=======================================================================
const SMDS_MeshNode * newNode = mesh->AddNode( p.X(), p.Y(), p.Z() );
newNodes.push_back( newNode );
}
+
+ if ( !myScales.empty() )
+ {
+ if ( makeMediumNodes && myMediumScales.empty() )
+ {
+ myMediumScales.resize( myScales.size() );
+ double prevFactor = 1.;
+ for ( size_t i = 0; i < myScales.size(); ++i )
+ {
+ myMediumScales[i] = 0.5 * ( prevFactor + myScales[i] );
+ prevFactor = myScales[i];
+ }
+ }
+ typedef std::vector<double>::iterator ScaleIt;
+ ScaleIt scales[] = { myScales.begin(), myMediumScales.begin() };
+
+ size_t iSc = 0, nbScales = myScales.size() + myMediumScales.size();
+
+ gp_XYZ center = myBaseP;
+ std::list<const SMDS_MeshNode*>::iterator nIt = newNodes.begin();
+ size_t iN = 0;
+ for ( beginStepIter( makeMediumNodes ); moreSteps() && ( iN < nbScales ); ++nIt, ++iN )
+ {
+ center += myDir.XYZ() * nextStep();
+
+ iSc += int( makeMediumNodes );
+ ScaleIt& scale = scales[ iSc % 2 ];
+
+ gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
+ xyz = ( *scale * ( xyz - center )) + center;
+ mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
+
+ ++scale;
+ }
+ }
return nbNodes;
}
const int theFlags,
const double theTolerance)
{
- ExtrusParam aParams( theStep, theNbSteps, theFlags, theTolerance );
+ ExtrusParam aParams( theStep, theNbSteps, std::list<double>(), 0, theFlags, theTolerance );
return ExtrusionSweep( theElems, aParams, newElemsMap );
}
// source elements for each generated one
SMESH_SequenceOfElemPtr srcElems, srcNodes;
- //SMESHDS_Mesh* aMesh = GetMeshDS();
-
setElemsFirst( theElemSets );
const int nbSteps = theParams.NbSteps();
- theParams.SetElementsToUse( theElemSets[0] );
+ theParams.SetElementsToUse( theElemSets[0], theElemSets[1] );
- TNodeOfNodeListMap mapNewNodes;
- //TNodeOfNodeVecMap mapNewNodes;
+ TNodeOfNodeListMap mapNewNodes;
TElemOfVecOfNnlmiMap mapElemNewNodes;
- //TElemOfVecOfMapNodesMap mapElemNewNodes;
const bool isQuadraticMesh = bool( myMesh->NbEdges(ORDER_QUADRATIC) +
myMesh->NbFaces(ORDER_QUADRATIC) +
//=======================================================================
//function : LinearAngleVariation
-//purpose : auxilary for ExtrusionAlongTrack
+//purpose : spread values over nbSteps
//=======================================================================
-void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
+
+void SMESH_MeshEditor::LinearAngleVariation(const int nbSteps,
list<double>& Angles)
{
int nbAngles = Angles.size();
- if( nbSteps > nbAngles ) {
+ if( nbSteps > nbAngles && nbAngles > 0 )
+ {
vector<double> theAngles(nbAngles);
- list<double>::iterator it = Angles.begin();
- int i = -1;
- for(; it!=Angles.end(); it++) {
- i++;
- theAngles[i] = (*it);
- }
+ theAngles.assign( Angles.begin(), Angles.end() );
+
list<double> res;
double rAn2St = double( nbAngles ) / double( nbSteps );
double angPrev = 0, angle;
- for ( int iSt = 0; iSt < nbSteps; ++iSt ) {
+ for ( int iSt = 0; iSt < nbSteps; ++iSt )
+ {
double angCur = rAn2St * ( iSt+1 );
double angCurFloor = floor( angCur );
double angPrevFloor = floor( angPrev );
res.push_back(angle);
angPrev = angCur;
}
- Angles.clear();
- it = res.begin();
- for(; it!=res.end(); it++)
- Angles.push_back( *it );
+ Angles.swap( res );
}
}
* else step size is measured along average normal of any element
* USE_INPUT_ELEMS_ONLY: to use only input elements to compute extrusion direction
* for ExtrusionByNormal()
+ * SCALE_LINEAR_VARIATION: to make linear variation of scale factors
*/
enum ExtrusionFlags {
EXTRUSION_FLAG_BOUNDARY = 0x01,
EXTRUSION_FLAG_SEW = 0x02,
EXTRUSION_FLAG_GROUPS = 0x04,
EXTRUSION_FLAG_BY_AVG_NORMAL = 0x08,
- EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10
+ EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY = 0x10,
+ EXTRUSION_FLAG_SCALE_LINEAR_VARIATION = 0x20
};
/*!
* Generator of nodes for extrusion functionality
*/
- class SMESH_EXPORT ExtrusParam {
+ class SMESH_EXPORT ExtrusParam
+ {
gp_Dir myDir; // direction of extrusion
Handle(TColStd_HSequenceOfReal) mySteps; // magnitudes for each step
+ std::vector<double> myScales, myMediumScales;// scale factors
+ gp_XYZ myBaseP; // scaling center
SMESH_SequenceOfNode myNodes; // nodes for using in sewing
int myFlags; // see ExtrusionFlags
double myTolerance; // tolerance for sewing nodes
const bool makeMediumNodes);
public:
- ExtrusParam( const gp_Vec& theStep,
- const int theNbSteps,
- const int theFlags = 0,
- const double theTolerance = 1e-6);
+ ExtrusParam( const gp_Vec& theStep,
+ const int theNbSteps,
+ const std::list<double>& theScales,
+ const gp_XYZ* theBaseP,
+ const int theFlags = 0,
+ const double theTolerance = 1e-6);
ExtrusParam( const gp_Dir& theDir,
Handle(TColStd_HSequenceOfReal) theSteps,
const int theFlags = 0,
const double theTolerance = 1e-6);
- ExtrusParam( const double theStep,
- const int theNbSteps,
- const int theFlags,
- const int theDim); // for extrusion by normal
+ ExtrusParam( const double theStep,
+ const int theNbSteps,
+ const int theFlags,
+ const int theDim); // for extrusion by normal
SMESH_SequenceOfNode& ChangeNodes() { return myNodes; }
int& Flags() { return myFlags; }
bool ToMakeBoundary() const { return myFlags & EXTRUSION_FLAG_BOUNDARY; }
bool ToMakeGroups() const { return myFlags & EXTRUSION_FLAG_GROUPS; }
bool ToUseInpElemsOnly() const { return myFlags & EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY; }
+ bool IsLinearVariation() const { return myFlags & EXTRUSION_FLAG_SCALE_LINEAR_VARIATION; }
int NbSteps() const { return mySteps->Length(); }
// stores elements to use for extrusion by normal, depending on
- // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag
- void SetElementsToUse( const TIDSortedElemSet& elems );
+ // state of EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY flag;
+ // define myBaseP for scaling
+ void SetElementsToUse( const TIDSortedElemSet& elems, const TIDSortedElemSet& nodes );
// creates nodes and returns number of nodes added in \a newNodes
int MakeNodes( SMESHDS_Mesh* mesh,
const bool theHasRefPoint,
const gp_Pnt& theRefPoint,
const bool theMakeGroups);
- void LinearAngleVariation(const int NbSteps,
- std::list<double>& theAngles);
+ static void LinearAngleVariation(const int NbSteps,
+ std::list<double>& theAngles);
bool doubleNodes( SMESHDS_Mesh* theMeshDS,
const TIDSortedElemSet& theElems,
const TopoDS_Shape& S = subMesh->_subShape;
if ( S.ShapeType() != this->_subShape.ShapeType() )
continue;
- theSubs.push_back( subMesh );
if ( subMesh == this )
{
aBuilder.Add( aCompound, S );
+ theSubs.push_back( subMesh );
}
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
aBuilder.Add( aCompound, S );
if ( !subMesh->SubMeshesComputed() )
theSubComputed = false;
+ theSubs.push_back( subMesh );
}
}
}
if ( anActor->GetControlMode() != aControl )
anActor->SetControlMode( aControl );
QString functorName = functorToString( anActor->GetFunctor() );
+ int anEntitiesCount = anActor->GetNumberControlEntities();
+ if (anEntitiesCount >= 0)
+ functorName = functorName + ": " + QString::number(anEntitiesCount);
anActor->GetScalarBarActor()->SetTitle( functorName.toLatin1().constData() );
SMESH::RepaintCurrentView();
#ifndef DISABLE_PLOT2DVIEWER
case SMESHOp::OpCreateMesh:
case SMESHOp::OpCreateSubMesh:
case SMESHOp::OpEditMeshOrSubMesh:
+ case SMESHOp::OpEditMesh:
+ case SMESHOp::OpEditSubMesh:
case SMESHOp::OpCompute:
+ case SMESHOp::OpComputeSubMesh:
case SMESHOp::OpPreCompute:
case SMESHOp::OpEvaluate:
case SMESHOp::OpMeshOrder:
createSMESHAction( SMESHOp::OpCreateMesh, "CREATE_MESH", "ICON_DLG_INIT_MESH" );
createSMESHAction( SMESHOp::OpCreateSubMesh, "CREATE_SUBMESH", "ICON_DLG_ADD_SUBMESH" );
createSMESHAction( SMESHOp::OpEditMeshOrSubMesh, "EDIT_MESHSUBMESH", "ICON_DLG_EDIT_MESH" );
+ createSMESHAction( SMESHOp::OpEditMesh, "EDIT_MESH", "ICON_DLG_EDIT_MESH" );
+ createSMESHAction( SMESHOp::OpEditSubMesh, "EDIT_SUBMESH", "ICON_DLG_EDIT_MESH" );
createSMESHAction( SMESHOp::OpBuildCompoundMesh, "BUILD_COMPOUND", "ICON_BUILD_COMPOUND" );
createSMESHAction( SMESHOp::OpCopyMesh, "COPY_MESH", "ICON_COPY_MESH" );
createSMESHAction( SMESHOp::OpCompute, "COMPUTE", "ICON_COMPUTE" );
+ createSMESHAction( SMESHOp::OpComputeSubMesh, "COMPUTE_SUBMESH", "ICON_COMPUTE" );
createSMESHAction( SMESHOp::OpPreCompute, "PRECOMPUTE", "ICON_PRECOMPUTE" );
createSMESHAction( SMESHOp::OpEvaluate, "EVALUATE", "ICON_EVALUATE" );
createSMESHAction( SMESHOp::OpMeshOrder, "MESH_ORDER", "ICON_MESH_ORDER");
QString dc = "selcount"; // VSR : instead of QtxPopupSelection::defSelCountParam()
myRules.clear();
- QString OB = "'ObjectBrowser'",
- View = "'" + SVTK_Viewer::Type() + "'",
- pat = "'%1'",
- mesh = pat.arg( SMESHGUI_Selection::typeName( SMESH::MESH ) ),
- group = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ),
- hypo = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ),
- algo = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ),
- elems = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_FACE ) ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_SOLID ) ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_COMPOUND ) ).
- arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH ) ),
- subMesh = elems,
- mesh_part = mesh + " " + subMesh + " " + group,
- mesh_group = mesh + " " + group,
- hyp_alg = hypo + " " + algo;
+ QString
+ OB = "'ObjectBrowser'",
+ View = "'" + SVTK_Viewer::Type() + "'",
+ pat = "'%1'",
+ mesh = pat.arg( SMESHGUI_Selection::typeName( SMESH::MESH ) ),
+ group = pat.arg( SMESHGUI_Selection::typeName( SMESH::GROUP ) ),
+ hypo = pat.arg( SMESHGUI_Selection::typeName( SMESH::HYPOTHESIS ) ),
+ algo = pat.arg( SMESHGUI_Selection::typeName( SMESH::ALGORITHM ) ),
+ elems = QString( "'%1' '%2' '%3' '%4' '%5' '%6'" ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_VERTEX ) ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_EDGE ) ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_FACE ) ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_SOLID ) ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH_COMPOUND ) ).
+ arg( SMESHGUI_Selection::typeName( SMESH::SUBMESH ) ),
+ subMesh = elems,
+ mesh_part = mesh + " " + subMesh + " " + group,
+ mesh_group = mesh + " " + group,
+ mesh_submesh = mesh + " " + subMesh,
+ hyp_alg = hypo + " " + algo;
// popup for object browser
QString
hasVolumes("({'Volume'} in elemTypes)"),
hasFacesOrVolumes("(({'Face'} in elemTypes) || ({'Volume'} in elemTypes)) ");
- createPopupItem( SMESHOp::OpFileInformation, OB, mesh, "&& selcount=1 && isImported" );
- createPopupItem( SMESHOp::OpCreateSubMesh, OB, mesh, "&& hasGeomReference");
- createPopupItem( SMESHOp::OpEditMeshOrSubMesh, OB, mesh );
- createPopupItem( SMESHOp::OpEditMeshOrSubMesh, OB, subMesh, "&& hasGeomReference" );
- createPopupItem( SMESHOp::OpEditGroup, OB, group );
+ createPopupItem( SMESHOp::OpFileInformation, OB, mesh, "&& selcount=1 && isImported" );
+ createPopupItem( SMESHOp::OpCreateSubMesh, OB, mesh, "&& hasGeomReference");
+ createPopupItem( SMESHOp::OpEditMesh, OB, mesh, "&& selcount=1" );
+ createPopupItem( SMESHOp::OpEditSubMesh, OB, subMesh, "&& selcount=1 && hasGeomReference" );
+ createPopupItem( SMESHOp::OpEditGroup, OB, group );
createPopupItem( SMESHOp::OpEditGeomGroupAsGroup, OB, group, "&& groupType != 'Group'" );
popupMgr()->insert( separator(), -1, 0 );
- createPopupItem( SMESHOp::OpCompute, OB, mesh, "&& isComputable" );
- createPopupItem( SMESHOp::OpPreCompute, OB, mesh, "&& isPreComputable" );
- createPopupItem( SMESHOp::OpEvaluate, OB, mesh, "&& isComputable" );
- createPopupItem( SMESHOp::OpMeshOrder, OB, mesh, "&& isComputable && hasGeomReference" );
- createPopupItem( SMESHOp::OpUpdate, OB, mesh_part );
- createPopupItem( SMESHOp::OpMeshInformation, OB, mesh_part );
- createPopupItem( SMESHOp::OpFindElementByPoint, OB, mesh_group );
- createPopupItem( SMESHOp::OpOverallMeshQuality, OB, mesh_part );
+ createPopupItem( SMESHOp::OpCompute, OB, mesh, "&& selcount=1 && isComputable" );
+ createPopupItem( SMESHOp::OpComputeSubMesh, OB, subMesh, "&& selcount=1 && isComputable" );
+ createPopupItem( SMESHOp::OpPreCompute, OB, mesh, "&& selcount=1 && isPreComputable" );
+ createPopupItem( SMESHOp::OpEvaluate, OB, mesh, "&& selcount=1 && isComputable" );
+ createPopupItem( SMESHOp::OpMeshOrder, OB, mesh, "&& selcount=1 && isComputable && hasGeomReference" );
+ createPopupItem( SMESHOp::OpUpdate, OB, mesh_part );
+ createPopupItem( SMESHOp::OpMeshInformation, OB, mesh_part );
+ createPopupItem( SMESHOp::OpFindElementByPoint,OB, mesh_group, "&& selcount=1" );
+ createPopupItem( SMESHOp::OpOverallMeshQuality,OB, mesh_part );
popupMgr()->insert( separator(), -1, 0 );
- createPopupItem( SMESHOp::OpCreateGroup, OB, mesh );
- createPopupItem( SMESHOp::OpCreateGeometryGroup, OB, mesh, "&& hasGeomReference" );
- createPopupItem( SMESHOp::OpConstructGroup, OB, subMesh );
+ createPopupItem( SMESHOp::OpCreateGroup, OB, mesh, "&& selcount=1" );
+ createPopupItem( SMESHOp::OpCreateGeometryGroup, OB, mesh, "&& selcount=1 && hasGeomReference" );
+ createPopupItem( SMESHOp::OpConstructGroup, OB, subMesh );
popupMgr()->insert( separator(), -1, 0 );
- createPopupItem( SMESHOp::OpEditHypothesis, OB, hypo, "&& isEditableHyp");
- createPopupItem( SMESHOp::OpUnassign, OB, hyp_alg ); // REMOVE HYPOTHESIS / ALGORITHMS
+ createPopupItem( SMESHOp::OpEditHypothesis, OB, hypo, "&& isEditableHyp");
+ createPopupItem( SMESHOp::OpUnassign, OB, hyp_alg );
popupMgr()->insert( separator(), -1, 0 );
- createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh + " " + subMesh ); // convert to quadratic
- createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh + " " + group, // create 2D mesh from 3D
- "&& dim>=2");
+ createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh );
+ createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh_group, "&& selcount=1 && dim>=2");
popupMgr()->insert( separator(), -1, 0 );
createPopupItem( SMESHOp::OpClearMesh, OB, mesh );
- popupMgr()->insert( separator(), -1, 0 );
+ //popupMgr()->insert( separator(), -1, 0 );
QString only_one_non_empty = QString( " && %1=1 && numberOfNodes>0" ).arg( dc );
QString multiple_non_empty = QString( " && %1>0 && numberOfNodes>0" ).arg( dc );
op = new SMESHGUI_MeshOp( true, false );
break;
case SMESHOp::OpEditMeshOrSubMesh:
+ case SMESHOp::OpEditMesh:
+ case SMESHOp::OpEditSubMesh:
op = new SMESHGUI_MeshOp( false );
break;
case SMESHOp::OpCompute:
+ case SMESHOp::OpComputeSubMesh:
op = new SMESHGUI_ComputeOp();
break;
case SMESHOp::OpPreCompute:
if (ac->IsA("SMESH_Actor")) {
SMESH_Actor* aGeomAc = SMESH_Actor::SafeDownCast(ac);
if (aGeomAc->hasIO()) {
- Handle(SALOME_InteractiveObject) io =
- Handle(SALOME_InteractiveObject)::DownCast(aGeomAc->getIO());
+ Handle(SALOME_InteractiveObject) io = aGeomAc->getIO();
if (io->hasEntry() && strcmp(io->getEntry(), entry.toLatin1().data()) == 0) {
isFound = true;
vtkActors.Bind(viewIndex, aGeomAc);
myMesh = SMESH::SMESH_Mesh::_nil();
myMainShape = GEOM::GEOM_Object::_nil();
+ myCurShape = GEOM::GEOM_Object::_nil();
// check selection
LightApp_SelectionMgr *Sel = selectionMgr();
}
myIObject = selected.First();
- myMesh = SMESH::GetMeshByIO(myIObject);
+ CORBA::Object_var anObj = SMESH::IObjectToObject( myIObject );
+
+ myMesh = SMESH::SMESH_Mesh::_narrow(anObj);
+ if ( myMesh->_is_nil() )
+ {
+ SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj);
+ if ( !aSubMesh->_is_nil() )
+ {
+ myMesh = aSubMesh->GetFather();
+ myCurShape = aSubMesh->GetSubShape();
+ }
+ }
+ else
+ {
+ myCurShape = myMesh->GetShapeToMesh();
+ }
+
if (myMesh->_is_nil()) {
SUIT_MessageBox::warning(desktop(),
tr("SMESH_WRN_WARNING"),
onCancel();
return;
}
+
myMainShape = myMesh->GetShapeToMesh();
SMESHGUI_Operation::startOperation();
myMesh->Clear();
SUIT_OverrideCursor aWaitCursor;
try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
OCC_CATCH_SIGNALS;
-#endif
- SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myMainShape);
+ SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myCurShape);
qthreaddialog.exec();
computeFailed = !qthreaddialog.result();
}
memoryLack = true;
}
try {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
OCC_CATCH_SIGNALS;
-#endif
aCompErrors = gen->GetComputeErrors( myMesh, myMainShape );
// check if there are memory problems
for ( CORBA::ULong i = 0; (i < aCompErrors->length()) && !memoryLack; ++i )
// NPAL16631: if ( !memoryLack )
{
- SMESH::ModifiedMesh( aMeshSObj,
+ _PTR(SObject) sobj = SMESH::GetActiveStudyDocument()->FindObjectID(myIObject->getEntry());
+ SMESH::ModifiedMesh( sobj,
!computeFailed && aHypErrors.isEmpty(),
myMesh->NbNodes() == 0);
update( UF_ObjBrowser | UF_Model );
void SMESHGUI_BaseComputeOp::onPublishShape()
{
- GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
- SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
+ GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
+ SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
+ GEOM::GEOM_Object_var meshShape = myMesh->GetShapeToMesh();
QStringList entryList;
QList<int> rows;
*/
//================================================================================
-void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
+void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh,
QMap<int,int>& theModeMap)
{
if ( !theMesh ) return;
+
_PTR(SObject) aHypFolder;
_PTR(GenericAttribute) anAttr;
int aPart = SMESH::Tag_RefOnAppliedAlgorithms;
- if ( theMesh->FindSubObject( aPart, aHypFolder ) )
+ if ( theMesh->FindSubObject( aPart, aHypFolder ))
{
_PTR(ChildIterator) anIter =
SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder );
protected:
SMESH::SMESH_Mesh_var myMesh;
GEOM::GEOM_Object_var myMainShape;
+ GEOM::GEOM_Object_var myCurShape;
SMESH::TShapeDisplayer* myTShapeDisplayer;
SMESHGUI_MeshEditPreview* myBadMeshDisplayer;
Handle(SALOME_InteractiveObject) myIObject;
#include "SMESHGUI_ExtrusionDlg.h"
#include "SMESHGUI.h"
-#include "SMESHGUI_Utils.h"
-#include "SMESHGUI_VTKUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_SpinBox.h"
-#include "SMESHGUI_IdValidator.h"
#include "SMESHGUI_FilterDlg.h"
+#include "SMESHGUI_IdValidator.h"
#include "SMESHGUI_MeshEditPreview.h"
-
+#include "SMESHGUI_MeshUtils.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_VTKUtils.h"
+#include <GEOMBase.h>
+#include <SMDS_Mesh.hxx>
#include <SMESH_Actor.h>
-#include <SMESH_TypeFilter.hxx>
#include <SMESH_LogicalFilter.hxx>
-
-#include <SMDS_Mesh.hxx>
+#include <SMESH_TypeFilter.hxx>
// SALOME GUI includes
-#include <SUIT_ResourceMgr.h>
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
#include <SUIT_Desktop.h>
#include <SUIT_MessageBox.h>
-#include <SUIT_Session.h>
#include <SUIT_OverrideCursor.h>
-
-#include <LightApp_Application.h>
-#include <LightApp_SelectionMgr.h>
-
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
#include <SVTK_ViewModel.h>
#include <SVTK_ViewWindow.h>
-
#include <SalomeApp_IntSpinBox.h>
// OCCT includes
-#include <TColStd_MapOfInteger.hxx>
+#include <BRep_Tool.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopoDS_Vertex.hxx>
#include <gp_XYZ.hxx>
// Qt includes
#include <QApplication>
#include <QButtonGroup>
+#include <QCheckBox>
+#include <QGridLayout>
#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
+#include <QListWidget>
#include <QPushButton>
#include <QRadioButton>
-#include <QCheckBox>
-#include <QHBoxLayout>
+#include <QToolButton>
#include <QVBoxLayout>
-#include <QGridLayout>
-#include <QKeyEvent>
// IDL includes
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Group)
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+#include <SMESH_NumberFilter.hxx>
#define SPACING 6
#define MARGIN 11
: SMESHGUI_PreviewDlg( theModule ),
mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
{
- QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
+ SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
+ QPixmap selectImage ( mgr->loadPixmap("SMESH", tr("ICON_SELECT")));
+ QPixmap addImage ( mgr->loadPixmap("SMESH", tr("ICON_APPEND")));
+ QPixmap removeImage ( mgr->loadPixmap("SMESH", tr("ICON_REMOVE")));
setModal( false );
setAttribute( Qt::WA_DeleteOnClose, true );
TextLabelVector = new QLabel(tr("SMESH_VECTOR"), GroupArguments);
- SelectVectorButton = new QPushButton(GroupArguments);
- SelectVectorButton->setIcon(image);
+ SelectVectorButton = new QPushButton( GroupArguments );
+ SelectVectorButton->setIcon( selectImage );
SelectVectorButton->setCheckable( true );
SelectorWdg->GetButtonGroup()->addButton( SelectVectorButton );
//Preview check box
myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArguments);
+ // Base point
+
+ BasePointGrp = new QGroupBox(tr("BASE_POINT"), GroupArguments);
+ BasePointGrp->setCheckable(true);
+ BasePointGrp->setChecked(false);
+ QHBoxLayout* BasePointGrpLayout = new QHBoxLayout(BasePointGrp);
+ BasePointGrpLayout->setSpacing(SPACING); BasePointGrpLayout->setMargin(MARGIN);
+
+ SelectBasePointButton = new QPushButton(BasePointGrp);
+ SelectBasePointButton->setIcon(selectImage);
+ SelectBasePointButton->setCheckable(true);
+ SelectorWdg->GetButtonGroup()->addButton( SelectBasePointButton );
+
+ QLabel* XLab = new QLabel(tr("SMESH_X"), BasePointGrp);
+ BasePoint_XSpin = new SMESHGUI_SpinBox(BasePointGrp);
+ BasePoint_XSpin->SetValue(0.);
+ QLabel* YLab = new QLabel(tr("SMESH_Y"), BasePointGrp);
+ BasePoint_YSpin = new SMESHGUI_SpinBox(BasePointGrp);
+ BasePoint_YSpin->SetValue(0.);
+ QLabel* ZLab = new QLabel(tr("SMESH_Z"), BasePointGrp);
+ BasePoint_ZSpin = new SMESHGUI_SpinBox(BasePointGrp);
+ BasePoint_ZSpin->SetValue(0.);
+
+ BasePointGrpLayout->addWidget(SelectBasePointButton);
+ BasePointGrpLayout->addWidget(XLab);
+ BasePointGrpLayout->addWidget(BasePoint_XSpin, 1);
+ BasePointGrpLayout->addWidget(YLab);
+ BasePointGrpLayout->addWidget(BasePoint_YSpin, 1);
+ BasePointGrpLayout->addWidget(ZLab);
+ BasePointGrpLayout->addWidget(BasePoint_ZSpin, 1);
+
+ // Scales
+
+ ScalesGrp = new QGroupBox(tr("SMESH_SCALES"), GroupArguments);
+ QGridLayout* ScalesGrpLayout = new QGridLayout( ScalesGrp );
+ ScalesGrpLayout->setSpacing(SPACING); ScalesGrpLayout->setMargin(MARGIN);
+
+ ScalesList = new QListWidget( ScalesGrp );
+ ScalesList->setSelectionMode(QListWidget::ExtendedSelection);
+
+ AddScaleButton = new QToolButton( ScalesGrp );
+ AddScaleButton->setIcon( addImage );
+
+ RemoveScaleButton = new QToolButton( ScalesGrp );
+ RemoveScaleButton->setIcon( removeImage );
+
+ ScaleSpin = new SMESHGUI_SpinBox( ScalesGrp );
+ ScaleSpin->SetValue(2);
+
+ LinearScalesCheck = new QCheckBox(tr("LINEAR_SCALES"), ScalesGrp );
+
+ ScalesGrpLayout->addWidget(ScalesList, 0, 0, 4, 1);
+ ScalesGrpLayout->addWidget(AddScaleButton, 0, 1);
+ ScalesGrpLayout->addWidget(RemoveScaleButton, 2, 1);
+ ScalesGrpLayout->addWidget(ScaleSpin, 0, 2);
+ ScalesGrpLayout->addWidget(LinearScalesCheck, 4, 0);
+ ScalesGrpLayout->setRowMinimumHeight(1, 10);
+ ScalesGrpLayout->setRowStretch(3, 10);
+
+ // layouting
GroupArgumentsLayout->addWidget(SelectorWdg, 0, 0, 1, 9);
GroupArgumentsLayout->addWidget(ExtrMethod_RBut0, 1, 0, 1, 3);
GroupArgumentsLayout->addWidget(ExtrMethod_RBut1, 1, 3, 1, 3);
GroupArgumentsLayout->addWidget(SpinBox_NbSteps, 5, 3);
GroupArgumentsLayout->addWidget(ByAverageNormalCheck, 6, 0, 1, 4);
GroupArgumentsLayout->addWidget(UseInputElemsOnlyCheck, 6, 4, 1, 4);
- GroupArgumentsLayout->addWidget(myPreviewCheckBox, 7, 0, 1, 8);
- GroupArgumentsLayout->addWidget(MakeGroupsCheck, 8, 0, 1, 8);
+ GroupArgumentsLayout->addWidget(BasePointGrp, 7, 0, 1, 9);
+ GroupArgumentsLayout->addWidget(ScalesGrp, 8, 0, 1, 9);
+ GroupArgumentsLayout->addWidget(myPreviewCheckBox, 9, 0, 1, 8);
+ GroupArgumentsLayout->addWidget(MakeGroupsCheck, 10,0, 1, 8);
GroupArgumentsLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 10, 0);
/***************************************************************/
SpinBox_NbSteps->setRange(1, 999999);
SpinBox_VDist->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+ BasePoint_XSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+ BasePoint_YSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+ BasePoint_ZSpin->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
+ ScaleSpin->RangeStepAndValidator (COORD_MIN, COORD_MAX, 1.0, "length_precision");
+
ExtrMethod_RBut0->setChecked(true);
UseInputElemsOnlyCheck->setChecked(true);
MakeGroupsCheck->setChecked(true);
connect(SpinBox_Dy, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable()));
connect(SpinBox_Dz, SIGNAL(valueChanged(double)), SLOT(CheckIsEnable()));
+ connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleAdded()));
+ connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(OnScaleRemoved()));
+
connect(SelectVectorButton, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+ connect(SelectBasePointButton,SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+ connect(BasePointGrp, SIGNAL(toggled(bool)), this, SLOT(SetEditCurrentArgument()));
+ connect(BasePointGrp, SIGNAL(toggled(bool)), SelectBasePointButton, SLOT(click()));
connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(toDisplaySimulation()));
connect(SelectorWdg, SIGNAL(selectionChanged()), this, SLOT(toDisplaySimulation()));
connect(SpinBox_NbSteps, SIGNAL(valueChanged(int)), this, SLOT(toDisplaySimulation()));
connect(ByAverageNormalCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
connect(UseInputElemsOnlyCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+ connect(AddScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
+ connect(RemoveScaleButton, SIGNAL(clicked()), this, SLOT(toDisplaySimulation()));
+ connect(LinearScalesCheck, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+ connect(BasePointGrp, SIGNAL(toggled(bool)), this, SLOT(toDisplaySimulation()));
+ connect(BasePoint_XSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+ connect(BasePoint_YSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
+ connect(BasePoint_ZSpin, SIGNAL(valueChanged(double)), this, SLOT(toDisplaySimulation()));
//To Connect preview check box
connectPreviewControl();
return aModule > 1.0E-38;
}
+//=======================================================================
+//function : getScaleParams
+//purpose : return 3 scaling parameters
+//=======================================================================
+
+bool SMESHGUI_ExtrusionDlg::getScaleParams( SMESH::double_array*& scales,
+ SMESH::double_array*& basePoint )
+{
+ scales = new SMESH::double_array;
+ scales->length( myScalesList.count() );
+ for ( int i = 0; i < myScalesList.count(); ++i )
+ (*scales)[i] = myScalesList[i];
+
+ basePoint = new SMESH::double_array;
+ if ( BasePointGrp->isChecked() )
+ {
+ basePoint->length( 3 );
+ (*basePoint)[0] = BasePoint_XSpin->GetValue();
+ (*basePoint)[1] = BasePoint_YSpin->GetValue();
+ (*basePoint)[2] = BasePoint_ZSpin->GetValue();
+ }
+
+ return ( scales->length() > 0 && LinearScalesCheck->isChecked() );
+}
+
//=================================================================================
// function : ClickOnRadio()
// purpose : Radio button management
SelectorWdg->SetEnabled( false, SMESH::EDGE );
}
+ BasePointGrp->setEnabled( !ExtrMethod_RBut2->isChecked() );
+ ScalesGrp ->setEnabled( !ExtrMethod_RBut2->isChecked() );
+
+
CheckIsEnable();
onDisplaySimulation(true);
{
SMESH::DirStruct aVector;
getExtrusionVector(aVector);
-
+
QStringList aParameters;
if ( ExtrMethod_RBut0->isChecked() )
{
}
long aNbSteps = (long)SpinBox_NbSteps->value();
-
aParameters << SpinBox_NbSteps->text();
+ SMESH::double_array_var scales = new SMESH::double_array;
+ scales->length( myScalesList.count() );
+ for (int i = 0; i < myScalesList.count(); i++)
+ {
+ scales[i] = myScalesList[i];
+ aParameters << ScalesList->item(i)->text();
+ }
+
bool meshHadNewTypeBefore = true;
int maxSelType = 0;
const bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
- try {
+ try
+ {
SUIT_OverrideCursor aWaitCursor;
SMESH::SMESH_Mesh_var mesh = SelectorWdg->GetMesh();
}
else
{
+ SMESH::double_array_var scales, basePoint;
+ bool linVariation = getScaleParams( scales.out(), basePoint.out() );
groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
- aVector, aNbSteps, makeGroups );
+ aVector, aNbSteps,
+ scales, linVariation, basePoint,
+ makeGroups );
}
} catch (...) {
if (!GroupButtons->isEnabled())
return;
+ SALOME_ListIO aList;
+ mySelectionMgr->selectedObjects(aList);
+ if ( aList.IsEmpty() || aList.Extent() > 1 )
+ return;
+
if ( SelectVectorButton->isChecked() )
{
- SALOME_ListIO aList;
- mySelectionMgr->selectedObjects(aList);
- if ( aList.IsEmpty() || aList.Extent() > 1 )
- return;
-
Handle(SALOME_InteractiveObject) IO = aList.First();
TColStd_IndexedMapOfInteger aMapIndex;
mySelector->GetIndex(IO,aMapIndex);
SpinBox_Vy->SetValue(aNormale.Y());
SpinBox_Vz->SetValue(aNormale.Z());
}
+ else if ( SelectBasePointButton->isChecked() )
+ {
+ if (!BasePointGrp->isChecked())
+ return;
+
+ // try to get shape from selection
+ Handle(SALOME_InteractiveObject) IO = aList.First();
+
+ // check if geom vertex is selected
+ GEOM::GEOM_Object_var aGeomObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(IO);
+ TopoDS_Vertex aVertex;
+ if (!aGeomObj->_is_nil()) {
+ if (aGeomObj->IsShape() && GEOMBase::GetShape(aGeomObj, aVertex) && !aVertex.IsNull()) {
+ gp_Pnt aPnt = BRep_Tool::Pnt(aVertex);
+ BasePoint_XSpin->SetValue(aPnt.X());
+ BasePoint_YSpin->SetValue(aPnt.Y());
+ BasePoint_ZSpin->SetValue(aPnt.Z());
+ }
+ }
+
+ if ( aVertex.IsNull() )
+ {
+ // check if smesh node is selected
+ SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(IO);
+ if (aMesh->_is_nil())
+ return;
+
+ QString aString;
+ int aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
+ // return if more than one node is selected
+ if (aNbUnits != 1)
+ return;
+
+ SMESH_Actor* aMeshActor = SMESH::FindActorByObject(aMesh);
+ if (!aMeshActor)
+ return;
+
+ SMDS_Mesh* mesh = aMeshActor->GetObject()->GetMesh();
+ if (!mesh)
+ return;
+
+ const SMDS_MeshNode* n = mesh->FindNode(aString.toLong());
+ if (!n)
+ return;
+
+ BasePoint_XSpin->SetValue(n->X());
+ BasePoint_YSpin->SetValue(n->Y());
+ BasePoint_ZSpin->SetValue(n->Z());
+ }
+ }
onDisplaySimulation(true);
CheckIsEnable();
if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
aViewWindow->SetSelectionMode(FaceSelection);
}
+ else if ( send == SelectBasePointButton )
+ {
+ SMESH::SetPointRepresentation(true);
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+ aViewWindow->SetSelectionMode(NodeSelection);
+
+ SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter(SMESH::IDSOURCE);
+ SMESH_NumberFilter* aVertexFilter = new SMESH_NumberFilter ("GEOM", TopAbs_VERTEX,
+ 1, TopAbs_VERTEX);
+ QList<SUIT_SelectionFilter*> aListOfFilters;
+ aListOfFilters << aMeshOrSubMeshFilter << aVertexFilter;
+
+ mySelectionMgr->installFilter(new SMESH_LogicalFilter
+ (aListOfFilters, SMESH_LogicalFilter::LO_OR, true));
+ }
connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
SelectionIntoArgument();
}
ok = SpinBox_NbSteps->isValid( msg, true ) && ok;
+ if ( BasePointGrp->isChecked()) {
+ ok = BasePoint_XSpin->isValid( msg, true ) && ok;
+ ok = BasePoint_YSpin->isValid( msg, true ) && ok;
+ ok = BasePoint_ZSpin->isValid( msg, true ) && ok;
+ }
+
if( !ok ) {
QString str( tr( "SMESH_INCORRECT_INPUT" ) );
if ( !msg.isEmpty() )
}
else
{
+ SMESH::double_array_var scales, basePoint;
+ bool linVariation = getScaleParams( scales.out(), basePoint.out() );
groups = meshEditor->ExtrusionSweepObjects( nodes, edges, faces,
- aVector, aNbSteps, makeGroups );
+ aVector, aNbSteps,
+ scales, linVariation, basePoint,
+ makeGroups );
}
SMESH::MeshPreviewStruct_var aMeshPreviewStruct = meshEditor->GetPreviewData();
mySimulation->SetData(aMeshPreviewStruct._retn());
aVector.PS.z = aNormale.Z()*aVDist;
}
}
+
+//=======================================================================
+// function : OnScaleAdded()
+// purpose : Called when user adds Scale to the list
+//=======================================================================
+void SMESHGUI_ExtrusionDlg::OnScaleAdded()
+{
+ QString msg;
+ if( !ScaleSpin->isValid( msg, true ) ) {
+ QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+ if ( !msg.isEmpty() )
+ str += "\n" + msg;
+ SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+ return;
+ }
+ ScalesList->addItem(ScaleSpin->text());
+ myScalesList.append(ScaleSpin->GetValue());
+}
+
+//=======================================================================
+// function : OnScaleRemoved()
+// purpose : Called when user removes Scale(s) from the list
+//=======================================================================
+void SMESHGUI_ExtrusionDlg::OnScaleRemoved()
+{
+ QList<QListWidgetItem*> aList = ScalesList->selectedItems();
+ QListWidgetItem* anItem;
+ int row = 0;
+ foreach(anItem, aList) {
+ row = ScalesList->row(anItem);
+ myScalesList.removeAt(row);
+ delete anItem;
+ }
+ ScalesList->setCurrentRow( row, QItemSelectionModel::Select );
+}
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
class QButtonGroup;
-class QRadioButton;
+class QCheckBox;
class QGroupBox;
class QLabel;
class QLineEdit;
-class QCheckBox;
+class QListWidget;
class QPushButton;
+class QRadioButton;
+class QToolButton;
class SMESHGUI;
class SMESH_Actor;
class SalomeApp_IntSpinBox;
//=================================================================================
-// class : SMESHGUI_ExtrusionDlg
+// class : SMESHGUI_3TypesSelector
// purpose : A widget used to select both nodes, edges and faces for
// Extrusion and Revolution operations
//=================================================================================
void getExtrusionVector(SMESH::DirStruct& aVector);
void extrusionByNormal(SMESH::SMESH_MeshEditor_ptr meshEditor,
const bool makeGroups=false);
+ bool getScaleParams( SMESH::double_array*& scales,
+ SMESH::double_array*& basePoint );
bool isValid();
bool isValuesValid();
LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */
SVTK_Selector* mySelector;
+ QList<double> myScalesList;
// widgets
SMESHGUI_3TypesSelector* SelectorWdg;
QCheckBox* UseInputElemsOnlyCheck;
QCheckBox* MakeGroupsCheck;
+ QGroupBox* BasePointGrp;
+ QPushButton* SelectBasePointButton;
+ SMESHGUI_SpinBox* BasePoint_XSpin;
+ SMESHGUI_SpinBox* BasePoint_YSpin;
+ SMESHGUI_SpinBox* BasePoint_ZSpin;
+
+ QGroupBox* ScalesGrp;
+ QListWidget* ScalesList;
+ QToolButton* AddScaleButton;
+ QToolButton* RemoveScaleButton;
+ SMESHGUI_SpinBox* ScaleSpin;
+ QCheckBox* LinearScalesCheck;
+
QGroupBox* GroupButtons;
QPushButton* buttonOk;
QPushButton* buttonCancel;
void ActivateThisDialog();
void onOpenView();
void onCloseView();
+ void OnScaleAdded();
+ void OnScaleRemoved();
};
objectWg( Mesh, Btn )->hide();
objectWg( Geom, Btn )->hide();
}
+ setTitile( theToCreate, theIsMesh );
}
SMESHGUI_MeshDlg::~SMESHGUI_MeshDlg()
{
}
+//================================================================================
+/*!
+ * \brief Set dialog title
+ */
+//================================================================================
+
+void SMESHGUI_MeshDlg::setTitile( const bool theToCreate, const bool theIsMesh )
+{
+ if ( theToCreate )
+ {
+ setWindowTitle( tr( theIsMesh ? "CREATE_MESH" : "CREATE_SUBMESH" ));
+ }
+ else
+ {
+ setWindowTitle( tr( theIsMesh ? "EDIT_MESH" : "EDIT_SUBMESH") );
+ }
+
+}
+
//================================================================================
/*!
* \brief Gets tab with given id
void setAvailableMeshType(const QStringList& );
int currentMeshType();
void setCurrentMeshType( const int );
+ void setTitile( const bool, const bool );
signals:
void hypoSet( const QString& );
{
SMESH::SMESH_subMesh_var submeshVar =
SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
+ myIsMesh = submeshVar->_is_nil();
+ myDlg->setTitile( myToCreate, myIsMesh );
myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !submeshVar->_is_nil() );
myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, true );
myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide();
myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide();
myDlg->updateGeometry();
myDlg->adjustSize();
- myIsMesh = submeshVar->_is_nil();
readMesh();
}
else
OpCreateMesh = 2030, // MENU MESH - CREATE MESH
OpCreateSubMesh = 2031, // MENU MESH - CREATE SUBMESH
OpEditMeshOrSubMesh = 2032, // MENU MESH - EDIT MESH/SUBMESH
- OpBuildCompoundMesh = 2033, // MENU MESH - BUILD COMPOUND
- OpCopyMesh = 2034, // MENU MESH - COPY MESH
+ OpEditMesh = 2033, // POPUP - EDIT MESH
+ OpEditSubMesh = 2034, // POPUP - EDIT SUBMESH
+ OpBuildCompoundMesh = 2035, // MENU MESH - BUILD COMPOUND
+ OpCopyMesh = 2036, // MENU MESH - COPY MESH
OpCompute = 2040, // MENU MESH - COMPUTE
- OpPreCompute = 2041, // MENU MESH - PREVIEW
- OpEvaluate = 2042, // MENU MESH - EVALUATE
- OpMeshOrder = 2043, // MENU MESH - CHANGE SUBMESH PRIORITY
+ OpComputeSubMesh = 2041, // POPUP - COMPUTE SUBMESH
+ OpPreCompute = 2042, // MENU MESH - PREVIEW
+ OpEvaluate = 2043, // MENU MESH - EVALUATE
+ OpMeshOrder = 2044, // MENU MESH - CHANGE SUBMESH PRIORITY
OpCreateGroup = 2050, // MENU MESH - CREATE GROUP
OpCreateGeometryGroup = 2051, // MENU MESH - CREATE GROUPS FROM GEOMETRY
OpConstructGroup = 2052, // MENU MESH - CONSTRUCT GROUP
bool SMESHGUI_Selection::isComputable( int ind ) const
{
- if ( ind >= 0 && ind < myTypes.count() && myTypes[ind] == "Mesh" )
+ if ( ind >= 0 && ind < myTypes.count() && ( myTypes[ind] == "Mesh" ||
+ myTypes[ind].startsWith("Mesh " )))
{
QMap<int,int> modeMap;
- _PTR(SObject) so = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
- SMESHGUI_PrecomputeOp::getAssignedAlgos( so, modeMap );
+ _PTR(SObject) meshSO = SMESH::GetActiveStudyDocument()->FindObjectID( entry( ind ).toLatin1().data() );
+
+ _PTR(SComponent) component = meshSO->GetFatherComponent();
+ if ( meshSO->Depth() - component->Depth() > 1 ) // sub-mesh, get a mesh
+ while ( meshSO->Depth() - component->Depth() > 1 )
+ meshSO = meshSO->GetFather();
+
+ SMESHGUI_PrecomputeOp::getAssignedAlgos( meshSO, modeMap );
return modeMap.size() > 0;
}
return false;
<source>AREA_ELEMENTS</source>
<translation>Area</translation>
</message>
+ <message>
+ <source>FREE_NODES</source>
+ <translation>Free nodes</translation>
+ </message>
+ <message>
+ <source>FREE_EDGES</source>
+ <translation>Free edges</translation>
+ </message>
+ <message>
+ <source>FREE_FACES</source>
+ <translation>Free faces</translation>
+ </message>
+ <message>
+ <source>BARE_BORDER_FACE</source>
+ <translation>Faces with bare border</translation>
+ </message>
+ <message>
+ <source>OVER_CONSTRAINED_FACE</source>
+ <translation>Over-constrained faces</translation>
+ </message>
+ <message>
+ <source>BARE_BORDER_VOLUME</source>
+ <translation>Volumes with bare border</translation>
+ </message>
+ <message>
+ <source>OVER_CONSTRAINED_VOLUME</source>
+ <translation>Over-constrained volumes</translation>
+ </message>
<message>
<source>MIN_DIAG_ELEMENTS</source>
<translation>Minimum diagonal</translation>
<source>MEN_COMPUTE</source>
<translation>Compute</translation>
</message>
+ <message>
+ <source>MEN_COMPUTE_SUBMESH</source>
+ <translation>Compute Sub-mesh</translation>
+ </message>
<message>
<source>MEN_PRECOMPUTE</source>
<translation>Preview</translation>
<source>MEN_EDIT_MESHSUBMESH</source>
<translation>Edit Mesh/Sub-mesh</translation>
</message>
+ <message>
+ <source>MEN_EDIT_MESH</source>
+ <translation>Edit Mesh</translation>
+ </message>
+ <message>
+ <source>MEN_EDIT_SUBMESH</source>
+ <translation>Edit Sub-mesh</translation>
+ </message>
<message>
<source>MEN_EXPORT</source>
<translation>Export</translation>
<source>STB_COMPUTE</source>
<translation>Compute</translation>
</message>
+ <message>
+ <source>STB_COMPUTE_SUBMESH</source>
+ <translation>Compute Sub-mesh</translation>
+ </message>
<message>
<source>STB_PRECOMPUTE</source>
<translation>Preview</translation>
<source>STB_EDIT_MESHSUBMESH</source>
<translation>Edit Mesh/Sub-mesh</translation>
</message>
+ <message>
+ <source>STB_EDIT_MESH</source>
+ <translation>Edit Mesh</translation>
+ </message>
+ <message>
+ <source>STB_EDIT_SUBMESH</source>
+ <translation>Edit Sub-mesh</translation>
+ </message>
<message>
<source>STB_EXPORT_DAT</source>
<translation>Export to DAT file</translation>
<source>TOP_COMPUTE</source>
<translation>Compute</translation>
</message>
+ <message>
+ <source>TOP_COMPUTE_SUBMESH</source>
+ <translation>Compute Sub-mesh</translation>
+ </message>
<message>
<source>TOP_PRECOMPUTE</source>
<translation>Preview</translation>
<source>TOP_EDIT_MESHSUBMESH</source>
<translation>Edit Mesh/Sub-mesh</translation>
</message>
+ <message>
+ <source>TOP_EDIT_MESH</source>
+ <translation>Edit Mesh</translation>
+ </message>
+ <message>
+ <source>TOP_EDIT_SUBMESH</source>
+ <translation>Edit Sub-mesh</translation>
+ </message>
<message>
<source>TOP_EXPORT_DAT</source>
<translation>Export to DAT file</translation>
<source>STB_SORT_CHILD_ITEMS</source>
<translation>Sort child items</translation>
</message>
+ <message>
+ <source>SMESH_ADVANCED</source>
+ <translation>Advanced</translation>
+ </message>
</context>
<context>
<name>SMESHGUI_FieldSelectorWdg</name>
<source>USE_INPUT_ELEMS_ONLY</source>
<translation>Use only input elements</translation>
</message>
+ <message>
+ <source>SMESH_SCALES</source>
+ <translation>Scale Factors</translation>
+ </message>
+ <message>
+ <source>LINEAR_SCALES</source>
+ <translation>Linear Variation of Scale Factors</translation>
+ </message>
+ <message>
+ <source>BASE_POINT</source>
+ <translation>Scaling Center</translation>
+ </message>
</context>
<context>
<name>SMESHGUI_FilterDlg</name>
<translation>3D</translation>
</message>
<message>
- <source>EDIT_MESH_SUBMESH</source>
- <translation>Edit mesh/sub-mesh</translation>
+ <source>EDIT_MESH</source>
+ <translation>Edit mesh</translation>
+ </message>
+ <message>
+ <source>EDIT_SUBMESH</source>
+ <translation>Edit sub-mesh</translation>
</message>
<message>
<source>GEOMETRY</source>
<translation>At least one entity type should be chosen!</translation>
</message>
</context>
+<context>
+ <name>SMESH_AdvOptionsWdg</name>
+ <message>
+ <source>ADD_OPTION_BTN</source>
+ <translation>Add option</translation>
+ </message>
+ <message>
+ <source>CHOICE</source>
+ <translation>Choice</translation>
+ </message>
+ <message>
+ <source>OPTION_NAME</source>
+ <translation>Option name</translation>
+ </message>
+ <message>
+ <source>OPTION_VALUE</source>
+ <translation>Option value</translation>
+ </message>
+</context>
</TS>
}
else if ( ! intersection.IsParallel() && intersection.NbPoints() > 0 )
{
+ double tol = 1e-4 * Sqrt( fNorm.Modulus() );
gp_Pnt intersectionPoint = intersection.Point(1);
- if ( !SMESH_MeshAlgos::IsOut( *face, intersectionPoint, tolerance ))
+ if ( !SMESH_MeshAlgos::IsOut( *face, intersectionPoint, tol ))
u2inters.insert(make_pair( intersection.ParamOnConic(1), TInters( *face, fNorm )));
}
}
// get ordered nodes
- vector< SMESH_TNodeXYZ > xyz;
+ vector< SMESH_TNodeXYZ > xyz; xyz.reserve( element->NbNodes()+1 );
SMDS_ElemIteratorPtr nodeIt = element->interlacedNodesElemIterator();
- while ( nodeIt->more() )
- {
- SMESH_TNodeXYZ node = nodeIt->next();
- xyz.push_back( node );
- }
+ for ( int i = 0; nodeIt->more(); ++i )
+ xyz.push_back( SMESH_TNodeXYZ( nodeIt->next() ));
int i, nbNodes = (int) xyz.size(); // central node of biquadratic is missing
// check if the point lays on face plane
gp_Vec n2p( xyz[0], point );
- if ( fabs( n2p * faceNorm ) > tol )
- return true; // not on face plane
+ double dot = n2p * faceNorm;
+ if ( Abs( dot ) > tol ) // not on face plane
+ {
+ bool isOut = true;
+ if ( nbNodes > 3 ) // maybe the face is not planar
+ {
+ double elemThick = 0;
+ for ( i = 1; i < nbNodes; ++i )
+ {
+ gp_Vec n2n( xyz[0], xyz[i] );
+ elemThick = Max( elemThick, Abs( n2n * faceNorm ));
+ }
+ isOut = Abs( dot ) > elemThick + tol;
+ }
+ if ( isOut )
+ return isOut;
+ }
// check if point is out of face boundary:
// define it by closest transition of a ray point->infinity through face boundary
normSize = plnNorm.Magnitude();
if ( normSize <= tol ) return false; // point coincides with the first node
plnNorm /= normSize;
- // for each node of the face, compute its signed distance to the plane
+ // for each node of the face, compute its signed distance to the cutting plane
vector<double> dist( nbNodes + 1);
for ( i = 0; i < nbNodes; ++i )
{
dist.back() = dist.front();
// find the closest intersection
int iClosest = -1;
- double rClosest = 0, distClosest = 1e100;;
+ double rClosest = 0, distClosest = 1e100;
gp_Pnt pClosest;
for ( i = 0; i < nbNodes; ++i )
{
double r;
- if ( fabs( dist[i]) < tol )
+ if ( fabs( dist[i] ) < tol )
r = 0.;
else if ( fabs( dist[i+1]) < tol )
r = 1.;
else
continue; // no intersection
gp_Pnt pInt = xyz[i] * (1.-r) + xyz[i+1] * r;
- gp_Vec p2int ( point, pInt);
- if ( p2int * ray > -tol ) // right half-space
+ gp_Vec p2int( point, pInt);
+ double intDist = p2int.SquareMagnitude();
+ if ( intDist < distClosest )
{
- double intDist = p2int.SquareMagnitude();
- if ( intDist < distClosest )
- {
- iClosest = i;
- rClosest = r;
- pClosest = pInt;
- distClosest = intDist;
- }
+ iClosest = i;
+ rClosest = r;
+ pClosest = pInt;
+ distClosest = intDist;
}
}
if ( iClosest < 0 )
bool covexCorner = ( edgeNorm * edgeAdjacent * (rClosest==1. ? 1. : -1.)) < 0;
return covexCorner ? (out || out2) : (out && out2);
}
+
if ( element->GetType() == SMDSAbs_Edge ) // --------------------------------------------------
{
// point is out of edge if it is NOT ON any straight part of edge
}
return true;
}
+
// Node or 0D element -------------------------------------------------------------------------
{
gp_Vec n2p ( xyz[0], point );
myLocShape = SMESH_Mesh::PseudoShape();
// call implementation compute
::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
- myGen.PrepareCompute( myLocMesh, myLocShape);
- bool ok = myGen.Compute( myLocMesh, myLocShape);
+ myGen.PrepareCompute( myLocMesh, myLocShape );
+ bool ok = myGen.Compute( myLocMesh, myLocShape, myLocShape != myLocMesh.GetShapeToMesh());
meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
myLocMesh.GetMeshDS()->Modified();
return ok;
bool myIsExtrusionByNormal;
static int makeFlags( CORBA::Boolean MakeGroups,
+ CORBA::Boolean LinearVariation = false,
CORBA::Boolean ByAverageNormal = false,
CORBA::Boolean UseInputElemsOnly = false,
CORBA::Long Flags = 0,
if ( MakeGroups ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
if ( ByAverageNormal ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
+ if ( LinearVariation ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
if ( MakeBoundary ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
return Flags;
}
// standard params
- ExtrusionParams(const SMESH::DirStruct & theDir,
- CORBA::Long theNbOfSteps,
- CORBA::Boolean theMakeGroups):
+ ExtrusionParams(const SMESH::DirStruct & theDir,
+ CORBA::Long theNbOfSteps,
+ const SMESH::double_array & theScaleFactors,
+ CORBA::Boolean theLinearVariation,
+ const SMESH::double_array & theBasePoint,
+ CORBA::Boolean theMakeGroups):
::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
theDir.PS.y,
theDir.PS.z ),
theNbOfSteps,
- makeFlags( theMakeGroups )),
+ toList( theScaleFactors ),
+ TBasePoint( theBasePoint ),
+ makeFlags( theMakeGroups, theLinearVariation )),
myIsExtrusionByNormal( false )
{
}
theDir.PS.y,
theDir.PS.z ),
theNbOfSteps,
- makeFlags( theMakeGroups, false, false,
+ std::list<double>(),
+ 0,
+ makeFlags( theMakeGroups, false, false, false,
theExtrFlags, false ),
theSewTolerance ),
myIsExtrusionByNormal( false )
CORBA::Boolean theMakeGroups ):
::SMESH_MeshEditor::ExtrusParam ( theStepSize,
theNbOfSteps,
- makeFlags( theMakeGroups,
+ makeFlags( theMakeGroups, false,
theByAverageNormal, theUseInputElemsOnly ),
theDim),
myIsExtrusionByNormal( true )
{
Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
}
+
+ private:
+
+ static std::list<double> toList( const SMESH::double_array & theScaleFactors )
+ {
+ std::list<double> scales;
+ for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
+ scales.push_back( theScaleFactors[i] );
+ return scales;
+ }
+
+ // structure used to convert SMESH::double_array to gp_XYZ*
+ struct TBasePoint
+ {
+ gp_XYZ *pp, p;
+ TBasePoint( const SMESH::double_array & theBasePoint )
+ {
+ pp = 0;
+ if ( theBasePoint.length() == 3 )
+ {
+ p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
+ pp = &p;
+ }
+ }
+ operator const gp_XYZ*() const { return pp; }
+ };
};
}
const SMESH::ListOfIDSources & theFaces,
const SMESH::DirStruct & theStepVector,
CORBA::Long theNbOfSteps,
+ const SMESH::double_array & theScaleFactors,
+ CORBA::Boolean theLinearVariation,
+ const SMESH::double_array & theBasePoint,
CORBA::Boolean theToMakeGroups)
throw (SALOME::SALOME_Exception)
{
SMESH_TRY;
initData();
- ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
+ ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
+ theLinearVariation, theBasePoint, theToMakeGroups );
TIDSortedElemSet elemsNodes[2];
for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
<< thePathShape << ", "
<< theNodeStart << ", "
<< theHasAngles << ", "
- << theAngles << ", "
+ << TVar( theAngles ) << ", "
<< theLinearVariation << ", "
<< theHasRefPoint << ", "
<< "SMESH.PointStruct( "
- << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
- << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
- << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
+ << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+ << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+ << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
<< theMakeGroups << " )";
}
else
const SMESH::ListOfIDSources & faces,
const SMESH::DirStruct & stepVector,
CORBA::Long nbOfSteps,
+ const SMESH::double_array & theScaleFactors,
+ CORBA::Boolean theLinearVariation,
+ const SMESH::double_array & theBasePoint,
CORBA::Boolean toMakeGroups)
throw (SALOME::SALOME_Exception);
print allReasons
pass
if salome.sg.hasDesktop() and self.mesh.GetStudyId() >= 0:
- smeshgui = salome.ImportComponentGUI("SMESH")
- smeshgui.Init(self.mesh.GetStudyId())
- smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
- if refresh: salome.sg.updateObjBrowser(1)
- pass
+ if not isinstance( refresh, list): # not a call from subMesh.Compute()
+ smeshgui = salome.ImportComponentGUI("SMESH")
+ smeshgui.Init(self.mesh.GetStudyId())
+ smeshgui.SetMeshIcon( salome.ObjectToID( self.mesh ), ok, (self.NbNodes()==0) )
+ if refresh: salome.sg.updateObjBrowser(1)
+
return ok
## Return a list of error messages (SMESH.ComputeError) of the last Compute()
NbOfSteps, Tolerance, MakeGroups, TotalAngle)
## Generates new elements by extrusion of the given elements and nodes
- # @param nodes - nodes to extrude: a list including ids, groups, sub-meshes or a mesh
- # @param edges - edges to extrude: a list including ids, groups, sub-meshes or a mesh
- # @param faces - faces to extrude: a list including ids, groups, sub-meshes or a mesh
+ # @param nodes nodes to extrude: a list including ids, groups, sub-meshes or a mesh
+ # @param edges edges to extrude: a list including ids, groups, sub-meshes or a mesh
+ # @param faces faces to extrude: a list including ids, groups, sub-meshes or a mesh
# @param StepVector vector or DirStruct or 3 vector components, defining
# the direction and value of extrusion for one step (the total extrusion
# length will be NbOfSteps * ||StepVector||)
# @param NbOfSteps the number of steps
# @param MakeGroups forces the generation of new groups from existing ones
+ # @param scaleFactors optional scale factors to apply during extrusion
+ # @param linearVariation if @c True, scaleFactors are spread over all @a scaleFactors,
+ # else scaleFactors[i] is applied to nodes at the i-th extrusion step
+ # @param basePoint optional scaling center; if not provided, a gravity center of
+ # nodes and elements being extruded is used as the scaling center.
+ # It can be either
+ # - a list of tree components of the point or
+ # - a node ID or
+ # - a GEOM point
# @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise
# @ingroup l2_modif_extrurev
- def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False):
+ def ExtrusionSweepObjects(self, nodes, edges, faces, StepVector, NbOfSteps, MakeGroups=False,
+ scaleFactors=[], linearVariation=False, basePoint=[] ):
unRegister = genObjUnRegister()
nodes = self._getIdSourceList( nodes, SMESH.NODE, unRegister )
edges = self._getIdSourceList( edges, SMESH.EDGE, unRegister )
if isinstance( StepVector, list ):
StepVector = self.smeshpyD.MakeDirStruct(*StepVector)
+ if isinstance( basePoint, int):
+ xyz = self.GetNodeXYZ( basePoint )
+ if not xyz:
+ raise RuntimeError, "Invalid node ID: %s" % basePoint
+ basePoint = xyz
+ if isinstance( basePoint, geomBuilder.GEOM._objref_GEOM_Object ):
+ basePoint = self.geompyD.PointCoordinates( basePoint )
+
NbOfSteps,Parameters,hasVars = ParseParameters(NbOfSteps)
Parameters = StepVector.PS.parameters + var_separator + Parameters
self.mesh.SetParameters(Parameters)
return self.editor.ExtrusionSweepObjects( nodes, edges, faces,
- StepVector, NbOfSteps, MakeGroups)
+ StepVector, NbOfSteps,
+ scaleFactors, linearVariation, basePoint,
+ MakeGroups)
## Generates new elements by extrusion of the elements with given ids
pass # end of Mesh class
-## class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
+## Class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
# with old dump scripts which call SMESH_Mesh directly and not via smeshBuilder.Mesh
#
class meshProxy(SMESH._objref_SMESH_Mesh):
pass
omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
-## class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
+
+## Class wrapping SMESH_SubMesh in order to add Compute()
+#
+class submeshProxy(SMESH._objref_SMESH_subMesh):
+ def __init__(self):
+ SMESH._objref_SMESH_subMesh.__init__(self)
+ self.mesh = None
+ def __deepcopy__(self, memo=None):
+ new = self.__class__()
+ return new
+
+ ## Computes the sub-mesh and returns the status of the computation
+ # @param refresh if @c True, Object browser is automatically updated (when running in GUI)
+ # @return True or False
+ # @ingroup l2_construct
+ def Compute(self,refresh=False):
+ if not self.mesh:
+ self.mesh = Mesh( smeshBuilder(), None, self.GetMesh())
+
+ ok = self.mesh.Compute( self.GetSubShape(),refresh=[] )
+
+ if salome.sg.hasDesktop() and self.mesh.GetStudyId() >= 0:
+ smeshgui = salome.ImportComponentGUI("SMESH")
+ smeshgui.Init(self.mesh.GetStudyId())
+ smeshgui.SetMeshIcon( salome.ObjectToID( self ), ok, (self.GetNumberOfElements()==0) )
+ if refresh: salome.sg.updateObjBrowser(1)
+ pass
+
+ return ok
+ pass
+omniORB.registerObjref(SMESH._objref_SMESH_subMesh._NP_RepositoryId, submeshProxy)
+
+
+## Class used to compensate change of CORBA API of SMESH_MeshEditor for backward compatibility
# with old dump scripts which call SMESH_MeshEditor directly and not via smeshBuilder.Mesh
#
class meshEditor(SMESH._objref_SMESH_MeshEditor):
raise RuntimeError, "No class found for algo type %s" % algoType
return None
-# Private class used to substitute and store variable parameters of hypotheses.
+## Private class used to substitute and store variable parameters of hypotheses.
#
class hypMethodWrapper:
def __init__(self, hyp, method):
return result
pass
-# A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+## A helper class that call UnRegister() of SALOME.GenericObj'es stored in it
+#
class genObjUnRegister:
def __init__(self, genObj=None):
if genObj and hasattr( genObj, "UnRegister" ):
genObj.UnRegister()
+
+## Bind methods creating mesher plug-ins to the Mesh class
+#
for pluginName in os.environ[ "SMESH_MeshersList" ].split( ":" ):
#
#print "pluginName: ", pluginName
const double theUFirst,
const double theULast)
{
+ myEdge.resize ( 1 );
+ myEdgeID.resize ( 1, 0 );
myC2d.push_back ( theC2d );
+ myC3dAdaptor.resize ( 1 );
myFirst.push_back ( theUFirst );
myLast.push_back ( theULast );
myNormPar.push_back ( 1. );
myIsUniform.push_back( true );
- myEdgeID.push_back ( 0 );
myLength = 0;
myProxyMesh = theSide->myProxyMesh;
myDefaultPnt2d = *thePnt2d1;
if ( NbEdges() == 0 ) return myPoints;
StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
- //SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
fHelper.SetSubShape( myFace );
else
{
node = VertexNode( iE );
- while ( !node && iE > 0 )
- node = VertexNode( --iE );
- if ( !node )
- return myPoints;
+ if ( myProxyMesh->GetMesh()->HasModificationsToDiscard() )
+ while ( !node && iE > 1 ) // check intermediate VERTEXes
+ node = VertexNode( --iE );
}
- if ( u2node.rbegin()->second == node &&
- !fHelper.IsRealSeam ( node->getshapeId() ) &&
- !fHelper.IsDegenShape( node->getshapeId() ))
- u2node.erase( --u2node.end() );
+ if ( node )
+ {
+ if ( u2node.rbegin()->second == node &&
+ !fHelper.IsRealSeam ( node->getshapeId() ) &&
+ !fHelper.IsDegenShape( node->getshapeId() ))
+ u2node.erase( --u2node.end() );
- u2node.insert( u2node.end(), make_pair( 1., node ));
+ u2node.insert( u2node.end(), make_pair( 1., node ));
+ }
}
if ((int) u2node.size() + nbProxyNodes != myNbPonits &&
*/
const SMDS_MeshNode* VertexNode(std::size_t i, bool* isMoved = 0) const;
- /*!
+ /*
* \brief Return edge and parameter on edge by normalized parameter
*/
inline double Parameter(double U, TopoDS_Edge & edge) const;
+ /*
+ * \brief Return edge ID and parameter on edge by normalized parameter
+ */
+ inline double Parameter(double U, int & edgeID) const;
/*!
* \brief Return UV by normalized parameter
*/
//================================================================================
/*!
- * \brief Return edge and parameter on edge by normalized parameter
- * \param U - the parameter
+ * \brief Return an edge and parameter on the edge by a normalized parameter
+ * \param U - normalized parameter
* \retval double - pameter on a curve
+ * \ warning The returned parameter can be inaccurate if the edge is non-uniformly
+ * parametrized. Use Value2d() to get a precise point on the edge
*/
//================================================================================
return myFirst[i] * ( 1 - r ) + myLast[i] * r;
}
+//================================================================================
+/*!
+ * \brief Return an edge ID and parameter on the edge by a normalized parameter
+ * \param U - normalized parameter
+ * \retval double - pameter on a curve
+ * \ warning The returned parameter can be inaccurate if the edge is non-uniformly
+ * parametrized. Use Value2d() to get a precise point on the edge
+ */
+//================================================================================
+
+inline double StdMeshers_FaceSide::Parameter(double U, int & edgeID) const
+{
+ int i = EdgeIndex( U );
+ edgeID = myEdgeID[ i ];
+ double prevU = i ? myNormPar[ i-1 ] : 0;
+ double r = ( U - prevU )/ ( myNormPar[ i ] - prevU );
+ return myFirst[i] * ( 1 - r ) + myLast[i] * r;
+}
+
//================================================================================
/*!
* \brief Return first normalized parameter of the i-th edge
if ( !StdMeshers_Regular_1D::computeInternalParameters( mesh, C3D, len, f, l, theParams, false))
{
for ( size_t i = 1; i < 15; ++i )
- theParams.push_back( i/15 );
+ theParams.push_back( i/15. ); // ????
}
else
{
uvsNew.push_back( uvPt );
for (list<double>::iterator itU = params.begin(); itU != params.end(); ++itU )
{
- gp_XY uv = ( 1 - *itU ) * uvOut + *itU * uvIn;
+ gp_XY uv = ( 1 - *itU ) * uvOut + *itU * uvIn; // applied in direction Out -> In
gp_Pnt p = surface->Value( uv.X(), uv.Y() );
uvPt.node = theHelper.AddNode( p.X(), p.Y(), p.Z(), /*id=*/0, uv.X(), uv.Y() );
uvPt.u = uv.X();
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// SMESH SMESH : implementaion of SMESH idl descriptions
-// File : StdMeshers_RadialQuadrangle_1D2D.cxx
-// Module : SMESH
+// File : StdMeshers_RadialQuadrangle_1D2D.cxx
+// Module: SMESH
#include "StdMeshers_RadialQuadrangle_1D2D.hxx"
#include "StdMeshers_LayerDistribution.hxx"
#include "StdMeshers_Regular_1D.hxx"
#include "StdMeshers_NumberOfSegments.hxx"
+#include "StdMeshers_FaceSide.hxx"
#include "SMDS_MeshNode.hxx"
#include "SMESHDS_Mesh.hxx"
#include "SMESH_MesherHelper.hxx"
#include "SMESH_subMesh.hxx"
#include "SMESH_subMeshEventListener.hxx"
+#include "SMESH_Block.hxx"
#include "utilities.h"
+#include <BRepAdaptor_CompCurve.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
+#include <ShapeFix_Edge.hxx>
#include <TColgp_SequenceOfPnt.hxx>
#include <TColgp_SequenceOfPnt2d.hxx>
#include <TopExp.hxx>
//purpose :
//=======================================================================
-StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
- int studyId,
+StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int hypId,
+ int studyId,
SMESH_Gen* gen)
- :SMESH_2D_Algo(hypId, studyId, gen)
+ :StdMeshers_Quadrangle_2D( hypId, studyId, gen )
{
_name = "RadialQuadrangle_1D2D";
_shapeType = (1 << TopAbs_FACE); // 1 bit per shape type
}
};
- // ------------------------------------------------------------------------------
+ //================================================================================
/*!
* \brief Mark an edge as computed by StdMeshers_RadialQuadrangle_1D2D
*/
+ //================================================================================
+
void markEdgeAsComputedByMe(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
{
if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
edgeSM);
}
}
- // ------------------------------------------------------------------------------
- /*!
- * \brief Return true if a radial edge was meshed with StdMeshers_RadialQuadrangle_1D2D with
- * the same radial distribution
- */
-// bool isEdgeCompatiballyMeshed(const TopoDS_Edge& edge, SMESH_subMesh* faceSubMesh)
-// {
-// if ( SMESH_subMesh* edgeSM = faceSubMesh->GetFather()->GetSubMeshContaining( edge ))
-// {
-// if ( SMESH_subMeshEventListenerData* otherFaceData =
-// edgeSM->GetEventListenerData( TEdgeMarker::getListener() ))
-// {
-// // compare hypothesis aplied to two disk faces sharing radial edges
-// SMESH_Mesh& mesh = *faceSubMesh->GetFather();
-// SMESH_Algo* radialQuadAlgo = mesh.GetGen()->GetAlgo(mesh, faceSubMesh->GetSubShape() );
-// SMESH_subMesh* otherFaceSubMesh = otherFaceData->mySubMeshes.front();
-// list <const SMESHDS_Hypothesis *> hyps1 =
-// radialQuadAlgo->GetUsedHypothesis( mesh, faceSubMesh->GetSubShape());
-// list <const SMESHDS_Hypothesis *> hyps2 =
-// radialQuadAlgo->GetUsedHypothesis( mesh, otherFaceSubMesh->GetSubShape());
-// if( hyps1.empty() && hyps2.empty() )
-// return true; // defaul hyps
-// if ( hyps1.size() != hyps2.size() )
-// return false;
-// return *hyps1.front() == *hyps2.front();
-// }
-// }
-// return false;
-// }
//================================================================================
/*!
- * \brief Return base curve of the edge and extremum parameters
+ * \brief Return sides of the face connected in the order: aCircEdge, aLinEdge1, aLinEdge2
+ * \retval int - nb of sides
*/
//================================================================================
- Handle(Geom_Curve) getCurve(const TopoDS_Edge& edge, double* f=0, double* l=0)
+ int analyseFace(const TopoDS_Shape& aShape,
+ SMESH_Mesh* aMesh,
+ StdMeshers_FaceSidePtr& aCircSide,
+ StdMeshers_FaceSidePtr& aLinSide1,
+ StdMeshers_FaceSidePtr& aLinSide2)
{
- Handle(Geom_Curve) C;
- if ( !edge.IsNull() )
+ const TopoDS_Face& face = TopoDS::Face( aShape );
+ aCircSide.reset(); aLinSide1.reset(); aLinSide2.reset();
+
+ list< TopoDS_Edge > edges;
+ list< int > nbEdgesInWire;
+ int nbWire = SMESH_Block::GetOrderedEdges ( face, edges, nbEdgesInWire );
+ if ( nbWire > 2 || nbEdgesInWire.front() < 1 ) return 0;
+
+ // remove degenerated EDGEs
+ list<TopoDS_Edge>::iterator edge = edges.begin();
+ while ( edge != edges.end() )
+ if ( SMESH_Algo::isDegenerated( *edge ))
+ edge = edges.erase( edge );
+ else
+ ++edge;
+ int nbEdges = edges.size();
+
+ // find VERTEXes between continues EDGEs
+ TopTools_MapOfShape contVV;
+ if ( nbEdges > 1 )
{
- double first = 0., last = 0.;
- C = BRep_Tool::Curve(edge, first, last);
- if ( !C.IsNull() )
+ TopoDS_Edge ePrev = edges.back();
+ for ( edge = edges.begin(); edge != edges.end(); ++edge )
{
- Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C);
- while( !tc.IsNull() ) {
- C = tc->BasisCurve();
- tc = Handle(Geom_TrimmedCurve)::DownCast(C);
- }
- if ( f ) *f = first;
- if ( l ) *l = last;
+ if ( SMESH_Algo::IsContinuous( ePrev, *edge ))
+ contVV.Add( SMESH_MesherHelper::IthVertex( 0, *edge ));
+ ePrev = *edge;
+ }
+ }
+ // make edges start from a non-continues VERTEX
+ if ( 1 < contVV.Extent() && contVV.Extent() < nbEdges )
+ {
+ while ( contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+ edges.splice( edges.end(), edges, edges.begin() );
+ }
+
+ // make face sides
+ TSideVector sides;
+ while ( !edges.empty() )
+ {
+ list< TopoDS_Edge > sideEdges;
+ sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+ while ( !edges.empty() &&
+ contVV.Contains( SMESH_MesherHelper::IthVertex( 0, edges.front() )))
+ sideEdges.splice( sideEdges.end(), edges, edges.begin() );
+
+ StdMeshers_FaceSidePtr side;
+ if ( aMesh )
+ side = StdMeshers_FaceSide::New( face, sideEdges, aMesh,
+ /*isFwd=*/true, /*skipMedium=*/ true );
+ sides.push_back( side );
+ }
+
+ if ( !aMesh ) // call from IsApplicable()
+ return sides.size();
+
+ if ( sides.size() > 3 )
+ return sides.size();
+
+ if ( nbWire == 2 && (( sides.size() != 2 ) ||
+ ( sides[0]->IsClosed() && sides[1]->IsClosed() ) ||
+ ( !sides[0]->IsClosed() && !sides[1]->IsClosed() )))
+ return -1;
+
+ // detect an elliptic side
+
+ if ( sides.size() == 1 )
+ {
+ aCircSide = sides[0];
+ return sides.size();
+ }
+
+ // sort sides by deviation from a straight line
+ multimap< double, int > deviation2sideInd;
+ const double nbSamples = 7;
+ for ( size_t iS = 0; iS < sides.size(); ++iS )
+ {
+ gp_Pnt pf = BRep_Tool::Pnt( sides[iS]->FirstVertex() );
+ gp_Pnt pl = BRep_Tool::Pnt( sides[iS]->LastVertex() );
+ gp_Vec v1( pf, pl );
+ double v1Len = v1.Magnitude();
+ if ( v1Len < std::numeric_limits< double >::min() )
+ {
+ deviation2sideInd.insert( make_pair( sides[iS]->Length(), iS )); // the side seems closed
+ continue;
+ }
+ double devia = 0;
+ for ( int i = 0; i < nbSamples; ++i )
+ {
+ gp_Pnt pi( sides[iS]->Value3d(( i + 1 ) / nbSamples ));
+ gp_Vec vi( pf, pi );
+ double h = 0.5 * v1.Crossed( vi ).Magnitude() / v1Len;
+ devia = Max( devia, h );
+ }
+ deviation2sideInd.insert( make_pair( devia, iS ));
+ }
+
+ int iCirc = deviation2sideInd.rbegin()->second;
+ aCircSide = sides[ iCirc ];
+ aLinSide1 = sides[( iCirc + 1 ) % sides.size() ];
+ if ( sides.size() > 2 )
+ {
+ aLinSide2 = sides[( iCirc + 2 ) % sides.size() ];
+ aLinSide2->Reverse(); // to be "parallel" to aLinSide1
+ }
+
+ if (( nbWire == 2 && aLinSide1 ) &&
+ ( aLinSide1->Edge(0).Orientation() == TopAbs_INTERNAL ) &&
+ ( aCircSide->IsClosed() ))
+ {
+ // assure that aCircSide starts at aLinSide1
+ TopoDS_Vertex v0 = aLinSide1->FirstVertex();
+ TopoDS_Vertex v1 = aLinSide1->LastVertex();
+ if ( ! aCircSide->FirstVertex().IsSame( v0 ) &&
+ ! aCircSide->FirstVertex().IsSame( v1 ))
+ {
+ int iE = 0;
+ for ( ; iE < aCircSide->NbEdges(); ++iE )
+ if ( aCircSide->FirstVertex(iE).IsSame( v0 ) ||
+ aCircSide->FirstVertex(iE).IsSame( v1 ))
+ break;
+ if ( iE == aCircSide->NbEdges() )
+ return -2;
+
+ edges.clear();
+ for ( int i = 0; i < aCircSide->NbEdges(); ++i, ++iE )
+ edges.push_back( aCircSide->Edge( iE % aCircSide->NbEdges() ));
+
+ aCircSide = StdMeshers_FaceSide::New( face, edges, aMesh,
+ /*isFwd=*/true, /*skipMedium=*/ true );
}
}
- return C;
+
+ return sides.size();
}
//================================================================================
/*!
- * \brief Return edges of the face
- * \retval int - nb of edges
+ * \brief Checks if the common vertex between LinSide's lies inside the circle
+ * and not outside
+ * \return bool - false if there are 3 EDGEs and the corner is outside
*/
//================================================================================
- int analyseFace(const TopoDS_Shape& face,
- TopoDS_Edge& CircEdge,
- TopoDS_Edge& LinEdge1,
- TopoDS_Edge& LinEdge2)
+ bool isCornerInsideCircle(const StdMeshers_FaceSidePtr& CircSide,
+ const StdMeshers_FaceSidePtr& LinSide1,
+ const StdMeshers_FaceSidePtr& LinSide2)
+ {
+ // if ( CircSide && LinSide1 && LinSide2 )
+ // {
+ // Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircSide ));
+ // TopoDS_Vertex aCommonV;
+ // if ( !aCirc.IsNull() &&
+ // TopExp::CommonVertex( LinSide1, LinSide2, aCommonV ))
+ // {
+ // gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
+ // gp_Pnt aCenter = aCirc->Location();
+ // double dist = aCenter.Distance( aCommonP );
+ // return dist < 0.1 * aCirc->Radius();
+ // }
+ // }
+ return true;
+ }
+
+ //================================================================================
+ /*!
+ * \brief Create an EDGE connecting the ellipse center with the most distant point
+ * of the ellipse.
+ * \param [in] circSide - the elliptic side
+ * \param [in] face - the FACE
+ * \param [out] circNode - a node on circSide most distant from the center
+ * \return TopoDS_Edge - the create EDGE
+ */
+ //================================================================================
+
+ TopoDS_Edge makeEdgeToCenter( StdMeshers_FaceSidePtr& circSide,
+ const TopoDS_Face& face,
+ const SMDS_MeshNode*& circNode)
{
- CircEdge.Nullify(); LinEdge1.Nullify(); LinEdge2.Nullify();
- int nbe = 0;
+ // find the center and a point most distant from it
+
+ double maxDist = 0, normPar;
+ gp_XY uv1, uv2;
+ for ( int i = 0; i < 32; ++i )
+ {
+ double u = 0.5 * i / 32.;
+ gp_Pnt2d p1 = circSide->Value2d( u );
+ gp_Pnt2d p2 = circSide->Value2d( u + 0.5 );
+ double dist = p1.SquareDistance( p2 );
+ if ( dist > maxDist )
+ {
+ maxDist = dist;
+ uv1 = p1.XY();
+ uv2 = p2.XY();
+ normPar = u;
+ }
+ }
+ gp_XY center = 0.5 * ( uv1 + uv2 );
+ double len = 0.5 * Sqrt( maxDist );
+ bool isCirc = ( Abs( len - circSide->Value2d( 0 ).Distance( center )) < 1e-3 * len );
+
+ // find a node closest to the most distant point
- for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next(), ++nbe )
+ size_t iDist = 0;
+ const UVPtStructVec& circNodes = circSide->GetUVPtStruct();
+ if ( !isCirc )
{
- const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
- double f,l;
- Handle(Geom_Curve) C = getCurve(E,&f,&l);
- if ( !C.IsNull() )
+ double minDist = 1e100;
+ for ( size_t i = 0; i <= circNodes.size(); ++i )
{
- if ( C->IsKind( STANDARD_TYPE(Geom_Circle)))
+ double dist = Abs( circNodes[i].normParam - normPar );
+ if ( dist < minDist )
{
- if ( CircEdge.IsNull() )
- CircEdge = E;
- else
- return 0;
+ iDist = i;
+ minDist = dist;
}
- else if ( LinEdge1.IsNull() )
- LinEdge1 = E;
- else
- LinEdge2 = E;
}
}
- return nbe;
+ circNode = circNodes[iDist].node;
+ uv1 = circNodes[iDist].UV();
+ len = ( uv1 - center ).Modulus();
+
+ // make the EDGE between the most distant point and the center
+
+ Handle(Geom2d_Line) line = new Geom2d_Line( uv1, gp_Dir2d( center - uv1 ) );
+ Handle(Geom2d_Curve) pcu = new Geom2d_TrimmedCurve( line, 0, len );
+
+ Handle(Geom_Surface) surface = BRep_Tool::Surface( face );
+ TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pcu, surface, 0, len );
+
+ BRep_Builder().UpdateEdge( edge, pcu, face, 1e-7 );
+ ShapeFix_Edge().FixAddCurve3d( edge );
+
+
+ // assure that circSide starts at circNode
+ if ( iDist != 0 && iDist != circNodes.size()-1 )
+ {
+ // create a new circSide
+ UVPtStructVec nodesNew;
+ nodesNew.reserve( circNodes.size() );
+ nodesNew.insert( nodesNew.end(), circNodes.begin() + iDist, circNodes.end() );
+ nodesNew.insert( nodesNew.end(), circNodes.begin() + 1, circNodes.begin() + iDist + 1 );
+ circSide = StdMeshers_FaceSide::New( nodesNew );
+ }
+
+ return edge;
}
+
//================================================================================
/*!
- * \brief Checks if the common vertex between LinEdge's lies inside the circle
- * and not outside
- * \param [in] CircEdge -
- * \param [in] LinEdge1 -
- * \param [in] LinEdge2 -
- * \return bool - false if there are 3 EDGEs and the corner is outside
+ * \brief Set nodes existing on a linSide to UVPtStructVec and create missing nodes
+ * corresponding to layerPositions
*/
//================================================================================
- bool isCornerInsideCircle(const TopoDS_Edge& CircEdge,
- const TopoDS_Edge& LinEdge1,
- const TopoDS_Edge& LinEdge2)
+ void makeMissingMesh( StdMeshers_FaceSidePtr& linSide,
+ UVPtStructVec& nodes,
+ const vector< double >& layerPositions,
+ SMESH_MesherHelper* helper )
{
- if ( !CircEdge.IsNull() &&
- !LinEdge1.IsNull() &&
- !LinEdge2.IsNull() )
+ // tolerance to compare normParam
+ double tol = 1e100;
+ for ( size_t i = 1; i < layerPositions.size(); ++i )
+ tol = Min( tol, layerPositions[i] - layerPositions[i-1] );
+ tol *= 0.05;
+
+ // merge existing nodes with layerPositions into UVPtStructVec
+ // ------------------------------------------------------------
+
+ const UVPtStructVec& exiNodes = linSide->GetUVPtStruct();
+ nodes.clear();
+ nodes.reserve( layerPositions.size() + exiNodes.size() );
+ vector< double >::const_iterator pos = layerPositions.begin(), posEnd = layerPositions.end();
+ for ( size_t i = 0; i < exiNodes.size(); ++i )
{
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
- TopoDS_Vertex aCommonV;
- if ( !aCirc.IsNull() &&
- TopExp::CommonVertex( LinEdge1, LinEdge2, aCommonV ))
+ switch ( exiNodes[i].node->GetPosition()->GetTypeOfPosition() )
+ {
+ case SMDS_TOP_VERTEX:
+ {
+ // allocate UVPtStruct's for non-existing nodes
+ while ( pos != posEnd && *pos < exiNodes[i].normParam - tol )
+ {
+ UVPtStruct uvPS;
+ uvPS.normParam = *pos++;
+ nodes.push_back( uvPS );
+ }
+ // save existing node on a VERTEX
+ nodes.push_back( exiNodes[i] );
+ break;
+ }
+ case SMDS_TOP_EDGE:
+ {
+ // save existing nodes on an EDGE
+ while ( i < exiNodes.size() && exiNodes[i].node->GetPosition()->GetDim() == 1 )
+ {
+ nodes.push_back( exiNodes[i++] );
+ }
+ // save existing node on a VERTEX
+ if ( i < exiNodes.size() && exiNodes[i].node->GetPosition()->GetDim() == 0 )
+ {
+ nodes.push_back( exiNodes[i] );
+ }
+ break;
+ }
+ default:;
+ }
+
+ // skip layer positions covered by saved nodes
+ while ( pos != posEnd && *pos < nodes.back().normParam + tol )
{
- gp_Pnt aCommonP = BRep_Tool::Pnt( aCommonV );
- gp_Pnt aCenter = aCirc->Location();
- double dist = aCenter.Distance( aCommonP );
- return dist < 0.1 * aCirc->Radius();
+ ++pos;
}
}
- return true;
- }
+ // allocate UVPtStruct's for the rest non-existing nodes
+ while ( pos != posEnd )
+ {
+ UVPtStruct uvPS;
+ uvPS.normParam = *pos++;
+ nodes.push_back( uvPS );
+ }
+
+ // create missing nodes
+ // ---------------------
+
+ SMESHDS_Mesh * meshDS = helper->GetMeshDS();
+ const TopoDS_Face& F = TopoDS::Face( helper->GetSubShape() );
+ Handle(ShapeAnalysis_Surface) surface = helper->GetSurface( F );
+
+ helper->SetElementsOnShape( false ); // we create nodes on EDGEs, not on the FACE
+
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ {
+ if ( nodes[ i ].node ) continue;
+
+ gp_Pnt2d uv = linSide->Value2d( nodes[i].normParam );
+ gp_Pnt xyz = surface->Value( uv.X(), uv.Y() );
+
+ nodes[ i ].SetUV( uv.XY() );
+ nodes[ i ].node = helper->AddNode( xyz.X(), xyz.Y(), xyz.Z() );
+ }
+
+ // set nodes on VERTEXes
+ for ( int iE = 0; iE < linSide->NbEdges(); ++iE )
+ {
+ TopoDS_Vertex v = linSide->LastVertex( iE );
+ if ( SMESH_Algo::VertexNode( v, meshDS ))
+ continue;
+
+ double normPar = linSide->LastParameter( iE );
+ size_t i = 0;
+ while ( nodes[ i ].normParam < normPar )
+ ++i;
+ if (( nodes[ i ].normParam - normPar ) > ( normPar - nodes[ i-1 ].normParam ))
+ --i;
+ meshDS->SetNodeOnVertex( nodes[ i ].node, v );
+ }
+
+ // set nodes on EDGEs
+ int edgeID;
+ for ( size_t i = 0; i < nodes.size(); ++i )
+ {
+ if ( nodes[ i ].node->getshapeId() > 0 ) continue;
+
+ double u = linSide->Parameter( nodes[i].normParam, edgeID );
+ meshDS->SetNodeOnEdge( nodes[ i ].node, edgeID, u );
+ }
+
+ // create segments
+ for ( size_t i = 1; i < nodes.size(); ++i )
+ {
+ if ( meshDS->FindEdge( nodes[i].node, nodes[i-1].node )) continue;
+
+ const SMDS_MeshElement* seg = helper->AddEdge( nodes[i].node, nodes[i-1].node );
+
+ double normParam = 0.5 * ( nodes[i].normParam + nodes[i-1].normParam );
+ edgeID = linSide->EdgeID( linSide->EdgeIndex( normParam ));
+ meshDS->SetMeshElementOnShape( seg, edgeID );
+ }
+
+ helper->SetElementsOnShape( true );
+
+ } // end makeMissingMesh()
//================================================================================
//================================================================================
// -----------------------------------------------------------------------------
//! Computes distribution of nodes on a straight line ending at pIn and pOut
bool Compute( vector< double > & positions,
- gp_Pnt pIn,
- gp_Pnt pOut,
- SMESH_Mesh& aMesh,
+ const TopoDS_Edge& edge,
+ Adaptor3d_Curve& curve,
+ double f,
+ double l,
+ SMESH_Mesh& mesh,
const SMESH_Hypothesis* hyp1d)
{
if ( !hyp1d ) return error( "Invalid LayerDistribution hypothesis");
- double len = pIn.Distance( pOut );
- if ( len <= DBL_MIN ) return error("Too close points of inner and outer shells");
-
myUsedHyps.clear();
myUsedHyps.push_back( hyp1d );
- TopoDS_Edge edge = BRepBuilderAPI_MakeEdge( pIn, pOut );
SMESH_Hypothesis::Hypothesis_Status aStatus;
- if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
+ if ( !StdMeshers_Regular_1D::CheckHypothesis( mesh, edge, aStatus ))
return error( "StdMeshers_Regular_1D::CheckHypothesis() failed "
"with LayerDistribution hypothesis");
- BRepAdaptor_Curve C3D(edge);
- double f = C3D.FirstParameter(), l = C3D.LastParameter();
+ double len = GCPnts_AbscissaPoint::Length( curve, f, l );
+
list< double > params;
- if ( !StdMeshers_Regular_1D::computeInternalParameters( aMesh, C3D, len, f, l, params, false ))
+ if ( !StdMeshers_Regular_1D::computeInternalParameters( mesh, curve, len, f, l, params, false ))
return error("StdMeshers_Regular_1D failed to compute layers distribution");
+ params.push_front( f );
+ params.push_back ( l );
positions.clear();
positions.reserve( params.size() );
for (list<double>::iterator itU = params.begin(); itU != params.end(); itU++)
- positions.push_back( *itU / len );
+ positions.push_back(( *itU - f ) / ( l - f ));
return true;
}
// -----------------------------------------------------------------------------
//! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
- bool ComputeCircularEdge(SMESH_Mesh& aMesh,
- const TopoDS_Edge& anEdge)
+ bool ComputeCircularEdge( SMESH_Mesh& aMesh,
+ const StdMeshers_FaceSidePtr& aSide )
+ {
+ bool ok = true;
+ for ( int i = 0; i < aSide->NbEdges(); ++i )
+ {
+ const TopoDS_Edge& edge = aSide->Edge( i );
+ _gen->Compute( aMesh, edge );
+ SMESH_subMesh *sm = aMesh.GetSubMesh( edge );
+ if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK)
+ {
+ // find any 1d hyp assigned (there can be a hyp w/o algo)
+ myUsedHyps = SMESH_Algo::GetUsedHypothesis( aMesh, edge, /*ignoreAux=*/true );
+ Hypothesis_Status aStatus;
+ if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, edge, aStatus ))
+ {
+ // no valid 1d hyp assigned, use default nb of segments
+ _hypType = NB_SEGMENTS;
+ _ivalue[ DISTR_TYPE_IND ] = StdMeshers_NumberOfSegments::DT_Regular;
+ _ivalue[ NB_SEGMENTS_IND ] = _gen->GetDefaultNbSegments();
+ }
+ ok &= StdMeshers_Regular_1D::Compute( aMesh, edge );
+ }
+ }
+ return ok;
+ }
+ // -----------------------------------------------------------------------------
+ //! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
+ bool EvaluateCircularEdge(SMESH_Mesh& aMesh,
+ const StdMeshers_FaceSidePtr aSide,
+ MapShapeNbElems& aResMap)
{
- _gen->Compute( aMesh, anEdge);
- SMESH_subMesh *sm = aMesh.GetSubMesh(anEdge);
- if ( sm->GetComputeState() != SMESH_subMesh::COMPUTE_OK)
+ bool ok = true;
+ for ( int i = 0; i < aSide->NbEdges(); ++i )
{
- // find any 1d hyp assigned (there can be a hyp w/o algo)
+ const TopoDS_Edge& anEdge = aSide->Edge( i );
+ _gen->Evaluate( aMesh, anEdge, aResMap );
+ if ( aResMap.count( aMesh.GetSubMesh( anEdge )))
+ continue;
+
+ // find any 1d hyp assigned
myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
Hypothesis_Status aStatus;
if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
_ivalue[ DISTR_TYPE_IND ] = StdMeshers_NumberOfSegments::DT_Regular;
_ivalue[ NB_SEGMENTS_IND ] = _gen->GetDefaultNbSegments();
}
- return StdMeshers_Regular_1D::Compute( aMesh, anEdge );
- }
- return true;
- }
- // -----------------------------------------------------------------------------
- //! Make mesh on an adge using assigned 1d hyp or defaut nb of segments
- bool EvaluateCircularEdge(SMESH_Mesh& aMesh,
- const TopoDS_Edge& anEdge,
- MapShapeNbElems& aResMap)
- {
- _gen->Evaluate( aMesh, anEdge, aResMap );
- if ( aResMap.count( aMesh.GetSubMesh( anEdge )))
- return true;
-
- // find any 1d hyp assigned
- myUsedHyps = SMESH_Algo::GetUsedHypothesis(aMesh, anEdge, /*ignoreAux=*/true);
- Hypothesis_Status aStatus;
- if ( !StdMeshers_Regular_1D::CheckHypothesis( aMesh, anEdge, aStatus ))
- {
- // no valid 1d hyp assigned, use default nb of segments
- _hypType = NB_SEGMENTS;
- _ivalue[ DISTR_TYPE_IND ] = StdMeshers_NumberOfSegments::DT_Regular;
- _ivalue[ NB_SEGMENTS_IND ] = _gen->GetDefaultNbSegments();
+ ok &= StdMeshers_Regular_1D::Evaluate( aMesh, anEdge, aResMap );
}
- return StdMeshers_Regular_1D::Evaluate( aMesh, anEdge, aResMap );
+ return ok;
}
protected:
// -----------------------------------------------------------------------------
{
if ( !faceSubMesh->IsEmpty() )
{
- TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
- analyseFace( faceSubMesh->GetSubShape(), CircEdge, LinEdge1, LinEdge2 );
- if ( !CircEdge.IsNull() ) markEdgeAsComputedByMe( CircEdge, faceSubMesh );
- if ( !LinEdge1.IsNull() ) markEdgeAsComputedByMe( LinEdge1, faceSubMesh );
- if ( !LinEdge2.IsNull() ) markEdgeAsComputedByMe( LinEdge2, faceSubMesh );
+ for ( TopExp_Explorer e( faceSubMesh->GetSubShape(), TopAbs_EDGE ); e.More(); e.Next() )
+ {
+ markEdgeAsComputedByMe( TopoDS::Edge( e.Current() ), faceSubMesh );
+ }
}
}
bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape)
{
- SMESHDS_Mesh * meshDS = aMesh.GetMeshDS();
-
- myHelper = new SMESH_MesherHelper( aMesh );
- // to delete helper at exit from Compute()
- SMESHUtils::Deleter<SMESH_MesherHelper> helperDeleter( myHelper );
+ SMESH_MesherHelper helper( aMesh );
+ StdMeshers_Quadrangle_2D::myHelper = & helper;
+ StdMeshers_Quadrangle_2D::myNeedSmooth = false;
+ StdMeshers_Quadrangle_2D::myCheckOri = false;
+ StdMeshers_Quadrangle_2D::myQuadList.clear();
+
+ StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+ int nbSides = analyseFace( aShape, &aMesh, circSide, linSide1, linSide2 );
+ if( nbSides > 3 || nbSides < 1 )
+ return error("The face must be a full ellipse or a part of ellipse (i.e. the number "
+ "of edges is less or equal to 3 and one of them is an ellipse curve)");
+
+ // get not yet computed EDGEs
+ list< TopoDS_Edge > emptyEdges;
+ for ( TopExp_Explorer e( aShape, TopAbs_EDGE ); e.More(); e.Next() )
+ {
+ if ( aMesh.GetSubMesh( e.Current() )->IsEmpty() )
+ emptyEdges.push_back( TopoDS::Edge( e.Current() ));
+ }
TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
- TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
- int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
- if( nbe > 3 || nbe < 1 || aCirc.IsNull() )
- return error("The face must be a full circle or a part of circle (i.e. the number "
- "of edges is less or equal to 3 and one of them is a circle curve)");
-
- gp_Pnt P0, P1;
- // points for rotation
- TColgp_SequenceOfPnt Points;
- // angles for rotation
- TColStd_SequenceOfReal Angles;
- // Nodes1 and Nodes2 - nodes along radiuses
- // CNodes - nodes on circle edge
- vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes;
- SMDS_MeshNode * NC;
- // parameters edge nodes on face
- TColgp_SequenceOfPnt2d Pnts2d1;
- gp_Pnt2d PC;
-
- int faceID = meshDS->ShapeToIndex(aShape);
+ if ( !algo1d->ComputeCircularEdge( aMesh, circSide ))
+ return error( algo1d->GetComputeError() );
+
+
TopoDS_Face F = TopoDS::Face(aShape);
Handle(Geom_Surface) S = BRep_Tool::Surface(F);
+ myHelper->IsQuadraticSubMesh( aShape );
+ myHelper->SetElementsOnShape( true );
+
+ vector< double > layerPositions; // [0,1]
+
+ const SMDS_MeshNode* centerNode = 0;
+ gp_Pnt2d centerUV(0,0);
- if(nbe==1)
+ // ------------------------------------------------------------------------------------------
+ if ( nbSides == 1 ) // full ellipse
{
- if (!algo1d->ComputeCircularEdge( aMesh, CircEdge ))
- return error( algo1d->GetComputeError() );
- map< double, const SMDS_MeshNode* > theNodes;
- if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes))
- return error("Circular edge is incorrectly meshed");
-
- myHelper->IsQuadraticSubMesh( aShape );
-
- CNodes.clear();
- map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
- const SMDS_MeshNode* NF = (*itn).second;
- CNodes.push_back( (*itn).second );
- double fang = (*itn).first;
- if ( itn != theNodes.end() ) {
- itn++;
- for(; itn != theNodes.end(); itn++ ) {
- CNodes.push_back( (*itn).second );
- double ang = (*itn).first - fang;
- if( ang>M_PI ) ang = ang - 2.*M_PI;
- if( ang<-M_PI ) ang = ang + 2.*M_PI;
- Angles.Append( ang );
- }
- }
- P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
- P0 = aCirc->Location();
+ const SMDS_MeshNode* circNode;
+ TopoDS_Edge linEdge = makeEdgeToCenter( circSide, F, circNode );
- if ( !computeLayerPositions(P0,P1))
- return false;
+ StdMeshers_FaceSidePtr tmpSide =
+ StdMeshers_FaceSide::New( F, linEdge, &aMesh, /*isFrw=*/true, /*skipMedium=*/true );
- TopoDS_Vertex V1 = myHelper->IthVertex(0, CircEdge );
- gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) );
+ if ( !computeLayerPositions( tmpSide, layerPositions ))
+ return false;
- NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
- GeomAPI_ProjectPointOnSurf PPS(P0,S);
- double U0,V0;
- PPS.Parameters(1,U0,V0);
- meshDS->SetNodeOnFace(NC, faceID, U0, V0);
- PC = gp_Pnt2d(U0,V0);
+ UVPtStructVec nodes( layerPositions.size() );
+ nodes[0].node = circNode;
+ for ( size_t i = 0; i < layerPositions.size(); ++i )
+ {
+ gp_Pnt2d uv = tmpSide->Value2d( layerPositions[i] );
+ gp_Pnt xyz = S->Value( uv.X(), uv.Y() );
- gp_Vec aVec(P0,P1);
- gp_Vec2d aVec2d(PC,p2dV);
- Nodes1.resize( myLayerPositions.size()+1 );
- Nodes2.resize( myLayerPositions.size()+1 );
- size_t i = 0;
- for ( ; i < myLayerPositions.size(); i++ ) {
- gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
- P0.Y() + aVec.Y()*myLayerPositions[i],
- P0.Z() + aVec.Z()*myLayerPositions[i] );
- Points.Append(P);
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- Nodes1[i] = node;
- Nodes2[i] = node;
- double U = PC.X() + aVec2d.X()*myLayerPositions[i];
- double V = PC.Y() + aVec2d.Y()*myLayerPositions[i];
- meshDS->SetNodeOnFace( node, faceID, U, V );
- Pnts2d1.Append(gp_Pnt2d(U,V));
+ nodes[ i ].SetUV( uv.XY() );
+ nodes[ i ].normParam = layerPositions[i];
+ if ( i )
+ nodes[ i ].node = myHelper->AddNode( xyz.X(), xyz.Y(), xyz.Z(), 0, uv.X(), uv.Y() );
}
- Nodes1[Nodes1.size()-1] = NF;
- Nodes2[Nodes1.size()-1] = NF;
+
+ linSide1 = StdMeshers_FaceSide::New( nodes );
+ linSide2 = StdMeshers_FaceSide::New( nodes );
+
+ centerNode = nodes.back().node;
+ centerUV = nodes.back().UV();
}
- else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL )
+ // ------------------------------------------------------------------------------------------
+ else if ( nbSides == 2 && linSide1->Edge(0).Orientation() == TopAbs_INTERNAL )
{
- // one curve must be a half of circle and other curve must be
- // a segment of line
- double fp, lp;
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
- if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) {
- // not half of circle
- return error(COMPERR_BAD_SHAPE);
- }
- Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
- if( aLine.IsNull() ) {
- // other curve not line
- return error(COMPERR_BAD_SHAPE);
- }
+ // full ellipse with an internal radial side
- if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
- return error( algo1d->GetComputeError() );
- map< double, const SMDS_MeshNode* > theNodes;
- if ( !GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes) )
- return error("Circular edge is incorrectly meshed");
-
- myHelper->IsQuadraticSubMesh( aShape );
-
- map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
- CNodes.clear();
- CNodes.push_back( itn->second );
- double fang = (*itn).first;
- itn++;
- for(; itn != theNodes.end(); itn++ ) {
- CNodes.push_back( (*itn).second );
- double ang = (*itn).first - fang;
- if( ang>M_PI ) ang = ang - 2.*M_PI;
- if( ang<-M_PI ) ang = ang + 2.*M_PI;
- Angles.Append( ang );
+ // eliminate INTERNAL orientation
+ list< TopoDS_Edge > edges;
+ for ( int iE = 0; iE < linSide1->NbEdges(); ++iE )
+ {
+ edges.push_back( linSide1->Edge( iE ));
+ edges.back().Orientation( TopAbs_FORWARD );
}
- const SMDS_MeshNode* NF = theNodes.begin()->second;
- const SMDS_MeshNode* NL = theNodes.rbegin()->second;
- P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
- gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
- P0 = aCirc->Location();
-
- bool linEdgeComputed;
- if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdgeComputed))
+
+ // orient the internal side
+ bool isVIn0Shared = false;
+ TopoDS_Vertex vIn0 = myHelper->IthVertex( 0, edges.front() );
+ for ( int iE = 0; iE < circSide->NbEdges() && !isVIn0Shared; ++iE )
+ isVIn0Shared = vIn0.IsSame( circSide->FirstVertex( iE ));
+
+ linSide1 = StdMeshers_FaceSide::New( F, edges, &aMesh,
+ /*isFrw=*/isVIn0Shared, /*skipMedium=*/true );
+
+ int nbMeshedEdges;
+ if ( !computeLayerPositions( linSide1, layerPositions, &nbMeshedEdges ))
return false;
- if ( linEdgeComputed )
- {
- if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
- return error("Invalid mesh on a straight edge");
-
- Nodes1.resize( myLayerPositions.size()+1 );
- Nodes2.resize( myLayerPositions.size()+1 );
- vector< const SMDS_MeshNode* > *pNodes1 = &Nodes1, *pNodes2 = &Nodes2;
- bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
- if ( !nodesFromP0ToP1 ) std::swap( pNodes1, pNodes2 );
-
- map< double, const SMDS_MeshNode* >::reverse_iterator ritn = theNodes.rbegin();
- itn = theNodes.begin();
- for ( int i = Nodes1.size()-1; i > -1; ++itn, ++ritn, --i )
- {
- (*pNodes1)[i] = ritn->second;
- (*pNodes2)[i] = itn->second;
- Points.Prepend( gpXYZ( Nodes1[i]));
- Pnts2d1.Prepend( myHelper->GetNodeUV( F, Nodes1[i]));
- }
- NC = const_cast<SMDS_MeshNode*>( itn->second );
- Points.Remove( Nodes1.size() );
- }
+ // merge existing nodes with new nodes at layerPositions into a UVPtStructVec
+ UVPtStructVec nodes;
+ if ( nbMeshedEdges != linSide1->NbEdges() )
+ makeMissingMesh( linSide1, nodes, layerPositions, myHelper );
else
+ nodes = linSide1->GetUVPtStruct();
+
+ linSide1 = StdMeshers_FaceSide::New( nodes );
+ linSide2 = StdMeshers_FaceSide::New( nodes );
+
+ centerNode = nodes.back().node;
+ centerUV = nodes.back().UV();
+ }
+ // ------------------------------------------------------------------------------------------
+ else if ( nbSides == 2 )
+ {
+ // find positions of layers for the first half of linSide1
+ int nbMeshedEdges;
+ if ( !computeLayerPositions( linSide1, layerPositions, &nbMeshedEdges, /*useHalf=*/true ))
+ return false;
+
+ // make positions for the whole linSide1
+ for ( size_t i = 0; i < layerPositions.size(); ++i )
{
- gp_Vec aVec(P0,P1);
- int edgeID = meshDS->ShapeToIndex(LinEdge1);
- // check orientation
- Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
- gp_Pnt Ptmp;
- Crv->D0(fp,Ptmp);
- bool ori = true;
- if( P1.Distance(Ptmp) > Precision::Confusion() )
- ori = false;
- // get UV points for edge
- gp_Pnt2d PF,PL;
- BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
- PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 );
- gp_Vec2d V2d;
- if(ori) V2d = gp_Vec2d(PC,PF);
- else V2d = gp_Vec2d(PC,PL);
- // add nodes on edge
- double cp = (fp+lp)/2;
- double dp2 = (lp-fp)/2;
- NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
- meshDS->SetNodeOnEdge(NC, edgeID, cp);
- Nodes1.resize( myLayerPositions.size()+1 );
- Nodes2.resize( myLayerPositions.size()+1 );
- size_t i = 0;
- for(; i<myLayerPositions.size(); i++) {
- gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
- P0.Y() + aVec.Y()*myLayerPositions[i],
- P0.Z() + aVec.Z()*myLayerPositions[i] );
- Points.Append(P);
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- Nodes1[i] = node;
- double param;
- if(ori)
- param = fp + dp2*(1-myLayerPositions[i]);
- else
- param = cp + dp2*myLayerPositions[i];
- meshDS->SetNodeOnEdge(node, edgeID, param);
- P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i],
- P0.Y() - aVec.Y()*myLayerPositions[i],
- P0.Z() - aVec.Z()*myLayerPositions[i] );
- node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- Nodes2[i] = node;
- if(!ori)
- param = fp + dp2*(1-myLayerPositions[i]);
- else
- param = cp + dp2*myLayerPositions[i];
- meshDS->SetNodeOnEdge(node, edgeID, param);
- // parameters on face
- gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
- PC.Y() + V2d.Y()*myLayerPositions[i] );
- Pnts2d1.Append(P2d);
- }
- Nodes1[ myLayerPositions.size() ] = NF;
- Nodes2[ myLayerPositions.size() ] = NL;
- // create 1D elements on edge
- vector< const SMDS_MeshNode* > tmpNodes;
- tmpNodes.resize(2*Nodes1.size()+1);
- for(i=0; i<Nodes2.size(); i++)
- tmpNodes[Nodes2.size()-i-1] = Nodes2[i];
- tmpNodes[Nodes2.size()] = NC;
- for(i=0; i<Nodes1.size(); i++)
- tmpNodes[Nodes2.size()+1+i] = Nodes1[i];
- for(i=1; i<tmpNodes.size(); i++) {
- SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] );
- if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
- }
- markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
+ layerPositions[i] *= 0.5;
}
+ layerPositions.reserve( layerPositions.size() * 2 );
+ for ( int nb = layerPositions.size()-1; nb > 0; --nb )
+ layerPositions.push_back( layerPositions.back() + layerPositions[nb] - layerPositions[nb-1] );
+
+ // merge existing nodes with new nodes at layerPositions into a UVPtStructVec
+ UVPtStructVec nodes;
+ if ( nbMeshedEdges != linSide1->NbEdges() )
+ makeMissingMesh( linSide1, nodes, layerPositions, myHelper );
+ else
+ nodes = linSide1->GetUVPtStruct();
+
+ // find a central node
+ size_t i = 0;
+ while ( nodes[ i ].normParam < 0.5 ) ++i;
+ if (( nodes[ i ].normParam - 0.5 ) > ( 0.5 - nodes[ i-1 ].normParam )) --i;
+
+ // distribute nodes between two linear sides
+ UVPtStructVec nodes2( nodes.rbegin(), nodes.rbegin() + nodes.size() - i );
+ nodes.resize( i + 1 );
+
+ linSide1 = StdMeshers_FaceSide::New( nodes );
+ linSide2 = StdMeshers_FaceSide::New( nodes2 );
+
+ centerNode = nodes.back().node;
+ centerUV = nodes.back().UV();
}
- else // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
+ // ------------------------------------------------------------------------------------------
+ else // nbSides == 3
{
- if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
- LinEdge2 = LinEdge1;
-
- // one curve must be a part of circle and other curves must be
- // segments of line
- double fp, lp;
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
- Handle(Geom_Line) aLine1 = Handle(Geom_Line )::DownCast( getCurve( LinEdge1 ));
- Handle(Geom_Line) aLine2 = Handle(Geom_Line )::DownCast( getCurve( LinEdge2 ));
- if ( aCirc.IsNull() || aLine1.IsNull() || aLine2.IsNull() )
- return error(COMPERR_BAD_SHAPE);
- if ( !isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ))
- return error(COMPERR_BAD_SHAPE);
-
- if ( !algo1d->ComputeCircularEdge( aMesh, CircEdge ))
- return error( algo1d->GetComputeError() );
- map< double, const SMDS_MeshNode* > theNodes;
- if ( !GetSortedNodesOnEdge( aMesh.GetMeshDS(), CircEdge, true, theNodes ))
- return error("Circular edge is incorrectly meshed");
-
- myHelper->IsQuadraticSubMesh( aShape );
-
- const SMDS_MeshNode* NF = theNodes.begin()->second;
- const SMDS_MeshNode* NL = theNodes.rbegin()->second;
- CNodes.clear();
- CNodes.push_back( NF );
- map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin();
- double fang = (*itn).first;
- itn++;
- for(; itn != theNodes.end(); itn++ ) {
- CNodes.push_back( (*itn).second );
- double ang = (*itn).first - fang;
- if( ang>M_PI ) ang = ang - 2.*M_PI;
- if( ang<-M_PI ) ang = ang + 2.*M_PI;
- Angles.Append( ang );
- }
- P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() );
- gp_Pnt P2( NL->X(), NL->Y(), NL->Z() );
- P0 = aCirc->Location();
-
- // make P1 belong to LinEdge1
- TopoDS_Vertex V1 = myHelper->IthVertex( 0, LinEdge1 );
- TopoDS_Vertex V2 = myHelper->IthVertex( 1, LinEdge1 );
- gp_Pnt PE1 = BRep_Tool::Pnt(V1);
- gp_Pnt PE2 = BRep_Tool::Pnt(V2);
- if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
- ( P1.Distance(PE2) > Precision::Confusion() ) )
- std::swap( LinEdge1, LinEdge2 );
-
- bool linEdge1Computed, linEdge2Computed;
- if ( !computeLayerPositions(P0,P1,LinEdge1,&linEdge1Computed))
- return false;
+ // one curve must be a part of ellipse and 2 other curves must be segments of line
- Nodes1.resize( myLayerPositions.size()+1 );
- Nodes2.resize( myLayerPositions.size()+1 );
+ int nbMeshedEdges1, nbMeshedEdges2;
+ vector< double > layerPositions2;
+ bool ok1 = computeLayerPositions( linSide1, layerPositions, &nbMeshedEdges1 );
+ bool ok2 = computeLayerPositions( linSide2, layerPositions2, &nbMeshedEdges2 );
+ if ( !ok1 && !ok2 )
+ return false;
- // check that both linear edges have same hypotheses
- if ( !computeLayerPositions(P0,P2,LinEdge2, &linEdge2Computed))
- return false;
- if ( Nodes1.size() != myLayerPositions.size()+1 )
- return error("Different hypotheses apply to radial edges");
+ bool linSide1Computed = ( nbMeshedEdges1 == linSide1->NbEdges() );
+ bool linSide2Computed = ( nbMeshedEdges2 == linSide2->NbEdges() );
- // find the central vertex
- TopoDS_Vertex VC = V2;
- if( ( P1.Distance(PE1) > Precision::Confusion() ) &&
- ( P2.Distance(PE1) > Precision::Confusion() ) )
- VC = V1;
- int vertID = meshDS->ShapeToIndex(VC);
+ UVPtStructVec nodes;
- // LinEdge1
- if ( linEdge1Computed )
- {
- if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes))
- return error("Invalid mesh on a straight edge");
-
- bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF );
- NC = const_cast<SMDS_MeshNode*>
- ( nodesFromP0ToP1 ? theNodes.begin()->second : theNodes.rbegin()->second );
- size_t i = 0, ir = Nodes1.size()-1;
- size_t * pi = nodesFromP0ToP1 ? &i : &ir;
- itn = theNodes.begin();
- if ( nodesFromP0ToP1 ) ++itn;
- for ( ; i < Nodes1.size(); ++i, --ir, ++itn )
- {
- Nodes1[*pi] = itn->second;
- }
- for ( i = 0; i < Nodes1.size()-1; ++i )
- {
- Points.Append( gpXYZ( Nodes1[i]));
- Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i]));
- }
- }
- else
+ if ( linSide1Computed && !linSide2Computed )
{
- int edgeID = meshDS->ShapeToIndex(LinEdge1);
- gp_Vec aVec(P0,P1);
- // check orientation
- Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp);
- gp_Pnt Ptmp = Crv->Value(fp);
- bool ori = false;
- if( P1.Distance(Ptmp) > Precision::Confusion() )
- ori = true;
- // get UV points for edge
- gp_Pnt2d PF,PL;
- BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL );
- gp_Vec2d V2d;
- if(ori) {
- V2d = gp_Vec2d(PF,PL);
- PC = PF;
- }
- else {
- V2d = gp_Vec2d(PL,PF);
- PC = PL;
- }
- NC = const_cast<SMDS_MeshNode*>( VertexNode( VC, meshDS ));
- if ( !NC )
- {
- NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z());
- meshDS->SetNodeOnVertex(NC, vertID);
- }
- double dp = lp-fp;
- size_t i = 0;
- for ( ; i < myLayerPositions.size(); i++ ) {
- gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
- P0.Y() + aVec.Y()*myLayerPositions[i],
- P0.Z() + aVec.Z()*myLayerPositions[i] );
- Points.Append(P);
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- Nodes1[i] = node;
- double param;
- if ( !ori )
- param = fp + dp*(1-myLayerPositions[i]);
- else
- param = fp + dp*myLayerPositions[i];
- meshDS->SetNodeOnEdge(node, edgeID, param);
- // parameters on face
- gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
- PC.Y() + V2d.Y()*myLayerPositions[i] );
- Pnts2d1.Append(P2d);
- }
- Nodes1[ myLayerPositions.size() ] = NF;
- // create 1D elements on edge
- SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] );
- if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
- for ( i = 1; i < Nodes1.size(); i++ ) {
- ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] );
- if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
- }
- if ( nbe == 2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
- Nodes2 = Nodes1;
+ // use layer positions of linSide1 to mesh linSide2
+ makeMissingMesh( linSide2, nodes, layerPositions, myHelper );
+ linSide2 = StdMeshers_FaceSide::New( nodes );
}
- markEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F ));
-
- // LinEdge2
- if ( linEdge2Computed )
+ else if ( linSide2Computed && !linSide1Computed )
{
- if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge2,true,theNodes))
- return error("Invalid mesh on a straight edge");
-
- bool nodesFromP0ToP2 = ( theNodes.rbegin()->second == NL );
- size_t i = 0, ir = Nodes1.size()-1;
- size_t * pi = nodesFromP0ToP2 ? &i : &ir;
- itn = theNodes.begin();
- if ( nodesFromP0ToP2 ) ++itn;
- for ( ; i < Nodes2.size(); ++i, --ir, ++itn )
- Nodes2[*pi] = itn->second;
+ // use layer positions of linSide2 to mesh linSide1
+ makeMissingMesh( linSide1, nodes, layerPositions2, myHelper );
+ linSide1 = StdMeshers_FaceSide::New( nodes );
}
- else
+ else if ( !linSide2Computed && !linSide1Computed )
{
- int edgeID = meshDS->ShapeToIndex(LinEdge2);
- gp_Vec aVec = gp_Vec(P0,P2);
- // check orientation
- Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge2,fp,lp);
- gp_Pnt Ptmp = Crv->Value(fp);
- bool ori = false;
- if( P2.Distance(Ptmp) > Precision::Confusion() )
- ori = true;
- // get UV points for edge
- gp_Pnt2d PF,PL;
- BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL );
- gp_Vec2d V2d;
- if(ori) {
- V2d = gp_Vec2d(PF,PL);
- PC = PF;
- }
- else {
- V2d = gp_Vec2d(PL,PF);
- PC = PL;
- }
- double dp = lp-fp;
- for ( size_t i = 0; i < myLayerPositions.size(); i++ ) {
- gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i],
- P0.Y() + aVec.Y()*myLayerPositions[i],
- P0.Z() + aVec.Z()*myLayerPositions[i] );
- SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z());
- Nodes2[i] = node;
- double param;
- if(!ori)
- param = fp + dp*(1-myLayerPositions[i]);
- else
- param = fp + dp*myLayerPositions[i];
- meshDS->SetNodeOnEdge(node, edgeID, param);
- // parameters on face
- gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i],
- PC.Y() + V2d.Y()*myLayerPositions[i] );
- }
- Nodes2[ myLayerPositions.size() ] = NL;
- // create 1D elements on edge
- SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes2[0] );
- if ( ME ) meshDS->SetMeshElementOnShape(ME, edgeID);
- for ( size_t i = 1; i < Nodes2.size(); i++ ) {
- ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] );
- if(ME) meshDS->SetMeshElementOnShape(ME, edgeID);
- }
- }
- markEdgeAsComputedByMe( LinEdge2, aMesh.GetSubMesh( F ));
- }
- markEdgeAsComputedByMe( CircEdge, aMesh.GetSubMesh( F ));
-
- // orientation
- bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD );
- const double angleSign = ( F.Orientation() == TopAbs_REVERSED ? -1.0 : 1.0 );
-
- // create nodes and mesh elements on face
- // find axis of rotation
- gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() );
- gp_Vec Vec1(P0,P1);
- gp_Vec Vec2(P0,P2);
- gp_Vec Axis = Vec1.Crossed(Vec2);
- // create elements
- int i = 1;
- //cout<<"Angles.Length() = "<<Angles.Length()<<" Points.Length() = "<<Points.Length()<<endl;
- //cout<<"Nodes1.size() = "<<Nodes1.size()<<" Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl;
- for(; i<Angles.Length(); i++) {
- vector< const SMDS_MeshNode* > tmpNodes;
- gp_Trsf aTrsf;
- gp_Ax1 theAxis(P0,gp_Dir(Axis));
- aTrsf.SetRotation( theAxis, Angles.Value(i) );
- gp_Trsf2d aTrsf2d;
- aTrsf2d.SetRotation( PC, Angles.Value(i) * angleSign );
- // create nodes
- int j = 1;
- for(; j<=Points.Length(); j++) {
- double cx,cy,cz;
- Points.Value(j).Coord( cx, cy, cz );
- aTrsf.Transforms( cx, cy, cz );
- SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz );
- // find parameters on face
- Pnts2d1.Value(j).Coord( cx, cy );
- aTrsf2d.Transforms( cx, cy );
- // set node on face
- meshDS->SetNodeOnFace( node, faceID, cx, cy );
- tmpNodes.push_back(node);
+ // use layer positions of a longer side to mesh the shorter side
+ vector< double >& lp =
+ ( linSide1->Length() > linSide2->Length() ) ? layerPositions : layerPositions2;
+
+ makeMissingMesh( linSide1, nodes, lp, myHelper );
+ linSide1 = StdMeshers_FaceSide::New( nodes );
+ makeMissingMesh( linSide2, nodes, lp, myHelper );
+ linSide2 = StdMeshers_FaceSide::New( nodes );
}
- // create faces
- tmpNodes.push_back( CNodes[i] );
- // quad
- for ( j = 0; j < (int)Nodes1.size() - 1; j++ ) {
- SMDS_MeshFace* MF;
- if(IsForward)
- MF = myHelper->AddFace( tmpNodes[j], Nodes1[j],
- Nodes1[j+1], tmpNodes[j+1] );
- else
- MF = myHelper->AddFace( tmpNodes[j], tmpNodes[j+1],
- Nodes1[j+1], Nodes1[j] );
- if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
- }
- // tria
- SMDS_MeshFace* MF;
- if(IsForward)
- MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] );
- else
- MF = myHelper->AddFace( NC, tmpNodes[0], Nodes1[0] );
- if ( MF ) meshDS->SetMeshElementOnShape(MF, faceID);
- for ( j = 0; j < (int) Nodes1.size(); j++ ) {
- Nodes1[j] = tmpNodes[j];
- }
- }
- // create last faces
- // quad
- for ( i = 0; i < (int)Nodes1.size()-1; i++ ) {
- SMDS_MeshFace* MF;
- if(IsForward)
- MF = myHelper->AddFace( Nodes2[i], Nodes1[i],
- Nodes1[i+1], Nodes2[i+1] );
- else
- MF = myHelper->AddFace( Nodes2[i], Nodes2[i+1],
- Nodes1[i+1], Nodes1[i] );
- if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
+
+ const UVPtStructVec& nodes2 = linSide2->GetUVPtStruct();
+ centerNode = nodes2.back().node;
+ centerUV = nodes2.back().UV();
}
- // tria
- SMDS_MeshFace* MF;
- if(IsForward)
- MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] );
+
+ list< TopoDS_Edge >::iterator ee = emptyEdges.begin();
+ for ( ; ee != emptyEdges.end(); ++ee )
+ markEdgeAsComputedByMe( *ee, aMesh.GetSubMesh( F ));
+
+ circSide->GetUVPtStruct(); // let sides take into account just computed nodes
+ linSide1->GetUVPtStruct();
+ linSide2->GetUVPtStruct();
+
+ FaceQuadStruct::Ptr quad( new FaceQuadStruct );
+ quad->side.resize( 4 );
+ quad->side[0] = circSide;
+ quad->side[1] = linSide1;
+ quad->side[2] = StdMeshers_FaceSide::New( circSide.get(), centerNode, ¢erUV );
+ quad->side[3] = linSide2;
+
+ myQuadList.push_back( quad );
+
+ // create quadrangles
+ bool ok;
+ if ( linSide1->NbPoints() == linSide2->NbPoints() )
+ ok = StdMeshers_Quadrangle_2D::computeQuadDominant( aMesh, F, quad );
else
- MF = myHelper->AddFace( NC, Nodes2[0], Nodes1[0] );
- if(MF) meshDS->SetMeshElementOnShape(MF, faceID);
+ ok = StdMeshers_Quadrangle_2D::computeTriangles( aMesh, F, quad );
- return true;
+ StdMeshers_Quadrangle_2D::myHelper = 0;
+
+ return ok;
}
//================================================================================
/*!
- * \brief Compute positions of nodes on the radial edge
- * \retval bool - is a success
+ * \brief Compute nodes on the radial edge
+ * \retval int - nb of segments on the linSide
*/
//================================================================================
-bool StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(const gp_Pnt& p1,
- const gp_Pnt& p2,
- const TopoDS_Edge& linEdge,
- bool* linEdgeComputed)
+int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSidePtr linSide,
+ vector< double > & positions,
+ int* nbMeshedEdges,
+ bool useHalf)
{
// First, try to compute positions of layers
- myLayerPositions.clear();
+ positions.clear();
SMESH_Mesh * mesh = myHelper->GetMesh();
if ( !hyp1D && !nbLayers )
{
// No own algo hypotheses assigned, so first try to find any 1D hypothesis.
- // We need some edge
- TopoDS_Shape edge = linEdge;
- if ( edge.IsNull() && !myHelper->GetSubShape().IsNull())
- for ( TopExp_Explorer e(myHelper->GetSubShape(), TopAbs_EDGE); e.More(); e.Next())
- edge = e.Current();
- if ( !edge.IsNull() )
- {
- // find a hyp usable by TNodeDistributor
- const SMESH_HypoFilter* hypKind =
- TNodeDistributor::GetDistributor(*mesh)->GetCompatibleHypoFilter(/*ignoreAux=*/true);
- hyp1D = mesh->GetHypothesis( edge, *hypKind, /*fromAncestors=*/true);
- }
+ // find a hyp usable by TNodeDistributor
+ TopoDS_Shape edge = linSide->Edge(0);
+ const SMESH_HypoFilter* hypKind =
+ TNodeDistributor::GetDistributor(*mesh)->GetCompatibleHypoFilter(/*ignoreAux=*/true);
+ hyp1D = mesh->GetHypothesis( edge, *hypKind, /*fromAncestors=*/true);
}
if ( hyp1D ) // try to compute with hyp1D
{
- if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( myLayerPositions,p1,p2,*mesh,hyp1D )) {
+ BRepAdaptor_CompCurve* curve = linSide->GetCurve3d();
+ SMESHUtils::Deleter< BRepAdaptor_CompCurve > delCurve( curve );
+ double f = curve->FirstParameter();
+ double l = curve->LastParameter();
+
+ if ( useHalf )
+ l = 0.5 * ( f + l ); // first part of linSide is used
+
+ if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( positions, linSide->Edge(0),
+ *curve, f, l, *mesh, hyp1D ))
+ {
if ( myDistributionHypo ) { // bad hyp assigned
return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
}
else {
- // bad hyp found, its Ok, lets try with default nb of segnents
+ // bad hyp found, its Ok, lets try with default nb of segments
}
}
}
- if ( myLayerPositions.empty() ) // try to use nb of layers
+ if ( positions.empty() ) // try to use nb of layers
{
if ( !nbLayers )
nbLayers = _gen->GetDefaultNbSegments();
if ( nbLayers )
{
- myLayerPositions.resize( nbLayers - 1 );
- for ( int z = 1; z < nbLayers; ++z )
- myLayerPositions[ z - 1 ] = double( z )/ double( nbLayers );
+ positions.resize( nbLayers + 1 );
+ for ( int z = 0; z < nbLayers; ++z )
+ positions[ z ] = double( z )/ double( nbLayers );
+ positions.back() = 1;
}
}
- // Second, check presence of a mesh built by other algo on linEdge
- // and mesh conformity to my hypothesis
+ // Second, check presence of a mesh built by other algo on linSide
- bool meshComputed = (!linEdge.IsNull() && !mesh->GetSubMesh(linEdge)->IsEmpty() );
- if ( linEdgeComputed ) *linEdgeComputed = meshComputed;
+ int nbEdgesComputed = 0;
+ for ( int i = 0; i < linSide->NbEdges(); ++i )
+ {
+ nbEdgesComputed += ( !mesh->GetSubMesh( linSide->Edge(i))->IsEmpty() );
+ }
- if ( meshComputed )
+ if ( nbEdgesComputed == linSide->NbEdges() )
{
- vector< double > nodeParams;
- GetNodeParamOnEdge( mesh->GetMeshDS(), linEdge, nodeParams );
-
- // nb of present nodes must be different in cases of 1 and 2 straight edges
-
- TopoDS_Vertex VV[2];
- TopExp::Vertices( linEdge, VV[0], VV[1]);
- const gp_Pnt* points[] = { &p1, &p2 };
- gp_Pnt vPoints[] = { BRep_Tool::Pnt(VV[0]), BRep_Tool::Pnt(VV[1]) };
- const double tol[] = { BRep_Tool::Tolerance(VV[0]), BRep_Tool::Tolerance(VV[1]) };
- bool pointsAreOnVertices = true;
- for ( int iP = 0; iP < 2 && pointsAreOnVertices; ++iP )
- pointsAreOnVertices = ( points[iP]->Distance( vPoints[0] ) < tol[0] ||
- points[iP]->Distance( vPoints[1] ) < tol[1] );
-
- int nbNodes = nodeParams.size() - 2; // 2 straight edges
- if ( !pointsAreOnVertices )
- nbNodes = ( nodeParams.size() - 3 ) / 2; // 1 straight edge
-
- if ( myLayerPositions.empty() )
+ const UVPtStructVec& points = linSide->GetUVPtStruct();
+ if ( points.size() >= 2 )
{
- myLayerPositions.resize( nbNodes );
- }
- else if ( myDistributionHypo || myNbLayerHypo )
- {
- // linEdge is computed by other algo. Check if there is a meshed face
- // using nodes on linEdge
- bool nodesAreUsed = false;
- TopTools_ListIteratorOfListOfShape ancestIt = mesh->GetAncestors( linEdge );
- for ( ; ancestIt.More() && !nodesAreUsed; ancestIt.Next() )
- if ( ancestIt.Value().ShapeType() == TopAbs_FACE )
- nodesAreUsed = (!mesh->GetSubMesh( ancestIt.Value() )->IsEmpty());
- if ( !nodesAreUsed ) {
- // rebuild them
- mesh->GetSubMesh( linEdge )->ComputeStateEngine( SMESH_subMesh::CLEAN );
- if ( linEdgeComputed ) *linEdgeComputed = false;
- }
- else {
-
- if ((int) myLayerPositions.size() != nbNodes )
- return error("Radial edge is meshed by other algorithm");
- }
+ positions.resize( points.size() );
+ for ( size_t i = 0; i < points.size(); ++i )
+ positions[ i ] = points[i].normParam;
}
}
- return !myLayerPositions.empty();
+ if ( nbMeshedEdges ) *nbMeshedEdges = nbEdgesComputed;
+
+ return positions.size();
}
//purpose :
//=======================================================================
-bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
+bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
- MapShapeNbElems& aResMap)
+ MapShapeNbElems& aResMap)
{
if( aShape.ShapeType() != TopAbs_FACE ) {
return false;
myHelper = new SMESH_MesherHelper( aMesh );
myHelper->SetSubShape( aShape );
- auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+ SMESHUtils::Deleter<SMESH_MesherHelper> helperDeleter( myHelper );
TNodeDistributor* algo1d = TNodeDistributor::GetDistributor(aMesh);
- TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
- int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 );
- if( nbe>3 || nbe < 1 || CircEdge.IsNull() )
+ StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+ int nbSides = analyseFace( aShape, &aMesh, circSide, linSide1, linSide2 );
+ if( nbSides > 3 || nbSides < 1 )
return false;
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
- if( aCirc.IsNull() )
- return error(COMPERR_BAD_SHAPE);
+ if ( algo1d->EvaluateCircularEdge( aMesh, circSide, aResMap ))
+ return false;
- gp_Pnt P0 = aCirc->Location();
- gp_Pnt P1 = aCirc->Value(0.);
- computeLayerPositions( P0, P1, LinEdge1 );
+ vector< double > layerPositions; // [0,1]
- int nb0d=0, nb2d_tria=0, nb2d_quad=0;
- bool isQuadratic = false, ok = true;
- if(nbe==1)
+ // ------------------------------------------------------------------------------------------
+ if ( nbSides == 1 )
{
- // C1 must be a circle
- ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
- if(ok) {
- const vector<int>& aVec = aResMap[aMesh.GetSubMesh(CircEdge)];
- isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
- if(isQuadratic) {
- // main nodes
- nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
- // radial medium nodes
- nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1);
- // other medium nodes
- nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
- }
- else {
- nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
- }
- nb2d_tria = aVec[SMDSEntity_Node] + 1;
- nb2d_quad = nb0d;
- }
+ const TopoDS_Face& F = TopoDS::Face( aShape );
+
+ const SMDS_MeshNode* circNode;
+ TopoDS_Edge linEdge = makeEdgeToCenter( circSide, F, circNode );
+
+ StdMeshers_FaceSidePtr tmpSide =
+ StdMeshers_FaceSide::New( F, linEdge, &aMesh, /*isFrw=*/true, /*skipMedium=*/true );
+
+ if ( !computeLayerPositions( tmpSide, layerPositions ))
+ return false;
}
- else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL)
+ // ------------------------------------------------------------------------------------------
+ else if ( nbSides == 2 && linSide1->Edge(0).Orientation() == TopAbs_INTERNAL )
{
- // one curve must be a half of circle and other curve must be
- // a segment of line
- double fp, lp;
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp ));
- if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) {
- // not half of circle
- return error(COMPERR_BAD_SHAPE);
- }
- Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
- if( aLine.IsNull() ) {
- // other curve not line
- return error(COMPERR_BAD_SHAPE);
- }
- ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1) );
- if ( !ok ) {
- const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
- ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
- }
- if(ok) {
- ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
- }
- if(ok) {
- const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
- isQuadratic = aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge];
- if(isQuadratic) {
- // main nodes
- nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
- // radial medium nodes
- nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
- // other medium nodes
- nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
- }
- else {
- nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
- }
- nb2d_tria = aVec[SMDSEntity_Node] + 1;
- nb2d_quad = nb2d_tria * myLayerPositions.size();
- // add evaluation for edges
- vector<int> aResVec(SMDSEntity_Last,0);
- if(isQuadratic) {
- aResVec[SMDSEntity_Node] = 4*myLayerPositions.size() + 3;
- aResVec[SMDSEntity_Quad_Edge] = 2*myLayerPositions.size() + 2;
- }
- else {
- aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
- aResVec[SMDSEntity_Edge] = 2*myLayerPositions.size() + 2;
- }
- aResMap[ aMesh.GetSubMesh(LinEdge1) ] = aResVec;
- }
+ if ( !computeLayerPositions( linSide1, layerPositions ))
+ return false;
}
- else // nbe==3 or ( nbe==2 && linEdge is INTERNAL )
+ // ------------------------------------------------------------------------------------------
+ else if ( nbSides == 2 )
{
- if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL )
- LinEdge2 = LinEdge1;
-
- // one curve must be a part of circle and other curves must be
- // segments of line
- Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 ));
- Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 ));
- if( aLine1.IsNull() || aLine2.IsNull() ) {
- // other curve not line
- return error(COMPERR_BAD_SHAPE);
- }
- size_t nbLayers = myLayerPositions.size();
- computeLayerPositions( P0, P1, LinEdge2 );
- if ( nbLayers != myLayerPositions.size() )
- return error("Different hypotheses apply to radial edges");
-
- bool ok = !aResMap.count( aMesh.GetSubMesh(LinEdge1));
- if ( !ok ) {
- if ( myDistributionHypo || myNbLayerHypo )
- ok = true; // override other 1d hyps
- else {
- const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge1) ];
- ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
- }
- }
- if( ok && aResMap.count( aMesh.GetSubMesh(LinEdge2) )) {
- if ( myDistributionHypo || myNbLayerHypo )
- ok = true; // override other 1d hyps
- else {
- const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(LinEdge2) ];
- ok = ( aVec[SMDSEntity_Node] == (int) myLayerPositions.size() );
- }
- }
- if(ok) {
- ok = algo1d->EvaluateCircularEdge( aMesh, CircEdge, aResMap );
- }
- if(ok) {
- const vector<int>& aVec = aResMap[ aMesh.GetSubMesh(CircEdge) ];
- isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge];
- if(isQuadratic) {
- // main nodes
- nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
- // radial medium nodes
- nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1);
- // other medium nodes
- nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size();
- }
- else {
- nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size();
- }
- nb2d_tria = aVec[SMDSEntity_Node] + 1;
- nb2d_quad = nb2d_tria * myLayerPositions.size();
- // add evaluation for edges
- vector<int> aResVec(SMDSEntity_Last, 0);
- if(isQuadratic) {
- aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1;
- aResVec[SMDSEntity_Quad_Edge] = myLayerPositions.size() + 1;
- }
- else {
- aResVec[SMDSEntity_Node] = myLayerPositions.size();
- aResVec[SMDSEntity_Edge] = myLayerPositions.size() + 1;
- }
- sm = aMesh.GetSubMesh(LinEdge1);
- aResMap[sm] = aResVec;
- sm = aMesh.GetSubMesh(LinEdge2);
- aResMap[sm] = aResVec;
- }
+ // find positions of layers for the first half of linSide1
+ if ( !computeLayerPositions( linSide1, layerPositions, 0, /*useHalf=*/true ))
+ return false;
+ }
+ // ------------------------------------------------------------------------------------------
+ else // nbSides == 3
+ {
+ if ( !computeLayerPositions(( linSide1->Length() > linSide2->Length() ) ? linSide1 : linSide2,
+ layerPositions ))
+ return false;
+ }
+
+ bool isQuadratic = false;
+ for ( TopExp_Explorer edge( aShape, TopAbs_EDGE ); edge.More() && !isQuadratic ; edge.Next() )
+ {
+ sm = aMesh.GetSubMesh( edge.Current() );
+ vector<int>& nbElems = aResMap[ sm ];
+ if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
+ isQuadratic = nbElems[ SMDSEntity_Quad_Edge ];
+ }
+
+ int nbCircSegments = 0;
+ for ( int iE = 0; iE < circSide->NbEdges(); ++iE )
+ {
+ sm = aMesh.GetSubMesh( circSide->Edge( iE ));
+ vector<int>& nbElems = aResMap[ sm ];
+ if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
+ nbCircSegments += ( nbElems[ SMDSEntity_Edge ] + nbElems[ SMDSEntity_Quad_Edge ]);
+ }
+
+ int nbQuads = nbCircSegments * ( layerPositions.size() - 1 );
+ int nbTria = nbCircSegments;
+ int nbNodes = ( nbCircSegments - 1 ) * ( layerPositions.size() - 2 );
+ if ( isQuadratic )
+ {
+ nbNodes += (( nbCircSegments - 1 ) * ( layerPositions.size() - 1 ) + // radial
+ ( nbCircSegments ) * ( layerPositions.size() - 2 )); // circular
+ aResVec[SMDSEntity_Quad_Triangle ] = nbTria;
+ aResVec[SMDSEntity_Quad_Quadrangle] = nbQuads;
+ }
+ else
+ {
+ aResVec[SMDSEntity_Triangle ] = nbTria;
+ aResVec[SMDSEntity_Quadrangle] = nbQuads;
}
+ aResVec[SMDSEntity_Node] = nbNodes;
- if(nb0d>0) {
- aResVec[0] = nb0d;
- if(isQuadratic) {
- aResVec[SMDSEntity_Quad_Triangle] = nb2d_tria;
- aResVec[SMDSEntity_Quad_Quadrangle] = nb2d_quad;
+ if ( linSide1 )
+ {
+ // evaluation for linSides
+ vector<int> aResVec(SMDSEntity_Last, 0);
+ if ( isQuadratic ) {
+ aResVec[SMDSEntity_Node ] = 2 * ( layerPositions.size() - 1 ) + 1;
+ aResVec[SMDSEntity_Quad_Edge] = layerPositions.size() - 1;
}
else {
- aResVec[SMDSEntity_Triangle] = nb2d_tria;
- aResVec[SMDSEntity_Quadrangle] = nb2d_quad;
+ aResVec[SMDSEntity_Node] = layerPositions.size() - 2;
+ aResVec[SMDSEntity_Edge] = layerPositions.size() - 1;
+ }
+ sm = aMesh.GetSubMesh( linSide1->Edge(0) );
+ aResMap[sm] = aResVec;
+ if ( linSide2 )
+ {
+ sm = aMesh.GetSubMesh( linSide2->Edge(0) );
+ aResMap[sm] = aResVec;
}
- return true;
}
- // invalid case
- sm = aMesh.GetSubMesh(aShape);
- SMESH_ComputeErrorPtr& smError = sm->GetComputeError();
- smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,
- "Submesh can not be evaluated",this));
- return false;
-
+ return true;
}
//================================================================================
int nbFoundFaces = 0;
for (TopExp_Explorer exp( aShape, TopAbs_FACE ); exp.More(); exp.Next(), ++nbFoundFaces )
{
- TopoDS_Edge CircEdge, LinEdge1, LinEdge2;
- int nbe = analyseFace( exp.Current(), CircEdge, LinEdge1, LinEdge2 );
- Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge ));
- bool ok = ( nbe <= 3 && nbe >= 1 && !aCirc.IsNull() &&
- isCornerInsideCircle( CircEdge, LinEdge1, LinEdge2 ));
+ StdMeshers_FaceSidePtr circSide, linSide1, linSide2;
+ int nbSides = analyseFace( exp.Current(), NULL, circSide, linSide1, linSide2 );
+ bool ok = ( 0 < nbSides && nbSides <= 3 &&
+ isCornerInsideCircle( circSide, linSide1, linSide2 ));
if( toCheckAll && !ok ) return false;
if( !toCheckAll && ok ) return true;
}
#ifndef _SMESH_RadialQuadrangle_1D2D_HXX_
#define _SMESH_RadialQuadrangle_1D2D_HXX_
-#include "SMESH_StdMeshers.hxx"
-
-#include "SMESH_Algo.hxx"
-
-#include <TopoDS_Edge.hxx>
+#include "StdMeshers_Quadrangle_2D.hxx"
#include <vector>
class StdMeshers_NumberOfLayers;
class StdMeshers_LayerDistribution;
-class SMESH_MesherHelper;
-class gp_Pnt;
-class STDMESHERS_EXPORT StdMeshers_RadialQuadrangle_1D2D: public SMESH_2D_Algo
+/*!
+ * \brief Algorithm generating quadrangles on a full or a part of an elliptic face.
+ * Elements around an ellipse center are triangles.
+ */
+
+class STDMESHERS_EXPORT StdMeshers_RadialQuadrangle_1D2D: public StdMeshers_Quadrangle_2D
{
public:
StdMeshers_RadialQuadrangle_1D2D(int hypId, int studyId, SMESH_Gen* gen);
protected:
- bool computeLayerPositions(const gp_Pnt& p1,
- const gp_Pnt& p2,
- const TopoDS_Edge& linEdge=TopoDS_Edge(),
- bool* linEdgeComputed = 0);
+ int computeLayerPositions(StdMeshers_FaceSidePtr linSide,
+ std::vector< double >& positions,
+ int* nbEdgesComputed = 0,
+ bool useHalf = false);
const StdMeshers_NumberOfLayers* myNbLayerHypo;
const StdMeshers_LayerDistribution* myDistributionHypo;
- SMESH_MesherHelper* myHelper;
- std::vector< double > myLayerPositions;
};
#endif
def readFromStdOut(self) :
a=self.monExe.readAllStandardOutput()
- aa=unicode(a.data(),len(a))
+ aa=unicode(a.data())
self.TB_Exe.append(aa)
if "END_OF_MGSurfOpt" in aa:
self.parent().enregistreResultat()
os.environ['DISTENE_LICENSE_FILE']
except:
QMessageBox.warning(None,"Products","""\
-Distene's product MeshGem SurfOpt (formerly Yams) is not installed.
+Distene's product MeshGem SurfOpt is not installed.
required environment variable:
DISTENE_LICENSE_FILE='.../dlim8.var.sh'""")
return
try:
from yamsplug_plugin import YamsLct
- salome_pluginsmanager.AddFunction('ReMesh with MGSurfOpt ( formerly Yams )',
+ salome_pluginsmanager.AddFunction('ReMesh with MGSurfOpt',
'Run Yams',
YamsLct)
except:
- salome_pluginsmanager.logger.info('ERROR: MGSurfOpt (Yams) plug-in is unavailable')
+ salome_pluginsmanager.logger.info('ERROR: MGSurfOpt plug-in is unavailable')
pass
try: