From 8866b5fcd5529bf033ebfb845dafdbaf33d3899c Mon Sep 17 00:00:00 2001 From: skv Date: Mon, 8 Sep 2014 16:07:16 +0400 Subject: [PATCH] 0022661: EDF GEOM: [HYDRO] Integration of the polyline editor in GEOM --- CMakeLists.txt | 23 +- doc/salome/examples/polyline.py | 48 + doc/salome/gui/GEOM/images/polyline_dlg.png | Bin 0 -> 27747 bytes .../GEOM/images/polyline_dlg_add_section.png | Bin 0 -> 14047 bytes .../GEOM/images/polyline_dlg_edit_section.png | Bin 0 -> 15222 bytes .../gui/GEOM/input/creating_basic_go.doc | 1 + .../gui/GEOM/input/creating_polyline.doc | 107 ++ doc/salome/gui/GEOM/input/tui_polyline.doc | 6 + idl/GEOM_Gen.idl | 80 +- src/CMakeLists.txt | 11 +- src/CurveCreator/CMakeLists.txt | 17 +- src/CurveCreator/CurveCreator.hxx | 35 +- src/CurveCreator/CurveCreator_Curve.cxx | 1014 +++++++++- src/CurveCreator/CurveCreator_Curve.hxx | 291 ++- src/CurveCreator/CurveCreator_CurveEditor.cxx | 511 ------ src/CurveCreator/CurveCreator_CurveEditor.hxx | 166 -- src/CurveCreator/CurveCreator_Diff.cxx | 347 ++-- src/CurveCreator/CurveCreator_Diff.hxx | 68 +- src/CurveCreator/CurveCreator_Displayer.cxx | 64 + src/CurveCreator/CurveCreator_Displayer.hxx | 33 + src/CurveCreator/CurveCreator_ICurve.cxx | 459 ----- src/CurveCreator/CurveCreator_ICurve.hxx | 237 +-- src/CurveCreator/CurveCreator_Macro.hxx | 4 +- src/CurveCreator/CurveCreator_NewPointDlg.cxx | 196 -- src/CurveCreator/CurveCreator_NewPointDlg.h | 70 - .../CurveCreator_NewSectionDlg.cxx | 44 +- src/CurveCreator/CurveCreator_NewSectionDlg.h | 15 +- src/CurveCreator/CurveCreator_Operation.cxx | 240 ++- src/CurveCreator/CurveCreator_Operation.hxx | 35 +- src/CurveCreator/CurveCreator_PosPoint.hxx | 46 + src/CurveCreator/CurveCreator_Section.hxx | 6 +- src/CurveCreator/CurveCreator_TableView.cxx | 178 ++ src/CurveCreator/CurveCreator_TableView.h | 69 + src/CurveCreator/CurveCreator_TreeView.cxx | 80 +- src/CurveCreator/CurveCreator_TreeView.h | 24 +- src/CurveCreator/CurveCreator_UndoOptsDlg.cxx | 237 --- src/CurveCreator/CurveCreator_UndoOptsDlg.h | 73 - src/CurveCreator/CurveCreator_Utils.cxx | 994 ++++++++++ src/CurveCreator/CurveCreator_Utils.hxx | 211 +++ src/CurveCreator/CurveCreator_UtilsICurve.cxx | 126 ++ src/CurveCreator/CurveCreator_UtilsICurve.hxx | 69 + src/CurveCreator/CurveCreator_Widget.cxx | 1626 +++++++++++------ src/CurveCreator/CurveCreator_Widget.h | 251 ++- src/EntityGUI/CMakeLists.txt | 5 + src/EntityGUI/EntityGUI.cxx | 5 + src/EntityGUI/EntityGUI_PolylineDlg.cxx | 670 +++++++ src/EntityGUI/EntityGUI_PolylineDlg.h | 152 ++ src/GEOM/GEOM_Function.cxx | 70 + src/GEOM/GEOM_Function.hxx | 13 + src/GEOMGUI/GEOM_images.ts | 4 + src/GEOMGUI/GEOM_msg_en.ts | 160 +- src/GEOMGUI/GeometryGUI.cxx | 71 +- src/GEOMGUI/GeometryGUI_Operations.h | 5 +- src/GEOMImpl/CMakeLists.txt | 4 + src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx | 155 ++ src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx | 13 + src/GEOMImpl/GEOMImpl_IPolyline2D.cxx | 112 ++ src/GEOMImpl/GEOMImpl_IPolyline2D.hxx | 94 + src/GEOMImpl/GEOMImpl_PolylineDriver.cxx | 231 ++- src/GEOMImpl/GEOMImpl_PolylineDriver.hxx | 3 + src/GEOMImpl/GEOMImpl_PolylineDumper.cxx | 251 +++ src/GEOMImpl/GEOMImpl_PolylineDumper.hxx | 132 ++ src/GEOMImpl/GEOMImpl_Types.hxx | 6 +- src/GEOM_I/GEOM_ICurvesOperations_i.cc | 189 ++ src/GEOM_I/GEOM_ICurvesOperations_i.hh | 27 + src/GEOM_I/GEOM_IHealingOperations_i.cc | 22 +- src/GEOM_I/GEOM_IHealingOperations_i.hh | 4 - src/GEOM_I/GEOM_IOperations_i.cc | 25 + src/GEOM_I/GEOM_IOperations_i.hh | 11 +- src/GEOM_SWIG/geomBuilder.py | 21 +- src/GEOM_SWIG/gsketcher.py | 142 ++ src/OperationGUI/CMakeLists.txt | 9 - src/OperationGUI/OperationGUI.cxx | 44 - src/SKETCHER/CMakeLists.txt | 3 + .../Sketcher.hxx} | 38 +- src/SKETCHER/Sketcher_Profile.hxx | 16 +- src/SKETCHER/Sketcher_Utils.cxx | 187 ++ src/SKETCHER/Sketcher_Utils.hxx | 103 ++ 78 files changed, 7960 insertions(+), 3149 deletions(-) create mode 100644 doc/salome/examples/polyline.py create mode 100644 doc/salome/gui/GEOM/images/polyline_dlg.png create mode 100644 doc/salome/gui/GEOM/images/polyline_dlg_add_section.png create mode 100644 doc/salome/gui/GEOM/images/polyline_dlg_edit_section.png create mode 100644 doc/salome/gui/GEOM/input/creating_polyline.doc create mode 100644 doc/salome/gui/GEOM/input/tui_polyline.doc delete mode 100644 src/CurveCreator/CurveCreator_CurveEditor.cxx delete mode 100644 src/CurveCreator/CurveCreator_CurveEditor.hxx create mode 100644 src/CurveCreator/CurveCreator_Displayer.cxx create mode 100644 src/CurveCreator/CurveCreator_Displayer.hxx delete mode 100644 src/CurveCreator/CurveCreator_ICurve.cxx delete mode 100755 src/CurveCreator/CurveCreator_NewPointDlg.cxx delete mode 100755 src/CurveCreator/CurveCreator_NewPointDlg.h mode change 100755 => 100644 src/CurveCreator/CurveCreator_NewSectionDlg.cxx mode change 100755 => 100644 src/CurveCreator/CurveCreator_NewSectionDlg.h create mode 100644 src/CurveCreator/CurveCreator_PosPoint.hxx create mode 100644 src/CurveCreator/CurveCreator_TableView.cxx create mode 100644 src/CurveCreator/CurveCreator_TableView.h mode change 100755 => 100644 src/CurveCreator/CurveCreator_TreeView.cxx mode change 100755 => 100644 src/CurveCreator/CurveCreator_TreeView.h delete mode 100644 src/CurveCreator/CurveCreator_UndoOptsDlg.cxx delete mode 100644 src/CurveCreator/CurveCreator_UndoOptsDlg.h create mode 100644 src/CurveCreator/CurveCreator_Utils.cxx create mode 100644 src/CurveCreator/CurveCreator_Utils.hxx create mode 100644 src/CurveCreator/CurveCreator_UtilsICurve.cxx create mode 100644 src/CurveCreator/CurveCreator_UtilsICurve.hxx create mode 100644 src/EntityGUI/EntityGUI_PolylineDlg.cxx create mode 100644 src/EntityGUI/EntityGUI_PolylineDlg.h create mode 100644 src/GEOMImpl/GEOMImpl_IPolyline2D.cxx create mode 100644 src/GEOMImpl/GEOMImpl_IPolyline2D.hxx create mode 100644 src/GEOMImpl/GEOMImpl_PolylineDumper.cxx create mode 100644 src/GEOMImpl/GEOMImpl_PolylineDumper.hxx mode change 100755 => 100644 src/GEOMImpl/GEOMImpl_Types.hxx rename src/{CurveCreator/CurveCreator_Listener.hxx => SKETCHER/Sketcher.hxx} (53%) mode change 100755 => 100644 create mode 100644 src/SKETCHER/Sketcher_Utils.cxx create mode 100644 src/SKETCHER/Sketcher_Utils.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index d741a55cc..91ef62ccb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,20 +67,7 @@ OPTION(SALOME_BUILD_TESTS "Build SALOME tests" ON) OPTION(SALOME_BUILD_GUI "Enable GUI" ON) CMAKE_DEPENDENT_OPTION(SALOME_GEOM_USE_OPENCV "Enable shape recognition from picture" OFF "SALOME_BUILD_GUI" OFF) -CMAKE_DEPENDENT_OPTION(SALOME_GEOM_BUILD_CC "Enable curve creator (experimental)" OFF - "SALOME_BUILD_GUI" OFF) -MARK_AS_ADVANCED(SALOME_BUILD_GUI SALOME_GEOM_USE_OPENCV SALOME_GEOM_BUILD_CC) - -# Debug options (!!! FOR DEVELOPERS ONLY !!! TO BE REMOVED LATER !!!) -IF(CMAKE_BUILD_TYPE MATCHES "^Debug$") - CMAKE_DEPENDENT_OPTION(SALOME_GEOM_DEBUG_CC "Debug curve creator" OFF - "SALOME_GEOM_BUILD_CC" OFF) - MARK_AS_ADVANCED(SALOME_GEOM_DEBUG_CC) - - IF(SALOME_GEOM_DEBUG_CC) - ADD_DEFINITIONS(-DDEBUG_CURVE_CREATOR) - ENDIF(SALOME_GEOM_DEBUG_CC) -ENDIF() +MARK_AS_ADVANCED(SALOME_BUILD_GUI SALOME_GEOM_USE_OPENCV) # Prerequisites # ============= @@ -242,7 +229,7 @@ SET(_${PROJECT_NAME}_exposed_targets ) IF(SALOME_BUILD_GUI) LIST(APPEND _${PROJECT_NAME}_exposed_targets - AdvancedGUI BasicGUI BlocksGUI BooleanGUI BuildGUI DisplayGUI DlgRef EntityGUI GEOMBase + AdvancedGUI BasicGUI BlocksGUI BooleanGUI BuildGUI DisplayGUI DlgRef CurveCreator EntityGUI GEOMBase GEOMFiltersSelection GEOM GEOMToolsGUI GenerationGUI GroupGUI Material MeasureGUI GEOMObject OperationGUI PrimitiveGUI RepairGUI TransformationGUI DependencyTree STLPluginGUI BREPPluginGUI STEPPluginGUI IGESPluginGUI XAOPluginGUI VTKPluginGUI @@ -255,12 +242,6 @@ IF(SALOME_GEOM_USE_OPENCV) ) ENDIF(SALOME_GEOM_USE_OPENCV) -IF(SALOME_GEOM_BUILD_CC) - LIST(APPEND _${PROJECT_NAME}_exposed_targets - CurveCreator - ) -ENDIF(SALOME_GEOM_BUILD_CC) - # Add all targets to the build-tree export set EXPORT(TARGETS ${_${PROJECT_NAME}_exposed_targets} FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake) diff --git a/doc/salome/examples/polyline.py b/doc/salome/examples/polyline.py new file mode 100644 index 000000000..8b7925607 --- /dev/null +++ b/doc/salome/examples/polyline.py @@ -0,0 +1,48 @@ +# 2D polyline + +import salome +salome.salome_init() +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New(salome.myStudy) +gg = salome.ImportComponentGUI("GEOM") + +# create vertices +p1 = geompy.MakeVertex(70., 0., 0.) +p2 = geompy.MakeVertex(70., 70., 80.) +p3 = geompy.MakeVertex( 0., 70., 0.) + +#create a vector from two points +vector_arc = geompy.MakeVector(p1, p3) + +# create an arc from three points +arc = geompy.MakeArc(p1, p2, p3) + +# create a wire +wire = geompy.MakeWire([vector_arc, arc]) + +# create a planar face +isPlanarWanted = 1 +face = geompy.MakeFace(wire, isPlanarWanted) + +# Create a 2D polyline with Polyline2D interface +pl = geompy.Polyline2D() +pl.addSection("section 1", GEOM.Polyline, True, [0, 0, 10, 0, 10, 10]) +polyline1 = pl.result([100, 0, 0, 1, 1, 1, -1, 1, 0]) + +pl = geompy.Polyline2D() +pl.addSection("section 2", GEOM.Interpolation, False) +pl.addPoints([20, 0, 30, 0, 30, 10]) +polyline2 = pl.result(face) + +# add objects in the study +id_face = geompy.addToStudy(face,"Face") +id_polyline1 = geompy.addToStudy(polyline1, "Polyline1") +id_polyline2 = geompy.addToStudy(polyline2, "Polyline2") + +# display the first polyline and the second polyline with its planar face +gg.createAndDisplayGO(id_face) +gg.setDisplayMode(id_face,1) +gg.setTransparency(id_face,0.5) +gg.createAndDisplayGO(id_polyline1) +gg.createAndDisplayGO(id_polyline2) diff --git a/doc/salome/gui/GEOM/images/polyline_dlg.png b/doc/salome/gui/GEOM/images/polyline_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..532817c402b62d976befa27b64ab1b0b93c6f4c0 GIT binary patch literal 27747 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/input/creating_basic_go.doc b/doc/salome/gui/GEOM/input/creating_basic_go.doc index 6693b469d..efdff9511 100644 --- a/doc/salome/gui/GEOM/input/creating_basic_go.doc +++ b/doc/salome/gui/GEOM/input/creating_basic_go.doc @@ -15,6 +15,7 @@ geometrical objects as:
  • \subpage create_isoline_page
  • \subpage create_sketcher_page
  • \subpage create_3dsketcher_page
  • +
  • \subpage create_polyline_page
  • \subpage create_vector_page
  • \subpage create_plane_page
  • \subpage create_lcs_page
  • diff --git a/doc/salome/gui/GEOM/input/creating_polyline.doc b/doc/salome/gui/GEOM/input/creating_polyline.doc new file mode 100644 index 000000000..7ec36434d --- /dev/null +++ b/doc/salome/gui/GEOM/input/creating_polyline.doc @@ -0,0 +1,107 @@ +/*! + +\page create_polyline_page 2D Polyline + +The 2D Polyline allows drawing arbitrary 2D shapes. + +To create a 2D Polyline select in the main menu New Entity -> Basic -> 2D Polyline. + +\image html polyline_dlg.png + +A polyline represents a section or a set of sections. Each section is constructed from a sequence of 2D points +connected either by linear setgments or an interpolation curve. Every section has its own attributes: +- \b Name, +- \b Type (Polyline or Spline), +- \b Closed flag. + +A Polyline created represents a shape that lies on the XOY plane. It can have the following types: +- \b Vertex for a single section with only 1 point. +- \b Wire for a single section with 2 or more points. A Wire can have multiple edges for more then 2 points if the section type is Polyline. +A single edge in the result wire is obtained for a Spline or Polyline with 2 points. +- \b Compound of Wires and/or Vertices if there are several sections. + +For the moment only one reference coordinate system for polyline creation is supported. The XOY plane of the Global coordinate system +is suggested. Implementation of another reference coordinate system is a subject of further development of this functionality. +Restore button orientates the viewer correspondingly to the chosen working plane and fits the scene to show all objects. +For the moment this button works with only one plane. + +It is possible to import a shape in this dialog using Import polyline selection button. To do it an imported object should satisfy conditions +for polyline shapes mentioned above. If a valid shape is selected, when dialog is opened, it is initialized by this shape. +Though the shape can be on any plane, an imported polyline will be defined on XOY plane only due to the limitation. + +The group \b Sections in this dialog represents the Polyline construction framework. Its toolbar has the following operations: +- \b Undo +- \b Redo +- Insert new section +- Addition mode +- Modification mode - not implemented +- Detection mode - not implemented +- \b Remove +- Join selected sections + +Undo/Redo buttons allows to undo/redo changes of the polyline. + +Insert new section button opens a dialog that allows to add a new section: + +\image html polyline_dlg_add_section.png + +In this dialog it is possible to choose: +- \b Name of section +- \b Type of section +- \b Closed flag + +To create a new section \b Add button should be clicked. \b Cancel button is used to cancel this operation. +After clicking \b Add button a new section is appeared on the list. Its name supplemented by its type and closedness +information (see icon) and the number of points (equal to 0 after creation). + +To modify section parameters it is possible to double-click on a section in the list. In this case the following dialog appears: + +\image html polyline_dlg_edit_section.png + +To apply modifications the button \b Ok should be clicked. + +Addition mode allows to add points to a section. It is necessary to select a particular section in a list of sections +and make some mouse clicks in the viewer. A section preview is recomputed after each click. + +Modification mode and Detection mode are not implemented for the moment. + +\b Remove button allows to remove a section. It is available if all modes are deactivated and one section is selected. + +Join selected sections button is available in modification mode if two or more sections are selected. It is used to +merge several sections into the first one from selection list. Joined section has parameters of the first selected one. Points of +the other sections are appended at the end of the list of the first section points. + +Some actions are available via popup menu by right mouse button click. + +If all modes are deactivated: +- Join all sections - join all defined sections into the first one. +- \b Join - join sections. Available if two or more sections are selected. + +In Addition mode: +- Join all sections - join all defined sections into the first one. + +In Modification mode: +- Join all sections - join all defined sections into the first one. +- \b Join - join sections. Available if two or more sections are selected. +- Clear all - remove all sections. Available if at least one section is selected. +- Set closed - set all selected section's Closed flag. Available if at least one section is selected. +- Set open - reset all selected section's Closed flag. Available if at least one section is selected. +- Set polyline - set all selected section's type to Polyline. Available if at least one section is selected. +- Set spline - set all selected section's type to Spline. Available if at least one section is selected. + +In Detection mode: +- Join all sections - join all defined sections into the first one. +- \b Join - join sections. Available if two or more sections are selected. + +

    TUI Commands

    + + +To create the 2D polyline in TUI Polyline2D interface is used. + +pl = geompy.Polyline2D() - returns an instance of Polyline2D interface pl. + +See the \ref gsketcher.Polyline2D "Polyline2D" interface documentation for more information. + +Our TUI Scripts provide you with useful examples of the use of +\ref tui_polyline_page "2D Polyline". +*/ diff --git a/doc/salome/gui/GEOM/input/tui_polyline.doc b/doc/salome/gui/GEOM/input/tui_polyline.doc new file mode 100644 index 000000000..ff83b9053 --- /dev/null +++ b/doc/salome/gui/GEOM/input/tui_polyline.doc @@ -0,0 +1,6 @@ +/*! + +\page tui_polyline_page 2D Polyline +\tui_script{polyline.py} + +*/ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 076f4fed4..8863bae26 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -164,7 +164,8 @@ module GEOM /*! * \brief Kind of the curves. * - * Used in the functions GEOM_ICurvesOperations.MakeCurveParametric(), GEOM_ICurvesOperations.MakeCurveParametricNew() + * Used in the functions GEOM_ICurvesOperations.MakeCurveParametric(), GEOM_ICurvesOperations.MakeCurveParametricNew(), + * GEOM_ICurvesOperations.MakePolyline2D, GEOM_ICurvesOperations.MakePolyline2DOnPlane. */ enum curve_type { /*! Polyline curve */ @@ -208,11 +209,12 @@ module GEOM }; - typedef sequence string_array; - typedef sequence short_array; - typedef sequence ListOfBool; - typedef sequence ListOfLong; - typedef sequence ListOfDouble; + typedef sequence string_array; + typedef sequence short_array; + typedef sequence ListOfBool; + typedef sequence ListOfLong; + typedef sequence ListOfDouble; + typedef sequence ListOfListOfDouble; interface GEOM_Object; interface GEOM_BaseObject; @@ -3332,6 +3334,72 @@ module GEOM * \return New GEOM_Object, containing the created wire. */ GEOM_Object Make3DSketcher (in ListOfDouble theCoordinates); + + /*! + * \brief Create a 2D polyline (wire or a compound of wires). + * + * The polyline can have several sections. Each section represents a set + * of points in the form of list of coordinates of the following order: + * x1, y1, x2, y2, ..., xN, yN + * Each section has its own name, type of curve (can be either + * GEOM::Polyline or GEOM::Interpolation) and Closed flag. + * For each section a wire is created. It represents either a polyline or + * interpolation BSpline either closed or not depending on the Closed flag. + * The result represents a wire if there is only one section is defined. + * Otherwise a compound of wires is returned. + * + * \param theCoordsList the list of coordinates list. theCoordsList[0] + * is the coordinates list of the first section. theCoordsList[1] + * is for the second section etc. + * \param theNamesList the list of names. The order corresponds to + * theCoordsList. + * \param theTypesList the list of curve types. The order corresponds to + * theCoordsList. + * \param theClosedList the list of Closed flags. The order corresponds to + * theCoordsList. + * \param theWorkingPlane 9 double values, defining origin, + * OZ and OX directions of the working plane. + * \return New GEOM_Object, containing the created wire or a compound + * of wires. + */ + GEOM_Object MakePolyline2D (in ListOfListOfDouble theCoordsList, + in string_array theNamesList, + in short_array theTypesList, + in ListOfBool theClosedList, + in ListOfDouble theWorkingPlane); + + /*! + * \brief Create a 2D polyline (wire or a compound of wires). + * + * The polyline can have several sections. Each section represents a set + * of points in the form of list of coordinates of the following order: + * x1, y1, x2, y2, ..., xN, yN + * Each section has its own name, type of curve (can be either + * GEOM::Polyline or GEOM::Interpolation) and Closed flag. + * For each section a wire is created. It represents either a polyline or + * interpolation BSpline either closed or not depending on the Closed flag. + * The result represents a wire if there is only one section is defined. + * Otherwise a compound of wires is returned. + * + * \param theCoordsList the list of coordinates list. theCoordsList[0] + * is the coordinates list of the first section. theCoordsList[1] + * is for the second section etc. + * \param theNamesList the list of names. The order corresponds to + * theCoordsList. + * \param theTypesList the list of curve types. The order corresponds to + * theCoordsList. + * \param theClosedList the list of Closed flags. The order corresponds to + * theCoordsList. + * \param theWorkingPlane planar Face or LCS(Marker) of the working plane. + * \return New GEOM_Object, containing the created wire or a compound + * of wires. + */ + GEOM_Object MakePolyline2DOnPlane (in ListOfListOfDouble theCoordsList, + in string_array theNamesList, + in short_array theTypesList, + in ListOfBool theClosedList, + in GEOM_Object theWorkingPlane); + }; // # GEOM_ILocalOperations: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7c10ef0d4..b4f792af1 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,15 +27,6 @@ SET(SUBDIRS_COMMON STLPlugin BREPPlugin STEPPlugin IGESPlugin XAOPlugin VTKPlugin ) -## -# Curve creator -## -IF(SALOME_GEOM_BUILD_CC) - SET(SUBDIRS_CC - CurveCreator - ) -ENDIF() - ## # OPENCV ## @@ -52,7 +43,7 @@ IF(SALOME_BUILD_GUI) SET(SUBDIRS_GUI OBJECT DlgRef GEOMFiltersSelection Material GEOMGUI GEOMBase DependencyTree GEOMToolsGUI DisplayGUI BasicGUI PrimitiveGUI GenerationGUI - EntityGUI BuildGUI BooleanGUI TransformationGUI OperationGUI + CurveCreator EntityGUI BuildGUI BooleanGUI TransformationGUI OperationGUI RepairGUI MeasureGUI GroupGUI BlocksGUI AdvancedGUI GEOM_SWIG_WITHIHM ) diff --git a/src/CurveCreator/CMakeLists.txt b/src/CurveCreator/CMakeLists.txt index 34582d31c..15677b68c 100644 --- a/src/CurveCreator/CMakeLists.txt +++ b/src/CurveCreator/CMakeLists.txt @@ -57,9 +57,8 @@ IF(SALOME_BUILD_GUI) # header files / to be processed by moc SET(_moc_HEADERS CurveCreator_NewSectionDlg.h - CurveCreator_NewPointDlg.h + CurveCreator_TableView.h CurveCreator_TreeView.h -# CurveCreator_UndoOptsDlg.h CurveCreator_Widget.h ) ENDIF(SALOME_BUILD_GUI) @@ -68,13 +67,15 @@ ENDIF(SALOME_BUILD_GUI) SET(_other_HEADERS CurveCreator.hxx CurveCreator_Curve.hxx - CurveCreator_CurveEditor.hxx CurveCreator_Diff.hxx + CurveCreator_Displayer.hxx CurveCreator_ICurve.hxx - CurveCreator_Listener.hxx CurveCreator_Macro.hxx CurveCreator_Operation.hxx + CurveCreator_PosPoint.hxx CurveCreator_Section.hxx + CurveCreator_UtilsICurve.hxx + CurveCreator_Utils.hxx ) # header files / to install @@ -90,17 +91,17 @@ ENDIF(SALOME_BUILD_GUI) # sources / static SET(_other_SOURCES CurveCreator_Curve.cxx - CurveCreator_CurveEditor.cxx CurveCreator_Diff.cxx - CurveCreator_ICurve.cxx + CurveCreator_Displayer.cxx CurveCreator_Operation.cxx + CurveCreator_Utils.cxx + CurveCreator_UtilsICurve.cxx ) IF(SALOME_BUILD_GUI) LIST(APPEND _other_SOURCES - CurveCreator_NewPointDlg.cxx CurveCreator_NewSectionDlg.cxx + CurveCreator_TableView.cxx CurveCreator_TreeView.cxx -# CurveCreator_UndoOptsDlg.cxx CurveCreator_Widget.cxx ) ENDIF(SALOME_BUILD_GUI) diff --git a/src/CurveCreator/CurveCreator.hxx b/src/CurveCreator/CurveCreator.hxx index 74a3faec4..9cd7ec720 100644 --- a/src/CurveCreator/CurveCreator.hxx +++ b/src/CurveCreator/CurveCreator.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -24,29 +24,30 @@ #define _CurveCreator_HeaderFile #include +#include +#include + +struct CurveCreator_Section; +struct CurveCreator_PosPoint; namespace CurveCreator { - - //! Dimension of the curve - enum Dimension - { - Dim2d = 2, - Dim3d = 3 - }; - - //! Type of the section - enum Type - { - Polyline, - BSpline - }; - //! Points coordinates typedef float TypeCoord; + /** List of coordinates in format depends on section dimension: + * 2D: [x1, y1, x2, y2, x3, y3, ..] + * 3D: [x1, y1, z1, x2, y2, z2, x3, y3, z3, ..] + */ typedef std::deque Coordinates; + //! List of sections + typedef std::deque Sections; + + // List of positioned points (points with coordinates) + typedef std::list PosPointsList; + //! Map of sections with positioned points + typedef std::map SectionsMap; }; #endif diff --git a/src/CurveCreator/CurveCreator_Curve.cxx b/src/CurveCreator/CurveCreator_Curve.cxx index b4fa90ffc..e20705c46 100644 --- a/src/CurveCreator/CurveCreator_Curve.cxx +++ b/src/CurveCreator/CurveCreator_Curve.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -21,8 +21,21 @@ // Author: Sergey KHROMOV #include "CurveCreator_Curve.hxx" + +#include "CurveCreator.hxx" +#include "CurveCreator_PosPoint.hxx" #include "CurveCreator_Section.hxx" -#include "CurveCreator_Listener.hxx" +#include "CurveCreator_Displayer.hxx" +#include "CurveCreator_Utils.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -30,24 +43,995 @@ // function: Constructor // purpose: //======================================================================= -CurveCreator_Curve::CurveCreator_Curve - (const CurveCreator::Dimension theDimension) -: CurveCreator_ICurve(theDimension) +CurveCreator_Curve::CurveCreator_Curve( const CurveCreator::Dimension theDimension ) +: myIsLocked (false), + myDimension (theDimension), + myDisplayer (NULL), + myAISShape (NULL), + myNbUndos (0), + myNbRedos (0), + myUndoDepth (-1), + myOpLevel(0), + mySkipSorting(false) +{ +} + +//======================================================================= +// function: Destructor +// purpose: +//======================================================================= +CurveCreator_Curve::~CurveCreator_Curve() +{ + // Delete all allocated data. + clear(); +} + +//======================================================================= +// function: getDimension +// purpose: +//======================================================================= +CurveCreator::Dimension CurveCreator_Curve::getDimension() const +{ + return myDimension; +} + +//======================================================================= +// function: getUniqSectionName +// purpose: return unique section name +//======================================================================= +std::string CurveCreator_Curve::getUniqSectionName() const +{ + CurveCreator_Section* aSection; + for( int i = 0 ; i < 1000000 ; i++ ){ + char aBuffer[255]; + sprintf( aBuffer, "Section_%d", i+1 ); + std::string aName(aBuffer); + int j; + for( j = 0 ; j < mySections.size() ; j++ ){ + aSection = getSection( j ); + if ( aSection && aSection->myName == aName ) + break; + } + if( j == mySections.size() ) + return aName; + } + return ""; +} + +//======================================================================= +// function: setDisplayer +// purpose: set curve changes Displayer +//======================================================================= +void CurveCreator_Curve::setDisplayer( CurveCreator_Displayer* theDisplayer ) +{ + myDisplayer = theDisplayer; +} + +//======================================================================= +// function: getDisplayer +// purpose: get curve changes Displayer +//======================================================================= +CurveCreator_Displayer* CurveCreator_Curve::getDisplayer() +{ + return myDisplayer; +} + +//======================================================================= +// function: removeDisplayer +// purpose: remove the attached Displayer +//======================================================================= +void CurveCreator_Curve::removeDisplayer() { + myDisplayer = NULL; } //======================================================================= -// function: addPoints +// function: addDiff // purpose: //======================================================================= -void CurveCreator_Curve::addPoints - (const CurveCreator::Coordinates &thePoints, const int theISection) +bool CurveCreator_Curve::addEmptyDiff() +{ + bool isEnabled = false; + + if (myUndoDepth != 0) { + // Forget all Redos after the current one. + if (myNbRedos > 0) { + myNbRedos = 0; + myListDiffs.erase(myCurrenPos, myListDiffs.end()); + } + + if (myUndoDepth == -1 || myNbUndos < myUndoDepth) { + // Increase the number of undos. + myNbUndos++; + } else { + // If there are too many differences, remove the first one. + myListDiffs.pop_front(); + } + + // Add new difference. + myListDiffs.push_back(CurveCreator_Diff()); + myCurrenPos = myListDiffs.end(); + isEnabled = true; + } + + return isEnabled; +} + +void CurveCreator_Curve::startOperation() +{ + myOpLevel++; +} + +void CurveCreator_Curve::finishOperation() +{ + myOpLevel--; +} + +//======================================================================= +// function: toICoord +// purpose: +//======================================================================= +int CurveCreator_Curve::toICoord(const int theIPnt) const +{ + return theIPnt * myDimension; +} + +//======================================================================= +// function: setUndoDepth +// purpose: +//======================================================================= +void CurveCreator_Curve::setUndoDepth(const int theDepth) +{ + if (theDepth == 0) { + // Reset all undo/redo data. + myNbUndos = 0; + myNbRedos = 0; + myListDiffs.clear(); + myCurrenPos = myListDiffs.end(); + myUndoDepth = 0; + } else if (theDepth == -1) { + // There is nothing to do as the depth become unlimited. + myUndoDepth = -1; + } else if (theDepth > 0) { + // The new "real" depth is set. + if (theDepth < myNbRedos) { + // The new depth is less then number of redos. Remove the latest redos. + int aShift = (myNbRedos - theDepth); + ListDiff::iterator aFromPos = myListDiffs.end(); + + while (aShift--) { + aFromPos--; + } + + myListDiffs.erase(aFromPos, myListDiffs.end()); + myNbRedos = theDepth; + } + + if (theDepth < myNbUndos + myNbRedos) { + // The new depth is less then the total number of differences. + // Remove the first undos. + int aShift = (myNbUndos + myNbRedos - theDepth); + ListDiff::iterator aToPos = myListDiffs.begin(); + + while (aShift--) { + aToPos++; + } + + myListDiffs.erase(myListDiffs.begin(), aToPos); + myNbUndos = theDepth - myNbRedos; + } + + myUndoDepth = theDepth; + } +} + +//======================================================================= +// function: getUndoDepth +// purpose: +//======================================================================= +int CurveCreator_Curve::getUndoDepth() const +{ + return myUndoDepth; +} + +void CurveCreator_Curve::getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const +{ + CurveCreator::Coordinates aCoords = getPoint( theISection, theIPoint ); + theX = aCoords[0]; + theY = aCoords[1]; + theZ = 0.; + if( getDimension() == CurveCreator::Dim3d ){ + theZ = aCoords[2]; + } +} + +void CurveCreator_Curve::redisplayCurve() +{ + if( myDisplayer ) { + myDisplayer->eraseAll( false ); + myAISShape = NULL; + + myDisplayer->display( getAISObject( true ), true ); + } +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::moveSectionInternal(const int theISection, + const int theNewIndex) +{ + bool res = false; + int aMovedSectionId = theISection >= 0 ? theISection : mySections.size()-1; + + if (aMovedSectionId != theNewIndex) { + CurveCreator_Section* aSection = getSection( aMovedSectionId ); + + // Remove section + CurveCreator::Sections::iterator anIter = mySections.begin() + aMovedSectionId; + + mySections.erase(anIter); + + // Insert section. + anIter = mySections.begin() + theNewIndex; + mySections.insert(anIter, aSection); + res = true; + } + return res; +} + +//======================================================================= +// function: moveSection +// purpose: +//======================================================================= +bool CurveCreator_Curve::moveSection(const int theISection, + const int theNewIndex) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::MoveSection, + theISection, theNewIndex); + } + + // Update the curve. + res = moveSectionInternal(theISection, theNewIndex); + finishOperation(); + return res; +} + +/************ Implementation of INTERFACE methods ************/ + +/***********************************************/ +/*** Undo/Redo methods ***/ +/***********************************************/ + +//! Get number of available undo operations +int CurveCreator_Curve::getNbUndo() const +{ + return myNbUndos; +} + +//! Undo previous operation +bool CurveCreator_Curve::undo() +{ + bool res = false; + if (myNbUndos > 0) { + myNbUndos--; + myNbRedos++; + myCurrenPos--; + myCurrenPos->applyUndo(this); + res = true; + } + return res; +} + +//! Get number of available redo operations +int CurveCreator_Curve::getNbRedo() const +{ + return myNbRedos; +} + +//! Redo last previously "undone" operation +bool CurveCreator_Curve::redo() +{ + bool res = false; + if (myNbRedos > 0) { + myCurrenPos->applyRedo(this); + myCurrenPos++; + myNbRedos--; + myNbUndos++; + res = true; + } + return res; +} + +/***********************************************/ +/*** Section methods ***/ +/***********************************************/ +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::clearInternal() +{ + // erase curve from the viewer + if( myDisplayer ) { + myDisplayer->eraseAll( true ); + myAISShape = NULL; + } + // Delete all allocated data. + int i = 0; + const int aNbSections = getNbSections(); + + CurveCreator_Section* aSection; + for (; i < aNbSections; i++) { + aSection = getSection( i ); + if ( aSection ) + delete aSection; + } + + mySections.clear(); + + return true; +} + +//======================================================================= +// function: clear +// purpose: +//======================================================================= +bool CurveCreator_Curve::clear() +{ + bool res = false; + startOperation(); + // Set the difference. + if (addEmptyDiff()) { + myListDiffs.back().init(this); + } + res = clearInternal(); + finishOperation(); + return res; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::joinInternal( const std::list& theSections ) +{ + bool res = false; + if ( theSections.empty() ) + return res; + + int anISectionMain = theSections.front(); + CurveCreator_Section* aSectionMain = getSection( anISectionMain ); + + std::list aSectionsToJoin = theSections; + aSectionsToJoin.erase( aSectionsToJoin.begin() ); // skip the main section + // it is important to sort and reverse the section ids in order to correctly remove them + aSectionsToJoin.sort(); + aSectionsToJoin.reverse(); + + std::list::const_iterator anIt = aSectionsToJoin.begin(), aLast = aSectionsToJoin.end(); + CurveCreator_Section* aSection; + for (; anIt != aLast; anIt++) { + aSection = getSection( *anIt ); + aSectionMain->myPoints.insert(aSectionMain->myPoints.end(), aSection->myPoints.begin(), + aSection->myPoints.end()); + res = removeSectionInternal(*anIt); + if ( !res ) + break; + } + + redisplayCurve(); + return res; +} + +bool CurveCreator_Curve::join( const std::list& theSections ) +{ + bool res = false; + + if ( !theSections.empty() ) + { + startOperation(); + if (addEmptyDiff()) + myListDiffs.back().init(this, CurveCreator_Operation::Join, theSections); + + res = joinInternal( theSections ); + + finishOperation(); + } + return res; +} + +//! Get number of sections +int CurveCreator_Curve::getNbSections() const +{ + return mySections.size(); +} + +//! For internal use only! Undo/Redo are not used here. +int CurveCreator_Curve::addSectionInternal + (const std::string& theName, const CurveCreator::SectionType theType, + const bool theIsClosed, const CurveCreator::Coordinates &thePoints) +{ + CurveCreator_Section *aSection = new CurveCreator_Section; + + std::string aName = theName; + if( aName.empty() ){ + aName = getUniqSectionName(); + } + aSection->myName = aName; + aSection->myType = theType; + aSection->myIsClosed = theIsClosed; + aSection->myPoints = thePoints; + mySections.push_back(aSection); + redisplayCurve(); + return mySections.size()-1; +} + +//======================================================================= +// function: addSection +// purpose: adds an empty section +//======================================================================= +int CurveCreator_Curve::addSection + (const std::string& theName, const CurveCreator::SectionType theType, + const bool theIsClosed) +{ + int resISection = -1; + // Set the difference. + startOperation(); + CurveCreator::Coordinates aCoords; //empty list + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::AddSection, + theName, aCoords, theType, theIsClosed); + } + + resISection = addSectionInternal(theName, theType, theIsClosed, aCoords); + + finishOperation(); + return resISection; +} +//======================================================================= +// function: addSection +// purpose: adds a section with the given points +//======================================================================= +int CurveCreator_Curve::addSection + (const std::string& theName, const CurveCreator::SectionType theType, + const bool theIsClosed, const CurveCreator::Coordinates &thePoints) +{ + int resISection = -1; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::AddSection, + theName, thePoints, theType, theIsClosed); + } + + resISection = addSectionInternal(theName, theType, theIsClosed, thePoints); + + finishOperation(); + return resISection; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::removeSectionInternal( const int theISection ) +{ + if (theISection == -1) { + delete mySections.back(); + mySections.pop_back(); + } else { + CurveCreator::Sections::iterator anIterRm = mySections.begin() + theISection; + + delete *anIterRm; + mySections.erase(anIterRm); + } + redisplayCurve(); + return true; +} + +//! Removes the given sections. +bool CurveCreator_Curve::removeSection( const int theISection ) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) + myListDiffs.back().init(this, CurveCreator_Operation::RemoveSection, theISection); + + res = removeSectionInternal( theISection ); + + finishOperation(); + return res; +} + +/** + * Get number of points in specified section or (the total number of points + * in Curve if theISection is equal to -1). + */ +int CurveCreator_Curve::getNbPoints( const int theISection ) const +{ + int aNbCoords = 0; + + CurveCreator_Section* aSection; + if (theISection == -1) { + int i = 0; + const int aNbSections = getNbSections(); + + for (; i < aNbSections; i++) { + aSection = getSection( i ); + if ( aSection ) + aNbCoords += aSection->myPoints.size(); + } + } else { + aSection = getSection( theISection ); + if ( aSection ) + aNbCoords = aSection->myPoints.size(); + } + + return aNbCoords/myDimension; +} + +void CurveCreator_Curve::setSkipSorting( const bool theIsToSkip ) +{ + mySkipSorting = theIsToSkip; +} + +bool CurveCreator_Curve::canPointsBeSorted() +{ + return false; +} + +/** + * Saves points coordinates difference. + * \param theOldCoords the old points coordinates + */ +void CurveCreator_Curve::saveCoordDiff( const SectionToPointCoordsList &theOldCoords ) +{ + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, theOldCoords); + } + finishOperation(); +} + +//! Get "closed" flag of the specified section +bool CurveCreator_Curve::isClosed( const int theISection ) const +{ + CurveCreator_Section* aSection = getSection( theISection ); + return aSection ? aSection->myIsClosed : false; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::setClosedInternal( const int theISection, + const bool theIsClosed ) +{ + CurveCreator_Section* aSection = 0; + if (theISection == -1) { + int aSize = mySections.size(); + int i; + + for (i = 0; i < aSize; i++) { + aSection = getSection( i ); + if( aSection ) { + aSection->myIsClosed = theIsClosed; + redisplayCurve(); + } + } + } else { + aSection = getSection( theISection ); + if ( aSection ) { + aSection->myIsClosed = theIsClosed; + redisplayCurve(); + } + } + return true; +} + +/** + * Set "closed" flag of the specified section (all sections if + * \a theISection is -1). + */ +bool CurveCreator_Curve::setClosed( const int theISection, + const bool theIsClosed ) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::SetClosed, + theIsClosed, theISection); + } + res = setClosedInternal( theISection, theIsClosed ); + finishOperation(); + return res; +} + +//! Returns specified section name +std::string CurveCreator_Curve::getSectionName( const int theISection ) const +{ + CurveCreator_Section* aSection = getSection( theISection ); + return aSection ? aSection->myName : ""; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::setSectionNameInternal( const int theISection, + const std::string& theName ) +{ + bool res = false; + CurveCreator_Section* aSection = getSection( theISection ); + if( aSection ) { + aSection->myName = theName; + res = true; + } + return res; +} + +/** Set name of the specified section */ +bool CurveCreator_Curve::setSectionName( const int theISection, + const std::string& theName ) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::RenameSection, + theName, theISection); + } + res = setSectionNameInternal( theISection, theName ); + finishOperation(); + return res; +} + +//! Get type of the specified section +CurveCreator::SectionType CurveCreator_Curve::getSectionType + ( const int theISection ) const +{ + CurveCreator_Section* aSection = getSection( theISection ); + return aSection ? aSection->myType : CurveCreator::Polyline; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::setSectionTypeInternal( const int theISection, + const CurveCreator::SectionType theType ) +{ + CurveCreator_Section* aSection; + if (theISection == -1) { + int i = 0; + const int aNbSections = getNbSections(); + + for (; i < aNbSections; i++) { + aSection = getSection( i ); + if ( aSection ) + aSection->myType = theType; + } + redisplayCurve(); + } else { + aSection = getSection( theISection ); + if ( aSection && aSection->myType != theType ){ + aSection->myType = theType; + redisplayCurve(); + } + } + return true; +} + +/** + * Set type of the specified section (or all sections + * if \a theISection is -1). + */ +bool CurveCreator_Curve::setSectionType( const int theISection, + const CurveCreator::SectionType theType ) +{ + bool res = false; + startOperation(); + // Set the difference. + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::SetType, + theType, theISection); + } + + res = setSectionTypeInternal( theISection, theType ); + + finishOperation(); + return res; +} + + +/***********************************************/ +/*** Point methods ***/ +/***********************************************/ + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap ) +{ + bool res = false; + CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin(); + CurveCreator_Section *aSection = 0; + for ( ; anIt != theSectionsMap.end(); anIt++ ) { + int anISection = anIt->first; + aSection = getSection( anISection ); + if( aSection ) { + CurveCreator::PosPointsList aSectionPoints = anIt->second; + CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin(); + for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){ + int anIPnt = (*aPntIt)->myID; + CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords; + CurveCreator::Coordinates::iterator anIterPosition; + if(anIPnt == -1) + anIterPosition = aSection->myPoints.end(); + else + anIterPosition = aSection->myPoints.begin() + toICoord(anIPnt); + CurveCreator::Coordinates::const_iterator aFirstPosition = + aCoords.begin(); + aSection->myPoints.insert(anIterPosition, + aCoords.begin(), aCoords.end()); + } + res = true; + } + } + if(res) + redisplayCurve(); + return res; +} + +/** + * Add one point to the specified section starting from the given theIPnt index + * (or at the end of points if \a theIPnt is -1). + */ +bool CurveCreator_Curve::addPoints( const CurveCreator::Coordinates& theCoords, + const int theISection, + const int theIPnt ) +{ + bool res = false; + CurveCreator::Coordinates aCoords = theCoords; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + CurveCreator_ICurve::SectionToPointCoordsList aList; + aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theCoords)); + myListDiffs.back().init(this, CurveCreator_Operation::InsertPoints, + aList); + } + CurveCreator::SectionsMap aSectionsMap; + CurveCreator::PosPointsList aPoints; + CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theCoords ); + aPoints.push_back( aPosPoint ); + aSectionsMap[theISection] = aPoints; + + res = addPointsInternal( aSectionsMap ); + + finishOperation(); + return res; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::setPointInternal( const CurveCreator::SectionsMap &theSectionsMap ) +{ + bool res = false; + // Update the curve. + CurveCreator::SectionsMap::const_iterator anIt = theSectionsMap.begin(); + CurveCreator_Section *aSection = 0; + for ( ; anIt != theSectionsMap.end(); anIt++ ) { + int anISection = anIt->first; + aSection = getSection( anISection ); + if( aSection ) { + CurveCreator::PosPointsList aSectionPoints = anIt->second; + CurveCreator::PosPointsList::const_iterator aPntIt = aSectionPoints.begin(); + for( ; aPntIt != aSectionPoints.end(); aPntIt++ ){ + int anIPnt = (*aPntIt)->myID; + CurveCreator::Coordinates aCoords = (*aPntIt)->myCoords; + for ( int i = 0; i < myDimension; i++) + aSection->myPoints.at(toICoord(anIPnt) + i) = aCoords[i]; + } + res = true; + } + } + if(res) + redisplayCurve(); + + return res; +} + +//! Set coordinates of specified point +bool CurveCreator_Curve::setPoint( const int theISection, + const int theIPnt, + const CurveCreator::Coordinates& theNewCoords ) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + CurveCreator_ICurve::SectionToPointCoordsList aList; + aList.push_back(std::make_pair(std::make_pair(theISection, theIPnt), theNewCoords)); + myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates, + aList); + } + CurveCreator::SectionsMap aSectionsMap; + CurveCreator::PosPointsList aPoints; + CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( theIPnt, theNewCoords ); + aPoints.push_back( aPosPoint ); + aSectionsMap[theISection] = aPoints; + + int aSize1 = getNbPoints( theISection ); + res = setPointInternal( aSectionsMap ); + int aSize2 = getNbPoints( theISection ); + + finishOperation(); + + return res; +} + +//! Set coordinates of specified points from different sections +bool CurveCreator_Curve::setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords, + const bool theIsToSaveDiff ) +{ + bool res = false; + // Set the difference. + startOperation(); + if (theIsToSaveDiff && addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::SetCoordinates, + theSectionToPntCoords); + } + CurveCreator::SectionsMap aSectionsMap; + CurveCreator::PosPointsList aPosPoints; + CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = + theSectionToPntCoords.begin(), aLast = theSectionToPntCoords.end(); + int aSectionId, aPointId; + for ( ; anIt != aLast; anIt++ ) { + aPosPoints.clear(); + aSectionId = anIt->first.first; + aPointId = anIt->first.second; + CurveCreator::Coordinates aNewCoords = anIt->second; + CurveCreator_PosPoint* aPosPoint = + new CurveCreator_PosPoint( aPointId, aNewCoords ); + if( aSectionsMap.find(aSectionId) != aSectionsMap.end() ) + aPosPoints = aSectionsMap[aSectionId]; + aPosPoints.push_back( aPosPoint ); + aSectionsMap[aSectionId] = aPosPoints; + + } + res = setPointInternal( aSectionsMap ); + finishOperation(); + + return res; +} + +//! For internal use only! Undo/Redo are not used here. +bool CurveCreator_Curve::removePointsInternal( const SectionToPointList &thePoints ) +{ + bool aRes = false; + std::map > aConvPoints; + convert( thePoints, aConvPoints ); + std::map >::const_iterator anIt = aConvPoints.begin(), + aLast = aConvPoints.end(); + for ( ; anIt != aLast; anIt++ ) { + int aSectionId = anIt->first; + aRes = removeSectionPoints(aSectionId, anIt->second); + } + if( aRes) + redisplayCurve(); + + return aRes; +} + +//! Remove point with given id +bool CurveCreator_Curve::removePoint( const int theISection, const int theIPnt ) +{ + bool res = false; + // Set the difference. + startOperation(); + SectionToPointList aListOfSectionsToPoints; + aListOfSectionsToPoints.push_back(std::make_pair(theISection, theIPnt)); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints, + aListOfSectionsToPoints); + } + res = removePointsInternal( aListOfSectionsToPoints ); + finishOperation(); + return res; +} + +//! Remove several points from different sections with given ids +bool CurveCreator_Curve::removeSeveralPoints( const SectionToPointList &theSectionToPntIDs) +{ + bool res = false; + // Set the difference. + startOperation(); + if (addEmptyDiff()) { + myListDiffs.back().init(this, CurveCreator_Operation::RemovePoints, + theSectionToPntIDs); + } + res = removePointsInternal( theSectionToPntIDs ); + finishOperation(); + return res; +} + + //======================================================================= +// function: getCoordinates +// purpose: +//======================================================================= +CurveCreator::Coordinates CurveCreator_Curve::getPoint( const int theISection, + const int theIPnt) const +{ + CurveCreator_Section* aSection = getSection( theISection ); + CurveCreator::Coordinates::const_iterator + anIter = aSection->myPoints.begin() + toICoord(theIPnt); + CurveCreator::Coordinates aResult(anIter, anIter + myDimension); + + return aResult; +} + +//======================================================================= +// function: getPoints +// purpose: +//======================================================================= +CurveCreator::Coordinates CurveCreator_Curve::getPoints( const int theISection ) const +{ + CurveCreator_Section* aSection = getSection( theISection ); + return aSection ? aSection->myPoints : CurveCreator::Coordinates(); +} + +void CurveCreator_Curve::constructAISObject() +{ + TopoDS_Shape aShape; + CurveCreator_Utils::constructShape( this, aShape ); + + myAISShape = new AIS_Shape( aShape ); +} + +CurveCreator_Section* CurveCreator_Curve::getSection( const int theSectionId ) const +{ + CurveCreator_Section *aSection = 0; + if ( theSectionId >= 0 && theSectionId < mySections.size() ) + aSection = mySections.at( theSectionId ); + + return aSection; +} + +Handle(AIS_InteractiveObject) CurveCreator_Curve::getAISObject( const bool theNeedToBuild ) const +{ + if ( !myAISShape && theNeedToBuild ) { + CurveCreator_Curve* aCurve = (CurveCreator_Curve*)this; + aCurve->constructAISObject(); + } + return myAISShape; +} + +bool CurveCreator_Curve::removeSectionPoints( const int theSectionId, + const std::list& thePointIds ) +{ + bool aRes = false; + + CurveCreator_Section* aSection = getSection( theSectionId ); + if ( !aSection ) + return aRes; + + std::list aSectionPoints = thePointIds; + aSectionPoints.sort(); + std::list::const_reverse_iterator aPntIt = aSectionPoints.rbegin(); + for ( ; aPntIt != aSectionPoints.rend(); aPntIt++ ) { + int aPntIndx = *aPntIt; + CurveCreator::Coordinates::iterator aFirstPosition; + if ( aPntIndx == -1 ) + aFirstPosition = aSection->myPoints.end() - getDimension(); + else + aFirstPosition = aSection->myPoints.begin() + toICoord( aPntIndx ); + aSection->myPoints.erase( aFirstPosition, aFirstPosition + getDimension() ); + aRes = true; + } + return aRes; +} + +void CurveCreator_Curve::convert( const SectionToPointList& thePoints, + std::map< int, std::list >& theConvPoints ) { - CurveCreator_Section *aSection = - (theISection == -1 ? mySections.back() : mySections.at(theISection)); + theConvPoints.clear(); - aSection->myPoints.insert(aSection->myPoints.end(), - thePoints.begin(), thePoints.end()); - if( myListener ) - myListener->pointInserted( theISection, -1 ); + SectionToPointList::const_iterator anIt = thePoints.begin(), aLast = thePoints.end(); + std::list aPoints; + int aSectionId, aPointId; + for ( ; anIt != aLast; anIt++ ) { + aSectionId = anIt->first; + aPointId = anIt->second; + aPoints.clear(); + if ( theConvPoints.find( aSectionId ) != theConvPoints.end() ) + aPoints = theConvPoints[aSectionId]; + aPoints.push_back( aPointId ); + theConvPoints[aSectionId] = aPoints; + } } diff --git a/src/CurveCreator/CurveCreator_Curve.hxx b/src/CurveCreator/CurveCreator_Curve.hxx index 309d06a84..adcfc87a8 100644 --- a/src/CurveCreator/CurveCreator_Curve.hxx +++ b/src/CurveCreator/CurveCreator_Curve.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -23,23 +23,32 @@ #ifndef _CurveCreator_Curve_HeaderFile #define _CurveCreator_Curve_HeaderFile -#include "CurveCreator.hxx" #include "CurveCreator_ICurve.hxx" + #include "CurveCreator_Macro.hxx" -#include "CurveCreator_Operation.hxx" +#include "CurveCreator.hxx" +#include "CurveCreator_Diff.hxx" -class CurveCreator_Section; -class CurveCreator_Listener; +#include +#include + +struct CurveCreator_Section; +class CurveCreator_Displayer; +class AIS_Shape; +class Handle_AIS_InteractiveObject; /** * The CurveCreator_Curve object is represented as one or more sets of * connected points; thus CurveCreator_Curve object can contain several * not connected curves (polylines or b-splines), each such curve has two - * only ends � start and end points � in other words non-manifold curves + * only ends "start and end points" in other words non-manifold curves * are not supported. */ class CURVECREATOR_EXPORT CurveCreator_Curve : public CurveCreator_ICurve { +protected: + typedef std::list ListDiff; + public: //! Constructor of the curve. /** The dimension is explicitly specified in the constructor @@ -47,15 +56,273 @@ public: */ CurveCreator_Curve(const CurveCreator::Dimension theDimension); - /** Add points to the specified section (or last section + //! Destructor. + virtual ~CurveCreator_Curve(); + + //! Get the dimension. + virtual CurveCreator::Dimension getDimension() const; + + //! Return unique section name + virtual std::string getUniqSectionName() const; + + //! Set curve creator Displayer object + virtual void setDisplayer( CurveCreator_Displayer* theDisplayer ); + + //! Return curve creator Displayer object + CurveCreator_Displayer* getDisplayer(); + + //! Remove curve creator Displayer object + virtual void removeDisplayer(); + + /** Set depth of undo operations (unlimited if \a theDepth is -1 + * or disabled if \a theDepth is 0) + */ + virtual void setUndoDepth(const int theDepth = -1); + + //! Get depth of undo operations. + virtual int getUndoDepth() const; + + virtual void startOperation(); + virtual void finishOperation(); + + /** + * This method converts the point index to the index in + * an array of coordinates. + */ + virtual int toICoord(const int theIPnt) const; + + //! For internal use only! Undo/Redo are not used here. + virtual bool moveSectionInternal(const int theISection, + const int theNewIndex); + //! Move section to new position in list + virtual bool moveSection(const int theISection, + const int theNewIndex); + +protected: + /** This method updates all undo/redo information required to be updated + * after curve modification operation. It returns false if undo/redo + * is disabled and true otherwise. + */ + virtual bool addEmptyDiff(); + +public: // TODO: remove public + void getCoordinates( int theISection, int theIPoint, double& theX, double& theY, double& theZ ) const; +protected: // TODO: remove public + void redisplayCurve(); + +public: + /************ Implementation of INTERFACE methods ************/ + + /***********************************************/ + /*** Undo/Redo methods ***/ + /***********************************************/ + + //! Get number of available undo operations + virtual int getNbUndo() const; + + //! Undo previous operation + virtual bool undo(); + + //! Get number of available redo operations + virtual int getNbRedo() const; + + //! Redo last previously "undone" operation + virtual bool redo(); + + + /***********************************************/ + /*** Section methods ***/ + /***********************************************/ + + //! For internal use only! Undo/Redo are not used here. + virtual bool clearInternal(); + //! Clear the polyline (remove all sections) + virtual bool clear(); + + //! For internal use only! Undo/Redo are not used here. + virtual bool joinInternal( const std::list& theSections ); + + //! Join list of sections to one section (join all if the list is empty) + // The first section in the list is a leader, another sections are joined to it + virtual bool join( const std::list& theSections ); + + //! Get number of sections + virtual int getNbSections() const; + + //! For internal use only! Undo/Redo are not used here. + virtual int addSectionInternal( const std::string &theName, + const CurveCreator::SectionType theType, + const bool theIsClosed, + const CurveCreator::Coordinates &thePoints); + //! Add a new section. + virtual int addSection( const std::string &theName, + const CurveCreator::SectionType theType, + const bool theIsClosed ); + //! Add a new section. + virtual int addSection( const std::string &theName, + const CurveCreator::SectionType theType, + const bool theIsClosed, + const CurveCreator::Coordinates &thePoints); + + //! For internal use only! Undo/Redo are not used here. + virtual bool removeSectionInternal( const int theISection ); + //! Removes the given sections. + virtual bool removeSection( const int theISection ); + + //! Get "closed" flag of the specified section + virtual bool isClosed( const int theISection ) const; + + //! For internal use only! Undo/Redo are not used here. + virtual bool setClosedInternal( const int theISection, + const bool theIsClosed ); + /** + * Set "closed" flag of the specified section (all sections if + * \a theISection is -1). + */ + virtual bool setClosed( const int theISection, + const bool theIsClosed ); + + //! Returns specifyed section name + virtual std::string getSectionName( const int theISection ) const; + + //! For internal use only! Undo/Redo are not used here. + virtual bool setSectionNameInternal( const int theISection, + const std::string& theName ); + /** Set name of the specified section */ + virtual bool setSectionName( const int theISection, + const std::string& theName ); + + //! Get type of the specified section + virtual CurveCreator::SectionType getSectionType( const int theISection ) const; + + //! For internal use only! Undo/Redo are not used here. + virtual bool setSectionTypeInternal( const int theISection, + const CurveCreator::SectionType theType ); + /** + * Set type of the specified section (or all sections * if \a theISection is -1). */ - virtual void addPoints - (const CurveCreator::Coordinates &thePoints, const int theISection = -1); + virtual bool setSectionType( const int theISection, + const CurveCreator::SectionType theType ); + + + /***********************************************/ + /*** Point methods ***/ + /***********************************************/ + + //! For internal use only! Undo/Redo are not used here. + virtual bool addPointsInternal( const CurveCreator::SectionsMap &theSectionsMap ); + /** + * Add one point to the specified section starting from the given theIPnt index + * (or at the end of points if \a theIPnt is -1). + */ + virtual bool addPoints( const CurveCreator::Coordinates &theCoords, + const int theISection, + const int theIPnt = -1 ); + + //! For internal use only! Undo/Redo are not used here. + virtual bool setPointInternal( const CurveCreator::SectionsMap &theSectionsMap ); + //! Set coordinates of specified point + virtual bool setPoint( const int theISection, + const int theIPnt, + const CurveCreator::Coordinates& theNewCoords ); + + //! Set coordinates of specified points from different sections + virtual bool setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords, + const bool theIsToSaveDiff = true ); + + //! For internal use only! Undo/Redo are not used here. + virtual bool removePointsInternal( const SectionToPointList &thePoints ); + /** Remove point with given id */ + virtual bool removePoint( const int theISection, const int theIPnt = -1 ); + + //! Remove several points from different sections with given ids + virtual bool removeSeveralPoints( const SectionToPointList &theSectionToPntIDs); + + //! Get coordinates of specified point + virtual CurveCreator::Coordinates getPoint( const int theISection, + const int theIPnt ) const; + + /** + * Get points of a section (the total points in Curve if theISection is equal to -1).. + */ + virtual CurveCreator::Coordinates getPoints( const int theISection = -1 ) const; + + + /** + * Get number of points in specified section or (the total number of points + * in Curve if theISection is equal to -1). + */ + virtual int getNbPoints( const int theISection ) const; + + /** + * Set skip sorting flag. If the flag is true - points sorting will be skipped. + */ + virtual void setSkipSorting( const bool theIsToSkip ); + + /** + * Indicates whether the points can be sorted. + */ + virtual bool canPointsBeSorted(); + + /** + * Saves points coordinates difference. + * \param theOldCoords the old points coordinates + */ + virtual void saveCoordDiff( const SectionToPointCoordsList &theOldCoords ); + + /***********************************************/ + /*** Presentation methods ***/ + /***********************************************/ + /** + * Get the curve AIS object + */ + virtual Handle_AIS_InteractiveObject getAISObject( const bool theNeedToBuild = false ) const; + +protected: + /** + * Removes the points from the section. It sortes the points and remove them + * in the decreasing order + * \param theSectionId a section index + * \param thePointIds a list of section points + */ + bool removeSectionPoints( const int theSectionId, + const std::list& thePointIds ); + /** + * Converts the list of pairs of section to point into map of a section to list of points + * \param thePoints an source list + * \param theConvPoints a converted map + */ + void convert( const SectionToPointList &thePoints, + std::map > &theConvPoints ); + +protected: + virtual void constructAISObject(); + /** + * Returns the section by the section index or NULL if the index is out of the section + * list range + * \param theSectionId the section index + */ + CurveCreator_Section* getSection( const int theSectionId ) const; + +protected: + bool mySkipSorting; + +public: + bool myIsLocked; + CurveCreator::Sections mySections; //!< curve data + CurveCreator::Dimension myDimension; //!< curve dimension + CurveCreator_Displayer* myDisplayer; //!< curve displayer - friend class CurveCreator_CurveEditor; - friend class CurveCreator_Operation; +private: + int myNbUndos; + int myNbRedos; + ListDiff::iterator myCurrenPos; + ListDiff myListDiffs; + int myUndoDepth; + int myOpLevel; + AIS_Shape* myAISShape; //!< AIS shape }; #endif diff --git a/src/CurveCreator/CurveCreator_CurveEditor.cxx b/src/CurveCreator/CurveCreator_CurveEditor.cxx deleted file mode 100644 index 559eabd5a..000000000 --- a/src/CurveCreator/CurveCreator_CurveEditor.cxx +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright (C) 2013-2014 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, 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: CurveCreator_CurveEditor.cxx -// Author: Sergey KHROMOV - -#include "CurveCreator_CurveEditor.hxx" - -//======================================================================= -// function: Constructor -// purpose: -//======================================================================= -CurveCreator_CurveEditor::CurveCreator_CurveEditor - (CurveCreator_Curve* thePCurve) - : myNbUndos (0), - myNbRedos (0), - myPCurve (thePCurve), - myUndoDepth (-1), - myOpLevel(0) -{ - if (myPCurve != NULL) { - if (myPCurve->isLocked()) { - // This curve is locked by another editor. Invalid case. - myPCurve = NULL; - } else { - // Lock the curve. - myPCurve->myIsLocked = true; - myCurrenPos = myListDiffs.end(); - } - } -} - -//======================================================================= -// function: Destructor -// purpose: -//======================================================================= -CurveCreator_CurveEditor::~CurveCreator_CurveEditor() -{ - if (myPCurve != NULL) { - // Unlock the curve. - myPCurve->myIsLocked = false; - } -} - -//======================================================================= -// function: getCurve -// purpose: -//======================================================================= -CurveCreator_Curve *CurveCreator_CurveEditor::getCurve() const -{ - return myPCurve; -} - -//======================================================================= -// function: isAttached -// purpose: -//======================================================================= -bool CurveCreator_CurveEditor::isAttached() const -{ - return (myPCurve != NULL); -} - -//======================================================================= -// function: undo -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::undo() -{ - if (myNbUndos > 0) { - myNbUndos--; - myNbRedos++; - myCurrenPos--; - myCurrenPos->applyUndo(myPCurve); - } -} - -//======================================================================= -// function: redo -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::redo() -{ - if (myNbRedos > 0) { - myCurrenPos->applyRedo(myPCurve); - myCurrenPos++; - myNbRedos--; - myNbUndos++; - } -} - -//======================================================================= -// function: getNbUndo -// purpose: -//======================================================================= -int CurveCreator_CurveEditor::getNbUndo() const -{ - return myNbUndos; -} - -//======================================================================= -// function: getNbRedo -// purpose: -//======================================================================= -int CurveCreator_CurveEditor::getNbRedo() const -{ - return myNbRedos; -} - -//======================================================================= -// function: setUndoDepth -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::setUndoDepth(const int theDepth) -{ - if (theDepth == 0) { - // Reset all undo/redo data. - myNbUndos = 0; - myNbRedos = 0; - myListDiffs.clear(); - myCurrenPos = myListDiffs.end(); - myUndoDepth = 0; - } else if (theDepth == -1) { - // There is nothing to do as the depth become unlimited. - myUndoDepth = -1; - } else if (theDepth > 0) { - // The new "real" depth is set. - if (theDepth < myNbRedos) { - // The new depth is less then number of redos. Remove the latest redos. - int aShift = (myNbRedos - theDepth); - ListDiff::iterator aFromPos = myListDiffs.end(); - - while (aShift--) { - aFromPos--; - } - - myListDiffs.erase(aFromPos, myListDiffs.end()); - myNbRedos = theDepth; - } - - if (theDepth < myNbUndos + myNbRedos) { - // The new depth is less then the total number of differences. - // Remove the first undos. - int aShift = (myNbUndos + myNbRedos - theDepth); - ListDiff::iterator aToPos = myListDiffs.begin(); - - while (aShift--) { - aToPos++; - } - - myListDiffs.erase(myListDiffs.begin(), aToPos); - myNbUndos = theDepth - myNbRedos; - } - - myUndoDepth = theDepth; - } -} - -//======================================================================= -// function: getUndoDepth -// purpose: -//======================================================================= -int CurveCreator_CurveEditor::getUndoDepth() const -{ - return myUndoDepth; -} - -//======================================================================= -// function: setType -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::setType(const CurveCreator::Type theType, - const int theISection) -{ - if (myPCurve != NULL) { - startOperation(); - // Set the difference. - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::SetType, - theType, theISection); - } - - // Update the curve. - myPCurve->setType(theType, theISection); - finishOperation(); - } -} - -//======================================================================= -// function: addPoints -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::addPoints - (const CurveCreator::Coordinates &thePoints, - const int theISection) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::AddPoints, - thePoints, theISection); - } - - // Update the curve. - myPCurve->addPoints(thePoints, theISection); - finishOperation(); - } -} - -//======================================================================= -// function: addSection -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::addSection - (const std::string& theName, const CurveCreator::Type theType, - const bool theIsClosed, - const CurveCreator::Coordinates &thePoints) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::AddSection, - theName, thePoints, theType, theIsClosed); - } - - // Update the curve. - myPCurve->addSection(theName, theType, theIsClosed, thePoints); - finishOperation(); - } -} - -//======================================================================= -// function: removeSection -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::removeSection(const int theISection) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::RemoveSection, - theISection); - } - - // Update the curve. - myPCurve->removeSection(theISection); - finishOperation(); - } -} - -//======================================================================= -// function: insertPoints -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::insertPoints - (const CurveCreator::Coordinates &thePoints, - const int theISection, - const int theIPnt) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::InsertPoints, - thePoints, theISection, theIPnt); - } - - // Update the curve. - myPCurve->insertPoints(thePoints, theISection, theIPnt); - finishOperation(); - } -} - -//======================================================================= -// function: movePoints -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::movePoint(const int theISection, - const int theOrigIPnt, - const int theNewIPnt ) -{ - startOperation(); - myPCurve->movePoint(theISection, theOrigIPnt, theNewIPnt); - finishOperation(); -} - -//======================================================================= -// function: removePoints -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::removePoints - (const int theISection, - const int theIPnt, - const int theNbPoints) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::RemovePoints, - theISection, theIPnt, theNbPoints); - } - - // Update the curve. - myPCurve->removePoints(theISection, theIPnt, theNbPoints); - finishOperation(); - } -} - -//======================================================================= -// function: clear -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::clear() -{ - if (myPCurve != NULL) { - startOperation(); - // Set the difference. - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::Clear); - } - - // Update the curve. - myPCurve->clear(); - finishOperation(); - } -} - -//======================================================================= -// function: setCoordinates -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::setCoordinates - (const CurveCreator::Coordinates &theCoords, - const int theISection, - const int theIPnt) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::SetCoordinates, - theCoords, theISection, theIPnt); - } - - // Update the curve. - myPCurve->setCoordinates(theCoords, theISection, theIPnt); - finishOperation(); - } -} - -//======================================================================= -// function: setClosed -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::setClosed(const bool theIsClosed, - const int theISection) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::SetClosed, - theIsClosed, theISection); - } - - // Update the curve. - myPCurve->setClosed(theIsClosed, theISection); - finishOperation(); - } -} - -//======================================================================= -// function: setName -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::setName(const std::string& theName, - const int theISection) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::RenameSection, - theName, theISection); - } - myPCurve->setName( theName, theISection ); - finishOperation(); - } -} - -//======================================================================= -// function: moveSection -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::moveSection(const int theISection, - const int theNewIndex) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::MoveSection, - theISection, theNewIndex); - } - - // Update the curve. - myPCurve->moveSection(theISection, theNewIndex); - finishOperation(); - } -} - -//======================================================================= -// function: join -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::join(const int theISectionTo, - const int theISectionFrom) -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::Join, - theISectionTo, theISectionFrom); - } - - // Update the curve. - myPCurve->join(theISectionTo, theISectionFrom); - finishOperation(); - } -} - -//======================================================================= -// function: join -// purpose: -//======================================================================= -void CurveCreator_CurveEditor::join() -{ - if (myPCurve != NULL) { - // Set the difference. - startOperation(); - if (addEmptyDiff()) { - myListDiffs.back().init(myPCurve, CurveCreator_Operation::Join); - } - - // Update the curve. - myPCurve->join(); - finishOperation(); - } -} - -//======================================================================= -// function: addDiff -// purpose: -//======================================================================= -bool CurveCreator_CurveEditor::addEmptyDiff() -{ - bool isEnabled = false; - - if (myUndoDepth != 0) { - // Forget all Redos after the current one. - if (myNbRedos > 0) { - myNbRedos = 0; - myListDiffs.erase(myCurrenPos, myListDiffs.end()); - } - - if (myUndoDepth == -1 || myNbUndos < myUndoDepth) { - // Increase the number of undos. - myNbUndos++; - } else { - // If there are too many differences, remove the first one. - myListDiffs.pop_front(); - } - - // Add new difference. - myListDiffs.push_back(CurveCreator_Diff()); - myCurrenPos = myListDiffs.end(); - isEnabled = true; - } - - return isEnabled; -} - -void CurveCreator_CurveEditor::startOperation() -{ - myOpLevel++; -} - -void CurveCreator_CurveEditor::finishOperation() -{ - myOpLevel--; -} diff --git a/src/CurveCreator/CurveCreator_CurveEditor.hxx b/src/CurveCreator/CurveCreator_CurveEditor.hxx deleted file mode 100644 index 32aa00948..000000000 --- a/src/CurveCreator/CurveCreator_CurveEditor.hxx +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (C) 2013-2014 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, 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: CurveCreator_CurveEditor.hxx -// Author: Sergey KHROMOV - -#ifndef _CurveCreator_CurveEditor_HeaderFile -#define _CurveCreator_CurveEditor_HeaderFile - -#include "CurveCreator_Diff.hxx" -#include "CurveCreator_Curve.hxx" - -#include - -/** - * The CurveCreator_CurveEditor is designed to manage of - * editing operations of CurveCreator_Curve class. - */ -class CURVECREATOR_EXPORT CurveCreator_CurveEditor -{ - -private: - - typedef std::list ListDiff; - -public: - - //! Constuctor, initialized by the curve object - CurveCreator_CurveEditor(CurveCreator_Curve* thePCurve); - - //! Destructor, detaches from the Curve - ~CurveCreator_CurveEditor(); - - //! Returns the curve. - CurveCreator_Curve *getCurve() const; - - //! This method returns true if this editor is attached to a valid curve. - bool isAttached() const; - - //! Undo previous operation - void undo(); - - //! Redo last previously �undoed� operation - void redo(); - - //! Get number of available undo operations - int getNbUndo() const; - - //! Get number of available redo operations - int getNbRedo() const; - - //! Set depth of undo operations (unlimited if \a theDepth is -1 - // or disabled if \a theDepth is 0) - void setUndoDepth(const int theDepth = -1); - - //! Get depth of undo operations. - int getUndoDepth() const; - - /** Set type of the specified section (or all sections - * if \a theISection is -1). - */ - void setType(const CurveCreator::Type theType, const int theISection = -1); - - /** Set section closed (or all sections - * if \a theISection is -1). - */ - void setClosed(const bool theIsClosed, const int theISection); - - /** Set section name (if theISection is invalid it is ignored). - */ - void setName(const std::string& theName, const int theISection); - - /** Add points to the specified section (or last section - * if \a theISection is -1). - */ - void addPoints(const CurveCreator::Coordinates &thePoints, - const int theISection = -1); - - //! Add a new section. - void addSection(const std::string &theName, const CurveCreator::Type theType, - const bool theIsClosed, - const CurveCreator::Coordinates &thePoints); - - //! Removes the section. If theISection equals -1, removes the last section. - void removeSection(const int theISection = -1); - - /** Insert points in the given position (add to the end of list - * if \a theIPnt parameter is -1) of the specified section - * (or last section if \a theISection parameter is -1). - */ - void insertPoints(const CurveCreator::Coordinates &thePoints, - const int theISection = -1, - const int theIPnt = -1); - - /** Remove \a nbPoints points from given \a theISection, - * starting from given \a theIPnt (of all points up to the end of - * section if \a theNbPoints is -1). - */ - void removePoints(const int theISection, - const int theIPnt, - const int theNbPoints = -1); - - /** Mobe point in \a theISection from given position \a theOrigIPnt - * to new position \a theNewIPnt. - */ - void movePoint(const int theISection, - const int theOrigIPnt, - const int theNewIPnt ); - - //! Remove all sections. - void clear(); - - //! Set coordinates of specified point - void setCoordinates(const CurveCreator::Coordinates &theCoords, - const int theISection, - const int theIPnt); - - /** Move specified \a theISection to the specified position - * in the sections list. - */ - void moveSection(const int theISection, const int theNewIndex); - - //! Join two sections to one section - void join(const int theISectionTo, const int theISectionFrom); - - //! Join all sections to the single curve - void join(); - - void startOperation(); - void finishOperation(); -private: - - /** This method updates all undo/redo information required to be updated - * after curve modification operation. It returns false if undo/redo - * is disabled and true otherwise. - */ - bool addEmptyDiff(); - -private: - - int myNbUndos; - int myNbRedos; - ListDiff::iterator myCurrenPos; - ListDiff myListDiffs; - CurveCreator_Curve* myPCurve; - int myUndoDepth; - int myOpLevel; -}; - -#endif diff --git a/src/CurveCreator/CurveCreator_Diff.cxx b/src/CurveCreator/CurveCreator_Diff.cxx index 22f099e11..d1a7dc322 100644 --- a/src/CurveCreator/CurveCreator_Diff.cxx +++ b/src/CurveCreator/CurveCreator_Diff.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -49,9 +49,9 @@ CurveCreator_Diff::~CurveCreator_Diff() // function: init // purpose: //======================================================================= -bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, - const CurveCreator_Operation::Type theType) +bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve) { + CurveCreator_Operation::Type aType = CurveCreator_Operation::Clear; bool isOK = false; if (theCurve != NULL) { @@ -60,36 +60,18 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, // Set redo. myPRedo = new CurveCreator_Operation; - if (myPRedo->init(theType)) { + if (myPRedo->init(aType)) { isOK = true; const int aNbSections = theCurve->getNbSections(); - if (theType == CurveCreator_Operation::Clear) { - // Construct undo for Clear command. - if (aNbSections > 0) { - setNbUndos(aNbSections); + // Construct undo for Clear command. + if (aNbSections > 0) { + setNbUndos(aNbSections); - for (int i = 0; i < aNbSections && isOK; i++) { - // Add AddSection command. - isOK = addSectionToUndo(theCurve, i, myPUndo[i]); - } - } - } else { // theType == CurveCreator_Operation::Join - // Construct undo for Join command. - if (aNbSections > 1) { - // Add the RemovePoints command to remove points of - // the second section fron the first one. - const int aNbPoints = theCurve->getNbPoints(0); - - setNbUndos(aNbSections); - isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints, - 0, aNbPoints, -1); - - for (int i = 1; i < aNbSections && isOK; i++) { - // Add AddSection command. - isOK = addSectionToUndo(theCurve, i, myPUndo[i]); - } + for (int i = 0; i < aNbSections && isOK; i++) { + // Add AddSection command. + isOK = addSectionToUndo(theCurve, i, myPUndo[i]); } } } @@ -176,33 +158,6 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, setNbUndos(1); isOK = myPUndo[0].init(theType, theIntParam2, theIntParam1); break; - case CurveCreator_Operation::Join: - { - // If the last section is removed, one AddSection command is - // enough. If not last section is removed, two commands are - // requred: AddSection and MoveSection. - const int aLastIndex = theCurve->getNbSections() - 1; - const int aNbPoints = theCurve->getNbPoints(theIntParam1); - - if (theIntParam2 == aLastIndex) { - setNbUndos(2); - } else { - setNbUndos(3); - } - - isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints, - theIntParam1, aNbPoints, -1); - - if (isOK) { - isOK = addSectionToUndo(theCurve, theIntParam2, myPUndo[1]); - - if (isOK && theIntParam2 != aLastIndex) { - isOK = myPUndo[2].init(CurveCreator_Operation::MoveSection, - aLastIndex, theIntParam2); - } - } - } - break; default: break; } @@ -222,77 +177,68 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, //======================================================================= bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const int theIntParam1, - const int theIntParam2, - const int theIntParam3) + const std::list& theParams) { bool isOK = false; - if (theCurve != NULL) { + if (theCurve != NULL || theParams.empty()) { clear(); // Set redo. myPRedo = new CurveCreator_Operation; - if (myPRedo->init(theType, theIntParam1, theIntParam2, theIntParam3)) { - // Construct undo for RemovePoints command. - const CurveCreator::Dimension aDim = theCurve->getDimension(); - const CurveCreator::Coordinates &aPoints = - theCurve->getPoints(theIntParam1); - CurveCreator::Coordinates::const_iterator anIterBegin = - aPoints.begin() + (aDim*theIntParam2); - CurveCreator::Coordinates::const_iterator anIterEnd; - - if (theIntParam3 == -1) { - anIterEnd = aPoints.end(); - } else { - anIterEnd = anIterBegin + (aDim*theIntParam3); - } - - CurveCreator::Coordinates aPointsToAdd; - - setNbUndos(1); - aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd); - isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints, - aPointsToAdd, theIntParam1, theIntParam2); - } - - if (!isOK) { - clear(); - } - } - - return isOK; -} - -//======================================================================= -// function: init -// purpose: -//======================================================================= -bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, - const CurveCreator_Operation::Type theType, - const CurveCreator::Coordinates &theCoords, - const int theIntParam) -{ - bool isOK = false; - - if (theCurve != NULL) { - clear(); - - // Set redo. - myPRedo = new CurveCreator_Operation; + if (myPRedo->init(theType, theParams)) { + // Construct undo for different commands. + switch (theType) { + case CurveCreator_Operation::Join: + { + int aSectionMain = theParams.front(); + const int aNbPointsMain = theCurve->getNbPoints(aSectionMain); + + std::list aSectionsToJoin = theParams; + aSectionsToJoin.erase( aSectionsToJoin.begin() ); + // it is important to sort the section indices in order to correct perform undo + // for the move sections to the previous positions + aSectionsToJoin.sort(); + // 1rst undo for remove points from the main and n-1 undoes to contain joined sections + int aSectionsToJoinNb = aSectionsToJoin.size(); + int aNbUndos = 2*aSectionsToJoinNb + 1; + setNbUndos( aNbUndos ); + + // Add joined sections to undo + std::list::const_iterator anIt = aSectionsToJoin.begin(), + aLast = aSectionsToJoin.end(); + anIt = aSectionsToJoin.begin(); + int aLastSectionId = -1; + for (int i = 0; anIt != aLast && i < aSectionsToJoinNb; anIt++, i++) { + int anISection = *anIt; + isOK = addSectionToUndo( theCurve, anISection, myPUndo[i*2] ); + if (isOK) { + isOK = myPUndo[i*2+1].init(CurveCreator_Operation::MoveSection, + aLastSectionId, anISection); + if (!isOK) + break; + } + } + // Construct undo for RemovePoints command. + if (isOK) { + int aNbPointsInJoined = 0; + anIt = aSectionsToJoin.begin(); + for ( ; anIt != aLast; anIt++ ) + aNbPointsInJoined += theCurve->getNbPoints( *anIt ); - if (myPRedo->init(theType, theCoords, theIntParam)) { - // Construct undo for AddPoints command. - const int aSectionInd = getSectionIndex(theCurve, theIntParam); - const CurveCreator::Dimension aDim = theCurve->getDimension(); - const CurveCreator::Coordinates &aPoints = - theCurve->getPoints(aSectionInd); - const int aNbPoints = (aPoints.size()/aDim); + int aJoinedSize = aNbPointsMain + aNbPointsInJoined; + CurveCreator_ICurve::SectionToPointList aSectionToPointList; + for (int anIPoint = aNbPointsMain; anIPoint < aJoinedSize; anIPoint++) + aSectionToPointList.push_back(std::make_pair(aSectionMain, anIPoint)); - setNbUndos(1); - isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints, - aSectionInd, aNbPoints, -1); + isOK = myPUndo[aNbUndos-1].init(CurveCreator_Operation::RemovePoints, aSectionToPointList); + } + } + break; + default: + break; + } } if (!isOK) { @@ -337,15 +283,33 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, return isOK; } -//======================================================================= -// function: init -// purpose: -//======================================================================= bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const CurveCreator::Coordinates &theCoords, - const int theIntParam1, - const int theIntParam2) + const std::string &theName, + const int theIntParam1 ) +{ + bool isOK = false; + myPRedo = new CurveCreator_Operation; + + if (myPRedo->init(theType, theName, theIntParam1 )) { + // Construct undo for different commands. + switch (theType) { + case CurveCreator_Operation::RenameSection: + setNbUndos(1); + isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection, + theCurve->getSectionName(theIntParam1), theIntParam1); + break; + } + } + if( !isOK ){ + clear(); + } + return isOK; +} + +bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, + const CurveCreator_Operation::Type theType, + const CurveCreator_ICurve::SectionToPointList &theParamList1) { bool isOK = false; @@ -355,35 +319,90 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, // Set redo. myPRedo = new CurveCreator_Operation; - if (myPRedo->init(theType, theCoords, theIntParam1, theIntParam2)) { + if (myPRedo->init(theType, theParamList1)) { // Construct undo for different commands. switch (theType) { - case CurveCreator_Operation::InsertPoints: + case CurveCreator_Operation::RemovePoints: { + // Construct undo for RemovePoints command. + CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointCoords; + CurveCreator::Coordinates aPointsToAdd; const CurveCreator::Dimension aDim = theCurve->getDimension(); - const int aNbPoints = (theCoords.size()/aDim); - const int aSectionInd = getSectionIndex(theCurve, theIntParam1); - int aPointInd; - - if (theIntParam2 == -1) { - aPointInd = theCurve->getNbPoints(aSectionInd); - } else { - aPointInd = theIntParam2; + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end(); + std::list aPoints; + int aSectionId, aPointId; + for ( ; anIt != aLast; anIt++ ) { + aPointsToAdd.clear(); + aSectionId = anIt->first; + aPointId = anIt->second; + const CurveCreator::Coordinates &aPoints = + theCurve->getPoints(aSectionId); + CurveCreator::Coordinates::const_iterator anIterBegin = + aPoints.begin() + (aDim*aPointId); + CurveCreator::Coordinates::const_iterator anIterEnd = + anIterBegin + aDim; + aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd); + aSectionToPointCoords.push_back(std::make_pair(*anIt, aPointsToAdd)); } + setNbUndos(1); + isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints, + aSectionToPointCoords); + } + break; + default: + break; + } + } + + if (!isOK) { + clear(); + } + } + return isOK; +} + +bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, + const CurveCreator_Operation::Type theType, + const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1) +{ + bool isOK = false; + + if (theCurve != NULL) { + clear(); + + // Set redo. + myPRedo = new CurveCreator_Operation; + + if (myPRedo->init(theType, theParamList1)) { + // Construct undo for different commands. + switch (theType) { + case CurveCreator_Operation::InsertPoints: + { + // Construct undo for RemovePoints command. + CurveCreator_ICurve::SectionToPointList aSectionToPointList; + CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end(); + for ( ; anIt != aLast; anIt++ ) { + aSectionToPointList.push_back(anIt->first); + } setNbUndos(1); isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints, - aSectionInd, aPointInd, aNbPoints); + aSectionToPointList); } break; case CurveCreator_Operation::SetCoordinates: { - const CurveCreator::Coordinates anOldCoords = - theCurve->getCoordinates(theIntParam1, theIntParam2); + // Construct undo for SetCoordinates command. + CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointOldCoords; + CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end(); + for ( ; anIt != aLast; anIt++ ) { + CurveCreator::Coordinates anOldCoords = theCurve->getPoint(anIt->first.first, anIt->first.second); + aSectionToPointOldCoords.push_back(std::make_pair(anIt->first, anOldCoords)); + } setNbUndos(1); isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates, - anOldCoords, theIntParam1, theIntParam2); + aSectionToPointOldCoords); } break; default: @@ -400,26 +419,37 @@ bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, } bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve, - const CurveCreator_Operation::Type theType, - const std::string &theName, - const int theIntParam1 ) + const CurveCreator_ICurve::SectionToPointCoordsList &theOldParamList) { bool isOK = false; - myPRedo = new CurveCreator_Operation; - if (myPRedo->init(theType, theName, theIntParam1 )) { - // Construct undo for different commands. - switch (theType) { - case CurveCreator_Operation::RenameSection: - setNbUndos(1); - isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection, - theCurve->getSectionName(theIntParam1), theIntParam1); - break; - } - } - if( !isOK ){ + if (theCurve != NULL && theOldParamList.size() > 0) { clear(); + + // Set redo. + myPRedo = new CurveCreator_Operation; + + // Construct redo for SetCoordinates command. + CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointActualCoords; + CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = + theOldParamList.begin(), aLast = theOldParamList.end(); + for ( ; anIt != aLast; anIt++ ) { + CurveCreator::Coordinates anActualCoords = theCurve->getPoint(anIt->first.first, anIt->first.second); + aSectionToPointActualCoords.push_back(std::make_pair(anIt->first, anActualCoords)); + } + + if (myPRedo->init(CurveCreator_Operation::SetCoordinates, aSectionToPointActualCoords)) { + // Undo for SetCoordinates command. + setNbUndos(1); + isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates, + theOldParamList); + } + + if (!isOK) { + clear(); + } } + return isOK; } @@ -495,12 +525,13 @@ bool CurveCreator_Diff::addSectionToUndo const int theIndex, CurveCreator_Operation &theOperation) const { + const std::string aName = theCurve->getSectionName(theIndex); const CurveCreator::Coordinates &aPnts = theCurve->getPoints(theIndex); - const CurveCreator::Type aType = theCurve->getType(theIndex); + const CurveCreator::SectionType aType = theCurve->getSectionType(theIndex); const bool isClosed = theCurve->isClosed(theIndex); bool isOK = theOperation.init(CurveCreator_Operation::AddSection, - aPnts, aType, isClosed); + aName, aPnts, aType, isClosed); return isOK; } @@ -533,7 +564,7 @@ bool CurveCreator_Diff::setTypeOrClosedToUndo // Get sections to be modified. for (i = 0; i < aNbSections; i++) { if (isSetType) { - aValue = theCurve->getType(i); + aValue = theCurve->getSectionType(i); } else { aValue = theCurve->isClosed(i); } @@ -556,7 +587,7 @@ bool CurveCreator_Diff::setTypeOrClosedToUndo // There is only particular section modified. // Check if there is a real modification required. if (isSetType) { - aValue = theCurve->getType(theIntParam2); + aValue = theCurve->getSectionType(theIntParam2); } else { aValue = theCurve->isClosed(theIntParam2); } @@ -572,7 +603,7 @@ bool CurveCreator_Diff::setTypeOrClosedToUndo std::list::iterator anIter = aListOfInd.begin(); if (isSetType) { - aValue = theCurve->getType(*anIter); + aValue = theCurve->getSectionType(*anIter); } else { aValue = theCurve->isClosed(*anIter); } diff --git a/src/CurveCreator/CurveCreator_Diff.hxx b/src/CurveCreator/CurveCreator_Diff.hxx index e56b294f2..f55f5306f 100644 --- a/src/CurveCreator/CurveCreator_Diff.hxx +++ b/src/CurveCreator/CurveCreator_Diff.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -56,11 +56,9 @@ public: * parameters. It is applicable to the following operations: *
      *
    • Clear
    • - *
    • Join (without arguments)
    • *
    */ - bool init(const CurveCreator_Curve *theCurve, - const CurveCreator_Operation::Type theType); + bool init(const CurveCreator_Curve *theCurve); /** * This method initializes the difference with an operation with one integer @@ -80,7 +78,6 @@ public: *
  • SetType
  • *
  • SetClosed
  • *
  • MoveSection
  • - *
  • Join (with 2 int arguments)
  • * */ bool init(const CurveCreator_Curve *theCurve, @@ -88,74 +85,77 @@ public: const int theIntParam1, const int theIntParam2); - /** - * This method initializes the difference with an operation with three - * integer parameters. It is applicable to the following operations: + /** + * This method initializes the difference with an operation with two integer + * parameters. It is applicable to the following operations: *
      - *
    • RemovePoints
    • + *
    • Join (with a list of int arguments)
    • *
    */ bool init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const int theIntParam1, - const int theIntParam2, - const int theIntParam3); + const std::list& theParams); /** * This method initializes the difference with an operation with one - * CurveCreator::Coordinates parameter and one integer parameter. + * Name, one CurveCreator::Coordinates parameter and two integer parameters. * It is applicable to the following operations: *
      - *
    • AddPoints
    • + *
    • AddSection
    • *
    */ bool init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, + const std::string& theName, const CurveCreator::Coordinates &theCoords, - const int theIntParam); + const int theIntParam1, + const int theIntParam2); /** * This method initializes the difference with an operation with one - * CurveCreator::Coordinates parameter and two integer parameters. + * string and one integer parameters. * It is applicable to the following operations: *
      - *
    • InsertPoints
    • - *
    • SetCoordinates
    • + *
    • RenameSection
    • *
    */ bool init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const CurveCreator::Coordinates &theCoords, - const int theIntParam1, - const int theIntParam2); + const std::string &theName, + const int theIntParam1 ); /** - * This method initializes the difference with an operation with one - * Name, one CurveCreator::Coordinates parameter and two integer parameters. + * This method initializes the difference with an operation with + * list of pairs of integer parameters. * It is applicable to the following operations: *
      - *
    • AddSection
    • + *
    • RemovePoints
    • *
    */ bool init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const std::string& theName, - const CurveCreator::Coordinates &theCoords, - const int theIntParam1, - const int theIntParam2); + const CurveCreator_ICurve::SectionToPointList &theParamList); /** - * This method initializes the difference with an operation with one - * string and one integer parameters. + * This method initializes the difference with an operation with + * list of pairs of integer parameters with point coordinates. * It is applicable to the following operations: *
      - *
    • RenameSection
    • + *
    • RemovePoints
    • *
    */ bool init(const CurveCreator_Curve *theCurve, const CurveCreator_Operation::Type theType, - const std::string &theName, - const int theIntParam1 ); + const CurveCreator_ICurve::SectionToPointCoordsList &theParamList); + + /** + * This method initializes the difference with an operation with + * list of pairs of integer parameters with point coordinates. + * \param theCurve the modified curve + * \param theOldParamList the old parameters (to be saved for undo) + */ + bool init(const CurveCreator_Curve *theCurve, + const CurveCreator_ICurve::SectionToPointCoordsList &theOldParamList); /** * This method applies undo operation to theCurve. diff --git a/src/CurveCreator/CurveCreator_Displayer.cxx b/src/CurveCreator/CurveCreator_Displayer.cxx new file mode 100644 index 000000000..22ae3990c --- /dev/null +++ b/src/CurveCreator/CurveCreator_Displayer.cxx @@ -0,0 +1,64 @@ +#include "CurveCreator_Displayer.hxx" + +CurveCreator_Displayer::CurveCreator_Displayer( Handle_AIS_InteractiveContext theContext, + const int theZLayer ) : + myContext( theContext ), myZLayer( theZLayer ) +{ + myObjects.clear(); +} + +CurveCreator_Displayer::~CurveCreator_Displayer(void) +{ + eraseAll( true ); + for( int i = 0 ; i < myObjects.size() ; i++ ){ + myObjects[i].Nullify(); + } + myObjects.clear(); +} + +void CurveCreator_Displayer::display( const Handle(AIS_InteractiveObject)& theObject, bool isUpdate ) +{ + if ( theObject.IsNull() ) + return; + + myObjects.push_back( theObject ); + myContext->Display( theObject, Standard_False ); + + if ( myZLayer >= 0 ) + myContext->SetZLayer( theObject, myZLayer ); + + if( isUpdate ) + myContext->UpdateCurrentViewer(); +} + +void CurveCreator_Displayer::eraseAll( bool isUpdate ) +{ + if(myObjects.empty()) + return; + for( int i = 0 ; i < myObjects.size() ; i++ ){ + myContext->Erase(myObjects[i], Standard_False); + } + myObjects.clear(); + if( isUpdate ) + myContext->UpdateCurrentViewer(); +} + +Quantity_Color CurveCreator_Displayer::getActiveColor( bool isHL ) +{ + if( isHL ){ + return Quantity_Color( 1., 0., 0., Quantity_TOC_RGB ); + } + return Quantity_Color( 0., 1., 0., Quantity_TOC_RGB ); +} + +/*void CurveCreator_Displayer::highlight( const AISObjectsList& theObjects, bool isHL ) +{ + return; + //TODO: + Quantity_Color aColor = getActiveColor( isHL ); + for( int i = 0 ; i < theObjects.size() ; i++ ){ + theObjects[i]->SetColor(aColor); + myContext->Display(theObjects[i], Standard_False); + } + myContext->UpdateCurrentViewer(); +}*/ diff --git a/src/CurveCreator/CurveCreator_Displayer.hxx b/src/CurveCreator/CurveCreator_Displayer.hxx new file mode 100644 index 000000000..f65e9d2ec --- /dev/null +++ b/src/CurveCreator/CurveCreator_Displayer.hxx @@ -0,0 +1,33 @@ +#ifndef CURVECREATOR_DISPLAYER_H +#define CURVECREATOR_DISPLAYER_H + +#include "CurveCreator_Macro.hxx" + +#include +#include + +#include + +class CURVECREATOR_EXPORT CurveCreator_Displayer +{ +typedef std::vector AISObjectsList; + +public: + CurveCreator_Displayer( Handle_AIS_InteractiveContext theContext, + const int theZLayer = -1 ); + ~CurveCreator_Displayer(void); + + void display( const Handle_AIS_InteractiveObject& theObject, bool isUpdate ); + void eraseAll( bool isUpdate ); + //void highlight( const AISObjectsList& theObjects, bool isHL ); + +protected: + Quantity_Color getActiveColor( bool isHL ); + +private: + Handle_AIS_InteractiveContext myContext; + AISObjectsList myObjects; + int myZLayer; +}; + +#endif diff --git a/src/CurveCreator/CurveCreator_ICurve.cxx b/src/CurveCreator/CurveCreator_ICurve.cxx deleted file mode 100644 index fc73f56e7..000000000 --- a/src/CurveCreator/CurveCreator_ICurve.cxx +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright (C) 2013-2014 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, 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: CurveCreator_ICurve.cxx -// Author: Sergey KHROMOV - -#include "CurveCreator_ICurve.hxx" -#include "CurveCreator_Section.hxx" -#include "CurveCreator_Listener.hxx" - -#include - -//======================================================================= -// function: Constructor -// purpose: -//======================================================================= -CurveCreator_ICurve::CurveCreator_ICurve - (const CurveCreator::Dimension theDimension) -: myIsLocked (false), - myDimension (theDimension), - myListener(NULL) -{ -} - -//======================================================================= -// function: Destructor -// purpose: -//======================================================================= -CurveCreator_ICurve::~CurveCreator_ICurve() -{ - // Delete all allocated data. - clear(); -} - -//======================================================================= -// function: isLocked -// purpose: -//======================================================================= -bool CurveCreator_ICurve::isLocked() const -{ - return myIsLocked; -} - -//======================================================================= -// function: getDimension -// purpose: -//======================================================================= -CurveCreator::Dimension CurveCreator_ICurve::getDimension() const -{ - return myDimension; -} - -//======================================================================= -// function: getNbPoints -// purpose: -//======================================================================= -int CurveCreator_ICurve::getNbPoints(const int theISection) const -{ - int aNbCoords = 0; - - if (theISection == -1) { - int i = 0; - const int aNbSections = getNbSections(); - - for (; i < aNbSections; i++) { - aNbCoords += mySections[i]->myPoints.size(); - } - } else { - aNbCoords = mySections.at(theISection)->myPoints.size(); - } - - return aNbCoords/myDimension; -} - -//======================================================================= -// function: getNbSections -// purpose: -//======================================================================= -int CurveCreator_ICurve::getNbSections() const -{ - return mySections.size(); -} - -//======================================================================= -// function: getCoordinates -// purpose: -//======================================================================= -CurveCreator::Coordinates CurveCreator_ICurve::getCoordinates - (const int theISection, const int theIPnt) const -{ - CurveCreator_Section *aSection = mySections.at(theISection); - CurveCreator::Coordinates::const_iterator - anIter = aSection->myPoints.begin() + toICoord(theIPnt); - CurveCreator::Coordinates aResult(anIter, anIter + myDimension); - - return aResult; -} - -//======================================================================= -// function: getType -// purpose: -//======================================================================= -CurveCreator::Type CurveCreator_ICurve::getType(const int theISection) const -{ - return mySections.at(theISection)->myType; -} - -//======================================================================= -// function: getPoints -// purpose: -//======================================================================= -const CurveCreator::Coordinates &CurveCreator_ICurve::getPoints - (const int theISection) const -{ - return mySections.at(theISection)->myPoints; -} - -//======================================================================= -// function: isClosed -// purpose: -//======================================================================= -bool CurveCreator_ICurve::isClosed(const int theISection) const -{ - return mySections.at(theISection)->myIsClosed; -} - -std::string CurveCreator_ICurve::getSectionName(const int theISection) const -{ - return mySections.at(theISection)->myName; -} - -//======================================================================= -// function: setType -// purpose: -//======================================================================= -void CurveCreator_ICurve::setType - (const CurveCreator::Type theType, const int theISection) -{ - if (theISection == -1) { - int i = 0; - const int aNbSections = getNbSections(); - - for (; i < aNbSections; i++) { - mySections[i]->myType = theType; - } - if( myListener ) - myListener->curveChanged(); - } else { - if( mySections.at(theISection)->myType != theType ){ - mySections.at(theISection)->myType = theType; - if( myListener ) - myListener->sectionTypeChanged(theISection); - } - } -} - -//======================================================================= -// function: addSection -// purpose: -//======================================================================= -void CurveCreator_ICurve::addSection - (const std::string& theName, - const CurveCreator::Type theType, - const bool theIsClosed, - const CurveCreator::Coordinates &thePoints) -{ - CurveCreator_Section *aSection = new CurveCreator_Section; - - std::string aName = theName; - if( aName.empty() ){ - aName = getUnicSectionName(); - } - aSection->myName = aName; - aSection->myType = theType; - aSection->myIsClosed = theIsClosed; - aSection->myPoints = thePoints; - mySections.push_back(aSection); - if( myListener ) - myListener->sectionAdded( -1 ); -} - -//======================================================================= -// function: removeSection -// purpose: -//======================================================================= -void CurveCreator_ICurve::removeSection(const int theISection) -{ - if (theISection == -1) { - delete mySections.back(); - mySections.pop_back(); - } else { - Sections::iterator anIterRm = mySections.begin() + theISection; - - delete *anIterRm; - mySections.erase(anIterRm); - } - if( myListener ) - myListener->sectionRemoved(theISection); -} - -//======================================================================= -// function: insertPoints -// purpose: -//======================================================================= -void CurveCreator_ICurve::insertPoints - (const CurveCreator::Coordinates &thePoints, - const int theISection, - const int theIPnt) -{ - if (theIPnt == -1) { - // Add points to the end of section points. - addPoints(thePoints, theISection); - } else { - CurveCreator_Section *aSection = - (theISection == -1 ? mySections.back() : mySections.at(theISection)); - - aSection->myPoints.insert(aSection->myPoints.begin() + toICoord(theIPnt), - thePoints.begin(), thePoints.end()); - if( myListener ) - myListener->pointInserted( theISection, theIPnt ); - } -} - -void CurveCreator_ICurve::movePoint(const int theISection, const int theIPointFrom, const int theNewIndex) -{ - CurveCreator::Coordinates aCoords = getCoordinates(theISection, theIPointFrom ); - insertPoints(aCoords, theISection, theNewIndex+1); - int aRemPntIndx = theIPointFrom; - if( theNewIndex < theIPointFrom ) - aRemPntIndx++; - removePoints(theISection, aRemPntIndx, 1 ); -} - -//======================================================================= -// function: removePoints -// purpose: -//======================================================================= -void CurveCreator_ICurve::removePoints(const int theISection, - const int theIPnt, - const int theNbPoints) -{ - CurveCreator_Section *aSection = mySections.at(theISection); - CurveCreator::Coordinates::iterator anIterBegin = - aSection->myPoints.begin() + toICoord(theIPnt); - CurveCreator::Coordinates::iterator anIterEnd = - (theNbPoints == -1 ? - aSection->myPoints.end() : anIterBegin + toICoord(theNbPoints)); - - aSection->myPoints.erase(anIterBegin, anIterEnd); - if( myListener ) - myListener->pointRemoved(theISection, theIPnt, theNbPoints ); -} - -//======================================================================= -// function: clear -// purpose: -//======================================================================= -void CurveCreator_ICurve::clear() -{ - // Delete all allocated data. - int i = 0; - const int aNbSections = getNbSections(); - - for (; i < aNbSections; i++) { - delete mySections[i]; - } - - mySections.clear(); - if( myListener ) - myListener->curveChanged(); -} - -//======================================================================= -// function: setCoordinates -// purpose: -//======================================================================= -void CurveCreator_ICurve::setCoordinates - (const CurveCreator::Coordinates &theCoords, - const int theISection, - const int theIPnt) -{ - if (theCoords.size() == myDimension) { - CurveCreator_Section *aSection = mySections.at(theISection); - int i; - - for (i = 0; i < myDimension; i++) { - aSection->myPoints.at(toICoord(theIPnt) + i) = theCoords[i]; - } - - if( myListener ) - myListener->pointChanged( theISection, theIPnt ); - } -} - -//======================================================================= -// function: setClosed -// purpose: -//======================================================================= -void CurveCreator_ICurve::setClosed(const bool theIsClosed, - const int theISection) -{ - if (theISection == -1) { - int aSize = mySections.size(); - int i; - - for (i = 0; i < aSize; i++) { - mySections[i]->myIsClosed = theIsClosed; - if( myListener ){ - myListener->sectionClosed( theISection, theIsClosed ); - } - } - } else { - mySections.at(theISection)->myIsClosed = theIsClosed; - if( myListener ){ - myListener->sectionClosed( theISection, theIsClosed ); - } - } -} - -/** Set name of the specified section. - */ -void CurveCreator_ICurve::setName( const std::string& theName, const int theISection ) -{ - if( ( theISection >= 0 ) && ( theISection < mySections.size() )){ - mySections.at(theISection)->myName = theName; - } -} - -//======================================================================= -// function: moveSection -// purpose: -//======================================================================= -void CurveCreator_ICurve::moveSection(const int theISection, - const int theNewIndex) -{ - if (theISection != theNewIndex) { - CurveCreator_Section *aSection = mySections.at(theISection); - - // Remove section - Sections::iterator anIter = mySections.begin() + theISection; - - mySections.erase(anIter); - - // Insert section. - anIter = mySections.begin() + theNewIndex; - mySections.insert(anIter, aSection); - } -} - -//======================================================================= -// function: join -// purpose: -//======================================================================= -void CurveCreator_ICurve::join(const int theISectionTo, - const int theISectionFrom) -{ - if (theISectionTo != theISectionFrom) { - CurveCreator_Section *aSection1 = mySections.at(theISectionTo); - CurveCreator_Section *aSection2 = mySections.at(theISectionFrom); - - aSection1->myPoints.insert(aSection1->myPoints.end(), - aSection2->myPoints.begin(), aSection2->myPoints.end()); - - removeSection(theISectionFrom); - if( myListener ) - myListener->curveChanged(); - } -} - -//======================================================================= -// function: join -// purpose: -//======================================================================= -void CurveCreator_ICurve::join() -{ - const int aSize = mySections.size(); - - if (aSize > 1) { - CurveCreator_Section *aSection1 = mySections[0]; - int i; - - for (i = 1; i < aSize; i++) { - CurveCreator_Section *aSection2 = mySections[i]; - - aSection1->myPoints.insert(aSection1->myPoints.end(), - aSection2->myPoints.begin(), aSection2->myPoints.end()); - delete aSection2; - } - - // Just erace section pointers as they were deleted before. - mySections.erase(mySections.begin() + 1, mySections.end()); - if( myListener ) - myListener->curveChanged(); - } -} - -//======================================================================= -// function: toICoord -// purpose: -//======================================================================= -int CurveCreator_ICurve::toICoord(const int theIPnt) const -{ - return theIPnt*myDimension; -} - -//======================================================================= -// function: getUnicSectionName -// purpose: return unic section name -//======================================================================= -std::string CurveCreator_ICurve::getUnicSectionName() -{ - for( int i = 0 ; i < 1000000 ; i++ ){ - char aBuffer[255]; - sprintf( aBuffer, "Section_%d", i+1 ); - std::string aName(aBuffer); - int j; - for( j = 0 ; j < mySections.size() ; j++ ){ - if( mySections[j]->myName == aName ) - break; - } - if( j == mySections.size() ) - return aName; - } - return ""; -} - -//======================================================================= -// function: setListener -// purpose: set curve changes listener -//======================================================================= -void CurveCreator_ICurve::setListener( CurveCreator_Listener* theListener ) -{ - myListener = theListener; -} - -//======================================================================= -// function: setListener -// purpose: set curve changes listener -//======================================================================= -void CurveCreator_ICurve::removeListener() -{ - myListener = NULL; -} diff --git a/src/CurveCreator/CurveCreator_ICurve.hxx b/src/CurveCreator/CurveCreator_ICurve.hxx index ca662be1d..9effa478a 100644 --- a/src/CurveCreator/CurveCreator_ICurve.hxx +++ b/src/CurveCreator/CurveCreator_ICurve.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -17,170 +17,189 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: CurveCreator_Curve.hxx -// Author: Sergey KHROMOV +// File: CurveCreator_ICurve.hxx +// Author: Alexander KOVALEV and Alexander SOLOVYOV #ifndef _CurveCreator_ICurve_HeaderFile #define _CurveCreator_ICurve_HeaderFile -#include "CurveCreator.hxx" #include "CurveCreator_Macro.hxx" -#include "CurveCreator_Operation.hxx" +#include +#include +#include +#include -class CurveCreator_Section; -class CurveCreator_Listener; +class Handle_AIS_InteractiveObject; + +namespace CurveCreator +{ + //! Type of the section + enum SectionType + { + Polyline, + Spline, + }; + + //! Dimension of the curve + enum Dimension + { + Dim2d = 2, + Dim3d = 3 + }; + +}; /** * The CurveCreator_ICurve object is represented as one or more sets of * connected points; thus CurveCreator_ICurve object can contain several * not connected curves (polylines or b-splines), each such curve has two - * only ends � start and end points � in other words non-manifold curves + * only ends "start and end points" in other words non-manifold curves * are not supported. */ class CURVECREATOR_EXPORT CurveCreator_ICurve { +public: + typedef std::pair SectionToPoint; + typedef std::deque SectionToPointList; - //! List of curves - typedef std::deque Sections; + typedef std::deque< std::pair< SectionToPoint,std::deque< float > > > SectionToPointCoordsList; public: - //! Constructor of the curve. - /** The dimension is explicitly specified in the constructor - * and cannot be changed later. - */ - CurveCreator_ICurve(const CurveCreator::Dimension theDimension); + /***********************************************/ + /*** Undo/Redo methods ***/ + /***********************************************/ - //! Destructor. - virtual ~CurveCreator_ICurve(); + //! Get number of available undo operations + virtual int getNbUndo() const = 0; - //! Returns true if this curve is locked by a curve editor. - virtual bool isLocked() const; + //! Undo previous operation + virtual bool undo() = 0; - //! Get the dimension. - virtual CurveCreator::Dimension getDimension() const; + //! Get number of available redo operations + virtual int getNbRedo() const = 0; - //! Get number of sections. - virtual int getNbSections() const; + //! Redo last previously "undone" operation + virtual bool redo() = 0; - /** Get number of points in specified section or (the total number of points - * in Curve if theISection is equal to -1). - */ - virtual int getNbPoints(const int theISection = -1) const; - //! Get coordinates of specified point - virtual CurveCreator::Coordinates getCoordinates - (const int theISection, const int theIPnt) const; + /***********************************************/ + /*** Section methods ***/ + /***********************************************/ - //! Get points of a section. - virtual const CurveCreator::Coordinates &getPoints(const int theISection) const; + //! Clear the polyline (remove all sections) + virtual bool clear() = 0; - //! Get type of the specified section - virtual CurveCreator::Type getType(const int theISection) const; + //! Join list of sections to one section (join all if the list is empty) + // The first section in the list is a leader, another sections are joined to it + virtual bool join( const std::list& theSections ) = 0; - //! Get �closed� flag of the specified section - virtual bool isClosed(const int theISection) const; + //! Get number of sections + virtual int getNbSections() const = 0; - //! Returns specifyed section name - virtual std::string getSectionName(const int theISection) const; + //! Add a new section. + virtual int addSection( const std::string& theName, + const CurveCreator::SectionType theType, + const bool theIsClosed ) = 0; - /** - * Return unic section name - */ - virtual std::string getUnicSectionName(); + //! Removes the given sections. + virtual bool removeSection( const int theISection ) = 0; - /** - * Set curve creator listener object - */ - virtual void setListener( CurveCreator_Listener* myWatcher ); + //! Get "closed" flag of the specified section + virtual bool isClosed( const int theISection ) const = 0; /** - * Remove curve creator listener object + * Set "closed" flag of the specified section (all sections if + * \a theISection is -1). */ - virtual void removeListener(); + virtual bool setClosed( const int theISection, + const bool theIsClosed ) = 0; -protected: + //! Returns specifyed section name + virtual std::string getSectionName( const int theISection ) const = 0; - /** Set type of the specified section (or all sections - * if \a theISection is -1). - */ - virtual void setType(const CurveCreator::Type theType, const int theISection = -1); + /** Set name of the specified section */ + virtual bool setSectionName( const int theISection, + const std::string& theName ) = 0; - /** Add points to the specified section (or last section + //! Get type of the specified section + virtual CurveCreator::SectionType getSectionType( const int theISection ) const = 0; + + /** + * Set type of the specified section (or all sections * if \a theISection is -1). */ - virtual void addPoints - (const CurveCreator::Coordinates &thePoints, const int theISection = -1) = 0; - - //! Add a new section. - virtual void addSection (const std::string &theName, const CurveCreator::Type theType, - const bool theIsClosed, - const CurveCreator::Coordinates &thePoints); + virtual bool setSectionType( const int theISection, + const CurveCreator::SectionType theType ) = 0; - //! Removes the section. If theISection equals -1, removes the last section. - virtual void removeSection(const int theISection = -1); - /** Insert points in the given position (add to the end of list - * if \a theIPnt parameter is -1) of the specified section - * (or last section if \a theISection parameter is -1). - */ - virtual void insertPoints(const CurveCreator::Coordinates &thePoints, - const int theISection = -1, - const int theIPnt = -1); + /***********************************************/ + /*** Point methods ***/ + /***********************************************/ - /** Remove \a nbPoints points from given \a theISection, - * starting from given \a theIPnt (of all points up to the end of - * section if \a theNbPoints is -1). - */ - virtual void removePoints(const int theISection, - const int theIPnt, - const int theNbPoints = -1); + //! Get the dimension. + virtual CurveCreator::Dimension getDimension() const = 0; - /** Move specified point within section to new position + /** + * Insert one or several points to the specified section starting from the given theIPnt index + * (or add these at the end of section points if \a theIPnt is -1). */ - virtual void movePoint(const int theISection, - const int theIPointFrom, - const int theNewIndex); - - //! Remove all sections. - virtual void clear(); + virtual bool addPoints( const std::deque& theCoords, + const int theISection, + const int theIPnt = -1 ) = 0; //! Set coordinates of specified point - virtual void setCoordinates(const CurveCreator::Coordinates &theCoords, - const int theISection, - const int theIPnt); + virtual bool setPoint( const int theISection, + const int theIPnt, + const std::deque& theNewCoords ) = 0; + + //! Set coordinates of specified points from different sections + virtual bool setSeveralPoints( const SectionToPointCoordsList &theSectionToPntCoords, + const bool theIsToSaveDiff = true ) = 0; + + //! Remove point with given id + virtual bool removePoint( const int theISection, const int theIPnt = -1 ) = 0; + //! Remove several points from different sections + virtual bool removeSeveralPoints( const SectionToPointList &theSectionToPntIDs) = 0; - /** Set �closed� flag of the specified section (all sections if - * \a theISection is -1). - */ - virtual void setClosed(const bool theIsClosed, const int theISection = -1); + //! Get coordinates of specified point + virtual std::deque getPoint( const int theISection, + const int theIPnt ) const = 0; - /** Set name of the specified section. + /** + * Get points of a section (the total points in Curve if theISection is equal to -1).. */ - virtual void setName( const std::string& theName, const int theISection ); + virtual std::deque getPoints( const int theISection = -1 ) const = 0; - /** Move specified \a theISection to the specified position - * in the sections list. + /** + * Get number of points in specified section or (the total number of points + * in Curve if theISection is equal to -1). */ - virtual void moveSection(const int theISection, const int theNewIndex); + virtual int getNbPoints( const int theISection ) const = 0; - //! Join two sections to one section - virtual void join(const int theISectionTo, const int theISectionFrom); + /** + * Set skip sorting flag. If the flag is true - points sorting will be skipped. + */ + virtual void setSkipSorting( const bool ) = 0; - //! Join all sections to the single curve - virtual void join(); + /** + * Indicates whether the points can be sorted. + */ + virtual bool canPointsBeSorted() = 0; /** - * This method converts the point index to the index in - * an array of coordinates. + * Saves points coordinates difference. + * \param theOldCoords the old points coordinates */ - virtual int toICoord(const int theIPnt) const; + virtual void saveCoordDiff( const SectionToPointCoordsList &theOldCoords ) = 0; -public: + /***********************************************/ + /*** Presentation methods ***/ + /***********************************************/ - bool myIsLocked; - Sections mySections; //!< curve data - CurveCreator::Dimension myDimension; //!< curve dimension - CurveCreator_Listener* myListener; //!< listener + virtual Handle_AIS_InteractiveObject getAISObject( const bool theNeedToBuild = false ) const = 0; + +protected: + virtual void constructAISObject() = 0; }; diff --git a/src/CurveCreator/CurveCreator_Macro.hxx b/src/CurveCreator/CurveCreator_Macro.hxx index 9e6c31c68..ec814eb49 100644 --- a/src/CurveCreator/CurveCreator_Macro.hxx +++ b/src/CurveCreator/CurveCreator_Macro.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 diff --git a/src/CurveCreator/CurveCreator_NewPointDlg.cxx b/src/CurveCreator/CurveCreator_NewPointDlg.cxx deleted file mode 100755 index bb15571e8..000000000 --- a/src/CurveCreator/CurveCreator_NewPointDlg.cxx +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2013-2014 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, 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 -// - -#include "CurveCreator_NewPointDlg.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CurveCreator_NewPointDlg::CurveCreator_NewPointDlg(CurveCreator::Dimension theDim, QWidget *parent) : - QWidget(parent), myX(NULL), myY(NULL), myZ(NULL), myIsEdit(false), myDim(theDim), - myIsInstantSketchingEnabled(false) -{ - QString aTitle = QString(tr("ADD_NEW_POINT")); - setWindowTitle(aTitle); - - QFrame* aFrame = new QFrame( this ); - QVBoxLayout* aLayout = new QVBoxLayout( aFrame ); - - QFrame* aCoordFrame = new QFrame( aFrame ); - QGridLayout* aCoordLayout = new QGridLayout( aCoordFrame ); - - QLabel* aLbl = new QLabel( tr("X_COORD"), this); - myX = new QDoubleSpinBox(this); - aCoordLayout->addWidget(aLbl, 0, 0); - aCoordLayout->addWidget(myX, 0, 1 ); - - aLbl = new QLabel( tr("Y_COORD"), this); - myY = new QDoubleSpinBox(this); - aCoordLayout->addWidget(aLbl, 1, 0 ); - aCoordLayout->addWidget(myY, 1, 1 ); - - myZLabel = new QLabel( tr("Z_COORD"), this); - myZ = new QDoubleSpinBox(this); - aCoordLayout->addWidget(myZLabel, 2,0 ); - aCoordLayout->addWidget(myZ, 2,1 ); - - if( theDim != CurveCreator::Dim3d ){ - myZ->hide(); - myZLabel->hide(); - } - - myBtnFrame = new QFrame( aFrame ); - QHBoxLayout* aBtnsLayout = new QHBoxLayout( myBtnFrame ); - - myAddBtn = new QPushButton( tr( "ADD_BTN" ), myBtnFrame ); - myCancelBtn = new QPushButton( tr( "CANCEL" ), myBtnFrame ); - - connect( myCancelBtn, SIGNAL( clicked() ), this, SIGNAL( cancelPoint() ) ); - - aBtnsLayout->addWidget( myAddBtn ); - aBtnsLayout->addStretch( 1 ); - aBtnsLayout->addWidget( myCancelBtn ); - - aLayout->addWidget( aCoordFrame, 0 ); - aLayout->addWidget( myBtnFrame, 1 ); - - clear(); - updateTitle(); -} - -void CurveCreator_NewPointDlg::setSectionName( const QString& theName ) -{ - mySectionName = theName; - updateTitle(); -} - -void CurveCreator_NewPointDlg::setEditMode( bool isEdit ) -{ - myIsEdit = isEdit; - if( myIsEdit ){ - myAddBtn->setText(tr("OK")); - myAddBtn->disconnect( SIGNAL( clicked() ) ); - connect( myAddBtn, SIGNAL( clicked() ), this, SIGNAL( modifyPoint() ) ); - } - else{ - myAddBtn->setText(tr("ADD_BTN")); - myAddBtn->disconnect( SIGNAL( clicked() ) ); - connect( myAddBtn, SIGNAL( clicked() ), this, SIGNAL( addPoint() ) ); - } - updateTitle(); -} - -void CurveCreator_NewPointDlg::updateTitle() -{ - QString aTitle; - if( !myIsEdit ){ - if( mySectionName.isEmpty() ){ - aTitle = tr("ADD_NEW_POINT"); - } - else{ - aTitle = QString(tr("ADD_NEW_POINT_TO_%1")).arg(mySectionName); - } - } - else{ - aTitle = tr("SET_POINT_COORDINATES"); - } - setWindowTitle(aTitle); -} - -CurveCreator::Coordinates CurveCreator_NewPointDlg::getCoordinates() const -{ - CurveCreator::Coordinates aCoords; - double anX = myX->value(); - aCoords.push_back(anX); - double anY = myY->value(); - aCoords.push_back(anY); - if( myDim == CurveCreator::Dim3d ){ - double aZ = myZ->value(); - aCoords.push_back(aZ); - } - return aCoords; -} - -void CurveCreator_NewPointDlg::clear() -{ - initSpinBox(myX); - initSpinBox(myY); - initSpinBox(myZ); -} - -void CurveCreator_NewPointDlg::setDimension(CurveCreator::Dimension theDim) -{ - if( theDim == CurveCreator::Dim2d ){ - myZ->hide(); - myZLabel->hide(); - } - else{ - myZ->show(); - myZLabel->show(); - } -} - -void CurveCreator_NewPointDlg::setCoordinates( const CurveCreator::Coordinates& theCoords ) -{ - double anX = theCoords[0]; - myX->setValue(anX); - double anY = theCoords[1]; - myY->setValue(anY); - if( theCoords.size() == 3 ){ - double aZ = theCoords[2]; - myZ->setValue(aZ); - } - if( isInstantSketchingEnabled() ) - emit addPoint(); -} - -bool CurveCreator_NewPointDlg::isInstantSketchingEnabled() const -{ - return myIsInstantSketchingEnabled; -} - -void CurveCreator_NewPointDlg::setInstantSketchingEnabled( const bool theState ) -{ - myIsInstantSketchingEnabled = theState; -} - -//======================================================================= -// function: initSpinBox -// purpose: -//======================================================================= -void CurveCreator_NewPointDlg::initSpinBox(QDoubleSpinBox *theSpinBox) -{ - const double aCoordMin = -1.e+15; - const double aCoordMax = 1.e+15; - const double aStep = 10; - const int aPrecision = 6; - - theSpinBox->setDecimals( qAbs( aPrecision ) ); - theSpinBox->setRange(aCoordMin, aCoordMax); - theSpinBox->setSingleStep(aStep); - theSpinBox->setValue(0.0); -} diff --git a/src/CurveCreator/CurveCreator_NewPointDlg.h b/src/CurveCreator/CurveCreator_NewPointDlg.h deleted file mode 100755 index a86189e54..000000000 --- a/src/CurveCreator/CurveCreator_NewPointDlg.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2013-2014 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, 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 -// - -#ifndef CURVECREATOR_NEWPOINTDLG_H -#define CURVECREATOR_NEWPOINTDLG_H - -#include "CurveCreator.hxx" - -#include - -class QDoubleSpinBox; -class QDialogButtonBox; -class QAbstractButton; -class QPushButton; -class QLabel; -class QFrame; - -class CurveCreator_NewPointDlg : public QWidget -{ - Q_OBJECT -public: - explicit CurveCreator_NewPointDlg(CurveCreator::Dimension theDim, QWidget *parent = 0); - CurveCreator::Coordinates getCoordinates() const; - void clear(); - void setSectionName( const QString& theName ); - void setEditMode( bool isEdit ); - void setCoordinates( const CurveCreator::Coordinates& theCoords ); - void setDimension(CurveCreator::Dimension theDim); - bool isInstantSketchingEnabled() const; - void setInstantSketchingEnabled( const bool theState ); -signals: - void addPoint(); - void modifyPoint(); - void cancelPoint(); -public slots: -protected slots: -protected: - void updateTitle(); - void initSpinBox(QDoubleSpinBox *theSpinBox); -private: - QFrame* myBtnFrame; - CurveCreator::Dimension myDim; - QDoubleSpinBox* myX; - QDoubleSpinBox* myY; - QDoubleSpinBox* myZ; - QLabel* myZLabel; - QPushButton* myAddBtn; - QPushButton* myCancelBtn; - bool myIsEdit; - QString mySectionName; - bool myIsInstantSketchingEnabled; -}; - -#endif // CURVECREATOR_NEWPOINTDLG_H diff --git a/src/CurveCreator/CurveCreator_NewSectionDlg.cxx b/src/CurveCreator/CurveCreator_NewSectionDlg.cxx old mode 100755 new mode 100644 index 275a94625..f5f602a3c --- a/src/CurveCreator/CurveCreator_NewSectionDlg.cxx +++ b/src/CurveCreator/CurveCreator_NewSectionDlg.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -18,7 +18,7 @@ // #include "CurveCreator_NewSectionDlg.h" -#include "CurveCreator_Curve.hxx" +//#include "CurveCreator_Curve.hxx" #include #include @@ -31,21 +31,27 @@ #include #include -CurveCreator_NewSectionDlg::CurveCreator_NewSectionDlg( QWidget *parent ) : - QWidget(parent) +CurveCreator_NewSectionDlg::CurveCreator_NewSectionDlg( QWidget *parent, bool enableClosed ) : + QWidget(parent), myIsEnableClosed( enableClosed ) { + QVBoxLayout* aMainLayout = new QVBoxLayout( this ); + aMainLayout->setMargin( 0 ); + QFrame* aFrame = new QFrame( this ); + aMainLayout->addWidget( aFrame ); + QVBoxLayout* aLayout = new QVBoxLayout( aFrame ); + aLayout->setMargin( 0 ); QFrame* aCoordFrame = new QFrame( aFrame ); QGridLayout* aCoordLayout = new QGridLayout( aCoordFrame ); - QLabel* aLbl = new QLabel(tr("NAME"), this); + QLabel* aLbl = new QLabel(tr("SECTION_NAME"), this); myName = new QLineEdit(this); aCoordLayout->addWidget(aLbl, 0, 0); aCoordLayout->addWidget(myName, 0 , 1); - aLbl = new QLabel(tr("LINE_TYPE")); + aLbl = new QLabel(tr("SECTION_LINE_TYPE")); myLineType = new QComboBox(this); SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); @@ -54,22 +60,26 @@ CurveCreator_NewSectionDlg::CurveCreator_NewSectionDlg( QWidget *parent ) : // QPixmap aPolylinePixmap = QPixmap(tr(":images/ICON_POLYLINE")); // QPixmap aSplinePixmap = QPixmap(tr(":images/ICON_SPLINE")); - myLineType->addItem(aPolylinePixmap, tr("POLYLINE_TYPE")); - myLineType->addItem(aSplinePixmap, tr("SPLINE_TYPE")); + myLineType->addItem(aPolylinePixmap, tr("SECTION_POLYLINE_TYPE")); + myLineType->addItem(aSplinePixmap, tr("SECTION_SPLINE_TYPE")); myLineType->setCurrentIndex(0); aCoordLayout->addWidget(aLbl, 1, 0); aCoordLayout->addWidget(myLineType, 1 , 1); - aLbl = new QLabel(tr("LINE_CLOSED")); + aLbl = new QLabel(tr("SECTION_LINE_CLOSED")); myIsClosed = new QCheckBox(this); aCoordLayout->addWidget(aLbl, 2, 0); aCoordLayout->addWidget(myIsClosed, 2, 1); + if ( !myIsEnableClosed ) { + aLbl->hide(); + myIsClosed->hide(); + } myBtnFrame = new QFrame( aFrame ); QHBoxLayout* aBtnsLayout = new QHBoxLayout( myBtnFrame ); - myAddBtn = new QPushButton( tr( "ADD_BTN" ), myBtnFrame ); - myCancelBtn = new QPushButton( tr( "CANCEL" ), myBtnFrame ); + myAddBtn = new QPushButton( tr( "SECTION_ADD_BTN" ), myBtnFrame ); + myCancelBtn = new QPushButton( tr( "SECTION_CANCEL_BTN" ), myBtnFrame ); connect( myAddBtn, SIGNAL( clicked() ), this, SIGNAL( addSection() ) ); connect( myCancelBtn, SIGNAL( clicked() ), this, SIGNAL( cancelSection() ) ); @@ -82,7 +92,7 @@ CurveCreator_NewSectionDlg::CurveCreator_NewSectionDlg( QWidget *parent ) : aLayout->addWidget( myBtnFrame, 1 ); } -void CurveCreator_NewSectionDlg::setSectionParameters( const QString& theName, bool isClosed, CurveCreator::Type theType ) +void CurveCreator_NewSectionDlg::setSectionParameters( const QString& theName, bool isClosed, CurveCreator::SectionType theType ) { myName->setText(theName); myIsClosed->setChecked(isClosed); @@ -103,12 +113,12 @@ void CurveCreator_NewSectionDlg::setEditMode( bool isEdit ) { myIsEdit = isEdit; if( myIsEdit ){ - myAddBtn->setText(tr("OK")); + myAddBtn->setText(tr("SECTION_OK_BTN")); myAddBtn->disconnect( SIGNAL( clicked() ) ); connect( myAddBtn, SIGNAL( clicked() ), this, SIGNAL( modifySection() ) ); } else{ - myAddBtn->setText(tr("ADD_BTN")); + myAddBtn->setText(tr("SECTION_ADD_BTN")); myAddBtn->disconnect( SIGNAL( clicked() ) ); connect( myAddBtn, SIGNAL( clicked() ), this, SIGNAL( addSection() ) ); } @@ -125,12 +135,12 @@ bool CurveCreator_NewSectionDlg::isClosed() const return myIsClosed->isChecked(); } -CurveCreator::Type CurveCreator_NewSectionDlg::getSectionType() const +CurveCreator::SectionType CurveCreator_NewSectionDlg::getSectionType() const { if( myLineType->currentIndex() == 0 ) return CurveCreator::Polyline; else - return CurveCreator::BSpline; + return CurveCreator::Spline; } void CurveCreator_NewSectionDlg::updateTitle() diff --git a/src/CurveCreator/CurveCreator_NewSectionDlg.h b/src/CurveCreator/CurveCreator_NewSectionDlg.h old mode 100755 new mode 100644 index 7f028f20e..d37ed1176 --- a/src/CurveCreator/CurveCreator_NewSectionDlg.h +++ b/src/CurveCreator/CurveCreator_NewSectionDlg.h @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -21,10 +21,11 @@ #define CURVECREATOR_NEWSECTION_H #include "CurveCreator.hxx" +#include "CurveCreator_ICurve.hxx" #include -class CurveCreator_Curve; +//class CurveCreator_Curve; class QLineEdit; class QComboBox; @@ -38,16 +39,17 @@ class CurveCreator_NewSectionDlg : public QWidget { Q_OBJECT public: - explicit CurveCreator_NewSectionDlg(QWidget *parent = 0); + explicit CurveCreator_NewSectionDlg(QWidget *parent = 0, bool enableClosed = true ); QString getName() const; bool isClosed() const; - CurveCreator::Type getSectionType() const; + CurveCreator::SectionType getSectionType() const; - void setSectionParameters( const QString& theName, bool isClosed, CurveCreator::Type theType ); + void setSectionParameters( const QString& theName, bool isClosed, CurveCreator::SectionType theType ); void setSectionName(const QString& theName ); void clear(); void setEditMode( bool isEdit ); + bool isEnableClosed() const { return myIsEnableClosed; } signals: void addSection(); @@ -63,6 +65,7 @@ private: QComboBox* myLineType; QCheckBox* myIsClosed; bool myIsEdit; + bool myIsEnableClosed; QPushButton* myAddBtn; QPushButton* myCancelBtn; }; diff --git a/src/CurveCreator/CurveCreator_Operation.cxx b/src/CurveCreator/CurveCreator_Operation.cxx index 2e4b6416a..173e1c881 100644 --- a/src/CurveCreator/CurveCreator_Operation.cxx +++ b/src/CurveCreator/CurveCreator_Operation.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -22,6 +22,7 @@ #include "CurveCreator_Operation.hxx" #include "CurveCreator_Curve.hxx" +#include "CurveCreator.hxx" #include #include @@ -46,6 +47,11 @@ CurveCreator_Operation::~CurveCreator_Operation() clear(); } +bool compId(CurveCreator_PosPoint* p1, CurveCreator_PosPoint* p2) +{ + return p1->myID < p2->myID; +} + //======================================================================= // function: Constructor // purpose: @@ -54,8 +60,7 @@ bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType) { bool isOK = false; - if (theType == CurveCreator_Operation::Clear || - theType == CurveCreator_Operation::Join) { + if (theType == CurveCreator_Operation::Clear) { clear(); myType = theType; isOK = true; @@ -113,56 +118,28 @@ bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, // function: Constructor // purpose: //======================================================================= -bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, - const int theIntParam1, - const int theIntParam2, - const int theIntParam3) +bool CurveCreator_Operation::init(const Type theType, const std::list theParamList) { bool isOK = false; - if (theType == CurveCreator_Operation::RemovePoints) { - int *pData = (int *)allocate(3*sizeof(int)); - - pData[0] = theIntParam1; - pData[1] = theIntParam2; - pData[2] = theIntParam3; - myType = theType; - isOK = true; - } - - return isOK; -} - -//======================================================================= -// function: Constructor -// purpose: -//======================================================================= -bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, - const CurveCreator::Coordinates &theCoords, - const int theIntParam) -{ - bool isOK = false; + if (theType == CurveCreator_Operation::Join) + { + const int aNbPoints = theParamList.size(); - if (theType == CurveCreator_Operation::AddPoints) { - const int aNbCoords = theCoords.size(); const size_t aSize = - 2*sizeof(theIntParam) + aNbCoords*sizeof(CurveCreator::TypeCoord); - int *pIntData = (int *)allocate(aSize); - - *pIntData++ = theIntParam; - *pIntData++ = aNbCoords; + sizeof(aNbPoints) + + aNbPoints * (sizeof(int)); - CurveCreator::TypeCoord *pRealData = (CurveCreator::TypeCoord *)pIntData; - int i = 0; + int *pIntData = (int *)allocate(aSize); - for (; i < aNbCoords; i++) { - *pRealData++ = theCoords[i]; - } + *pIntData++ = aNbPoints; + std::list::const_iterator anIt = theParamList.begin(), aLast = theParamList.end(); + for ( ; anIt != aLast; anIt++ ) + *pIntData++ = *anIt; - myType = theType; + myType = theType; isOK = true; } - return isOK; } @@ -172,21 +149,17 @@ bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, //======================================================================= bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, const CurveCreator::Coordinates &theCoords, - const int theIntParam1, - const int theIntParam2) + const int theIntParam) { bool isOK = false; - if (theType == CurveCreator_Operation::AddSection || - theType == CurveCreator_Operation::InsertPoints || - theType == CurveCreator_Operation::SetCoordinates) { + if (theType == CurveCreator_Operation::AddPoints) { const int aNbCoords = theCoords.size(); const size_t aSize = - 3*sizeof(theIntParam1) + aNbCoords*sizeof(CurveCreator::TypeCoord); + 2*sizeof(theIntParam) + aNbCoords*sizeof(CurveCreator::TypeCoord); int *pIntData = (int *)allocate(aSize); - *pIntData++ = theIntParam1; - *pIntData++ = theIntParam2; + *pIntData++ = theIntParam; *pIntData++ = aNbCoords; CurveCreator::TypeCoord *pRealData = (CurveCreator::TypeCoord *)pIntData; @@ -234,7 +207,7 @@ bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, pIntData = (int*)aStrPtr; *pIntData++ = aNbCoords; - CurveCreator::TypeCoord *pRealData = (CurveCreator::TypeCoord *)aStrPtr; + CurveCreator::TypeCoord *pRealData = (CurveCreator::TypeCoord *)pIntData; int i = 0; for (; i < aNbCoords; i++) { @@ -269,6 +242,84 @@ bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, return false; } +bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, + const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1) +{ + bool isOK = false; + + if (theType == CurveCreator_Operation::InsertPoints || + theType == CurveCreator_Operation::SetCoordinates ) { + + const int aNbPoints = theParamList1.size(); + + CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = + theParamList1.begin(); + const int aNbCoords = anIt->second.size(); + + const size_t aSize = + sizeof(aNbPoints) + sizeof(aNbCoords) + + aNbPoints * (3*sizeof(int) + aNbCoords*sizeof(CurveCreator::TypeCoord)); + int *pIntData = (int *)allocate(aSize); + + *pIntData++ = aNbPoints; + *pIntData++ = aNbCoords; + int aSectionId, aPointId; + for ( ; anIt != theParamList1.end(); anIt++ ) { + aSectionId = anIt->first.first; + aPointId = anIt->first.second; + + *pIntData++ = aSectionId; + *pIntData++ = aPointId; + *pIntData++ = aNbCoords; + + const CurveCreator::Coordinates &aCoords = anIt->second; + CurveCreator::TypeCoord *pRealData = (CurveCreator::TypeCoord *)pIntData; + for (int i = 0; i < aNbCoords; i++) { + *pRealData++ = aCoords[i]; + } + pIntData = (int *)pRealData; + } + + myType = theType; + isOK = true; + } + + return isOK; +} + +bool CurveCreator_Operation::init(const CurveCreator_Operation::Type theType, + const CurveCreator_ICurve::SectionToPointList &theParamList1) +{ + bool isOK = false; + + if (theType == CurveCreator_Operation::RemovePoints) { + const int aNbPoints = theParamList1.size(); + + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = + theParamList1.begin(); + + const size_t aSize = + sizeof(aNbPoints) + + aNbPoints * (2*sizeof(int)); + int *pIntData = (int *)allocate(aSize); + + *pIntData++ = aNbPoints; + int aSectionId, aPointId; + for ( ; anIt != theParamList1.end(); anIt++ ) { + aSectionId = anIt->first; + aPointId = anIt->second; + + *pIntData++ = aSectionId; + *pIntData++ = aPointId; + } + + myType = theType; + isOK = true; + } + + return isOK; +} + //======================================================================= // function: apply // purpose: @@ -280,58 +331,81 @@ void CurveCreator_Operation::apply(CurveCreator_Curve *theCurve) switch (myType) { case CurveCreator_Operation::AddPoints: + case CurveCreator_Operation::InsertPoints: + case CurveCreator_Operation::SetCoordinates: { + int aSectionId, aPointId; + CurveCreator::SectionsMap aSectionsMap; + CurveCreator::PosPointsList aPoints; CurveCreator::Coordinates aCoords; - getCoords(&pInt[1], aCoords); - theCurve->addPoints(aCoords, pInt[0]); + int nbPoints = pInt[0]; + int nbCoords = pInt[1]; + int nbParams = 3+nbCoords; + for (int i = 0; i < nbPoints*nbParams; i=i+nbParams) { + aCoords.clear(); + aPoints.clear(); + getCoords(&pInt[4+i], aCoords); + aSectionId = pInt[2+i]; + aPointId = pInt[3+i]; + if ( aSectionsMap.find( aSectionId ) != aSectionsMap.end() ) + aPoints = aSectionsMap[aSectionId]; + CurveCreator_PosPoint* aPosPoint = new CurveCreator_PosPoint( aPointId, aCoords ); + aPoints.push_back( aPosPoint ); + aPoints.sort(compId); + aSectionsMap[aSectionId] = aPoints; + } + switch (myType) { + case CurveCreator_Operation::AddPoints: + case CurveCreator_Operation::InsertPoints: + theCurve->addPointsInternal( aSectionsMap ); + break; + case CurveCreator_Operation::SetCoordinates: + theCurve->setPointInternal( aSectionsMap ); + break; + } } break; case CurveCreator_Operation::RemovePoints: - theCurve->removePoints(pInt[0], pInt[1], pInt[2]); - break; - case CurveCreator_Operation::InsertPoints: { - CurveCreator::Coordinates aCoords; - - getCoords(&pInt[2], aCoords); - theCurve->insertPoints(aCoords, pInt[0], pInt[1]); + CurveCreator_ICurve::SectionToPointList aListOfSectionsToPoints; + int nbPoints = pInt[0]; + for (int i = 1; i < nbPoints*2; i=i+2) { + aListOfSectionsToPoints.push_back(std::make_pair(pInt[i], pInt[i+1])); + } + theCurve->removePointsInternal(aListOfSectionsToPoints); } break; case CurveCreator_Operation::SetType: { - const CurveCreator::Type aType = (CurveCreator::Type) pInt[0]; + const CurveCreator::SectionType aType = (CurveCreator::SectionType) pInt[0]; - theCurve->setType(aType, pInt[1]); + theCurve->setSectionTypeInternal( pInt[1], aType ); } break; case CurveCreator_Operation::Clear: - theCurve->clear(); - break; - case CurveCreator_Operation::SetCoordinates: - { - CurveCreator::Coordinates aCoords; - - getCoords(&pInt[2], aCoords); - theCurve->setCoordinates(aCoords, pInt[0], pInt[1]); - } + theCurve->clearInternal(); break; case CurveCreator_Operation::SetClosed: - theCurve->setClosed((pInt[0] != 0), pInt[1]); + theCurve->setClosedInternal(pInt[1], (pInt[0] != 0)); break; case CurveCreator_Operation::MoveSection: - theCurve->moveSection(pInt[0], pInt[1]); + theCurve->moveSectionInternal(pInt[0], pInt[1]); break; case CurveCreator_Operation::Join: - if (myPData == NULL) { - theCurve->join(); - } else { - theCurve->join(pInt[0], pInt[1]); + if (myPData != NULL) + { + std::list aListOfSections; + int nbSections = pInt[0]; + for (int i = 1; i < nbSections+1; i++) { + aListOfSections.push_back(pInt[i]); + } + theCurve->joinInternal(aListOfSections); } break; case CurveCreator_Operation::AddSection: { - const CurveCreator::Type aType = (CurveCreator::Type) pInt[0]; + const CurveCreator::SectionType aType = (CurveCreator::SectionType) pInt[0]; std::string aName = std::string((char*)&pInt[2]); @@ -340,16 +414,16 @@ void CurveCreator_Operation::apply(CurveCreator_Curve *theCurve) char* aPtr = ((char*)&pInt[2]); aPtr += (aName.length()) + 1; getCoords((int*)aPtr, aCoords); - theCurve->addSection(aName, aType, (pInt[1] != 0), aCoords); + theCurve->addSectionInternal(aName, aType, (pInt[1] != 0), aCoords); } break; case CurveCreator_Operation::RemoveSection: - theCurve->removeSection(pInt[0]); + theCurve->removeSectionInternal(pInt[0]); break; case CurveCreator_Operation::RenameSection: { std::string aName = std::string((char*)&pInt[1]); - theCurve->setName(aName, pInt[0]); + theCurve->setSectionNameInternal(pInt[0], aName); } break; default: diff --git a/src/CurveCreator/CurveCreator_Operation.hxx b/src/CurveCreator/CurveCreator_Operation.hxx index a74ac19ca..855d0da2a 100644 --- a/src/CurveCreator/CurveCreator_Operation.hxx +++ b/src/CurveCreator/CurveCreator_Operation.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -24,8 +24,11 @@ #define _CurveCreator_Operation_HeaderFile #include "CurveCreator.hxx" +#include "CurveCreator_ICurve.hxx" +#include "CurveCreator_PosPoint.hxx" #include +#include class CurveCreator_Curve; @@ -74,7 +77,6 @@ public: * It is applicable to the following operations: *
      *
    • Clear
    • - *
    • Join (without arguments)
    • *
    * @return true in case of success; false otherwise. */ @@ -105,15 +107,26 @@ public: const int theIntParam2); /** - * This method initializes the object with an operation with three integer + * This method initializes the object with an operation with two integer * parameters. It is applicable to the following operations: *
      + *
    • Join (with a list of int arguments)
    • + *
    + * @return true in case of success; false otherwise. + */ + bool init(const Type theType, const std::list theParamList); + + /** + * This method initializes the object with an operation with + * list of pairs of integer parameters. + * It is applicable to the following operations: + *
      *
    • RemovePoints
    • *
    * @return true in case of success; false otherwise. */ - bool init(const Type theType, const int theIntParam1, - const int theIntParam2, const int theIntParam3); + bool init(const Type theType, + const CurveCreator_ICurve::SectionToPointList &theParamList1); /** * This method initializes the object with an operation with one @@ -128,18 +141,16 @@ public: const int theIntParam); /** - * This method initializes the object with an operation with one - * CurveCreator::Coordinates parameter and two integer parameters. + * This method initializes the object with an operation with + * list of pairs of integer parameters and CurveCreator::Coordinates parameters. * It is applicable to the following operations: *
      - *
    • AddSection
    • *
    • InsertPoints
    • - *
    • SetCoordinates
    • *
    * @return true in case of success; false otherwise. */ - bool init(const Type theType, const CurveCreator::Coordinates &theCoords, - const int theIntParam1, const int theIntParam2); + bool init(const Type theType, + const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1); /** * This method initializes the object with an operation with one diff --git a/src/CurveCreator/CurveCreator_PosPoint.hxx b/src/CurveCreator/CurveCreator_PosPoint.hxx new file mode 100644 index 000000000..230137423 --- /dev/null +++ b/src/CurveCreator/CurveCreator_PosPoint.hxx @@ -0,0 +1,46 @@ +// Copyright (C) 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 +// + +// File: CurveCreator_PosPoint.hxx +// Author: Alexander KOVALEV + +#ifndef _CurveCreator_PosPoint_HeaderFile +#define _CurveCreator_PosPoint_HeaderFile + +#include "CurveCreator.hxx" + +struct CurveCreator_PosPoint +{ +public: + CurveCreator_PosPoint( int theID, CurveCreator::Coordinates theCoords ) + : myID( theID ), myCoords( theCoords ) + { }; + + ////! Overloaded operator to use sorting. + //bool operator < (CurveCreator_PosPoint const & thePosPoint) const + //{ + // return myID < thePosPoint.myID; + //} + + int myID; // point ID + CurveCreator::Coordinates myCoords; // point coordinates + +}; + +#endif diff --git a/src/CurveCreator/CurveCreator_Section.hxx b/src/CurveCreator/CurveCreator_Section.hxx index 0eafa0629..68b03aaa7 100644 --- a/src/CurveCreator/CurveCreator_Section.hxx +++ b/src/CurveCreator/CurveCreator_Section.hxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -36,7 +36,7 @@ struct CurveCreator_Section std::string myName; //!< section name CurveCreator::Coordinates myPoints; //!< points coordinates - CurveCreator::Type myType; //!< type of the section + CurveCreator::SectionType myType; //!< type of the section bool myIsClosed; //!< closed or not }; diff --git a/src/CurveCreator/CurveCreator_TableView.cxx b/src/CurveCreator/CurveCreator_TableView.cxx new file mode 100644 index 000000000..b40760511 --- /dev/null +++ b/src/CurveCreator/CurveCreator_TableView.cxx @@ -0,0 +1,178 @@ +// Copyright (C) 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 +// + +#include "CurveCreator_TableView.h" +#include "CurveCreator_UtilsICurve.hxx" + +#include + +#include +#include + +#include + +const double DBL_MINIMUM = -10000000.; +const double DBL_MAXIMUM = 10000000.; + +const int SECTION_NAME_COLUMN_WIDTH = 75; +const int POINT_INDEX_COLUMN_WIDTH = 40; + +const double LOCAL_SELECTION_TOLERANCE = 0.0001; + +CurveCreator_TableItemDelegate::CurveCreator_TableItemDelegate( QObject* theParent ) +: QItemDelegate( theParent ) +{ +} + +/** + * Creates an editor for the cell + */ +QWidget* CurveCreator_TableItemDelegate::createEditor( QWidget* theParent, + const QStyleOptionViewItem& theOption, + const QModelIndex& theIndex ) const +{ + QWidget* anEditor = 0; + + int aColumnId = theIndex.column(); + if ( aColumnId == 2 || aColumnId == 3 ) { + QDoubleSpinBox* aSpin = new QtxDoubleSpinBox( theParent ); + aSpin->setDecimals( 2 ); + aSpin->setRange( DBL_MINIMUM, DBL_MAXIMUM ); + anEditor = aSpin; + } + else + anEditor = QItemDelegate::createEditor( theParent, theOption, theIndex ); + + return anEditor; +} + +void CurveCreator_TableItemDelegate::setEditorData( QWidget* theEditor, + const QModelIndex& theIndex ) const +{ + int aColumnId = theIndex.column(); + if ( aColumnId == 2 || aColumnId == 3 ) { + QDoubleSpinBox* aDblSpin = dynamic_cast( theEditor ); + if ( aDblSpin ) { + double aValue = theIndex.model()->data( theIndex, Qt::EditRole ).toDouble(); + aDblSpin->setValue( aValue ); + } + } + else + QItemDelegate::setEditorData( theEditor, theIndex ); +} + +void CurveCreator_TableItemDelegate::setModelData( QWidget* theEditor, + QAbstractItemModel* theModel, + const QModelIndex& theIndex ) const +{ + int aColumnId = theIndex.column(); + if ( aColumnId == 2 || aColumnId == 3 ) { + QDoubleSpinBox* aDblSpin = dynamic_cast( theEditor ); + if ( aDblSpin ) { + double aValue = aDblSpin->value(); + theModel->setData( theIndex, aValue, Qt::UserRole); + } + } + else + QItemDelegate::setModelData( theEditor, theModel, theIndex ); +} + +CurveCreator_TableView::CurveCreator_TableView( CurveCreator_ICurve* theCurve, + QWidget* theParent, + const QStringList& theCoordTitles ) +: QTableWidget( theParent ), myCurve( theCurve ) +{ + setItemDelegate( new CurveCreator_TableItemDelegate( this ) ); + setVisible( false ); + setColumnCount( 4 ); + setColumnWidth( 0, SECTION_NAME_COLUMN_WIDTH ); + setColumnWidth( 1, POINT_INDEX_COLUMN_WIDTH ); + QStringList aLabels; + QString aCoord1 = theCoordTitles.size() > 0 ? theCoordTitles[0] : tr( "TABLE_X" ); // tr( "X_POSITION_LBL" ) + QString aCoord2 = theCoordTitles.size() > 1 ? theCoordTitles[1] : tr( "TABLE_Y" ); // tr( "Y_POSITION_LBL" ) + //aLabels << tr( "SECTION_LABEL" ) << tr( "IDENTIFIER_LABEL" ) << aCoord1 << aCoord2; + aLabels << tr( "TABLE_SECTION" ) << tr("TABLE_INDEX") << aCoord1 << aCoord2; + setHorizontalHeaderLabels( aLabels ); +} + +void CurveCreator_TableView::setCurve( CurveCreator_ICurve* theCurve ) +{ + myCurve = theCurve; +} + +void CurveCreator_TableView::setLocalPointsToTable( + const CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + setRowCount( thePoints.size() ); + + int aRowId = 0; + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = thePoints.begin(), + aLast = thePoints.end(); + for ( ; anIt != aLast; anIt++ ) { + CurveCreator_ICurve::SectionToPoint aSPoint = *anIt; + int anISection = aSPoint.first; + int anIPoint = aSPoint.second; + + QTableWidgetItem* anItem; + anItem = new QTableWidgetItem( myCurve->getSectionName( anISection ).c_str() ); + anItem->setFlags( anItem->flags() & ~Qt::ItemIsEnabled ); + anItem->setData( Qt::UserRole, anISection ); + setItem( aRowId, 0, anItem ); + + anItem = new QTableWidgetItem( QString::number( anIPoint + 1 ) ); + anItem->setFlags( anItem->flags() & ~Qt::ItemIsEnabled ); + anItem->setData( Qt::UserRole, anIPoint ); + setItem( aRowId, 1, anItem ); + + gp_Pnt aPoint; + CurveCreator_UtilsICurve::getPoint( myCurve, anISection, anIPoint, aPoint ); + + anItem = item( aRowId, 2 ); + if ( !anItem ) { + anItem = new QTableWidgetItem(); + setItem( aRowId, 2, anItem ); + } + anItem->setData( Qt::UserRole, aPoint.X() ); + anItem->setData( Qt::DisplayRole, QString::number( aPoint.X(), 'f', 2 ) ); + + anItem = item( aRowId, 3 ); + if ( !anItem ) { + anItem = new QTableWidgetItem(); + setItem( aRowId, 3, anItem ); + } + anItem->setData( Qt::UserRole, aPoint.Y() ); + anItem->setData( Qt::DisplayRole, QString::number( aPoint.Y(), 'f', 2 ) ); + + aRowId++; + } +} + +int CurveCreator_TableView::getSectionId( const int theRowId ) const +{ + return item( theRowId, 0 )->data( Qt::UserRole ).toInt(); +} + +/** + * Returns a point index from the table + * \param theRowId a table row + */ +int CurveCreator_TableView::getPointId( const int theRowId ) const +{ + return item( theRowId, 1 )->data( Qt::UserRole ).toInt(); +} diff --git a/src/CurveCreator/CurveCreator_TableView.h b/src/CurveCreator/CurveCreator_TableView.h new file mode 100644 index 000000000..4565ab5d7 --- /dev/null +++ b/src/CurveCreator/CurveCreator_TableView.h @@ -0,0 +1,69 @@ +// Copyright (C) 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 +// + +#ifndef CURVECREATOR_TABLEVIEW_H +#define CURVECREATOR_TABLEVIEW_H + +#include "CurveCreator_ICurve.hxx" + +#include +#include + +class CurveCreator_TableItemDelegate : public QItemDelegate +{ +public: + CurveCreator_TableItemDelegate( QObject* theParent ); + ~CurveCreator_TableItemDelegate() {} + + virtual QWidget* createEditor( QWidget* theParent, + const QStyleOptionViewItem& theOption, + const QModelIndex& theIndex ) const; + virtual void setEditorData( QWidget* theEditor, const QModelIndex& theIndex ) const; + virtual void setModelData( QWidget* theEditor, QAbstractItemModel* theModel, + const QModelIndex& theIndex ) const; +}; + +class CurveCreator_TableView : public QTableWidget +{ +public: + CurveCreator_TableView( CurveCreator_ICurve* theCurve, QWidget* theParent = 0, + const QStringList& theCoordTitles = QStringList() ); + ~CurveCreator_TableView() {}; + + void setCurve( CurveCreator_ICurve* theCurve ); + + void setLocalPointsToTable( const CurveCreator_ICurve::SectionToPointList& thePoints ); + + /** + * Returns a section index from the table + * \param theRowId a table row + */ + int getSectionId( const int theRowId ) const; + /** + * Returns a point index from the table + * \param theRowId a table row + */ + int getPointId( const int theRowId ) const; + +private: + CurveCreator_ICurve* myCurve; + +}; + +#endif // CURVECREATOR_TABLEVIEW_H diff --git a/src/CurveCreator/CurveCreator_TreeView.cxx b/src/CurveCreator/CurveCreator_TreeView.cxx old mode 100755 new mode 100644 index 1b7fa9587..36d1dfcfb --- a/src/CurveCreator/CurveCreator_TreeView.cxx +++ b/src/CurveCreator/CurveCreator_TreeView.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -18,7 +18,7 @@ // #include "CurveCreator_TreeView.h" -#include "CurveCreator_Curve.hxx" +#include "CurveCreator_ICurve.hxx" #include #include @@ -28,7 +28,7 @@ #define ID_SECTION -1 -CurveCreator_TreeViewModel::CurveCreator_TreeViewModel( CurveCreator_Curve* theCurve, QObject* parent ) : +CurveCreator_TreeViewModel::CurveCreator_TreeViewModel( CurveCreator_ICurve* theCurve, QObject* parent ) : QAbstractItemModel(parent), myCurve(theCurve) { SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); @@ -86,7 +86,7 @@ QVariant CurveCreator_TreeViewModel::data(const QModelIndex & index, int role ) } else if( role == Qt::DecorationRole ){ if( aColumn == 0 ){ - CurveCreator::Type aSectionType = myCurve->getType(aRow); + CurveCreator::SectionType aSectionType = myCurve->getSectionType(aRow); if( aSectionType == CurveCreator::Polyline ){ if( myCurve->isClosed(aRow) ){ return myCachedIcons[ICON_CLOSED_POLYLINE]; @@ -161,12 +161,12 @@ int CurveCreator_TreeViewModel::rowCount(const QModelIndex & parent ) const int aRowCnt = 0; if( myCurve != NULL ){ if( !parent.isValid() ){ - //Points level + //Section level aRowCnt = myCurve->getNbSections(); } else{ - //Section level if( parent.internalId() == ID_SECTION ){ + //Points level aRowCnt = myCurve->getNbPoints(parent.row()); } } @@ -210,14 +210,14 @@ int CurveCreator_TreeViewModel::getPoint( const QModelIndex& theIndx ) const return theIndx.row(); } -void CurveCreator_TreeViewModel::setCurve( CurveCreator_Curve* theCurve ) +void CurveCreator_TreeViewModel::setCurve( CurveCreator_ICurve* theCurve ) { myCurve = theCurve; reset(); } /*****************************************************************************************/ -CurveCreator_TreeView::CurveCreator_TreeView( CurveCreator_Curve* theCurve, QWidget *parent) : +CurveCreator_TreeView::CurveCreator_TreeView( CurveCreator_ICurve* theCurve, QWidget *parent) : QTreeView(parent) { header()->hide(); @@ -249,7 +249,6 @@ QList CurveCreator_TreeView::getSelectedSections() const aSect << aModel->getSection( anIndxs[i] ); } } - qSort(aSect.begin(), aSect.end()); return aSect; } @@ -290,7 +289,11 @@ void CurveCreator_TreeView::sectionAdded( int theSection ) { CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); if( aModel ){ - rowsInserted(QModelIndex(), theSection, theSection ); + int nbRows = aModel->rowCount(); + int aSection = (theSection == -1 ? (nbRows==0 ? 0 : nbRows-1) : theSection); + rowsInserted(QModelIndex(), aSection, aSection ); + QModelIndex aSectIndx = aModel->sectionIndex(aSection); + selectionModel()->select(aSectIndx, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } } @@ -361,16 +364,6 @@ void CurveCreator_TreeView::sectionsSwapped( int theSection, int theOffset ) } } -void CurveCreator_TreeView::pointsSwapped( int theSection, int thePointNum, int theOffset ) -{ - CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); - if( aModel ){ - QModelIndex aFirstIndex = aModel->pointIndex( theSection, thePointNum ); - QModelIndex aSecondIndex = aModel->pointIndex( theSection, thePointNum + theOffset ); - swapIndexes( aFirstIndex, aSecondIndex ); - } -} - void CurveCreator_TreeView::setSelectedSections( const QList& theList ) { CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); @@ -378,19 +371,7 @@ void CurveCreator_TreeView::setSelectedSections( const QList& theList ) selectionModel()->clearSelection(); for( int i = 0 ; i < theList.size() ; i++ ){ QModelIndex aSectIndx = aModel->sectionIndex(theList[i]); - selectionModel()->select(aSectIndx, QItemSelectionModel::Select ); - } - } -} - -void CurveCreator_TreeView::setSelectedPoints( const QList< QPair >& thePointsList ) -{ - CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); - if( aModel ){ - selectionModel()->clearSelection(); - for( int i = 0 ; i < thePointsList.size() ; i++ ){ - QModelIndex aSectIndx = aModel->pointIndex( thePointsList[i].first, thePointsList[i].second ); - selectionModel()->select(aSectIndx, QItemSelectionModel::Select ); + selectionModel()->select(aSectIndx, QItemSelectionModel::Select | QItemSelectionModel::Rows ); } } } @@ -404,25 +385,6 @@ bool pointLessThan(const QPair &s1, const QPair &s2) return s1.second < s2.second; } -QList< QPair< int, int > > CurveCreator_TreeView::getSelectedPoints() const -{ - QList< QPair< int, int > > aPoints; - CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); - if( !aModel ) - return aPoints; - QModelIndexList anIndxs = selectionModel()->selectedIndexes(); - for( int i = 0 ; i < anIndxs.size() ; i++ ){ - if( !aModel->isSection( anIndxs[i] ) ){ - int aSect = aModel->getSection(anIndxs[i]); - int aPointNum = aModel->getPoint(anIndxs[i]); - QPair< int, int > aPoint = QPair( aSect, aPointNum ); - aPoints.push_back( aPoint ); - } - } - qSort( aPoints.begin(), aPoints.end(), pointLessThan ); - return aPoints; -} - CurveCreator_TreeView::SelectionType CurveCreator_TreeView::getSelectionType() const { CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); @@ -470,16 +432,20 @@ void CurveCreator_TreeView::onActivated( QModelIndex theIndx ) int aSect = aModel->getSection(theIndx); if( aModel->isSection(theIndx) ){ emit sectionEntered( aSect ); - return; } - int aPointNum = aModel->getPoint( theIndx ); - emit pointEntered( aSect, aPointNum ); } -void CurveCreator_TreeView::setCurve( CurveCreator_Curve* theCurve ) +void CurveCreator_TreeView::setCurve( CurveCreator_ICurve* theCurve ) { CurveCreator_TreeViewModel* aModel = dynamic_cast(model()); if( aModel ) aModel->setCurve(theCurve); reset(); } + +void CurveCreator_TreeView::reset() +{ + QList aSelSections = getSelectedSections(); + QTreeView::reset(); + setSelectedSections(aSelSections); +} diff --git a/src/CurveCreator/CurveCreator_TreeView.h b/src/CurveCreator/CurveCreator_TreeView.h old mode 100755 new mode 100644 index 09929bf35..be00a75d3 --- a/src/CurveCreator/CurveCreator_TreeView.h +++ b/src/CurveCreator/CurveCreator_TreeView.h @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -23,12 +23,12 @@ #include #include -class CurveCreator_Curve; +class CurveCreator_ICurve; class CurveCreator_TreeViewModel : public QAbstractItemModel { public: - CurveCreator_TreeViewModel( CurveCreator_Curve* theCurve, QObject* parent ); + CurveCreator_TreeViewModel( CurveCreator_ICurve* theCurve, QObject* parent ); virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; @@ -44,12 +44,12 @@ public: int getSection( const QModelIndex& theIndx ) const; int getPoint( const QModelIndex& theIndx ) const; - void setCurve( CurveCreator_Curve* theCurve ); + void setCurve( CurveCreator_ICurve* theCurve ); private: enum IconType{ ICON_POLYLINE, ICON_SPLINE, ICON_CLOSED_SPLINE, ICON_CLOSED_POLYLINE, ICON_POINT }; private: - CurveCreator_Curve* myCurve; + CurveCreator_ICurve* myCurve; QMap myCachedIcons; }; @@ -59,15 +59,13 @@ class CurveCreator_TreeView : public QTreeView public: enum SelectionType{ ST_NOSEL, ST_POINTS, ST_POINTS_ONE_SECTION, ST_SECTIONS, ST_MIXED }; public: - explicit CurveCreator_TreeView( CurveCreator_Curve* theCurve, QWidget *parent = 0); + explicit CurveCreator_TreeView( CurveCreator_ICurve* theCurve, QWidget *parent = 0); SelectionType getSelectionType() const; QList getSelectedSections() const; - QList< QPair< int, int > > getSelectedPoints() const; void pointsAdded( int theSection, int thePoint, int thePointsCnt=1 ); void pointDataChanged( int theSection, int thePoint ); void pointsRemoved(int theSection, int thePoint, int thePointsCnt=1 ); - void pointsSwapped( int theSection, int thePointNum, int theOffset ); void sectionAdded( int theSection ); void sectionChanged(int theSection , int aSectCnt = 1); @@ -75,15 +73,15 @@ public: void sectionsSwapped( int theSection, int theOffset ); void setSelectedSections( const QList& theList ); - void setSelectedPoints( const QList< QPair >& thePointsList ); - void setCurve( CurveCreator_Curve* theCurve ); + void setCurve( CurveCreator_ICurve* theCurve ); + + void reset(); signals: void selectionChanged(); void sectionEntered(int); - void pointEntered(int,int); -public slots: + protected slots: void onActivated( QModelIndex theIndx ); protected: diff --git a/src/CurveCreator/CurveCreator_UndoOptsDlg.cxx b/src/CurveCreator/CurveCreator_UndoOptsDlg.cxx deleted file mode 100644 index ec8fd5898..000000000 --- a/src/CurveCreator/CurveCreator_UndoOptsDlg.cxx +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (C) 2013-2014 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, 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: CurveCreator_UndoOptsDlg.cxx -// Author: Sergey KHROMOV - -#include "CurveCreator_UndoOptsDlg.h" - -#include -#include -#include -#include -#include -#include -#include - -#define UNDO_DEPTH_UNLIMITED 0 -#define UNDO_DEPTH_DISABLED 1 -#define UNDO_DEPTH_FIX_SIZE 2 - -//======================================================================= -// function: Constructor -// purpose: -//======================================================================= -CurveCreator_UndoOptsDlg::CurveCreator_UndoOptsDlg(QWidget* parent) - : QDialog (parent), - myUndoDepth (UNDO_DEPTH_UNLIMITED), - myOptsBtnGrp (NULL), - myBufferSizeEdit (NULL), - myOkBtn (NULL), - myCancelBtn (NULL) -{ - setWindowTitle(tr("CC_UNDO_OPTIONS_TITLE")); - - // Set Undo/Redo options group - QGroupBox *anUndoOptsGrp = - new QGroupBox(tr("CC_UNDO_OPTIONS_MODIFY")); - QGridLayout *anUndoOptsLO = new QGridLayout(anUndoOptsGrp); - QRadioButton *aDisabledRdBtn = - new QRadioButton(tr("CC_UNDO_OPTIONS_DISABLED"), anUndoOptsGrp); - QRadioButton *aFixSizeRdBtn = - new QRadioButton(tr("CC_UNDO_OPTIONS_FIXED_SIZE"), anUndoOptsGrp); - QRadioButton *anUnlimRdBtn = - new QRadioButton(tr("CC_UNDO_OPTIONS_UNLIMITED"), anUndoOptsGrp); - - myOptsBtnGrp = new QButtonGroup(anUndoOptsGrp); - myBufferSizeEdit = new QLineEdit(anUndoOptsGrp); - anUndoOptsLO->setMargin(9); - anUndoOptsLO->setSpacing(6); - anUndoOptsLO->addWidget(aDisabledRdBtn, 0, 0); - anUndoOptsLO->addWidget(aFixSizeRdBtn, 1, 0); - anUndoOptsLO->addWidget(anUnlimRdBtn, 2, 0); - anUndoOptsLO->addWidget(myBufferSizeEdit, 1, 1); - myOptsBtnGrp->addButton(anUnlimRdBtn, UNDO_DEPTH_UNLIMITED); - myOptsBtnGrp->addButton(aDisabledRdBtn, UNDO_DEPTH_DISABLED); - myOptsBtnGrp->addButton(aFixSizeRdBtn, UNDO_DEPTH_FIX_SIZE); - - // Set OK/Cancel buttons group - QGroupBox *anOkCancelGrp = new QGroupBox; - QGridLayout *anOkCancelLO = new QGridLayout(anOkCancelGrp); - - myOkBtn = new QPushButton(tr("GEOM_BUT_OK"), anOkCancelGrp); - myCancelBtn = new QPushButton(tr("GEOM_BUT_CANCEL"), anOkCancelGrp); - anOkCancelLO->setMargin(9); - anOkCancelLO->setSpacing(6); - anOkCancelLO->addWidget(myOkBtn, 0, 0); - anOkCancelLO->addWidget(myCancelBtn, 0, 1); - - // Set main group - QGroupBox *aMainGrp = new QGroupBox; - QVBoxLayout *aMainLO = new QVBoxLayout(aMainGrp); - - aMainLO->addWidget(anUndoOptsGrp); - aMainLO->addWidget(anOkCancelGrp); - - setLayout(aMainLO); - - init(); -} - -//======================================================================= -// function: Destructor -// purpose: -//======================================================================= -CurveCreator_UndoOptsDlg::~CurveCreator_UndoOptsDlg() -{ -} - -//======================================================================= -// function: setUndoDepth -// purpose: -//======================================================================= -void CurveCreator_UndoOptsDlg::setUndoDepth(const int theDepth) -{ - myUndoDepth = theDepth; - - const int aDepthId = myUndoDepth + 1; - int anId = UNDO_DEPTH_FIX_SIZE; - - if (aDepthId == UNDO_DEPTH_UNLIMITED || - aDepthId == UNDO_DEPTH_DISABLED) { - anId = aDepthId; - } else if (myUndoDepth > 0) { - myBufferSizeEdit->setText(QString::number(myUndoDepth)); - } - - myOptsBtnGrp->button(anId)->setChecked(true); - optionChanged(anId); -} - -//======================================================================= -// function: getUndoDepth -// purpose: -//======================================================================= -int CurveCreator_UndoOptsDlg::getUndoDepth() const -{ - return myUndoDepth; -} - -//======================================================================= -// function: isEnabled -// purpose: -//======================================================================= -bool CurveCreator_UndoOptsDlg::isEnabled() const -{ - return (myUndoDepth + 1 != UNDO_DEPTH_DISABLED); -} - -//======================================================================= -// function: isUnlimited -// purpose: -//======================================================================= -bool CurveCreator_UndoOptsDlg::isUnlimited() const -{ - return (myUndoDepth + 1 == UNDO_DEPTH_UNLIMITED); -} - -//======================================================================= -// function: init -// purpose: -//======================================================================= -void CurveCreator_UndoOptsDlg::init() -{ - // Initialize sections group. - myOptsBtnGrp->setExclusive(true); - myOptsBtnGrp->button(UNDO_DEPTH_UNLIMITED)->setChecked(true); - connect(myOptsBtnGrp, SIGNAL(buttonClicked(int)), - this, SLOT(optionChanged(int))); - - // Initialize line edit. - QIntValidator *aValidator = new QIntValidator(myBufferSizeEdit); - - aValidator->setBottom(1); - myBufferSizeEdit->setValidator(aValidator); - optionChanged(UNDO_DEPTH_UNLIMITED); - - // Init buttons. - myOkBtn->setDefault(true); - - connect(myOkBtn, SIGNAL(clicked()), this, SLOT(accept())); - connect(myCancelBtn, SIGNAL(clicked()), this, SLOT(reject())); - - setTabOrder(); -} - -//======================================================================= -// function: setTabOrder -// purpose: -//======================================================================= -void CurveCreator_UndoOptsDlg::setTabOrder() -{ - QWidget::setTabOrder(myOptsBtnGrp->button(UNDO_DEPTH_DISABLED), - myOptsBtnGrp->button(UNDO_DEPTH_FIX_SIZE)); - QWidget::setTabOrder(myOptsBtnGrp->button(UNDO_DEPTH_FIX_SIZE), - myBufferSizeEdit); - QWidget::setTabOrder(myBufferSizeEdit, - myOptsBtnGrp->button(UNDO_DEPTH_UNLIMITED)); - QWidget::setTabOrder(myOptsBtnGrp->button(UNDO_DEPTH_UNLIMITED), myOkBtn); - QWidget::setTabOrder(myOkBtn, myCancelBtn); -} - -//======================================================================= -// function: optionChanged -// purpose: -//======================================================================= -void CurveCreator_UndoOptsDlg::optionChanged(int theId) -{ - switch (theId) { - case UNDO_DEPTH_FIX_SIZE: - myBufferSizeEdit->setEnabled(true); - break; - case UNDO_DEPTH_UNLIMITED: - case UNDO_DEPTH_DISABLED: - default: - myBufferSizeEdit->setEnabled(false); - break; - } -} - -//======================================================================= -// function: accept -// purpose: -//======================================================================= -void CurveCreator_UndoOptsDlg::accept() -{ - const int anId = myOptsBtnGrp->checkedId(); - - switch (anId) { - case UNDO_DEPTH_FIX_SIZE: - myUndoDepth = myBufferSizeEdit->text().toInt(); - break; - case UNDO_DEPTH_UNLIMITED: - case UNDO_DEPTH_DISABLED: - myUndoDepth = anId - 1; - break; - default: - break; - } - - QDialog::accept(); -} diff --git a/src/CurveCreator/CurveCreator_UndoOptsDlg.h b/src/CurveCreator/CurveCreator_UndoOptsDlg.h deleted file mode 100644 index 86aa87aa3..000000000 --- a/src/CurveCreator/CurveCreator_UndoOptsDlg.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (C) 2013-2014 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, 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: CurveCreator_UndoOptsDlg.h -// Author: Sergey KHROMOV - -#ifndef _CurveCreator_UndoOptsDlg_HeaderFile -#define _CurveCreator_UndoOptsDlg_HeaderFile - -#include - -class QButtonGroup; -class QLineEdit; -class QPushButton; - - -class CurveCreator_UndoOptsDlg : public QDialog -{ - Q_OBJECT - -public: - - CurveCreator_UndoOptsDlg(QWidget* parent); - - ~CurveCreator_UndoOptsDlg(); - - void setUndoDepth(const int theDepth); - - int getUndoDepth() const; - - bool isEnabled() const; - - bool isUnlimited() const; - -private: - - void init(); - - void setTabOrder(); - -private slots: - - void optionChanged(int theId); - - void accept(); - -protected: - - int myUndoDepth; - QButtonGroup *myOptsBtnGrp; - QLineEdit *myBufferSizeEdit; - QPushButton *myOkBtn; - QPushButton *myCancelBtn; - -}; - -#endif diff --git a/src/CurveCreator/CurveCreator_Utils.cxx b/src/CurveCreator/CurveCreator_Utils.cxx new file mode 100644 index 000000000..146676c95 --- /dev/null +++ b/src/CurveCreator/CurveCreator_Utils.cxx @@ -0,0 +1,994 @@ +// Copyright (C) 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 +// + +#include "CurveCreator_Utils.hxx" +#include "CurveCreator.hxx" +#include "CurveCreator_Curve.hxx" +#include "CurveCreator_UtilsICurve.hxx" + +#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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "CurveCreator_ICurve.hxx" + +const double LOCAL_SELECTION_TOLERANCE = 0.0001; +const int SCENE_PIXEL_PROJECTION_TOLERANCE = 10; +const int SCENE_PIXEL_POINT_TOLERANCE = 5; + +#define PLN_FREE 0 +#define PLN_ORIGIN 1 +#define PLN_OX 2 +#define PLN_FIXED 3 + +/** + * This static function returns the curve of original type from the edge. + * + * \param theEdge the edge + * \return the curve of original type. Can be null handle. + */ +static Handle(Geom_Curve) GetCurve(const TopoDS_Edge &theEdge) +{ + Handle(Geom_Curve) aResult; + + if (theEdge.IsNull()) { + return aResult; + } + + Standard_Real aF; + Standard_Real aL; + + aResult = BRep_Tool::Curve(theEdge, aF, aL); + + if (aResult.IsNull()) { + return aResult; + } + + // Get the curve of original type + Handle(Standard_Type) aType = aResult->DynamicType(); + + while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) { + Handle(Geom_TrimmedCurve) aTrCurve = + Handle(Geom_TrimmedCurve)::DownCast(aResult); + + aResult = aTrCurve->BasisCurve(); + aType = aResult->DynamicType(); + } + + return aResult; +} + +//======================================================================= +// function : ConvertClickToPoint() +// purpose : Returns the point clicked in 3D view +//======================================================================= +void CurveCreator_Utils::ConvertPointToClick( const gp_Pnt& thePoint, + Handle(V3d_View) theView, + int& x, int& y ) +{ + theView->Convert(thePoint.X(), thePoint.Y(), thePoint.Z(), x, y ); +} + + +//======================================================================= +// function : ConvertClickToPoint() +// purpose : Returns the point clicked in 3D view +//======================================================================= +gp_Pnt CurveCreator_Utils::ConvertClickToPoint( int x, int y, Handle(V3d_View) aView ) +{ + // the 3D point, that is a projection of the pixels to the XYZ view plane + //return GEOMUtils::ConvertClickToPoint( x, y, aView ); + + // we need the projection to the XOY plane + // 1. find a point in the plane of the eye and the normal to the plane + Standard_Real X, Y, Z; + Quantity_Parameter Vx, Vy, Vz; + aView->ConvertWithProj( x, y, X, Y, Z, Vx, Vy, Vz ); + + // 2. build a ray from the point by the normal to the XOY plane and intersect it + // The ray equation is the following : p(x,y,z) = p0(x,y,z) + t*V(x,y,z) + // X,Y,Z - defines p0(x,y,z), Vx,Vy,Vz - defines V(x,y,z) + // p(x,y,z) - is a searched point, t - should to be calculated by the condition of XOY plane + // The system of equations is the following: + // p(x) = p0(x)+t*V(x) + // p(y) = p0(y)+t*V(y) + // p(z) = p0(z)+t*V(z) + // p(z) = 0 + + Standard_Real aXp, aYp, aZp; + //It is not possible to use Precision::Confusion(), because it is e-0.8, but V is sometimes e-6 + Standard_Real aPrec = LOCAL_SELECTION_TOLERANCE; + if ( fabs( Vz ) > aPrec ) { + Standard_Real aT = -Z/Vz; + aXp = X + aT*Vx; + aYp = Y + aT*Vy; + aZp = Z + aT*Vz; + } + else { // Vz = 0 - the eyed plane is orthogonal to Z plane - XOZ, or YOZ + aXp = aYp = aZp = 0; + if ( fabs( Vy ) < aPrec ) // Vy = 0 - the YOZ plane + aYp = Y; + else if ( fabs( Vx ) < aPrec ) // Vx = 0 - the XOZ plane + aXp = X; + } + /*std::cout << "ConvertClickToPoint: " << std::endl + << "XYZ1 = (" << X << ", " << Y << ", " << Z << "); " << std::endl + << "Vxyz = (" << Vx << ", " << Vy << ", " << Vz << "); " << std::endl + << "Resp = (" << aXp << ", " << aYp << ", " << aZp << "); " << std::endl;*/ + + gp_Pnt ResultPoint( aXp, aYp, aZp ); + return ResultPoint; +} + +void CurveCreator_Utils::constructShape( const CurveCreator_ICurve* theCurve, + TopoDS_Shape& theShape ) +{ + BRep_Builder aBuilder; + TopoDS_Compound aComp; + aBuilder.MakeCompound( aComp ); + for( int iSection = 0 ; iSection < theCurve->getNbSections() ; iSection++ ) + { + int theISection = iSection; + + CurveCreator::SectionType aSectType = theCurve->getSectionType( theISection ); + int aPointSize = theCurve->getNbPoints( theISection ); + if ( aPointSize == 0 ) + continue; + + bool aSectIsClosed = theCurve->isClosed( theISection ); + bool isPolyline = aSectType == CurveCreator::Polyline; + + int iPoint = 0; + gp_Pnt aPrevPoint, aPoint; + // filters the curve points to skip equal points + std::vector aPoints; + CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + aPoints.push_back( aPoint ); + aPrevPoint = aPoint; + iPoint++; + for( ; iPoint < aPointSize; iPoint++ ) { + CurveCreator_UtilsICurve::getPoint( theCurve, theISection, iPoint, aPoint ); + if ( !isEqualPoints( aPrevPoint, aPoint ) ) + aPoints.push_back( aPoint ); + aPrevPoint = aPoint; + } + int aNbPoints = aPoints.size(); + + if ( aNbPoints == 1 ) { + aPoint = aPoints.front(); + TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); + aBuilder.Add( aComp, aVertex ); + } + else if ( aNbPoints > 1 ) { + Handle(TColgp_HArray1OfPnt) aHCurvePoints = new TColgp_HArray1OfPnt(1, aNbPoints); + TColgp_Array1OfVec aTangents(1, aNbPoints); + Handle(TColStd_HArray1OfBoolean) aTangentFlags = new TColStd_HArray1OfBoolean(1, aNbPoints); + gp_Vec aNullVec(0, 0, 0); + + TopoDS_Edge aPointEdge; + TopoDS_Vertex aVertex; + + std::vector::const_iterator aPointIt = aPoints.begin(), aPointLast = aPoints.end(); + aPoint = *aPointIt; + + int aHIndex = 1; + aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); + aBuilder.Add( aComp, aVertex ); + if ( !isPolyline ) { + aHCurvePoints->SetValue( aHIndex, aPoint ); + aTangents.SetValue( aHIndex, aNullVec ); + aTangentFlags->SetValue( aHIndex, Standard_False ); + aHIndex++; + } + + aPrevPoint = aPoint; + aPointIt++; + for( ; aPointIt != aPointLast; aPointIt++ ) { + aPoint = *aPointIt; + aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); + aBuilder.Add( aComp, aVertex ); + if ( isPolyline ) { + TopoDS_Edge aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge(); + aBuilder.Add( aComp, aPointEdge ); + } + else { + aHCurvePoints->SetValue( aHIndex, aPoint ); + aTangents.SetValue( aHIndex, aNullVec ); + aTangentFlags->SetValue( aHIndex, Standard_False ); + aHIndex++; + } + aPrevPoint = aPoint; + } + if( aSectIsClosed && ( aNbPoints > 2 ) ) { + aPoint = aPoints.front(); + aVertex = BRepBuilderAPI_MakeVertex( aPoint ).Vertex(); + aBuilder.Add( aComp, aVertex ); + if ( isPolyline ) { + aPointEdge = BRepBuilderAPI_MakeEdge( aPrevPoint, aPoint ).Edge(); + aBuilder.Add( aComp, aPointEdge ); + } + } + if( !isPolyline ) { + // compute BSpline + Handle(Geom_BSplineCurve) aBSplineCurve; + GeomAPI_Interpolate aGBC(aHCurvePoints, aSectIsClosed, gp::Resolution()); + // correct the spline degree to be as 3 for non-periodic spline if number of points + // less than 3. It is need to have a knot in each spline point. This knots are used + // to found a neighbour points when a new point is inserted between two existing. + if (!aSectIsClosed ) { + if (aHCurvePoints->Length() == 3) + aGBC.Load(aTangents, aTangentFlags); + } + + aGBC.Perform(); + if ( aGBC.IsDone() ) + aBSplineCurve = aGBC.Curve(); + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSplineCurve ).Edge(); + TopoDS_Wire aWire = BRepBuilderAPI_MakeWire( anEdge ).Wire(); + aBuilder.Add( aComp, aWire ); + } + } + } + theShape = aComp; +} + +/** + * This is an intermediate structure for curve construction. + */ +struct Section3D +{ + Section3D() : myIsClosed(false), myIsBSpline(false) + { } + + bool myIsClosed; + bool myIsBSpline; + Handle(TColgp_HArray1OfPnt) myPoints; +}; + +//======================================================================= +// function : constructCurve +// purpose : +//======================================================================= +bool CurveCreator_Utils::constructCurve + (const TopoDS_Shape theShape, + CurveCreator_Curve *theCurve, + gp_Ax3 &theLocalCS) +{ + if (theShape.IsNull()) { + return false; + } + + // Collect wires or vertices from shape. + TopTools_ListOfShape aWOrV; + TopAbs_ShapeEnum aType = theShape.ShapeType(); + + if (aType == TopAbs_WIRE || aType == TopAbs_VERTEX) { + aWOrV.Append(theShape); + } else if (aType == TopAbs_COMPOUND) { + TopoDS_Iterator aShIter(theShape); + + for (; aShIter.More(); aShIter.Next()) { + const TopoDS_Shape &aSubShape = aShIter.Value(); + + aType = aSubShape.ShapeType(); + + if (aType == TopAbs_WIRE || aType == TopAbs_VERTEX) { + aWOrV.Append(aSubShape); + } else { + // Only subshapes of types wire or vertex are supported. + return false; + } + } + } else { + // Only wire (vertex) or compound of wires (vertices) are supported. + return false; + } + + // Treat each wire or vertex. Get points, compute the working plane. + gp_Pln aPlane; + Standard_Integer aPlaneStatus = PLN_FREE; + TopTools_ListIteratorOfListOfShape anIter(aWOrV); + std::list aListSec; + + for (; anIter.More(); anIter.Next()) { + Section3D aSec3D; + + aSec3D.myPoints = CurveCreator_Utils::getPoints + (anIter.Value(), aSec3D.myIsClosed, aSec3D.myIsBSpline); + + if (aSec3D.myPoints.IsNull()) { + return false; + } + + aListSec.push_back(aSec3D); + + if (aPlaneStatus != PLN_FIXED) { + // Compute plane + CurveCreator_Utils::FindPlane(aSec3D.myPoints, aPlane, aPlaneStatus); + } + } + + // Check if it is possible to change a computed coordinate system by + // XOY, XOZ or YOZ or parallel to them. + gp_Pnt aO(0., 0., 0.); + gp_Dir aNDir(0., 0., 1.); + gp_Dir aXDir(1., 0., 0.); + gp_Ax3 anAxis; + Standard_Real aTolAng = Precision::Confusion(); // Angular() is too small. + + switch (aPlaneStatus) { + case PLN_ORIGIN: + { + // Change the location. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } + break; + case PLN_OX: + { + // Fixed origin + OX axis + const gp_Dir &aPlnX = aPlane.Position().XDirection(); + + if (Abs(aPlnX.Z()) <= aTolAng) { + // Make a coordinate system parallel to XOY. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } else if (Abs(aPlnX.Y()) <= aTolAng) { + // Make a coordinate system parallel to XOZ. + aO.SetY(aPlane.Location().Y()); + aNDir.SetCoord(0., 1., 0.); + aXDir.SetCoord(0., 0., 1.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } else if (Abs(aPlnX.X()) <= aTolAng) { + // Make a coordinate system parallel to YOZ. + aO.SetX(aPlane.Location().X()); + aNDir.SetCoord(1., 0., 0.); + aXDir.SetCoord(0., 1., 0.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } + } + break; + case PLN_FIXED: + { + const gp_Dir &aPlnN = aPlane.Position().Direction(); + gp_Dir aYDir(0., 1., 0.); + + if (aPlnN.IsParallel(aNDir, aTolAng)) { + // Make a coordinate system parallel to XOY. + aO.SetZ(aPlane.Location().Z()); + anAxis.SetLocation(aO); + aPlane.SetPosition(anAxis); + } else if (aPlnN.IsParallel(aYDir, aTolAng)) { + // Make a coordinate system parallel to XOZ. + aO.SetY(aPlane.Location().Y()); + aNDir.SetCoord(0., 1., 0.); + aXDir.SetCoord(0., 0., 1.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } else if (aPlnN.IsParallel(aXDir, aTolAng)) { + // Make a coordinate system parallel to YOZ. + aO.SetX(aPlane.Location().X()); + aNDir.SetCoord(1., 0., 0.); + aXDir.SetCoord(0., 1., 0.); + anAxis = gp_Ax3(aO, aNDir, aXDir); + aPlane.SetPosition(anAxis); + } + } + break; + case PLN_FREE: + default: + // Use XOY plane. + aPlane.SetPosition(anAxis); + break; + } + + // Compute 2d points. + std::list::const_iterator aSecIt = aListSec.begin(); + Standard_Real aTolConf2 = + Precision::Confusion()*Precision::Confusion(); + Standard_Real aX; + Standard_Real aY; + + for (; aSecIt != aListSec.end(); ++aSecIt) { + Standard_Integer i; + CurveCreator::Coordinates aCoords; + + for (i = aSecIt->myPoints->Lower(); i <= aSecIt->myPoints->Upper(); ++i) { + const gp_Pnt &aPnt = aSecIt->myPoints->Value(i); + + if (aPlane.SquareDistance(aPnt) > aTolConf2) { + // The point doesn't lie on the plane. + return false; + } + + ElSLib::Parameters(aPlane, aPnt, aX, aY); + aCoords.push_back(aX); + aCoords.push_back(aY); + } + + // Add a new section to the curve. + const std::string aSecName = + CurveCreator_UtilsICurve::getUniqSectionName(theCurve); + const CurveCreator::SectionType aSecType = aSecIt->myIsBSpline ? + CurveCreator::Spline : CurveCreator::Polyline; + + theCurve->addSectionInternal(aSecName, aSecType, + aSecIt->myIsClosed, aCoords); + } + + // Set the local coordinate system. + theLocalCS = aPlane.Position(); + + return true; +} + +class CompareSectionToPoint +{ +public: + CompareSectionToPoint( const int theISection = -1, const int theIPoint = -1 ) + : mySectionId( theISection ), myPointId( theIPoint ) {}; + ~CompareSectionToPoint() {} + + bool operator < ( const CompareSectionToPoint& theOther ) const + { + bool isLess = mySectionId < theOther.mySectionId; + if ( !isLess && mySectionId == theOther.mySectionId ) + isLess = myPointId < theOther.myPointId; + return isLess; + } + +private: + int mySectionId; + int myPointId; +}; + + +void CurveCreator_Utils::getSelectedPoints( Handle(AIS_InteractiveContext) theContext, + const CurveCreator_ICurve* theCurve, + CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + thePoints.clear(); + + std::list aSelectedPoints; + gp_Pnt aPnt; + std::map aPointsMap; + + CurveCreator_ICurve::SectionToPointList aPoints; + for ( theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected() ) { + TopoDS_Vertex aVertex; + TopoDS_Shape aShape = theContext->SelectedShape(); + if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX ) + aVertex = TopoDS::Vertex( theContext->SelectedShape() ); + + if ( aVertex.IsNull() ) + continue; + aPnt = BRep_Tool::Pnt( aVertex ); + + CurveCreator_UtilsICurve::findSectionsToPoints( theCurve, aPnt.X(), aPnt.Y(), aPoints ); + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aPoints.begin(), + aLast = aPoints.end(); + CompareSectionToPoint aPoint; + for ( ; anIt != aLast; anIt++ ) { + aPoint = CompareSectionToPoint( (*anIt).first, (*anIt).second ); + if ( aPointsMap.find( aPoint ) != aPointsMap.end() ) + continue; + aPointsMap[aPoint] = 0; + + thePoints.push_back( *anIt ); + } + } +} + +void CurveCreator_Utils::setSelectedPoints( Handle(AIS_InteractiveContext) theContext, + const CurveCreator_ICurve* theCurve, + const CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + if ( !theCurve ) + return; + + Handle(AIS_InteractiveObject) anAIS = theCurve->getAISObject(); + if ( anAIS.IsNull() ) + return; + Handle(AIS_Shape) anAISShape = Handle(AIS_Shape)::DownCast( anAIS ); + if ( anAISShape.IsNull() ) + return; + + //ASL: we convert list of point indices to list of points coordinates + int aSize = thePoints.size(); + std::vector aPntsToSelect( aSize ); + + CurveCreator_ICurve::SectionToPointList::const_iterator + aPIt = thePoints.begin(), aPLast = thePoints.end(); + CurveCreator_ICurve::SectionToPoint aSToPoint; + for( int i=0; aPIt != aPLast; aPIt++, i++ ) + { + gp_Pnt aPntToSelect; + CurveCreator_UtilsICurve::getPoint( theCurve, aPIt->first, aPIt->second, aPntToSelect ); + aPntsToSelect[i] = aPntToSelect; + } + + theContext->ClearSelected( Standard_False ); + //ASL: we switch off automatic highlight to improve performance of selection + theContext->SetAutomaticHilight( Standard_False ); + + Handle_SelectMgr_Selection aSelection = anAISShape->Selection( AIS_Shape::SelectionMode( TopAbs_VERTEX ) ); + for( aSelection->Init(); aSelection->More(); aSelection->Next() ) + { + Handle_SelectBasics_SensitiveEntity aSenEntity = aSelection->Sensitive(); + Handle_Select3D_SensitivePoint aSenPnt = Handle_Select3D_SensitivePoint::DownCast( aSenEntity ); + + gp_Pnt anOwnerPnt = aSenPnt->Point(); + Handle_SelectMgr_EntityOwner anOwner = Handle_SelectMgr_EntityOwner::DownCast( aSenPnt->OwnerId() ); + + + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = thePoints.begin(), + aLast = thePoints.end(); + bool isFound = false; + for( int i=0; iAddOrRemoveSelected( anOwner, Standard_False ); + break; + } + } + } + + //ASL: we switch on again automatic highlight (otherwise selection will not be shown) + // and call HilightPicked to draw selected owners + theContext->SetAutomaticHilight( Standard_True ); + theContext->LocalContext()->HilightPicked( Standard_True ); +} + +//======================================================================= +// function : setLocalPointContext +// purpose : Open/close the viewer local context +//======================================================================= +void CurveCreator_Utils::setLocalPointContext( const CurveCreator_ICurve* theCurve, + Handle(AIS_InteractiveContext) theContext, + const bool theOpen ) +{ + if ( !theContext ) + return; + + if ( theOpen ) { + // Open local context if there is no one + if ( !theContext->HasOpenedContext() ) { + theContext->ClearCurrents( false ); + theContext->OpenLocalContext( false/*use displayed objects*/, true/*allow shape decomposition*/ ); + } + // load the curve AIS object to the local context with the point selection + Handle(AIS_InteractiveObject) anAIS = theCurve->getAISObject(); + if ( !anAIS.IsNull() ) + { + if ( anAIS->IsKind( STANDARD_TYPE( AIS_Shape ) ) ) + { + theContext->Load( anAIS, -1/*selection mode*/, true/*allow decomposition*/ ); + theContext->Activate( anAIS, AIS_Shape::SelectionMode( (TopAbs_ShapeEnum)TopAbs_VERTEX ) ); + } + } + } + else { + if ( theContext->HasOpenedContext() ) + theContext->CloseAllContexts(); + } +} + +bool CurveCreator_Utils::pointOnObject( Handle(V3d_View) theView, + Handle(AIS_InteractiveObject) theObject, + const int theX, const int theY, + gp_Pnt& thePoint, + gp_Pnt& thePoint1, gp_Pnt& thePoint2 ) +{ + bool isFullFound = false; + + if ( theObject.IsNull() || theView.IsNull() ) + return isFullFound; + Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast( theObject ); + if ( aShape.IsNull() ) + return isFullFound; + const TopoDS_Compound& aCompound = TopoDS::Compound( aShape->Shape() ); + if ( aCompound.IsNull() ) + return isFullFound; + + gp_Pnt aCurPoint, aCurPoint1, aCurPoint2; + gp_Pnt aFoundPoint, aFoundPnt1, aFoundPnt2; + Standard_Real aParameter; + bool isFound = false; + int aDelta, aMinDelta = 2*SCENE_PIXEL_PROJECTION_TOLERANCE*SCENE_PIXEL_PROJECTION_TOLERANCE; + TopExp_Explorer anExp( aCompound, TopAbs_EDGE ); + for ( ; anExp.More(); anExp.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current()); + if ( anEdge.IsNull() ) + continue; + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve( anEdge, aFirst, aLast ); + if ( aCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) ) { + Handle(Geom_BSplineCurve) aBSplineCurve = + Handle(Geom_BSplineCurve)::DownCast( aCurve ); + if ( !aBSplineCurve.IsNull() ) { + isFound = hasProjectPointOnCurve( theView, theX, theY, aBSplineCurve, + aParameter, aDelta ); + if ( isFound ) { + aCurPoint = aBSplineCurve->Value( aParameter ); + Standard_Integer anI1, anI2; + aBSplineCurve->LocateU( aParameter, LOCAL_SELECTION_TOLERANCE, anI1, anI2 ); + aCurPoint1 = aBSplineCurve->Value( aBSplineCurve->Knot( anI1 ) ); + aCurPoint2 = aBSplineCurve->Value( aBSplineCurve->Knot( anI2 ) ); + } + } + } + else { // a curve built on a polyline edge + Handle(Geom_Line) aGLine = Handle(Geom_Line)::DownCast( aCurve ); + if ( aGLine.IsNull() ) + continue; + isFound = hasProjectPointOnCurve( theView, theX, theY, aGLine, aParameter, + aDelta ); + if ( isFound ) { + aCurPoint = aGLine->Value( aParameter ); + TopoDS_Vertex V1, V2; + TopExp::Vertices( anEdge, V1, V2, Standard_True ); + if ( V1.IsNull() || V2.IsNull() ) + continue; + aCurPoint1 = BRep_Tool::Pnt(V1); + aCurPoint2 = BRep_Tool::Pnt(V2); + + // check that the projected point is on the bounded curve + gp_Vec aVec1( aCurPoint1, aCurPoint ); + gp_Vec aVec2( aCurPoint2, aCurPoint ); + isFound = fabs( aVec1.Angle( aVec2 ) - M_PI ) < LOCAL_SELECTION_TOLERANCE; + } + } + if ( isFound && aMinDelta >= aDelta ) { + aMinDelta = aDelta; + + isFullFound = true; + aFoundPnt1 = aCurPoint1; + aFoundPnt2 = aCurPoint2; + aFoundPoint = aCurPoint; + } + } + if ( isFullFound ) { + int aX, anY, aX1, anY1, aX2, anY2; + int aDelta; + CurveCreator_Utils::ConvertPointToClick( aFoundPoint, theView, aX, anY ); + CurveCreator_Utils::ConvertPointToClick( aFoundPnt1, theView, aX1, anY1 ); + CurveCreator_Utils::ConvertPointToClick( aFoundPnt2, theView, aX2, anY2 ); + + isFullFound = !isEqualPixels( aX, anY, aX1, anY1, SCENE_PIXEL_POINT_TOLERANCE, aDelta ) && + !isEqualPixels( aX, anY, aX2, anY2, SCENE_PIXEL_POINT_TOLERANCE, aDelta ); + if ( isFullFound ) { + thePoint = aFoundPoint; + thePoint1 = aFoundPnt1; + thePoint2 = aFoundPnt2; + } + } + return isFullFound; +} + +bool CurveCreator_Utils::hasProjectPointOnCurve( Handle(V3d_View) theView, + const int theX, const int theY, + const Handle(Geom_Curve)& theCurve, + Standard_Real& theParameter, + int& theDelta ) +{ + bool isFound = false; + if ( theView.IsNull() ) + return isFound; + + gp_Pnt aPoint = CurveCreator_Utils::ConvertClickToPoint( theX, theY, theView ); + + GeomAPI_ProjectPointOnCurve aProj( aPoint, theCurve ); + Standard_Integer aNbPoint = aProj.NbPoints(); + if (aNbPoint > 0) { + for (Standard_Integer j = 1; j <= aNbPoint && !isFound; j++) { + gp_Pnt aNewPoint = aProj.Point( j ); + theParameter = aProj.Parameter( j ); + + int aX, anY; + CurveCreator_Utils::ConvertPointToClick( aNewPoint, theView, aX, anY ); + + isFound = isEqualPixels( aX, anY, theX, theY, SCENE_PIXEL_PROJECTION_TOLERANCE, theDelta ); + } + } + return isFound; +} + +bool CurveCreator_Utils::isEqualPixels( const int theX, const int theY, const int theOtherX, + const int theOtherY, const double theTolerance, int& theDelta ) +{ + int aXDelta = abs( theX - theOtherX ); + int anYDelta = abs( theY - theOtherY ); + + theDelta = aXDelta*aXDelta + anYDelta*anYDelta; + + return aXDelta < theTolerance && anYDelta < theTolerance; +} + +bool CurveCreator_Utils::isEqualPoints( const gp_Pnt& thePoint, const gp_Pnt& theOtherPoint ) +{ + return theOtherPoint.IsEqual( thePoint, LOCAL_SELECTION_TOLERANCE ); +} + +//======================================================================= +// function : getPoints +// purpose : +//======================================================================= +Handle(TColgp_HArray1OfPnt) CurveCreator_Utils::getPoints + (const TopoDS_Shape &theShape, + bool &IsClosed, + bool &IsBSpline) +{ + Handle(TColgp_HArray1OfPnt) aResult; + + IsClosed = false; + IsBSpline = false; + + if (theShape.IsNull()) { + return aResult; + } + + const TopAbs_ShapeEnum aShType = theShape.ShapeType(); + + if (aShType == TopAbs_VERTEX) { + // There is a single point. + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape)); + + aResult = new TColgp_HArray1OfPnt(1, 1, aPnt); + + return aResult; + } else if (aShType != TopAbs_WIRE) { + // The shape is neither a vertex nor a wire. + return aResult; + } + + // Treat wire. + BRepTools_WireExplorer anExp(TopoDS::Wire(theShape)); + + if (!anExp.More()) { + // Empty wires are not allowed. + return aResult; + } + + // Treat the first edge. + TopoDS_Edge anEdge = anExp.Current(); + Handle(Geom_Curve) aCurve = GetCurve(anEdge); + + if (aCurve.IsNull()) { + return aResult; + } + + // Check the curve type. + Handle(Standard_Type) aType = aCurve->DynamicType(); + + if (aType == STANDARD_TYPE(Geom_BSplineCurve)) { + IsBSpline = true; + } else if (aType != STANDARD_TYPE(Geom_Line)) { + // The curve is neither a line or a BSpline. It is not valid. + return aResult; + } + + // Go to the next edge. + TopoDS_Vertex aFirstVtx = anExp.CurrentVertex(); + + anExp.Next(); + + if (IsBSpline) { + // There should be a single BSpline curve in the wire. + if (anExp.More()) { + return aResult; + } + + // Construct a section from poles of BSpline. + Handle(Geom_BSplineCurve) aBSplCurve = + Handle(Geom_BSplineCurve)::DownCast(aCurve); + + // Check if the edge is valid. It should not be based on trimmed curve. + gp_Pnt aCP[2] = { aBSplCurve->StartPoint(), aBSplCurve->EndPoint() }; + TopoDS_Vertex aV[2]; + Standard_Integer i; + + TopExp::Vertices(anEdge, aV[0], aV[1]); + + for (i = 0; i < 2; i++) { + gp_Pnt aPnt = BRep_Tool::Pnt(aV[i]); + Standard_Real aTol = BRep_Tool::Tolerance(aV[i]); + + if (!aPnt.IsEqual(aCP[i], aTol)) { + return aResult; + } + } + + IsClosed = aV[0].IsSame(aV[1]) ? true : false; + + const Standard_Integer aNbPoints = aBSplCurve->NbKnots(); + TColStd_Array1OfReal aKnots(1, aNbPoints); + + aBSplCurve->Knots(aKnots); + aResult = new TColgp_HArray1OfPnt(1, aBSplCurve->NbKnots()); + + for (i = aKnots.Lower(); i <= aKnots.Upper(); ++i) { + aResult->SetValue(i, aBSplCurve->Value(aKnots.Value(i))); + } + } else { + // This is a polyline. + TopTools_ListOfShape aVertices; + Standard_Integer aNbVtx = 1; + + + aVertices.Append(aFirstVtx); + + for (; anExp.More(); anExp.Next(), ++aNbVtx) { + anEdge = anExp.Current(); + aCurve = GetCurve(anEdge); + + if (aCurve.IsNull()) { + return aResult; + } + + aType = aCurve->DynamicType(); + + if (aType != STANDARD_TYPE(Geom_Line)) { + // The curve is not a line. It is not valid. + return aResult; + } + + // Add the current vertex to the list. + aVertices.Append(anExp.CurrentVertex()); + } + + // Check if the section is closed. + TopoDS_Vertex aLastVtx = TopExp::LastVertex(anEdge, Standard_True); + + IsClosed = aFirstVtx.IsSame(aLastVtx) ? true : false; + + // Fill the array of points. + aResult = new TColgp_HArray1OfPnt(1, aNbVtx); + + Standard_Integer i; + TopTools_ListIteratorOfListOfShape aVtxIter(aVertices); + + for (i = 1; aVtxIter.More(); aVtxIter.Next(), ++i) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVtxIter.Value())); + + aResult->SetValue(i, aPnt); + } + } + + return aResult; +} +//======================================================================= +// function : FindPlane +// purpose : +//======================================================================= +void CurveCreator_Utils::FindPlane + (const Handle_TColgp_HArray1OfPnt &thePoints, + gp_Pln &thePlane, + Standard_Integer &thePlnStatus) +{ + if (thePoints.IsNull() || thePlnStatus == PLN_FIXED) { + // The plane can't be defined or is fixed. Nothing to change. + return; + } + + Standard_Integer i; + const Standard_Real aTolConf = Precision::Confusion(); + + for (i = thePoints->Lower(); i <= thePoints->Upper(); ++i) { + const gp_Pnt &aPnt = thePoints->Value(i); + + switch (thePlnStatus) { + case PLN_FREE: + // Fix the origin. + thePlane.SetLocation(aPnt); + thePlnStatus = PLN_ORIGIN; + break; + case PLN_ORIGIN: + { + // Fix origin + OX axis + const gp_Pnt &aPlnLoc = thePlane.Location(); + + if (!aPnt.IsEqual(aPlnLoc, aTolConf)) { + // Set the X axis. + gp_Dir aXDir(aPnt.XYZ().Subtracted(aPlnLoc.XYZ())); + gp_Ax3 aXNorm(aPlnLoc, aXDir); + gp_Ax3 aNewPlnPos(aPlnLoc, aXNorm.XDirection(), aXNorm.Direction()); + + thePlane.SetPosition(aNewPlnPos); + thePlnStatus = PLN_OX; + } + } + break; + case PLN_OX: + { + // Fix OY axis + gp_Lin aXLin(thePlane.XAxis()); + Standard_Real aSqrDist = aXLin.SquareDistance(aPnt); + + if (aSqrDist > aTolConf*aTolConf) { + // Compute main axis. + const gp_Pnt &aPlnLoc = thePlane.Location(); + gp_Dir aDir(aPnt.XYZ().Subtracted(aPlnLoc.XYZ())); + gp_Ax3 aXNorm(aPlnLoc, aXLin.Direction(), aDir); + gp_Ax3 aNewPlnPos(aPlnLoc, aXNorm.YDirection(), + aXNorm.Direction()); + + thePlane.SetPosition(aNewPlnPos); + thePlnStatus = PLN_FIXED; + return; + } + } + break; + default: + return; + } + } +} diff --git a/src/CurveCreator/CurveCreator_Utils.hxx b/src/CurveCreator/CurveCreator_Utils.hxx new file mode 100644 index 000000000..8dddaf2ff --- /dev/null +++ b/src/CurveCreator/CurveCreator_Utils.hxx @@ -0,0 +1,211 @@ +// Copyright (C) 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 +// + +#ifndef CURVECREATOR_UTILS_H +#define CURVECREATOR_UTILS_H + +#include "CurveCreator_Macro.hxx" +#include "CurveCreator_ICurve.hxx" + +#include +#include // TODO: remove +#include +#include +#include +#include +#include + +#include +#include // TODO: remove + +class CurveCreator_Curve; + + +class CurveCreator_Utils +{ +public: + + /*! + * \brief Returns the point clicked in 3D view. + * + * \param x The X coordinate in the view. + * \param y The Y coordinate in the view. + * \param theView View where the given point takes place. + * \retval gp_Pnt Returns the point clicked in 3D view + */ + CURVECREATOR_EXPORT static void ConvertPointToClick( const gp_Pnt& thePoint, + Handle(V3d_View) theView, + int& x, int& y ); + + /*! + * \brief Returns the point clicked in 3D view. + * + * \param x The X coordinate in the view. + * \param y The Y coordinate in the view. + * \param theView View where the given point takes place. + * \retval gp_Pnt Returns the point clicked in 3D view + */ + CURVECREATOR_EXPORT static gp_Pnt ConvertClickToPoint( int x, int y, + Handle(V3d_View) theView ); + + /** + * Generates shape on the curve + * \param theCurve a curve object, that contains data + * \param theShape a generated shape + */ + CURVECREATOR_EXPORT static void constructShape( const CurveCreator_ICurve* theCurve, + TopoDS_Shape& theShape ); + + /** + * Generates a curve from a shape. + * \param theShape a shape to be converted to curve. + * \param theCurve a curve object to be initialized. + * \param theLocalCS the local coordinate system of the curve. + * \return true in case of success; false otherwise. Warning: the curve can + * be modified even if the shape is not valid for curve construction. + */ + CURVECREATOR_EXPORT static bool constructCurve + (const TopoDS_Shape theShape, + CurveCreator_Curve *theCurve, + gp_Ax3 &theLocalCS); + + /** + * Find selected points in the context + * \param theContext the viewer context + * \param theCurve a curve object, that contains data + */ + CURVECREATOR_EXPORT static void getSelectedPoints( Handle(AIS_InteractiveContext) theContext, + const CurveCreator_ICurve* theCurve, + CurveCreator_ICurve::SectionToPointList& thePoints ); + + /** + * Set selected points to the context + * \param theContext the viewer context + * \param theCurve a curve object, that contains data + * \param thePoints the curve point indices to be selected in the context + */ + CURVECREATOR_EXPORT static void setSelectedPoints( + Handle(AIS_InteractiveContext) theContext, + const CurveCreator_ICurve* theCurve, + const CurveCreator_ICurve::SectionToPointList& thePoints = + CurveCreator_ICurve::SectionToPointList() ); + + /*! + * \brief Sets the local point context for the 3D viewer. + * \param theCurve a curve object, that contains data + * \param theContext the viewer context + * \param theOpen The flag to open or close the local context. + */ + CURVECREATOR_EXPORT static void setLocalPointContext( + const CurveCreator_ICurve* theCurve, + Handle(AIS_InteractiveContext) theContext, + const bool theOpen ); + + /** + * Checks whether the point belongs to the OCC object + * \param theObject a line or shape with a bspline inside + * \param theX the X coordinate in the view. + * \param theY the Y coordinate in the view. + * \param thePoint the output point to be append to the model curve + * \param thePoint1 the output point to bound the line where a new point should be inserted + * \param thePoint2 the output point to bound the line where a new point should be inserted + */ + CURVECREATOR_EXPORT static bool pointOnObject( Handle(V3d_View) theView, + Handle(AIS_InteractiveObject) theObject, + const int theX, const int theY, + gp_Pnt& thePoint, gp_Pnt& thePoint1, + gp_Pnt& thePoint2 ); + +protected: + /* + * Returns whether the clicked point belong to the curve or has a very near projection + * \param theX the X coordinate of a point clicked in the OCC viewer + * \param theY the Y coordinate of a point clicked in the OCC viewer + * \param theCurve a geometry curve + * \param theOutPoint a found projected point on the curve + */ + static bool hasProjectPointOnCurve( + Handle(V3d_View) theView, + const int theX, const int theY, + const Handle(Geom_Curve)& theCurve, + Standard_Real& theParameter, + int& theDelta ); + + /* + * Returns whether the X and Y coordinates is in the pixel tolerance + * \param theX the X coordinate of the first point + * \param theY the Y coordinate of the first point + * \param theOtherX the X coordinate of the second point + * \param theOtherY the Y coordinate of the second point + * \param theTolerance the tolerance to compare + * \param theDelta the sum of the a square of X and a square of Y + * \returns whether the points are provide to the pixel tolerance + */ + static bool isEqualPixels( const int theX, const int theY, + const int theOtherX, const int theOtherY, + const double theTolerance, int& theDelta ); + + + /* + * Returns whether the points are the same + * \param thePoint the first point + * \param theOtherPoint the second point + * \returns whether the points are provide to the pixel tolerance + */ + static bool isEqualPoints( const gp_Pnt& thePoint, + const gp_Pnt& theOtherPoint ); + + /** + * Returns the array of points of a shape to construct a curve section. The + * shape can be either a wire or a vertex. For vertex a single point in the + * array is returned. + * + * \param theShape the shape. Can be either a wire or a vertex. + * \param IsClosed closed flag. Output parameter. + * \param IsBSpline BSpline flag. Output parameter. + * \return the array of points. Null handle in case of failure. + */ + static Handle_TColgp_HArray1OfPnt getPoints + (const TopoDS_Shape &theShape, + bool &IsClosed, + bool &IsBSpline); + + /** + * This method computes a plane using the input points. The plane is defined + * by gp_Pln object and the status. The status can have one of the following + * values: + * - 0 plane is not set.
    + * - 1 origin of the plane is fixed. The plane is defined by 1 or several + * coincident points.
    + * - 2 origin + OX axis of the plane is fixed. The plane is defined by 2 + * or more points that lie on a particular line.
    + * - 3 plane is fixed. Plane is defined by 3 not coincident points.
    + * + * \param thePoints the points. + * \param thePlane the current plane on input. It can be modified on output. + * \param thePlnStatus the current status on input. It can be modified on + * output. + */ + static void FindPlane(const Handle_TColgp_HArray1OfPnt &thePoints, + gp_Pln &thePlane, + Standard_Integer &thePlnStatus); + +}; + +#endif // CURVECREATOR_UTILS_H diff --git a/src/CurveCreator/CurveCreator_UtilsICurve.cxx b/src/CurveCreator/CurveCreator_UtilsICurve.cxx new file mode 100644 index 000000000..d11598e25 --- /dev/null +++ b/src/CurveCreator/CurveCreator_UtilsICurve.cxx @@ -0,0 +1,126 @@ +// Copyright (C) 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 +// + +#include "CurveCreator_UtilsICurve.hxx" + +#include "CurveCreator.hxx" +#include + +const double LOCAL_SELECTION_TOLERANCE = 0.0001; + +int CurveCreator_UtilsICurve::findLocalPointIndex( const CurveCreator_ICurve* theCurve, + int theSectionId, float theX, float theY ) +{ + int aPntIndex = -1; + if ( !theCurve ) + return aPntIndex; + + CurveCreator::Coordinates aCoords; + for ( int i = 0, aNb = theCurve->getNbPoints( theSectionId ); i < aNb && aPntIndex < 0; i++ ) { + aCoords = theCurve->getPoint( theSectionId, i ); + if ( aCoords.size() < 2 ) + continue; + if ( fabs( aCoords[0] - theX ) < LOCAL_SELECTION_TOLERANCE && + fabs( aCoords[1] - theY ) < LOCAL_SELECTION_TOLERANCE ) + aPntIndex = i; + } + + return aPntIndex; +} + +void CurveCreator_UtilsICurve::findSectionsToPoints( const CurveCreator_ICurve* theCurve, + const double theX, const double theY, + CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + thePoints.clear(); + + int aPointId = -1; + for ( int i = 0, aNb = theCurve->getNbSections(); i < aNb; i++ ) { + aPointId = CurveCreator_UtilsICurve::findLocalPointIndex( theCurve, i, theX, theY ); + if ( aPointId < 0 ) + continue; + CurveCreator_ICurve::SectionToPoint aPoint = std::make_pair( i, aPointId ); + if ( !CurveCreator_UtilsICurve::contains( thePoints, aPoint ) ) + thePoints.push_back( aPoint ); + } +} + +void CurveCreator_UtilsICurve::convert( const CurveCreator_ICurve::SectionToPointList& thePoints, + QMap >& theConvPoints ) +{ + theConvPoints.clear(); + + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = thePoints.begin(), + aLast = thePoints.end(); + QList aPoints; + int aSectionId, aPointId; + for ( ; anIt != aLast; anIt++ ) { + aSectionId = anIt->first; + aPointId = anIt->second; + aPoints.clear(); + if ( theConvPoints.contains( aSectionId ) ) + aPoints = theConvPoints[aSectionId]; + if ( aPoints.contains( aPointId ) ) + continue; + aPoints.append( aPointId ); + theConvPoints[aSectionId] = aPoints; + } +} + +#include "CurveCreator_Curve.hxx" // TODO +void CurveCreator_UtilsICurve::getPoint( const CurveCreator_ICurve* theCurve, const int theISection, + const int theIPoint, gp_Pnt& thePoint ) +{ + double anX, anY, aZ; + // TODO + const CurveCreator_Curve* aCurve = dynamic_cast( theCurve ); + if ( aCurve ) + aCurve->getCoordinates( theISection, theIPoint, anX, anY, aZ ); + thePoint = gp_Pnt( anX, anY, aZ); +} + +std::string CurveCreator_UtilsICurve::getUniqSectionName( CurveCreator_ICurve* theCurve ) +{ + for( int i = 0 ; i < 1000000 ; i++ ){ + char aBuffer[255]; + sprintf( aBuffer, "Section_%d", i+1 ); + std::string aName(aBuffer); + int j; + for( j = 0 ; j < theCurve->getNbSections() ; j++ ){ + if( theCurve->getSectionName(j) == aName ) + break; + } + if( j == theCurve->getNbSections() ) + return aName; + } + return ""; +} + +bool CurveCreator_UtilsICurve::contains( const CurveCreator_ICurve::SectionToPointList& theList, + const CurveCreator_ICurve::SectionToPoint& theValue ) +{ + bool isFound = false; + + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theList.begin(), + aLast = theList.end(); + for ( ; anIt != aLast && !isFound; anIt++ ) + isFound = anIt->first == theValue.first && anIt->second == theValue.second; + + return isFound; +} diff --git a/src/CurveCreator/CurveCreator_UtilsICurve.hxx b/src/CurveCreator/CurveCreator_UtilsICurve.hxx new file mode 100644 index 000000000..96b4e454b --- /dev/null +++ b/src/CurveCreator/CurveCreator_UtilsICurve.hxx @@ -0,0 +1,69 @@ +// Copyright (C) 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 +// + +#ifndef CURVECREATOR_UTILS_ICURVE_H +#define CURVECREATOR_UTILS_ICURVE_H + +#include "CurveCreator_Macro.hxx" + +#include "CurveCreator_ICurve.hxx" + +#include + +#include +#include + +class CurveCreator_UtilsICurve +{ +public: + + /*! + * Returns a point index in the model curve by the point coordinates in the viewer + * \param theX the X coordinate of the point + * \param theY the Y coordinate of the point + */ + CURVECREATOR_EXPORT static int findLocalPointIndex( const CurveCreator_ICurve* theCurve, + int theSectionId, float theX, float theY ); + + CURVECREATOR_EXPORT static void findSectionsToPoints( const CurveCreator_ICurve* theCurve, + const double theX, const double theY, + CurveCreator_ICurve::SectionToPointList& thePoints ); + CURVECREATOR_EXPORT static void convert( const CurveCreator_ICurve::SectionToPointList& thePoints, + QMap >& theConvPoints ); + + CURVECREATOR_EXPORT static void getPoint( const CurveCreator_ICurve* theCurve, const int theISection, + const int theIPoint, gp_Pnt& thePoint ); + + /*! + * Returns a unique section name + * \param theCurve a curve interface + */ + CURVECREATOR_EXPORT static std::string getUniqSectionName( + CurveCreator_ICurve* theCurve ); + + /** + * Returns whethe the container has the value + * \param theList a container of values + * \param theValue a value + */ + CURVECREATOR_EXPORT static bool contains( const CurveCreator_ICurve::SectionToPointList& theList, + const CurveCreator_ICurve::SectionToPoint& theValue ); +}; + +#endif // CURVECREATOR_UTILS_ICURVE_H diff --git a/src/CurveCreator/CurveCreator_Widget.cxx b/src/CurveCreator/CurveCreator_Widget.cxx index 180284fc1..9cd21e3b7 100644 --- a/src/CurveCreator/CurveCreator_Widget.cxx +++ b/src/CurveCreator/CurveCreator_Widget.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -19,25 +19,21 @@ #include "CurveCreator_Widget.h" #include "CurveCreator_TreeView.h" -#include "CurveCreator_Curve.hxx" -#include "CurveCreator_CurveEditor.hxx" +#include "CurveCreator_ICurve.hxx" #include "CurveCreator.hxx" -#include "CurveCreator_NewPointDlg.h" #include "CurveCreator_NewSectionDlg.h" - -#include +#include "CurveCreator_Utils.hxx" +#include "CurveCreator_UtilsICurve.hxx" +#include "CurveCreator_TableView.h" #include #include #include #include -#include #include #include - -#include -#include +#include #include #include @@ -50,204 +46,304 @@ #include #include #include +#include +#include + +//#define MEASURE_TIME + +#ifdef MEASURE_TIME + + #define START_MEASURE_TIME \ + QTime aTimer; \ + aTimer.start(); \ + + #define END_MEASURE_TIME( theMsg ) \ + double aTime = aTimer.elapsed() * 0.001; \ + FILE* aFile = fopen( "performance", "a" ); \ + fprintf( aFile, "%s = %.3lf sec\n", theMsg, aTime ); \ + fclose( aFile ); \ + +#else + + #define START_MEASURE_TIME + #define END_MEASURE_TIME( theMsg ) + +#endif + + + + + CurveCreator_Widget::CurveCreator_Widget(QWidget* parent, - CurveCreator_Curve *theCurve, - Qt::WindowFlags fl) : - QWidget(parent), myNewPointEditor(NULL), myNewSectionEditor(NULL), myEdit(NULL), myCurve(theCurve) -{ - if( myCurve ) - myEdit = new CurveCreator_CurveEditor( myCurve ); - - CurveCreator::Dimension aDim = CurveCreator::Dim2d; - if( myCurve ) - aDim = myCurve->getDimension(); - myNewPointEditor = new CurveCreator_NewPointDlg( aDim, this ); - myNewPointEditor->hide(); -// connect( myNewPointEditor, SIGNAL(addPoint()), this, SLOT(onAddNewPoint()) ); - connect( myNewPointEditor, SIGNAL(modifyPoint()), this, SLOT(onModifyPoint()) ); - connect( myNewPointEditor, SIGNAL(cancelPoint()), this, SLOT(onCancelPoint()) ); - - myNewSectionEditor = new CurveCreator_NewSectionDlg( this ); - myNewSectionEditor->hide(); - connect( myNewSectionEditor, SIGNAL(addSection()), this, SLOT(onAddNewSection()) ); - connect( myNewSectionEditor, SIGNAL(modifySection()), this, SLOT(onModifySection()) ); - connect( myNewSectionEditor, SIGNAL(cancelSection()), this, SLOT(onCancelSection()) ); - - QGroupBox* aSectionGroup = new QGroupBox(tr("Sections"),this); - - mySectionView = new CurveCreator_TreeView(myCurve, aSectionGroup); - connect( mySectionView, SIGNAL(selectionChanged()), this, SLOT( onSelectionChanged() ) ); - connect( mySectionView, SIGNAL(pointEntered(int,int)), this, SLOT(onEditPoint(int,int)) ); - connect( mySectionView, SIGNAL(sectionEntered(int)), this, SLOT(onEditSection(int)) ); - connect( mySectionView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onContextMenu(QPoint)) ); - QToolBar* aTB = new QToolBar(tr("TOOL_BAR_TLT"), aSectionGroup); + CurveCreator_ICurve *theCurve, + const int theActionFlags, + const QStringList& theCoordTitles, + Qt::WindowFlags fl, + int theLocalPointRowLimit ) +: QWidget(parent), myNewSectionEditor(NULL), myCurve(theCurve), mySection(0), + myDragStarted( false ), myDragInteractionStyle( SUIT_ViewModel::STANDARD ), + myOCCViewer( 0 ), myLocalPointRowLimit( theLocalPointRowLimit ), + myOld2DMode(OCCViewer_ViewWindow::No2dMode) +{ + bool isToEnableClosed = !( theActionFlags & DisableClosedSection ); + myNewSectionEditor = new CurveCreator_NewSectionDlg( this, isToEnableClosed ); + myNewSectionEditor->hide(); + connect( myNewSectionEditor, SIGNAL(addSection()), this, SLOT(onAddNewSection()) ); + connect( myNewSectionEditor, SIGNAL(modifySection()), this, SLOT(onModifySection()) ); + connect( myNewSectionEditor, SIGNAL(cancelSection()), this, SLOT(onCancelSection()) ); + + QGroupBox* aSectionGroup = new QGroupBox(tr("SECTION_GROUP_TITLE"),this); + + mySectionView = new CurveCreator_TreeView(myCurve, aSectionGroup); + mySectionView->setSelectionMode( QTreeView::ExtendedSelection ); + connect( mySectionView, SIGNAL(selectionChanged()), this, SLOT( onSelectionChanged() ) ); + connect( mySectionView, SIGNAL(sectionEntered(int)), this, SLOT(onEditSection(int)) ); + connect( mySectionView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onContextMenu(QPoint)) ); + + myLocalPointView = new CurveCreator_TableView( myCurve, this, theCoordTitles ); + connect( myLocalPointView, SIGNAL( cellChanged( int, int ) ), + this, SLOT( onCellChanged( int, int ) ) ); + + QToolBar* aTB = new QToolBar(tr("SECTION_GROUP_TITLE"), aSectionGroup); // QToolButton* anUndoBtn = new QToolButton(aTB); - SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); - QPixmap anUndoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_UNDO"))); - QPixmap aRedoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_REDO"))); - QPixmap aNewSectionPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_SECTION"))); - QPixmap aNewPointPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_POINT"))); - QPixmap anEditPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS"))); - QPixmap aDetectPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS"))); - QPixmap aPolylinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_POLYLINE"))); - QPixmap aSplinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_SPLINE"))); - QPixmap aRemovePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_DELETE"))); - QPixmap aJoinPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_JOIN"))); - QPixmap aStepUpPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_UP"))); - QPixmap aStepDownPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_DOWN"))); - -/* QPixmap anUndoPixmap = QPixmap(tr(":images/ICON_UNDO")); - QPixmap aRedoPixmap = QPixmap(tr(":images/ICON_REDO")); - QPixmap aNewSectionPixmap = QPixmap(tr(":images/ICON_NEW_SECTION")); - QPixmap aNewPointPixmap = QPixmap(tr(":images/ICON_NEW_POINT")); - QPixmap aPolylinePixmap = QPixmap(tr(":images/ICON_POLYLINE")); - QPixmap aSplinePixmap = QPixmap(tr(":images/ICON_SPLINE")); - QPixmap aRemovePixmap = QPixmap(tr(":images/ICON_REMOVE")); - QPixmap aJoinPixmap = QPixmap(tr(":images/ICON_JOIN")); - QPixmap aStepUpPixmap = QPixmap(tr(":images/ICON_STEP_UP")); - QPixmap aStepDownPixmap = QPixmap(tr(":images/ICON_STEP_DOWN"));*/ - - QAction* anAct = createAction( UNDO_ID, tr("UNDO"), anUndoPixmap, tr("UNDO_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_Z) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onUndo()) ); + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + QPixmap anUndoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_UNDO"))); + QPixmap aRedoPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_REDO"))); + QPixmap aNewSectionPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_SECTION"))); + QPixmap aNewPointPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_NEW_POINT"))); + QPixmap anEditPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS"))); + QPixmap aDetectPointsPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_EDIT_POINTS"))); + QPixmap aPolylinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_POLYLINE"))); + QPixmap aSplinePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_SPLINE"))); + QPixmap aRemovePixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_DELETE"))); + QPixmap aJoinPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_JOIN"))); + QPixmap aStepUpPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_UP"))); + QPixmap aStepDownPixmap(aResMgr->loadPixmap("GEOM", tr("ICON_CC_ARROW_DOWN"))); + + QAction* anAct = createAction( UNDO_ID, tr("UNDO"), anUndoPixmap, tr("UNDO_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_Z) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onUndo()) ); + aTB->addAction(anAct); + + anAct = createAction( REDO_ID, tr("REDO"), aRedoPixmap, tr("REDO_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_Y) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onRedo()) ); + aTB->addAction(anAct); + + aTB->addSeparator(); + + anAct = createAction( NEW_SECTION_ID, tr("NEW_SECTION"), aNewSectionPixmap, tr("NEW_SECTION_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_N) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onNewSection()) ); + if ( !(theActionFlags & DisableNewSection) ) { aTB->addAction(anAct); + aTB->addSeparator(); + } - anAct = createAction( REDO_ID, tr("REDO"), aRedoPixmap, tr("REDO_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_Y) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onRedo()) ); + anAct = createAction( ADDITION_MODE_ID, tr("ADDITION_MODE"), aNewPointPixmap, tr("ADDITION_MODE_TLT"), + QKeySequence() ); + anAct->setCheckable(true); + connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onAdditionMode(bool)) ); + connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); + aTB->addAction(anAct); + + anAct = createAction( MODIFICATION_MODE_ID, tr("MODIFICATION_MODE"), anEditPointsPixmap, tr("MODIFICATION_MODE_TLT"), + QKeySequence() ); + anAct->setCheckable(true); + connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onModificationMode(bool)) ); + connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); + aTB->addAction(anAct); + + anAct = createAction( DETECTION_MODE_ID, tr("DETECTION_MODE"), aDetectPointsPixmap, tr("DETECTION_MODE_TLT"), + QKeySequence() ); + anAct->setCheckable(true); + connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onDetectionMode(bool)) ); + connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); + if ( !(theActionFlags & DisableDetectionMode) ) { aTB->addAction(anAct); + } + + anAct = createAction( CLOSE_SECTIONS_ID, tr("CLOSE_SECTIONS"), QPixmap(), tr("CLOSE_SECTIONS_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_W) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onCloseSections()) ); + + anAct = createAction( UNCLOSE_SECTIONS_ID, tr("UNCLOSE_SECTIONS"), QPixmap(), + tr("UNCLOSE_SECTIONS_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_S) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onUncloseSections()) ); + + anAct = createAction( SET_SECTIONS_POLYLINE_ID, tr("SET_SECTIONS_POLYLINE"), + aPolylinePixmap, tr("SET_SECTIONS_POLYLINE_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_E) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onSetPolyline()) ); + + anAct = createAction( SET_SECTIONS_SPLINE_ID, tr("SET_SECTIONS_SPLINE"), aSplinePixmap, + tr("SET_SECTIONS_SPLINE_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_R) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onSetSpline()) ); + + anAct = createAction( REMOVE_ID, tr("REMOVE"), aRemovePixmap, tr("REMOVE_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_Delete ) ); + connect(anAct, SIGNAL(triggered()), this, SLOT(onRemove()) ); + aTB->addAction(anAct); + + aTB->addSeparator(); + + anAct = createAction( JOIN_ID, tr("JOIN"), aJoinPixmap, tr("JOIN_TLT"), + QKeySequence(Qt::ControlModifier|Qt::Key_Plus ) ); + connect( anAct, SIGNAL(triggered()), this, SLOT(onJoin()) ); + aTB->addAction(anAct); + + anAct = createAction( CLEAR_ALL_ID, tr("CLEAR_ALL"), QPixmap(), tr("CLEAR_ALL_TLT"), + QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Delete ) ); + connect( anAct, SIGNAL(triggered()), this, SLOT( onClearAll()) ); + + anAct = createAction( JOIN_ALL_ID, tr("JOIN_ALL"), QPixmap(), tr("JOIN_ALL_TLT"), + QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Plus ) ); + connect( anAct, SIGNAL(triggered()), this, SLOT(onJoinAll()) ); + + QVBoxLayout* aSectLayout = new QVBoxLayout(); + aSectLayout->setMargin( 5 ); + aSectLayout->setSpacing( 5 ); + aSectLayout->addWidget(aTB); + aSectLayout->addWidget(mySectionView); + aSectLayout->addWidget( myLocalPointView ); + aSectionGroup->setLayout(aSectLayout); + QVBoxLayout* aLay = new QVBoxLayout(); + aLay->setMargin( 0 ); + aLay->setSpacing( 5 ); +// aLay->addLayout(aNameLayout); + aLay->addWidget(aSectionGroup); + setLayout(aLay); - aTB->addSeparator(); + updateActionsStates(); + updateUndoRedo(); +} - anAct = createAction( NEW_SECTION_ID, tr("NEW_SECTION"), aNewSectionPixmap, tr("NEW_SECTION_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_N) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onNewSection()) ); - aTB->addAction(anAct); - aTB->addSeparator(); +/** + * Set an OCC viewer + */ +void CurveCreator_Widget::setOCCViewer( OCCViewer_Viewer* theViewer ) +{ + if ( myOCCViewer == theViewer ) + return; - anAct = createAction( INSERT_SECTION_BEFORE_ID, tr("INSERT_SECTION_BEFORE"), QPixmap(), - tr("INSERT_SECTION_BEFORE_TLT"), - QKeySequence(Qt::ControlModifier | Qt::Key_Insert ) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onInsertSectionBefore()) ); - - anAct = createAction( INSERT_SECTION_AFTER_ID, tr("INSERT_SECTION_AFTER"), QPixmap(), - tr("INSERT_SECTION_AFTER_TLT"), - QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Insert ) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onInsertSectionAfter()) ); - - anAct = createAction( ADDITION_MODE_ID, tr("ADDITION_MODE"), aNewPointPixmap, tr("ADDITION_MODE_TLT"), - QKeySequence() ); - anAct->setCheckable(true); - connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onAdditionMode(bool)) ); - connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); - aTB->addAction(anAct); + if ( myOCCViewer ) { + OCCViewer_ViewManager* aViewManager = dynamic_cast + ( myOCCViewer->getViewManager() ); + disconnect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMousePress( SUIT_ViewWindow*, QMouseEvent* ) ) ); + disconnect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ) ); + disconnect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) ); + disconnect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), + this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) ); + // restore normal mode in the viewer + SetViewer2DMode(false); + // all local contexts should be closed if the viewer is not more used + setLocalPointContext( false, true ); + } + + myOCCViewer = theViewer; + if ( myOCCViewer ) { + OCCViewer_ViewManager* aViewManager = dynamic_cast + ( myOCCViewer->getViewManager() ); + connect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMousePress( SUIT_ViewWindow*, QMouseEvent* ) ) ); + connect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ) ); + connect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ), + this, SLOT( onMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) ); + connect( aViewManager, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ), + this, SLOT( onLastViewClosed( SUIT_ViewManager* ) ) ); + SetViewer2DMode(true); + } +} + +/** + * Returns current OCC viewer + */ +OCCViewer_Viewer* CurveCreator_Widget::getOCCViewer() +{ + return myOCCViewer; +} + +/** + * Returns OCC viewer context + */ +Handle(AIS_InteractiveContext) CurveCreator_Widget::getAISContext() +{ + Handle(AIS_InteractiveContext) aContext; + OCCViewer_Viewer* aViewer = getOCCViewer(); + if ( aViewer ) + aContext = aViewer->getAISContext(); + + return aContext; +} + +/** + * Returns OCC viewer view port + */ +OCCViewer_ViewPort3d* CurveCreator_Widget::getViewPort() +{ + OCCViewer_ViewPort3d* aViewPort = 0; + OCCViewer_Viewer* aViewer = getOCCViewer(); + if ( aViewer ) + aViewPort = ((OCCViewer_ViewWindow*)aViewer->getViewManager()->getActiveView())->getViewPort(); - anAct = createAction( MODIFICATION_MODE_ID, tr("MODIFICATION_MODE"), anEditPointsPixmap, tr("MODIFICATION_MODE_TLT"), - QKeySequence() ); - anAct->setCheckable(true); - connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onModificationMode(bool)) ); - connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); - aTB->addAction(anAct); + return aViewPort; +} - anAct = createAction( DETECTION_MODE_ID, tr("DETECTION_MODE"), aDetectPointsPixmap, tr("DETECTION_MODE_TLT"), - QKeySequence() ); - anAct->setCheckable(true); - connect(anAct, SIGNAL(triggered(bool)), this, SLOT(onDetectPoints(bool)) ); - connect(anAct, SIGNAL(toggled(bool)), this, SLOT(onModeChanged(bool)) ); - aTB->addAction(anAct); +/** + * Set interaction style in the OCC viewer + * \param theStyle a new style + * \return the previous style + */ +int CurveCreator_Widget::changeInteractionStyle( int theStyle ) +{ + OCCViewer_Viewer* aViewer = getOCCViewer(); + if ( !aViewer ) + return -1; - anAct = createAction( INSERT_POINT_BEFORE_ID, tr("INSERT_POINT_BEFORE"), QPixmap(), - tr("INSERT_POINT_BEFORE_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_B) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onInsertPointBefore()) ); - - anAct = createAction( INSERT_POINT_AFTER_ID, tr("INSERT_POINT_AFTER"), QPixmap(), - tr("INSERT_POINT_AFTER_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_M) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onInsertPointAfter()) ); - - anAct = createAction( CLOSE_SECTIONS_ID, tr("CLOSE_SECTIONS"), QPixmap(), tr("CLOSE_SECTIONS_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_W) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onCloseSections()) ); - - anAct = createAction( UNCLOSE_SECTIONS_ID, tr("UNCLOSE_SECTIONS"), QPixmap(), - tr("UNCLOSE_SECTIONS_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_S) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onUncloseSections()) ); - - anAct = createAction( SET_SECTIONS_POLYLINE_ID, tr("SET_SECTIONS_POLYLINE"), - aPolylinePixmap, tr("SET_POLYLINE_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_E) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onSetPolyline()) ); - - anAct = createAction( SET_SECTIONS_SPLINE_ID, tr("SET_SECTIONS_SPLINE"), aSplinePixmap, - tr("SET_SPLINE_TLT"), QKeySequence(Qt::ControlModifier|Qt::Key_R) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onSetSpline()) ); - - anAct = createAction( REMOVE_ID, tr("REMOVE"), aRemovePixmap, tr("REMOVE_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_Delete ) ); - connect(anAct, SIGNAL(triggered()), this, SLOT(onRemove()) ); - aTB->addAction(anAct); - aTB->addSeparator(); + int aPrevStyle = aViewer->interactionStyle(); + aViewer->setInteractionStyle( theStyle ); - anAct = createAction( JOIN_ID, tr("JOIN"), aJoinPixmap, tr("JOIN_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_Plus ) ); - connect( anAct, SIGNAL(triggered()), this, SLOT(onJoin()) ); - aTB->addAction(anAct); - aTB->addSeparator(); + return aPrevStyle; +} - anAct = createAction( UP_ID, tr("STEP_UP"), aStepUpPixmap, tr("STEP_UP_TLT"), - QKeySequence(Qt::ControlModifier|Qt::Key_Up ) ); - connect( anAct, SIGNAL(triggered()), this, SLOT(onMoveUp()) ); - - anAct = createAction( DOWN_ID, tr("STEP_DOWN"), aStepDownPixmap, tr("STEP_DOWN"), - QKeySequence(Qt::ControlModifier|Qt::Key_Down ) ); - connect( anAct, SIGNAL(triggered()), this, SLOT(onMoveDown()) ); - - anAct = createAction( CLEAR_ALL_ID, tr("CLEAR_ALL"), QPixmap(), tr("CLEAR_ALL_TLT"), - QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Delete ) ); - connect( anAct, SIGNAL(triggered()), this, SLOT( onClearAll()) ); - - anAct = createAction( JOIN_ALL_ID, tr("JOIN_ALL"), QPixmap(), tr("JOIN_ALL_TLT"), - QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Plus ) ); - connect( anAct, SIGNAL(triggered()), this, SLOT(onJoinAll()) ); - - QVBoxLayout* aSectLayout = new QVBoxLayout(); - aSectLayout->setMargin( 5 ); - aSectLayout->setSpacing( 5 ); - aSectLayout->addWidget(aTB); - aSectLayout->addWidget(mySectionView); - aSectionGroup->setLayout(aSectLayout); - QVBoxLayout* aLay = new QVBoxLayout(); - aLay->setMargin( 0 ); - aLay->setSpacing( 5 ); -// aLay->addLayout(aNameLayout); - aLay->addWidget(aSectionGroup); - setLayout(aLay); - onSelectionChanged(); +//======================================================================= +// function: reset +// purpose: reset the widget viewer, close local context, clear selection +//======================================================================= +void CurveCreator_Widget::reset() +{ } -void CurveCreator_Widget::setCurve( CurveCreator_Curve* theCurve ) +void CurveCreator_Widget::setCurve( CurveCreator_ICurve* theCurve ) { - if( myEdit != NULL ){ - delete myEdit; - myEdit = NULL; - } myCurve = theCurve; - mySectionView->setCurve(myCurve); - if( myCurve != NULL ){ - myEdit = new CurveCreator_CurveEditor(myCurve); - } - onSelectionChanged(); + mySectionView->setCurve( myCurve ); + myLocalPointView->setCurve( myCurve ); + updateActionsStates(); updateUndoRedo(); } void CurveCreator_Widget::onSelectionChanged() +{ + updateActionsStates(); + updateUndoRedo(); + emit selectionChanged(); +} + +void CurveCreator_Widget::updateActionsStates() { QList anEnabledAct; if( myCurve ){ - anEnabledAct << NEW_SECTION_ID; + anEnabledAct << NEW_SECTION_ID << MODIFICATION_MODE_ID; + if ( removeEnabled() ) + anEnabledAct << REMOVE_ID; QList aSelSections = mySectionView->getSelectedSections(); - QList< QPair< int, int > > aSelPoints = mySectionView->getSelectedPoints(); CurveCreator_TreeView::SelectionType aSelType = mySectionView->getSelectionType(); switch( aSelType ){ case CurveCreator_TreeView::ST_NOSEL:{ @@ -258,29 +354,47 @@ void CurveCreator_Widget::onSelectionChanged() anEnabledAct << UP_ID; }*/ if( aSelSections.size() == 1 ){ - anEnabledAct << ADDITION_MODE_ID << MODIFICATION_MODE_ID << DETECTION_MODE_ID; + anEnabledAct << ADDITION_MODE_ID << DETECTION_MODE_ID; } - if (myActionMap[ADDITION_MODE_ID]->isChecked()) { - mySection = -1; - myPointNum = -1; - QList aSelSection = mySectionView->getSelectedSections(); - if( aSelSection.size() > 0 ){ - mySection = aSelSection[0]; - myPointNum = myCurve->getNbPoints(mySection); + switch ( getActionMode() ) { + case AdditionMode: { + mySection = -1; + myPointNum = -1; + QList aSelSection = mySectionView->getSelectedSections(); + if( aSelSection.size() > 0 ){ + mySection = aSelSection[0]; + myPointNum = myCurve->getNbPoints(mySection); + } } - } else if (myActionMap[MODIFICATION_MODE_ID]->isChecked()) { - anEnabledAct << REMOVE_ID; - anEnabledAct << CLOSE_SECTIONS_ID << UNCLOSE_SECTIONS_ID << SET_SECTIONS_POLYLINE_ID << SET_SECTIONS_SPLINE_ID; - int aSectCnt = myCurve->getNbSections(); - if( aSectCnt > 0 ) - anEnabledAct << CLEAR_ALL_ID; - if( aSectCnt > 1 ) - anEnabledAct << JOIN_ALL_ID; - if( aSelSections.size() > 1 ){ - anEnabledAct << JOIN_ID; + break; + case ModificationMode: { + if ( myNewSectionEditor->isEnableClosed() ) + anEnabledAct << CLOSE_SECTIONS_ID << UNCLOSE_SECTIONS_ID; + anEnabledAct << SET_SECTIONS_POLYLINE_ID << SET_SECTIONS_SPLINE_ID; + int aSectCnt = myCurve->getNbSections(); + if( aSectCnt > 0 ) + anEnabledAct << CLEAR_ALL_ID; + if( aSectCnt > 1 ) + anEnabledAct << JOIN_ALL_ID; + if( aSelSections.size() > 1 ){ + anEnabledAct << JOIN_ID; + } + } + break; + case DetectionMode: { } - } else if (myActionMap[DETECTION_MODE_ID]->isChecked()) { - } else { //no active mode + break; + case NoneMode: + { + int aSectCnt = myCurve->getNbSections(); + if( aSectCnt > 1 ) + anEnabledAct << JOIN_ALL_ID; + if( aSelSections.size() > 1 ) + anEnabledAct << JOIN_ID; + } + break; + default: + break; } /*if( aSelSections[ aSelSections.size() - 1 ] < ( myCurve->getNbSections() - 1 ) ){ anEnabledAct << DOWN_ID; @@ -326,32 +440,16 @@ void CurveCreator_Widget::onSelectionChanged() } } } - emit selectionChanged(); } void CurveCreator_Widget::onAdditionMode(bool checked) { - if( !myEdit ) + if (!checked) return; - SUIT_ViewWindow* aViewWindow = 0; - SUIT_Study* activeStudy = SUIT_Session::session()->activeApplication()->activeStudy(); - if ( activeStudy ) - aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); - if ( aViewWindow == 0 ) + Handle(AIS_InteractiveContext) aContext = getAISContext(); + if( !myCurve || aContext.IsNull() ) return; - SUIT_ViewManager* aViewManager = aViewWindow->getViewManager(); - - if ( aViewManager->getType() == OCCViewer_Viewer::Type() ) { - if (checked) { - connect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ), - this, SLOT( onGetPointByClick( SUIT_ViewWindow*, QMouseEvent* ) ) ); - } else { - disconnect( aViewManager, SIGNAL( mousePress( SUIT_ViewWindow*, QMouseEvent* ) ), - this, SLOT( onGetPointByClick( SUIT_ViewWindow*, QMouseEvent* ) ) ); - return; - } - } mySection= -1; myPointNum = -1; @@ -359,78 +457,40 @@ void CurveCreator_Widget::onAdditionMode(bool checked) if( aSelSection.size() > 0 ){ mySection = aSelSection[0]; } - else{ - QList< QPair > aSelPoints = mySectionView->getSelectedPoints(); - if( aSelPoints.size() > 0 ){ - mySection = aSelPoints[0].first; - myPointNum = aSelPoints[0].second + 1; - } - } -/* - QString aSectName; - if( mySection < 0 ){ - mySection = myCurve->getNbSections() - 1; - } - aSectName = QString::fromStdString( myCurve->getSectionName(mySection)); - if( myPointNum < 0 ){ - myPointNum = myCurve->getNbPoints(mySection); - } - myNewPointEditor->clear(); - myNewPointEditor->setEditMode(false); - myNewPointEditor->setSectionName(aSectName); - myNewPointEditor->setDimension(myCurve->getDimension()); -*/ // emit subOperationStarted( myNewPointEditor ); } void CurveCreator_Widget::onModificationMode(bool checked) { - SUIT_ViewWindow* aViewWindow = 0; - SUIT_Study* activeStudy = SUIT_Session::session()->activeApplication()->activeStudy(); - if ( activeStudy ) - aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); - if ( aViewWindow == 0 ) - return; - SUIT_ViewManager* aViewManager = aViewWindow->getViewManager(); - if ( aViewManager->getType() == OCCViewer_Viewer::Type() ) { - if (checked) { -// connect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ), -// this, SLOT( onPointSelect( SUIT_ViewWindow*, QMouseEvent* ) ) ); - connect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ), - this, SLOT( onPointDrag( SUIT_ViewWindow*, QMouseEvent* ) ) ); - } - else { -// disconnect( aViewManager, SIGNAL( mouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ), -// this, SLOT( onPointSelect( SUIT_ViewWindow*, QMouseEvent* ) ) ); - disconnect( aViewManager, SIGNAL( mouseMove( SUIT_ViewWindow*, QMouseEvent* ) ), - this, SLOT( onPointDrag( SUIT_ViewWindow*, QMouseEvent* ) ) ); - return; - } - } + myLocalPointView->setVisible( checked ); } -void CurveCreator_Widget::onDetectPoints(bool checked) +void CurveCreator_Widget::onDetectionMode(bool checked) { } void CurveCreator_Widget::onModeChanged(bool checked) { + ActionMode aMode = NoneMode; if (checked) { QAction* anAction = (QAction*)sender(); switch(myActionMap.key(anAction)) { case ADDITION_MODE_ID: + aMode = AdditionMode; if (myActionMap[MODIFICATION_MODE_ID]->isChecked()) myActionMap[MODIFICATION_MODE_ID]->trigger(); else if (myActionMap[DETECTION_MODE_ID]->isChecked()) myActionMap[DETECTION_MODE_ID]->trigger(); break; case MODIFICATION_MODE_ID: + aMode = ModificationMode; if (myActionMap[ADDITION_MODE_ID]->isChecked()) myActionMap[ADDITION_MODE_ID]->trigger(); else if (myActionMap[DETECTION_MODE_ID]->isChecked()) myActionMap[DETECTION_MODE_ID]->trigger(); break; case DETECTION_MODE_ID: + aMode = DetectionMode; if (myActionMap[ADDITION_MODE_ID]->isChecked()) myActionMap[ADDITION_MODE_ID]->trigger(); else if (myActionMap[MODIFICATION_MODE_ID]->isChecked()) @@ -438,54 +498,39 @@ void CurveCreator_Widget::onModeChanged(bool checked) break; } } - onSelectionChanged(); -} - -void CurveCreator_Widget::onAddNewPoint(const CurveCreator::Coordinates& theCoords) -{ - if( !myEdit ) - return; -// CurveCreator::Coordinates aCoords = myNewPointEditor->getCoordinates(); - myEdit->insertPoints(theCoords, mySection, myPointNum ); - mySectionView->pointsAdded( mySection, myPointNum ); -// myNewPointEditor->clear(); - myPointNum++; - onSelectionChanged(); + updateActionsStates(); updateUndoRedo(); + setLocalPointContext( aMode == ModificationMode, true ); } void CurveCreator_Widget::onNewSection() { - if( !myEdit ) + if( !myCurve ) return; + + stopActionMode(); myNewSectionEditor->clear(); myNewSectionEditor->setEditMode(false); - QString aSectName = QString( myCurve->getUnicSectionName().c_str() ); + QString aSectName = QString( CurveCreator_UtilsICurve::getUniqSectionName( myCurve ).c_str() ); myNewSectionEditor->setSectionParameters(aSectName, true, CurveCreator::Polyline ); - emit subOperationStarted( myNewSectionEditor ); + emit subOperationStarted( myNewSectionEditor, false ); } void CurveCreator_Widget::onAddNewSection() { - if( !myEdit ) + if( !myCurve ) return; - CurveCreator::Coordinates aCoords; - myEdit->addSection( myNewSectionEditor->getName().toStdString(), myNewSectionEditor->getSectionType(), - myNewSectionEditor->isClosed(), aCoords ); - mySectionView->sectionAdded( mySection ); - QString aNewName = QString(myCurve->getUnicSectionName().c_str()); + myCurve->addSection( myNewSectionEditor->getName().toStdString(), + myNewSectionEditor->getSectionType(), + myNewSectionEditor->isClosed() ); + mySectionView->sectionAdded( -1 ); // add a new section to the end of list + QString aNewName = QString( CurveCreator_UtilsICurve::getUniqSectionName( myCurve ).c_str() ); myNewSectionEditor->setSectionName(aNewName); - mySection++; - onSelectionChanged(); + updateActionsStates(); updateUndoRedo(); onCancelSection(); } -void CurveCreator_Widget::onCancelPoint() -{ - emit subOperationFinished( myNewPointEditor ); -} - void CurveCreator_Widget::onCancelSection() { emit subOperationFinished( myNewSectionEditor ); @@ -504,212 +549,161 @@ QAction* CurveCreator_Widget::createAction( ActionId theId, const QString& theNa return anAct; } -QAction* CurveCreator_Widget::getAction(ActionId theId) +QAction* CurveCreator_Widget::getAction( ActionId theId ) { if( myActionMap.contains(theId) ) return myActionMap[theId]; return NULL; } +QAction* CurveCreator_Widget::getAction( ActionMode theMode ) +{ + ActionId anActionId = NONE_ID; + switch ( theMode ) { + case AdditionMode: + anActionId = ADDITION_MODE_ID; + break; + case ModificationMode: + anActionId = MODIFICATION_MODE_ID; + break; + case DetectionMode: + anActionId = DETECTION_MODE_ID; + break; + default: + break; + } + QAction* anAction = 0; + if ( anActionId != NONE_ID && myActionMap.contains( anActionId ) ) + anAction = myActionMap[anActionId]; + return anAction; +} + void CurveCreator_Widget::onEditSection( int theSection ) { - if( !myEdit ) + if( !myCurve ) return; + + stopActionMode(); mySection = theSection; QString aSectName = QString::fromStdString( myCurve->getSectionName(theSection)); bool isClosed = myCurve->isClosed(theSection); - CurveCreator::Type aType = myCurve->getType(theSection); + CurveCreator::SectionType aType = myCurve->getSectionType(theSection); myNewSectionEditor->setEditMode(true); myNewSectionEditor->setSectionParameters( aSectName, isClosed, aType ); - emit subOperationStarted( myNewSectionEditor ); + emit subOperationStarted( myNewSectionEditor, true ); } void CurveCreator_Widget::onModifySection() { - if( !myEdit ) + if( !myCurve ) return; QString aName = myNewSectionEditor->getName(); bool isClosed = myNewSectionEditor->isClosed(); - CurveCreator::Type aSectType = myNewSectionEditor->getSectionType(); - myEdit->startOperation(); - myEdit->setClosed( isClosed, mySection ); - myEdit->setName( aName.toStdString(), mySection ); - myEdit->setType( aSectType, mySection ); - myEdit->finishOperation(); + CurveCreator::SectionType aSectType = myNewSectionEditor->getSectionType(); + if( myCurve->getSectionName(mySection) != aName.toStdString() ) + myCurve->setSectionName( mySection , aName.toStdString() ); + + bool isGeomModified = false; + + if( myCurve->getSectionType(mySection) != aSectType ) { + myCurve->setSectionType( mySection, aSectType ); + isGeomModified = true; + } + + if( myCurve->isClosed(mySection) != isClosed ) { + myCurve->setClosed( mySection, isClosed ); + isGeomModified = true; + } mySectionView->sectionChanged(mySection); updateUndoRedo(); onCancelSection(); -} -void CurveCreator_Widget::onEditPoint( int theSection, int thePoint ) -{ - if( !myNewPointEditor || !myEdit ) - return; - mySection = theSection; - myPointNum = thePoint; - QString aSectName = QString::fromStdString( myCurve->getSectionName(theSection)); - myNewPointEditor->setEditMode(true); - myNewPointEditor->setSectionName(aSectName); - myNewPointEditor->setDimension( myCurve->getDimension() ); - CurveCreator::Coordinates aCoords = myCurve->getCoordinates(theSection,thePoint); - myNewPointEditor->setCoordinates(aCoords); - emit subOperationStarted( myNewPointEditor ); -} - -void CurveCreator_Widget::onModifyPoint() -{ - if( !myEdit ) - return; - CurveCreator::Coordinates aCoords = myNewPointEditor->getCoordinates(); - myEdit->setCoordinates( aCoords, mySection, myPointNum ); - mySectionView->pointDataChanged( mySection, myPointNum ); - updateUndoRedo(); - onCancelPoint(); + emit curveModified(); } void CurveCreator_Widget::onJoin() { - if( !myEdit ) + if( !myCurve ) return; QList aSections = mySectionView->getSelectedSections(); if( aSections.size() == 0 ){ return; } - int aMainSect = aSections[0]; - int aMainSectSize = myCurve->getNbPoints(aMainSect); - myEdit->startOperation(); - for( int i = 1 ; i < aSections.size() ; i++ ){ - int aSectNum = aSections[i] - (i-1); - myEdit->join( aMainSect, aSectNum ); - mySectionView->sectionsRemoved( aSectNum ); + stopActionMode(); + + std::list aSectionsToJoin; + for( int i = 0; i < aSections.size() ; i++ ){ + aSectionsToJoin.push_back( aSections[i] ); + } + //int aMainSect = aSectionsToJoin.front(); + //int aMainSectSize = myCurve->getNbPoints(aMainSect); + if ( myCurve->join( aSectionsToJoin ) ) + { + std::list::const_iterator anIt = aSectionsToJoin.begin(), + aLast = aSectionsToJoin.end(); + // the first section should be skipped. It is not removed, but is modified + anIt++; + for ( ; anIt != aLast; anIt++ ) + mySectionView->sectionsRemoved( *anIt ); } - myEdit->finishOperation(); + + /* The update for the points of the main section int aNewSectSize = myCurve->getNbPoints(aMainSect); if( aNewSectSize != aMainSectSize ) - mySectionView->pointsAdded( aMainSect, aMainSectSize, aNewSectSize-aMainSectSize ); + mySectionView->pointsAdded( aMainSect, aMainSectSize, aNewSectSize-aMainSectSize );*/ updateUndoRedo(); -} -void CurveCreator_Widget::onRemove() -{ - if( !myEdit ) - return; - QList< QPair > aSelPoints = mySectionView->getSelectedPoints(); - int aCurrSect=-1; - int aRemoveCnt = 0; - myEdit->startOperation(); - for( int i = 0 ; i < aSelPoints.size() ; i++ ){ - if( aCurrSect != aSelPoints[i].first ){ - aRemoveCnt = 0; - aCurrSect = aSelPoints[i].first; - } - int aPntIndx = aSelPoints[i].second - aRemoveCnt; - myEdit->removePoints(aCurrSect,aPntIndx, 1); - mySectionView->pointsRemoved( aCurrSect, aPntIndx ); - aRemoveCnt++; - } - QList aSections = mySectionView->getSelectedSections(); - for( int i = 0 ; i < aSections.size() ; i++ ){ - int aSectNum = aSections[i] - (i); - myEdit->removeSection( aSectNum ); - mySectionView->sectionsRemoved( aSectNum ); - } - myEdit->finishOperation(); - mySectionView->clearSelection(); - updateUndoRedo(); + emit curveModified(); } -void CurveCreator_Widget::onMoveUp() +void CurveCreator_Widget::onRemove() { - if( !myEdit ) + if( !myCurve ) return; - if( mySectionView->getSelectionType() == CurveCreator_TreeView::ST_SECTIONS ){ - //Move sections - QList aSections = mySectionView->getSelectedSections(); - for( int i = 0 ; i < aSections.size() ; i++ ){ - int anIndx = aSections[i]; - myEdit->moveSection( anIndx, anIndx-1); - mySectionView->sectionsSwapped( anIndx, -1 ); - } - } - else{ - //Move points - QList< QPair > aPoints = mySectionView->getSelectedPoints(); - for( int i = 0 ; i < aPoints.size() ; i++ ){ - int aSection = aPoints[i].first; - int aPoint = aPoints[i].second; - myEdit->movePoint(aSection, aPoint, aPoint-2); - mySectionView->pointsSwapped( aSection, aPoint, -1 ); - } - } - updateUndoRedo(); -} -void CurveCreator_Widget::onMoveDown() -{ - if( !myEdit ) - return; - if( mySectionView->getSelectionType() == CurveCreator_TreeView::ST_SECTIONS ){ - //Move sections - QList aSections = mySectionView->getSelectedSections(); - for( int i = aSections.size()-1 ; i >=0 ; i-- ){ - int anIndx = aSections[i]; - myEdit->moveSection( anIndx, anIndx+1); - mySectionView->sectionsSwapped( anIndx, 1 ); - } - } - else{ - //Move points - QList< QPair > aPoints = mySectionView->getSelectedPoints(); - for( int i = aPoints.size() - 1; i >= 0 ; i-- ){ - int aSection = aPoints[i].first; - int aPoint = aPoints[i].second; - myEdit->movePoint(aSection, aPoint, aPoint+1); - mySectionView->pointsSwapped( aSection, aPoint, 1 ); - } + switch( getActionMode() ) { + case NoneMode: + removeSection(); + break; + case ModificationMode: + removePoint(); + break; + default: + break; } - updateUndoRedo(); } void CurveCreator_Widget::onClearAll() { - if( !myEdit ) + if( !myCurve ) return; - myEdit->clear(); + stopActionMode(); + myCurve->clear(); mySectionView->reset(); - onSelectionChanged(); + updateActionsStates(); updateUndoRedo(); + + emit curveModified(); } void CurveCreator_Widget::onJoinAll() { - if( !myEdit ) + if( !myCurve ) return; - myEdit->join(); - mySectionView->reset(); - onSelectionChanged(); - updateUndoRedo(); -} + stopActionMode(); -void CurveCreator_Widget::onInsertSectionBefore() -{ - -} - -void CurveCreator_Widget::onInsertSectionAfter() -{ - -} - -void CurveCreator_Widget::onInsertPointBefore() -{ - -} + std::list aSectionsToJoin; + for( int i = 0, aNb = myCurve->getNbSections(); i < aNb ; i++ ){ + aSectionsToJoin.push_back( i ); + } + bool aRes = myCurve->join( aSectionsToJoin ); -void CurveCreator_Widget::onInsertPointAfter() -{ + mySectionView->reset(); + updateActionsStates(); + updateUndoRedo(); + emit curveModified(); } void CurveCreator_Widget::onUndoSettings() @@ -719,104 +713,119 @@ void CurveCreator_Widget::onUndoSettings() void CurveCreator_Widget::onSetSpline() { - if( !myEdit ) + if( !myCurve ) return; + stopActionMode(); QList aSelSections = mySectionView->getSelectedSections(); - myEdit->startOperation(); for( int i = 0 ; i < aSelSections.size() ; i++ ){ - myEdit->setType(CurveCreator::BSpline, aSelSections[i]); + myCurve->setSectionType(aSelSections[i], CurveCreator::Spline ); mySectionView->sectionChanged(aSelSections[i]); } - myEdit->finishOperation(); updateUndoRedo(); + + emit curveModified(); } void CurveCreator_Widget::onSetPolyline() { - if( !myEdit ) + if( !myCurve ) return; - myEdit->startOperation(); + stopActionMode(); QList aSelSections = mySectionView->getSelectedSections(); for( int i = 0 ; i < aSelSections.size() ; i++ ){ - myEdit->setType(CurveCreator::Polyline, aSelSections[i]); - mySectionView->sectionChanged(aSelSections[i]); + myCurve->setSectionType( aSelSections[i], CurveCreator::Polyline ); + mySectionView->sectionChanged( aSelSections[i] ); } - myEdit->finishOperation(); updateUndoRedo(); + + emit curveModified(); } void CurveCreator_Widget::onCloseSections() { - if( !myEdit ) + if( !myCurve ) return; - myEdit->startOperation(); + stopActionMode(); QList aSelSections = mySectionView->getSelectedSections(); for( int i = 0 ; i < aSelSections.size() ; i++ ){ - myEdit->setClosed(true, aSelSections[i]); + myCurve->setClosed(aSelSections[i], true); mySectionView->sectionChanged(aSelSections[i]); } - myEdit->finishOperation(); updateUndoRedo(); + + emit curveModified(); } void CurveCreator_Widget::onUncloseSections() { - if( !myEdit ) + if( !myCurve ) return; - myEdit->startOperation(); + stopActionMode(); QList aSelSections = mySectionView->getSelectedSections(); for( int i = 0 ; i < aSelSections.size() ; i++ ){ - myEdit->setClosed(false, aSelSections[i]); + myCurve->setClosed(aSelSections[i], false); mySectionView->sectionChanged(aSelSections[i]); } - myEdit->finishOperation(); updateUndoRedo(); + + emit curveModified(); } void CurveCreator_Widget::onUndo() { - if( !myEdit ) - return; - myEdit->undo(); - mySectionView->reset(); - updateUndoRedo(); + if( !myCurve ) + return; + + CurveCreator_ICurve::SectionToPointList aPoints; + startCurveModification( aPoints, false ); + myCurve->undo(); + finishCurveModification(); + mySectionView->reset(); + + emit curveModified(); } void CurveCreator_Widget::onRedo() { - if( !myEdit ) - return; - myEdit->redo(); - mySectionView->reset(); - updateUndoRedo(); + if( !myCurve ) + return; + CurveCreator_ICurve::SectionToPointList aPoints; + startCurveModification( aPoints, false ); + myCurve->redo(); + finishCurveModification(); + mySectionView->reset(); + + emit curveModified(); } void CurveCreator_Widget::updateUndoRedo() { - QAction* anAct = myActionMap[UNDO_ID]; - if( anAct != 0 ){ - if( myEdit->getNbUndo() != 0 ){ - anAct->setEnabled(true); - } - else{ - anAct->setDisabled(true); - } + if( !myCurve ) + return; + QAction* anAct = myActionMap[UNDO_ID]; + if( anAct != 0 ){ + if( myCurve->getNbUndo() != 0 ){ + anAct->setEnabled(true); } - anAct = myActionMap[REDO_ID]; - if( anAct != 0 ){ - if( myEdit->getNbRedo() != 0 ){ - anAct->setEnabled(true); - } - else{ - anAct->setDisabled(true); - } + else{ + anAct->setDisabled(true); + } + } + anAct = myActionMap[REDO_ID]; + if( anAct != 0 ){ + if( myCurve->getNbRedo() != 0 ){ + anAct->setEnabled(true); } + else{ + anAct->setDisabled(true); + } + } } void CurveCreator_Widget::onContextMenu( QPoint thePoint ) { QList aContextActions; - aContextActions << CLEAR_ALL_ID << JOIN_ALL_ID << SEPARATOR_ID << + aContextActions << CLEAR_ALL_ID << JOIN_ID << JOIN_ALL_ID << SEPARATOR_ID << CLOSE_SECTIONS_ID << UNCLOSE_SECTIONS_ID << SET_SECTIONS_POLYLINE_ID << SET_SECTIONS_SPLINE_ID; QPoint aGlPoint = mySectionView->mapToGlobal(thePoint); @@ -857,35 +866,111 @@ QList CurveCreator_Widget::getSelectedSections() return mySectionView->getSelectedSections(); } -QList< QPair< int, int > > CurveCreator_Widget::getSelectedPoints() +void CurveCreator_Widget::setSelectedSections( const QList& theSections ) { - return mySectionView->getSelectedPoints(); + mySectionView->setSelectedSections( theSections ); + updateActionsStates(); + updateUndoRedo(); } -bool CurveCreator_Widget::isInstantSketchingEnabled() const +/** + * According to the widget state, performs the remove action + */ +void CurveCreator_Widget::removeSelected() { - if( myNewPointEditor ) - return myNewPointEditor->isInstantSketchingEnabled(); - return false; + onRemove(); } -void CurveCreator_Widget::setInstantSketchingEnabled( const bool theState ) +/** + * Checks whether there are some selection to be removed + */ +bool CurveCreator_Widget::removeEnabled() { - if( myNewPointEditor ) - myNewPointEditor->setInstantSketchingEnabled( theState ); + bool isEnabled = getActionMode() == ModificationMode; + if ( !isEnabled ) { + QList aSelSections = mySectionView->getSelectedSections(); + CurveCreator_TreeView::SelectionType aSelType = mySectionView->getSelectionType(); + isEnabled = aSelType == CurveCreator_TreeView::ST_SECTIONS && + aSelSections.size() == 1; + } + return isEnabled; +} + +void CurveCreator_Widget::setActionMode( const ActionMode& theMode ) +{ + ActionMode aPrevMode = getActionMode(); + QAction* aPrevAction = getAction( aPrevMode ); + QAction* anAction = getAction( theMode ); + switch ( theMode ) { + case NoneMode: + case AdditionMode: { + if ( aPrevAction ) { + if ( aPrevAction->isChecked() ) { + aPrevAction->setChecked( false ); + } + } + if ( aPrevMode == ModificationMode ) + onModificationMode( false ); + if ( aPrevMode == AdditionMode ) + onAdditionMode( false ); + + if ( theMode == AdditionMode ) + { + anAction->setChecked( true ); + onModeChanged( true ); + } + } + break; + break; + case ModificationMode: + { + //TODO + } + break; + case DetectionMode: + break; + } +} + +CurveCreator_Widget::ActionMode CurveCreator_Widget::getActionMode() const +{ + ActionMode aMode = NoneMode; + + if ( myActionMap[ADDITION_MODE_ID]->isChecked() ) + aMode = AdditionMode; + else if ( myActionMap[MODIFICATION_MODE_ID]->isChecked() ) + aMode = ModificationMode; + else if ( myActionMap[DETECTION_MODE_ID]->isChecked() ) + aMode = DetectionMode; + + return aMode; +} + +void CurveCreator_Widget::SetViewer2DMode(const bool To2D) +{ + if (myOCCViewer) { + if (To2D) { + myOld2DMode = OCCViewer_Utilities::setViewer2DMode + (myOCCViewer, OCCViewer_ViewWindow::XYPlane); + } else { + OCCViewer_Utilities::setViewer2DMode(myOCCViewer, myOld2DMode); + } + } } //================================================================================= -// function : GeometryGUI::onGetPointByClick() +// function : GeometryGUI::addCoordsByClick() // purpose : Manage mouse press events in Additon mode //================================================================================= -void CurveCreator_Widget::onGetPointByClick( SUIT_ViewWindow* theViewWindow, QMouseEvent* pe ) +void CurveCreator_Widget::addCoordsByClick( QMouseEvent* pe ) { - if ( myNewPointEditor && theViewWindow->getViewManager()->getType() == OCCViewer_Viewer::Type() && - pe->modifiers() != Qt::ControlModifier ) { - OCCViewer_Viewer* anOCCViewer = - ( (OCCViewer_ViewManager*)( theViewWindow->getViewManager() ) )->getOCCViewer(); - Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext(); + if (pe->button() != Qt::LeftButton) + return; + + if ( pe->modifiers() != Qt::ControlModifier ) { + Handle(AIS_InteractiveContext) ic = getAISContext(); + if ( ic.IsNull() ) + return; gp_Pnt aPnt; @@ -895,18 +980,9 @@ void CurveCreator_Widget::onGetPointByClick( SUIT_ViewWindow* theViewWindow, QMo else ic->Select(); // New selection - /*TopoDS_Shape aShape; - - ic->InitSelected(); - if ( ic->MoreSelected() ) - aShape = ic->SelectedShape(); - - if ( !aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX ) - aPnt = BRep_Tool::Pnt( TopoDS::Vertex( ic->SelectedShape() ) ); - else*/ { - OCCViewer_ViewPort3d* vp = ((OCCViewer_ViewWindow*)theViewWindow)->getViewPort(); - aPnt = GEOMUtils::ConvertClickToPoint( pe->x(), pe->y(), vp->getView() ); + OCCViewer_ViewPort3d* vp = getViewPort(); + aPnt = CurveCreator_Utils::ConvertClickToPoint( pe->x(), pe->y(), vp->getView() ); } // set the coordinates into dialog CurveCreator::Coordinates aCoords; @@ -915,28 +991,522 @@ void CurveCreator_Widget::onGetPointByClick( SUIT_ViewWindow* theViewWindow, QMo if ( myCurve->getDimension() == 3 ) { aCoords.push_back( aPnt.Z() ); } - onAddNewPoint(aCoords); -// myNewPointEditor->setCoordinates( aCoords ); + addNewPoint(aCoords); } } -//================================================================================= -// function : GeometryGUI::onPointDrag() -// purpose : Manage mouse move events in Modification mode -//================================================================================= -void CurveCreator_Widget::onPointDrag( SUIT_ViewWindow* theViewWindow, QMouseEvent* pe ) +/** + * Manage mouse press events + * \param theWindow an owner of the signal + * \param theEvent a mouse event + */ +void CurveCreator_Widget::onMousePress( SUIT_ViewWindow*, QMouseEvent* theEvent ) { - if ( !(pe->buttons() & Qt::LeftButton) ) + if ( theEvent->button() != Qt::LeftButton ) return; - if ( (pe->pos() - myDragStartPosition).manhattanLength() < QApplication::startDragDistance() ) + + myPressedX = theEvent->x(); + myPressedY = theEvent->y(); + + switch( getActionMode() ) { + case ModificationMode: { + //store initial cursor position for Drag&Drop + setDragStarted( true, theEvent->pos() ); + break; + } + case AdditionMode: { + addCoordsByClick( theEvent ); + break; + } + default: + break; + } +} + +/** + * Manage mouse release events in Modification mode + * \param theWindow an owner of the signal + * \param theEvent a mouse event + */ +void CurveCreator_Widget::onMouseRelease( SUIT_ViewWindow*, QMouseEvent* theEvent ) +{ + if ( getActionMode() != ModificationMode ) return; -/* - QDrag *drag = new QDrag(this); - QMimeData *mimeData = new QMimeData; - - mimeData->setData(mimeType, data); - drag->setMimeData(mimeData); - - Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction); - */ + + if ( myDragStarted ) { + bool isDragged = myDragged; + CurveCreator_ICurve::SectionToPointList aDraggedPoints; + QMap > anInitialDragPointsCoords; + if ( myDragged ) { + aDraggedPoints = myDragPoints; + anInitialDragPointsCoords = myInitialDragPointsCoords; + } + + setDragStarted( false ); + + if ( aDraggedPoints.size() > 0 ) { + // Collect old coordinates of the dragged points + CurveCreator_ICurve::SectionToPointCoordsList anOldPoints; + foreach ( const CurveCreator_ICurve::SectionToPoint aSectionToPoint, anInitialDragPointsCoords.keys() ) { + CurveCreator::Coordinates aCoords = anInitialDragPointsCoords.value( aSectionToPoint ); + anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) ); + } + + if ( myCurve->canPointsBeSorted() ) { + // Add old coordinates of the curve points (except the dragged points) to the list + for( int aSectionId = 0 ; aSectionId < myCurve->getNbSections() ; aSectionId++ ) { + CurveCreator::Coordinates aCoords; + for ( int aPointId = 0, aNb = myCurve->getNbPoints( aSectionId ); aPointId < aNb; aPointId++ ) { + aCoords = myCurve->getPoint( aSectionId, aPointId ); + if ( aCoords.size() < 2 ) { + continue; + } + + CurveCreator_ICurve::SectionToPoint aSectionToPoint = std::make_pair( aSectionId, aPointId ); + + if ( !anInitialDragPointsCoords.contains( aSectionToPoint ) ) { + anOldPoints.push_back( std::make_pair( aSectionToPoint, aCoords ) ); + } + } + } + + // Apply points sorting + CurveCreator_ICurve::SectionToPointList aPoints; + startCurveModification( aPoints, false ); + + myCurve->setSkipSorting( false ); + + CurveCreator_ICurve::SectionToPointCoordsList aCoordList; + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aDraggedPoints.begin(), + aLast = aDraggedPoints.end(); + for ( ; anIt != aLast; anIt++ ) { + int aSectionId = anIt->first; + int aPointId = anIt->second; + std::deque aPos = myCurve->getPoint( aSectionId, aPointId ); + + aCoordList.push_back( + std::make_pair( std::make_pair( aSectionId, aPointId ), aPos ) ); + } + + myCurve->setSeveralPoints( aCoordList, false ); + + finishCurveModification( aDraggedPoints ); + } else { + // if the drag of some points has happened, restore the drag selection + START_MEASURE_TIME; + setSelectedPoints( aDraggedPoints ); + END_MEASURE_TIME( "drop" ); + } + + // Save drag difference + myCurve->saveCoordDiff( anOldPoints ); + } + } + else // check whether the segment is clicked an a new point should be added to the segment + { + int aReleasedX = theEvent->x(); + int aReleasedY = theEvent->y(); + if ( myPressedX == aReleasedX && myPressedY == aReleasedY ) + insertPointToSelectedSegment( aReleasedX, aReleasedY ); + } + + // updates the input panel table to show the selected point coordinates + updateLocalPointView(); + updateUndoRedo(); + + emit curveModified(); +} + +/** + * Manage mouse move events in Modification mode + * \param theWindow an owner of the signal + * \param theEvent a mouse event + */ +void CurveCreator_Widget::onMouseMove( SUIT_ViewWindow*, QMouseEvent* theEvent ) +{ + if ( getActionMode() != ModificationMode || !myDragStarted ) + return; + + QPoint aPos = theEvent->pos(); + if ( (aPos - myDragStartPosition).manhattanLength() < QApplication::startDragDistance() ) + return; + + START_MEASURE_TIME; + + moveSelectedPoints( aPos.x(), aPos.y() ); + myDragStartPosition = aPos; + + END_MEASURE_TIME( "drag" ); +} + +/** + * Set zero viewer by the last view closed in + * \param theManager a viewer manager + */ +void CurveCreator_Widget::onLastViewClosed( SUIT_ViewManager* theManager ) +{ + myOCCViewer = 0; +} + +void CurveCreator_Widget::onMousePress( QMouseEvent* theEvent ) +{ + onMousePress( 0, theEvent ); +} + +void CurveCreator_Widget::onMouseRelease( QMouseEvent* theEvent ) +{ + onMouseRelease( 0, theEvent ); +} + +void CurveCreator_Widget::onMouseMove( QMouseEvent* theEvent ) +{ + onMouseMove( 0, theEvent ); +} + +void CurveCreator_Widget::onCellChanged( int theRow, int theColumn ) +{ + int aCurrSect = myLocalPointView->getSectionId( theRow ); + int aPntIndex = myLocalPointView->getPointId( theRow ); + + if ( aPntIndex < 0 ) + return; + + CurveCreator_ICurve::SectionToPointList aSelPoints; + startCurveModification( aSelPoints ); + + double aX = myLocalPointView->item( theRow, 2 )->data( Qt::UserRole ).toDouble(); + double anY = myLocalPointView->item( theRow, 3 )->data( Qt::UserRole ).toDouble(); + std::deque aChangedPos; + aChangedPos.push_back( aX ); + aChangedPos.push_back( anY ); + myCurve->setPoint( aCurrSect, aPntIndex, aChangedPos ); + + finishCurveModification( aSelPoints ); + + emit curveModified(); +} + +/** + * Removes a selected section from the curve. Updates undo/redo status + */ +void CurveCreator_Widget::removeSection() +{ + stopActionMode(); + + QList aSections = mySectionView->getSelectedSections(); + for( int i = 0 ; i < aSections.size() ; i++ ){ + int aSectNum = aSections[i] - (i); + myCurve->removeSection( aSectNum ); + mySectionView->sectionsRemoved( aSectNum ); + } + mySectionView->clearSelection(); + updateUndoRedo(); + + emit curveModified(); +} + +/** + * Removes a selected points from the curve. Updates undo/redo status + */ +void CurveCreator_Widget::removePoint() +{ + CurveCreator_ICurve::SectionToPointList aPoints; + getSelectedPoints( aPoints ); + if ( aPoints.size() == 0 ) + return; + + CurveCreator_ICurve::SectionToPointList aSelPoints; + startCurveModification( aSelPoints, false ); + + myCurve->removeSeveralPoints( aPoints ); + finishCurveModification( CurveCreator_ICurve::SectionToPointList() ); + mySectionView->reset(); + + emit curveModified(); +} + +void CurveCreator_Widget::addNewPoint(const CurveCreator::Coordinates& theCoords) +{ + if( !myCurve ) + return; + QList aSections = mySectionView->getSelectedSections(); + if( aSections.size() == 0 ){ + return; + } + int aSection = aSections[0]; + myCurve->addPoints(theCoords, aSection); // add to the end of section + mySectionView->pointsAdded( aSection, myCurve->getNbPoints( aSection ) ); + updateActionsStates(); + updateUndoRedo(); + + emit curveModified(); +} + +void CurveCreator_Widget::insertPointToSelectedSegment( const int theX, + const int theY ) +{ + Handle(AIS_InteractiveContext) aContext = getAISContext(); + + OCCViewer_ViewPort3d* aViewPort = getViewPort(); + Handle(V3d_View) aView; + if ( aViewPort ) + aView = aViewPort->getView(); + + if ( aContext.IsNull() || aView.IsNull() ) + return; + gp_Pnt aPoint; + gp_Pnt aPoint1, aPoint2; + Handle(AIS_InteractiveObject) anAISObject = myCurve->getAISObject(); + bool isFoundPoint = CurveCreator_Utils::pointOnObject( aView, anAISObject, theX, theY, + aPoint, aPoint1, aPoint2 ); + if ( !isFoundPoint ) + return; + + // insert the point to the model curve + CurveCreator_ICurve::SectionToPointList aSelPoints; + startCurveModification( aSelPoints ); + + CurveCreator::Coordinates aCoords; + aCoords.push_back( aPoint.X() ); + aCoords.push_back( aPoint.Y() ); + + CurveCreator_ICurve::SectionToPointList aPoints1, aPoints2; + findSectionsToPoints( aPoint1.X(), aPoint1.Y(), aPoints1 ); + findSectionsToPoints( aPoint2.X(), aPoint2.Y(), aPoints2 ); + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = aPoints1.begin(), + aLast = aPoints1.end(); + int aSectionId = -1; + // find the indices of the neighbour point + // there can be a case when a new point is added into two sections + int aPoint1Id = -1, aPoint2Id = -1; + for ( ; anIt != aLast && aSectionId < 0; anIt++ ) { + int aSectionCur = anIt->first; + CurveCreator_ICurve::SectionToPointList::const_iterator anIt2 = aPoints2.begin(), + aLast2 = aPoints2.end(); + for ( ; anIt2 != aLast2 && aSectionId < 0; anIt2++ ) { + if ( anIt2->first == aSectionCur ) { + aSectionId = aSectionCur; + aPoint1Id = anIt->second; + aPoint2Id = anIt2->second; + } + } + } + + int anInsertPos = -1; + int aLastPoint = myCurve->getNbPoints( aSectionId )-1; + if ( ( aPoint1Id == aLastPoint && aPoint2Id == 0 ) || + ( aPoint2Id == aLastPoint && aPoint1Id == 0 ) ) + anInsertPos = -1; // if the section happens between first and last points + else + anInsertPos = aPoint1Id < aPoint2Id ? aPoint1Id + 1 : aPoint2Id + 1; + + myCurve->addPoints( aCoords, aSectionId, anInsertPos ); + mySectionView->pointsAdded( aSectionId, myCurve->getNbPoints( aSectionId ) ); + + finishCurveModification( aSelPoints ); + + setSelectedPoints(); + + emit curveModified(); +} + +void CurveCreator_Widget::moveSelectedPoints( const int theXPosition, + const int theYPosition ) +{ + OCCViewer_ViewPort3d* aViewPort = getViewPort(); + if ( !aViewPort ) + return; + + CurveCreator_ICurve::SectionToPointList aPoints; + startCurveModification( aPoints, false ); + + gp_Pnt aStartPnt = CurveCreator_Utils::ConvertClickToPoint( myDragStartPosition.x(), + myDragStartPosition.y(), + aViewPort->getView() ); + gp_Pnt anEndPnt = CurveCreator_Utils::ConvertClickToPoint( theXPosition, theYPosition, + aViewPort->getView() ); + double aXDelta = aStartPnt.X() - anEndPnt.X(); + double anYDelta = aStartPnt.Y() - anEndPnt.Y(); + + CurveCreator_ICurve::SectionToPointCoordsList aCoordList; + std::deque aChangedPos; + CurveCreator_ICurve::SectionToPointList::const_iterator anIt = myDragPoints.begin(), + aLast = myDragPoints.end(); + for ( ; anIt != aLast; anIt++ ) { + int aSectionId = anIt->first; + int aPointId = anIt->second; + aChangedPos = myCurve->getPoint( aSectionId, aPointId ); + if ( aChangedPos.size() < 2 ) + continue; + + // Remember drag points coordinates + if ( !myDragged ) { + myInitialDragPointsCoords.insert( std::make_pair( aSectionId, aPointId ), aChangedPos ); + } + + aChangedPos[0] = aChangedPos[0] - aXDelta; + aChangedPos[1] = aChangedPos[1] - anYDelta; + + aCoordList.push_back( + std::make_pair(std::make_pair( aSectionId, aPointId ), + aChangedPos )); + } + myCurve->setSeveralPoints( aCoordList, false ); + + myDragged = true; + finishCurveModification( myDragPoints ); + + emit curveModified(); +} + +void CurveCreator_Widget::updateLocalPointView() +{ + if ( myDragStarted ) + return; + Handle(AIS_InteractiveContext) aContext = getAISContext(); + if ( aContext.IsNull() ) + return; + + CurveCreator_Utils::getSelectedPoints( aContext, myCurve, myLocalPoints ); + int aNbPoints = myLocalPoints.size(); + + bool isRowLimit = aNbPoints > myLocalPointRowLimit; + myLocalPointView->setVisible( getActionMode() == ModificationMode && !isRowLimit ); + + if ( !isRowLimit ) { + bool isBlocked = myLocalPointView->blockSignals(true); + + myLocalPointView->setLocalPointsToTable( myLocalPoints ); + + myLocalPointView->blockSignals( isBlocked ); + } +} + +/** + * + */ +void CurveCreator_Widget::setLocalPointContext( const bool theOpen, const bool isUpdateTable ) +{ + CurveCreator_Utils::setLocalPointContext( myCurve, getAISContext(), theOpen ); + if ( !theOpen && isUpdateTable ) + updateLocalPointView(); +} + +/** + * Set drag operation started. Save the position and a list of dragged points + * \param theState the drag operation state: started/finished + * \param thePoint the start drag position + */ +void CurveCreator_Widget::setDragStarted( const bool theState, const QPoint& thePoint ) +{ + if ( theState ) { + getSelectedPoints( myDragPoints ); + + myDragStarted = myDragPoints.size(); + myDragStartPosition = thePoint; + if ( myDragStarted ) { + // change a viewer interaction style in order to avoid a select rectangle build + myDragInteractionStyle = changeInteractionStyle( SUIT_ViewModel::KEY_FREE ); + myCurve->setSkipSorting( true ); + } + } + else { + if ( myDragStarted ) + changeInteractionStyle( myDragInteractionStyle ); + myDragStarted = false; + myDragPoints.clear(); + myInitialDragPointsCoords.clear(); + } + myDragged = false; +} + +void CurveCreator_Widget::getSelectedPoints( CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + thePoints.clear(); + thePoints = myLocalPoints; +} + +void CurveCreator_Widget::setSelectedPoints( const CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + if ( myDragStarted ) + return; + Handle(AIS_InteractiveContext) aContext = getAISContext(); + if ( aContext.IsNull() || !aContext->HasOpenedContext() ) + return; + + CurveCreator_Utils::setSelectedPoints( aContext, myCurve, thePoints ); + + updateLocalPointView(); +} + +void CurveCreator_Widget::stopActionMode() +{ + setActionMode( NoneMode ); +} + +/** + * Get viewer information before perform the curve modification. + * Take a list of selected cuve points an close local context. + * The context should be closed because the curve presentation is + * redisplayed and if it is not closed, when we close the local context + * later, the presentation shown in the local context is disappeared. + * \param thePoints an output list of curve selected points + * \param theFillPoints a flag whether the selection list should be filled + */ +void CurveCreator_Widget::startCurveModification( + CurveCreator_ICurve::SectionToPointList& thePoints, + const bool theFillPoints ) +{ + if ( theFillPoints ) { + thePoints.clear(); + getSelectedPoints( thePoints ); + } + setLocalPointContext( false ); +} + +/** + * Restore the viewer state after the curve modification is done. + * Open local context and select given points inside it. + * \param thePoints a list of curve selected points + */ +void CurveCreator_Widget::finishCurveModification( + const CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + if ( getActionMode() == ModificationMode ) + setLocalPointContext( true ); + setSelectedPoints( thePoints ); + updateUndoRedo(); +} + +/** + * Returns a point index in the model curve by the point coordinates in the viewer + * \param theX the X coordinate of the point + * \param theY the Y coordinate of the point + */ +int CurveCreator_Widget::findLocalPointIndex( int theSectionId, float theX, float theY ) +{ + return CurveCreator_UtilsICurve::findLocalPointIndex( myCurve, theSectionId, theX, theY ); +} + +void CurveCreator_Widget::findSectionsToPoints( const double theX, const double theY, + CurveCreator_ICurve::SectionToPointList& thePoints ) +{ + return CurveCreator_UtilsICurve::findSectionsToPoints( myCurve, theX, theY, thePoints ); +} + +void CurveCreator_Widget::convert( const CurveCreator_ICurve::SectionToPointList& thePoints, + QMap >& theConvPoints ) +{ + return CurveCreator_UtilsICurve::convert( thePoints, theConvPoints ); +} + +/** + * Returns whethe the container has the value + * \param theList a container of values + * \param theValue a value + */ +bool CurveCreator_Widget::contains( const CurveCreator_ICurve::SectionToPointList& theList, + const CurveCreator_ICurve::SectionToPoint& theValue ) const +{ + return CurveCreator_UtilsICurve::contains( theList, theValue ); } diff --git a/src/CurveCreator/CurveCreator_Widget.h b/src/CurveCreator/CurveCreator_Widget.h index 7f335e8db..e15e92309 100644 --- a/src/CurveCreator/CurveCreator_Widget.h +++ b/src/CurveCreator/CurveCreator_Widget.h @@ -1,9 +1,9 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 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, or (at your option) any later version. +// 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 @@ -20,101 +20,212 @@ #ifndef CURVECREATOR_WIDGET_H #define CURVECREATOR_WIDGET_H -#include "CurveCreator_Curve.hxx" +#include "CurveCreator_Macro.hxx" #include "CurveCreator.hxx" +#include "CurveCreator_ICurve.hxx" #include #include +#include #include +#include +#include + +#include +#include +#include +#include // TODO - remove + +class OCCViewer_Viewer; +class OCCViewer_ViewPort3d; + +class AIS_ListOfInteractive; class QAction; class QPixmap; -class CurveCreator_CurveEditor; +class CurveCreator_TableView; class CurveCreator_TreeView; -class CurveCreator_NewPointDlg; class CurveCreator_NewSectionDlg; class CURVECREATOR_EXPORT CurveCreator_Widget : public QWidget { - Q_OBJECT + Q_OBJECT + +public: + enum ActionFlags { + NoFlags = 0x00000000, + DisableDetectionMode = 0x00000001, + DisableNewSection = 0x00000002, + DisableClosedSection = 0x00000004 + }; + + enum ActionMode { + NoneMode, + AdditionMode, + ModificationMode, + DetectionMode + }; + public: - explicit CurveCreator_Widget( QWidget* parent, - CurveCreator_Curve *theCurve, - Qt::WindowFlags fl=0 ); + explicit CurveCreator_Widget( QWidget* parent, + CurveCreator_ICurve *theCurve, + const int theActionFlags = NoFlags, + const QStringList& theCoordTitles = QStringList(), + Qt::WindowFlags fl=0, + int theLocalPointRowLimit = 20); - void setCurve( CurveCreator_Curve* theCurve ); + // OCC viewer manipulation + void setOCCViewer( OCCViewer_Viewer* theViewer ); - QList getSelectedSections(); - QList< QPair< int, int > > getSelectedPoints(); + Handle(AIS_InteractiveContext) getAISContext(); + OCCViewer_ViewPort3d* getViewPort(); + int changeInteractionStyle( int theStyle ); - bool isInstantSketchingEnabled() const; - void setInstantSketchingEnabled( const bool theState ); + void reset(); + void setCurve( CurveCreator_ICurve* theCurve ); + + QList getSelectedSections(); + void setSelectedSections( const QList& theSections ); + + void removeSelected(); + bool removeEnabled(); + + void setActionMode( const ActionMode& theMode ); + ActionMode getActionMode() const; + + void SetViewer2DMode(const bool To2D); signals: - void selectionChanged(); - void subOperationStarted( QWidget* ); - void subOperationFinished( QWidget* ); + void selectionChanged(); + void subOperationStarted( QWidget*, bool ); + void subOperationFinished( QWidget* ); + void curveModified(); public slots: protected slots: - void onAdditionMode(bool checked); - void onModificationMode(bool checked); - void onDetectPoints(bool checked); - void onModeChanged(bool checked); - void onNewSection(); - void onSelectionChanged(); - void onAddNewPoint(const CurveCreator::Coordinates& theCoords); - void onAddNewSection(); - void onEditSection( int theSection ); - void onEditPoint( int theSection, int thePoint ); - void onModifyPoint(); - void onModifySection(); - void onCancelPoint(); - void onCancelSection(); - void onJoin(); - void onRemove(); - void onMoveUp(); - void onMoveDown(); - void onClearAll(); - void onJoinAll(); - void onInsertSectionBefore(); - void onInsertSectionAfter(); - void onSetSpline(); - void onSetPolyline(); - void onCloseSections(); - void onUncloseSections(); - void onInsertPointBefore(); - void onInsertPointAfter(); - void onUndo(); - void onRedo(); - void onUndoSettings(); - void onContextMenu(QPoint thePoint); - void onGetPointByClick( SUIT_ViewWindow*, QMouseEvent* ); -// void onPointSelect( SUIT_ViewWindow*, QMouseEvent* ); - void onPointDrag( SUIT_ViewWindow*, QMouseEvent* ); + void onAdditionMode(bool checked); + void onModificationMode(bool checked); + void onDetectionMode(bool checked); + void onModeChanged(bool checked); + void onNewSection(); + void onSelectionChanged(); + void onAddNewSection(); + void onEditSection( int theSection ); + void onModifySection(); + void onCancelSection(); + void onJoin(); + void onRemove(); + void onClearAll(); + void onJoinAll(); + void onSetSpline(); + void onSetPolyline(); + void onCloseSections(); + void onUncloseSections(); + void onUndo(); + void onRedo(); + void onUndoSettings(); + void onContextMenu(QPoint thePoint); + + void onMousePress( SUIT_ViewWindow*, QMouseEvent* theEvent ); + void onMouseRelease( SUIT_ViewWindow*, QMouseEvent* theEvent ); + void onMouseMove( SUIT_ViewWindow*, QMouseEvent* theEvent ); + void onLastViewClosed( SUIT_ViewManager* theManager ); + + void onMousePress( QMouseEvent* theEvent ); + void onMouseRelease( QMouseEvent* theEvent ); + void onMouseMove( QMouseEvent* theEvent ); + + void onCellChanged( int theRow, int theColumn ); + +protected: + void addCoordsByClick( QMouseEvent* ); + protected: - enum ActionId{ UNDO_ID, REDO_ID, NEW_SECTION_ID, ADDITION_MODE_ID, REMOVE_ID, REMOVE_ALL_ID, JOIN_ID, - JOIN_ALL_ID, UP_ID, DOWN_ID, INSERT_SECTION_BEFORE_ID, INSERT_SECTION_AFTER_ID, - INSERT_POINT_BEFORE_ID, INSERT_POINT_AFTER_ID, CLOSE_SECTIONS_ID, UNCLOSE_SECTIONS_ID, - SET_SECTIONS_POLYLINE_ID, SET_SECTIONS_SPLINE_ID, CLEAR_ALL_ID, SEPARATOR_ID, - MODIFICATION_MODE_ID, DETECTION_MODE_ID }; + enum ActionId{ NONE_ID, + UNDO_ID, + REDO_ID, + NEW_SECTION_ID, + ADDITION_MODE_ID, + REMOVE_ID, + REMOVE_ALL_ID, + JOIN_ID, + JOIN_ALL_ID, + CLOSE_SECTIONS_ID, + UNCLOSE_SECTIONS_ID, + SET_SECTIONS_POLYLINE_ID, + SET_SECTIONS_SPLINE_ID, + CLEAR_ALL_ID, + SEPARATOR_ID, + MODIFICATION_MODE_ID, + DETECTION_MODE_ID + }; + private: - QAction* createAction( ActionId theId, const QString& theName, const QPixmap& theImage, - const QString& theToolTip, const QKeySequence& theShortcut ); - QAction* getAction(ActionId theId); - void updateUndoRedo(); + OCCViewer_Viewer* getOCCViewer(); + + QAction* createAction( ActionId theId, const QString& theName, const QPixmap& theImage, + const QString& theToolTip, const QKeySequence& theShortcut ); + QAction* getAction(ActionId theId); + QAction* getAction(ActionMode theMode); + + void updateActionsStates(); + void updateUndoRedo(); + + void removeSection(); + void removePoint(); + void addNewPoint(const CurveCreator::Coordinates& theCoords); + void insertPointToSelectedSegment( const int theXPosition, + const int theYPosition ); + void moveSelectedPoints( const int theXPosition, const int theYPosition ); + void updateLocalPointView(); + void setLocalPointContext( const bool theOpen, const bool isUpdateTable = false ); + + void setDragStarted( const bool theState, const QPoint& thePoint = QPoint() ); + + void getSelectedPoints( CurveCreator_ICurve::SectionToPointList& thePoints ); + void setSelectedPoints( const CurveCreator_ICurve::SectionToPointList& = + CurveCreator_ICurve::SectionToPointList() ); + + void stopActionMode(); + + void startCurveModification( CurveCreator_ICurve::SectionToPointList& thePoints, + const bool theFillPoints = true ); + void finishCurveModification( const CurveCreator_ICurve::SectionToPointList& thePoints = + CurveCreator_ICurve::SectionToPointList() ); + + // curve algorithm + int findLocalPointIndex( int theSectionId, float theX, float theY ); + void findSectionsToPoints( const double theX, const double theY, + CurveCreator_ICurve::SectionToPointList& thePoints ); + void convert( const CurveCreator_ICurve::SectionToPointList& thePoints, + QMap >& theConvPoints ); + + bool contains( const CurveCreator_ICurve::SectionToPointList& theList, + const CurveCreator_ICurve::SectionToPoint& theValue ) const; + private: - QMap myActionMap; - CurveCreator_Curve* myCurve; - CurveCreator_CurveEditor* myEdit; - CurveCreator_TreeView* mySectionView; - CurveCreator_NewPointDlg* myNewPointEditor; - CurveCreator_NewSectionDlg* myNewSectionEditor; - int mySection; - int myPointNum; - QPoint myDragStartPosition; + QMap myActionMap; + CurveCreator_ICurve* myCurve; + CurveCreator_TreeView* mySectionView; + CurveCreator_TableView* myLocalPointView; + CurveCreator_ICurve::SectionToPointList myLocalPoints; + CurveCreator_NewSectionDlg* myNewSectionEditor; + OCCViewer_Viewer* myOCCViewer; + int myLocalPointRowLimit; + int mySection; + int myPointNum; + bool myDragStarted; + QPoint myDragStartPosition; + int myDragInteractionStyle; + CurveCreator_ICurve::SectionToPointList myDragPoints; + QMap myInitialDragPointsCoords; + bool myDragged; + QByteArray myGuiState; + int myPressedX; + int myPressedY; + OCCViewer_ViewWindow::Mode2dType myOld2DMode; }; #endif // CURVECREATOR_WIDGET_H diff --git a/src/EntityGUI/CMakeLists.txt b/src/EntityGUI/CMakeLists.txt index 865678ad3..79668add1 100755 --- a/src/EntityGUI/CMakeLists.txt +++ b/src/EntityGUI/CMakeLists.txt @@ -40,6 +40,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/GEOMGUI ${PROJECT_SOURCE_DIR}/src/GEOMBase ${PROJECT_SOURCE_DIR}/src/SKETCHER + ${PROJECT_SOURCE_DIR}/src/CurveCreator ${PROJECT_SOURCE_DIR}/src/ShapeRecognition ${PROJECT_SOURCE_DIR}/src/DlgRef ${PROJECT_BINARY_DIR}/src/DlgRef @@ -65,6 +66,7 @@ SET(_link_LIBRARIES GEOM DlgRef GEOMSketcher + CurveCreator ) # optional sources @@ -103,6 +105,7 @@ SET(EntityGUI_HEADERS EntityGUI.h EntityGUI_Widgets.h EntityGUI_SketcherDlg.h + EntityGUI_PolylineDlg.h EntityGUI_3DSketcherDlg.h EntityGUI_IsolineDlg.h EntityGUI_SubShapeDlg.h @@ -115,6 +118,7 @@ SET(_moc_HEADERS EntityGUI_Widgets.h EntityGUI_FieldDlg.h EntityGUI_SketcherDlg.h + EntityGUI_PolylineDlg.h EntityGUI_3DSketcherDlg.h EntityGUI_IsolineDlg.h EntityGUI_SubShapeDlg.h @@ -135,6 +139,7 @@ SET(EntityGUI_SOURCES EntityGUI_Widgets.cxx EntityGUI_FieldDlg.cxx EntityGUI_SketcherDlg.cxx + EntityGUI_PolylineDlg.cxx EntityGUI_3DSketcherDlg.cxx EntityGUI_IsolineDlg.cxx EntityGUI_SubShapeDlg.cxx diff --git a/src/EntityGUI/EntityGUI.cxx b/src/EntityGUI/EntityGUI.cxx index b6f36c8ad..3a3bd6297 100644 --- a/src/EntityGUI/EntityGUI.cxx +++ b/src/EntityGUI/EntityGUI.cxx @@ -59,6 +59,7 @@ #include "EntityGUI_FeatureDetectorDlg.h" // Feature Detection #include "EntityGUI_PictureImportDlg.h" // Import Picture in viewer #include "EntityGUI_FieldDlg.h" // Create/Edit Field +#include "EntityGUI_PolylineDlg.h" // Create/Edit 2d polyline #include "GEOMImpl_Types.hxx" @@ -188,6 +189,10 @@ bool EntityGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) SUIT_MessageBox::warning(parent, tr("WRN_WARNING"), tr("NO_FIELD")); break; } + case GEOMOp::Op2dPolylineEditor: // POLYLINE EDITOR + getGeometryGUI()->ActiveWorkingPlane(); + aDlg = new EntityGUI_PolylineDlg( getGeometryGUI(), parent ); + break; default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); break; diff --git a/src/EntityGUI/EntityGUI_PolylineDlg.cxx b/src/EntityGUI/EntityGUI_PolylineDlg.cxx new file mode 100644 index 000000000..50c12462a --- /dev/null +++ b/src/EntityGUI/EntityGUI_PolylineDlg.cxx @@ -0,0 +1,670 @@ +// 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 "EntityGUI_PolylineDlg.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +//#define SET_PLANE + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +EntityGUI_PolylineDlg::EntityGUI_PolylineDlg + (GeometryGUI* theGeometryGUI, QWidget* parent, bool modal, Qt::WindowFlags fl) + : GEOMBase_Skeleton( theGeometryGUI, parent, modal, fl ), + myCurve (0), + myEditorWidget (0), + myAddElementBox (0), + myPlnComboBox (0), + myPlnButton (0), + myPlnSelButton (0), + myWPlaneLineEdit (0), + myPolylineSelButton (0), + myPolylineEdit (0), + myEditCurrentArgument (0) +{ + QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_CC_POLYLINE"))); + QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(tr("POLYLINE_DLG_TITLE")); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(tr("POLYLINE_TITLE")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->setAttribute( Qt::WA_DeleteOnClose ); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose ); + mainFrame()->RadioButton3->close(); + + QGroupBox *aGroupBox1 = new QGroupBox(tr("GEOM_CS"), this); + QGridLayout *aPlaneLayout = new QGridLayout(aGroupBox1); + + aPlaneLayout->setSpacing(6); + aPlaneLayout->setMargin(11); + + myPlnComboBox = new QComboBox(aGroupBox1); + aPlaneLayout->addWidget(myPlnComboBox, 0, 0, 1, 3); + + myPlnButton = new QPushButton (aGroupBox1); + myPlnButton->setText( tr( "GEOM_SKETCHER_RESTORE" ) ); + aPlaneLayout->addWidget(myPlnButton, 0, 3); + +#ifdef SET_PLANE + QLabel *aPlaneLbl = new QLabel(tr("GEOM_PLANE"), aGroupBox1); + + myPlnSelButton = new QPushButton (aGroupBox1); + myPlnSelButton->setIcon(image1); + myWPlaneLineEdit = new QLineEdit (aGroupBox1); + myWPlaneLineEdit->setReadOnly(true); +#endif + + QLabel *aPolylineLbl = new QLabel(tr("POLYLINE_IMPORT"), aGroupBox1); + + myPolylineSelButton = new QPushButton (aGroupBox1); + myPolylineSelButton->setIcon(image1); + myPolylineEdit = new QLineEdit (aGroupBox1); + myPolylineEdit->setReadOnly(true); + +#ifdef SET_PLANE + aPlaneLayout->addWidget(aPlaneLbl, 1, 0); + aPlaneLayout->addWidget(myPlnSelButton, 1, 1); + aPlaneLayout->addWidget(myWPlaneLineEdit, 1, 2, 1, 2); +#endif + aPlaneLayout->addWidget(aPolylineLbl, 2, 0); + aPlaneLayout->addWidget(myPolylineSelButton, 2, 1); + aPlaneLayout->addWidget(myPolylineEdit, 2, 2, 1, 2); + + aPlaneLayout->setColumnStretch(2, 1); + + myCurve = new CurveCreator_Curve( CurveCreator::Dim2d ); + myEditorWidget = new CurveCreator_Widget (centralWidget(), myCurve); + myAddElementBox = new QGroupBox (tr("POLYLINE_ADD_SECTION"), centralWidget()); + + QBoxLayout* anAddElementLayout = new QVBoxLayout( myAddElementBox ); + + anAddElementLayout->setMargin( 0 ); + anAddElementLayout->setSpacing( 6 ); + + QVBoxLayout* layout = new QVBoxLayout( centralWidget() ); + + layout->setMargin( 0 ); + layout->setSpacing( 6 ); + layout->addWidget( aGroupBox1 ); + layout->addWidget( myEditorWidget ); + layout->addWidget( myAddElementBox ); + + /***************************************************************/ + + setHelpFileName( "create_polyline_page.html" ); + + /* Initialisations */ + Init(); +} + +//================================================================================= +// function : Destructor +// purpose : +//================================================================================= +EntityGUI_PolylineDlg::~EntityGUI_PolylineDlg() +{ + delete myCurve; +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::Init() +{ + initName(tr("POLYLINE_NAME")); + + SalomeApp_Application *anApp = myGeomGUI->getApp(); + OCCViewer_ViewManager *aViewManager = dynamic_cast + (anApp->getViewManager(OCCViewer_Viewer::Type(), true)); + LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr(); + + myEditorWidget->setOCCViewer(aViewManager ? aViewManager->getOCCViewer() : 0); + + // Init the list of local coordinate system + gp_Pnt aPnt(0., 0., 0.); + gp_Dir aDirN(0., 0., 1.); + gp_Dir aDirX(1., 0., 0.); + gp_Ax3 aLCS(aPnt, aDirN, aDirX); + + //add Global CS + myPlnComboBox->addItem(tr("GEOM_GCS"), false); + myWPlaneList.push_back(GEOM::GeomObjPtr()); + myLCSList.push_back(aLCS); + + connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); + connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel())); + +#ifdef SET_PLANE + connect(myPlnSelButton, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); +#endif + connect(myPolylineSelButton, SIGNAL(clicked()), + this, SLOT(SetEditCurrentArgument())); + connect(aSelMgr, SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + connect(myEditorWidget, SIGNAL(subOperationStarted(QWidget*, bool)), + this, SLOT(processStartedSubOperation(QWidget*, bool))); + connect(myEditorWidget, SIGNAL(subOperationFinished(QWidget*)), + this, SLOT(processFinishedSubOperation(QWidget*))); + connect(myEditorWidget, SIGNAL(curveModified()), + this, SLOT(onUpdatePreview())); +#ifdef SET_PLANE + connect(myPlnComboBox, SIGNAL(activated(int)), + this, SLOT(ActivateLocalCS())); + connect(myPlnButton, SIGNAL(clicked()), + this, SLOT(ActivateLocalCS())); +#endif + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + + myAddElementBox->hide(); + myPolylineSelButton->click(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : Clear +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::Clear() +{ + delete myCurve; + + myCurve = new CurveCreator_Curve( CurveCreator::Dim2d ); + myEditorWidget->setCurve(myCurve); +} + +//================================================================================= +// function : GetCurveParams +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::GetCurveParams(GEOM::ListOfListOfDouble &theCoords, + GEOM::string_array &theNames, + GEOM::short_array &theTypes, + GEOM::ListOfBool &theCloseds) +{ + const int aNbSec = myCurve->getNbSections(); + int i; + int j; + + theCoords.length(aNbSec); + theNames.length(aNbSec); + theTypes.length(aNbSec); + theCloseds.length(aNbSec); + + for (i = 0; i < aNbSec; ++i) { + // Set coordinates + CurveCreator::Coordinates aCoords = myCurve->getPoints(i); + const int aNbPoints = aCoords.size(); + + theCoords[i].length(aNbPoints); + + for (j = 0; j < aNbPoints; ++j) { + theCoords[i][j] = aCoords[j]; + } + + // Set section type + const CurveCreator::SectionType aType = myCurve->getSectionType(i); + + switch (aType) { + case CurveCreator::Spline: + theTypes[i] = GEOM::Interpolation; + break; + case CurveCreator::Polyline: + default: + theTypes[i] = GEOM::Polyline; + break; + } + + // Set section names and closed flags. + theNames[i] = CORBA::string_dup(myCurve->getSectionName(i).c_str()); + theCloseds[i] = myCurve->isClosed(i); + } +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr EntityGUI_PolylineDlg::createOperation() +{ + return getGeomEngine()->GetICurvesOperations( getStudyId() ); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool EntityGUI_PolylineDlg::isValid( QString& msg ) +{ + return true; +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool EntityGUI_PolylineDlg::execute( ObjectList& objects ) +{ + GEOM::GEOM_ICurvesOperations_var anOper = + GEOM::GEOM_ICurvesOperations::_narrow(getOperation()); + + // Get the polyline creation parameters. + GEOM::ListOfListOfDouble aCoords; + GEOM::string_array aNames; + GEOM::short_array aTypes; + GEOM::ListOfBool aCloseds; + + GetCurveParams(aCoords, aNames, aTypes, aCloseds); + + // Get Working Plane. + int ind = myPlnComboBox->currentIndex(); + + if (ind != -1) { + bool isPlane = myPlnComboBox->itemData(ind).toBool(); + GEOM::GEOM_Object_var anObj; + + // Perform operation + if (isPlane) { + anObj = anOper->MakePolyline2DOnPlane + (aCoords, aNames, aTypes, aCloseds, myWPlaneList.at(ind).get()); + } else { + gp_Ax3 anAxis = myLCSList.at(ind); + GEOM::ListOfDouble aPlane; + + aPlane.length(9); + aPlane[0] = anAxis.Location().X(); + aPlane[1] = anAxis.Location().Y(); + aPlane[2] = anAxis.Location().Z(); + aPlane[3] = anAxis.Direction().X(); + aPlane[4] = anAxis.Direction().Y(); + aPlane[5] = anAxis.Direction().Z(); + aPlane[6] = anAxis.XDirection().X(); + aPlane[7] = anAxis.XDirection().Y(); + aPlane[8] = anAxis.XDirection().Z(); + + anObj = anOper->MakePolyline2D + (aCoords, aNames, aTypes, aCloseds, aPlane); + } + + if (!anObj->_is_nil()) { + objects.push_back(anObj._retn()); + } + } + + return true; +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool EntityGUI_PolylineDlg::ClickOnApply() +{ + if (!onAccept()) + return false; + + initName(); + + return true; +} + +//================================================================================= +// function : ClickOnCancel() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::ClickOnCancel() +{ + myEditorWidget->SetViewer2DMode(false); + GEOMBase_Skeleton::ClickOnCancel(); +} + +//================================================================================= +// function : processStartedSubOperation +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::processStartedSubOperation( QWidget* theWidget, bool theIsEdit ) +{ + myEditorWidget->setEnabled( false ); + + myAddElementBox->setTitle( theIsEdit ? tr( "POLYLINE_EDIT_SECTION" ) : tr( "POLYLINE_ADD_SECTION" ) ); + QBoxLayout* anAddElementLayout = dynamic_cast( myAddElementBox->layout() ); + anAddElementLayout->addWidget( theWidget ); + + theWidget->show(); + myAddElementBox->show(); +} + + +//================================================================================= +// function : processFinishedSubOperation +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::processFinishedSubOperation( QWidget* theWidget ) +{ + myEditorWidget->setEnabled( true ); + + QBoxLayout* anAddElementLayout = dynamic_cast( myAddElementBox->layout() ); + anAddElementLayout->removeWidget( theWidget ); + + theWidget->hide(); + myAddElementBox->hide(); +} + +//================================================================================= +// function : deleteSelected +// purpose : Redirect the delete action to editor widget +//================================================================================= +void EntityGUI_PolylineDlg::deleteSelected() +{ + myEditorWidget->removeSelected(); +} + +//================================================================================= +// function : deleteEnabled +// purpose : Checks whether there are some to delete +//================================================================================= +bool EntityGUI_PolylineDlg::deleteEnabled() +{ + return myEditorWidget->removeEnabled(); +} + +//================================================================================= +// function : SelectionIntoArgument +// purpose : Called when selection is changed +//================================================================================= +void EntityGUI_PolylineDlg::SelectionIntoArgument() +{ + bool isModified = false; + GEOM::GeomObjPtr aSelectedObject = getSelected(TopAbs_SHAPE); + TopoDS_Shape aShape; + + if (aSelectedObject && GEOMBase::GetShape(aSelectedObject.get(), aShape) && + !aShape.IsNull()) { + QString aName = GEOMBase::GetName(aSelectedObject.get()); + + if (myEditCurrentArgument == myPolylineEdit) { + // Import a curve + CurveCreator_Curve *aNewCurve = + new CurveCreator_Curve(CurveCreator::Dim2d); + gp_Ax3 aLocalCS; + + if (CurveCreator_Utils::constructCurve(aShape, aNewCurve, aLocalCS)) { + // Change the current curve be the new one. + myEditorWidget->setCurve(aNewCurve); + delete myCurve; + myCurve = aNewCurve; + isModified = true; + myPolylineEdit->setText(aName); +#ifdef SET_PLANE + AddLocalCS(aSelectedObject.get(), false, aLocalCS); + myWPlaneLineEdit->clear(); + myPlnSelButton->setDown(false); +#endif + myPolylineSelButton->setDown(true); + } else { + // Does nothing, just clears selection. + delete aNewCurve; + } +#ifdef SET_PLANE + } else if (myEditCurrentArgument == myWPlaneLineEdit) { + // Import planar face. + if (aShape.ShapeType() == TopAbs_FACE) { + // Check if the face is planar + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); + GeomLib_IsPlanarSurface aPlanarCheck(aSurf, Precision::Confusion()); + + if (aPlanarCheck.IsPlanar()) { + myWPlaneLineEdit->setText(aName); + myPolylineEdit->clear(); + AddLocalCS(aSelectedObject.get(), true, + WPlaneToLCS(aSelectedObject.get())); + isModified = true; + myPlnSelButton->setDown(true); + myPolylineSelButton->setDown(false); + } + } + + if (!isModified) { + myEditCurrentArgument->setText(tr("GEOM_SKETCHER_WPLANE")); + } +#endif + } + } + + if (!isModified) { + // Does nothing, just clears selection. + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + myGeomGUI->getApp()->selectionMgr()->clearSelected(); + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + } +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::SetEditCurrentArgument() +{ + if (sender() == myPlnSelButton) { +#ifdef SET_PLANE + myEditCurrentArgument = myWPlaneLineEdit; + myEditCurrentArgument->setFocus(); + myPlnSelButton->setDown(true); + myPolylineSelButton->setDown(false); +#endif + } else if (sender() == myPolylineSelButton) { + myEditCurrentArgument = myPolylineEdit; + myEditCurrentArgument->setFocus(); +#ifdef SET_PLANE + myPlnSelButton->setDown(false); +#endif + myPolylineSelButton->setDown(true); + } +} + +//================================================================================= +// function : ActivateThisDialog +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : onUpdatePreview +// purpose : +//================================================================================= +void EntityGUI_PolylineDlg::onUpdatePreview() +{ + displayPreview(true); +} + +//================================================================================= +// function : ActivateLocalCS +// purpose : Activate & Fit Working plane +//================================================================================= +void EntityGUI_PolylineDlg::ActivateLocalCS() +{ + const int ind = myPlnComboBox->currentIndex(); + + if (ind == 0) { + // Default plane +#ifdef SET_PLANE + myWPlaneLineEdit->clear(); +#endif + myPolylineEdit->clear(); + } else if (ind > 0) { // Skip 0 as it is default + // Update text on line edits. + QString aName = GEOMBase::GetName(GetActiveWPlane().get()); + bool isPlane = myPlnComboBox->itemData(ind).toBool(); + + if (isPlane) { +#ifdef SET_PLANE + myWPlaneLineEdit->setText(aName); +#endif + myPolylineEdit->clear(); + } else { + myPolylineEdit->setText(aName); +#ifdef SET_PLANE + myWPlaneLineEdit->clear(); +#endif + } + } + + gp_Ax3 anAxis = GetActiveLocalCS(); + + myGeomGUI->SetWorkingPlane(anAxis); + myGeomGUI->ActiveWorkingPlane(); +} + +//================================================================================= +// function : GetActiveLocalCS +// purpose : Get Working plane +//================================================================================= +gp_Ax3 EntityGUI_PolylineDlg::GetActiveLocalCS() +{ + const int ind = myPlnComboBox->currentIndex(); + + return ind >= 0 ? myLCSList.at(ind) : myGeomGUI->GetWorkingPlane(); +} + +//================================================================================= +// function : GetActiveWPlane +// purpose : Get Working plane +//================================================================================= +GEOM::GeomObjPtr EntityGUI_PolylineDlg::GetActiveWPlane() +{ + const int ind = myPlnComboBox->currentIndex(); + + return ind >= 0 ? myWPlaneList.at(ind) : GEOM::GeomObjPtr(); +} + +//================================================================================= +// function : AddLocalCS() +// purpose : Add All Coordinates systems in study +//================================================================================= +void EntityGUI_PolylineDlg::AddLocalCS(GEOM::GeomObjPtr theSelectedObject, + const bool IsPlane, + const gp_Ax3 &theLCS) +{ + QString aName = GEOMBase::GetName(theSelectedObject.get()); + + int index = myPlnComboBox->findText(aName, Qt::MatchExactly); + + if (index == -1) { // If the working plane hasn't been added yet + myWPlaneList.push_back(theSelectedObject); + myLCSList.push_back(theLCS); + myPlnComboBox->addItem(aName, QVariant(IsPlane)); + index = myPlnComboBox->count(); + myPlnComboBox->setCurrentIndex(index - 1); + } else { + myPlnComboBox->setCurrentIndex(index); + } + ActivateLocalCS(); +} + +//================================================================================= +// function : WPlaneToLCS ( aWPlane ) +// purpose : +//================================================================================= +gp_Ax3 EntityGUI_PolylineDlg::WPlaneToLCS(GEOM::GeomObjPtr theGeomObj) +{ + TopoDS_Shape aShape = + GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), theGeomObj.get()); + gp_Ax3 aLCS; + + if (theGeomObj || aShape.IsNull()) { + MESSAGE("CORBA::is_nil(theGeomObj) || aShape.IsNull()") + } + + aLCS.Transform(aShape.Location().Transformation()); + + if (aShape.ShapeType() == TopAbs_FACE) { + GEOM::GEOM_IMeasureOperations_ptr aMeasureOp = + myGeomGUI->GetGeomGen()->GetIMeasureOperations(getStudyId()); + double Ox, Oy, Oz, Zx, Zy, Zz, Xx, Xy, Xz; + + aMeasureOp->GetPosition(theGeomObj.get(), Ox, Oy, Oz, Zx, Zy, Zz, Xx, Xy, Xz); + + if (aMeasureOp->IsDone()) { + gp_Pnt aPnt (Ox, Oy, Oz); + gp_Dir aDirN (Zx, Zy, Zz); + gp_Dir aDirX (Xx, Xy, Xz); + aLCS = gp_Ax3(aPnt, aDirN, aDirX); + } + } + + return aLCS; +} diff --git a/src/EntityGUI/EntityGUI_PolylineDlg.h b/src/EntityGUI/EntityGUI_PolylineDlg.h new file mode 100644 index 000000000..6f7b009a5 --- /dev/null +++ b/src/EntityGUI/EntityGUI_PolylineDlg.h @@ -0,0 +1,152 @@ +// 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 ENTITYGUI_POLYLINEDLG_H +#define ENTITYGUI_POLYLINEDLG_H + + +#include + +class CurveCreator_Curve; +class CurveCreator_Widget; +class QGroupBox; +class QComboBox; + + +//================================================================================= +// class : EntityGUI_PolylineDlg +// purpose : +//================================================================================= +class EntityGUI_PolylineDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + + EntityGUI_PolylineDlg (GeometryGUI*, QWidget* = 0, + bool = false, Qt::WindowFlags = 0); + + virtual ~EntityGUI_PolylineDlg(); + + void deleteSelected(); + bool deleteEnabled(); + +protected: + + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid( QString& ); + virtual bool execute( ObjectList& ); + +private: + + void Init(); + void Clear(); + void enterEvent(QEvent *); + + /** + * This method converts the curve into curve parameters required to + * construct an object using the interface + * GEOM_ICurvesOperations::MakePolyline2DOnPlane. + * + * \param theCurve a curve object, that contains data. + * \param theCoordsList the list of coordinates list. theCoordsList[0] + * is the coordinates list of the first section. theCoordsList[1] + * is for the second section etc. Output parameter. + * \param theNamesList the list of names. The order corresponds to + * theCoordsList. Output parameter. + * \param theTypesList the list of curve types. The order corresponds to + * theCoordsList. Output parameter. + * \param theClosedList the list of Closed flags. The order corresponds to + * theCoordsList. Output parameter. + */ + void GetCurveParams(GEOM::ListOfListOfDouble &theCoords, + GEOM::string_array &theNames, + GEOM::short_array &theTypes, + GEOM::ListOfBool &theCloseds); + + /** + * This method returns the current local coordinate system. + * + * \return local coordinate system. + */ + gp_Ax3 GetActiveLocalCS(); + + /** + * This method returns the current working plane. Can be null. + * + * \return the current working plane. + */ + GEOM::GeomObjPtr GetActiveWPlane(); + + /** + * This method add a local coordinate system of the selected object. + * + * \param theSelectedObject the selected object. It can be a planar face + * or an inported polyline. + * \param IsPlane true for planar face; false for imported polyline. + * \param theLCS the local coordinate system. + */ + void AddLocalCS(GEOM::GeomObjPtr theSelectedObject, + const bool IsPlane, + const gp_Ax3 &theLCS); + + /** + * This method converts the working plane object into + * the local coordinate system of the polyline. + * + * \param theGeomObj the working plane + * \return the local coordinate system + */ + gp_Ax3 WPlaneToLCS(GEOM::GeomObjPtr theGeomObj); + +protected slots: + + void ClickOnOk(); + bool ClickOnApply(); + void ClickOnCancel(); + void processStartedSubOperation( QWidget*, bool ); + void processFinishedSubOperation( QWidget* ); + void SetEditCurrentArgument(); + void SelectionIntoArgument(); + void ActivateThisDialog(); + void onUpdatePreview(); + void ActivateLocalCS(); + +private: + + CurveCreator_Curve *myCurve; + CurveCreator_Widget *myEditorWidget; + QGroupBox *myAddElementBox; + QComboBox *myPlnComboBox; + QPushButton *myPlnButton; + QPushButton *myPlnSelButton; + QPushButton *myPolylineSelButton; + QLineEdit *myWPlaneLineEdit; + QLineEdit *myPolylineEdit; + QLineEdit *myEditCurrentArgument; /* Current LineEdit */ + QList myLCSList; + QList myWPlaneList; + +}; + +#endif // ENTITYGUI_POLYLINEDLG_H diff --git a/src/GEOM/GEOM_Function.cxx b/src/GEOM/GEOM_Function.cxx index c141e2e4c..458e0a0bc 100644 --- a/src/GEOM/GEOM_Function.cxx +++ b/src/GEOM/GEOM_Function.cxx @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -474,6 +476,74 @@ Handle(TColStd_HArray1OfInteger) GEOM_Function::GetIntegerArray(int thePosition) return anIntegerArray->Array(); } +//============================================================================= +/*! + * SetByteArray + */ +//============================================================================= +void GEOM_Function::SetByteArray (int thePosition, + const Handle(TColStd_HArray1OfByte)& theArray) +{ + _isDone = false; + if(thePosition <= 0) return; + TDF_Label anArgLabel = ARGUMENT(thePosition); + Handle(TDataStd_ByteArray) anAttr = + TDataStd_ByteArray::Set(anArgLabel, theArray->Lower(), theArray->Upper()); + anAttr->ChangeArray(theArray); + _isDone = true; +} + +//============================================================================= +/*! + * GetByteArray + */ +//============================================================================= +Handle(TColStd_HArray1OfByte) GEOM_Function::GetByteArray(int thePosition) +{ + _isDone = false; + if(thePosition <= 0) return 0; + Handle(TDataStd_ByteArray) aByteArray; + TDF_Label anArgLabel = ARGUMENT(thePosition); + if(!anArgLabel.FindAttribute(TDataStd_ByteArray::GetID(), aByteArray)) return 0; + + _isDone = true; + return aByteArray->InternalArray(); +} + +//============================================================================= +/*! + * SetBooleanArray + */ +//============================================================================= +void GEOM_Function::SetBooleanArray (int thePosition, + const Handle(TColStd_HArray1OfByte)& theArray) +{ + _isDone = false; + if(thePosition <= 0) return; + TDF_Label anArgLabel = ARGUMENT(thePosition); + Handle(TDataStd_BooleanArray) anAttr = + TDataStd_BooleanArray::Set(anArgLabel, theArray->Lower(), theArray->Upper()); + anAttr->SetInternalArray(theArray); + _isDone = true; +} + +//============================================================================= +/*! + * GetBooleanArray + */ +//============================================================================= +Handle(TColStd_HArray1OfByte) GEOM_Function::GetBooleanArray(int thePosition) +{ + _isDone = false; + if(thePosition <= 0) return 0; + Handle(TDataStd_BooleanArray) aBooleanArray; + TDF_Label anArgLabel = ARGUMENT(thePosition); + if(!anArgLabel.FindAttribute(TDataStd_BooleanArray::GetID(), aBooleanArray)) return 0; + + _isDone = true; + return aBooleanArray->InternalArray(); +} + //============================================================================= /*! * SetString diff --git a/src/GEOM/GEOM_Function.hxx b/src/GEOM/GEOM_Function.hxx index 702acb959..688324dae 100644 --- a/src/GEOM/GEOM_Function.hxx +++ b/src/GEOM/GEOM_Function.hxx @@ -32,6 +32,7 @@ #include #include +class Handle_TColStd_HArray1OfByte; class Handle_TColStd_HArray1OfReal; class Handle_TColStd_HArray1OfInteger; class Handle_TColStd_HSequenceOfTransient; @@ -108,6 +109,18 @@ public: //Returns an integer array argument at position thePosition Standard_EXPORT Handle(TColStd_HArray1OfInteger) GetIntegerArray(int thePosition); + //Sets a byte array argument at position thePosition + Standard_EXPORT void SetByteArray(int thePosition, const Handle(TColStd_HArray1OfByte)& theArray); + + //Returns a byte array argument at position thePosition + Standard_EXPORT Handle(TColStd_HArray1OfByte) GetByteArray(int thePosition); + + //Sets a boolean array argument at position thePosition + Standard_EXPORT void SetBooleanArray(int thePosition, const Handle(TColStd_HArray1OfByte)& theArray); + + //Returns a boolean array argument at position thePosition + Standard_EXPORT Handle(TColStd_HArray1OfByte) GetBooleanArray(int thePosition); + //Sets a reference to other function argument at position thePosition Standard_EXPORT void SetReference(int thePosition, Handle(GEOM_Function) theReference); diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 115e51e67..40c06a632 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -1215,6 +1215,10 @@ ICO_SHELL_SEL_ONLY build_shell.png + + ICO_CURVE_CREATOR + polyline.png + ICO_SKETCH sketch.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 89480676b..754afda3d 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -2366,7 +2366,15 @@ Please, select face, shell or solid and try again MEN_CURVE_CREATOR - Curve creator + 2D Polyline + + + TOP_CURVE_CREATOR + Create 2D polyline + + + STB_CURVE_CREATOR + Create 2D polyline MEN_ALL_SEL_ONLY @@ -5163,6 +5171,22 @@ shells and solids on the other hand. TOOL_IMPORTEXPORT Import / Export XAO + + TABLE_SECTION + Section + + + TABLE_INDEX + Index + + + TABLE_X + X + + + TABLE_Y + Y + BasicGUI_CurveDlg @@ -5404,74 +5428,39 @@ shells and solids on the other hand. Face 2 V - - CurveCreator_NewPointDlg - - ADD_NEW_POINT - Add new points - - - X_COORD - X - - - Y_COORD - Y - - - Z_COORD - Z - - - ADD_BTN - Add - - - ADD_CONTINUE_BTN - Add and continue - - - ADD_NEW_POINT_TO_%1 - Add new point to %1 - - - SET_POINT_COORDINATES - Set point coordinates - - CurveCreator_NewSectionDlg - NAME + SECTION_NAME Name - LINE_TYPE + SECTION_LINE_TYPE Type - POLYLINE_TYPE + SECTION_POLYLINE_TYPE Polyline - SPLINE_TYPE + SECTION_SPLINE_TYPE Spline - LINE_CLOSED + SECTION_LINE_CLOSED Closed - OK - Ok + SECTION_ADD_BTN + Add - ADD_BTN - Add + SECTION_OK_BTN + Ok - ADD_CONTINUE_BTN - Add and continue + SECTION_CANCEL_BTN + Cancel ADD_NEW_SECTION @@ -5496,11 +5485,7 @@ shells and solids on the other hand. CurveCreator_Widget - CURVE_NAME_TLT - Name - - - SECTION_GROUP_TLT + SECTION_GROUP_TITLE Sections @@ -5527,22 +5512,6 @@ shells and solids on the other hand. NEW_SECTION_TLT Insert new section - - INSERT_SECTION_BEFORE - Insert section before - - - INSERT_SECTION_BEFORE_TLT - Insert section before - - - INSERT_SECTION_AFTER - Insert section after - - - INSERT_SECTION_AFTER_TLT - Insert section after - ADDITION_MODE Addition mode @@ -5567,18 +5536,6 @@ shells and solids on the other hand. DETECTION_MODE_TLT Detection mode - - INSERT_POINT_BEFORE - Insert point before - - - INSERT_POINT_BEFORE_TLT - Insert point before - - - INSERT_POINT_AFTER - Insert point after - CLOSE_SECTIONS Set closed @@ -5627,22 +5584,6 @@ shells and solids on the other hand. JOIN_TLT Join selected sections - - STEP_UP - Move up - - - STEP_UP_TLT - Move selected objects up - - - STEP_DOWN - Move down - - - STEP_DOWN_TLT - Move selected objects down - CLEAR_ALL Clear all @@ -5660,6 +5601,33 @@ shells and solids on the other hand. Join all sections + + EntityGUI_PolylineDlg + + POLYLINE_DLG_TITLE + Polyline Construction + + + POLYLINE_TITLE + Polyline + + + POLYLINE_NAME + Polyline + + + POLYLINE_IMPORT + Import polyline + + + POLYLINE_ADD_SECTION + Add section + + + POLYLINE_EDIT_SECTION + Edit section + + EntityGUI_SketcherDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 2b3b7ca83..d3d37411c 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -561,6 +561,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpCreateField: // MENU FIELD - CREATE FIELD case GEOMOp::OpEditField: // MENU FIELD - EDIT FIELD case GEOMOp::OpEditFieldPopup: // POPUP MENU - EDIT FIELD + case GEOMOp::Op2dPolylineEditor: // MENU BASIC - POLYLINE EDITOR libName = "EntityGUI"; break; case GEOMOp::OpEdge: // MENU BUILD - EDGE @@ -600,10 +601,6 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpSharedShapes: // MENU OPERATION - GET SHARED SHAPES case GEOMOp::OpExtrudedBoss: // MENU OPERATION - EXTRUDED BOSS case GEOMOp::OpExtrudedCut: // MENU OPERATION - EXTRUDED CUT -#ifdef DEBUG_CURVE_CREATOR - // for debug purposes, to be removed - case GEOMOp::OpCurveCreator: // MENU OPERATION - CURVE CREATOR -#endif libName = "OperationGUI"; break; case GEOMOp::OpSewing: // MENU REPAIR - SEWING @@ -941,6 +938,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpFeatureDetect,"FEATURE_DETECTION" ); #endif createGeomAction( GEOMOp::OpPictureImport,"PICTURE_IMPORT" ); + createGeomAction( GEOMOp::Op2dPolylineEditor, "CURVE_CREATOR" ); createGeomAction( GEOMOp::OpEdge, "EDGE" ); createGeomAction( GEOMOp::OpWire, "WIRE" ); @@ -973,10 +971,6 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpSharedShapes, "GET_SHARED_SHAPES" ); createGeomAction( GEOMOp::OpExtrudedCut, "EXTRUDED_CUT" ); createGeomAction( GEOMOp::OpExtrudedBoss, "EXTRUDED_BOSS" ); -#ifdef DEBUG_CURVE_CREATOR - // for debug purposes, to be removed - createGeomAction( GEOMOp::OpCurveCreator, "CURVE_CREATOR" ); -#endif createGeomAction( GEOMOp::OpFillet1d, "FILLET_1D" ); createGeomAction( GEOMOp::OpFillet2d, "FILLET_2D" ); @@ -1106,19 +1100,20 @@ void GeometryGUI::initialize( CAM_Application* app ) int newEntId = createMenu( tr( "MEN_NEW_ENTITY" ), -1, -1, 10 ); int basicId = createMenu( tr( "MEN_BASIC" ), newEntId, -1 ); - createMenu( GEOMOp::OpPoint, basicId, -1 ); - createMenu( GEOMOp::OpLine, basicId, -1 ); - createMenu( GEOMOp::OpCircle, basicId, -1 ); - createMenu( GEOMOp::OpEllipse, basicId, -1 ); - createMenu( GEOMOp::OpArc, basicId, -1 ); - 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 ); - createMenu( GEOMOp::OpLCS, basicId, -1 ); + createMenu( GEOMOp::OpPoint, basicId, -1 ); + createMenu( GEOMOp::OpLine, basicId, -1 ); + createMenu( GEOMOp::OpCircle, basicId, -1 ); + createMenu( GEOMOp::OpEllipse, basicId, -1 ); + createMenu( GEOMOp::OpArc, basicId, -1 ); + createMenu( GEOMOp::OpCurve, basicId, -1 ); + createMenu( GEOMOp::Op2dSketcher, basicId, -1 ); + createMenu( GEOMOp::Op2dPolylineEditor, 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 ); + createMenu( GEOMOp::OpLCS, basicId, -1 ); createMenu( GEOMOp::OpOriginAndVectors, basicId, -1 ); int primId = createMenu( tr( "MEN_PRIMITIVES" ), newEntId, -1 ); @@ -1224,11 +1219,6 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpChamfer, operId, -1 ); createMenu( GEOMOp::OpExtrudedBoss, operId, -1 ); createMenu( GEOMOp::OpExtrudedCut, operId, -1 ); -#ifdef DEBUG_CURVE_CREATOR - // for debug purposes, to be removed - createMenu( separator(), operId, -1 ); - createMenu( GEOMOp::OpCurveCreator, operId, -1 ); -#endif //createMenu( GEOMOp::OpClipping, operId, -1 ); int repairId = createMenu( tr( "MEN_REPAIR" ), -1, -1, 10 ); @@ -1319,18 +1309,19 @@ void GeometryGUI::initialize( CAM_Application* app ) // ---- create toolbars -------------------------- int basicTbId = createTool( tr( "TOOL_BASIC" ), QString( "GEOMBasic" ) ); - createTool( GEOMOp::OpPoint, basicTbId ); - createTool( GEOMOp::OpLine, basicTbId ); - createTool( GEOMOp::OpCircle, basicTbId ); - createTool( GEOMOp::OpEllipse, basicTbId ); - createTool( GEOMOp::OpArc, basicTbId ); - createTool( GEOMOp::OpCurve, basicTbId ); - 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::OpPoint, basicTbId ); + createTool( GEOMOp::OpLine, basicTbId ); + createTool( GEOMOp::OpCircle, basicTbId ); + createTool( GEOMOp::OpEllipse, basicTbId ); + createTool( GEOMOp::OpArc, basicTbId ); + createTool( GEOMOp::OpCurve, basicTbId ); + createTool( GEOMOp::OpVector, basicTbId ); + createTool( GEOMOp::Op2dSketcher, basicTbId ); //rnc + createTool( GEOMOp::Op2dPolylineEditor, basicTbId ); + createTool( GEOMOp::Op3dSketcher, basicTbId ); //rnc + createTool( GEOMOp::OpIsoline, basicTbId ); + createTool( GEOMOp::OpPlane, basicTbId ); + createTool( GEOMOp::OpLCS, basicTbId ); createTool( GEOMOp::OpOriginAndVectors, basicTbId ); // int sketchTbId = createTool( tr( "TOOL_SKETCH" ), QString( "GEOMSketch" ) ); @@ -1390,10 +1381,6 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpChamfer, featTbId ); createTool( GEOMOp::OpExtrudedBoss, featTbId ); createTool( GEOMOp::OpExtrudedCut, featTbId ); -#ifdef DEBUG_CURVE_CREATOR - // for debug purposes, to be removed - createTool( GEOMOp::OpCurveCreator, featTbId ); -#endif int buildTbId = createTool( tr( "TOOL_BUILD" ), QString( "GEOMBuild" ) ); createTool( GEOMOp::OpEdge, buildTbId ); diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index f392e4df6..f66c19df1 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -119,6 +119,7 @@ namespace GEOMOp { OpCreateField = 3305, // MENU FIELD - CREATE FIELD OpEditField = 3306, // MENU FIELD - EDIT FIELD OpEditFieldPopup = 3307, // POPUP MENU - EDIT FIELD + Op2dPolylineEditor = 3308, // MENU NEW ENTITY - BASIC - POLYLINE EDITOR // BuildGUI --------------------//-------------------------------- OpEdge = 3400, // MENU NEW ENTITY - BUILD - EDGE OpWire = 3401, // MENU NEW ENTITY - BUILD - WIRE @@ -154,10 +155,6 @@ namespace GEOMOp { OpSharedShapes = 3708, // MENU OPERATION - GET SHARED SHAPES OpExtrudedBoss = 3709, // MENU OPERATION - ETRUDED BOSS OpExtrudedCut = 3710, // MENU OPERATION - ETRUDED CUT -#ifdef DEBUG_CURVE_CREATOR - OpCurveCreator = 3799, // MENU OPERATION - CURVE CREATOR -#endif - // for debug purposes, to be removed // RepairGUI -------------------//-------------------------------- OpSewing = 4000, // MENU REPAIR - SEWING OpSuppressFaces = 4001, // MENU REPAIR - SUPPRESS FACES diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt index 0fb145931..a09066811 100755 --- a/src/GEOMImpl/CMakeLists.txt +++ b/src/GEOMImpl/CMakeLists.txt @@ -74,6 +74,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_PointDriver.hxx GEOMImpl_IPoint.hxx GEOMImpl_IPolyline.hxx + GEOMImpl_IPolyline2D.hxx GEOMImpl_ICircle.hxx GEOMImpl_ISpline.hxx GEOMImpl_IEllipse.hxx @@ -150,6 +151,7 @@ SET(GEOMImpl_HEADERS GEOMImpl_Block6Explorer.hxx GEOMImpl_MeasureDriver.hxx GEOMImpl_PolylineDriver.hxx + GEOMImpl_PolylineDumper.hxx GEOMImpl_CircleDriver.hxx GEOMImpl_EllipseDriver.hxx GEOMImpl_ArcDriver.hxx @@ -192,6 +194,7 @@ SET(GEOMImpl_SOURCES GEOMImpl_IGroupOperations.cxx GEOMImpl_IFieldOperations.cxx GEOMImpl_IBaseIEOperations.cxx + GEOMImpl_IPolyline2D.cxx GEOMImpl_Gen.cxx GEOMImpl_PointDriver.cxx GEOMImpl_VectorDriver.cxx @@ -221,6 +224,7 @@ SET(GEOMImpl_SOURCES GEOMImpl_Block6Explorer.cxx GEOMImpl_MeasureDriver.cxx GEOMImpl_PolylineDriver.cxx + GEOMImpl_PolylineDumper.cxx GEOMImpl_CircleDriver.cxx GEOMImpl_EllipseDriver.cxx GEOMImpl_ArcDriver.cxx diff --git a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx index df1c543e7..f6c452b95 100644 --- a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx @@ -51,6 +51,7 @@ #include "GEOMImpl_3DSketcherDriver.hxx" #include "GEOMImpl_IPolyline.hxx" +#include "GEOMImpl_IPolyline2D.hxx" #include "GEOMImpl_ICircle.hxx" #include "GEOMImpl_ISpline.hxx" #include "GEOMImpl_IEllipse.hxx" @@ -59,12 +60,14 @@ #include "GEOMImpl_I3DSketcher.hxx" #include "GEOMImpl_ICurveParametric.hxx" #include "GEOMImpl_IIsoline.hxx" +#include "GEOMImpl_PolylineDumper.hxx" #include #include "utilities.h" #include +#include #include #include @@ -1465,3 +1468,155 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakeIsoline SetErrorCode(OK); return anIsoline; } + +//============================================================================= +/*! + * MakePolyline2D + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakePolyline2D + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(TColStd_HArray1OfReal) &theWorkingPlane) +{ + SetErrorCode(KO); + + if (theCoords.empty() || theNames.IsNull() || theTypes.IsNull() || + theCloseds.IsNull() || theWorkingPlane.IsNull()) { + return NULL; + } + + // Add a new Polyline object + Handle(GEOM_Object) aResult = + GetEngine()->AddObject(GetDocID(), GEOM_POLYLINE2D); + Handle(GEOM_Function) aFunction = aResult->AddFunction + (GEOMImpl_PolylineDriver::GetID(), POLYLINE2D_PLN_COORDS); + + if (aFunction.IsNull()) { + return NULL; + } + + // Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PolylineDriver::GetID()) { + return NULL; + } + + GEOMImpl_IPolyline2D aCI(aFunction); + + aCI.SetCoords(theCoords); + aCI.SetNames(theNames); + aCI.SetTypes(theTypes); + aCI.SetClosedFlags(theCloseds); + aCI.SetWorkingPlaneDbls(theWorkingPlane); + + // Compute the isoline curve + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Polyline driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOMImpl_PolylineDumper aDumper(theCoords, theNames, theTypes, + theCloseds, theWorkingPlane); + + aDumper.Dump(aResult); + + if (aDumper.IsDone() == Standard_False) { + SetErrorCode("Python dump failed"); + return NULL; + } + + SetErrorCode(OK); + return aResult; +} + +//============================================================================= +/*! + * MakePolyline2DOnPlane + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakePolyline2DOnPlane + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(GEOM_Object) &theWorkingPlane) +{ + SetErrorCode(KO); + + if (theCoords.empty() || theNames.IsNull() || theTypes.IsNull() || + theCloseds.IsNull() || theWorkingPlane.IsNull()) { + return NULL; + } + + //Add a new Polyline object + Handle(GEOM_Object) aResult = + GetEngine()->AddObject(GetDocID(), GEOM_POLYLINE2D); + Handle(GEOM_Function) aFunction = aResult->AddFunction + (GEOMImpl_PolylineDriver::GetID(), POLYLINE2D_PLN_OBJECT); + + if (aFunction.IsNull()) { + return NULL; + } + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PolylineDriver::GetID()) { + return NULL; + } + + Handle(GEOM_Function) aRefPlane = theWorkingPlane->GetLastFunction(); + + if (aRefPlane.IsNull()) { + return NULL; + } + + GEOMImpl_IPolyline2D aCI(aFunction); + + aCI.SetCoords(theCoords); + aCI.SetNames(theNames); + aCI.SetTypes(theTypes); + aCI.SetClosedFlags(theCloseds); + aCI.SetWorkingPlane(aRefPlane); + + //Compute the isoline curve + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Polyline driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } + + //Make a Python command + GEOMImpl_PolylineDumper aDumper(theCoords, theNames, theTypes, + theCloseds, theWorkingPlane); + + aDumper.Dump(aResult); + + if (aDumper.IsDone() == Standard_False) { + SetErrorCode("Python dump failed"); + return NULL; + } + + SetErrorCode(OK); + return aResult; +} diff --git a/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx b/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx index 15591a64f..fe4278cc6 100644 --- a/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_ICurvesOperations.hxx @@ -100,6 +100,19 @@ class GEOMImpl_ICurvesOperations : public GEOM_IOperations { const bool IsUIso, const double theParameter); + Standard_EXPORT Handle(GEOM_Object) MakePolyline2D + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(TColStd_HArray1OfReal) &theWorkingPlane); + + Standard_EXPORT Handle(GEOM_Object) MakePolyline2DOnPlane + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(GEOM_Object) &theWorkingPlane); }; #endif diff --git a/src/GEOMImpl/GEOMImpl_IPolyline2D.cxx b/src/GEOMImpl/GEOMImpl_IPolyline2D.cxx new file mode 100644 index 000000000..eb1bcfdd7 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IPolyline2D.cxx @@ -0,0 +1,112 @@ +// Copyright (C) 2007-2014 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 +// + + +#include "GEOMImpl_IPolyline2D.hxx" + +#include + + +//============================================================================= +/*! + * SetCoords + */ +//============================================================================= +void GEOMImpl_IPolyline2D::SetCoords + (const std::list > &theValue) +{ + const Standard_Integer aNbSec = theValue.size(); + + if (aNbSec > 0) { + // Compute the total number of points and fill the array of start indices. + Standard_Integer i; + Standard_Integer aNbCoords = 0; + Handle(TColStd_HArray1OfInteger) anIndices = + new TColStd_HArray1OfInteger(1, aNbSec); + Handle(TColStd_HArray1OfReal) aCoords; + std::list >::const_iterator aSecIter = theValue.begin(); + + for (i = 1; aSecIter != theValue.end(); ++aSecIter, ++i) { + anIndices->SetValue(i, aNbCoords + 1); + aNbCoords += aSecIter->size(); + } + + if (aNbCoords > 0) { + // Fill the array of coordinates. + std::list::const_iterator aCIter; + + aCoords = new TColStd_HArray1OfReal(1, aNbCoords); + aSecIter = theValue.begin(); + + for (i = 1; aSecIter != theValue.end(); ++aSecIter) { + for (aCIter = aSecIter->begin(); aCIter != aSecIter->end(); ++aCIter) { + aCoords->SetValue(i++, *aCIter); + } + } + } + + // Store the coordinates. + if (aCoords.IsNull() == Standard_False) { + _func->SetRealArray(POLY_ARG_COORDS, aCoords); + } + + _func->SetIntegerArray(POLY_ARG_START_INDICES, anIndices); + } +} + +//============================================================================= +/*! + * GetCoords + */ +//============================================================================= +void GEOMImpl_IPolyline2D::GetCoords(std::list > &theValue) +{ + theValue.clear(); + + Handle(TColStd_HArray1OfReal) aCoords = + _func->GetRealArray(POLY_ARG_COORDS); + Handle(TColStd_HArray1OfInteger) anIndices = + _func->GetIntegerArray(POLY_ARG_START_INDICES); + + if (anIndices.IsNull() == Standard_False) { + const Standard_Integer aNbSec = anIndices->Length(); + + // Create an empty sections. + theValue.resize(aNbSec); + + if (aCoords.IsNull() == Standard_False) { + Standard_Integer i; + Standard_Integer j; + std::list >::iterator anIt = theValue.begin(); + + for (i = anIndices->Lower(); i <= anIndices->Upper(); ++i, ++anIt) { + const Standard_Integer iCoord1 = anIndices->Value(i); + const Standard_Integer iCoord2 = i + 1 > anIndices->Upper() ? + aCoords->Upper() + 1 : anIndices->Value(i + 1); + + for (j = iCoord1; j < iCoord2; ++j) { + anIt->push_back(aCoords->Value(j)); + } + } + } + } +} diff --git a/src/GEOMImpl/GEOMImpl_IPolyline2D.hxx b/src/GEOMImpl/GEOMImpl_IPolyline2D.hxx new file mode 100644 index 000000000..302e9f899 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_IPolyline2D.hxx @@ -0,0 +1,94 @@ +// Copyright (C) 2007-2014 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 +// + +//NOTE: This is an interface to a function for the Polyline2D creation. + + +#ifndef _GEOMImpl_IPolyline2D_HXX_ +#define _GEOMImpl_IPolyline2D_HXX_ + + +#include +#include + +#include + +#include +#include +#include + + +#define POLY_ARG_NAMES 1 +#define POLY_ARG_TYPES 2 +#define POLY_ARG_CLOSEDS 3 +#define POLY_ARG_COORDS 4 +#define POLY_ARG_START_INDICES 5 +#define POLY_ARG_WPLANE_DBLS 6 +#define POLY_ARG_WPLANE_OBJ 7 + + +class GEOMIMPL_EXPORT GEOMImpl_IPolyline2D +{ + public: + + GEOMImpl_IPolyline2D(Handle(GEOM_Function) theFunction): _func(theFunction) {} + + void SetNames(const Handle_TColStd_HArray1OfExtendedString &theValue) + { _func->SetStringArray(POLY_ARG_NAMES, theValue); } + + Handle_TColStd_HArray1OfExtendedString GetNames() + { return _func->GetStringArray(POLY_ARG_NAMES); } + + void SetTypes(const Handle_TColStd_HArray1OfByte &theValue) + { _func->SetByteArray(POLY_ARG_TYPES, theValue); } + + Handle_TColStd_HArray1OfByte GetTypes() + { return _func->GetByteArray(POLY_ARG_TYPES); } + + void SetClosedFlags(const Handle_TColStd_HArray1OfByte &theValue) + { _func->SetBooleanArray(POLY_ARG_CLOSEDS, theValue); } + + Handle_TColStd_HArray1OfByte GetClosedFlags() + { return _func->GetBooleanArray(POLY_ARG_CLOSEDS); } + + void SetWorkingPlaneDbls(const Handle_TColStd_HArray1OfReal &thePlane) + { _func->SetRealArray(POLY_ARG_WPLANE_DBLS, thePlane); } + + Handle_TColStd_HArray1OfReal GetWorkingPlaneDbls() + { return _func->GetRealArray(POLY_ARG_WPLANE_DBLS); } + + void SetWorkingPlane(const Handle_GEOM_Function &thePlane) + { _func->SetReference(POLY_ARG_WPLANE_OBJ, thePlane); } + + Handle_GEOM_Function GetWorkingPlane() + { return _func->GetReference(POLY_ARG_WPLANE_OBJ); } + + void SetCoords(const std::list > &theValue); + + void GetCoords(std::list > &theValue); + + private: + + Handle(GEOM_Function) _func; +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_PolylineDriver.cxx b/src/GEOMImpl/GEOMImpl_PolylineDriver.cxx index 1eeeaf277..1a996c1e5 100644 --- a/src/GEOMImpl/GEOMImpl_PolylineDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PolylineDriver.cxx @@ -23,12 +23,17 @@ #include "GEOMImpl_PolylineDriver.hxx" #include "GEOMImpl_ICurveParametric.hxx" +#include "GEOMImpl_ICurvesOperations.hxx" #include "GEOMImpl_IPolyline.hxx" +#include "GEOMImpl_IPolyline2D.hxx" #include "GEOMImpl_Types.hxx" #include "GEOM_Function.hxx" +#include +#include #include #include +#include #include #include #include @@ -38,6 +43,7 @@ #include #include #include +#include #include //======================================================================= @@ -59,6 +65,125 @@ GEOMImpl_PolylineDriver::GEOMImpl_PolylineDriver() { } +//======================================================================= +//function : MakePolyline2D +//purpose : +//======================================================================= +Standard_Integer GEOMImpl_PolylineDriver::MakePolyline2D + (TFunction_Logbook& log) const +{ + if (Label().IsNull()) { + return 0; + } + + Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + GEOMImpl_IPolyline2D aCI(aFunction); + Standard_Integer aType = aFunction->GetType(); + TopoDS_Shape aShape; + + // Get data. + Handle(TColStd_HArray1OfExtendedString) aNames = aCI.GetNames(); + Handle(TColStd_HArray1OfByte) aTypes = aCI.GetTypes(); + Handle(TColStd_HArray1OfByte) aClosedFlags = aCI.GetClosedFlags(); + std::list > aCoords; + gp_Ax3 aWPlane; + + aCI.GetCoords(aCoords); + + // Check the data validity + if (aNames.IsNull()) { + return 0; + } + + Standard_Integer aNbSections = aNames->Length(); + + if (aTypes.IsNull() || aNbSections != aTypes->Length()) { + return 0; + } + + if (aClosedFlags.IsNull() || aNbSections != aClosedFlags->Length()) { + return 0; + } + + if (aNbSections != aCoords.size()) { + return 0; + } + + if (aType == POLYLINE2D_PLN_COORDS) { + Handle(TColStd_HArray1OfReal) aPlaneCoords = aCI.GetWorkingPlaneDbls(); + + if (aPlaneCoords.IsNull()) { + return 0; + } + + if (aPlaneCoords->Length() != 9) { + return 0; + } + + Standard_Integer i = aPlaneCoords->Lower(); + gp_Pnt aOrigin(aPlaneCoords->Value(i), aPlaneCoords->Value(i + 1), + aPlaneCoords->Value(i + 2)); + gp_Dir aDirZ(aPlaneCoords->Value(i + 3), aPlaneCoords->Value(i + 4), + aPlaneCoords->Value(i + 5)); + gp_Dir aDirX(aPlaneCoords->Value(i + 6), aPlaneCoords->Value(i + 7), + aPlaneCoords->Value(i + 8)); + aWPlane = gp_Ax3(aOrigin, aDirZ, aDirX); + } else if (aType == POLYLINE2D_PLN_OBJECT) { + Handle(GEOM_Function) aRefFace = aCI.GetWorkingPlane(); + TopoDS_Shape aShape = aRefFace->GetValue(); + + aWPlane = GEOMUtils::GetPosition(aShape); + } else { + return 0; + } + + // Construct a shape. + Standard_Integer iN = aNames->Lower(); + Standard_Integer iT = aTypes->Lower(); + Standard_Integer iC = aClosedFlags->Lower(); + std::list >::const_iterator anIter = aCoords.begin(); + BRep_Builder aBuilder; + Standard_Boolean isEmpty = Standard_True; + + if (aNbSections > 1) { + aBuilder.MakeCompound(TopoDS::Compound(aShape)); + } + + for (; anIter != aCoords.end(); ++anIter, ++iN, ++iT, ++iC) { + Standard_Integer aType = aTypes->Value(iT); + TopoDS_Shape aSection; + + if (aType == GEOMImpl_ICurvesOperations::Polyline) { + aSection = Sketcher_Utils::MakePolyline + (*anIter, aClosedFlags->Value(iC), aWPlane); + } else if (aType == GEOMImpl_ICurvesOperations::Interpolation) { + aSection = Sketcher_Utils::MakeInterpolation + (*anIter, aClosedFlags->Value(iC), aWPlane); + } + + if (aNbSections > 1) { + // There are multiple sections. + if (aSection.IsNull() == Standard_False) { + aBuilder.Add(aShape, aSection); + isEmpty = Standard_False; + } + } else { + // There is only one section. + isEmpty = aSection.IsNull(); + aShape = aSection; + } + } + + if (isEmpty) { + return 0; + } + + aFunction->SetValue(aShape); + log.SetTouched(Label()); + + return 1; +} + //======================================================================= //function : Execute //purpose : @@ -67,9 +192,13 @@ Standard_Integer GEOMImpl_PolylineDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + Standard_Integer aType = aFunction->GetType(); + + if (aType == POLYLINE2D_PLN_COORDS || aType == POLYLINE2D_PLN_OBJECT) { + return MakePolyline2D(log); + } GEOMImpl_IPolyline aCI (aFunction); - Standard_Integer aType = aFunction->GetType(); TopoDS_Shape aShape; @@ -166,10 +295,9 @@ GetCreationInformation(std::string& theOperationName, GEOMImpl_ICurveParametric aIP( function ); Standard_Integer aType = function->GetType(); - theOperationName = "CURVE"; - switch ( aType ) { case POLYLINE_POINTS: + theOperationName = "CURVE"; AddParam( theParams, "Type", "Polyline"); if ( aIP.HasData() ) { @@ -206,6 +334,103 @@ GetCreationInformation(std::string& theOperationName, AddParam( theParams, "Is closed", aCI.GetIsClosed() ); } break; + case POLYLINE2D_PLN_COORDS: + case POLYLINE2D_PLN_OBJECT: + { + theOperationName = "SKETCH"; + + GEOMImpl_IPolyline2D aP2d(function); + Handle(TColStd_HArray1OfExtendedString) aNames = aP2d.GetNames(); + + if (aNames.IsNull() == Standard_False) { + if (aNames->Length() == 1) { + // This is the single curve. Make its full dump. + AddParam(theParams, "Name", aNames->Value(aNames->Lower())); + + Handle(TColStd_HArray1OfByte) aTypes = aP2d.GetTypes(); + + if (aTypes.IsNull() == Standard_False && aTypes->Length() == 1) { + Standard_Integer aType = aTypes->Value(aTypes->Lower()); + + if (aType == GEOMImpl_ICurvesOperations::Polyline) { + AddParam(theParams, "Type") << "Polyline"; + } else if (aType == GEOMImpl_ICurvesOperations::Interpolation) { + AddParam(theParams, "Type") << "Interpolation"; + } + } + + Handle(TColStd_HArray1OfByte) aCloseds = aP2d.GetClosedFlags(); + + if (aCloseds.IsNull() == Standard_False && aCloseds->Length() == 1) { + const char *aYesNo = + aCloseds->Value(aCloseds->Lower()) ? "Yes" : "No"; + + AddParam(theParams, "Is closed", aYesNo); + } + + std::list > aCoords; + + aP2d.GetCoords(aCoords); + + if (aCoords.size() == 1) { + AddParam(theParams, "Number of points", aCoords.front().size()/2); + } + } else { + // There are more than 1 curve. + Standard_Integer aNbCurves = aNames->Length(); + Standard_Integer i; + std::list > aCoords; + + AddParam(theParams, "Number of curves", aNbCurves); + aP2d.GetCoords(aCoords); + + Standard_Integer aNbCoords = aCoords.size(); + std::list >::const_iterator + anIt = aCoords.begin(); + + for (i = 0; i < aNbCurves; i++) { + TCollection_AsciiString aName("Curve "); + TCollection_ExtendedString + aValue(aNames->Value(aNames->Lower() + i)); + + aName.AssignCat(i + 1); + + if (anIt != aCoords.end()) { + aValue.AssignCat(" ("); + aValue.AssignCat(Standard_Integer(anIt->size())); + aValue.AssignCat(" points)"); + anIt++; + } + + AddParam(theParams, aName.ToCString(), aValue); + } + } + } + + if (aType == POLYLINE2D_PLN_COORDS) { + Handle(TColStd_HArray1OfReal) aPln = aP2d.GetWorkingPlaneDbls(); + + if (aPln.IsNull() == Standard_False && aPln->Length() == 9) { + Standard_Integer i = aPln->Lower(); + + AddParam( theParams, "Origin") + << aPln->Value(i) << " " + << aPln->Value(i + 1) << " " + << aPln->Value(i + 2); + AddParam( theParams, "OZ") + << aPln->Value(i + 3) << " " + << aPln->Value(i + 4) << " " + << aPln->Value(i + 5); + AddParam( theParams, "OX") + << aPln->Value(i + 6) << " " + << aPln->Value(i + 7) << " " + << aPln->Value(i + 8); + } + } else { + AddParam(theParams, "Working plane", aP2d.GetWorkingPlane(), "XOY"); + } + } + break; default: return false; } diff --git a/src/GEOMImpl/GEOMImpl_PolylineDriver.hxx b/src/GEOMImpl/GEOMImpl_PolylineDriver.hxx index 3f8165537..b3f89d91e 100644 --- a/src/GEOMImpl/GEOMImpl_PolylineDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_PolylineDriver.hxx @@ -80,6 +80,9 @@ Standard_EXPORT ~GEOMImpl_PolylineDriver() {}; Standard_EXPORT virtual bool GetCreationInformation(std::string& theOperationName, std::vector& params); +private: + + Standard_Integer MakePolyline2D(TFunction_Logbook& log) const; DEFINE_STANDARD_RTTI( GEOMImpl_PolylineDriver ) }; diff --git a/src/GEOMImpl/GEOMImpl_PolylineDumper.cxx b/src/GEOMImpl/GEOMImpl_PolylineDumper.cxx new file mode 100644 index 000000000..05fb9a61a --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PolylineDumper.cxx @@ -0,0 +1,251 @@ +// Copyright (C) 2007-2014 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 : GEOMImpl_PolylineDumper.cxx +// Author : Sergey KHROMOV +// Module : GEOM + + +#include "GEOMImpl_PolylineDumper.hxx" +#include "GEOMImpl_ICurvesOperations.hxx" + +#include + + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +GEOMImpl_PolylineDumper::GEOMImpl_PolylineDumper + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(TColStd_HArray1OfReal) &thePlnCoords) + : myCoords (theCoords), + myNames (theNames), + myTypes (theTypes), + myCloseds (theCloseds), + myPlnCoords (thePlnCoords), + myIsDone (Standard_False) +{ + init(); +} + + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +GEOMImpl_PolylineDumper::GEOMImpl_PolylineDumper + (const std::list > &theCoords, + const Handle(TColStd_HArray1OfExtendedString) &theNames, + const Handle(TColStd_HArray1OfByte) &theTypes, + const Handle(TColStd_HArray1OfByte) &theCloseds, + const Handle(GEOM_Object) &theWorkingPlane) + : myCoords (theCoords), + myNames (theNames), + myTypes (theTypes), + myCloseds (theCloseds), + myWorkingPlane (theWorkingPlane), + myIsDone (Standard_False) +{ + init(); +} + +//======================================================================= +// function : Dump +// purpose : +//======================================================================= +Standard_Boolean GEOMImpl_PolylineDumper::Dump + (const Handle(GEOM_Object) &theObject) +{ + if (theObject.IsNull()) { + return Standard_False; + } + + if (myIsDone) { + Handle(GEOM_Function) aFunction = theObject->GetLastFunction(); + GEOM::TPythonDump aPD(aFunction); + + aPD << myDescr; + aPD << theObject << " = pl.result("; + + if (myWorkingPlane.IsNull()) { + // Add coodinates of working plane. + Standard_Integer i; + + aPD << "["; + for (i = 0; i < 9; ++i) { + aPD << myPlnCoords->Value(myPlnCoords->Lower() + i); + + if (i < 8) { + aPD << ", "; + } + } + aPD << "]"; + } else { + aPD << myWorkingPlane; + } + + aPD << ")"; + } + + return myIsDone; +} + +//======================================================================= +// function : init +// purpose : +//======================================================================= +void GEOMImpl_PolylineDumper::init() +{ + // Check input parameters. + if (myCoords.empty() || myNames.IsNull() || + myTypes.IsNull() || myCloseds.IsNull()) { + // One or more input parameters are null or empty() + return; + } + + const Standard_Integer aNbSec = myCoords.size(); + + if (aNbSec != myNames->Length() || aNbSec != myTypes->Length() || + aNbSec != myCloseds->Length()) { + // Inconsistent data. + return; + } + + // Check the reference plane + if (myPlnCoords.IsNull()) { + if (myWorkingPlane.IsNull()) { + // Null working plane + return; + } + } else { + if (myWorkingPlane.IsNull() == Standard_False) { + // Ambiguous working plane + return; + } + + if (myPlnCoords->Length() != 9) { + // Invalid number of plane coordinates. + return; + } + } + + char *aSeparator = "\n\t"; + Standard_Integer i; + std::list >::const_iterator anIt = myCoords.begin(); + + myDescr += "pl = geompy.Polyline2D()"; + + // Add sections. + for (i = 0; i < aNbSec && anIt != myCoords.end(); ++i, ++anIt) { + myDescr += aSeparator; + myDescr += "pl.addSection("; + // Add name + myDescr += "\""; + myDescr += myNames->Value(myNames->Lower() + i) + "\", "; + // Add type + const Standard_Integer aType = myTypes->Value(myTypes->Lower() + i); + + switch (aType) { + case GEOMImpl_ICurvesOperations::Polyline: + myDescr += "GEOM.Polyline, "; + break; + case GEOMImpl_ICurvesOperations::Interpolation: + myDescr += "GEOM.Interpolation, "; + break; + default: + myDescr.Clear(); + return; + break; // NEVERREACHED + } + + // Add Closed flag. + if (myCloseds->Value(myCloseds->Lower() + i)) { + myDescr += "True"; + } else { + myDescr += "False"; + } + + // Add points. + const Standard_Integer aNbCoords = anIt->size(); + + if (aNbCoords > 0) { + if (aNbCoords % 2) { + // Odd number of coordinates. + myDescr.Clear(); + return; + } + + if (aNbCoords <= 4) { + // Add 2 points to the same command addSection. + myDescr += ", ["; + + std::list ::const_iterator aCIt = anIt->begin(); + + while (aCIt != anIt->end()) { + myDescr += *aCIt; + + if (++aCIt != anIt->end()) { + myDescr += ", "; + } + } + } else { + // Add points to a separate command addPoints. + // Add maximum 4 points in a command. + std::list ::const_iterator aCIt = anIt->begin(); + Standard_Integer aMaxNbCoord = 8; + Standard_Integer j = 1; + + myDescr += ")"; + myDescr += aSeparator; + myDescr += "pl.addPoints(["; + + while (aCIt != anIt->end()) { + myDescr += *aCIt; + + if (++aCIt != anIt->end()) { + if (j == aMaxNbCoord) { + // 4 points are added. Add a new command. + myDescr += "])"; + myDescr += aSeparator; + myDescr += "pl.addPoints(["; + j = 1; + } else { + myDescr += ", "; + j++; + } + } + } + } + + myDescr += "]"; + } + + myDescr += ")"; + } + + myDescr += aSeparator; + myIsDone = Standard_True; +} diff --git a/src/GEOMImpl/GEOMImpl_PolylineDumper.hxx b/src/GEOMImpl/GEOMImpl_PolylineDumper.hxx new file mode 100644 index 000000000..1fe396bfd --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PolylineDumper.hxx @@ -0,0 +1,132 @@ +// Copyright (C) 2007-2014 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 : GEOMImpl_PolylineDumper.h +// Author : Sergey KHROMOV + + +#ifndef _GEOMImpl_PolylineDumper_HXX_ +#define _GEOMImpl_PolylineDumper_HXX_ + + +#include "GEOM_GEOMImpl.hxx" + +#include + +#include +#include +#include + +#include + + +/** + * This is a helper class to form a dump of a polyline 2d curves creation + * algorithm. + */ +class GEOMIMPL_EXPORT GEOMImpl_PolylineDumper +{ + +public: + + /** + * This construcor initializes the object with 2D polyline creation + * parameters. + * + * \param theCoords the list of coordinates list. theCoordsList[0] + * is the coordinates list of the first section. theCoordsList[1] + * is for the second section etc. + * \param theNames the list of names. The order corresponds to theCoords. + * \param theTypes the list of curve types. The order corresponds to + * theCoords. + * \param theCloseds the list of Closed flags. The order corresponds to + * theCoords. + * \param thePlnCoords 9 double values, defining origin, + * OZ and OX directions of the working plane. + */ + GEOMImpl_PolylineDumper + (const std::list > &theCoords, + const Handle_TColStd_HArray1OfExtendedString &theNames, + const Handle_TColStd_HArray1OfByte &theTypes, + const Handle_TColStd_HArray1OfByte &theCloseds, + const Handle_TColStd_HArray1OfReal &thePlnCoords); + + /** + * This construcor initializes the object with 2D polyline creation + * parameters. + * + * \param theCoords the list of coordinates list. theCoordsList[0] + * is the coordinates list of the first section. theCoordsList[1] + * is for the second section etc. + * \param theNames the list of names. The order corresponds to theCoords. + * \param theTypes the list of curve types. The order corresponds to + * theCoords. + * \param theCloseds the list of Closed flags. The order corresponds to + * theCoords. + * \param theWorkingPlane planar Face or LCS(Marker) of the working plane. + */ + GEOMImpl_PolylineDumper + (const std::list > &theCoords, + const Handle_TColStd_HArray1OfExtendedString &theNames, + const Handle_TColStd_HArray1OfByte &theTypes, + const Handle_TColStd_HArray1OfByte &theCloseds, + const Handle_GEOM_Object &theWorkingPlane); + + /** + * This method returns Standard_True if the dump description is created + * successfully. + * + * \return Standard_True in case of success; Standard_False otherwise. + */ + Standard_Boolean IsDone() const + { return myIsDone; } + + /** + * This method performs dump of the polyline. + * + * \param theObject the newly created object. + * \return Standard_True in case of success; Standard_False otherwise. + */ + Standard_Boolean Dump(const Handle_GEOM_Object &theObject); + +protected: + + /** + * This method generates the description required for python dump. + * It is called from constructor. + */ + void init(); + +private: + + const std::list > &myCoords; + Handle_TColStd_HArray1OfExtendedString myNames; + Handle_TColStd_HArray1OfByte myTypes; + Handle_TColStd_HArray1OfByte myCloseds; + Handle_TColStd_HArray1OfReal myPlnCoords; + Handle_GEOM_Object myWorkingPlane; + Standard_Boolean myIsDone; + TCollection_ExtendedString myDescr; + +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx old mode 100755 new mode 100644 index 0bc7505c1..0ea9449e2 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -111,6 +111,8 @@ #define GEOM_ISOLINE 55 +#define GEOM_POLYLINE2D 56 + //GEOM_Function types #define COPY_WITH_REF 1 @@ -250,7 +252,9 @@ #define PARTITION_HALF 2 #define PARTITION_NO_SELF_INTERSECTIONS 3 -#define POLYLINE_POINTS 1 +#define POLYLINE_POINTS 1 +#define POLYLINE2D_PLN_COORDS 2 +#define POLYLINE2D_PLN_OBJECT 3 #define SPLINE_BEZIER 1 #define SPLINE_INTERPOLATION 2 diff --git a/src/GEOM_I/GEOM_ICurvesOperations_i.cc b/src/GEOM_I/GEOM_ICurvesOperations_i.cc index f1d2469c0..06d9b66d3 100644 --- a/src/GEOM_I/GEOM_ICurvesOperations_i.cc +++ b/src/GEOM_I/GEOM_ICurvesOperations_i.cc @@ -30,6 +30,9 @@ #include "GEOM_Engine.hxx" #include "GEOM_Object.hxx" +#include +#include + //============================================================================= /*! * constructor: @@ -667,3 +670,189 @@ GEOM::GEOM_Object_ptr GEOM_ICurvesOperations_i::Make3DSketcher return GetObject(anObject); } + +//============================================================================= +/*! + * MakePolyline2D + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_ICurvesOperations_i::MakePolyline2D + (const GEOM::ListOfListOfDouble &theCoordsList, + const GEOM::string_array &theNamesList, + const GEOM::short_array &theTypesList, + const GEOM::ListOfBool &theClosedList, + const GEOM::ListOfDouble &theWorkingPlane) +{ + //Set a not done flag + GetOperations()->SetNotDone(); + + // Convert input data + Handle(TColStd_HArray1OfExtendedString) aNames = + ConvertStringArray(theNamesList); + Handle(TColStd_HArray1OfByte) aTypes = + ConvertEnumArray(theTypesList); + Handle(TColStd_HArray1OfByte) aCloseds = + ConvertBoolArray(theClosedList); + std::list > aCoords; + + ConvertListListDouble(theCoordsList, aCoords); + + Handle(TColStd_HArray1OfReal) aWorkingPlane; + const int n = theWorkingPlane.length(); + int i; + + if (n > 0) { + aWorkingPlane = new TColStd_HArray1OfReal(1, n); + + for (i = 0; i < n; i++) { + aWorkingPlane->SetValue(i + 1, theWorkingPlane[i]); + } + } + + // Make Polyline + Handle(GEOM_Object) anObject = GetOperations()->MakePolyline2D + (aCoords, aNames, aTypes, aCloseds, aWorkingPlane); + + if (!GetOperations()->IsDone() || anObject.IsNull()) { + return GEOM::GEOM_Object::_nil(); + } + + return GetObject(anObject); +} + +//============================================================================= +/*! + * MakePolylineOnPlane + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_ICurvesOperations_i::MakePolyline2DOnPlane + (const GEOM::ListOfListOfDouble &theCoordsList, + const GEOM::string_array &theNamesList, + const GEOM::short_array &theTypesList, + const GEOM::ListOfBool &theClosedList, + GEOM::GEOM_Object_ptr theWorkingPlane) +{ + //Set a not done flag + GetOperations()->SetNotDone(); + + // Convert input data + Handle(TColStd_HArray1OfExtendedString) aNames = + ConvertStringArray(theNamesList); + Handle(TColStd_HArray1OfByte) aTypes = + ConvertEnumArray(theTypesList); + Handle(TColStd_HArray1OfByte) aCloseds = + ConvertBoolArray(theClosedList); + std::list > aCoords; + Handle(GEOM_Object) aWorkingPlane = + GetObjectImpl(theWorkingPlane); + + ConvertListListDouble(theCoordsList, aCoords); + + // Make Polyline + Handle(GEOM_Object) anObject = GetOperations()->MakePolyline2DOnPlane + (aCoords, aNames, aTypes, aCloseds, aWorkingPlane); + + if (!GetOperations()->IsDone() || anObject.IsNull()) { + return GEOM::GEOM_Object::_nil(); + } + + return GetObject(anObject); +} + +//============================================================================= +/*! + * ConvertEnumArray + */ +//============================================================================= +Handle(TColStd_HArray1OfByte) GEOM_ICurvesOperations_i::ConvertEnumArray + (const GEOM::short_array &theInArray) +{ + Handle(TColStd_HArray1OfByte) anOutArray; + const int n = theInArray.length(); + int i; + + if (n <= 0) { + return anOutArray; + } + + anOutArray = new TColStd_HArray1OfByte(1, n); + + for (i = 0; i < n; i++) { + bool isOK = true; + GEOMImpl_ICurvesOperations::CurveType aType; + + switch(theInArray[i]) { + case GEOM::Polyline: + aType = GEOMImpl_ICurvesOperations::Polyline; + break; + case GEOM::Bezier: + aType = GEOMImpl_ICurvesOperations::Bezier; + break; + case GEOM::Interpolation: + aType = GEOMImpl_ICurvesOperations::Interpolation; + break; + default: + isOK = false; + break; + } + + if (isOK) { + anOutArray->SetValue(i + 1, aType); + } else { + anOutArray.Nullify(); + break; + } + } + + return anOutArray; +} + +//============================================================================= +/*! + * ConvertBoolArray + */ +//============================================================================= +Handle(TColStd_HArray1OfByte) GEOM_ICurvesOperations_i::ConvertBoolArray + (const GEOM::ListOfBool &theInArray) +{ + Handle(TColStd_HArray1OfByte) anOutArray; + const int n = theInArray.length(); + int i; + + if (n <= 0) { + return anOutArray; + } + + anOutArray = new TColStd_HArray1OfByte(1, n); + + for (i = 0; i < n; i++) { + anOutArray->SetValue(i + 1, theInArray[i]); + } + + return anOutArray; +} + +//============================================================================= +/*! + * ConvertListListDouble + */ +//============================================================================= +void GEOM_ICurvesOperations_i::ConvertListListDouble + (const GEOM::ListOfListOfDouble &theInList, + std::list > &theOutList) +{ + const int n = theInList.length(); + int i; + std::list anEmptyList; + + for (i = 0; i < n; i++) { + theOutList.push_back(anEmptyList); + + const int m = theInList[i].length(); + int j; + + for (j = 0; j < m; j++) { + theOutList.back().push_back(theInList[i][j]); + } + } +} diff --git a/src/GEOM_I/GEOM_ICurvesOperations_i.hh b/src/GEOM_I/GEOM_ICurvesOperations_i.hh index c08cb0156..90cbb2114 100644 --- a/src/GEOM_I/GEOM_ICurvesOperations_i.hh +++ b/src/GEOM_I/GEOM_ICurvesOperations_i.hh @@ -112,8 +112,35 @@ class GEOM_I_EXPORT GEOM_ICurvesOperations_i : GEOM::GEOM_Object_ptr Make3DSketcher (const GEOM::ListOfDouble& theCoordinates); + GEOM::GEOM_Object_ptr MakePolyline2D + (const GEOM::ListOfListOfDouble &theCoordsList, + const GEOM::string_array &theNamesList, + const GEOM::short_array &theTypesList, + const GEOM::ListOfBool &theClosedList, + const GEOM::ListOfDouble &theWorkingPlane); + + GEOM::GEOM_Object_ptr MakePolyline2DOnPlane + (const GEOM::ListOfListOfDouble &theCoordsList, + const GEOM::string_array &theNamesList, + const GEOM::short_array &theTypesList, + const GEOM::ListOfBool &theClosedList, + GEOM::GEOM_Object_ptr theWorkingPlane); + ::GEOMImpl_ICurvesOperations* GetOperations() { return (::GEOMImpl_ICurvesOperations*)GetImpl(); } + +private: + + Handle(TColStd_HArray1OfByte) + ConvertEnumArray(const GEOM::short_array &theInArray); + + Handle(TColStd_HArray1OfByte) + ConvertBoolArray(const GEOM::ListOfBool &theInArray); + + void ConvertListListDouble + (const GEOM::ListOfListOfDouble &theCoordsList, + std::list > &theCoords); + }; #endif diff --git a/src/GEOM_I/GEOM_IHealingOperations_i.cc b/src/GEOM_I/GEOM_IHealingOperations_i.cc index af7cb5cd4..51fe6c46e 100644 --- a/src/GEOM_I/GEOM_IHealingOperations_i.cc +++ b/src/GEOM_I/GEOM_IHealingOperations_i.cc @@ -78,25 +78,6 @@ Handle(TColStd_HArray1OfInteger) GEOM_IHealingOperations_i::Convert return anOutArray; } -//============================================================================= -/*! - * Convert - */ -//============================================================================= -Handle(TColStd_HArray1OfExtendedString) GEOM_IHealingOperations_i::Convert - (const GEOM::string_array& theInArray) -{ - Handle(TColStd_HArray1OfExtendedString) anOutArray; - int n = theInArray.length(); - if ( n <= 0 ) - return anOutArray; - anOutArray = new TColStd_HArray1OfExtendedString( 1, n ); - for ( int i = 0; i < n; i++ ) - anOutArray->SetValue( i+1, TCollection_ExtendedString( theInArray[i].in() ) ); - - return anOutArray; -} - //============================================================================= /*! * ProcessShape @@ -125,7 +106,8 @@ GEOM::GEOM_Object_ptr GEOM_IHealingOperations_i::ProcessShape (GEOM::GEOM_Object // Perform Handle(GEOM_Object) aNewObject = GetOperations()->ShapeProcess( anObject, - Convert( theOperations ), Convert( theParams ), Convert( theValues ) ); + ConvertStringArray( theOperations ), ConvertStringArray( theParams ), + ConvertStringArray( theValues ) ); if ( !GetOperations()->IsDone() || aNewObject.IsNull() ) return aGEOMObject._retn(); diff --git a/src/GEOM_I/GEOM_IHealingOperations_i.hh b/src/GEOM_I/GEOM_IHealingOperations_i.hh index 8b30c9530..091358771 100644 --- a/src/GEOM_I/GEOM_IHealingOperations_i.hh +++ b/src/GEOM_I/GEOM_IHealingOperations_i.hh @@ -33,9 +33,6 @@ #include "GEOMImpl_IHealingOperations.hxx" -#include -#include - class GEOM_I_EXPORT GEOM_IHealingOperations_i : public virtual POA_GEOM::GEOM_IHealingOperations, public virtual GEOM_IOperations_i @@ -101,7 +98,6 @@ class GEOM_I_EXPORT GEOM_IHealingOperations_i : ::GEOMImpl_IHealingOperations* GetOperations() { return (::GEOMImpl_IHealingOperations*)GetImpl(); } private: - Handle(TColStd_HArray1OfExtendedString) Convert( const GEOM::string_array& ); Handle(TColStd_HArray1OfInteger) Convert( const GEOM::short_array& ); }; diff --git a/src/GEOM_I/GEOM_IOperations_i.cc b/src/GEOM_I/GEOM_IOperations_i.cc index 12184fd17..9cb5b8469 100644 --- a/src/GEOM_I/GEOM_IOperations_i.cc +++ b/src/GEOM_I/GEOM_IOperations_i.cc @@ -237,3 +237,28 @@ void GEOM_IOperations_i::UpdateGUIForObject(GEOM::GEOM_Object_ptr theObj) } } } + +//============================================================================= +/*! + * ConvertStringArray + */ +//============================================================================= +Handle(TColStd_HArray1OfExtendedString) GEOM_IOperations_i::ConvertStringArray + (const GEOM::string_array &theInArray) +{ + Handle(TColStd_HArray1OfExtendedString) anOutArray; + const int n = theInArray.length(); + int i; + + if (n <= 0) { + return anOutArray; + } + + anOutArray = new TColStd_HArray1OfExtendedString( 1, n ); + + for (i = 0; i < n; i++) { + anOutArray->SetValue(i + 1, TCollection_ExtendedString(theInArray[i].in())); + } + + return anOutArray; +} diff --git a/src/GEOM_I/GEOM_IOperations_i.hh b/src/GEOM_I/GEOM_IOperations_i.hh index 1d5b7fd56..b82b36c68 100644 --- a/src/GEOM_I/GEOM_IOperations_i.hh +++ b/src/GEOM_I/GEOM_IOperations_i.hh @@ -52,9 +52,6 @@ class GEOM_I_EXPORT GEOM_IOperations_i : public virtual POA_GEOM::GEOM_IOperatio virtual GEOM::GEOM_Object_ptr GetObject(Handle(GEOM_Object) theObject); virtual Handle(GEOM_Object) GetObjectImpl(GEOM::GEOM_Object_ptr theObject); - virtual Handle(TColStd_HSequenceOfTransient) - GetListOfObjectsImpl(const GEOM::ListOfGO& theObjects); - virtual void StartOperation(); virtual void FinishOperation(); @@ -66,6 +63,14 @@ class GEOM_I_EXPORT GEOM_IOperations_i : public virtual POA_GEOM::GEOM_IOperatio virtual void UpdateGUIForObject(GEOM::GEOM_Object_ptr theObj); +protected: + + Handle(TColStd_HSequenceOfTransient) + GetListOfObjectsImpl(const GEOM::ListOfGO& theObjects); + + Handle(TColStd_HArray1OfExtendedString) + ConvertStringArray(const GEOM::string_array &theInArray); + private: ::GEOM_IOperations* _impl; diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index c0cd25a60..27b194dc2 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -256,7 +256,7 @@ import math import os import functools -from salome.geom.gsketcher import Sketcher3D, Sketcher2D +from salome.geom.gsketcher import Sketcher3D, Sketcher2D, Polyline2D # service function def _toListOfNames(_names, _size=-1): @@ -2667,6 +2667,25 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): sk = Sketcher3D (self) return sk + ## Obtain a 2D polyline creation interface + # @return An instance of @ref gsketcher.Polyline2D "Polyline2D" interface + # + # @ref tui_3dsketcher_page "Example" + def Polyline2D (self): + """ + Obtain a 2D polyline creation interface. + + Example of usage: + pl = geompy.Polyline2D() + pl.addSection("section 1", GEOM.Polyline, True) + pl.addPoints(0, 0, 10, 0, 10, 10) + pl.addSection("section 2", GEOM.Interpolation, False) + pl.addPoints(20, 0, 30, 0, 30, 10) + resultObj = pl.result(WorkingPlane) + """ + pl = Polyline2D (self) + return pl + # end of l3_sketcher ## @} diff --git a/src/GEOM_SWIG/gsketcher.py b/src/GEOM_SWIG/gsketcher.py index 783bfffca..004e8e63e 100644 --- a/src/GEOM_SWIG/gsketcher.py +++ b/src/GEOM_SWIG/gsketcher.py @@ -1211,3 +1211,145 @@ class Sketcher2D: self.myCommand = "Sketcher" self.geompyD._autoPublish(face, theName, "face") return face + +## An interface to build a 2D polyline step-by-step. The polyline can contain +# several sections. Each section represents a list of 2d points. As well it +# has a name, curve type, either polyline or interpolation (BSpline curve) and +# Closed flag. +# Use geompy.Polyline2D() method to obtain an instance of this class. +# @ingroup sketcher +class Polyline2D: + """ + An interface to build a 2D polyline step-by-step. The polyline can contain + several sections. Each section represents a list of 2d points. As well it + has a name, curve type, either polyline or interpolation (BSpline curve) and + Closed flag. + Use geompy.Polyline2D() method to obtain an instance of this class. + + Example of usage: + pl = geompy.Polyline2D() + pl.addSection("section 1", GEOM.Polyline, True, [0, 0, 10, 0, 10, 10]) + pl.addSection("section 2", GEOM.Interpolation, False) + pl.addPoints([20, 0, 30, 0, 30, 10]) + resultObj = pl.result(WorkingPlane) + """ + + def __init__(self, geompyD): + self.geompyD = geompyD + self.myNameList = [] + self.myTypeList = [] + self.myClosedList = [] + self.myCoordsList = [] + pass + + ## Add a new section to the polyline. + # + # @param theName the name + # @param theType the type. It can have either CORBA enumeration type + # GEOM.curve_type or a value of type long. Possible input values + # are: GEOM.Polyline(0) and GEOM.Interpolation(2). + # @param theClosed True for closed section; False otherwise + # @param thePoints the list of 2D points coordinates in the form: + # [x1, y1, x2, y2, ..., xN, yN] for N points. + def addSection(self, theName, theType, theClosed, thePoints = None): + """ + Add a new section to the polyline. + + Parameters: + theName the name + theType the type. It can have either CORBA enumeration type + GEOM.curve_type or a value of type long. Possible input + values are: GEOM.Polyline(0) and GEOM.Interpolation(2). + theClosed True for closed section; False otherwise + thePoints the list of 2D points coordinates in the form: + [x1, y1, x2, y2, ..., xN, yN] for N points. + + Example of usage: + pl = geompy.Polyline2D() + pl.addSection("section 1", GEOM.Polyline, True, [0, 0, 10, 0, 10, 10]) + resultObj = pl.result(WorkingPlane) + """ + from salome.geom.geomBuilder import EnumToLong + self.myNameList.append(theName) + self.myTypeList.append(EnumToLong(theType)) + self.myClosedList.append(theClosed) + if thePoints is None: + self.myCoordsList.append([]) + else: + self.myCoordsList.append(thePoints) + pass + + ## Add a points to the last added section of the polyline. If there are + # no sections in the polyline it does nothing. + # + # @param thePoints the list of 2D points coordinates in the form: + # [x1, y1, x2, y2, ..., xN, yN] for N points. + def addPoints(self, thePoints): + """ + Add a points to the last added section of the polyline. If there are + no sections in the polyline it does nothing. + + Parameters: + thePoints the list of 2D points coordinates in the form: + [x1, y1, x2, y2, ..., xN, yN] for N points. + + Example of usage: + pl = geompy.Polyline2D() + pl.addSection("section 1", GEOM.Polyline, True) + pl.addPoints([0, 0, 10, 0, 10, 10]) + pl.addPoints([20, 0, 30, 0, 30, 10]) + resultObj = pl.result(WorkingPlane) + """ + if self.myNameList: + self.myCoordsList[-1].extend(thePoints) + pass + + ## Obtain the 2D polyline result as a wire or a compound of wires in case + # of several sections defined. + # + # @param theWorkingPlane - current Working Plane used for this 2D polyline + # @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_Object, containing the created shape. + def result(self, theWorkingPlane=[0, 0, 0, 0, 0, 1, 1, 0, 0], theName=None): + """ + Obtain the 2D polyline result as a wire or a compound of wires in case + of several sections defined. + + Parameters: + theWorkingPlane current Working Plane used for this 2D polyline + 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_Object, containing the created shape. + + Example of usage: + pl = geompy.Polyline2D() + pl.addSection("section 1", GEOM.Polyline, True, [0, 0, 10, 0, 10, 10]) + pl.addSection("section 2", GEOM.Interpolation, False) + pl.addPoints([20, 0, 30, 0, 30, 10]) + resultObj = pl.result(WorkingPlane) + """ + from salome.geom.geomBuilder import RaiseIfFailed + import GEOM + if isinstance(theWorkingPlane, list): + aResult = self.geompyD.CurvesOp.MakePolyline2D( + self.myCoordsList, self.myNameList, self.myTypeList, + self.myClosedList, theWorkingPlane) + if isinstance(theWorkingPlane, GEOM._objref_GEOM_Object): + aResult = self.geompyD.CurvesOp.MakePolyline2DOnPlane( + self.myCoordsList, self.myNameList, self.myTypeList, + self.myClosedList, theWorkingPlane) + + self.myNameList = [] + self.myTypeList = [] + self.myClosedList = [] + self.myCoordsList = [] + RaiseIfFailed("Polyline2D.result", self.geompyD.CurvesOp) + self.geompyD._autoPublish(aResult, theName, "polyline") + + return aResult diff --git a/src/OperationGUI/CMakeLists.txt b/src/OperationGUI/CMakeLists.txt index f176f9d0b..0f8ae114e 100755 --- a/src/OperationGUI/CMakeLists.txt +++ b/src/OperationGUI/CMakeLists.txt @@ -45,11 +45,6 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ) -IF(SALOME_GEOM_DEBUG_CC) - # for debug purposes, to be removed - INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/CurveCreator) -ENDIF() - # additional preprocessor / compiler flags ADD_DEFINITIONS( ${CAS_DEFINITIONS} @@ -61,10 +56,6 @@ ADD_DEFINITIONS( SET(_link_LIBRARIES GEOMBase ) -IF(SALOME_GEOM_DEBUG_CC) - # for debug purposes, to be removed - LIST(APPEND _link_LIBRARIES CurveCreator) -ENDIF() # --- resources --- diff --git a/src/OperationGUI/OperationGUI.cxx b/src/OperationGUI/OperationGUI.cxx index c84dc1cf3..a705e0ae2 100644 --- a/src/OperationGUI/OperationGUI.cxx +++ b/src/OperationGUI/OperationGUI.cxx @@ -27,15 +27,8 @@ #include #include "GeometryGUI_Operations.h" -#include #include -#include #include -#include - -#include -#include -#include #include "OperationGUI_PartitionDlg.h" // Method PARTITION #include "OperationGUI_ArchimedeDlg.h" // Method ARCHIMEDE @@ -47,13 +40,6 @@ #include "OperationGUI_GetSharedShapesDlg.h" #include "OperationGUI_ExtrudedFeatureDlg.h" // Methods EXTRUDED BOSS / CUT -#ifdef DEBUG_CURVE_CREATOR -// for debug purposes, to be removed -#include "CurveCreator_Widget.h" -#include -#include -#endif - //======================================================================= // function : OperationGUI() // purpose : Constructor @@ -95,36 +81,6 @@ bool OperationGUI::OnGUIEvent (int theCommandID, SUIT_Desktop* parent) case GEOMOp::OpExtrudedCut: (new OperationGUI_ExtrudedFeatureDlg (CUT, getGeometryGUI(), parent))->show(); break; case GEOMOp::OpFillet1d: (new OperationGUI_Fillet1d2dDlg (getGeometryGUI(), parent, true))->show(); break; case GEOMOp::OpFillet2d: (new OperationGUI_Fillet1d2dDlg (getGeometryGUI(), parent, false))->show(); break; -#ifdef DEBUG_CURVE_CREATOR - // for debug purposes, to be removed - case GEOMOp::OpCurveCreator: - { - static CurveCreator_Curve *aStaticCurve = NULL; - - if (aStaticCurve == NULL) { - aStaticCurve = new CurveCreator_Curve(CurveCreator::Dim2d); - } - if (CurveCreator::Dim2d == aStaticCurve->getDimension()) { - OCCViewer_ViewWindow* vw = (OCCViewer_ViewWindow*)getGeometryGUI()->getApp()->activeViewManager()->getActiveView(); - vw->onTopView(); - } - - QDialog *aDialog = new QDialog(parent); - QVBoxLayout *aMainLO = new QVBoxLayout; - QPushButton *aQuitButton = new QPushButton(tr("Close")); - CurveCreator_Widget *aWidget = - new CurveCreator_Widget (aDialog, aStaticCurve); - - connect(aQuitButton, SIGNAL(clicked()), aDialog, SLOT(close())); - aMainLO->addWidget(aWidget); - aMainLO->addWidget(aQuitButton); - - aDialog->setLayout(aMainLO); - aDialog->setAttribute(Qt::WA_DeleteOnClose); - aDialog->show(); - } - break; -#endif default: app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID)); } diff --git a/src/SKETCHER/CMakeLists.txt b/src/SKETCHER/CMakeLists.txt index 257c2dd1e..ef7e87480 100755 --- a/src/SKETCHER/CMakeLists.txt +++ b/src/SKETCHER/CMakeLists.txt @@ -43,13 +43,16 @@ SET(_link_LIBRARIES # --- headers --- SET(SKETCHER_HEADERS + Sketcher.hxx Sketcher_Profile.hxx + Sketcher_Utils.hxx ) # --- sources --- SET(SKETCHER_SOURCES Sketcher_Profile.cxx + Sketcher_Utils.cxx ) # --- rules --- diff --git a/src/CurveCreator/CurveCreator_Listener.hxx b/src/SKETCHER/Sketcher.hxx old mode 100755 new mode 100644 similarity index 53% rename from src/CurveCreator/CurveCreator_Listener.hxx rename to src/SKETCHER/Sketcher.hxx index 4fd4a29fa..09602cee5 --- a/src/CurveCreator/CurveCreator_Listener.hxx +++ b/src/SKETCHER/Sketcher.hxx @@ -1,4 +1,7 @@ -// Copyright (C) 2013-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 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 @@ -17,25 +20,20 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#ifndef CURVE_CREATOR_LISTENER_HXX -#define CURVE_CREATOR_LISTENER_HXX - -class CurveCreator_Listener -{ -public: - CurveCreator_Listener(void){}; - virtual ~CurveCreator_Listener(void){}; - - virtual void pointChanged( int theSection, int thePoint ){} - virtual void pointRemoved( int theSection, int theFirstPoint, int thePointCnt ){} - virtual void pointInserted( int theSection, int theIndx ){} +// File : Sketcher.hxx +// Author : Sergey KHROMOV - virtual void sectionClosed( int theSection, bool isClosed ){} - virtual void sectionAdded( int theSection ){} - virtual void sectionRemoved( int theSection ){} - virtual void sectionTypeChanged( int theSection ){} +#ifndef _SKETCHER_HXX_ +#define _SKETCHER_HXX_ - virtual void curveChanged(){} -}; +#if defined WIN32 +# if defined SKETCHER_SALOME_EXPORTS || defined SKETCHER_EXPORTS || defined GEOMSketcher_EXPORTS || defined GEOMSKETCHER_EXPORTS +# define SKETCHER_SALOME_EXPORT _declspec( dllexport ) +# else +# define SKETCHER_SALOME_EXPORT _declspec( dllimport ) +# endif +#else +# define SKETCHER_SALOME_EXPORT +#endif -#endif \ No newline at end of file +#endif // SKETCHER_HXX \ No newline at end of file diff --git a/src/SKETCHER/Sketcher_Profile.hxx b/src/SKETCHER/Sketcher_Profile.hxx index ed792f83b..8d36b639b 100644 --- a/src/SKETCHER/Sketcher_Profile.hxx +++ b/src/SKETCHER/Sketcher_Profile.hxx @@ -23,16 +23,12 @@ // File : Sketcher_Profile.h // Author : Damien COQUERET -#if defined WIN32 -# if defined SKETCHER_SALOME_EXPORTS || defined SKETCHER_EXPORTS || defined GEOMSketcher_EXPORTS || defined GEOMSKETCHER_EXPORTS -# define SKETCHER_SALOME_EXPORT _declspec( dllexport ) -# else -# define SKETCHER_SALOME_EXPORT _declspec( dllimport ) -# endif -#else -# define SKETCHER_SALOME_EXPORT -#endif +#ifndef _Sketcher_Profile_HXX_ +#define _Sketcher_Profile_HXX_ + + +#include "Sketcher.hxx" #include #include #include @@ -63,3 +59,5 @@ private: private: TCollection_AsciiString myCommand; }; + +#endif diff --git a/src/SKETCHER/Sketcher_Utils.cxx b/src/SKETCHER/Sketcher_Utils.cxx new file mode 100644 index 000000000..725a985cf --- /dev/null +++ b/src/SKETCHER/Sketcher_Utils.cxx @@ -0,0 +1,187 @@ +// Copyright (C) 2007-2014 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 : Sketcher_Utils.cxx +// Author : Sergey KHROMOV +// Module : GEOM + + +#include "Sketcher_Utils.hxx" + +#include +#include +#include +#include +#include +#include +#include + +const double POINT_CONFUSION_TOLERANCE = 0.0001; + + +//======================================================================= +// function : MakePolyline +// purpose : +//======================================================================= +TopoDS_Shape Sketcher_Utils::MakePolyline + (const std::list &theCoords2D, + const Standard_Boolean IsClosed, + const gp_Ax3 &thePlane) +{ + std::list aPoints; + TopoDS_Shape aResult; + + To3D(theCoords2D, thePlane, aPoints); + + Standard_Integer aNbPnts = aPoints.size(); + + if (aNbPnts > 1) { + if (IsClosed && + aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) { + // The polyline should be closed, first and last points are confused. + // Remove the last point. + aPoints.pop_back(); + --aNbPnts; + } + } + + if (aNbPnts == 1) { + // The result is vertex. + aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex(); + } else if (aNbPnts > 1) { + // There are several points. Make a polyline. + std::list ::const_iterator anIter = aPoints.begin(); + TopoDS_Vertex aVtxFirst = + BRepBuilderAPI_MakeVertex(*anIter).Vertex(); + TopoDS_Vertex aVtx[2]; + TopoDS_Edge aSegment; + BRepBuilderAPI_MakeWire aMkWire; + + aVtx[0] = aVtxFirst; + + for (++anIter; anIter != aPoints.end(); ++anIter) { + aVtx[1] = BRepBuilderAPI_MakeVertex(*anIter).Vertex(); + aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtx[1]).Edge(); + aMkWire.Add(aSegment); + aVtx[0] = aVtx[1]; + } + + if (IsClosed) { + // Create a closing segment. + aSegment = BRepBuilderAPI_MakeEdge(aVtx[0], aVtxFirst).Edge(); + aMkWire.Add(aSegment); + } + + aResult = aMkWire.Wire(); + } + + return aResult; +} + +//======================================================================= +// function : MakeInterpolation +// purpose : +//======================================================================= +TopoDS_Shape Sketcher_Utils::MakeInterpolation + (const std::list &theCoords2D, + const Standard_Boolean IsClosed, + const gp_Ax3 &thePlane) +{ + std::list aPoints; + TopoDS_Shape aResult; + + To3D(theCoords2D, thePlane, aPoints); + + Standard_Integer aNbPnts = aPoints.size(); + + if (aNbPnts > 1) { + if (IsClosed && + aPoints.front().IsEqual(aPoints.back(), POINT_CONFUSION_TOLERANCE)) { + // The polyline should be closed, first and last points are confused. + // Remove the last point. + aPoints.pop_back(); + --aNbPnts; + } + } + + if (aNbPnts == 1) { + // The result is vertex. + aResult = BRepBuilderAPI_MakeVertex(aPoints.front()).Vertex(); + } else if (aNbPnts > 1) { + std::list ::const_iterator anIter = aPoints.begin(); + Handle(TColgp_HArray1OfPnt) aHCurvePoints = + new TColgp_HArray1OfPnt(1, aNbPnts); + Standard_Integer i; + + for (i = 1; anIter != aPoints.end(); ++anIter, ++i) { + aHCurvePoints->SetValue(i, *anIter); + } + + // Compute BSpline + Standard_Real aTol = Precision::Confusion(); + GeomAPI_Interpolate aGBC(aHCurvePoints, IsClosed, aTol); + + aGBC.Perform(); + + if (aGBC.IsDone()) { + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(aGBC.Curve()).Edge(); + aResult = BRepBuilderAPI_MakeWire(anEdge).Wire(); + } + } + + return aResult; +} + +//======================================================================= +// function : To3D +// purpose : +//======================================================================= +void Sketcher_Utils::To3D(const std::list &theCoords2D, + const gp_Ax3 &thePlane, + std::list &thePoints) +{ + thePoints.clear(); + + if (theCoords2D.empty() || theCoords2D.size() % 2 == 1) { + // Odd number of coordinates or empty list. Invalid case. + return; + } + + std::list ::const_iterator anIter = theCoords2D.begin(); + Standard_Real aX = *anIter; + Standard_Real aY = *(++anIter); + gp_Pnt aPLast = ElSLib::PlaneValue (aX, aY, thePlane); + gp_Pnt aPnt; + + thePoints.push_back(aPLast); + + for (++anIter; anIter != theCoords2D.end(); ++anIter) { + aX = *anIter; + aY = *(++anIter); + aPnt = ElSLib::PlaneValue (aX, aY, thePlane); + + if (!aPLast.IsEqual(aPnt, POINT_CONFUSION_TOLERANCE)) { + thePoints.push_back(aPnt); + aPLast = aPnt; + } + } +} diff --git a/src/SKETCHER/Sketcher_Utils.hxx b/src/SKETCHER/Sketcher_Utils.hxx new file mode 100644 index 000000000..75360111d --- /dev/null +++ b/src/SKETCHER/Sketcher_Utils.hxx @@ -0,0 +1,103 @@ +// Copyright (C) 2007-2014 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 : Sketcher_Utils.h +// Author : Sergey KHROMOV + + +#ifndef _Sketcher_Utils_HXX_ +#define _Sketcher_Utils_HXX_ + + +#include "Sketcher.hxx" + +#include +#include + +#include + + +class gp_Ax3; + + +/** + * This class represents a set of utils needed to compute sketcher geometry. + */ +class SKETCHER_SALOME_EXPORT Sketcher_Utils +{ + +public: + + /** + * This method makes a shape from the list of 2D coordinates on the working + * plane. The result represents a vertex if there is only one point + * in the contour. If there are more then one points the result is a wire + * consisting of linear segments between points. It is either closed or not + * depending on the flag IsClosed. In case of failure the result is a null + * shape. + * + * \param theCoords2D is the list of coordinates in the form x1, y1, x2, y2, + * ..., xN, yN for N 2D points. + * \param IsClosed if Standard_True the first and last points are connected + * to form the closed contour. + * \param thePlane the working plane coordinate system. + * \return the result polyline. + */ + static TopoDS_Shape MakePolyline(const std::list &theCoords2D, + const Standard_Boolean IsClosed, + const gp_Ax3 &thePlane); + + /** + * This method makes a shape from the list of 2D coordinates on the working + * plane. The result represents a vertex if there is only one point + * in the contour. If there are more then one points the result is a wire + * consisting of a points interpolation BSpline curve. It is either closed + * or not depending on the flag IsClosed. In case of failure the result is + * a null shape. + * + * \param theCoords2D is the list of coordinates in the form x1, y1, x2, y2, + * ..., xN, yN for N 2D points. + * \param IsClosed if Standard_True the first and last points are connected + * to form the closed contour. + * \param thePlane the working plane coordinate system. + * \return the result interpolation wire. + */ + static TopoDS_Shape MakeInterpolation(const std::list &theCoords2D, + const Standard_Boolean IsClosed, + const gp_Ax3 &thePlane); + + /** + * This method converts the list of 2D point coordinates into 3D points + * basing on the working plane. The result list contains not confused points. + * + * \param theCoords2D is the list of coordinates in the form x1, y1, x2, y2, + * ..., xN, yN for N 2D points. + * \param thePlane the working plane coordinate system. + * \param thePoints the list of 3D points. + */ + static void To3D(const std::list &theCoords2D, + const gp_Ax3 &thePlane, + std::list &thePoints); + +}; + +#endif -- 2.30.2