From: skv Date: Tue, 19 Nov 2013 11:55:25 +0000 (+0000) Subject: 0022354: EDF GEOM: Create edge by getting iso-line of surface X-Git-Tag: BR_hydro_v_0_3_1~6 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=82eebc8aee95a51d7c4c8ba8afa1ba3f60a7cf53;p=modules%2Fgeom.git 0022354: EDF GEOM: Create edge by getting iso-line of surface --- diff --git a/doc/salome/examples/basic_geom_objs_ex06.py b/doc/salome/examples/basic_geom_objs_ex06.py index 661b0edef..ecaec0ed5 100644 --- a/doc/salome/examples/basic_geom_objs_ex06.py +++ b/doc/salome/examples/basic_geom_objs_ex06.py @@ -19,6 +19,7 @@ v2 = geompy.MakeVectorDXDYDZ(1, 0, 0) # create a polyline from a list of points polyline = geompy.MakePolyline([p0, p1, p2, p3, p4]) +closed_polyline = geompy.MakePolyline([p0, p1, p2, p0]) # create a bezier curve from a list of points bezier = geompy.MakeBezier([p0, p1, p2, p3, p4]) @@ -38,6 +39,11 @@ param_bezier = geompy.MakeCurveParametric("t", "sin(t)", "cos(t)", 0., 100., 20, #create a b-spline curve using parametric definition of the basic points param_interpol = geompy.MakeCurveParametric("t", "sin(t)", "cos(t)", 0., 100., 100, GEOM.Interpolation, theNewMethod=True) +#create a face from closed polyline +face = geompy.MakeFace(closed_polyline, True) + +#create an U-isoline curve +isoline = geompy.MakeIsoline(face, True, 0.6) # add objects in the study id_p0 = geompy.addToStudy(p0, "Point1") @@ -48,12 +54,15 @@ id_p4 = geompy.addToStudy(p4, "Point5") id_v1 = geompy.addToStudy(v1, "Vector1") id_v2 = geompy.addToStudy(v2, "Vector2") id_polyline = geompy.addToStudy(polyline, "Polyline") +id_closed_polyline = geompy.addToStudy(closed_polyline, "Closed Polyline") id_bezier = geompy.addToStudy(bezier, "Bezier") id_interpol = geompy.addToStudy(interpol, "Interpol") id_interpol_tangents = geompy.addToStudy(interpol_tangents, "Interpol Tangents") id_param_polyline = geompy.addToStudy(param_polyline, "Polyline Parametric") id_param_bezier = geompy.addToStudy(param_bezier, "Bezier Parametric") id_param_interpol = geompy.addToStudy(param_interpol, "Interpol Parametric") +id_face = geompy.addToStudy(face, "Face") +id_isoline = geompy.addToStudy(isoline, "Isoline") # display the points and the curves @@ -63,9 +72,12 @@ gg.createAndDisplayGO(id_p2) gg.createAndDisplayGO(id_p3) gg.createAndDisplayGO(id_p4) gg.createAndDisplayGO(id_polyline) +gg.createAndDisplayGO(id_closed_polyline) gg.createAndDisplayGO(id_bezier) gg.createAndDisplayGO(id_interpol) gg.createAndDisplayGO(id_interpol_tangents) gg.createAndDisplayGO(id_param_polyline) gg.createAndDisplayGO(id_param_bezier) gg.createAndDisplayGO(id_param_interpol) +gg.createAndDisplayGO(id_face) +gg.createAndDisplayGO(id_isoline) diff --git a/doc/salome/gui/GEOM/images/isoline1.png b/doc/salome/gui/GEOM/images/isoline1.png new file mode 100644 index 000000000..8bc863141 Binary files /dev/null and b/doc/salome/gui/GEOM/images/isoline1.png differ diff --git a/doc/salome/gui/GEOM/images/isoline2.png b/doc/salome/gui/GEOM/images/isoline2.png new file mode 100644 index 000000000..3a41807df Binary files /dev/null and b/doc/salome/gui/GEOM/images/isoline2.png differ diff --git a/doc/salome/gui/GEOM/input/creating_basic_go.doc b/doc/salome/gui/GEOM/input/creating_basic_go.doc index aea41d9b3..6693b469d 100644 --- a/doc/salome/gui/GEOM/input/creating_basic_go.doc +++ b/doc/salome/gui/GEOM/input/creating_basic_go.doc @@ -12,6 +12,7 @@ geometrical objects as:
  • \subpage create_ellipse_page
  • \subpage create_arc_page
  • \subpage create_curve_page
  • +
  • \subpage create_isoline_page
  • \subpage create_sketcher_page
  • \subpage create_3dsketcher_page
  • \subpage create_vector_page
  • diff --git a/doc/salome/gui/GEOM/input/creating_isoline.doc b/doc/salome/gui/GEOM/input/creating_isoline.doc new file mode 100644 index 000000000..2aac337f1 --- /dev/null +++ b/doc/salome/gui/GEOM/input/creating_isoline.doc @@ -0,0 +1,24 @@ +/*! + +\page create_isoline_page Isoline + +To create an \b Isoline in the Main Menu select New Entity - > +Basic - > Isoline + +\n The \b Result of this operation will be a GEOM_Object. +It may be either an edge or a compound of several edges. + +\n You can define an Isoline by a \b Face, \b Type and \b Parameter. +\n TUI Command: geompy.MakeIsoline(theFace, IsUIsoline, theParameter) +\n Arguments: Name + Face + Type (True for U-Isoline; False for V-Isoline) + Parameter. + +\image html isoline1.png + +Example: + +\image html isoline2.png "Isoline on face" + +Our TUI Scripts provide you with useful examples of creation of +\ref tui_creation_curve "Basic Geometric Objects". + +*/ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index ad612446c..a9ad919b6 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -3192,6 +3192,20 @@ module GEOM in long theParamNbStep, in curve_type theCurveType); + /*! + * \brief Creates an isoline curve on a face. + * \param theFace the face for which an isoline is created. + * \param IsUIsoline True for U-isoline creation; False for V-isoline + * creation. + * \param theParameter the U parameter for U-isoline or V parameter + * for V-isoline. + * \return New GEOM_Object, containing the created isoline edge or a + * compound of edges. + */ + GEOM_Object MakeIsoline(in GEOM_Object theFace, + in boolean IsUIsoline, + in double theParameter); + /*! * \brief Create a sketcher (wire or face), following the textual description, * passed through \a theCommand argument. diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 72f3188d6..7e9c9aa48 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -31,6 +31,8 @@ SET( _res_files ImportExport ShHealing 3dsketch.png + isoline.png + isoline_v.png angle.png arc.png arccenter.png diff --git a/resources/isoline.png b/resources/isoline.png new file mode 100644 index 000000000..dc6257381 Binary files /dev/null and b/resources/isoline.png differ diff --git a/resources/isoline_v.png b/resources/isoline_v.png new file mode 100644 index 000000000..ce143a177 Binary files /dev/null and b/resources/isoline_v.png differ diff --git a/src/EntityGUI/CMakeLists.txt b/src/EntityGUI/CMakeLists.txt index 510546716..322cdeb14 100755 --- a/src/EntityGUI/CMakeLists.txt +++ b/src/EntityGUI/CMakeLists.txt @@ -104,6 +104,7 @@ SET(EntityGUI_HEADERS EntityGUI_Widgets.h EntityGUI_SketcherDlg.h EntityGUI_3DSketcherDlg.h + EntityGUI_IsolineDlg.h EntityGUI_SubShapeDlg.h EntityGUI_FeatureDetectorDlg.h EntityGUI_PictureImportDlg.h @@ -115,6 +116,7 @@ SET(_moc_HEADERS EntityGUI_FieldDlg.h EntityGUI_SketcherDlg.h EntityGUI_3DSketcherDlg.h + EntityGUI_IsolineDlg.h EntityGUI_SubShapeDlg.h EntityGUI_PictureImportDlg.h ${FeatureDetectorDlg_moc_h} @@ -134,6 +136,7 @@ SET(EntityGUI_SOURCES EntityGUI_FieldDlg.cxx EntityGUI_SketcherDlg.cxx EntityGUI_3DSketcherDlg.cxx + EntityGUI_IsolineDlg.cxx EntityGUI_SubShapeDlg.cxx EntityGUI_PictureImportDlg.cxx ${FeatureDetectorDlg_Sources} diff --git a/src/EntityGUI/EntityGUI.cxx b/src/EntityGUI/EntityGUI.cxx index b45d42774..ba8860a15 100644 --- a/src/EntityGUI/EntityGUI.cxx +++ b/src/EntityGUI/EntityGUI.cxx @@ -54,6 +54,7 @@ #include "EntityGUI_SketcherDlg.h" // Sketcher #include "EntityGUI_3DSketcherDlg.h" // Sketcher +#include "EntityGUI_IsolineDlg.h" // Isoline #include "EntityGUI_SubShapeDlg.h" // Method SUBSHAPE #include "EntityGUI_FeatureDetectorDlg.h" // Feature Detection #include "EntityGUI_PictureImportDlg.h" // Import Picture in viewer @@ -101,6 +102,9 @@ bool EntityGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::Op3dSketcher: // 3D SKETCHER aDlg = new EntityGUI_3DSketcherDlg( getGeometryGUI(), parent ); break; + case GEOMOp::OpIsoline: // ISOLINE + aDlg = new EntityGUI_IsolineDlg( getGeometryGUI(), parent ); + break; case GEOMOp::OpExplode: // EXPLODE aDlg = new EntityGUI_SubShapeDlg( getGeometryGUI(), parent ); break; diff --git a/src/EntityGUI/EntityGUI_IsolineDlg.cxx b/src/EntityGUI/EntityGUI_IsolineDlg.cxx new file mode 100755 index 000000000..3eb87766c --- /dev/null +++ b/src/EntityGUI/EntityGUI_IsolineDlg.cxx @@ -0,0 +1,283 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : EntityGUI_IsolineDlg.cxx + +#include "EntityGUI_IsolineDlg.h" +#include +#include +#include + +#include +#include +#include +#include + + +//================================================================================= +// class : EntityGUI_IsolineDlg +// purpose : +//================================================================================= +EntityGUI_IsolineDlg::EntityGUI_IsolineDlg (GeometryGUI *theGeometryGUI, + QWidget *parent, + bool modal, + Qt::WindowFlags fl) + : GEOMBase_Skeleton (theGeometryGUI, parent, modal, fl), + myRBGroup (0) +{ + QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICO_ISOLINE"))); + QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); + QPixmap image2(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICO_ISOLINE_V"))); + + setWindowTitle(tr("GEOM_ISOLINE_TITLE")); + + /***************************************************************/ + + mainFrame()->GroupConstructors->setTitle(tr("GEOM_ISOLINE")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->close(); + + // Construct a group. + myGroup = new DlgRef_3Radio1Sel1Spin(centralWidget()); + myGroup->GroupBox1->setTitle(tr("GEOM_ARGUMENTS")); + myGroup->TextLabel1->setText(tr("GEOM_FACE")); + myGroup->PushButton1->setIcon(image1); + myGroup->LineEdit1->setReadOnly(true); + myGroup->RadioButton1->setIcon(image0); + myGroup->RadioButton2->setIcon(image2); + myGroup->RadioButton1->setText(tr("GEOM_ISOLINE_U")); + myGroup->RadioButton2->setText(tr("GEOM_ISOLINE_V")); + myGroup->RadioButton3->hide(); + myGroup->TextLabel2->setText(tr("GEOM_PARAMETER")); + + QVBoxLayout* layout = new QVBoxLayout(centralWidget()); + layout->setMargin(0); layout->setSpacing(6); + layout->addWidget(myGroup); + + myRBGroup = new QButtonGroup( this ); + myRBGroup->addButton( myGroup->RadioButton1, 0 ); + myRBGroup->addButton( myGroup->RadioButton2, 1 ); + + setHelpFileName("create_isoline_page.html"); + + Init(); +} + +//================================================================================= +// function : ~EntityGUI_IsolineDlg() +// purpose : +//================================================================================= +EntityGUI_IsolineDlg::~EntityGUI_IsolineDlg() +{ +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::Init() +{ + /* min, max, step and decimals for spin box */ + initSpinBox(myGroup->SpinBox_DX, 0., 1., 0.1, "parametric_precision"); + myGroup->SpinBox_DX->setValue(0.5); + myGroup->RadioButton1->setChecked(true); + + initName(mainFrame()->GroupConstructors->title()); + + connect(myGroup->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditFace())); + connect(myGroup->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + + connect(myGeomGUI, SIGNAL(SignalDefaultStepValueChanged(double)), this, SLOT(SetDoubleSpinBoxStep(double))); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + /* signals and slots connections */ + connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); + connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel())); + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + connect(myRBGroup, SIGNAL(buttonClicked(int)), this, SLOT(TypeChanged(int))); + + myGroup->PushButton1->click(); + SelectionIntoArgument(); + resize(100,100); +} + +//================================================================================= +// function : SelectionIntoArgument +// purpose : Called when selection is changed +//================================================================================= +void EntityGUI_IsolineDlg::SelectionIntoArgument() +{ + myGroup->LineEdit1->setText(""); + myFace.nullify(); + + GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_SHAPE ); + TopoDS_Shape aShape; + + if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aShape ) && !aShape.IsNull() ) { + if (aShape.ShapeType() == TopAbs_FACE) { + QString aName = GEOMBase::GetName( aSelectedObject.get() ); + myGroup->LineEdit1->setText( aName ); + + // clear selection + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + myGeomGUI->getApp()->selectionMgr()->clearSelected(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + myFace = aSelectedObject; + } + } + + displayPreview(true); +} + +//================================================================================= +// function : ActivateThisDialog +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + + connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ), + this, SLOT( SelectionIntoArgument() ) ); + SetEditFace(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : TypeChanged +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::TypeChanged(int) +{ + displayPreview(true); +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr EntityGUI_IsolineDlg::createOperation() +{ + return myGeomGUI->GetGeomGen()->GetICurvesOperations( getStudyId() ); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool EntityGUI_IsolineDlg::isValid (QString& msg) +{ + return myFace; +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool EntityGUI_IsolineDlg::execute (ObjectList& objects) +{ + GEOM::GEOM_ICurvesOperations_var anOper = GEOM::GEOM_ICurvesOperations::_narrow(getOperation()); + GEOM::GEOM_Object_var anObj = anOper->MakeIsoline + (myFace.get(), myGroup->RadioButton1->isChecked(), myGroup->SpinBox_DX->value()); + + if (!anObj->_is_nil()) + objects.push_back(anObj._retn()); + + return true; +} + +//================================================================================= +// function : addSubshapesToStudy() +// purpose : Double spin box management +//================================================================================= +void EntityGUI_IsolineDlg::addSubshapesToStudy() +{ + GEOMBase::PublishSubObject(myFace.get()); +} + +//================================================================================= +// function : SetDoubleSpinBoxStep() +// purpose : Double spin box management +//================================================================================= +void EntityGUI_IsolineDlg::SetDoubleSpinBoxStep (double step) +{ + myGroup->SpinBox_DX->setSingleStep(step); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool EntityGUI_IsolineDlg::ClickOnApply() +{ + if (!onAccept()) + return false; + + initName(); + // activate selection and connect selection manager + myGroup->PushButton1->click(); + return true; +} + +//================================================================================= +// function : SetEditFace +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::SetEditFace() +{ + myGroup->LineEdit1->setFocus(); + myGroup->PushButton1->setDown(true); +} + +//================================================================================= +// function : ValueChangedInSpinBox +// purpose : +//================================================================================= +void EntityGUI_IsolineDlg::ValueChangedInSpinBox(double newValue) +{ + displayPreview(true); +} diff --git a/src/EntityGUI/EntityGUI_IsolineDlg.h b/src/EntityGUI/EntityGUI_IsolineDlg.h new file mode 100755 index 000000000..50194ff16 --- /dev/null +++ b/src/EntityGUI/EntityGUI_IsolineDlg.h @@ -0,0 +1,83 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : EntityGUI_IsolineDlg.h + +#ifndef ENTITYGUI_ISOLINEDLG_H +#define ENTITYGUI_ISOLINEDLG_H + + +#include + +class DlgRef_3Radio1Sel1Spin; + +//================================================================================= +// class : EntityGUI_IsolineDlg +// purpose : +//================================================================================= +class EntityGUI_IsolineDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + + EntityGUI_IsolineDlg (GeometryGUI *theGeometryGUI, + QWidget *parent = 0, + bool modal = false, + Qt::WindowFlags fl = 0); + + ~EntityGUI_IsolineDlg(); + +protected: + + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + + virtual bool isValid( QString& ); + + virtual bool execute( ObjectList& ); + + virtual void addSubshapesToStudy(); + +private: + + void Init(); + void enterEvent( QEvent* ); + +private: + + DlgRef_3Radio1Sel1Spin *myGroup; + QButtonGroup *myRBGroup; + GEOM::GeomObjPtr myFace; + + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + + void SetEditFace(); + void ValueChangedInSpinBox( double ); + void SelectionIntoArgument(); + void ActivateThisDialog(); + void SetDoubleSpinBoxStep( double ); + void TypeChanged(int); +}; + +#endif // ENTITYGUI_ISOLINEDLG_H diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 409484017..1e27166a6 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -1219,6 +1219,14 @@ ICO_3DSKETCH 3dsketch.png + + ICO_ISOLINE + isoline.png + + + ICO_ISOLINE_V + isoline_v.png + ICO_SOLID build_solid.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index b861fe2d9..a56f0efd8 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -2960,6 +2960,10 @@ Please, select face, shell or solid and try again MEN_3DSKETCH 3D Sketch + + MEN_ISOLINE + Isoline + MEN_SOLID Solid @@ -3785,6 +3789,10 @@ Please, select face, shell or solid and try again STB_3DSKETCH Create 3D sketch + + STB_ISOLINE + Create U- or V-Isoline + STB_SOLID Build a solid @@ -4401,6 +4409,10 @@ Please, select face, shell or solid and try again TOP_3DSKETCH 3D sketch + + TOP_ISOLINE + Isoline + TOP_SOLID Build solid @@ -6497,4 +6509,23 @@ Do you want to create new material? Step + + EntityGUI_IsolineDlg + + GEOM_ISOLINE_TITLE + Isoline Construction + + + GEOM_ISOLINE + Isoline + + + GEOM_ISOLINE_U + U-Isoline + + + GEOM_ISOLINE_V + V-Isoline + + diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 6ba66d776..25b53507c 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -545,6 +545,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) break; case GEOMOp::Op2dSketcher: // MENU ENTITY - SKETCHER case GEOMOp::Op3dSketcher: // MENU ENTITY - 3D SKETCHER + case GEOMOp::OpIsoline: // MENU BASIC - ISOLINE case GEOMOp::OpExplode: // MENU ENTITY - EXPLODE #ifdef WITH_OPENCV case GEOMOp::OpFeatureDetect: // MENU ENTITY - FEATURE DETECTION @@ -890,6 +891,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpEllipse, "ELLIPSE" ); createGeomAction( GEOMOp::OpArc, "ARC" ); createGeomAction( GEOMOp::OpCurve, "CURVE" ); + createGeomAction( GEOMOp::OpIsoline, "ISOLINE" ); createGeomAction( GEOMOp::OpVector, "VECTOR" ); createGeomAction( GEOMOp::OpPlane, "PLANE" ); createGeomAction( GEOMOp::OpLCS, "LOCAL_CS" ); @@ -925,6 +927,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::Op2dSketcher, "SKETCH" ); createGeomAction( GEOMOp::Op3dSketcher, "3DSKETCH" ); + createGeomAction( GEOMOp::OpIsoline, "ISOLINE" ); createGeomAction( GEOMOp::OpExplode, "EXPLODE" ); #ifdef WITH_OPENCV createGeomAction( GEOMOp::OpFeatureDetect,"FEATURE_DETECTION" ); @@ -1106,6 +1109,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpCurve, basicId, -1 ); createMenu( GEOMOp::Op2dSketcher, basicId, -1 ); createMenu( GEOMOp::Op3dSketcher, basicId, -1 ); + createMenu( GEOMOp::OpIsoline, basicId, -1 ); createMenu( separator(), basicId, -1 ); createMenu( GEOMOp::OpVector, basicId, -1 ); createMenu( GEOMOp::OpPlane, basicId, -1 ); @@ -1318,6 +1322,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpVector, basicTbId ); createTool( GEOMOp::Op2dSketcher, basicTbId ); //rnc createTool( GEOMOp::Op3dSketcher, basicTbId ); //rnc + createTool( GEOMOp::OpIsoline, basicTbId ); createTool( GEOMOp::OpPlane, basicTbId ); createTool( GEOMOp::OpLCS, basicTbId ); createTool( GEOMOp::OpOriginAndVectors, basicTbId ); diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 40c0e38cd..965e9e445 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -90,6 +90,7 @@ namespace GEOMOp { OpCurve = 3007, // MENU NEW ENTITY - BASIC - CURVE OpLCS = 3008, // MENU NEW ENTITY - BASIC - LOCAL COORDINATE SYSTEM OpOriginAndVectors = 3009, // MENU NEW ENTITY - BASIC - ORIGIN AND BASE VECTORS + OpIsoline = 3010, // MENU NEW ENTITY - BASIC - ISOLINE // PrimitiveGUI ----------------//-------------------------------- OpBox = 3100, // MENU NEW ENTITY - PRIMITIVES - BOX OpCylinder = 3101, // MENU NEW ENTITY - PRIMITIVES - CYLINDER diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index cbdc2708d..49123eb2a 100755 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -120,6 +120,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_IPipeShellSect.hxx GEOMImpl_IPipeBiNormal.hxx GEOMImpl_ICurveParametric.hxx + GEOMImpl_IIsoline.hxx GEOMImpl_VectorDriver.hxx GEOMImpl_LineDriver.hxx GEOMImpl_DiskDriver.hxx diff --git a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx index c679b048a..977a76297 100644 --- a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx @@ -46,6 +46,7 @@ #include "GEOMImpl_SplineDriver.hxx" #include "GEOMImpl_EllipseDriver.hxx" #include "GEOMImpl_ArcDriver.hxx" +#include "GEOMImpl_ShapeDriver.hxx" #include "GEOMImpl_SketcherDriver.hxx" #include "GEOMImpl_3DSketcherDriver.hxx" @@ -57,6 +58,7 @@ #include "GEOMImpl_ISketcher.hxx" #include "GEOMImpl_I3DSketcher.hxx" #include "GEOMImpl_ICurveParametric.hxx" +#include "GEOMImpl_IIsoline.hxx" #include @@ -1429,3 +1431,71 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::Make3DSketcher (std::listAddObject(GetDocID(), GEOM_ISOLINE); + + //Add a new Spline function for interpolation type + Handle(GEOM_Function) aFunction = + anIsoline->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPE_ISOLINE); + + if (aFunction.IsNull()) { + return NULL; + } + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) { + return NULL; + } + + GEOMImpl_IIsoline aCI (aFunction); + Handle(GEOM_Function) aRefFace = theFace->GetLastFunction(); + + if (aRefFace.IsNull()) { + return NULL; + } + + aCI.SetFace(aRefFace); + aCI.SetIsUIso(IsUIso); + aCI.SetParameter(theParameter); + + //Compute the isoline curve + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump (aFunction) << anIsoline << " = geompy.MakeIsoline( " + << theFace << ", " << IsUIso << ", " << theParameter << " )"; + + SetErrorCode(OK); + return anIsoline; +} diff --git a/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx b/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx index 8bdd6c239..dbad87e06 100644 --- a/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx @@ -94,6 +94,12 @@ class GEOMImpl_ICurvesOperations : public GEOM_IOperations { Handle(GEOM_Object) theWorkingPlane); Standard_EXPORT Handle(GEOM_Object) Make3DSketcherCommand (const char* theCommand); Standard_EXPORT Handle(GEOM_Object) Make3DSketcher (std::list theCoordinates); + + Standard_EXPORT Handle(GEOM_Object) MakeIsoline + (const Handle(GEOM_Object) &theFace, + const bool IsUIso, + const double theParameter); + }; #endif diff --git a/src/GEOMImpl/GEOMImpl_IIsoline.hxx b/src/GEOMImpl/GEOMImpl_IIsoline.hxx new file mode 100755 index 000000000..b1417b16b --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IIsoline.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2013 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. +// +// 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 +// + +//NOTE: This is an interface to a function for the isoline creation algorithm. + +#include "GEOM_Function.hxx" + +#define ISOLINE_ARG_FACE 1 +#define ISOLINE_ARG_U_OR_V 2 +#define ISOLINE_ARG_PARAMETER 3 + +class GEOMImpl_IIsoline +{ + public: + + GEOMImpl_IIsoline(Handle(GEOM_Function) theFunction): _func(theFunction) {} + + void SetFace (Handle(GEOM_Function) theFace) + { _func->SetReference(ISOLINE_ARG_FACE, theFace); } + void SetIsUIso (bool IsUIso) + { _func->SetInteger(ISOLINE_ARG_U_OR_V, IsUIso ? 1 : 0); } + void SetParameter (double theParameter) + { _func->SetReal(ISOLINE_ARG_PARAMETER, theParameter); } + + + Handle(GEOM_Function) GetFace() + { return _func->GetReference(ISOLINE_ARG_FACE); } + bool GetIsUIso() + { return (_func->GetInteger(ISOLINE_ARG_U_OR_V) != 0); } + double GetParameter() { return _func->GetReal(ISOLINE_ARG_PARAMETER ); } + + private: + + Handle(GEOM_Function) _func; +}; diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx index 0ec4b35e6..13df35af1 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx @@ -22,12 +22,14 @@ #include +#include #include #include #include #include #include +#include // OCCT Includes #include @@ -50,6 +52,7 @@ #include #include +#include #include #include @@ -72,6 +75,7 @@ #include #include +#include #include #include #include @@ -531,6 +535,32 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam); if (aME.IsDone()) aShape = aME.Shape(); + } else if (aType == SHAPE_ISOLINE) { + GEOMImpl_IIsoline aII (aFunction); + Handle(GEOM_Function) aRefFace = aII.GetFace(); + TopoDS_Shape aShapeFace = aRefFace->GetValue(); + + if (aShapeFace.ShapeType() == TopAbs_FACE) { + TopoDS_Face aFace = TopoDS::Face(aShapeFace); + bool isUIso = aII.GetIsUIso(); + Standard_Real aParam = aII.GetParameter(); + Standard_Real U1,U2,V1,V2; + + // Construct a real geometric parameter. + aFace.Orientation(TopAbs_FORWARD); + ShapeAnalysis::GetFaceUVBounds(aFace,U1,U2,V1,V2); + + if (isUIso) { + aParam = U1 + (U2 - U1)*aParam; + } else { + aParam = V1 + (V2 - V1)*aParam; + } + + aShape = MakeIsoline(aFace, isUIso, aParam); + } else { + Standard_NullObject::Raise + ("Shape for isoline construction is not a face"); + } } else { } @@ -974,6 +1004,101 @@ TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire, return ResEdge; } +//============================================================================= +/*! + * \brief Returns an isoline for a face. + */ +//============================================================================= + +TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline + (const TopoDS_Face &theFace, + const bool IsUIso, + const double theParameter) const +{ + TopoDS_Shape aResult; + GEOMUtils_Hatcher aHatcher(theFace); + const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV); + + aHatcher.Init(aType, theParameter); + aHatcher.Perform(); + + if (!aHatcher.IsDone()) { + Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure"); + } + + const Handle(TColStd_HArray1OfInteger) &anIndices = + (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices()); + + if (anIndices.IsNull()) { + Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices"); + } + + const Standard_Integer anIsoInd = anIndices->Lower(); + const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd); + + if (aHatchingIndex == 0) { + Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index"); + } + + const Standard_Integer aNbDomains = + aHatcher.GetNbDomains(aHatchingIndex); + + if (aNbDomains < 0) { + Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains"); + } + + // The hatching is performed successfully. Create the 3d Curve. + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace); + Handle(Geom_Curve) anIsoCurve = (IsUIso ? + aSurface->UIso(theParameter) : aSurface->VIso(theParameter)); + Handle(Geom2d_Curve) aPIsoCurve = + aHatcher.GetHatching(aHatchingIndex); + const Standard_Real aTol = Precision::Confusion(); + Standard_Integer anIDom = 1; + Standard_Real aV1; + Standard_Real aV2; + BRep_Builder aBuilder; + Standard_Integer aNbEdges = 0; + + for (; anIDom <= aNbDomains; anIDom++) { + if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) { + // Check first and last parameters. + if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) { + // Create an edge. + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2); + + // Update it with a parametric curve on face. + aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol); + aNbEdges++; + + if (aNbEdges > 1) { + // Result is a compond. + if (aNbEdges == 2) { + // Create a new compound. + TopoDS_Compound aCompound; + + aBuilder.MakeCompound(aCompound); + aBuilder.Add(aCompound, aResult); + aResult = aCompound; + } + + // Add an edge to the compound. + aBuilder.Add(aResult, anEdge); + } else { + // Result is the edge. + aResult = anEdge; + } + } + } + } + + if (aNbEdges == 0) { + Standard_ConstructionError::Raise("MakeIsoline : Empty result"); + } + + return aResult; +} + //================================================================================ /*! * \brief Returns a name of creation operation and names and values of creation parameters @@ -1046,6 +1171,16 @@ GetCreationInformation(std::string& theOperationName, AddParam( theParams, "State", TopAbs_State((int) aCI.GetTolerance() )); break; } + case SHAPE_ISOLINE: + { + GEOMImpl_IIsoline aII (function); + + theOperationName = "ISOLINE"; + AddParam(theParams, "Face", aII.GetFace()); + AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V")); + AddParam(theParams, "Parameter", aII.GetParameter()); + break; + } default: return false; } diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx index 650a16948..e139eadd6 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx @@ -63,6 +63,7 @@ #include class TColStd_SequenceOfExtendedString; +class TopoDS_Face; #include "GEOM_BaseDriver.hxx" @@ -98,6 +99,11 @@ public: // DEFINE_STANDARD_RTTI( GEOMImpl_ShapeDriver ) +private: + + TopoDS_Shape MakeIsoline(const TopoDS_Face &theFace, + const bool IsUIso, + const double theParameter) const; }; diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index 0f092ff3b..5e81208f1 100755 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -111,6 +111,8 @@ #define GEOM_EXPORTXAO 54 +#define GEOM_ISOLINE 55 + //GEOM_Function types #define COPY_WITH_REF 1 @@ -296,6 +298,7 @@ #define EDGE_WIRE 11 #define EDGE_CURVE_LENGTH 12 #define SHAPES_ON_SHAPE 13 +#define SHAPE_ISOLINE 14 #define ARCHIMEDE_TYPE 1 diff --git a/src/GEOMUtils/CMakeLists.txt b/src/GEOMUtils/CMakeLists.txt index 9993ff947..0ad8f6724 100755 --- a/src/GEOMUtils/CMakeLists.txt +++ b/src/GEOMUtils/CMakeLists.txt @@ -47,11 +47,13 @@ SET(_link_LIBRARIES SET(GEOMUtils_HEADERS GEOMUtils.hxx + GEOMUtils_Hatcher.hxx ) # --- sources --- SET(GEOMUtils_SOURCES GEOMUtils.cxx + GEOMUtils_Hatcher.cxx ) # --- rules --- diff --git a/src/GEOMUtils/GEOMUtils_Hatcher.cxx b/src/GEOMUtils/GEOMUtils_Hatcher.cxx new file mode 100755 index 000000000..ee5c3af26 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_Hatcher.cxx @@ -0,0 +1,398 @@ +// Copyright (C) 2007-2013 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. +// +// 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 +// + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static Standard_Real IntersectorConfusion = 1.e-10; // -8; +static Standard_Real IntersectorTangency = 1.e-10; // -8; +static Standard_Real HatcherConfusion2d = 1.e-8; +static Standard_Real HatcherConfusion3d = 1.e-8; +// VTK uses float numbers - Precision::Infinite() is double and +// can not be accepted. +static float InfiniteValue = 1e38; + +//======================================================================= +//function : GEOMUtils_Hatcher +//purpose : +//======================================================================= +GEOMUtils_Hatcher::GEOMUtils_Hatcher(const TopoDS_Face &theFace) +: myHatcher(Geom2dHatch_Intersector (IntersectorConfusion, IntersectorTangency), + HatcherConfusion2d, HatcherConfusion3d, + Standard_True, Standard_False), + myFace (theFace), + myIsDone (Standard_False), + myUMin (0.), + myUMax (0.), + myVMin (0.), + myVMax (0.) +{ + // Get bounds. + BRepTools::UVBounds (theFace, myUMin, myUMax, myVMin, myVMax); + + Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (myUMin); + Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (myUMax); + Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (myVMin); + Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (myVMax); + + if (InfiniteUMin && InfiniteUMax) { + myUMin = - InfiniteValue; + myUMax = InfiniteValue; + } else if (InfiniteUMin) { + myUMin = myUMax - InfiniteValue; + } else if (InfiniteUMax) { + myUMax = myUMin + InfiniteValue; + } + + if (InfiniteVMin && InfiniteVMax) { + myVMin = - InfiniteValue; + myVMax = InfiniteValue; + } else if (InfiniteVMin) { + myVMin = myVMax - InfiniteValue; + } else if (InfiniteVMax) { + myVMax = myVMin + InfiniteValue; + } + + // Add edges + TopExp_Explorer anExpEdges(theFace, TopAbs_EDGE); + const Standard_Real aParamTol = Precision::PConfusion(); + + for (; anExpEdges.More(); anExpEdges.Next()) { + const TopoDS_Edge& anEdge = TopoDS::Edge (anExpEdges.Current()); + Standard_Real U1, U2; + const Handle(Geom2d_Curve) PCurve = + BRep_Tool::CurveOnSurface (anEdge, theFace, U1, U2); + + if (PCurve.IsNull()) { + continue; + } + + if (U1 == U2) { + continue; + } + + //-- Test if a TrimmedCurve is necessary + if(Abs(PCurve->FirstParameter() - U1) <= aParamTol && + Abs(PCurve->LastParameter() - U2) <= aParamTol) { + myHatcher.AddElement(PCurve, anEdge.Orientation()); + } else { + if (!PCurve->IsPeriodic()) { + Handle(Geom2d_TrimmedCurve) TrimPCurve = + Handle(Geom2d_TrimmedCurve)::DownCast(PCurve); + + if (!TrimPCurve.IsNull()) { + Handle(Geom2d_Curve) aBasisCurve = TrimPCurve->BasisCurve(); + + if (aBasisCurve->FirstParameter() - U1 > aParamTol || + U2 - aBasisCurve->LastParameter() > aParamTol) { + myHatcher.AddElement (PCurve, anEdge.Orientation()); + return; + } + } else { + if (PCurve->FirstParameter() - U1 > aParamTol) { + U1 = PCurve->FirstParameter(); + } + if (U2 - PCurve->LastParameter() > aParamTol) { + U2=PCurve->LastParameter(); + } + } + } + + Handle (Geom2d_TrimmedCurve) TrimPCurve = + new Geom2d_TrimmedCurve (PCurve, U1, U2); + + myHatcher.AddElement (TrimPCurve, anEdge.Orientation()); + } + } +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void GEOMUtils_Hatcher::Init(const Standard_Integer theNbIsos) +{ + Init(theNbIsos, theNbIsos); +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void GEOMUtils_Hatcher::Init(const Standard_Integer theNbIsoU, + const Standard_Integer theNbIsoV) +{ + // Initialize data. + Clear(); + + if (theNbIsoU > 0 || theNbIsoV > 0) { + Standard_Integer IIso; + Standard_Real DeltaU = Abs (myUMax - myUMin); + Standard_Real DeltaV = Abs (myVMax - myVMin); + Standard_Real confusion = Min (DeltaU, DeltaV) * myHatcher.Confusion3d(); + + myHatcher.Confusion3d (confusion); + + if (theNbIsoU > 0) { + myUPrm = new TColStd_HArray1OfReal (1, theNbIsoU); + myUInd = new TColStd_HArray1OfInteger(1, theNbIsoU, 0); + + Standard_Real StepU = DeltaU / (Standard_Real) theNbIsoU; + + if (StepU > confusion) { + Standard_Real UPrm = myUMin + StepU / 2.; + gp_Dir2d Dir (0., 1.); + + for (IIso = 1; IIso <= theNbIsoU; IIso++) { + myUPrm->SetValue(IIso, UPrm); + gp_Pnt2d Ori (UPrm, 0.); + Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)); + myUInd->SetValue(IIso, myHatcher.AddHatching(HCur)); + UPrm += StepU; + } + } + } + + if (theNbIsoV > 0) { + myVPrm = new TColStd_HArray1OfReal (1, theNbIsoV); + myVInd = new TColStd_HArray1OfInteger(1, theNbIsoV, 0); + + Standard_Real StepV = DeltaV / (Standard_Real) theNbIsoV; + + if (StepV > confusion) { + Standard_Real VPrm = myVMin + StepV / 2.; + gp_Dir2d Dir (1., 0.); + + for (IIso = 1; IIso <= theNbIsoV; IIso++) { + myVPrm->SetValue(IIso, VPrm); + gp_Pnt2d Ori (0., VPrm); + Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)); + myVInd->SetValue(IIso, myHatcher.AddHatching(HCur)); + VPrm += StepV; + } + } + } + } +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void GEOMUtils_Hatcher::Init(const GeomAbs_IsoType theIsoType, + const Standard_Real theParameter) +{ + // Initialize data. + Clear(); + + if (theIsoType == GeomAbs_IsoU || theIsoType == GeomAbs_IsoV) { + const Standard_Boolean isIsoU = (theIsoType == GeomAbs_IsoU); + Handle(TColStd_HArray1OfReal) &aPrm = (isIsoU ? myUPrm : myVPrm); + Handle(TColStd_HArray1OfInteger) &anInd = (isIsoU ? myUInd : myVInd); + Handle(Geom2d_Line) aLine; + + aPrm = new TColStd_HArray1OfReal (1, 1); + anInd = new TColStd_HArray1OfInteger(1, 1); + aPrm->SetValue(1, theParameter); + + if (isIsoU) { + // U-isoline + gp_Dir2d aDir (0., 1.); + gp_Pnt2d anOri(theParameter, 0.); + + aLine = new Geom2d_Line(anOri, aDir); + } else { + // V-isoline + gp_Dir2d aDir (1., 0.); + gp_Pnt2d anOri(0., theParameter); + + aLine = new Geom2d_Line(anOri, aDir); + } + + Geom2dAdaptor_Curve aGACurve (aLine); + + anInd->SetValue(1, myHatcher.AddHatching(aGACurve)); + } +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void GEOMUtils_Hatcher::Perform() +{ + myHatcher.Trim(); + + // Compute domains. + Standard_Integer i; + Standard_Integer anIndex; + + if (myUInd.IsNull() == Standard_False) { + for (i = myUInd->Lower() ; i <= myUInd->Upper() ; i++) { + anIndex = myUInd->Value(i); + + if (anIndex != 0) { + if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) { + myHatcher.ComputeDomains(anIndex); + + if (!myIsDone) { + myIsDone = (myHatcher.NbDomains(anIndex) > 0); + } + } + } + } + } + + if (myVInd.IsNull() == Standard_False) { + for (i = myVInd->Lower() ; i <= myVInd->Upper() ; i++) { + anIndex = myVInd->Value(i); + + if (anIndex != 0) { + if (myHatcher.TrimDone(anIndex) && !myHatcher.TrimFailed(anIndex)) { + myHatcher.ComputeDomains(anIndex); + + if (!myIsDone) { + myIsDone = (myHatcher.NbDomains(anIndex) > 0); + } + } + } + } + } +} + +//======================================================================= +//function : GetNbDomains +//purpose : +//======================================================================= +Standard_Integer GEOMUtils_Hatcher::GetNbDomains + (const Standard_Integer theHatchingIndex) const +{ + Standard_Integer aResult = -1; + + if (myIsDone && myHatcher.IsDone(theHatchingIndex)) { + aResult = myHatcher.NbDomains(theHatchingIndex); + } + + return aResult; +} + +//======================================================================= +//function : GetDomain +//purpose : +//======================================================================= +Standard_Boolean GEOMUtils_Hatcher::GetDomain + (const Standard_Integer theHatchingIndex, + const Standard_Integer theDomainIndex, + Standard_Real &theParam1, + Standard_Real &theParam2) const +{ + Standard_Boolean isOK = Standard_False; + + if (theDomainIndex > 0) { + const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex); + + if (theDomainIndex <= aNbDomains) { + const HatchGen_Domain& aDomain = + myHatcher.Domain (theHatchingIndex, theDomainIndex); + + if (aDomain.HasFirstPoint()) { + theParam1 = aDomain.FirstPoint().Parameter(); + } else { + theParam1 = myVMin - InfiniteValue; + } + + if (aDomain.HasSecondPoint()) { + theParam2 = aDomain.SecondPoint().Parameter(); + } else { + theParam2 = myVMax + InfiniteValue; + } + + isOK = Standard_True; + } + } + + return isOK; +} + +//======================================================================= +//function : IsDomainInfinite +//purpose : +//======================================================================= +Standard_Boolean GEOMUtils_Hatcher::IsDomainInfinite + (const Standard_Integer theHatchingIndex, + const Standard_Integer theDomainIndex) const +{ + Standard_Boolean isInfinite = Standard_False; + + if (theDomainIndex > 0) { + const Standard_Integer aNbDomains = GetNbDomains(theHatchingIndex); + + if (theDomainIndex <= aNbDomains) { + const HatchGen_Domain& aDomain = + myHatcher.Domain (theHatchingIndex, theDomainIndex); + + if (!aDomain.HasFirstPoint() || !aDomain.HasSecondPoint()) { + isInfinite = Standard_True; + } + } + } + + return isInfinite; +} + +//======================================================================= +//function : GetHatching +//purpose : +//======================================================================= +const Handle(Geom2d_Curve) &GEOMUtils_Hatcher::GetHatching + (const Standard_Integer theHatchingIndex) const +{ + const Geom2dAdaptor_Curve &aGACurve = + myHatcher.HatchingCurve(theHatchingIndex); + + return aGACurve.Curve(); +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void GEOMUtils_Hatcher::Clear() +{ + myIsDone = Standard_False; + myUPrm.Nullify(); + myVPrm.Nullify(); + myUInd.Nullify(); + myVInd.Nullify(); + myHatcher.ClrHatchings(); +} diff --git a/src/GEOMUtils/GEOMUtils_Hatcher.hxx b/src/GEOMUtils/GEOMUtils_Hatcher.hxx new file mode 100755 index 000000000..2d3c13697 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_Hatcher.hxx @@ -0,0 +1,208 @@ +// Copyright (C) 2007-2013 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. +// +// 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 +// + +#ifndef _GEOMUtils_Hatcher_HXX_ +#define _GEOMUtils_Hatcher_HXX_ + + +#include +#include +#include +#include +#include + + +/*! + * This class represents a hatcher for topological faces. + */ +class GEOMUtils_Hatcher { + +public: + + /** + * Constructor. Initializes the object with the face. + */ + Standard_EXPORT GEOMUtils_Hatcher(const TopoDS_Face &theFace); + + /** + * This method initializes the hatcher with hatchings. + * + * \param theNbIsos the number of U- and V-isolines. + */ + Standard_EXPORT void Init(const Standard_Integer theNbIsos); + + /** + * This method initializes the hatcher with hatchings. + * + * \param theNbIsoU the number of U-isolines. + * \param theNbIsoV the number of V-isolines. + */ + Standard_EXPORT void Init(const Standard_Integer theNbIsoU, + const Standard_Integer theNbIsoV); + + /** + * This method initializes the hatcher with a hatching. + * + * \param theIsoType the isoline type. + * \param theParameter the isoline parameter. + */ + Standard_EXPORT void Init(const GeomAbs_IsoType theIsoType, + const Standard_Real theParameter); + + /** + * Compute hatching domatins. + */ + Standard_EXPORT void Perform(); + + /** + * This method returns true if at least one hatching's domains + * are computed successfully. + * + * \return Standard_True is case of success. + */ + Standard_Boolean IsDone() const + { return myIsDone; } + + /** + * This method returns the initial face. + * + * \return the initial face. + */ + const TopoDS_Face &GetFace() const + { return myFace; } + + /** + * This method returns the number of domains for a particular hatching. + * If the operation is not done or there is no real hatching for + * a particular index a negative value is returned. + * + * \param theHatchingIndex the hatching index. + * \return the number of domains computed for the hatching. + */ + Standard_EXPORT Standard_Integer GetNbDomains + (const Standard_Integer theHatchingIndex) const; + + /** + * This method returns the domputed domain range computed for a particular + * hatching. theDomainIndex should be in the range [1..GetNbDomains]. + * + * \param theHatchingIndex the hatching index. + * \param theDomainIndex the domain index for the particular hatching. + * \param theParam1 (output) the first parameter of the domain. + * \param theParam2 (output) the last parameter of the domain. + * \return Standard_True in case of success; Standard_False otherwise. + */ + Standard_EXPORT Standard_Boolean GetDomain + (const Standard_Integer theHatchingIndex, + const Standard_Integer theDomainIndex, + Standard_Real &theParam1, + Standard_Real &theParam2) const; + + /** + * This method returns Standard_True if a domain has infinite first + * or last parameter. + * + * \param theHatchingIndex the hatching index. + * \param theDomainIndex the domain index for the particular hatching. + * \return Standard_True if a domain is infinite; Standard_False otherwise. + */ + Standard_EXPORT Standard_Boolean IsDomainInfinite + (const Standard_Integer theHatchingIndex, + const Standard_Integer theDomainIndex) const; + + /** + * This method returns the reference to OCCT hatcher. + * + * \return the reference to OCCT hatcher. + */ + const Geom2dHatch_Hatcher &GetHatcher() const + { return myHatcher; } + + /** + * This method returns the array of indices of U-isoline hatchings. + * Can be null if the object is initialized by 0 U-isolines. + * + * \return the array of U-isoline hatching indices. + */ + const Handle(TColStd_HArray1OfInteger) &GetUIndices() const + { return myUInd; } + + /** + * This method returns the array of indices of V-isoline hatchings. + * Can be null if the object is initialized by 0 V-isolines. + * + * \return the array of V-isoline hatching indices. + */ + const Handle(TColStd_HArray1OfInteger) &GetVIndices() const + { return myVInd; } + + /** + * This method returns the array of parameters of U-isoline hatchings. + * Can be null if the object is initialized by 0 U-isolines. + * + * \return the array of U-isoline hatching parameters. + */ + const Handle(TColStd_HArray1OfReal) &GetUParams() const + { return myUPrm; } + + /** + * This method returns the array of parameters of V-isoline hatchings. + * Can be null if the object is initialized by 0 V-isolines. + * + * \return the array of V-isoline hatching parameters. + */ + const Handle(TColStd_HArray1OfReal) &GetVParams() const + { return myVPrm; } + + /** + * This method returns a hatching curve by its index. + * If the curve is not found null handle is returned. + * + * \param theHatchingIndex the hatching curve index. + */ + const Handle(Geom2d_Curve) &GetHatching + (const Standard_Integer theHatchingIndex) const; + +protected: + + /** + * This method clears all hatchings data. + */ + void Clear(); + +private: + + Geom2dHatch_Hatcher myHatcher; + TopoDS_Face myFace; + Standard_Boolean myIsDone; + Standard_Real myUMin; + Standard_Real myUMax; + Standard_Real myVMin; + Standard_Real myVMax; + Handle(TColStd_HArray1OfReal) myUPrm; + Handle(TColStd_HArray1OfReal) myVPrm; + Handle(TColStd_HArray1OfInteger) myUInd; + Handle(TColStd_HArray1OfInteger) myVInd; + +}; + +#endif diff --git a/src/GEOM_I/GEOM_ICurvesOperations_i.cc b/src/GEOM_I/GEOM_ICurvesOperations_i.cc index 1a802dc52..26423df74 100644 --- a/src/GEOM_I/GEOM_ICurvesOperations_i.cc +++ b/src/GEOM_I/GEOM_ICurvesOperations_i.cc @@ -550,6 +550,32 @@ GEOM::GEOM_Object_ptr GEOM_ICurvesOperations_i::MakeCurveParametricNew return GetObject(anObject); } +//============================================================================= +/*! + * MakeIsoline + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_ICurvesOperations_i::MakeIsoline + (GEOM::GEOM_Object_ptr theFace, + CORBA::Boolean IsUIsoline, + double theParameter) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + Handle(GEOM_Object) aFace = GetObjectImpl(theFace); + + // Make isoline + Handle(GEOM_Object) anObject = + GetOperations()->MakeIsoline(aFace, IsUIsoline, theParameter); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * MakeSketcher diff --git a/src/GEOM_I/GEOM_ICurvesOperations_i.hh b/src/GEOM_I/GEOM_ICurvesOperations_i.hh index f91e7c41c..cae0cbecf 100644 --- a/src/GEOM_I/GEOM_ICurvesOperations_i.hh +++ b/src/GEOM_I/GEOM_ICurvesOperations_i.hh @@ -100,6 +100,10 @@ class GEOM_I_EXPORT GEOM_ICurvesOperations_i : double theParamMin, double theParamMax, CORBA::Long theParamNbStep, GEOM::curve_type theCurveType); + GEOM::GEOM_Object_ptr MakeIsoline (GEOM::GEOM_Object_ptr theFace, + CORBA::Boolean IsUIsoline, + double theParameter); + GEOM::GEOM_Object_ptr MakeSketcher (const char* theCommand, const GEOM::ListOfDouble& theWorkingPlane); GEOM::GEOM_Object_ptr MakeSketcherOnPlane (const char* theCommand, GEOM::GEOM_Object_ptr theWorkingPlane); diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index 36e6e0aa7..e5caf3d32 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -188,6 +188,9 @@ def TestAll (geompy, math): prism1_faces[5], prism1_faces[2]]) Solid = geompy.MakeSolid([Shell1]) #(List of GEOM_Object)->GEOM_Object + # Create Isoline + Isoline = geompy.MakeIsoline(Face1, True, 0.5) #(1 GEOM_Object, Boolean, Double)->GEOM_Object + ShapeListCompound = [] i = 0 while i <= 3 : @@ -395,6 +398,8 @@ def TestAll (geompy, math): id_Disk3 = geompy.addToStudy(Disk3, "Disk OXY Radius") id_Shell = geompy.addToStudy(Shell, "Shell") + id_Isoline = geompy.addToStudy(Isoline, "Isoline") + id_p_on_face = geompy.addToStudy(p_on_face, "Vertex on Face (0.1, 0.8)") id_p_on_face2 = geompy.addToStudy(p_on_face2, "Vertex on Face at(0., 0., 0.)") id_p_on_face3 = geompy.addToStudy(p_on_face3, "Vertex inside Face") diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index d26f3c665..a0d60cb5f 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -2300,6 +2300,47 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): self._autoPublish(anObj, theName, "curve") return anObj + ## Create an isoline curve on a face. + # @param theFace the face for which an isoline is created. + # @param IsUIsoline True for U-isoline creation; False for V-isoline + # creation. + # @param theParameter the U parameter for U-isoline or V parameter + # for V-isoline. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the created isoline edge or + # a compound of edges. + # + # @ref tui_creation_curve "Example" + def MakeIsoline(self, theFace, IsUIsoline, theParameter, theName=None): + """ + Create an isoline curve on a face. + + Parameters: + theFace the face for which an isoline is created. + IsUIsoline True for U-isoline creation; False for V-isoline + creation. + theParameter the U parameter for U-isoline or V parameter + for V-isoline. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the created isoline edge or a + compound of edges. + """ + # Example: see GEOM_TestAll.py + anObj = self.CurvesOp.MakeIsoline(theFace, IsUIsoline, theParameter) + RaiseIfFailed("MakeIsoline", self.CurvesOp) + if IsUIsoline: + self._autoPublish(anObj, theName, "U-Isoline") + else: + self._autoPublish(anObj, theName, "V-Isoline") + return anObj + # end of l4_curves ## @} diff --git a/src/OBJECT/CMakeLists.txt b/src/OBJECT/CMakeLists.txt index fb595ae69..7f8ac53dd 100755 --- a/src/OBJECT/CMakeLists.txt +++ b/src/OBJECT/CMakeLists.txt @@ -34,6 +34,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_BINARY_DIR}/idl ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/src/OCC2VTK + ${PROJECT_SOURCE_DIR}/src/GEOMUtils ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -55,6 +56,7 @@ SET(_link_LIBRARIES ${QT_QTCORE_LIBRARY} vtkRenderingMatplotlib vtkInteractionStyle + GEOMUtils #${VTK_LIBRARIES} ) diff --git a/src/OBJECT/GEOM_OCCReader.cxx b/src/OBJECT/GEOM_OCCReader.cxx index 334275ef6..84dbf3c9c 100644 --- a/src/OBJECT/GEOM_OCCReader.cxx +++ b/src/OBJECT/GEOM_OCCReader.cxx @@ -27,6 +27,8 @@ #include "GEOM_OCCReader.h" +#include + // VTK Includes #include #include @@ -37,42 +39,21 @@ #include // OpenCASCADE Includes -#include +#include #include #include #include +#include #include #include -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #include "utilities.h" -#define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) ) -#define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) ) - -// Constante for iso building -static Standard_Real IntersectorConfusion = 1.e-10 ; // -8 ; -static Standard_Real IntersectorTangency = 1.e-10 ; // -8 ; -static Standard_Real HatcherConfusion2d = 1.e-8 ; -static Standard_Real HatcherConfusion3d = 1.e-8 ; - static Standard_Integer lastVTKpoint = 0; static Standard_Integer PlotCount = 0; static Standard_Real IsoRatio = 1.001; @@ -219,7 +200,7 @@ void GEOM_OCCReader::TransferFaceWData(const TopoDS_Face& aFace, { TopoDS_Face aCopyFace = aFace; aCopyFace.Orientation (TopAbs_FORWARD); - createISO(aCopyFace,Precision::Infinite(),1,Pts,Cells); + createISO(aCopyFace,1,Pts,Cells); } //======================================================================= @@ -227,225 +208,100 @@ void GEOM_OCCReader::TransferFaceWData(const TopoDS_Face& aFace, // Purpose : Create ISO for Face Wireframe representation //======================================================================= -void GEOM_OCCReader::createISO (const TopoDS_Face& TopologicalFace, - const Standard_Real Infinite, - const Standard_Integer NbIsos, - vtkPoints* Pts, - vtkCellArray* Cell) +void GEOM_OCCReader::createISO (const TopoDS_Face &TopologicalFace, + const Standard_Integer NbIsos, + vtkPoints *Pts, + vtkCellArray *Cell) { - Geom2dHatch_Hatcher aHatcher (Geom2dHatch_Intersector (IntersectorConfusion, - IntersectorTangency), - HatcherConfusion2d, - HatcherConfusion3d, - Standard_True, - Standard_False); - - Standard_Real myInfinite,myUMin,myUMax,myVMin,myVMax; - //myInfinite = Precision::Infinite(); - myInfinite = 1e38; // VTK uses float numbers - Precision::Infinite() is double and can not be accepted. - - Standard_Integer myNbDom; - TColStd_Array1OfReal myUPrm(1, NbIsos),myVPrm(1, NbIsos); - TColStd_Array1OfInteger myUInd(1, NbIsos),myVInd(1, NbIsos); - - myUInd.Init(0); - myVInd.Init(0); - - //----------------------------------------------------------------------- - // If the Min Max bounds are infinite, there are bounded to Infinite - // value. - //----------------------------------------------------------------------- - - BRepTools::UVBounds (TopologicalFace, myUMin, myUMax, myVMin, myVMax) ; - Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (myUMin) ; - Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (myUMax) ; - Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (myVMin) ; - Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (myVMax) ; - if (InfiniteUMin && InfiniteUMax) { - myUMin = - myInfinite ; - myUMax = myInfinite ; - } else if (InfiniteUMin) { - myUMin = myUMax - myInfinite ; - } else if (InfiniteUMax) { - myUMax = myUMin + myInfinite ; - } - if (InfiniteVMin && InfiniteVMax) { - myVMin = - myInfinite ; - myVMax = myInfinite ; - } else if (InfiniteVMin) { - myVMin = myVMax - myInfinite ; - } else if (InfiniteVMax) { - myVMax = myVMin + myInfinite ; - } - - //----------------------------------------------------------------------- - // Retreiving the edges and loading them into the hatcher. - //----------------------------------------------------------------------- + GEOMUtils_Hatcher aHatcher(TopologicalFace); - TopExp_Explorer ExpEdges ; - for (ExpEdges.Init (TopologicalFace, TopAbs_EDGE) ; ExpEdges.More() ; ExpEdges.Next()) { - const TopoDS_Edge& TopologicalEdge = TopoDS::Edge (ExpEdges.Current()) ; - Standard_Real U1, U2 ; - const Handle(Geom2d_Curve) PCurve = BRep_Tool::CurveOnSurface (TopologicalEdge, TopologicalFace, U1, U2) ; + aHatcher.Init(NbIsos); + aHatcher.Perform(); - if ( PCurve.IsNull() ) { - return; - } + if (aHatcher.IsDone()) { + // Push iso lines in vtk kernel + Standard_Integer pt_start_idx = 0; - if ( U1==U2) { - return; - } - - //-- Test if a TrimmedCurve is necessary - if( Abs(PCurve->FirstParameter()-U1)<= Precision::PConfusion() - && Abs(PCurve->LastParameter()-U2)<= Precision::PConfusion()) { - aHatcher.AddElement (PCurve, TopologicalEdge.Orientation()) ; - } - else { - if (!PCurve->IsPeriodic()) { - Handle (Geom2d_TrimmedCurve) TrimPCurve =Handle(Geom2d_TrimmedCurve)::DownCast(PCurve); - if (!TrimPCurve.IsNull()) { - if (TrimPCurve->BasisCurve()->FirstParameter()-U1 > Precision::PConfusion() || - U2-TrimPCurve->BasisCurve()->LastParameter() > Precision::PConfusion()) { - aHatcher.AddElement (PCurve, TopologicalEdge.Orientation()) ; - return; - } - } - else { - if (PCurve->FirstParameter()-U1 > Precision::PConfusion()){ - U1=PCurve->FirstParameter(); - } - if (U2-PCurve->LastParameter() > Precision::PConfusion()){ - U2=PCurve->LastParameter(); - } - } - } - Handle (Geom2d_TrimmedCurve) TrimPCurve = new Geom2d_TrimmedCurve (PCurve, U1, U2) ; - aHatcher.AddElement (TrimPCurve, TopologicalEdge.Orientation()) ; - } + createIsos(aHatcher, Standard_True, pt_start_idx, Pts, Cell); + createIsos(aHatcher, Standard_False, pt_start_idx, Pts, Cell); } +} +//======================================================================= +// Function : createIsos +// Purpose : Create isolines obtained from hatcher. +//======================================================================= +void GEOM_OCCReader::createIsos(const GEOMUtils_Hatcher &theHatcher, + const Standard_Boolean IsUIso, + Standard_Integer &pt_start_idx, + vtkPoints *Pts, + vtkCellArray *Cell) +{ + // Push iso lines in vtk kernel + Handle(TColStd_HArray1OfInteger) anIndices; + Handle(TColStd_HArray1OfReal) aParams; - //----------------------------------------------------------------------- - // Loading and trimming the hatchings. - //----------------------------------------------------------------------- - - Standard_Integer IIso ; - Standard_Real DeltaU = Abs (myUMax - myUMin) ; - Standard_Real DeltaV = Abs (myVMax - myVMin) ; - Standard_Real confusion = Min (DeltaU, DeltaV) * HatcherConfusion3d ; - aHatcher.Confusion3d (confusion) ; - - Standard_Real StepU = DeltaU / (Standard_Real) NbIsos ; - if (StepU > confusion) { - Standard_Real UPrm = myUMin + StepU / 2. ; - gp_Dir2d Dir (0., 1.) ; - for (IIso = 1 ; IIso <= NbIsos ; IIso++) { - myUPrm(IIso) = UPrm ; - gp_Pnt2d Ori (UPrm, 0.) ; - Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ; - myUInd(IIso) = aHatcher.AddHatching (HCur) ; - UPrm += StepU ; - } - } - - Standard_Real StepV = DeltaV / (Standard_Real) NbIsos ; - if (StepV > confusion) { - Standard_Real VPrm = myVMin + StepV / 2. ; - gp_Dir2d Dir (1., 0.) ; - for (IIso = 1 ; IIso <= NbIsos ; IIso++) { - myVPrm(IIso) = VPrm ; - gp_Pnt2d Ori (0., VPrm) ; - Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ; - myVInd(IIso) = aHatcher.AddHatching (HCur) ; - VPrm += StepV ; - } + if (IsUIso) { + // U-isolines + anIndices = theHatcher.GetUIndices(); + aParams = theHatcher.GetUParams(); + } else { + // V-isolines + anIndices = theHatcher.GetVIndices(); + aParams = theHatcher.GetVParams(); } - //----------------------------------------------------------------------- - // Computation. - //----------------------------------------------------------------------- - - aHatcher.Trim() ; - - myNbDom = 0 ; - for (IIso = 1 ; IIso <= NbIsos ; IIso++) { - Standard_Integer Index ; - - Index = myUInd(IIso) ; - if (Index != 0) { - if (aHatcher.TrimDone (Index) && !aHatcher.TrimFailed (Index)) { - aHatcher.ComputeDomains (Index); - if (aHatcher.IsDone (Index)) myNbDom = myNbDom + aHatcher.NbDomains (Index) ; - } - } - - Index = myVInd(IIso) ; - if (Index != 0) { - if (aHatcher.TrimDone (Index) && !aHatcher.TrimFailed (Index)) { - aHatcher.ComputeDomains (Index); - if (aHatcher.IsDone (Index)) myNbDom = myNbDom + aHatcher.NbDomains (Index) ; - } + if (anIndices.IsNull() || aParams.IsNull()) { + if (IsUIso) { + MESSAGE("GEOMUtils_Hatcher: null U-isoline indices") + } else { + MESSAGE("GEOMUtils_Hatcher: null V-isoline indices") } - } + } else { + const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV); + Standard_Integer anIsoInd = anIndices->Lower(); + + for (; anIsoInd <= anIndices->Upper(); anIsoInd++) { + const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd); + + if (aHatchingIndex != 0) { + const Standard_Real aParam = aParams->Value(anIsoInd); + const Standard_Integer aNbDomains = + theHatcher.GetNbDomains(aHatchingIndex); + + if (aNbDomains < 0) { + if (IsUIso) { + MESSAGE("GEOMUtils_Hatcher: U iso of parameter: "< #include -#include +#include #include #include @@ -94,10 +96,16 @@ class GEOM_OBJECT_EXPORT GEOM_OCCReader : public vtkAlgorithm { vtkCellArray* Cells); void createISO(const TopoDS_Face &, - double, int, + int, vtkPoints* Pts, vtkCellArray* Cells); - + + void createIsos(const GEOMUtils_Hatcher &theHatcher, + const Standard_Boolean IsUIso, + Standard_Integer &pt_start_idx, + vtkPoints *Pts, + vtkCellArray *Cell); + void DrawIso(GeomAbs_IsoType aType, Standard_Real PParm, Standard_Real p1, diff --git a/src/OCC2VTK/CMakeLists.txt b/src/OCC2VTK/CMakeLists.txt index 67ae3bf9d..3c477f574 100755 --- a/src/OCC2VTK/CMakeLists.txt +++ b/src/OCC2VTK/CMakeLists.txt @@ -25,6 +25,7 @@ INCLUDE_DIRECTORIES( ${KERNEL_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/src/GEOMUtils ) # additional preprocessor / compiler flags @@ -38,7 +39,8 @@ SET(_link_LIBRARIES ${CAS_KERNEL} ${CAS_TKMesh} ${CAS_TKTopAlgo} ${CAS_MODELER} - ${KERNEL_SALOMELocalTrace} + ${KERNEL_SALOMELocalTrace} + GEOMUtils ) # --- headers --- diff --git a/src/OCC2VTK/GEOM_WireframeFace.cxx b/src/OCC2VTK/GEOM_WireframeFace.cxx index 981bc24e0..f91c0ef78 100755 --- a/src/OCC2VTK/GEOM_WireframeFace.cxx +++ b/src/OCC2VTK/GEOM_WireframeFace.cxx @@ -17,7 +17,9 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include "GEOM_WireframeFace.h" +#include "GEOM_WireframeFace.h" + +#include #include @@ -29,26 +31,9 @@ #include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #include +#include +#include vtkStandardNewMacro(GEOM_WireframeFace); @@ -116,217 +101,80 @@ OCC2VTK(const TopoDS_Face& theFace, CreateIso(aFace,theNbIso,theDiscret,thePolyData,thePts); } -void -GEOM_WireframeFace:: +void +GEOM_WireframeFace:: CreateIso(const TopoDS_Face& theFace, - const int theNbIso[2], - const int theDiscret, + const int theNbIso[2], + const int theDiscret, vtkPolyData* thePolyData, vtkPoints* thePts) { - // Constants for iso building - static Standard_Real INTERSECTOR_CONFUSION = 1.e-10 ; // -8 ; - static Standard_Real INTERSECTOR_TANGENCY = 1.e-10 ; // -8 ; - - static Standard_Real HATHCER_CONFUSION_2D = 1.e-8 ; - static Standard_Real HATHCER_CONFUSION_3D = 1.e-8 ; - - Geom2dHatch_Hatcher - aHatcher(Geom2dHatch_Intersector(INTERSECTOR_CONFUSION, - INTERSECTOR_TANGENCY), - HATHCER_CONFUSION_2D, - HATHCER_CONFUSION_3D, - Standard_True, - Standard_False); - - Standard_Real anUMin, anUMax, aVMin, aVMax; - TColStd_Array1OfReal anUPrm(0, theNbIso[0]), aVPrm(0, theNbIso[1]); - TColStd_Array1OfInteger anUInd(0, theNbIso[0]), aVInd(0, theNbIso[1]); - - anUInd.Init(0); - aVInd.Init(0); - - //----------------------------------------------------------------------- - // If the Min Max bounds are infinite, there are bounded to Infinite - // value. - //----------------------------------------------------------------------- - BRepTools::UVBounds(theFace, anUMin, anUMax, aVMin, aVMax) ; - Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (anUMin) ; - Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (anUMax) ; - Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (aVMin) ; - Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (aVMax) ; - - static float VTKINFINITE = 1.0E38; - if(InfiniteUMin && InfiniteUMax){ - anUMin = - VTKINFINITE ; - anUMax = VTKINFINITE ; - }else if(InfiniteUMin){ - anUMin = anUMax - VTKINFINITE ; - }else if(InfiniteUMax){ - anUMax = anUMin + VTKINFINITE ; - } + GEOMUtils_Hatcher aHatcher(theFace); - if(InfiniteVMin && InfiniteVMax){ - aVMin = - VTKINFINITE ; - aVMax = VTKINFINITE ; - }else if(InfiniteVMin){ - aVMin = aVMax - VTKINFINITE ; - }else if(InfiniteVMax){ - aVMax = aVMin + VTKINFINITE ; - } + aHatcher.Init(theNbIso[0], theNbIso[1]); + aHatcher.Perform(); - //----------------------------------------------------------------------- - // Retreiving the edges and loading them into the hatcher. - //----------------------------------------------------------------------- - TopExp_Explorer ExpEdges(theFace, TopAbs_EDGE); - for(; ExpEdges.More(); ExpEdges.Next()){ - const TopoDS_Edge& anEdge = TopoDS::Edge(ExpEdges.Current()); - Standard_Real U1, U2 ; - const Handle(Geom2d_Curve) PCurve = - BRep_Tool::CurveOnSurface(anEdge, theFace, U1, U2) ; - - if(PCurve.IsNull() || U1 == U2) - return; - - //-- Test if a TrimmedCurve is necessary - if(Abs(PCurve->FirstParameter()-U1) <= Precision::PConfusion() && - Abs(PCurve->LastParameter()-U2) <= Precision::PConfusion()) - { - aHatcher.AddElement(PCurve, anEdge.Orientation()) ; - }else{ - if(!PCurve->IsPeriodic()){ - Handle(Geom2d_TrimmedCurve) TrimPCurve = - Handle(Geom2d_TrimmedCurve)::DownCast(PCurve); - if(!TrimPCurve.IsNull()){ - Handle_Geom2d_Curve aBasisCurve = TrimPCurve->BasisCurve(); - if(aBasisCurve->FirstParameter()-U1 > Precision::PConfusion() || - U2-aBasisCurve->LastParameter() > Precision::PConfusion()) - { - aHatcher.AddElement(PCurve, anEdge.Orientation()) ; - return; - } - }else{ - if(PCurve->FirstParameter()-U1 > Precision::PConfusion()){ - U1=PCurve->FirstParameter(); - } - if(U2-PCurve->LastParameter() > Precision::PConfusion()){ - U2=PCurve->LastParameter(); - } - } - } - Handle(Geom2d_TrimmedCurve) TrimPCurve = - new Geom2d_TrimmedCurve(PCurve, U1, U2); - aHatcher.AddElement(TrimPCurve, anEdge.Orientation()); - } + if (aHatcher.IsDone()) { + // Push iso lines in vtk kernel + CreateIso(aHatcher, Standard_True, theDiscret, thePolyData, thePts); + CreateIso(aHatcher, Standard_False, theDiscret, thePolyData, thePts); } +} - //----------------------------------------------------------------------- - // Loading and trimming the hatchings. - //----------------------------------------------------------------------- - Standard_Integer IIso; - Standard_Real DeltaU = Abs(anUMax - anUMin) ; - Standard_Real DeltaV = Abs(aVMax - aVMin) ; - Standard_Real confusion = Min(DeltaU, DeltaV) * HATHCER_CONFUSION_3D ; - aHatcher.Confusion3d (confusion) ; - - if ( theNbIso[0] ) { - Standard_Real StepU = DeltaU / (Standard_Real)theNbIso[0]; - if(StepU > confusion){ - Standard_Real UPrm = anUMin + StepU / 2.; - gp_Dir2d Dir(0., 1.) ; - for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++) { - anUPrm(IIso) = UPrm ; - gp_Pnt2d Ori (UPrm, 0.) ; - Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ; - anUInd(IIso) = aHatcher.AddHatching (HCur) ; - UPrm += StepU ; - } - } - } - if ( theNbIso[1] ) { - Standard_Real StepV = DeltaV / (Standard_Real) theNbIso[1] ; - if(StepV > confusion){ - Standard_Real VPrm = aVMin + StepV / 2.; - gp_Dir2d Dir(1., 0.); - for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){ - aVPrm(IIso) = VPrm; - gp_Pnt2d Ori (0., VPrm); - Geom2dAdaptor_Curve HCur(new Geom2d_Line (Ori, Dir)); - aVInd(IIso) = aHatcher.AddHatching (HCur) ; - VPrm += StepV ; - } - } - } +void +GEOM_WireframeFace:: +CreateIso(const GEOMUtils_Hatcher &theHatcher, + const Standard_Boolean IsUIso, + const int theDiscret, + vtkPolyData *thePolyData, + vtkPoints *thePts) +{ + Handle(TColStd_HArray1OfInteger) anIndices; + Handle(TColStd_HArray1OfReal) aParams; - //----------------------------------------------------------------------- - // Computation. - //----------------------------------------------------------------------- - aHatcher.Trim() ; - - Standard_Integer aNbDom = 0 ; // for debug purpose - Standard_Integer Index ; - - for(IIso = 1 ; IIso <= theNbIso[0] ; IIso++){ - Index = anUInd(IIso) ; - if(Index != 0){ - if(aHatcher.TrimDone(Index) && !aHatcher.TrimFailed(Index)){ - aHatcher.ComputeDomains(Index); - if(aHatcher.IsDone (Index)) - aNbDom = aHatcher.NbDomains (Index); - } - } + if (IsUIso) { + // U-isolines + anIndices = theHatcher.GetUIndices(); + aParams = theHatcher.GetUParams(); + } else { + // V-isolines + anIndices = theHatcher.GetVIndices(); + aParams = theHatcher.GetVParams(); } - for(IIso = 1 ; IIso <= theNbIso[1] ; IIso++){ - Index = aVInd(IIso); - if(Index != 0){ - if(aHatcher.TrimDone (Index) && !aHatcher.TrimFailed(Index)){ - aHatcher.ComputeDomains (Index); - if(aHatcher.IsDone (Index)) - aNbDom = aHatcher.NbDomains (Index); - } - } - } + if (anIndices.IsNull() == Standard_False && + aParams.IsNull() == Standard_False) { + const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV); + Standard_Integer anIsoInd = anIndices->Lower(); - //----------------------------------------------------------------------- - // Push iso lines in vtk kernel - //----------------------------------------------------------------------- - for(Standard_Integer UIso = anUPrm.Lower() ; UIso <= anUPrm.Upper(); UIso++){ - Standard_Integer UInd = anUInd.Value(UIso); - if(UInd != 0){ - Standard_Real UPrm = anUPrm.Value(UIso); - if(aHatcher.IsDone(UInd)){ - Standard_Integer NbDom = aHatcher.NbDomains(UInd); - for(Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){ - const HatchGen_Domain& Dom = aHatcher.Domain(UInd, IDom) ; - Standard_Real V1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE; - Standard_Real V2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE; - CreateIso_(theFace, GeomAbs_IsoU, UPrm, V1, V2, theDiscret, thePolyData, thePts); - } - } - } - } + for (; anIsoInd <= anIndices->Upper(); anIsoInd++) { + const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd); - for(Standard_Integer VIso = aVPrm.Lower() ; VIso <= aVPrm.Upper(); VIso++){ - Standard_Integer VInd = aVInd.Value(VIso); - if(VInd != 0){ - Standard_Real VPrm = aVPrm.Value(VIso); - if(aHatcher.IsDone (VInd)){ - Standard_Integer NbDom = aHatcher.NbDomains(VInd); - for (Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++){ - const HatchGen_Domain& Dom = aHatcher.Domain(VInd, IDom); - Standard_Real U1 = Dom.HasFirstPoint()? Dom.FirstPoint().Parameter(): aVMin - VTKINFINITE; - Standard_Real U2 = Dom.HasSecondPoint()? Dom.SecondPoint().Parameter(): aVMax + VTKINFINITE; - CreateIso_(theFace, GeomAbs_IsoV, VPrm, U1, U2, theDiscret, thePolyData, thePts); - } + if (aHatchingIndex != 0) { + const Standard_Real aParam = aParams->Value(anIsoInd); + const Standard_Integer aNbDomains = + theHatcher.GetNbDomains(aHatchingIndex); + + if (aNbDomains >= 0) { + Standard_Integer anIDom = 1; + Standard_Real aV1; + Standard_Real aV2; + + for (; anIDom <= aNbDomains; anIDom++) { + if (theHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) { + CreateIso_(theHatcher.GetFace(), aType, aParam, aV1, aV2, + theDiscret, thePolyData, thePts); + } + } + } } } } } - + void GEOM_WireframeFace:: diff --git a/src/OCC2VTK/GEOM_WireframeFace.h b/src/OCC2VTK/GEOM_WireframeFace.h index b6953143b..d89325c09 100755 --- a/src/OCC2VTK/GEOM_WireframeFace.h +++ b/src/OCC2VTK/GEOM_WireframeFace.h @@ -27,6 +27,7 @@ #include class vtkPolyData; +class GEOMUtils_Hatcher; class OCC2VTK_EXPORT GEOM_WireframeFace: public GEOM_FaceSource { @@ -63,7 +64,15 @@ protected: const int theDiscret, vtkPolyData* thePolyData, vtkPoints* thePts); - + + static + void + CreateIso(const GEOMUtils_Hatcher &theHatcher, + const Standard_Boolean IsUIso, + const int theDiscret, + vtkPolyData *thePolyData, + vtkPoints *thePts); + static void CreateIso_(const TopoDS_Face& theFace,