From cb234e246225d575d6682ca4587e54b5f6f30497 Mon Sep 17 00:00:00 2001 From: vsr Date: Tue, 8 Dec 2009 12:05:55 +0000 Subject: [PATCH] Merge from V5_1_3_BR branch (07/12/09) --- adm_local/unix/config_files/check_qt.m4 | 2 + doc/salome/gui/GEOM/doxyfile_py.in | 2 +- .../gui/GEOM/images/custom_point_marker.png | Bin 0 -> 1058 bytes doc/salome/gui/GEOM/images/dialog.png | Bin 13630 -> 7626 bytes doc/salome/gui/GEOM/images/image167.png | Bin 22431 -> 18233 bytes doc/salome/gui/GEOM/images/image168.png | Bin 0 -> 21600 bytes .../gui/GEOM/images/point_marker_dlg1.png | Bin 0 -> 8927 bytes .../gui/GEOM/images/point_marker_dlg2.png | Bin 0 -> 8742 bytes .../gui/GEOM/images/std_point_marker.png | Bin 0 -> 1546 bytes doc/salome/gui/GEOM/input/creating_point.doc | 26 +- doc/salome/gui/GEOM/input/isolines.doc | 4 +- .../GEOM/input/modify_location_operation.doc | 7 +- doc/salome/gui/GEOM/input/point_marker.doc | 56 + .../input/remove_extra_edges_operation.doc | 4 +- .../gui/GEOM/input/sewing_operation.doc | 2 +- .../gui/GEOM/input/tui_viewing_geom_objs.doc | 19 +- .../gui/GEOM/input/viewing_geom_obj.doc | 2 + idl/GEOM_Gen.idl | 108 +- resources/Makefile.am | 13 + resources/marker_1.png | Bin 0 -> 239 bytes resources/marker_10.png | Bin 0 -> 333 bytes resources/marker_11.png | Bin 0 -> 237 bytes resources/marker_12.png | Bin 0 -> 234 bytes resources/marker_13.png | Bin 0 -> 234 bytes resources/marker_2.png | Bin 0 -> 261 bytes resources/marker_3.png | Bin 0 -> 285 bytes resources/marker_4.png | Bin 0 -> 274 bytes resources/marker_5.png | Bin 0 -> 266 bytes resources/marker_6.png | Bin 0 -> 283 bytes resources/marker_7.png | Bin 0 -> 282 bytes resources/marker_8.png | Bin 0 -> 320 bytes resources/marker_9.png | Bin 0 -> 300 bytes src/DisplayGUI/DisplayGUI.cxx | 52 +- src/GEOM/GEOM_Application.ixx | 8 +- ...MapNodeOfDataMapOfAsciiStringTransient.hxx | 2 +- ...pNodeOfDataMapOfAsciiStringTransient_0.cxx | 8 +- src/GEOM/GEOM_Engine.cxx | 549 +++-- src/GEOM/GEOM_Engine.hxx | 28 +- src/GEOM/GEOM_Function.cxx | 8 +- src/GEOM/GEOM_Object.cxx | 135 +- src/GEOM/GEOM_Object.hxx | 22 + src/GEOM/GEOM_Solver.cxx | 6 +- src/GEOM/GEOM_SubShapeDriver.cxx | 18 +- src/GEOMAlgo/GEOMAlgo_Splitter.cxx | 196 +- src/GEOMBase/GEOMBase_Helper.cxx | 38 +- src/GEOMGUI/GEOMGUI_Selection.cxx | 54 +- src/GEOMGUI/GEOMGUI_Selection.h | 1 + src/GEOMGUI/GEOM_Displayer.cxx | 143 +- src/GEOMGUI/GEOM_images.ts | 52 + src/GEOMGUI/GEOM_msg_en.ts | 63 + src/GEOMGUI/GeometryGUI.cxx | 94 +- src/GEOMGUI/GeometryGUI.h | 12 +- src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx | 6 +- src/GEOMImpl/GEOMImpl_IGroupOperations.cxx | 6 +- src/GEOMImpl/GEOMImpl_IInsertOperations.cxx | 102 +- src/GEOMImpl/GEOMImpl_IInsertOperations.hxx | 13 + src/GEOMImpl/GEOMImpl_IShapesOperations.cxx | 2 +- src/GEOMImpl/GEOMImpl_PartitionDriver.cxx | 9 + src/GEOMImpl/GEOMImpl_PipeDriver.cxx | 1950 ++++++++--------- src/GEOMImpl/GEOMImpl_ShapeDriver.cxx | 13 +- src/GEOMImpl/GEOMImpl_SketcherDriver.cxx | 5 + src/GEOMImpl/Makefile.am | 2 +- src/GEOMToolsGUI/GEOMToolsGUI.cxx | 5 + src/GEOMToolsGUI/GEOMToolsGUI.h | 1 + src/GEOMToolsGUI/GEOMToolsGUI_1.cxx | 28 +- src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx | 370 ++++ src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.h | 78 + src/GEOMToolsGUI/Makefile.am | 9 +- src/GEOM_I/GEOM_Gen_i.cc | 38 +- src/GEOM_I/GEOM_IInsertOperations_i.cc | 50 + src/GEOM_I/GEOM_IInsertOperations_i.hh | 10 + src/GEOM_I/GEOM_Object_i.cc | 63 + src/GEOM_I/GEOM_Object_i.hh | 10 + src/GEOM_SWIG/GEOM_TestOthers.py | 6 +- src/GEOM_SWIG/GEOM_example7.py | 53 + src/GEOM_SWIG/Makefile.am | 1 + src/GEOM_SWIG/geompy.py | 2 +- src/GEOM_SWIG/geompyDC.py | 188 +- src/GroupGUI/GroupGUI_GroupDlg.cxx | 110 +- src/IGESExport/IGESExport.cxx | 10 +- src/IGESExport/Makefile.am | 2 +- src/IGESImport/IGESImport.cxx | 5 + src/IGESImport/Makefile.am | 2 +- .../MeasureGUI_CheckCompoundOfBlocksDlg.cxx | 57 +- src/OBJECT/GEOM_VTKTrihedron.cxx | 101 +- src/OBJECT/GEOM_VTKTrihedron.hxx | 15 +- .../OperationGUI_Fillet1d2dDlg.cxx | 2 + src/STEPExport/Makefile.am | 2 +- src/STEPExport/STEPExport.cxx | 9 +- src/STEPImport/Makefile.am | 2 +- src/STEPImport/STEPImport.cxx | 5 + .../TransformationGUI_MirrorDlg.cxx | 5 +- .../TransformationGUI_PositionDlg.cxx | 5 +- .../TransformationGUI_RotationDlg.cxx | 9 +- .../TransformationGUI_ScaleDlg.cxx | 5 +- .../TransformationGUI_TranslationDlg.cxx | 5 +- 96 files changed, 3426 insertions(+), 1679 deletions(-) create mode 100755 doc/salome/gui/GEOM/images/custom_point_marker.png create mode 100644 doc/salome/gui/GEOM/images/image168.png create mode 100755 doc/salome/gui/GEOM/images/point_marker_dlg1.png create mode 100755 doc/salome/gui/GEOM/images/point_marker_dlg2.png create mode 100755 doc/salome/gui/GEOM/images/std_point_marker.png create mode 100644 doc/salome/gui/GEOM/input/point_marker.doc create mode 100755 resources/marker_1.png create mode 100755 resources/marker_10.png create mode 100755 resources/marker_11.png create mode 100755 resources/marker_12.png create mode 100755 resources/marker_13.png create mode 100755 resources/marker_2.png create mode 100755 resources/marker_3.png create mode 100755 resources/marker_4.png create mode 100755 resources/marker_5.png create mode 100755 resources/marker_6.png create mode 100755 resources/marker_7.png create mode 100755 resources/marker_8.png create mode 100755 resources/marker_9.png create mode 100644 src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx create mode 100644 src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.h create mode 100644 src/GEOM_SWIG/GEOM_example7.py diff --git a/adm_local/unix/config_files/check_qt.m4 b/adm_local/unix/config_files/check_qt.m4 index d98fff260..0f28aef7d 100644 --- a/adm_local/unix/config_files/check_qt.m4 +++ b/adm_local/unix/config_files/check_qt.m4 @@ -51,6 +51,8 @@ fi qt_ok=yes +QTDIR=$(echo $QTDIR | sed 's%[/]\+$%%') + AC_LANG_SAVE AC_LANG_CPLUSPLUS diff --git a/doc/salome/gui/GEOM/doxyfile_py.in b/doc/salome/gui/GEOM/doxyfile_py.in index efa355dfc..c3b0a156d 100755 --- a/doc/salome/gui/GEOM/doxyfile_py.in +++ b/doc/salome/gui/GEOM/doxyfile_py.in @@ -29,7 +29,7 @@ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = NO +REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = YES FULL_PATH_NAMES = NO diff --git a/doc/salome/gui/GEOM/images/custom_point_marker.png b/doc/salome/gui/GEOM/images/custom_point_marker.png new file mode 100755 index 0000000000000000000000000000000000000000..a71625ecd6a0f27da1a7ea4a061f83eac683ac8f GIT binary patch literal 1058 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 literal 22431 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�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

}>ife{G;$2^VHp2>r&Hx5n5&eTkCwMg2`gxC#+ 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/std_point_marker.png b/doc/salome/gui/GEOM/images/std_point_marker.png new file mode 100755 index 0000000000000000000000000000000000000000..ccf478b0c2301433e5507c5198211aa6bc2bed6d GIT binary patch literal 1546 zcmeAS@N?(olHy`uVBq!ia0y~yV9W=y|8Xz@$tq!CK?Vlai=HlyAr*7p-r49U?a6Tb zp`z3EyHWO;X2|;&Urq(idtN1+=Hc7Gqb;l845UmMjjphq z2oN61oJRIv--_NS`b zSAF-&lC*yRh1uWFd|03K(Z9}7q~wWbR?z0H&inKA{~GG(%-(cf-^Kmg616ke?YQMR z@6DfOkZmnyw@l@{>B(7p-jqC4Ic&DtSJUcK(Bw5IlbUvY^x5=l&Q^C>nK$3ooE4F? zw%R-Em44pORrZ#?r8OJ)|355UzrP(U<{PPRf7?b|K+LXs)~kId-_>+*-KKWxr!iMQW<^=coIA-#NuU zTU%j8^DGtJ;7i->y)8ALK0bWg^Zq{(uwHG=%Kbi`m;dhOIdy}%#qoxD=g#|jmeHOk z^L@*U|G%izwDvF%ccd2RK+Kb!K;d+(Gk zv@zJS`10!48;=L{w@Yu_Z+`c_w&PCir~8BIrhM8vC4cFiTTM%io~c#(eqT7{{n9^| zx7SZ8DzE=N73gMzZw!e7S(C1mh%deK?d|o{fUvy%L6^42`}(YyG}Z6kx9=}&w3m8t zZY}y66?Zu{XJ^5`Z58~6UxOw)>P&k0*>{GhspNzj1MRZJ#=%im{9`vhI_E_5vb$S= PWjuqYtDnm{r-UW|L3e+N literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/input/creating_point.doc b/doc/salome/gui/GEOM/input/creating_point.doc index b472e12c9..fadededd8 100644 --- a/doc/salome/gui/GEOM/input/creating_point.doc +++ b/doc/salome/gui/GEOM/input/creating_point.doc @@ -25,45 +25,43 @@ the position of this point regarding the reference one. \image html point2.png -\n Thirdly, we can define a point by an \b Edge and a \b -[list] -[*]Parameter +\n Thirdly, we can define a point by an \b Edge and a \b Parameter indicating its position on the Edge, ranging from 0.0 to 1.0. For example, 0.5 means that the point is located in the middle of the edge. \n TUI Command: geompy.MakeVertexOnCurve(Edge,Parameter). \n Arguments: Name + 1 edge + 1 Parameter defining the position of the point on the given edge. \image html point3.png -[*]3D co-ordinate of point to project on the given edge -\n TUI Command: geompy.MakeVertexOnCurveByCoord(Edge,X,Y,Z). -\n Arguments: Name + 1 edge + 3 coordinate values -to project point on the given edge. -\image html point3_2.png -[/list] +Alternatively, it is possible to define 3D coordinates of the point +projected on the given edge to produce the resulting point. +\n TUI Command: geompy.MakeVertexOnCurveByCoord(Edge,X,Y,Z). +\n Arguments: Name + 1 edge + 3 coordinate values of the +projected point. +\image html point3_2.png \n Fourthly, we can define a point by intersection of two \b Lines. \n TUI Command: geompy.MakePointOnLinesIntersection(myLine1,myLine2). \n Arguments: Name + 2 lines \image html point4.png -Example: \n Finally, we can define a point by a \b Face and -[list] -[*]Two Parameters: U and \b V +Two Parameters: U and \b V indicating its position on the Face, ranging from 0.0 to 1.0. For example, (0.5; 0.5) means that the point is located in the middle of the face. \n TUI Command: geompy.MakeVertexOnSurface(myFace,myUParameter,myVParameter). \n Arguments: Name + 1 face + 2 Parameters defining the position of the point on the given face. -[*] 3D co-ordinate of point to project on the given face. + \image html point5.png + +Alternatively, it is possible to define 3D coordinates of the point projected on the given face. \n TUI Command: geompy.MakeVertexOnSurface(myFace,X,Y,Z). \n Arguments: Name + 1 face + 3 coordinate values to project point on the given face. + \image html point5_2.png -[/list] Example: diff --git a/doc/salome/gui/GEOM/input/isolines.doc b/doc/salome/gui/GEOM/input/isolines.doc index 10862f046..4f503afdf 100644 --- a/doc/salome/gui/GEOM/input/isolines.doc +++ b/doc/salome/gui/GEOM/input/isolines.doc @@ -4,7 +4,7 @@ \n In this menu you can change the number of isolines displayed within a shape. -\n Arguments:2 values (number of isolines). +\n Arguments: 2 values (number of isolines). \image html neo-isos.png @@ -14,4 +14,4 @@ a shape. \image html isos_u12_v12sn.png -*/ \ No newline at end of file +*/ diff --git a/doc/salome/gui/GEOM/input/modify_location_operation.doc b/doc/salome/gui/GEOM/input/modify_location_operation.doc index 8ad902a15..632842243 100644 --- a/doc/salome/gui/GEOM/input/modify_location_operation.doc +++ b/doc/salome/gui/GEOM/input/modify_location_operation.doc @@ -13,7 +13,7 @@ with the origin of the Local Coordinate System. will be removed. \n Arguments: Name + one or several objects + End Coordinate System. \n Advanced option: - \ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". +\ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". \image html transformation5.png @@ -34,7 +34,7 @@ otherwise it will be removed. \n Arguments: Name + one or several objects + Start Coordinate System + End Coordinate System. \n Advanced option: - \ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". +\ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". \image html transformation6.png @@ -64,8 +64,7 @@ the other objects. Arguments: Name + one or several objects + Translation path. \n Advanced option: - \ref restore_presentation_parameters_page "Set presentation - parameters and subshapes from arguments". +\ref restore_presentation_parameters_page "Set presentation parameters and subshapes from arguments". \image html transformation13.png diff --git a/doc/salome/gui/GEOM/input/point_marker.doc b/doc/salome/gui/GEOM/input/point_marker.doc new file mode 100644 index 000000000..ddc4a6b3d --- /dev/null +++ b/doc/salome/gui/GEOM/input/point_marker.doc @@ -0,0 +1,56 @@ +/*! + +\page point_marker_page Point Marker + +\n You can change the representation of the geometrical vertices in +the 3D viewer either by selecting one of the predefined +shapes or by loading a custom texture from an external file. + +- Standard point markers + +The Geometry module provides a set of predefined point marker shapes which +can be used to display vertices in 3D viewer. +Each standard point marker has two attributes: type (defines shape +form) and scale factor (defines shape size). + +\image html point_marker_dlg1.png + +TUI Command: go.SetMarkerStd(Type, Size). + +\image html std_point_marker.png "Standard point markers" + +- Custom point markers + +It is also possible to load a point marker shape from an external file. +This file should provide a description of the point texture as a set +of lines; each line is represented as sequence of "0" and "1" symbols, +where "1" symbol means an opaque pixel and "0" symbol means a +transparent pixel. The width of the texture correspond to the length +of the longest line in the file, expanded to the nearest byte-aligned +value. The height of the texture is equal to the number of non-empty +lines in the file. Note that missing symbols are replaced by "0". + +Here is a texture file sample: + +

+00111100
+00111100
+11111111
+11111111
+11111111
+11111111
+00111100
+00111100
+
+ +\image html point_marker_dlg2.png + +TUI Command: go.SetMarkerTexture(ID). + +\image html custom_point_marker.png "Custom point markers" + +Our TUI Scripts provide you with useful examples of +\ref tui_point_marker "Point Marker" setting. + +*/ + diff --git a/doc/salome/gui/GEOM/input/remove_extra_edges_operation.doc b/doc/salome/gui/GEOM/input/remove_extra_edges_operation.doc index 4988009e6..ef1b932bf 100644 --- a/doc/salome/gui/GEOM/input/remove_extra_edges_operation.doc +++ b/doc/salome/gui/GEOM/input/remove_extra_edges_operation.doc @@ -10,9 +10,9 @@ hexahedral solids and compounds of hexahedral solids. However, there is an option to unite all faces sharing one surface, which produces not only hexahedral solids. -\n TUI Command: geompy.RemoveExtraEdges(theShape,theOptimumNbFaces), +\n TUI Command: geompy.RemoveExtraEdges(theShape,doUnionFaces), where theShape is a compound or a single solid -and theOptimumNbFaces is an integer parameter, that regulates, +and doUnionFaces is a boolean parameter, that regulates, whether the faces, sharing a common surface, should be united. \n Arguments: Name + one shape + a flag. \n Advanced option: diff --git a/doc/salome/gui/GEOM/input/sewing_operation.doc b/doc/salome/gui/GEOM/input/sewing_operation.doc index a32474bce..9ee5eff67 100644 --- a/doc/salome/gui/GEOM/input/sewing_operation.doc +++ b/doc/salome/gui/GEOM/input/sewing_operation.doc @@ -4,7 +4,7 @@ \n To produce a \b Sewing operation in the Main Menu select Repair - > Sewing. -\n It is possible to sew only compounds or shells. +\n It is possible to sew only compounds of faces or shells. \n The \b Result will be a \b GEOM_Object. diff --git a/doc/salome/gui/GEOM/input/tui_viewing_geom_objs.doc b/doc/salome/gui/GEOM/input/tui_viewing_geom_objs.doc index 743205b57..2573c0fa5 100644 --- a/doc/salome/gui/GEOM/input/tui_viewing_geom_objs.doc +++ b/doc/salome/gui/GEOM/input/tui_viewing_geom_objs.doc @@ -61,4 +61,21 @@ gg.setColor(fuse_id,218,165,31) gg.setTransparency(fuse_id,0.5) \endcode -*/ \ No newline at end of file +\anchor tui_point_marker +

Set Point Marker

+ +\code +import salome +import geompy + +texture = geompy.LoadTexture("/users/user/mytexture.dat") + +v1 = geompy.MakeVertex(0, 0, 0) +v2 = geompy.MakeVertex(100, 0, 0) +v3 = geompy.MakeVertex(0, 100, 0) + +v1.SetMarkerStd(GEOM.MT_O_PLUS, GEOM.MS_25) +v2.SetMarkerStd(GEOM.MT_BALL, GEOM.MS_40) +v3.SetMarkerTexture(texture) +\endcode +*/ diff --git a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc index 1c2a518d4..6a485015e 100644 --- a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc +++ b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc @@ -27,6 +27,8 @@ the standard Select Color menu. transparency of geometrical objects.
  • \subpage isolines_page "Isos" - allows to change the number of isolines displayed within a shape.
  • +
  • \subpage point_marker_page "Point Marker" - allows to change the +representation of geometrical vertices.
  • Auto color / Disable auto color - activates the auto color mode. When the auto color mode is enabled, the groups created on the sub-shapes of the selected geometrical object are automatically diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index a04fcb4c6..978cde0d2 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -40,6 +40,17 @@ module GEOM enum shape_type { COMPOUND, COMPSOLID, SOLID, SHELL, FACE, WIRE, EDGE, VERTEX, SHAPE }; + /*! + * Marker type + */ + enum marker_type { MT_NONE, MT_POINT, MT_PLUS, MT_STAR, MT_O, MT_X, MT_O_POINT, MT_O_PLUS, + MT_O_STAR, MT_O_X, MT_BALL, MT_RING1, MT_RING2, MT_RING3, MT_USER }; + + /*! + * Marker size + */ + enum marker_size { MS_NONE, MS_10, MS_15, MS_20, MS_25, MS_30, MS_35, + MS_40, MS_45, MS_50, MS_55, MS_60, MS_65, MS_70 }; /*! * State of shape relatively geometrical surface like plane, sphere or cylinder. @@ -172,6 +183,38 @@ module GEOM */ boolean GetAutoColor(); + /*! + * Set standard point marker for the object + * \param theType standard marker type + * \param theSize marker relative size + */ + void SetMarkerStd(in marker_type theType, in marker_size theSize ); + + /*! + * Set custom point marker for the object. The texture can be added + * by LoadTexture() or AddTexture() functions. + * \param theTextureId texture ID + */ + void SetMarkerTexture(in long theTextureId); + + /*! + * Get type of the point marker assigned to the object + * \return current marker type (MT_NONE if no marker is set) + */ + marker_type GetMarkerType(); + + /*! + * Get size of the point marker assigned to the object + * \return current marker relative size (MS_NONE if no marker is set) + */ + marker_size GetMarkerSize(); + + /*! + * Get texture idenifier of the point marker assigned to the object + * \return marker texture ID (0 if no marker set) + */ + long GetMarkerTexture(); + /*! * Set a Study entry where this object was published. */ @@ -240,7 +283,7 @@ module GEOM * used for object creation */ void SetParameters (in string theParameters); - + /*! * Return list of notebook variables used for object creation separated by ":" symbol */ @@ -462,7 +505,7 @@ module GEOM */ GEOM_Object MakePlaneFace (in GEOM_Object theFace, in double theTrimSize); - + /*! * Create a plane, by two vectors. * \param theVec1 Vector1, the plane has to pass through first point of this vector. @@ -473,7 +516,7 @@ module GEOM GEOM_Object MakePlane2Vec (in GEOM_Object theVec1, in GEOM_Object theVec2, in double theTrimSize); - + /*! * Create a plane, defined by local coordinate system. * \param theLCS Referenced LCS(Marker). @@ -922,7 +965,7 @@ module GEOM * vertical (H) and horisontal (W). * \param theVec defines plane. * \param theH vertical size (height). - * \param theW horisontal size (width). + * \param theW horisontal size (width). * \return New GEOM_Object, containing the created face. */ GEOM_Object MakeFaceObjHW (in GEOM_Object theObj, in double theH, in double theW); @@ -944,7 +987,7 @@ module GEOM GEOM_Object MakeDiskThreePnt (in GEOM_Object thePnt1, in GEOM_Object thePnt2, in GEOM_Object thePnt3); - + /*! * Create a disk specified dimensions along OX-OY coordinate axes, * Center of the disk at point (0, 0, 0). @@ -953,7 +996,7 @@ module GEOM * \return New GEOM_Object, containing the created disk. */ GEOM_Object MakeDiskR (in double theR, in short theOrientation); - + /*! * Create a cylinder with given radius and height at * the origin of coordinate system. Axis of the cylinder @@ -1075,7 +1118,7 @@ module GEOM GEOM_Object MakePrismTwoPnt2Ways (in GEOM_Object theBase, in GEOM_Object thePoint1, in GEOM_Object thePoint2); - + /*! * Create a shape by extrusion of the base shape along a vector, defined by DX DY DZ. * \param theBase Base shape to be extruded. @@ -1144,7 +1187,7 @@ module GEOM /*! * Create a shape by extrusion of the profile shape along * the path shape. The path shape can be a wire or an edge. - * the several profiles can be specified in the several locations of path. + * the several profiles can be specified in the several locations of path. * \param theSeqBases - list of Bases shape to be extruded. * \param theLocations - list of locations on the path corresponding * specified list of the Bases shapes. Number of locations @@ -1165,7 +1208,7 @@ module GEOM /*! * Create a shape by extrusion of the profile shape along * the path shape. The path shape can be a shell or a face. - * the several profiles can be specified in the several locations of path. + * the several profiles can be specified in the several locations of path. * \param theSeqBases - list of Bases shape to be extruded. * \param theSeqSubBases - list of corresponding subshapes of section shapes. * \param theLocations - list of locations on the path corresponding @@ -1196,7 +1239,7 @@ module GEOM /*! * Create a shape by extrusion of the base shape along - * the path shape with constant bi-normal direction along the given vector. + * the path shape with constant bi-normal direction along the given vector. * The path shape can be a wire or an edge. * \param theBase Base shape to be extruded. * \param thePath Path shape to extrude the base shape along it. @@ -1205,8 +1248,8 @@ module GEOM * along the sweep surface. * \return New GEOM_Object, containing the created pipe. */ - GEOM_Object MakePipeBiNormalAlongVector (in GEOM_Object theBase, - in GEOM_Object thePath, + GEOM_Object MakePipeBiNormalAlongVector (in GEOM_Object theBase, + in GEOM_Object thePath, in GEOM_Object theVec); }; @@ -2206,7 +2249,7 @@ module GEOM in GEOM_Object thePnt1, in GEOM_Object thePnt2, in boolean theSense); - + /*! * Create an arc of ellipse of center C and two points P1 P2. * \param theCenter Center point of the arc. @@ -2277,7 +2320,7 @@ module GEOM * \return New GEOM_Object, containing the created wire. */ GEOM_Object MakeSketcher (in string theCommand, in ListOfDouble theWorkingPlane); - + /*! * Create a 3D sketcher, following the numerical description, * passed through points created by \a theCoordinates argument. \n @@ -2285,7 +2328,7 @@ module GEOM * * "Make3DSketcher[x1, y1, z1, x2, y2, z2, ..., xN, yN, zN]" */ - + GEOM_Object Make3DSketcher (in ListOfDouble theCoordinates); /*! @@ -2343,12 +2386,12 @@ module GEOM GEOM_Object MakeFilletFaces (in GEOM_Object theShape, in double theR, in ListOfLong theFaces); - + GEOM_Object MakeFilletFacesR1R2 (in GEOM_Object theShape, in double theR1, in double theR2, in ListOfLong theFaces); - + /*! * Perform a fillet on face of the specified vertexes of the given shape. * \param theShape Shape, to perform fillet on. @@ -2651,6 +2694,37 @@ module GEOM */ void ExportTranslators (out string_array theFormats, out string_array thePatterns); + + /*! + * Load texture from file + * \param theTextureFile texture file name + * \return unique texture identifier + */ + long LoadTexture(in string theTextureFile); + + /*! + * Add texture to the study + * \param theWidth texture width in pixels + * \param theHeight texture height in pixels + * \param theTexture texture byte array + * \return unique texture identifier + */ + long AddTexture(in long theWidth, in long theHeight, in SALOMEDS::TMPFile theTexture); + + /*! + * Get previously loaded texture data + * \param theID texture identifier + * \param theWidth texture width in pixels + * \param theHeight texture height in pixels + * \return texture byte array + */ + SALOMEDS::TMPFile GetTexture(in long theID, out long theWidth, out long theHeight); + + /*! + * Get list of all avaiable texture IDs + * \return list of all texture IDs avaiable for the current study + */ + ListOfLong GetAllTextures(); }; /*! diff --git a/resources/Makefile.am b/resources/Makefile.am index 7e74345c4..30478317f 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -186,6 +186,19 @@ suppressintwires.png \ marker.png \ marker2.png \ marker3.png \ +marker_1.png \ +marker_2.png \ +marker_3.png \ +marker_4.png \ +marker_5.png \ +marker_6.png \ +marker_7.png \ +marker_8.png \ +marker_9.png \ +marker_10.png \ +marker_11.png \ +marker_12.png \ +marker_13.png \ position.png \ position2.png \ position3.png \ diff --git a/resources/marker_1.png b/resources/marker_1.png new file mode 100755 index 0000000000000000000000000000000000000000..8bbaa854e234d7a1d13ac8dc60d02098178db461 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hUudb&7bP0l+XkKJNr5W literal 0 HcmV?d00001 diff --git a/resources/marker_10.png b/resources/marker_10.png new file mode 100755 index 0000000000000000000000000000000000000000..aa7d857472f6d984f42f1e401041772d808b2658 GIT binary patch literal 333 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggaZVmx+-kpMt4nU!^o-U3d7N^%v zR^&Tuz~lNhW5I&dMqQ29ibc(nWR|I@b9_v6s%n;7l#|e$DlPFjV3E&9wbHlKnI_fj zuZiR{GM2gMYL&Bl--3Jj;Zyd^Q158)^0HoWb#QFC zc2r5pP}0bFOYHfNscTImvJ)exr5GJ^;9%UA>+PAurE01sR{h@azIV`ly*=M8&KtX* z$ZII>J6`DWT;@HSM6!^|{r_{CZ+Iv*2{QL70(Y)*K0-AbW|YuPggaZVmxM#k-TeRDnXdo-U3d7N?g^ zb`)wb;9!Lnsu4)_YD23pKmPu`sgQ9?gimV z_J^b9Z%JxgaysX(cgyF~4&n>@Un+GxuJB7p-6pi_zoW^qtCNd*gbHtYvD`9RTE4Jl a!dmYBW?OEf+(ccV#SEUVelF{r5}E*`&Qpv4 literal 0 HcmV?d00001 diff --git a/resources/marker_12.png b/resources/marker_12.png new file mode 100755 index 0000000000000000000000000000000000000000..b6c09964b43f82cafffc9314326063a98f946eaa GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggaZVmxMj`@n0Jb^-4o-U3d7N^$+ z8wwpz;1E8SzNPtp{gmc^&Fkj0Id%6)Fimt&3Ni`|{Iu)#F)MfV7FAnDtuGxvybTXs z^_ae$ZI4}4RB7Dfohr?;do7zRtNIjl4*pWe=9ZE#Tcmw3YW{OUr{iCKi}n3h5aQoh WWl@m+XZ0DNtqh*7elF{r5}E*FWlmK9 literal 0 HcmV?d00001 diff --git a/resources/marker_13.png b/resources/marker_13.png new file mode 100755 index 0000000000000000000000000000000000000000..16162a752649e417dc92d6cf333ecd00fe86bde1 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPggaZVmwh%~Qdj!+=6ro-U3d7N?W{ z{QqyytlGdjdqK|{rM8v+a`)4ZESn~Hll6v)kP$~7!=|*HZ4W1nx z+!aW?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTzd%8G=RNPAX^Z&m+vnqo^!;BA}r%q@InaBc}5*jQFj4m4)F^D4^U2aKE(y}&{ zHS+~sm{|mvPcXzpM7ce*x2qIj<51|@%OKz&B8^G(OnK(kz_92BD+41NgMzQk)H8b{ RPXe96;OXk;vd$@?2>?nQL0td< literal 0 HcmV?d00001 diff --git a/resources/marker_3.png b/resources/marker_3.png new file mode 100755 index 0000000000000000000000000000000000000000..e37d613e1edc4afdb1b26b886c74481c907b63ce GIT binary patch literal 285 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTr_H=O!skoK&=l_3uW>p4-h8Z6`Po2;bGLZ!`B{WzV7>~Gg_1<{G$kf3o!geAe z%I%@OqL~pJhXPwplfls!CT2VW4m~@P7;oSA84DR0T{dzv zFm*gKVBk>bN@i4OD9BQ4<39v6wBdAS%N)MLKox~SK*QX;ij^H00^cw-FfcQ$e52eg TWvmW#9Rq`>tDnm{r-UW|VCYco literal 0 HcmV?d00001 diff --git a/resources/marker_4.png b/resources/marker_4.png new file mode 100755 index 0000000000000000000000000000000000000000..78c8055325e4c2bc3fa924015482adbf401fb3f2 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hU8c)B=-RNPAX^Z&m+vnqo^L&OHoQzx{NX8d~cvDPgoi;<~=b+%hhSK&!U76IlH z+zL9ni$BO8JJx>jDo{X}xfQ6zW0UM`Z3d=}Byk27fun4w#6=DP2a(-CRT2|FGg)d1 v0vQ`q)q*}TIWQOo&5{P1|Hy!W!+?SN`^u?H9{2D7-NfMO>gTe~DWM4f^qWmT literal 0 HcmV?d00001 diff --git a/resources/marker_5.png b/resources/marker_5.png new file mode 100755 index 0000000000000000000000000000000000000000..a994c1100412a856d0609296d30fa92a841f1fa2 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTTc)B=-RNPAX^Z&m+vnqo^!wd-x76wKZa|gGui5klntY+p=V4EPG5E13}(B4R1 zHhD5Thr%L}hr%E#=g@Pb1_q@UF;4fGfXagY_Vh6_btH*1um~JYWDsx=InLz35IBdA zfvIB&!{KFo3JnsPXMGqLT?*5H>brOuI1CuLgpN0+)LE$j-NNAM>gTe~DWM4fhCxL{ literal 0 HcmV?d00001 diff --git a/resources/marker_6.png b/resources/marker_6.png new file mode 100755 index 0000000000000000000000000000000000000000..967b93ecc25181d1b2fea151d283eed958c8eedc GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTr^mK6yskoK&=l_3uW>p4-hKLQEr%q@k&G_}?W35|G79&#!>uk52uELXyECS3Y zxD|AC7k`jHcC7v4RiJ<{b1P7b$0pg?+6+t`N#YDF0&&b6j?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTr@N{tuskoK&?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hU0^K@|xskoK&=l_3uW>p4-hKLQEr%q@k&G_}?W35|G79&#!;}a%{Y10CK@Ez_VQG^To`ZIA#t7wU~3QJ6V>W z4PXGO-=UH)>q90RV*|sXOomO|A0$D7ElfP|2bvfh7#{Li#N>QoU?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx&hTL@^op4-h6sn2o;8pDtM|V*KE&c!Q_}k4lYyNBgJDAq!=Xz? zT>mF#mh^bbDKu=*I@G%HBr}V^Q9T9@g*9rE53zG7sO2bfb16hPEMhmX0*b1|2pKqk z$Yf(|U^tY?;A6Z^!K*2>8Vhl_jk4hK>97J{l?Urz4QLSVI(wb*` hf$EMpC^B#uFx+uYQBZVc>j1iz!PC{xWt~$(6999WRk;8F literal 0 HcmV?d00001 diff --git a/src/DisplayGUI/DisplayGUI.cxx b/src/DisplayGUI/DisplayGUI.cxx index 952007b0a..44a14839c 100644 --- a/src/DisplayGUI/DisplayGUI.cxx +++ b/src/DisplayGUI/DisplayGUI.cxx @@ -511,18 +511,18 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow SVTK_Prs* vtkPrs = stvkViewer ? dynamic_cast( stvkViewer->CreatePrs( It.Value()->getEntry() ) ) : 0; if ( vtkPrs && !vtkPrs->IsNull() ) { - if ( mode == 0 ) - aView->ChangeRepresentationToWireframe( vtkPrs->GetObjects() ); - else if ( mode == 1 ) - aView->ChangeRepresentationToSurface( vtkPrs->GetObjects() ); - else if ( mode == 2 ) { - vtkActorCollection* anActors = vtkPrs->GetObjects(); - anActors->InitTraversal(); - while (vtkActor* anAct = anActors->GetNextActor()) { - GEOM_Actor* aGeomActor = GEOM_Actor::SafeDownCast(anAct); - aGeomActor->SetVectorMode(!aGeomActor->GetVectorMode()); - } - } + if ( mode == 0 ) + aView->ChangeRepresentationToWireframe( vtkPrs->GetObjects() ); + else if ( mode == 1 ) + aView->ChangeRepresentationToSurface( vtkPrs->GetObjects() ); + else if ( mode == 2 ) { + vtkActorCollection* anActors = vtkPrs->GetObjects(); + anActors->InitTraversal(); + while (vtkActor* anAct = anActors->GetNextActor()) { + GEOM_Actor* aGeomActor = GEOM_Actor::SafeDownCast(anAct); + aGeomActor->SetVectorMode(!aGeomActor->GetVectorMode()); + } + } } } aView->Repaint(); @@ -538,19 +538,21 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow SOCC_Viewer* soccViewer = (SOCC_Viewer*)(viewWindow->getViewManager()->getViewModel()); SOCC_Prs* occPrs = dynamic_cast( soccViewer->CreatePrs( It.Value()->getEntry() ) ); if ( occPrs && !occPrs->IsNull() ) { - AIS_ListOfInteractive shapes; occPrs->GetObjects( shapes ); - AIS_ListIteratorOfListOfInteractive interIter( shapes ); - for ( ; interIter.More(); interIter.Next() ) { - if ( mode == 0 ) - ic->SetDisplayMode( interIter.Value(), AIS_WireFrame, false ); - else if ( mode == 1 ) - ic->SetDisplayMode( interIter.Value(), AIS_Shaded, false ); - if (mode == 2 ) { - Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( interIter.Value() ); - aSh->SetDisplayVectors(!aSh->isShowVectors()); - ic->RecomputePrsOnly(interIter.Value()); - } - } + AIS_ListOfInteractive shapes; occPrs->GetObjects( shapes ); + AIS_ListIteratorOfListOfInteractive interIter( shapes ); + for ( ; interIter.More(); interIter.Next() ) { + if ( mode == 0 ) + ic->SetDisplayMode( interIter.Value(), AIS_WireFrame, false ); + else if ( mode == 1 ) + ic->SetDisplayMode( interIter.Value(), AIS_Shaded, false ); + if (mode == 2 ) { + Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( interIter.Value() ); + if ( !aSh.IsNull() ) { + aSh->SetDisplayVectors(!aSh->isShowVectors()); + ic->RecomputePrsOnly(interIter.Value()); + } + } + } } } ic->UpdateCurrentViewer(); diff --git a/src/GEOM/GEOM_Application.ixx b/src/GEOM/GEOM_Application.ixx index 8a2c33ff7..3fbbfcaf1 100644 --- a/src/GEOM/GEOM_Application.ixx +++ b/src/GEOM/GEOM_Application.ixx @@ -47,10 +47,10 @@ Standard_EXPORT Handle_Standard_Type& GEOM_Application_Type_() static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,aType4,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOM_Application", - sizeof(GEOM_Application), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOM_Application), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } diff --git a/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient.hxx b/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient.hxx index f63d23b3b..c91aa4823 100644 --- a/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient.hxx +++ b/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient.hxx @@ -77,7 +77,7 @@ Standard_EXPORT ~GEOM_DataMapNodeOfDataMapOfAsciiStringTransient(); // Standard_EXPORT friend Handle_Standard_Type& GEOM_DataMapNodeOfDataMapOfAsciiStringTransient_Type_(); Standard_EXPORT const Handle(Standard_Type)& DynamicType() const; - Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)&) const; + Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)&) const; protected: diff --git a/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient_0.cxx b/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient_0.cxx index 7dbb47f54..cf99e71de 100644 --- a/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient_0.cxx +++ b/src/GEOM/GEOM_DataMapNodeOfDataMapOfAsciiStringTransient_0.cxx @@ -54,10 +54,10 @@ Standard_EXPORT Handle_Standard_Type& GEOM_DataMapNodeOfDataMapOfAsciiStringTran static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOM_DataMapNodeOfDataMapOfAsciiStringTransient", - sizeof(GEOM_DataMapNodeOfDataMapOfAsciiStringTransient), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOM_DataMapNodeOfDataMapOfAsciiStringTransient), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } diff --git a/src/GEOM/GEOM_Engine.cxx b/src/GEOM/GEOM_Engine.cxx index 7a572ba1f..e6da3ad15 100644 --- a/src/GEOM/GEOM_Engine.cxx +++ b/src/GEOM/GEOM_Engine.cxx @@ -42,6 +42,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -106,7 +111,7 @@ bool ProcessFunction(Handle(GEOM_Function)& theFunction, TCollection_AsciiString& theScript, TCollection_AsciiString& theAfterScript, const TVariablesList& theVariables, - const bool theIsPublished, + const bool theIsPublished, TDF_LabelMap& theProcessed, std::set& theIgnoreObjs, bool& theIsDumpCollected); @@ -117,23 +122,35 @@ void ReplaceVariables(TCollection_AsciiString& theCommand, Handle(TColStd_HSequenceOfInteger) FindEntries(TCollection_AsciiString& theString); void ReplaceEntriesByNames (TCollection_AsciiString& theScript, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames, - const bool theIsPublished, - Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + const bool theIsPublished, + Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, TColStd_SequenceOfAsciiString& theObjListToPublish); -void AddObjectColors (const Handle(TDocStd_Document)& theDoc, - TCollection_AsciiString& theScript, - const Resource_DataMapOfAsciiStringAsciiString& theObjectNames); +void AddObjectColors (int theDocID, + TCollection_AsciiString& theScript, + const Resource_DataMapOfAsciiStringAsciiString& theObjectNames); + +void AddTextures (int theDocID, TCollection_AsciiString& theScript); void PublishObject (const TCollection_AsciiString& theEntry, - const TCollection_AsciiString& theName, - const Resource_DataMapOfAsciiStringAsciiString& theObjectNames, - const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry, - const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry, - const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, - std::map< int, std::string >& theEntryToCommandMap, - std::set& theMapOfPublished); + const TCollection_AsciiString& theName, + const Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry, + const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry, + const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, + std::map< int, std::string >& theEntryToCommandMap, + std::set& theMapOfPublished); + +//======================================================================= +//function : GetTextureGUID +//purpose : +//======================================================================= +const Standard_GUID& GEOM_Engine::GetTextureGUID() +{ + static Standard_GUID anID("FF1BBB01-5D14-4df2-980B-3A668264EA17"); + return anID; +} //============================================================================= /*! @@ -186,17 +203,19 @@ GEOM_Engine::~GEOM_Engine() * GetDocument */ //============================================================================= -Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID) +Handle(TDocStd_Document) GEOM_Engine::GetDocument(int theDocID, bool force) { Handle(TDocStd_Document) aDoc; - if(!_mapIDDocument.IsBound(theDocID)) { + if(_mapIDDocument.IsBound(theDocID)) { + aDoc = Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID)); + } + else if (force) { _OCAFApp->NewDocument("SALOME_GEOM", aDoc); aDoc->SetUndoLimit(_UndoLimit); _mapIDDocument.Bind(theDocID, aDoc); TDataStd_Integer::Set(aDoc->Main(), theDocID); } - - return Handle(TDocStd_Document)::DownCast(_mapIDDocument(theDocID)); + return aDoc; } //============================================================================= @@ -219,17 +238,24 @@ int GEOM_Engine::GetDocID(Handle(TDocStd_Document) theDocument) * GetObject */ //============================================================================= -Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry) +Handle(GEOM_Object) GEOM_Engine::GetObject(int theDocID, char* theEntry, bool force) { + Handle(GEOM_Object) anObject; + TCollection_AsciiString anID = BuildID(theDocID, theEntry); - if(_objects.IsBound(anID)) return Handle(GEOM_Object)::DownCast(_objects(anID)); - TDF_Label aLabel; - Handle(TDocStd_Document) aDoc = GetDocument(theDocID); - TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True); - Handle(GEOM_Object) anObject = new GEOM_Object(aLabel); - - _objects.Bind(anID, anObject); + if (_objects.IsBound(anID)) { + anObject = Handle(GEOM_Object)::DownCast(_objects(anID)); + } + else if (force) { + Handle(TDocStd_Document) aDoc = GetDocument(theDocID, force); + if ( !aDoc.IsNull()) { + TDF_Label aLabel; + TDF_Tool::Label(aDoc->Main().Data(), theEntry, aLabel, Standard_True); + anObject = new GEOM_Object(aLabel); + _objects.Bind(anID, anObject); + } + } return anObject; } @@ -370,10 +396,12 @@ Handle(GEOM_Object) GEOM_Engine::AddSubShape(Handle(GEOM_Object) theMainShape, //============================================================================= bool GEOM_Engine::RemoveObject(Handle(GEOM_Object) theObject) { - if (!theObject) return false; + if (theObject.IsNull()) return false; int aDocID = theObject->GetDocID(); - + if(!_mapIDDocument.IsBound(aDocID)) + return false; // document is closed... + //Remove an object from the map of available objects TCollection_AsciiString anID = BuildIDFromObject(theObject); if (_objects.IsBound(anID)) _objects.UnBind(anID); @@ -503,11 +531,14 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID, if (aDoc.IsNull()) return TCollection_AsciiString("def RebuildData(theStudy): pass\n"); - aScript = "import geompy\n"; + aScript = "import GEOM\n"; + aScript += "import geompy\n"; aScript += "import math\n"; aScript += "import SALOMEDS\n\n"; aScript += "def RebuildData(theStudy):"; - aScript += "\n\tgeompy.init_geom(theStudy)"; + aScript += "\n\tgeompy.init_geom(theStudy)\n"; + + AddTextures(theDocID, aScript); Standard_Integer posToInsertGlobalVars = aScript.Length() + 1; @@ -556,32 +587,32 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID, bool isDumpCollected = false; TCollection_AsciiString aCurScript, anAfterScript; if (!ProcessFunction(aFunction, aCurScript, anAfterScript, theVariables, - isPublished, aCheckedFuncMap, anIgnoreObjMap, - isDumpCollected )) + isPublished, aCheckedFuncMap, anIgnoreObjMap, + isDumpCollected )) continue; // add function description before dump if (!aCurScript.IsEmpty()) aFuncScript += aCurScript; if (isDumpCollected ) { - // Replace entries by the names + // Replace entries by the names ReplaceEntriesByNames( aFuncScript, theObjectNames, isPublished, anEntryToBadName, aObjListToPublish ); - - // publish collected objects - std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry + + // publish collected objects + std::map< int, std::string > anEntryToCommandMap; // sort publishing commands by object entry int i = 1, n = aObjListToPublish.Length(); - for ( ; i <= n; i++ ) + for ( ; i <= n; i++ ) { const TCollection_AsciiString& aEntry = aObjListToPublish.Value(i); - if (!theObjectNames.IsBound( aEntry )) + if (!theObjectNames.IsBound( aEntry )) continue; - PublishObject( aEntry, theObjectNames.Find(aEntry), - theObjectNames, aEntry2StEntry, aStEntry2Entry, - anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap ); + PublishObject( aEntry, theObjectNames.Find(aEntry), + theObjectNames, aEntry2StEntry, aStEntry2Entry, + anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap ); } - // add publishing commands to the script - std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin(); - for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) + // add publishing commands to the script + std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin(); + for ( ; anEntryToCommand != anEntryToCommandMap.end(); ++anEntryToCommand ) aFuncScript += (char*)anEntryToCommand->second.c_str(); // PTv, 0020001 add result objects from RestoreSubShapes into ignore list, @@ -599,9 +630,9 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID, } } - aObjListToPublish.Clear(); - aScript += aFuncScript; - aFuncScript.Clear(); + aObjListToPublish.Clear(); + aScript += aFuncScript; + aFuncScript.Clear(); } aFuncScript += anAfterScript; } @@ -615,7 +646,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID, aScript += aFuncScript; // ouv : NPAL12872 - AddObjectColors( aDoc, aScript, theObjectNames ); + AddObjectColors( theDocID, aScript, theObjectNames ); // Make script to publish in study if ( isPublished ) @@ -630,8 +661,8 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID, continue; // should not be dumped const TCollection_AsciiString& aName = anEntryToNameIt.Value(); PublishObject( aEntry, aName, theObjectNames, - aEntry2StEntry, aStEntry2Entry, - anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap ); + aEntry2StEntry, aStEntry2Entry, + anEntryToBadName, anEntryToCommandMap, anIgnoreObjMap ); } // add publishing commands to the script std::map< int, std::string >::iterator anEntryToCommand = anEntryToCommandMap.begin(); @@ -695,6 +726,117 @@ Handle(TColStd_HSequenceOfAsciiString) GEOM_Engine::GetAllDumpNames() const return aRetSeq; } +#define TEXTURE_LABEL_ID 1 +#define TEXTURE_LABEL_FILE 2 +#define TEXTURE_LABEL_WIDTH 3 +#define TEXTURE_LABEL_HEIGHT 4 +#define TEXTURE_LABEL_DATA 5 + +int GEOM_Engine::addTexture(int theDocID, int theWidth, int theHeight, + const Handle(TDataStd_HArray1OfByte)& theTexture, + const TCollection_AsciiString& theFileName) +{ + Handle(TDocStd_Document) aDoc = GetDocument(theDocID); + Handle(TDataStd_TreeNode) aRoot = TDataStd_TreeNode::Set(aDoc->Main()); + + // NPAL18604: use existing label to decrease memory usage, + // if this label has been freed (object deleted) + bool useExisting = false; + TDF_Label aChild; + if (_freeLabels.find(theDocID) != _freeLabels.end()) { + std::list& aFreeLabels = _freeLabels[theDocID]; + if (!aFreeLabels.empty()) { + useExisting = true; + aChild = aFreeLabels.front(); + aFreeLabels.pop_front(); + } + } + if (!useExisting) { + // create new label + aChild = TDF_TagSource::NewChild(aDoc->Main()); + } + + aChild.ForgetAllAttributes(Standard_True); + Handle(TDataStd_TreeNode) node; + if ( !aChild.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), node ) ) + node = TDataStd_TreeNode::Set(aChild); + TDataStd_UAttribute::Set(aChild, GetTextureGUID()); + + static int aTextureID = 0; + + TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_ID), ++aTextureID); + TDataStd_Comment::Set(aChild.FindChild(TEXTURE_LABEL_FILE), theFileName); + TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_WIDTH), theWidth); + TDataStd_Integer::Set(aChild.FindChild(TEXTURE_LABEL_HEIGHT), theHeight); + + Handle(TDataStd_ByteArray) anAttr = + TDataStd_ByteArray::Set(aChild.FindChild(TEXTURE_LABEL_DATA), + theTexture.IsNull() ? 0 : theTexture->Lower(), + theTexture.IsNull() ? 0 : theTexture->Upper()); + anAttr->ChangeArray(theTexture); + + return aTextureID; +} + +Handle(TDataStd_HArray1OfByte) GEOM_Engine::getTexture(int theDocID, int theTextureID, + int& theWidth, int& theHeight, + TCollection_AsciiString& theFileName) +{ + Handle(TDataStd_HArray1OfByte) anArray; + theWidth = theHeight = 0; + + Handle(TDocStd_Document) aDoc = GetDocument(theDocID); + + TDF_ChildIterator anIterator(aDoc->Main(), Standard_True); + bool found = false; + for (; anIterator.More() && !found; anIterator.Next()) { + TDF_Label aTextureLabel = anIterator.Value(); + if (aTextureLabel.IsAttribute( GetTextureGUID())) { + TDF_Label anIDLabel = aTextureLabel.FindChild(TEXTURE_LABEL_ID, Standard_False); + Handle(TDataStd_Integer) anIdAttr; + if(!anIDLabel.IsNull() && anIDLabel.FindAttribute(TDataStd_Integer::GetID(), anIdAttr) && + anIdAttr->Get() == theTextureID) { + TDF_Label aFileLabel = aTextureLabel.FindChild(TEXTURE_LABEL_FILE, Standard_False); + TDF_Label aWidthLabel = aTextureLabel.FindChild(TEXTURE_LABEL_WIDTH, Standard_False); + TDF_Label aHeightLabel = aTextureLabel.FindChild(TEXTURE_LABEL_HEIGHT, Standard_False); + TDF_Label aDataLabel = aTextureLabel.FindChild(TEXTURE_LABEL_DATA, Standard_False); + Handle(TDataStd_Integer) aWidthAttr, aHeightAttr; + Handle(TDataStd_ByteArray) aTextureAttr; + Handle(TDataStd_Comment) aFileAttr; + if (!aWidthLabel.IsNull() && aWidthLabel.FindAttribute(TDataStd_Integer::GetID(), aWidthAttr) && + !aHeightLabel.IsNull() && aHeightLabel.FindAttribute(TDataStd_Integer::GetID(), aHeightAttr) && + !aDataLabel.IsNull() && aDataLabel.FindAttribute(TDataStd_ByteArray::GetID(), aTextureAttr)) { + theWidth = aWidthAttr->Get(); + theHeight = aHeightAttr->Get(); + anArray = aTextureAttr->InternalArray(); + } + if (!aFileLabel.IsNull() && aFileLabel.FindAttribute(TDataStd_Comment::GetID(), aFileAttr)) + theFileName = aFileAttr->Get(); + found = true; + } + } + } + return anArray; +} + +std::list GEOM_Engine::getAllTextures(int theDocID) +{ + std::list id_list; + + Handle(TDocStd_Document) aDoc = GetDocument(theDocID); + + TDF_ChildIterator anIterator(aDoc->Main(), Standard_True); + for (; anIterator.More(); anIterator.Next()) { + TDF_Label aTextureLabel = anIterator.Value(); + if (aTextureLabel.IsAttribute( GetTextureGUID())) { + TDF_Label anIDLabel = aTextureLabel.FindChild(TEXTURE_LABEL_ID, Standard_False); + Handle(TDataStd_Integer) anIdAttr; + if(!anIDLabel.IsNull() && anIDLabel.FindAttribute(TDataStd_Integer::GetID(), anIdAttr)) + id_list.push_back((int)anIdAttr->Get()); + } + } + return id_list; +} //=========================================================================== // Internal functions @@ -709,7 +851,7 @@ bool ProcessFunction(Handle(GEOM_Function)& theFunction, TCollection_AsciiString& theScript, TCollection_AsciiString& theAfterScript, const TVariablesList& theVariables, - const bool theIsPublished, + const bool theIsPublished, TDF_LabelMap& theProcessed, std::set& theIgnoreObjs, bool& theIsDumpCollected) @@ -887,14 +1029,14 @@ void ReplaceVariables(TCollection_AsciiString& theCommand, int aNbEntries = 1; if( anEntry.Value( 1 ) == O_SQR_BRACKET && anEntry.Value( anEntry.Length() ) == C_SQR_BRACKET ) { while(anEntry.Location(aNbEntries,COMMA,1,anEntry.Length())) - aNbEntries++; + aNbEntries++; TCollection_AsciiString aSeparator(COMMA); anEntry = anEntry.Token(aSeparator.ToCString(),1); anEntry.Remove( 1, 1 ); anEntry.RightAdjust(); anEntry.LeftAdjust(); if(MYDEBUG) - cout<<"Sub-entry : '" <= aVariables.size()) - continue; + if(iVar >= aVariables.size()) + continue; - aReplacedParameter = aVariables[iVar].myVariable; - if(aReplacedParameter.IsEmpty()) { - iVar++; - continue; - } + aReplacedParameter = aVariables[iVar].myVariable; + if(aReplacedParameter.IsEmpty()) { + iVar++; + continue; + } - if(aVariables[iVar].isVariable) { - aReplacedParameter.InsertBefore(1,"'"); - aReplacedParameter.InsertAfter(aReplacedParameter.Length(),"'"); - } + if(aVariables[iVar].isVariable) { + aReplacedParameter.InsertBefore(1,"'"); + aReplacedParameter.InsertAfter(aReplacedParameter.Length(),"'"); + } - if(MYDEBUG) - cout<<"aSection before : "<= aVariables.size()) - continue; + continue; aReplacedVar = aVariables[iVar].myVariable; if(aReplacedVar.IsEmpty()) { - iVar++; - continue; + iVar++; + continue; } if(aVariables[iVar].isVariable) { - aReplacedVar.InsertBefore(1,"\""); - aReplacedVar.InsertAfter(aReplacedVar.Length(),"\""); + aReplacedVar.InsertBefore(1,"\""); + aReplacedVar.InsertAfter(aReplacedVar.Length(),"\""); } aCommand.Remove(aStartPos, aEndPos - aStartPos); @@ -1092,9 +1234,9 @@ void ReplaceVariables(TCollection_AsciiString& theCommand, */ //============================================================================= void ReplaceEntriesByNames (TCollection_AsciiString& theScript, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames, - const bool theIsPublished, - Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + const bool theIsPublished, + Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, TColStd_SequenceOfAsciiString& theObjListToPublish) { Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(theScript); @@ -1164,10 +1306,13 @@ void ReplaceEntriesByNames (TCollection_AsciiString& theScript, * AddObjectColors: Add color to objects */ //============================================================================= -void AddObjectColors (const Handle(TDocStd_Document)& theDoc, - TCollection_AsciiString& theScript, - const Resource_DataMapOfAsciiStringAsciiString& theObjectNames) +void AddObjectColors (int theDocID, + TCollection_AsciiString& theScript, + const Resource_DataMapOfAsciiStringAsciiString& theObjectNames) { + GEOM_Engine* engine = GEOM_Engine::GetEngine(); + Handle(TDocStd_Document) aDoc = engine->GetDocument(theDocID); + Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString anEntryToNameIt; for (anEntryToNameIt.Initialize( theObjectNames ); anEntryToNameIt.More(); @@ -1177,7 +1322,7 @@ void AddObjectColors (const Handle(TDocStd_Document)& theDoc, const TCollection_AsciiString& aName = anEntryToNameIt.Value(); TDF_Label L; - TDF_Tool::Label( theDoc->GetData(), aEntry, L ); + TDF_Tool::Label( aDoc->GetData(), aEntry, L ); if ( L.IsNull() ) continue; @@ -1200,6 +1345,108 @@ void AddObjectColors (const Handle(TDocStd_Document)& theDoc, aCommand += aName + ".SetColor(SALOMEDS.Color(" + aColor.R + "," + aColor.G + "," + aColor.B + "))"; theScript += aCommand.ToCString(); } + + Aspect_TypeOfMarker aMarkerType = obj->GetMarkerType(); + if (aMarkerType >= Aspect_TOM_POINT && aMarkerType < Aspect_TOM_USERDEFINED) { + TCollection_AsciiString aCommand( "\n\t" ); + aCommand += aName + ".SetMarkerStd("; + switch (aMarkerType) { + case Aspect_TOM_POINT: aCommand += "GEOM.MT_POINT"; break; + case Aspect_TOM_PLUS: aCommand += "GEOM.MT_PLUS"; break; + case Aspect_TOM_STAR: aCommand += "GEOM.MT_STAR"; break; + case Aspect_TOM_O: aCommand += "GEOM.MT_O"; break; + case Aspect_TOM_X: aCommand += "GEOM.MT_X"; break; + case Aspect_TOM_O_POINT: aCommand += "GEOM.MT_O_POINT"; break; + case Aspect_TOM_O_PLUS: aCommand += "GEOM.MT_O_PLUS"; break; + case Aspect_TOM_O_STAR: aCommand += "GEOM.MT_O_STAR"; break; + case Aspect_TOM_O_X: aCommand += "GEOM.MT_O_X"; break; + case Aspect_TOM_BALL: aCommand += "GEOM.MT_BALL"; break; + case Aspect_TOM_RING1: aCommand += "GEOM.MT_RING1"; break; + case Aspect_TOM_RING2: aCommand += "GEOM.MT_RING2"; break; + case Aspect_TOM_RING3: aCommand += "GEOM.MT_RING3"; break; + default: aCommand += "GEOM.MT_NONE"; break; // just for completeness, should not get here + } + aCommand += ", "; + int aSize = (int)( obj->GetMarkerSize()/0.5 ) - 1; + switch (aSize) { + case 1: aCommand += "GEOM.MS_10"; break; + case 2: aCommand += "GEOM.MS_15"; break; + case 3: aCommand += "GEOM.MS_20"; break; + case 4: aCommand += "GEOM.MS_25"; break; + case 5: aCommand += "GEOM.MS_30"; break; + case 6: aCommand += "GEOM.MS_35"; break; + case 7: aCommand += "GEOM.MS_40"; break; + case 8: aCommand += "GEOM.MS_45"; break; + case 9: aCommand += "GEOM.MS_50"; break; + case 10: aCommand += "GEOM.MS_55"; break; + case 11: aCommand += "GEOM.MS_60"; break; + case 12: aCommand += "GEOM.MS_65"; break; + case 13: aCommand += "GEOM.MS_70"; break; + default: aCommand += "GEOM.MS_NONE"; break; + } + aCommand += ")"; + theScript += aCommand.ToCString(); + } + else if (aMarkerType == Aspect_TOM_USERDEFINED) { + int aMarkerTextureID = obj->GetMarkerTexture(); + if (aMarkerTextureID >= 0) { + TCollection_AsciiString aCommand( "\n\t" ); + aCommand += aName + ".SetMarkerTexture(texture_map["; + aCommand += aMarkerTextureID; + aCommand += "])"; + theScript += aCommand.ToCString(); + } + } + } +} + +static TCollection_AsciiString pack_data(const Handle(TDataStd_HArray1OfByte)& aData ) +{ + TCollection_AsciiString stream; + if (!aData.IsNull()) { + for (Standard_Integer i = aData->Lower(); i <= aData->Upper(); i++) { + Standard_Byte byte = aData->Value(i); + TCollection_AsciiString strByte = ""; + for (int j = 0; j < 8; j++) + strByte.Prepend((byte & (1< allTextures = engine->getAllTextures(theDocID); + std::list::const_iterator it; + + if (allTextures.size() > 0) { + theScript += "\n\ttexture_map = {}\n"; + + for (it = allTextures.begin(); it != allTextures.end(); ++it) { + if (*it <= 0) continue; + Standard_Integer aWidth, aHeight; + TCollection_AsciiString aFileName; + Handle(TDataStd_HArray1OfByte) aTexture = engine->getTexture(theDocID, *it, aWidth, aHeight, aFileName); + if (aWidth > 0 && aHeight > 0 && !aTexture.IsNull() && aTexture->Length() > 0 ) { + TCollection_AsciiString aCommand = "\n\t"; + aCommand += "texture_map["; aCommand += *it; aCommand += "] = "; + if (aFileName != "" ) { + aCommand += "geompy.LoadTexture(\""; + aCommand += aFileName.ToCString(); + aCommand += "\")"; + } + else { + aCommand += "geompy.AddTexture("; + aCommand += aWidth; aCommand += ", "; aCommand += aHeight; aCommand += ", \""; + aCommand += pack_data(aTexture); + aCommand += "\")"; + } + theScript += aCommand; + } + } + theScript += "\n"; } } @@ -1209,13 +1456,13 @@ void AddObjectColors (const Handle(TDocStd_Document)& theDoc, */ //============================================================================= void PublishObject (const TCollection_AsciiString& theEntry, - const TCollection_AsciiString& theName, - const Resource_DataMapOfAsciiStringAsciiString& theObjectNames, - const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry, - const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry, - const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, - std::map< int, std::string >& theEntryToCommandMap, - std::set& theMapOfPublished) + const TCollection_AsciiString& theName, + const Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + const Resource_DataMapOfAsciiStringAsciiString& theEntry2StEntry, + const Resource_DataMapOfAsciiStringAsciiString& theStEntry2Entry, + const Resource_DataMapOfAsciiStringAsciiString& theEntryToBadName, + std::map< int, std::string >& theEntryToCommandMap, + std::set& theMapOfPublished) { if ( !theEntry2StEntry.IsBound( theEntry )) return; // was not published diff --git a/src/GEOM/GEOM_Engine.hxx b/src/GEOM/GEOM_Engine.hxx index c901123b6..25b661d15 100644 --- a/src/GEOM/GEOM_Engine.hxx +++ b/src/GEOM/GEOM_Engine.hxx @@ -37,6 +37,8 @@ #include #include +class Handle_TDataStd_HArray1OfByte; + struct TVariable{ TCollection_AsciiString myVariable; bool isVariable; @@ -80,7 +82,7 @@ class GEOM_Engine Standard_EXPORT static GEOM_Engine* GetEngine(); //Returns the OCAF document by its ID, if document doesn't exists it will be created - Standard_EXPORT Handle(TDocStd_Document) GetDocument(int theDocID); + Standard_EXPORT Handle(TDocStd_Document) GetDocument(int theDocID, bool force=true); //Returns the ID of the given OCAF document Standard_EXPORT int GetDocID(Handle(TDocStd_Document) theDocument); @@ -89,7 +91,7 @@ class GEOM_Engine Standard_EXPORT Handle(TDocStd_Application) GetApplication() { return _OCAFApp; } //Returns a pointer to GEOM_Object defined by a document and the entry - Standard_EXPORT Handle(GEOM_Object) GetObject(int theDocID, char* theEntry); + Standard_EXPORT Handle(GEOM_Object) GetObject(int theDocID, char* theEntry, bool force=true); //Adds a new object of the type theType in the OCAF document Standard_EXPORT Handle(GEOM_Object) AddObject(int theDocID, int theType); @@ -117,19 +119,31 @@ class GEOM_Engine //Adds a new sub shape object of the MainShape object Standard_EXPORT Handle(GEOM_Object) AddSubShape(Handle(GEOM_Object) theMainShape, - Handle(TColStd_HArray1OfInteger) theIndices, - bool isStandaloneOperation = false); + Handle(TColStd_HArray1OfInteger) theIndices, + bool isStandaloneOperation = false); Standard_EXPORT TCollection_AsciiString DumpPython(int theDocID, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, TVariablesList theVariables, - bool isPublished, - bool& aValidScript); + bool isPublished, + bool& aValidScript); Standard_EXPORT const char* GetDumpName (const char* theStudyEntry) const; Standard_EXPORT Handle(TColStd_HSequenceOfAsciiString) GetAllDumpNames() const; + Standard_EXPORT int addTexture(int theDocID, int theWidth, int theHeight, + const Handle(TDataStd_HArray1OfByte)& theTexture, + const TCollection_AsciiString& theFileName = ""); + + Standard_EXPORT Handle(TDataStd_HArray1OfByte) getTexture(int theDocID, int theTextureID, + int& theWidth, int& theHeight, + TCollection_AsciiString& theFileName); + + Standard_EXPORT std::list getAllTextures(int theDocID); + + static const Standard_GUID& GetTextureGUID(); + protected: Standard_EXPORT static void SetEngine(GEOM_Engine* theEngine); diff --git a/src/GEOM/GEOM_Function.cxx b/src/GEOM/GEOM_Function.cxx index d10bd9daf..d9d1c321e 100644 --- a/src/GEOM/GEOM_Function.cxx +++ b/src/GEOM/GEOM_Function.cxx @@ -727,10 +727,10 @@ Standard_EXPORT Handle_Standard_Type& GEOM_Function_Type_() static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOM_Function", - sizeof(GEOM_Function), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOM_Function), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } diff --git a/src/GEOM/GEOM_Object.cxx b/src/GEOM/GEOM_Object.cxx index b2ca175f4..fc2170a86 100644 --- a/src/GEOM/GEOM_Object.cxx +++ b/src/GEOM/GEOM_Object.cxx @@ -33,11 +33,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -45,11 +47,16 @@ #include #define FUNCTION_LABEL(theNb) (_label.FindChild(1).FindChild((theNb))) -#define TYPE_LABEL 2 -#define FREE_LABEL 3 -#define TIC_LABEL 4 +#define TYPE_LABEL 2 +#define FREE_LABEL 3 +#define TIC_LABEL 4 #define COLOR_LABEL 5 #define AUTO_COLOR_LABEL 6 +#define MARKER_LABEL 7 + +#define MARKER_LABEL_TYPE 1 +#define MARKER_LABEL_SIZE 2 +#define MARKER_LABEL_ID 3 //======================================================================= //function : GetObjectID @@ -140,8 +147,14 @@ Handle(GEOM_Object) GEOM_Object::GetReferencedObject(TDF_Label& theLabel) */ //============================================================================= GEOM_Object::GEOM_Object(TDF_Label& theEntry) -: _label(theEntry), _ior("") + : _label(theEntry), _ior(""), _docID(-1) { + Handle(TDocStd_Document) aDoc = TDocStd_Owner::GetDocument(_label.Data()); + if(!aDoc.IsNull()) { + Handle(TDataStd_Integer) anID; + if(aDoc->Main().FindAttribute(TDataStd_Integer::GetID(), anID)) _docID = anID->Get(); + } + if(!theEntry.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), _root)) _root = TDataStd_TreeNode::Set(theEntry); } @@ -152,8 +165,14 @@ GEOM_Object::GEOM_Object(TDF_Label& theEntry) */ //============================================================================= GEOM_Object::GEOM_Object(TDF_Label& theEntry, int theType) -: _label(theEntry), _ior("") +: _label(theEntry), _ior(""), _docID(-1) { + Handle(TDocStd_Document) aDoc = TDocStd_Owner::GetDocument(_label.Data()); + if(!aDoc.IsNull()) { + Handle(TDataStd_Integer) anID; + if(aDoc->Main().FindAttribute(TDataStd_Integer::GetID(), anID)) _docID = anID->Get(); + } + theEntry.ForgetAllAttributes(Standard_True); if(!theEntry.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), _root)) @@ -255,13 +274,7 @@ void GEOM_Object::IncrementTic() //============================================================================= int GEOM_Object::GetDocID() { - Handle(TDocStd_Document) aDoc = TDocStd_Owner::GetDocument(_label.Data()); - if(aDoc.IsNull()) return -1; - - Handle(TDataStd_Integer) anID; - if(!aDoc->Main().FindAttribute(TDataStd_Integer::GetID(), anID)) return -1; - - return anID->Get(); + return _docID; } @@ -368,6 +381,96 @@ CORBA::Boolean GEOM_Object::GetAutoColor() return anAutoColor->Get(); } +//============================================================================= +/*! + * SetMarkerStd + */ +//============================================================================= +void GEOM_Object::SetMarkerStd(const Aspect_TypeOfMarker theType, double theSize) +{ + TDF_Label aMarkerLabel = _label.FindChild(MARKER_LABEL); + TDataStd_Integer::Set(aMarkerLabel.FindChild(MARKER_LABEL_TYPE), (int)theType); + TDataStd_Real::Set(aMarkerLabel.FindChild(MARKER_LABEL_SIZE), theSize); +} + +//============================================================================= +/*! + * SetMarkerTexture + */ +//============================================================================= +void GEOM_Object::SetMarkerTexture(int theTextureId) +{ + TDF_Label aMarkerLabel = _label.FindChild(MARKER_LABEL); + TDataStd_Integer::Set(aMarkerLabel.FindChild(MARKER_LABEL_TYPE), (int)Aspect_TOM_USERDEFINED); + TDataStd_Integer::Set(aMarkerLabel.FindChild(MARKER_LABEL_ID), theTextureId); +} + +//============================================================================= +/*! + * GetMarkerType + */ +//============================================================================= +Aspect_TypeOfMarker GEOM_Object::GetMarkerType() +{ + Standard_Integer aType = -1; + TDF_Label aMarkerLabel = _label.FindChild(MARKER_LABEL, Standard_False); + if(!aMarkerLabel.IsNull()) { + TDF_Label aTypeLabel = aMarkerLabel.FindChild(MARKER_LABEL_TYPE, Standard_False); + Handle(TDataStd_Integer) aTypeAttr; + if (!aTypeLabel.IsNull() && aTypeLabel.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) + aType = aTypeAttr->Get(); + } + return (Aspect_TypeOfMarker)aType; +} + +//============================================================================= +/*! + * GetMarkerSize + */ +//============================================================================= +double GEOM_Object::GetMarkerSize() +{ + Standard_Real aSize = 0.; + TDF_Label aMarkerLabel = _label.FindChild(MARKER_LABEL, Standard_False); + if(!aMarkerLabel.IsNull()) { + TDF_Label aSizeLabel = aMarkerLabel.FindChild(MARKER_LABEL_SIZE, Standard_False); + Handle(TDataStd_Real) aSizeAttr; + if (!aSizeLabel.IsNull() && aSizeLabel.FindAttribute(TDataStd_Real::GetID(), aSizeAttr)) + aSize = aSizeAttr->Get(); + } + return aSize; +} + +//============================================================================= +/*! + * GetMarkerTexture + */ +//============================================================================= +int GEOM_Object::GetMarkerTexture() +{ + Standard_Integer anId = 0; + if ( GetMarkerType() == Aspect_TOM_USERDEFINED) { + TDF_Label aMarkerLabel = _label.FindChild(MARKER_LABEL, Standard_False); + if(!aMarkerLabel.IsNull()) { + TDF_Label aTypeLabel = aMarkerLabel.FindChild(MARKER_LABEL_ID, Standard_False); + Handle(TDataStd_Integer) anIdAttr; + if (!aTypeLabel.IsNull() && aTypeLabel.FindAttribute(TDataStd_Integer::GetID(), anIdAttr)) + anId = anIdAttr->Get(); + } + } + return anId; +} + +//============================================================================= +/*! + * SetAuxData + */ +//============================================================================= +void GEOM_Object::UnsetMarker() +{ + SetMarkerStd((Aspect_TypeOfMarker)-1, 0.); +} + //============================================================================= /*! * SetAuxData @@ -568,10 +671,10 @@ Standard_EXPORT Handle_Standard_Type& GEOM_Object_Type_() static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOM_Object", - sizeof(GEOM_Object), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOM_Object), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } diff --git a/src/GEOM/GEOM_Object.hxx b/src/GEOM/GEOM_Object.hxx index dd2f73ea2..c79f827e1 100644 --- a/src/GEOM/GEOM_Object.hxx +++ b/src/GEOM/GEOM_Object.hxx @@ -55,6 +55,9 @@ #ifndef _TCollection_AsciiString_HeaderFile #include #endif +#ifndef _Aspect_TypeOfMarker_HeaderFile +#include +#endif #include "SALOMEconfig.h" #include CORBA_SERVER_HEADER(SALOMEDS) @@ -215,6 +218,24 @@ class GEOM_Object : public MMgt_TShared //Returns a flag of auto color mode of this GEOM_Object Standard_EXPORT CORBA::Boolean GetAutoColor(); + //Sets predefined point marker texture + Standard_EXPORT void SetMarkerStd(const Aspect_TypeOfMarker theType, double theSize); + + //Sets custom point marker texture + Standard_EXPORT void SetMarkerTexture(int theTextureId); + + //Gets point marker type + Standard_EXPORT Aspect_TypeOfMarker GetMarkerType(); + + //Gets point marker scale factor / size + Standard_EXPORT double GetMarkerSize(); + + //Gets custom marker texture ID + Standard_EXPORT int GetMarkerTexture(); + + //Unsets point marker + Standard_EXPORT void UnsetMarker(); + //Sets an auxiliary data Standard_EXPORT void SetAuxData(const char* theData); @@ -279,6 +300,7 @@ class GEOM_Object : public MMgt_TShared TDF_Label _label; TCollection_AsciiString _ior; TCollection_AsciiString _parameters; + int _docID; }; #endif diff --git a/src/GEOM/GEOM_Solver.cxx b/src/GEOM/GEOM_Solver.cxx index 4967c088b..f38f1e622 100644 --- a/src/GEOM/GEOM_Solver.cxx +++ b/src/GEOM/GEOM_Solver.cxx @@ -60,11 +60,11 @@ bool GEOM_Solver::ComputeFunction(Handle(GEOM_Function) theFunction) Handle(TFunction_Driver) aDriver; if(!TFunction_DriverTable::Get()->FindDriver(aGUID, aDriver)) return false; - + aDriver->Init(theFunction->GetEntry()); - + TFunction_Logbook aLog; if(aDriver->Execute(aLog) == 0) return false; - + return true; } diff --git a/src/GEOM/GEOM_SubShapeDriver.cxx b/src/GEOM/GEOM_SubShapeDriver.cxx index 12d62e5a1..39aa38208 100644 --- a/src/GEOM/GEOM_SubShapeDriver.cxx +++ b/src/GEOM/GEOM_SubShapeDriver.cxx @@ -101,11 +101,11 @@ Standard_Integer GEOM_SubShapeDriver::Execute(TFunction_Logbook& log) const B.MakeCompound(aCompound); for (int i = anIndices->Lower(); i<= anIndices->Upper(); i++) { - if (aMapOfShapes.Extent() < anIndices->Value(i)) - Standard_NullObject::Raise("GEOM_SubShapeDriver::Execute: Index is out of range"); - TopoDS_Shape aSubShape = aMapOfShapes.FindKey(anIndices->Value(i)); - if (aSubShape.IsNull()) continue; - B.Add(aCompound,aSubShape); + if (aMapOfShapes.Extent() < anIndices->Value(i)) + Standard_NullObject::Raise("GEOM_SubShapeDriver::Execute: Index is out of range"); + TopoDS_Shape aSubShape = aMapOfShapes.FindKey(anIndices->Value(i)); + if (aSubShape.IsNull()) continue; + B.Add(aCompound,aSubShape); } aShape = aCompound; @@ -145,10 +145,10 @@ Standard_EXPORT Handle_Standard_Type& GEOM_SubShapeDriver_Type_() static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOM_SubShapeDriver", - sizeof(GEOM_SubShapeDriver), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOM_SubShapeDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } diff --git a/src/GEOMAlgo/GEOMAlgo_Splitter.cxx b/src/GEOMAlgo/GEOMAlgo_Splitter.cxx index 34b284b55..f7d150c6c 100755 --- a/src/GEOMAlgo/GEOMAlgo_Splitter.cxx +++ b/src/GEOMAlgo/GEOMAlgo_Splitter.cxx @@ -19,11 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File: GEOMAlgo_Splitter.cxx -// Created: -// Author: Peter KURNEV -// -// +// File: GEOMAlgo_Splitter.cxx +// Author: Peter KURNEV + #include #include @@ -45,13 +43,13 @@ #include -static - void TreatCompound(const TopoDS_Shape& aC, - TopTools_ListOfShape& aLSX); +static + void TreatCompound(const TopoDS_Shape& aC, + TopTools_ListOfShape& aLSX); //======================================================================= -//function : -//purpose : +//function : +//purpose : //======================================================================= GEOMAlgo_Splitter::GEOMAlgo_Splitter() : @@ -62,14 +60,14 @@ static } //======================================================================= //function : ~ -//purpose : +//purpose : //======================================================================= GEOMAlgo_Splitter::~GEOMAlgo_Splitter() { } //======================================================================= //function : AddToolCompound -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::AddToolCompound(const TopoDS_Shape& theShape) { @@ -83,7 +81,7 @@ static } //======================================================================= //function : AddTool -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::AddTool(const TopoDS_Shape& theShape) { @@ -95,7 +93,7 @@ static } //======================================================================= //function : Tools -//purpose : +//purpose : //======================================================================= const TopTools_ListOfShape& GEOMAlgo_Splitter::Tools()const { @@ -103,15 +101,15 @@ static } //======================================================================= //function : SetLimit -//purpose : +//purpose : //======================================================================= - void GEOMAlgo_Splitter::SetLimit(const TopAbs_ShapeEnum aLimit) + void GEOMAlgo_Splitter::SetLimit(const TopAbs_ShapeEnum aLimit) { myLimit=aLimit; } //======================================================================= //function : Limit -//purpose : +//purpose : //======================================================================= TopAbs_ShapeEnum GEOMAlgo_Splitter::Limit()const { @@ -119,7 +117,7 @@ static } //======================================================================= //function : SetLimitMode -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::SetLimitMode(const Standard_Integer aMode) { @@ -127,7 +125,7 @@ static } //======================================================================= //function : LimitMode -//purpose : +//purpose : //======================================================================= Standard_Integer GEOMAlgo_Splitter::LimitMode()const { @@ -135,7 +133,7 @@ static } //======================================================================= //function : Clear -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::Clear() { @@ -146,7 +144,7 @@ static } //======================================================================= //function : BuildResult -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::BuildResult(const TopAbs_ShapeEnum theType) { @@ -163,26 +161,26 @@ static aType=aS.ShapeType(); if (aType==theType && !myMapTools.Contains(aS)) { if (myImages.HasImage(aS)) { - const TopTools_ListOfShape& aLSIm=myImages.Image(aS); - aItIm.Initialize(aLSIm); - for (; aItIm.More(); aItIm.Next()) { - const TopoDS_Shape& aSIm=aItIm.Value(); - if (aM.Add(aSIm)) { - aBB.Add(myShape, aSIm); - } - } + const TopTools_ListOfShape& aLSIm=myImages.Image(aS); + aItIm.Initialize(aLSIm); + for (; aItIm.More(); aItIm.Next()) { + const TopoDS_Shape& aSIm=aItIm.Value(); + if (aM.Add(aSIm)) { + aBB.Add(myShape, aSIm); + } + } } else { - if (aM.Add(aS)) { - aBB.Add(myShape, aS); - } + if (aM.Add(aS)) { + aBB.Add(myShape, aS); + } } } } } //======================================================================= //function : PostTreat -//purpose : +//purpose : //======================================================================= void GEOMAlgo_Splitter::PostTreat() { @@ -200,7 +198,7 @@ static const TopoDS_Shape& aS=aMx(i); aBB.Add(aC, aS); } - //modified by NIZNHY-PKV Thu Feb 15 17:09:32 2007f + // if (myLimitMode) { Standard_Integer iType, iLimit, iTypeX; TopAbs_ShapeEnum aType, aTypeX; @@ -208,63 +206,77 @@ static TopTools_ListIteratorOfListOfShape aIt, aItX, aItIm; TopTools_MapOfShape aM; // - iLimit=(Standard_Integer)myLimit; + iLimit=(Standard_Integer)myLimit; // // 1. Collect the shapes to process aLSP aIt.Initialize(myShapes); for (; aIt.More(); aIt.Next()) { - const TopoDS_Shape& aS=aIt.Value(); - if (myMapTools.Contains(aS)) { - continue; - } - // - aType=aS.ShapeType(); - iType=(Standard_Integer)aType; - // - if (iType>iLimit) { - aLSP.Append(aS); - } - // - else if (aType==TopAbs_COMPOUND) { - aLSX.Clear(); - // - TreatCompound(aS, aLSX); - // - aItX.Initialize(aLSX); - for (; aItX.More(); aItX.Next()) { - const TopoDS_Shape& aSX=aItX.Value(); - aTypeX=aSX.ShapeType(); - iTypeX=(Standard_Integer)aTypeX; - // - if (iTypeX>iLimit) { - aLSP.Append(aSX); - } - } - } + const TopoDS_Shape& aS=aIt.Value(); + if (myMapTools.Contains(aS)) { + continue; + } + // + aType=aS.ShapeType(); + iType=(Standard_Integer)aType; + // + if (iType>iLimit) { + aLSP.Append(aS); + } + // + else if (aType==TopAbs_COMPOUND) { + aLSX.Clear(); + // + TreatCompound(aS, aLSX); + // + aItX.Initialize(aLSX); + for (; aItX.More(); aItX.Next()) { + const TopoDS_Shape& aSX=aItX.Value(); + aTypeX=aSX.ShapeType(); + iTypeX=(Standard_Integer)aTypeX; + // + if (iTypeX>iLimit) { + aLSP.Append(aSX); + } + } + } }// for (; aIt.More(); aIt.Next()) { // + //modified by NIZNHY-PKV Fri Oct 30 11:07:08 2009 f + aMx.Clear(); + TopExp::MapShapes(aC, aMx); + //modified by NIZNHY-PKV Fri Oct 30 11:12:30 2009t + // // 2. Add them to aC aIt.Initialize(aLSP); for (; aIt.More(); aIt.Next()) { - const TopoDS_Shape& aS=aIt.Value(); - if (myImages.HasImage(aS)) { - const TopTools_ListOfShape& aLSIm=myImages.Image(aS); - aItIm.Initialize(aLSIm); - for (; aItIm.More(); aItIm.Next()) { - const TopoDS_Shape& aSIm=aItIm.Value(); - if (aM.Add(aSIm)) { - aBB.Add(aC, aSIm); - } - } - } - else { - if (aM.Add(aS)) { - aBB.Add(aC, aS); - } - } + const TopoDS_Shape& aS=aIt.Value(); + if (myImages.HasImage(aS)) { + const TopTools_ListOfShape& aLSIm=myImages.Image(aS); + aItIm.Initialize(aLSIm); + for (; aItIm.More(); aItIm.Next()) { + const TopoDS_Shape& aSIm=aItIm.Value(); + if (aM.Add(aSIm)) { + //modified by NIZNHY-PKV Fri Oct 30 11:09:57 2009f + if (!aMx.Contains(aSIm)) { + aBB.Add(aC, aSIm); + } + //aBB.Add(aC, aSIm); + //modified by NIZNHY-PKV Fri Oct 30 11:10:02 2009 + } + } + } + else { + if (aM.Add(aS)) { + //modified by NIZNHY-PKV Fri Oct 30 11:10:46 2009f + if (!aMx.Contains(aS)) { + aBB.Add(aC, aS); + } + //aBB.Add(aC, aS); + //modified by NIZNHY-PKV Fri Oct 30 11:11:00 2009t + } + } } }// if (myLimitMode) { - //modified by NIZNHY-PKV Thu Feb 15 17:09:34 2007t myShape=aC; }//if (myLimit!=TopAbs_SHAPE) { // @@ -272,10 +284,10 @@ static } //======================================================================= //function : TreatCompound -//purpose : +//purpose : //======================================================================= -void TreatCompound(const TopoDS_Shape& aC1, - TopTools_ListOfShape& aLSX) +void TreatCompound(const TopoDS_Shape& aC1, + TopTools_ListOfShape& aLSX) { Standard_Integer aNbC1; TopAbs_ShapeEnum aType; @@ -292,14 +304,14 @@ void TreatCompound(const TopoDS_Shape& aC1, // aItC.Initialize(aC); for (; aItC.More(); aItC.Next()) { - const TopoDS_Shape& aS=aItC.Value(); - aType=aS.ShapeType(); - if (aType==TopAbs_COMPOUND) { - aLC1.Append(aS); - } - else { - aLSX.Append(aS); - } + const TopoDS_Shape& aS=aItC.Value(); + aType=aS.ShapeType(); + if (aType==TopAbs_COMPOUND) { + aLC1.Append(aS); + } + else { + aLSX.Append(aS); + } } } // @@ -318,7 +330,7 @@ void TreatCompound(const TopoDS_Shape& aC1, } // // myErrorStatus -// +// // 0 - Ok // 1 - The object is just initialized // 2 - PaveFiller is failed diff --git a/src/GEOMBase/GEOMBase_Helper.cxx b/src/GEOMBase/GEOMBase_Helper.cxx index 1bb44f33e..70c5ebd6d 100755 --- a/src/GEOMBase/GEOMBase_Helper.cxx +++ b/src/GEOMBase/GEOMBase_Helper.cxx @@ -52,6 +52,10 @@ #include #include +//To disable automatic genericobj management, the following line should be commented. +//Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx +//#define WITHGENERICOBJ + //================================================================ // Function : getActiveView // Purpose : Get active view window, returns 0 if no open study frame @@ -833,10 +837,12 @@ bool GEOMBase_Helper::onAccept( const bool publish, const bool useTransaction ) addInStudy( obj, aName.toLatin1().constData() ); // updateView=false display( obj, false ); +#ifdef WITHGENERICOBJ // obj has been published in study. Its refcount has been incremented. // It is safe to decrement its refcount // so that it will be destroyed when the entry in study will be removed obj->Destroy(); +#endif } else { // asv : fix of PAL6454. If publish==false, then the original shape @@ -1078,23 +1084,23 @@ void GEOMBase_Helper::addSubshapesToFather( QMap GEOM::GEOM_IGroupOperations_var anOp = getGeomEngine()->GetIGroupOperations( getStudyId() ); - for( QMap::Iterator it = theMap.begin(); it != theMap.end(); it++ ) - { - if ( !anOp->_is_nil() ) { - GEOM::GEOM_Object_var aFatherObj = anOp->GetMainShape( it.value() ); - if ( !aFatherObj->_is_nil() ) { - GEOM::GEOM_Object_var aFindedObject = findObjectInFather(aFatherObj, it.key().toLatin1().data() ); - - //Add Object to study if its not exist - if ( aFindedObject == GEOM::GEOM_Object::_nil() ) - GeometryGUI::GetGeomGen()->AddInStudy(GeometryGUI::ClientStudyToStudy(aDStudy), - it.value(), it.key().toLatin1().data(), aFatherObj ); - } - } - else { - //cout << " anOperations is NULL! " << endl; + for( QMap::Iterator it = theMap.begin(); it != theMap.end(); it++ ) { + if ( !anOp->_is_nil() ) { + GEOM::GEOM_Object_var aFatherObj = anOp->GetMainShape( it.value() ); + if ( !aFatherObj->_is_nil() ) { + std::string aFatherEntry = getEntry( aFatherObj ); + if ( aFatherEntry != "") { // additional checking that object is valid 0020598 EDF 1191 + GEOM::GEOM_Object_var aFindedObject = findObjectInFather(aFatherObj, it.key().toLatin1().data() ); + //Add Object to study if its not exist + if ( aFindedObject == GEOM::GEOM_Object::_nil() ) + GeometryGUI::GetGeomGen()->AddInStudy(GeometryGUI::ClientStudyToStudy(aDStudy), + it.value(), it.key().toLatin1().data(), aFatherObj ); + } } + } else { + //cout << " anOperations is NULL! " << endl; } -} + } +} diff --git a/src/GEOMGUI/GEOMGUI_Selection.cxx b/src/GEOMGUI/GEOMGUI_Selection.cxx index 593d80550..a3e9d133b 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.cxx +++ b/src/GEOMGUI/GEOMGUI_Selection.cxx @@ -83,6 +83,8 @@ QVariant GEOMGUI_Selection::parameter( const int ind, const QString& p ) const // else if( p == "type" ) return QVariant( typeName( ind ) ); + if( p == "typeid" ) + return QVariant( typeId( ind ) ); else if ( p == "displaymode" ) return QVariant( displayMode( ind ) ); else if ( p == "isAutoColor" ) @@ -112,6 +114,15 @@ QString GEOMGUI_Selection::typeName( const int index ) const return "Unknown"; } +int GEOMGUI_Selection::typeId( const int index ) const +{ + int aType = -1; + GEOM::GEOM_Object_var anObj = getObject( index ); + if ( !CORBA::is_nil( anObj ) ) + aType = anObj->GetType(); + return aType; +} + bool GEOMGUI_Selection::isVisible( const int index ) const { GEOM::GEOM_Object_var obj = getObject( index ); @@ -195,28 +206,29 @@ bool GEOMGUI_Selection::isVectorsMode( const int index ) const SALOME_Prs* prs = view->CreatePrs( entry( index ).toLatin1().constData() ); if ( prs ) { if ( viewType == OCCViewer_Viewer::Type() ) { // assuming OCC - SOCC_Prs* occPrs = (SOCC_Prs*) prs; - AIS_ListOfInteractive lst; - occPrs->GetObjects( lst ); - if ( lst.Extent() ) { - Handle(AIS_InteractiveObject) io = lst.First(); - if ( !io.IsNull() ) { - Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast(io); - ret = aSh->isShowVectors(); - } - } + SOCC_Prs* occPrs = (SOCC_Prs*) prs; + AIS_ListOfInteractive lst; + occPrs->GetObjects( lst ); + if ( lst.Extent() ) { + Handle(AIS_InteractiveObject) io = lst.First(); + if ( !io.IsNull() ) { + Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast(io); + if ( !aSh.IsNull() ) + ret = aSh->isShowVectors(); + } + } } else if ( viewType == SVTK_Viewer::Type() ) { // assuming VTK - SVTK_Prs* vtkPrs = dynamic_cast( prs ); - vtkActorCollection* lst = vtkPrs ? vtkPrs->GetObjects() : 0; - if ( lst ) { - lst->InitTraversal(); - vtkActor* actor = lst->GetNextActor(); - if ( actor ) { - GEOM_Actor* aGeomActor = GEOM_Actor::SafeDownCast(actor); - if ( aGeomActor ) - ret = aGeomActor->GetVectorMode(); - } - } + SVTK_Prs* vtkPrs = dynamic_cast( prs ); + vtkActorCollection* lst = vtkPrs ? vtkPrs->GetObjects() : 0; + if ( lst ) { + lst->InitTraversal(); + vtkActor* actor = lst->GetNextActor(); + if ( actor ) { + GEOM_Actor* aGeomActor = GEOM_Actor::SafeDownCast(actor); + if ( aGeomActor ) + ret = aGeomActor->GetVectorMode(); + } + } } } } diff --git a/src/GEOMGUI/GEOMGUI_Selection.h b/src/GEOMGUI/GEOMGUI_Selection.h index d6b4dabf0..bb8d0aaab 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.h +++ b/src/GEOMGUI/GEOMGUI_Selection.h @@ -48,6 +48,7 @@ private: bool isVisible( const int ) const; bool isAutoColor( const int ) const; QString typeName( const int ) const; + int typeId( const int ) const; QString displayMode( const int ) const; QString selectionMode() const; bool isVectorsMode( const int ) const; diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 7f778b23e..7cbc862c3 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -79,6 +79,7 @@ #include #include #include +#include // VTK Includes #include @@ -88,6 +89,7 @@ #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes) #include +#include using namespace std; @@ -256,13 +258,10 @@ GEOM_Displayer::GEOM_Displayer( SalomeApp_Study* st ) myShadingColor = SalomeApp_Tools::color( col ); myDisplayMode = resMgr->integerValue("Geometry", "display_mode", 0); - myTypeOfMarker = (Aspect_TypeOfMarker)resMgr->integerValue("Geometry", "type_of_marker", Aspect_TOM_PLUS); - myScaleOfMarker = resMgr->doubleValue("Geometry", "marker_scale", 1.); - if(myScaleOfMarker < 1.0) - myScaleOfMarker = 1.0; - if(myScaleOfMarker > 7.) - myScaleOfMarker = 7.; - + int aType = resMgr->integerValue("Geometry", "type_of_marker", (int)Aspect_TOM_PLUS); + myTypeOfMarker = (Aspect_TypeOfMarker)(std::min((int)Aspect_TOM_RING3, std::max((int)Aspect_TOM_POINT, aType))); + myScaleOfMarker = (resMgr->integerValue("Geometry", "marker_scale", 1)-(int)GEOM::MS_10)*0.5 + 1.0; + myScaleOfMarker = std::min(7.0, std::max(1., myScaleOfMarker)); myColor = -1; // This color is used for shape displaying. If it is equal -1 then @@ -588,54 +587,54 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) } } else + { + if ( myShape.ShapeType() == TopAbs_VERTEX ) { - if ( myShape.ShapeType() == TopAbs_VERTEX ) - { - col = aResMgr->colorValue( "Geometry", "point_color", QColor( 255, 255, 0 ) ); - aColor = SalomeApp_Tools::color( col ); - - Handle(Prs3d_PointAspect) anAspect = AISShape->Attributes()->PointAspect(); - anAspect->SetColor( aColor ); - anAspect->SetScale( myScaleOfMarker ); - anAspect->SetTypeOfMarker( myTypeOfMarker ); - AISShape->Attributes()->SetPointAspect( anAspect ); - } - else - { - // Set line aspect - col = aResMgr->colorValue( "Geometry", "wireframe_color", QColor( 255, 255, 0 ) ); - aColor = SalomeApp_Tools::color( col ); - - Handle(Prs3d_LineAspect) anAspect = AISShape->Attributes()->LineAspect(); - anAspect->SetColor( aColor ); - AISShape->Attributes()->SetLineAspect( anAspect ); - - // Set unfree boundaries aspect - anAspect = AISShape->Attributes()->UnFreeBoundaryAspect(); - anAspect->SetColor( aColor ); - AISShape->Attributes()->SetUnFreeBoundaryAspect( anAspect ); - - // Set free boundaries aspect - col = aResMgr->colorValue( "Geometry", "free_bound_color", QColor( 0, 255, 0 ) ); - aColor = SalomeApp_Tools::color( col ); - - anAspect = AISShape->Attributes()->FreeBoundaryAspect(); - anAspect->SetColor( aColor ); - AISShape->Attributes()->SetFreeBoundaryAspect( anAspect ); - - // Set wire aspect - col = aResMgr->colorValue( "Geometry", "line_color", QColor( 255, 0, 0 ) ); - aColor = SalomeApp_Tools::color( col ); - - anAspect = AISShape->Attributes()->WireAspect(); - anAspect->SetColor( aColor ); - AISShape->Attributes()->SetWireAspect( anAspect ); - - // bug [SALOME platform 0019868] - // Set deviation angle. Default one is 12 degrees (Prs3d_Drawer.cxx:18) - AISShape->SetOwnDeviationAngle( 10*PI/180 ); - } + col = aResMgr->colorValue( "Geometry", "point_color", QColor( 255, 255, 0 ) ); + aColor = SalomeApp_Tools::color( col ); + + Handle(Prs3d_PointAspect) anAspect = AISShape->Attributes()->PointAspect(); + anAspect->SetColor( aColor ); + anAspect->SetScale( myScaleOfMarker ); + anAspect->SetTypeOfMarker( myTypeOfMarker ); + AISShape->Attributes()->SetPointAspect( anAspect ); } + else + { + // Set line aspect + col = aResMgr->colorValue( "Geometry", "wireframe_color", QColor( 255, 255, 0 ) ); + aColor = SalomeApp_Tools::color( col ); + + Handle(Prs3d_LineAspect) anAspect = AISShape->Attributes()->LineAspect(); + anAspect->SetColor( aColor ); + AISShape->Attributes()->SetLineAspect( anAspect ); + + // Set unfree boundaries aspect + anAspect = AISShape->Attributes()->UnFreeBoundaryAspect(); + anAspect->SetColor( aColor ); + AISShape->Attributes()->SetUnFreeBoundaryAspect( anAspect ); + + // Set free boundaries aspect + col = aResMgr->colorValue( "Geometry", "free_bound_color", QColor( 0, 255, 0 ) ); + aColor = SalomeApp_Tools::color( col ); + + anAspect = AISShape->Attributes()->FreeBoundaryAspect(); + anAspect->SetColor( aColor ); + AISShape->Attributes()->SetFreeBoundaryAspect( anAspect ); + + // Set wire aspect + col = aResMgr->colorValue( "Geometry", "line_color", QColor( 255, 0, 0 ) ); + aColor = SalomeApp_Tools::color( col ); + + anAspect = AISShape->Attributes()->WireAspect(); + anAspect->SetColor( aColor ); + AISShape->Attributes()->SetWireAspect( anAspect ); + + // bug [SALOME platform 0019868] + // Set deviation angle. Default one is 12 degrees (Prs3d_Drawer.cxx:18) + AISShape->SetOwnDeviationAngle( 10*PI/180 ); + } + } if ( HasWidth() ) AISShape->SetWidth( GetWidth() ); @@ -657,7 +656,7 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) AISShape->SetOwner( anObj ); } - // Get color from GEOM_Object + // Get color and other properties from GEOM_Object SUIT_Session* session = SUIT_Session::session(); SUIT_Application* app = session->activeApplication(); if ( app ) @@ -731,6 +730,36 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) AISShape->Attributes()->SetPointAspect( anAspect ); } } + // ... marker type + GEOM::marker_type aType = aGeomObject->GetMarkerType(); + GEOM::marker_size aSize = aGeomObject->GetMarkerSize(); + if ( aType > GEOM::MT_NONE && aType < GEOM::MT_USER && aSize > GEOM::MS_NONE && aSize <= GEOM::MS_70 ) { + Aspect_TypeOfMarker aMType = (Aspect_TypeOfMarker)( (int)aType-1 ); + double aMSize = ((int)aSize+1)*0.5; + Handle(Prs3d_PointAspect) anAspect = AISShape->Attributes()->PointAspect(); + anAspect->SetScale( aMSize ); + anAspect->SetTypeOfMarker( aMType ); + Quantity_Color aQuanColor = SalomeApp_Tools::color( aResMgr->colorValue( "Geometry", "point_color", QColor( 255, 255, 0 ) ) ); + if ( hasColor ) + aQuanColor = Quantity_Color( aSColor.R, aSColor.G, aSColor.B, Quantity_TOC_RGB ); + anAspect->SetColor( aQuanColor ); + AISShape->Attributes()->SetPointAspect( anAspect ); + } + else if ( aType == GEOM::MT_USER ) { + int aTextureId = aGeomObject->GetMarkerTexture(); + Quantity_Color aQuanColor = SalomeApp_Tools::color( aResMgr->colorValue( "Geometry", "point_color", QColor( 255, 255, 0 ) ) ); + if ( hasColor ) aQuanColor = Quantity_Color( aSColor.R, aSColor.G, aSColor.B, Quantity_TOC_RGB ); + Standard_Integer aWidth, aHeight; + Handle(Graphic3d_HArray1OfBytes) aTexture = GeometryGUI::getTexture( getStudy(), aTextureId, aWidth, aHeight ); + if ( !aTexture.IsNull() ) { + static int TextureId = 0; + Handle(Prs3d_PointAspect) aTextureAspect = new Prs3d_PointAspect(aQuanColor, + ++TextureId, + aWidth, aHeight, + aTexture ); + AISShape->Attributes()->SetPointAspect( aTextureAspect ); + } + } } } } @@ -793,7 +822,7 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) if ( myType == GEOM_MARKER && myShape.ShapeType() == TopAbs_FACE ) { - myToActivate = false; + //myToActivate = false; // ouv: commented to make the trihedron pickable (see IPAL18657) GEOM_VTKTrihedron* aTrh = GEOM_VTKTrihedron::New(); if ( HasColor() ) @@ -820,9 +849,7 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) } else { - bool isVector = false; - if (myType == GEOM_VECTOR) isVector = true; - theActors = GEOM_AssemblyBuilder::BuildActors( myShape, 0, 0, Standard_True, isVector ); + theActors = GEOM_AssemblyBuilder::BuildActors( myShape, 0, 0, Standard_True, myType == GEOM_VECTOR ); } theActors->InitTraversal(); diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 2e25def67..94257fbd4 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -629,6 +629,58 @@ ICON_SELECT select1.png + + ICON_VERTEX_MARKER_1 + marker_1.png + + + ICON_VERTEX_MARKER_2 + marker_2.png + + + ICON_VERTEX_MARKER_3 + marker_3.png + + + ICON_VERTEX_MARKER_4 + marker_4.png + + + ICON_VERTEX_MARKER_5 + marker_5.png + + + ICON_VERTEX_MARKER_6 + marker_6.png + + + ICON_VERTEX_MARKER_7 + marker_7.png + + + ICON_VERTEX_MARKER_8 + marker_8.png + + + ICON_VERTEX_MARKER_9 + marker_9.png + + + ICON_VERTEX_MARKER_10 + marker_10.png + + + ICON_VERTEX_MARKER_11 + marker_11.png + + + ICON_VERTEX_MARKER_12 + marker_12.png + + + ICON_VERTEX_MARKER_13 + marker_13.png + ICO_ARC arc.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index ed1f7a99e..399dd04a4 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -335,6 +335,10 @@ Please, select face, shell or solid and try again GEOM_CHECK_BLOCKS_COMPOUND Check and Improve Blocks Compound + + GEOM_CHECK_BLOCKS_COMPOUND_FAILED + Check failed + GEOM_CHECK_BLOCKS_COMPOUND_ERRORS Errors @@ -2551,6 +2555,10 @@ Please, select face, shell or solid and try again MEN_WORK_PLANE Working Plane + + MEN_POP_POINT_MARKER + Point Marker + NAME_LBL Name: @@ -3051,6 +3059,10 @@ Please, select face, shell or solid and try again STB_WORK_PLANE Create a working plane + + STB_POP_POINT_MARKER + Set Point Marker + SUPPRESS_RESULT Suppress Result @@ -3511,6 +3523,10 @@ Please, select face, shell or solid and try again TOP_WORK_PLANE Create a working plane + + TOP_POP_POINT_MARKER + Point Marker + WRN_NOT_IMPLEMENTED Sorry, this functionality is not yet implemented @@ -4265,4 +4281,51 @@ Would you like to continue? Delete objects + + GEOMToolsGUI_MarkerDlg + + SET_MARKER_TLT + Set Point Marker + + + STANDARD_MARKER + Standard + + + CUSTOM_MARKER + Custom + + + TYPE + Type: + + + SCALE + Scale: + + + CUSTOM + Texture: + + + BROWSE + Browse... + + + OK_BTN + &OK + + + CANCEL_BTN + &Cancel + + + HELP_BTN + &Help + + + LOAD_TEXTURE_TLT + Load Texture + + diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 81efb22a1..611022451 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -80,6 +80,7 @@ #include #include #include +#include #include @@ -96,7 +97,7 @@ extern "C" { } } - +GeometryGUI::StudyTextureMap GeometryGUI::myTextureMap; GEOM::GEOM_Gen_var GeometryGUI::myComponentGeom = GEOM::GEOM_Gen::_nil(); @@ -343,7 +344,7 @@ void GeometryGUI::OnGUIEvent( int id ) bool ViewVTK = ( window && window->getViewManager()->getType() == SVTK_Viewer::Type() ); // if current viewframe is not of OCC and not of VTK type - return immediately // fix for IPAL8958 - allow some commands to execute even when NO viewer is active (rename for example) - bool NotViewerDependentCommand = ( id == 901 || id == 216 || id == 213 ); + bool NotViewerDependentCommand = ( id == 901 || id == 216 || id == 213 || id == 33 || id == 8037 || id == 8038 || id == 8039 ); if ( !ViewOCC && !ViewVTK && !NotViewerDependentCommand ) return; @@ -381,6 +382,7 @@ void GeometryGUI::OnGUIEvent( int id ) id == 8036 || // POPUP VIEWER - DISABLE AUTO COLOR id == 8037 || // POPUP VIEWER - SHOW CHILDREN id == 8038 || // POPUP VIEWER - HIDE CHILDREN + id == 8039 || // POPUP VIEWER - POINT MARKER id == 804 || // POPUP VIEWER - ADD IN STUDY id == 901 || // OBJECT BROWSER - RENAME id == 9024 ) { // OBJECT BROWSER - OPEN @@ -903,6 +905,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( 8001, "POP_CREATE_GROUP" ); createGeomAction( 8037, "POP_SHOW_CHILDREN" ); createGeomAction( 8038, "POP_HIDE_CHILDREN" ); + createGeomAction( 8039, "POP_POINT_MARKER" ); // make wireframe-shading items to be exclusive (only one at a time is selected) //QActionGroup* dispModeGr = new QActionGroup( this, "", true ); @@ -1170,6 +1173,8 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->setRule( action( 8033 ), clientOCCorVTK_AndSomeVisible, QtxPopupMgr::VisibleRule ); mgr->insert( action( 8034 ), -1, -1 ); // isos mgr->setRule( action( 8034 ), clientOCCorVTK_AndSomeVisible + " and selcount>0 and isVisible", QtxPopupMgr::VisibleRule ); + mgr->insert( action( 8039 ), -1, -1 ); // point marker + mgr->setRule( action( 8039 ), QString( "selcount>0 and $typeid in {%1}" ).arg( GEOM_POINT ), QtxPopupMgr::VisibleRule ); mgr->insert( separator(), -1, -1 ); // ----------- mgr->insert( action( 8035 ), -1, -1 ); // auto color mgr->setRule( action( 8035 ), autoColorPrefix + " and isAutoColor=false", QtxPopupMgr::VisibleRule ); @@ -1462,6 +1467,32 @@ QString GeometryGUI::engineIOR() const return ""; } +Handle(Graphic3d_HArray1OfBytes) GeometryGUI::getTexture( SalomeApp_Study* theStudy, int theId, int& theWidth, int& theHeight ) +{ + theWidth = theHeight = 0; + Handle(Graphic3d_HArray1OfBytes) aTexture; + if ( theStudy ) { + TextureMap aTextureMap = myTextureMap[ theStudy->studyDS()->StudyId() ]; + aTexture = aTextureMap[ theId ]; + if ( aTexture.IsNull() ) { + GEOM::GEOM_IInsertOperations_var aInsOp = GeometryGUI::GetGeomGen()->GetIInsertOperations( theStudy->studyDS()->StudyId() ); + if ( !aInsOp->_is_nil() ) { + CORBA::Long aWidth, aHeight; + SALOMEDS::TMPFile_var aStream = aInsOp->GetTexture( theId, aWidth, aHeight ); + if ( aWidth > 0 && aHeight > 0 && aStream->length() > 0 ) { + theWidth = aWidth; + theHeight = aHeight; + aTexture = new Graphic3d_HArray1OfBytes( 1, aStream->length() ); + for ( int i = 0; i < aStream->length(); i++ ) + aTexture->SetValue( i+1, (Standard_Byte)aStream[i] ); + aTextureMap[ theId ] = aTexture; + } + } + } + } + return aTexture; +} + LightApp_Selection* GeometryGUI::createSelection() const { return new GEOMGUI_Selection(); @@ -1542,7 +1573,7 @@ void GeometryGUI::createPreferences() LightApp_Preferences::Selector, "Geometry", "type_of_marker" ); int markerScale = addPreference( tr( "PREF_MARKER_SCALE" ), VertexGroup, - LightApp_Preferences::DblSpin, "Geometry", "marker_scale" ); + LightApp_Preferences::Selector, "Geometry", "marker_scale" ); // Set property for default display mode QStringList aModesList; @@ -1561,47 +1592,32 @@ void GeometryGUI::createPreferences() setPreferenceProperty( step, "max", 10000 ); setPreferenceProperty( step, "precision", 3 ); - // Set property for type of vertex marker - QStringList aTypeOfMarkerList; - QList anTypeOfMarkerIndexesList; + // Set property vertex marker type + QList aMarkerTypeIndicesList; + QList aMarkerTypeIconsList; - aTypeOfMarkerList.append( tr("TOM_PLUS") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_PLUS); + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + for ( int i = GEOM::MT_POINT; i < GEOM::MT_USER; i++ ) { + QString icoFile = QString( "ICON_VERTEX_MARKER_%1" ).arg( i ); + QPixmap pixmap = resMgr->loadPixmap( "GEOM", tr( qPrintable( icoFile ) ) ); + aMarkerTypeIndicesList << (i-1); + aMarkerTypeIconsList << pixmap; + } - aTypeOfMarkerList.append( tr("TOM_POINT") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_POINT); + setPreferenceProperty( typeOfMarker, "indexes", aMarkerTypeIndicesList ); + setPreferenceProperty( typeOfMarker, "icons", aMarkerTypeIconsList ); - aTypeOfMarkerList.append( tr("TOM_STAR") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_STAR); + // Set property for vertex marker scale + QList aMarkerScaleIndicesList; + QStringList aMarkerScaleValuesList; - aTypeOfMarkerList.append( tr("TOM_O") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_O); - - aTypeOfMarkerList.append( tr("TOM_X") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_X); - - aTypeOfMarkerList.append( tr("TOM_O_POINT") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_O_POINT); - - aTypeOfMarkerList.append( tr("TOM_O_PLUS") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_O_PLUS); - - aTypeOfMarkerList.append( tr("TOM_O_STAR") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_O_STAR); - - aTypeOfMarkerList.append( tr("TOM_O_X") ); - anTypeOfMarkerIndexesList.append(Aspect_TOM_O_X); - - - setPreferenceProperty( typeOfMarker, "strings", aTypeOfMarkerList ); - setPreferenceProperty( typeOfMarker, "indexes", anTypeOfMarkerIndexesList ); - - // Set property for Vertex Marker scale - setPreferenceProperty( markerScale, "min", 1. ); - setPreferenceProperty( markerScale, "max", 7. ); - setPreferenceProperty( markerScale, "precision", 0.01 ); - setPreferenceProperty( markerScale, "step", 0.5 ); + for ( int i = GEOM::MS_10; i <= GEOM::MS_70; i++ ) { + aMarkerScaleIndicesList << i; + aMarkerScaleValuesList << QString::number( (i-(int)GEOM::MS_10)*0.5 + 1.0 ); + } + setPreferenceProperty( markerScale, "strings", aMarkerScaleValuesList ); + setPreferenceProperty( markerScale, "indexes", aMarkerScaleIndicesList ); } void GeometryGUI::preferencesChanged( const QString& section, const QString& param ) diff --git a/src/GEOMGUI/GeometryGUI.h b/src/GEOMGUI/GeometryGUI.h index a82efcb25..2cbd9d1dd 100644 --- a/src/GEOMGUI/GeometryGUI.h +++ b/src/GEOMGUI/GeometryGUI.h @@ -41,6 +41,7 @@ // OCCT Includes #include +#include // IDL headers #include "SALOMEconfig.h" @@ -54,6 +55,7 @@ class GEOMGUI_OCCSelector; class LightApp_VTKSelector; class LightApp_Selection; class SUIT_ViewManager; +class SalomeApp_Study; //================================================================================= // class : GeometryGUI @@ -74,6 +76,8 @@ public: virtual void initialize( CAM_Application* ); virtual QString engineIOR() const; + static Handle(Graphic3d_HArray1OfBytes) getTexture( SalomeApp_Study*, int, int&, int& ); + static bool InitGeomGen(); //BugID IPAL9186: SRN: To be called by Python scripts static GEOM::GEOM_Gen_var GetGeomGen();// { return GeometryGUI::myComponentGeom; } @@ -159,7 +163,12 @@ private: public: static GEOM::GEOM_Gen_var myComponentGeom; // GEOM engine!!! + private: + + typedef QMap TextureMap; + typedef QMap StudyTextureMap; + GUIMap myGUIMap; // GUI libraries map QDialog* myActiveDialogBox; // active dialog box GEOM_Client myShapeReader; // geom shape reader @@ -167,6 +176,7 @@ private: int myState; // identify a method gp_Ax3 myWorkingPlane; QMap myRules; // popup rules + static StudyTextureMap myTextureMap; // texture map QList myOCCSelectors; QList myVTKSelectors; @@ -174,7 +184,7 @@ private: LightApp_Displayer* myDisplayer; int myLocalSelectionMode; //Select Only -friend class DisplayGUI; + friend class DisplayGUI; }; #endif diff --git a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx index 0a2c4d6e0..586967966 100644 --- a/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IBlocksOperations.cxx @@ -2350,9 +2350,9 @@ Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges } //Make a Python command - GEOM::TPythonDump(aFunction) << aCopy - << " = geompy.RemoveExtraEdges(" << theObject - << ", " << theOptimumNbFaces << ")"; + std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True"; + GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges(" + << theObject << ", " << doUnionFaces.data() << ")"; SetErrorCode(OK); return aCopy; diff --git a/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx b/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx index b9734d9c4..ab894fcbc 100644 --- a/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IGroupOperations.cxx @@ -567,13 +567,17 @@ void GEOMImpl_IGroupOperations::UnionIDs (Handle(GEOM_Object) theGroup, TopTools_IndexedMapOfShape mapIndices; TopExp::MapShapes(aMainShape, mapIndices); + // Get group type + TopAbs_ShapeEnum aType = GetType(theGroup); + // Get IDs of sub-shapes to add Standard_Integer i, new_id; for (i = 1; i <= aLen; i++) { new_id = theSubShapes->Value(i); if (0 < new_id && new_id <= mapIndices.Extent()) { - if (mapIDs.Add(new_id)) { + //if (mapIDs.Add(new_id)) { IPAL21297. Why we ignore invalid ids silently? + if (mapIDs.Add(new_id) && mapIndices(new_id).ShapeType()==aType ) { aNewIDs.Append(new_id); } } diff --git a/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx b/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx index 102ebba74..80f4a2962 100644 --- a/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC @@ -240,8 +241,10 @@ Handle(GEOM_Object) GEOMImpl_IInsertOperations::Import } //Make a Python command - GEOM::TPythonDump(aFunction) << result << " = geompy.Import(\"" - << theFileName.ToCString() << "\", \"" << theFormatName.ToCString() << "\")"; + if( theFormatName != "IGES_UNIT" ) { + GEOM::TPythonDump(aFunction) << result << " = geompy.Import(\"" + << theFileName.ToCString() << "\", \"" << theFormatName.ToCString() << "\")"; + } SetErrorCode(OK); @@ -541,3 +544,98 @@ Standard_Boolean GEOMImpl_IInsertOperations::InitResMgr() return ( myResMgr->Find("Import") || myResMgr->Find("Export") || myResMgrUser->Find("Import") || myResMgrUser->Find("Export")); } + +int GEOMImpl_IInsertOperations::LoadTexture(const TCollection_AsciiString& theTextureFile) +{ + SetErrorCode(KO); + + if (theTextureFile.IsEmpty()) return 0; + + Handle(TDataStd_HArray1OfByte) aTexture; + + FILE* fp = fopen(theTextureFile.ToCString(), "r"); + if (!fp) return 0; + + std::list lines; + char buffer[4096]; + int maxlen = 0; + while (!feof(fp)) { + if ((fgets(buffer, 4096, fp)) == NULL) break; + int aLen = strlen(buffer); + if (buffer[aLen-1] == '\n') buffer[aLen-1] = '\0'; + lines.push_back(buffer); + maxlen = std::max(maxlen, (int)strlen(buffer)); + } + + fclose(fp); + + int lenbytes = maxlen/8; + if (maxlen%8) lenbytes++; + + if (lenbytes == 0 || lines.empty()) + return 0; + + std::list bytedata; + std::list::const_iterator it; + for (it = lines.begin(); it != lines.end(); ++it) { + std::string line = *it; + int lenline = (line.size()/8 + (line.size()%8 ? 1 : 0)) * 8; + for (int i = 0; i < lenline/8; i++) { + unsigned char byte = 0; + for (int j = 0; j < 8; j++) + byte = (byte << 1) + ( i*8+j < line.size() && line[i*8+j] != '0' ? 1 : 0 ); + bytedata.push_back(byte); + } + for (int i = lenline/8; i < lenbytes; i++) + bytedata.push_back((unsigned char)0); + } + + if (bytedata.empty() || bytedata.size() != lines.size()*lenbytes) + return 0; + + aTexture = new TDataStd_HArray1OfByte(1, lines.size()*lenbytes); + std::list::iterator bdit; + int i; + for (i = 1, bdit = bytedata.begin(); bdit != bytedata.end(); ++bdit, ++i) + aTexture->SetValue(i, (Standard_Byte)(*bdit)); + + int aTextureId = GetEngine()->addTexture(GetDocID(), lenbytes*8, lines.size(), aTexture, theTextureFile); + if (aTextureId > 0) SetErrorCode(OK); + return aTextureId; +} + +int GEOMImpl_IInsertOperations::AddTexture(int theWidth, int theHeight, + const Handle(TDataStd_HArray1OfByte)& theTexture) +{ + SetErrorCode(KO); + int aTextureId = GetEngine()->addTexture(GetDocID(), theWidth, theHeight, theTexture); + if (aTextureId > 0) SetErrorCode(OK); + return aTextureId; +} + +Handle(TDataStd_HArray1OfByte) GEOMImpl_IInsertOperations::GetTexture(int theTextureId, + int& theWidth, int& theHeight) +{ + SetErrorCode(KO); + + Handle(TDataStd_HArray1OfByte) aTexture; + theWidth = theHeight = 0; + TCollection_AsciiString aFileName; + + if (theTextureId <= 0) + return aTexture; + + aTexture = GetEngine()->getTexture(GetDocID(), theTextureId, theWidth, theHeight, aFileName); + + if (theWidth > 0 && theHeight > 0 && aTexture->Length() > 0) SetErrorCode(OK); + + return aTexture; +} + +std::list GEOMImpl_IInsertOperations::GetAllTextures() +{ + SetErrorCode(KO); + std::list id_list = GetEngine()->getAllTextures(GetDocID()); + SetErrorCode(OK); + return id_list; +} diff --git a/src/GEOMImpl/GEOMImpl_IInsertOperations.hxx b/src/GEOMImpl/GEOMImpl_IInsertOperations.hxx index aba0c227f..51d2ed350 100644 --- a/src/GEOMImpl/GEOMImpl_IInsertOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IInsertOperations.hxx @@ -30,6 +30,9 @@ #include #include #include +#include + +class Handle_TDataStd_HArray1OfByte; class GEOMImpl_IInsertOperations : public GEOM_IOperations { public: @@ -56,6 +59,16 @@ class GEOMImpl_IInsertOperations : public GEOM_IOperations { const TCollection_AsciiString& theFormat, Handle(TCollection_HAsciiString)& theLibName); + Standard_EXPORT int LoadTexture(const TCollection_AsciiString& theTextureFile); + + Standard_EXPORT int AddTexture(int theWidth, int theHeight, + const Handle(TDataStd_HArray1OfByte)& theTexture); + + Standard_EXPORT Handle(TDataStd_HArray1OfByte) GetTexture(int theTextureId, + int& theWidth, int& theHeight); + + Standard_EXPORT std::list GetAllTextures(); + private: Standard_Boolean InitResMgr (); diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index cb173b0c4..0eff72be4 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -941,7 +941,7 @@ Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::SubShapeAllIDs } else { TopExp_Explorer exp (aShape, TopAbs_ShapeEnum(theShapeType)); for (; exp.More(); exp.Next()) - if (!exp.Current().IsSame(aShape) && mapShape.Add(exp.Current())) + if (mapShape.Add(exp.Current())) listShape.Append(exp.Current()); } diff --git a/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx b/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx index 40d68aa88..7f54d9abf 100644 --- a/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx @@ -261,6 +261,15 @@ Standard_Integer GEOMImpl_PartitionDriver::Execute(TFunction_Logbook& log) const aShape = PS.Shape(); if (aShape.IsNull()) return 0; + //Alternative case to check not valid partition IPAL21418 + TopoDS_Iterator It (aShape, Standard_True, Standard_True); + int nbSubshapes=0; + for (; It.More(); It.Next()) + nbSubshapes++; + if (!nbSubshapes) + Standard_ConstructionError::Raise("Partition aborted : non valid shape result"); + //end of IPAL21418 + if (!BRepAlgo::IsValid(aShape)) { // 08.07.2008 added by skl during fixing bug 19761 from Mantis ShapeFix_ShapeTolerance aSFT; diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx index 212575e3a..e35a5119c 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx @@ -94,7 +94,6 @@ #include "utilities.h" - //======================================================================= //function : GetID //purpose : @@ -105,7 +104,6 @@ const Standard_GUID& GEOMImpl_PipeDriver::GetID() return aPipeDriver; } - //======================================================================= //function : GEOMImpl_PipeDriver //purpose : @@ -114,15 +112,14 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver() { } - //======================================================================= //function : FillForOtherEdges //purpose : auxilary for CreatePipeForShellSections() //======================================================================= static bool FillForOtherEdges(const TopoDS_Shape& F1, - const TopoDS_Shape& E1, - const TopoDS_Shape& V1, - TopTools_IndexedDataMapOfShapeShape& FF) + const TopoDS_Shape& E1, + const TopoDS_Shape& V1, + TopTools_IndexedDataMapOfShapeShape& FF) { //cout<<"FillForOtherEdges"<0 && Num2>0 ) { TopoDS_Wire W; B.MakeWire(W); for(i=Num1; i<=Num2; i++) { - B.Add(W,Edges.Value(i)); + B.Add(W,Edges.Value(i)); } Wires.Append(W); } @@ -727,7 +719,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, if( PF.Distance(PLocs.First()) > tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise - ("First location shapes is not coincided with first vertex of aWirePath"); + ("First location shapes is not coincided with first vertex of aWirePath"); } VLocs.ChangeValue(1) = VF; edge = TopoDS::Edge(Edges.Last()); @@ -737,7 +729,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, if( PL.Distance(PLocs.Last()) > tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise - ("Last location shapes is not coincided with last vertex of aWirePath"); + ("Last location shapes is not coincided with last vertex of aWirePath"); } VLocs.ChangeValue(nbLocs) = VL; int jcurr = 2; @@ -750,73 +742,73 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); if( P2.Distance(PLocs.Value(jcurr)) < tol ) { - // make wire from current edge and add created - // wire to Wires - TopoDS_Wire W; - B.MakeWire(W); - for(j=1; j<=tmpEdges.Length(); j++) - B.Add(W,tmpEdges.Value(j)); - B.Add(W,E); - Wires.Append(W); - VLocs.ChangeValue(jcurr) = V2; - jcurr++; - tmpEdges.Clear(); + // make wire from current edge and add created + // wire to Wires + TopoDS_Wire W; + B.MakeWire(W); + for(j=1; j<=tmpEdges.Length(); j++) + B.Add(W,tmpEdges.Value(j)); + B.Add(W,E); + Wires.Append(W); + VLocs.ChangeValue(jcurr) = V2; + jcurr++; + tmpEdges.Clear(); } else { - // find distance between E and aLocs(jcurr) - double fp,lp; - Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp); - GeomAPI_ProjectPointOnCurve PPC (PLocs.Value(jcurr),C); - if( PPC.NbPoints()>0 && - PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { - double param = PPC.Parameter(1); - gp_Pnt PC1; - C->D0(param,PC1); - // split current edge - Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); - Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); - TopoDS_Edge E1,E2; - gp_Pnt Pfp; - C->D0(fp,Pfp); - if(Pfp.Distance(P1)0 && + PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { + double param = PPC.Parameter(1); + gp_Pnt PC1; + C->D0(param,PC1); + // split current edge + Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); + Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); + TopoDS_Edge E1,E2; + gp_Pnt Pfp; + C->D0(fp,Pfp); + if(Pfp.Distance(P1)Value(i); @@ -898,69 +890,69 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, TColgp_SequenceOfPnt aPnts; double xc=0, yc=0, zc=0; for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) { - TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); - aPnts.Append(BRep_Tool::Pnt(V)); - xc += aPnts.Last().X(); - yc += aPnts.Last().Y(); - zc += aPnts.Last().Z(); + TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); + aPnts.Append(BRep_Tool::Pnt(V)); + xc += aPnts.Last().X(); + yc += aPnts.Last().Y(); + zc += aPnts.Last().Z(); } gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() ); gp_Vec V1(PC,aPnts.Value(1)); gp_Vec V2(PC,aPnts.Value(2)); gp_Vec VN = V1.Crossed(V2); for(int ip=2; ipD0(fp,P1); - if( P1.Distance(PLoc) < tol ) { - C->D0(fp+(lp-fp)/100,P2); - } - else { - C->D0(lp,P1); - C->D0(lp+(fp-lp)/100,P2); - } - PathNorm = gp_Vec(P1,P2); - break; - } - else { - TopoDS_Vertex VL = sae.LastVertex(edge); - gp_Pnt PL = BRep_Tool::Pnt(VL); - if( PL.Distance(PLoc) < tol ) { - double fp,lp; - Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); - gp_Pnt P1,P2; - C->D0(fp,P1); - if( P1.Distance(PLoc) < tol ) { - C->D0(fp+(lp-fp)/100,P2); - } - else { - C->D0(lp,P1); - C->D0(lp+(fp-lp)/100,P2); - } - PathNorm = gp_Vec(P2,P1); - break; - } - } + TopoDS_Edge edge = TopoDS::Edge(WE.Current()); + double tol = BRep_Tool::Tolerance(edge); + TopoDS_Vertex VF = sae.FirstVertex(edge); + gp_Pnt PF = BRep_Tool::Pnt(VF); + if( PF.Distance(PLoc) < tol ) { + double fp,lp; + Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); + gp_Pnt P1,P2; + C->D0(fp,P1); + if( P1.Distance(PLoc) < tol ) { + C->D0(fp+(lp-fp)/100,P2); + } + else { + C->D0(lp,P1); + C->D0(lp+(fp-lp)/100,P2); + } + PathNorm = gp_Vec(P1,P2); + break; + } + else { + TopoDS_Vertex VL = sae.LastVertex(edge); + gp_Pnt PL = BRep_Tool::Pnt(VL); + if( PL.Distance(PLoc) < tol ) { + double fp,lp; + Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); + gp_Pnt P1,P2; + C->D0(fp,P1); + if( P1.Distance(PLoc) < tol ) { + C->D0(fp+(lp-fp)/100,P2); + } + else { + C->D0(lp,P1); + C->D0(lp+(fp-lp)/100,P2); + } + PathNorm = gp_Vec(P2,P1); + break; + } + } } cout<<"VN("<PI/2.) { - NeedReverse = true; - aShBase1.Reverse(); + NeedReverse = true; + aShBase1.Reverse(); } } { @@ -970,68 +962,68 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, TColgp_SequenceOfPnt aPnts; double xc=0, yc=0, zc=0; for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) { - TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); - aPnts.Append(BRep_Tool::Pnt(V)); - xc += aPnts.Last().X(); - yc += aPnts.Last().Y(); - zc += aPnts.Last().Z(); + TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); + aPnts.Append(BRep_Tool::Pnt(V)); + xc += aPnts.Last().X(); + yc += aPnts.Last().Y(); + zc += aPnts.Last().Z(); } gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() ); gp_Vec V1(PC,aPnts.Value(1)); gp_Vec V2(PC,aPnts.Value(2)); gp_Vec VN = V1.Crossed(V2); for(int ip=2; ipD0(fp,P1); - if( P1.Distance(PLoc) < tol ) { - C->D0(fp+(lp-fp)/100,P2); - } - else { - C->D0(lp,P1); - C->D0(lp+(fp-lp)/100,P2); - } - PathNorm = gp_Vec(P2,P1); - break; - } - else { - TopoDS_Vertex VL = sae.LastVertex(edge); - gp_Pnt PL = BRep_Tool::Pnt(VL); - if( PL.Distance(PLoc) < tol ) { - double fp,lp; - Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); - gp_Pnt P1,P2; - C->D0(fp,P1); - if( P1.Distance(PLoc) < tol ) { - C->D0(fp+(lp-fp)/100,P2); - } - else { - C->D0(lp,P1); - C->D0(lp+(fp-lp)/100,P2); - } - PathNorm = gp_Vec(P2,P1); - break; - } - } + TopoDS_Edge edge = TopoDS::Edge(WE.Current()); + double tol = BRep_Tool::Tolerance(edge); + TopoDS_Vertex VF = sae.FirstVertex(edge); + gp_Pnt PF = BRep_Tool::Pnt(VF); + if( PF.Distance(PLoc) < tol ) { + double fp,lp; + Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); + gp_Pnt P1,P2; + C->D0(fp,P1); + if( P1.Distance(PLoc) < tol ) { + C->D0(fp+(lp-fp)/100,P2); + } + else { + C->D0(lp,P1); + C->D0(lp+(fp-lp)/100,P2); + } + PathNorm = gp_Vec(P2,P1); + break; + } + else { + TopoDS_Vertex VL = sae.LastVertex(edge); + gp_Pnt PL = BRep_Tool::Pnt(VL); + if( PL.Distance(PLoc) < tol ) { + double fp,lp; + Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); + gp_Pnt P1,P2; + C->D0(fp,P1); + if( P1.Distance(PLoc) < tol ) { + C->D0(fp+(lp-fp)/100,P2); + } + else { + C->D0(lp,P1); + C->D0(lp+(fp-lp)/100,P2); + } + PathNorm = gp_Vec(P2,P1); + break; + } + } } //cout<<"VN("<PI/2.) - aShBase2.Reverse(); + aShBase2.Reverse(); } */ @@ -1040,114 +1032,114 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, TopoDS_Shape aWire1, aWire2; // prepare aWire1 if(aType1==TopAbs_SHELL) { - // create wire as boundary contour if shell is no closed - // get free boundary shapes - ShapeAnalysis_FreeBounds anAnalizer( aShBase1 ); - TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); - //TopExp_Explorer anExp; - Standard_Integer NbWires = 0; - for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { - NbWires++; - aWire1 = anExp.Current(); - } - if(NbWires!=1) { - // bad case - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Bad shell is used as section "); - } + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShBase1 ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + //TopExp_Explorer anExp; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire1 = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } } else { // aType1==TopAbs_FACE - TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE); - aWire1 = aExpW.Current(); + TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE); + aWire1 = aExpW.Current(); } // prepare aWire2 if(aType2==TopAbs_SHELL) { - // create wire as boundary contour if shell is no closed - // get free boundary shapes - ShapeAnalysis_FreeBounds anAnalizer( aShBase2 ); - TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); - //TopExp_Explorer anExp; - Standard_Integer NbWires = 0; - for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { - NbWires++; - aWire2 = anExp.Current(); - } - if(NbWires!=1) { - // bad case - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Bad shell is used as section "); - } + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShBase2 ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + //TopExp_Explorer anExp; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire2 = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } } else { // aType2==TopAbs_FACE - TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE); - aWire2 = aExpW.Current(); + TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE); + aWire2 = aExpW.Current(); } // make pipe using aWire1 and aWire2 if( !aWire1.IsNull() && !aWire2.IsNull() ) { - //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); - BRepOffsetAPI_MakePipeShell aBuilder(WPath); - aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), - aWithContact, aWithCorrect); - aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), - aWithContact, aWithCorrect); - if(!aBuilder.IsReady()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); - } - aBuilder.Build(); - TopoDS_Shape aShape = aBuilder.Shape(); - TopoDS_Shell aShell; - B.MakeShell(aShell); - for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - B.Add(aShell,anExp.Current()); - } - for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - B.Add(aShell,anExp.Current()); - } - for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - B.Add(aShell,anExp.Current()); - } - // make sewing for this shell - Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; - aSewing->SetTolerance(Precision::Confusion()); - aSewing->SetFaceMode(Standard_True); - aSewing->SetFloatingEdgesMode(Standard_False); - aSewing->SetNonManifoldMode(Standard_False); - for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - aSewing->Add(anExp.Current()); - } - aSewing->Perform(); - const TopoDS_Shape aSewShape = aSewing->SewedShape(); - if( aSewShape.ShapeType() == TopAbs_SHELL ) { - aShell = TopoDS::Shell(aSewShape); - GProp_GProps aSystem; - BRepGProp::VolumeProperties(aShell, aSystem); - if(aSystem.Mass()<0) { - aShell.Reverse(); - } - if(BRep_Tool::IsClosed(aShell)) { - TopoDS_Solid aSolid; - B.MakeSolid(aSolid); - B.Add(aSolid,aShell); - B.Add(aComp,aSolid); - } - else { - B.Add(aComp,aShell); - } - } - else { - B.Add(aComp,aShell); - } + //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); + BRepOffsetAPI_MakePipeShell aBuilder(WPath); + aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), + aWithContact, aWithCorrect); + aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), + aWithContact, aWithCorrect); + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + TopoDS_Shape aShape = aBuilder.Shape(); + TopoDS_Shell aShell; + B.MakeShell(aShell); + for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } + // make sewing for this shell + Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; + aSewing->SetTolerance(Precision::Confusion()); + aSewing->SetFaceMode(Standard_True); + aSewing->SetFloatingEdgesMode(Standard_False); + aSewing->SetNonManifoldMode(Standard_False); + for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + aSewing->Add(anExp.Current()); + } + aSewing->Perform(); + const TopoDS_Shape aSewShape = aSewing->SewedShape(); + if( aSewShape.ShapeType() == TopAbs_SHELL ) { + aShell = TopoDS::Shell(aSewShape); + GProp_GProps aSystem; + BRepGProp::VolumeProperties(aShell, aSystem); + if(aSystem.Mass()<0) { + aShell.Reverse(); + } + if(BRep_Tool::IsClosed(aShell)) { + TopoDS_Solid aSolid; + B.MakeSolid(aSolid); + B.Add(aSolid,aShell); + B.Add(aComp,aSolid); + } + else { + B.Add(aComp,aShell); + } + } + else { + B.Add(aComp,aShell); + } } } else { // main block - creation few solids (for each pair of faces) TopTools_MapOfShape aFaces1,aFaces2; for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - aFaces1.Add(anExp.Current()); + aFaces1.Add(anExp.Current()); } for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - aFaces2.Add(anExp.Current()); + aFaces2.Add(anExp.Current()); } // creating map of edge faces TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1; @@ -1159,220 +1151,219 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, TopTools_IndexedDataMapOfShapeShape FF; TopoDS_Shape FS1,FS2; if(nbSubBases==0) { - // find edge the most distant from location point - // (this edge is not shared by two faces) - double maxdist = 0.; - TopoDS_Shape E1; - TopoDS_Vertex V11,V21; - for(j=1; j<=aMapEdgeFaces1.Extent(); j++) { - TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j); - const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp); - if(aList.Extent()>1) - continue; - TopExp_Explorer expv; - expv.Init( tmp, TopAbs_VERTEX ); - TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current()); - expv.Next(); - TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current()); - gp_Pnt P1 = BRep_Tool::Pnt(V1); - gp_Pnt P2 = BRep_Tool::Pnt(V2); - double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2); - if(dist>maxdist) { - E1 = tmp; - V11 = V1; - V21 = V2; - TopTools_ListIteratorOfListOfShape anIter(aList); - FS1 = anIter.Value(); - maxdist = dist; - } - } - // main direction for comparing - gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1)); - // find corresponding edge from next section - double minang = PI; - gp_Pnt P11 = BRep_Tool::Pnt(V11); - gp_Pnt P21 = BRep_Tool::Pnt(V21); - TopoDS_Shape E2; - TopoDS_Vertex V12,V22; - for(j=1; j<=aMapEdgeFaces2.Extent(); j++) { - TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j); - const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp); - if(aList.Extent()>1) - continue; - TopExp_Explorer expv; - expv.Init( tmp, TopAbs_VERTEX ); - TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current()); - expv.Next(); - TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current()); - gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp); - gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp); - double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21); - double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11); - TopoDS_Vertex V1,V2; - gp_Pnt P1,P2; - if(d1>d2) { - V1 = V2tmp; P1 = P2tmp; - V2 = V1tmp; P2 = P1tmp; - } - else { - V1 = V1tmp; P1 = P1tmp; - V2 = V2tmp; P2 = P2tmp; - } - gp_Vec Vec1(P11,P1); - gp_Vec Vec2(P21,P2); - double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM)); - if(ang1) + continue; + TopExp_Explorer expv; + expv.Init( tmp, TopAbs_VERTEX ); + TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current()); + expv.Next(); + TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current()); + gp_Pnt P1 = BRep_Tool::Pnt(V1); + gp_Pnt P2 = BRep_Tool::Pnt(V2); + double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2); + if(dist>maxdist) { + E1 = tmp; + V11 = V1; + V21 = V2; + TopTools_ListIteratorOfListOfShape anIter(aList); + FS1 = anIter.Value(); + maxdist = dist; + } + } + // main direction for comparing + gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1)); + // find corresponding edge from next section + double minang = PI; + gp_Pnt P11 = BRep_Tool::Pnt(V11); + gp_Pnt P21 = BRep_Tool::Pnt(V21); + TopoDS_Shape E2; + TopoDS_Vertex V12,V22; + for(j=1; j<=aMapEdgeFaces2.Extent(); j++) { + TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j); + const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp); + if(aList.Extent()>1) + continue; + TopExp_Explorer expv; + expv.Init( tmp, TopAbs_VERTEX ); + TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current()); + expv.Next(); + TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current()); + gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp); + gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp); + double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21); + double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11); + TopoDS_Vertex V1,V2; + gp_Pnt P1,P2; + if(d1>d2) { + V1 = V2tmp; P1 = P2tmp; + V2 = V1tmp; P2 = P1tmp; + } + else { + V1 = V1tmp; P1 = P1tmp; + V2 = V2tmp; P2 = P2tmp; + } + gp_Vec Vec1(P11,P1); + gp_Vec Vec2(P21,P2); + double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM)); + if(angValue(i); - if(anItem.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); - if(aRefBase.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - TopoDS_Shape aSh = aRefBase->GetValue(); - if(aSh.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - if(aSh.ShapeType()!=TopAbs_FACE) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - FS1 = aSh; - } - { // 2 section - Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1); - if(anItem.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); - if(aRefBase.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - TopoDS_Shape aSh = aRefBase->GetValue(); - if(aSh.IsNull()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - if(aSh.ShapeType()!=TopAbs_FACE) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } - FS2 = aSh; - } + { // 1 section + Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i); + if(anItem.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); + if(aRefBase.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + TopoDS_Shape aSh = aRefBase->GetValue(); + if(aSh.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + if(aSh.ShapeType()!=TopAbs_FACE) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + FS1 = aSh; + } + { // 2 section + Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1); + if(anItem.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); + if(aRefBase.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + TopoDS_Shape aSh = aRefBase->GetValue(); + if(aSh.IsNull()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + if(aSh.ShapeType()!=TopAbs_FACE) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } + FS2 = aSh; + } - if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid subbase shape"); - } + if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid subbase shape"); + } - FF.Add(FS1,FS2); + FF.Add(FS1,FS2); - // add pairs of edges to FF - bool stat = FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)), - TopoDS::Vertex(VLocs(i+1)), WPath, FF); - if( !stat ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Can not create correct pipe"); - } + // add pairs of edges to FF + bool stat = FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)), + TopoDS::Vertex(VLocs(i+1)), WPath, FF); + if( !stat ) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Can not create correct pipe"); + } } FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); - // make pipe for each pair of faces for(j=1; j<=FF.Extent(); j++) { - TopoDS_Shape F1 = FF.FindKey(j); - if( F1.ShapeType() != TopAbs_FACE ) - continue; - TopoDS_Shape F2 = FF.FindFromIndex(j); - TopExp_Explorer aExpW1(F1,TopAbs_WIRE); - TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current()); - TopExp_Explorer aExpW2(F2,TopAbs_WIRE); - TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current()); - // make pipe using aWire1 and aWire2 - if( !aWire1.IsNull() && !aWire2.IsNull() ) { - BRepOffsetAPI_MakePipeShell aBuilder(WPath); - aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), - aWithContact, aWithCorrect); - aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), - aWithContact, aWithCorrect); - if(!aBuilder.IsReady()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); - } - aBuilder.Build(); - TopoDS_Shape aShape = aBuilder.Shape(); - TopoDS_Shell aShell; - B.MakeShell(aShell); - for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - B.Add(aShell,anExp.Current()); - } + TopoDS_Shape F1 = FF.FindKey(j); + if( F1.ShapeType() != TopAbs_FACE ) + continue; + TopoDS_Shape F2 = FF.FindFromIndex(j); + TopExp_Explorer aExpW1(F1,TopAbs_WIRE); + TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current()); + TopExp_Explorer aExpW2(F2,TopAbs_WIRE); + TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current()); + // make pipe using aWire1 and aWire2 + if( !aWire1.IsNull() && !aWire2.IsNull() ) { + BRepOffsetAPI_MakePipeShell aBuilder(WPath); + aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), + aWithContact, aWithCorrect); + aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), + aWithContact, aWithCorrect); + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + TopoDS_Shape aShape = aBuilder.Shape(); + TopoDS_Shell aShell; + B.MakeShell(aShell); + for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + B.Add(aShell,anExp.Current()); + } - B.Add(aShell,F1); - B.Add(aShell,F2); - // make sewing for this shell - Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; - aSewing->SetTolerance(Precision::Confusion()); - aSewing->SetFaceMode(Standard_True); - aSewing->SetFloatingEdgesMode(Standard_False); - aSewing->SetNonManifoldMode(Standard_False); - for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - aSewing->Add(anExp.Current()); - } - aSewing->Perform(); - const TopoDS_Shape aSewShape = aSewing->SewedShape(); - if( aSewShape.ShapeType() == TopAbs_SHELL ) { - aShell = TopoDS::Shell(aSewShape); - GProp_GProps aSystem; - BRepGProp::VolumeProperties(aShell, aSystem); - if(aSystem.Mass()<0) { - //cout<<"aSewShape is reversed"<SetTolerance(Precision::Confusion()); + aSewing->SetFaceMode(Standard_True); + aSewing->SetFloatingEdgesMode(Standard_False); + aSewing->SetNonManifoldMode(Standard_False); + for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { + aSewing->Add(anExp.Current()); + } + aSewing->Perform(); + const TopoDS_Shape aSewShape = aSewing->SewedShape(); + if( aSewShape.ShapeType() == TopAbs_SHELL ) { + aShell = TopoDS::Shell(aSewShape); + GProp_GProps aSystem; + BRepGProp::VolumeProperties(aShell, aSystem); + if(aSystem.Mass()<0) { + //cout<<"aSewShape is reversed"<IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { - Handle(Geom_RectangularTrimmedSurface) RTS = - Handle(Geom_RectangularTrimmedSurface)::DownCast(S1); - S1 = RTS->BasisSurface(); + Handle(Geom_RectangularTrimmedSurface) RTS = + Handle(Geom_RectangularTrimmedSurface)::DownCast(S1); + S1 = RTS->BasisSurface(); } Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1); if( Pln1.IsNull() ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Surface from face is not plane"); + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Surface from face is not plane"); } gp_Vec aDir1(Pln1->Axis().Direction()); Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2)); if(S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { - Handle(Geom_RectangularTrimmedSurface) RTS = - Handle(Geom_RectangularTrimmedSurface)::DownCast(S2); - S2 = RTS->BasisSurface(); + Handle(Geom_RectangularTrimmedSurface) RTS = + Handle(Geom_RectangularTrimmedSurface)::DownCast(S2); + S2 = RTS->BasisSurface(); } Handle(Geom_Plane) Pln2 = - Handle(Geom_Plane)::DownCast(S2); + Handle(Geom_Plane)::DownCast(S2); if( Pln2.IsNull() ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Surface from face is not plane"); + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Surface from face is not plane"); } gp_Vec aDir2(Pln2->Axis().Direction()); @@ -1542,247 +1531,247 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1))); gp_Vec aDir(P1,P2); if(fabs(aDir.Angle(aDir1))>PI/2.) - aDir1.Reverse(); + aDir1.Reverse(); if(fabs(aDir.Angle(aDir2))>PI/2.) - aDir2.Reverse(); + aDir2.Reverse(); TopExp_Explorer anExpE(F1,TopAbs_EDGE); TopTools_SequenceOfShape aNewFs; //int nbee=0; for(; anExpE.More(); anExpE.Next()) { - TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current()); - //nbee++; - if(!FF.Contains(E1)) - MESSAGE ("map FF not contains key E1"); + TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current()); + //nbee++; + if(!FF.Contains(E1)) + MESSAGE ("map FF not contains key E1"); - if(VPE.Contains(E1)) { - aNewFs.Append(VPE.FindFromKey(E1)); + if(VPE.Contains(E1)) { + aNewFs.Append(VPE.FindFromKey(E1)); #ifdef _DEBUG_ - MESSAGE (" using existed face"); + MESSAGE (" using existed face"); #endif - continue; - } + continue; + } - TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1)); - TopoDS_Vertex V1 = sae.FirstVertex(E1); - TopoDS_Vertex V2 = sae.LastVertex(E1); - if(!FF.Contains(V1)) - MESSAGE ("map FF not contains key V1"); - if(!FF.Contains(V2)) - MESSAGE ("map FF not contains key V2"); - TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2)); - TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1)); - TopoDS_Vertex Vtmp = sae.FirstVertex(E3); - if(Vtmp.IsSame(V4)) - E3.Reverse(); - gp_Pnt P1 = BRep_Tool::Pnt(V1); - gp_Pnt P2 = BRep_Tool::Pnt(V2); - gp_Pnt P3 = BRep_Tool::Pnt(V3); - gp_Pnt P4 = BRep_Tool::Pnt(V4); - // make E2 - TopoDS_Edge E2; - Handle(Geom_BSplineCurve) C2; - if(VPE.Contains(V2)) { - E2 = TopoDS::Edge(VPE.FindFromKey(V2)); - double fp,lp; - C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp)); - } - else { - Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); - HAP->SetValue(1,P2); - HAP->SetValue(2,P3); - GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); - anInt.Load(aDir1,aDir2); - anInt.Perform(); - C2 = anInt.Curve(); - B.MakeEdge(E2,C2,1.e-7); - B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD))); - B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED))); - VPE.Add(V2,E2); - } - // make E4 - TopoDS_Edge E4; - Handle(Geom_BSplineCurve) C4; - if(VPE.Contains(V1)) { - E4 = TopoDS::Edge(VPE.FindFromKey(V1)); - double fp,lp; - C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp)); - } - else { - Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); - HAP->SetValue(1,P1); - HAP->SetValue(2,P4); - GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); - anInt.Load(aDir1,aDir2); - anInt.Perform(); - C4 = anInt.Curve(); - B.MakeEdge(E4,anInt.Curve(),1.e-7); - B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD))); - B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED))); - VPE.Add(V1,E4); - } + TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1)); + TopoDS_Vertex V1 = sae.FirstVertex(E1); + TopoDS_Vertex V2 = sae.LastVertex(E1); + if(!FF.Contains(V1)) + MESSAGE ("map FF not contains key V1"); + if(!FF.Contains(V2)) + MESSAGE ("map FF not contains key V2"); + TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2)); + TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1)); + TopoDS_Vertex Vtmp = sae.FirstVertex(E3); + if(Vtmp.IsSame(V4)) + E3.Reverse(); + gp_Pnt P1 = BRep_Tool::Pnt(V1); + gp_Pnt P2 = BRep_Tool::Pnt(V2); + gp_Pnt P3 = BRep_Tool::Pnt(V3); + gp_Pnt P4 = BRep_Tool::Pnt(V4); + // make E2 + TopoDS_Edge E2; + Handle(Geom_BSplineCurve) C2; + if(VPE.Contains(V2)) { + E2 = TopoDS::Edge(VPE.FindFromKey(V2)); + double fp,lp; + C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp)); + } + else { + Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); + HAP->SetValue(1,P2); + HAP->SetValue(2,P3); + GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); + anInt.Load(aDir1,aDir2); + anInt.Perform(); + C2 = anInt.Curve(); + B.MakeEdge(E2,C2,1.e-7); + B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD))); + B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED))); + VPE.Add(V2,E2); + } + // make E4 + TopoDS_Edge E4; + Handle(Geom_BSplineCurve) C4; + if(VPE.Contains(V1)) { + E4 = TopoDS::Edge(VPE.FindFromKey(V1)); + double fp,lp; + C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp)); + } + else { + Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); + HAP->SetValue(1,P1); + HAP->SetValue(2,P4); + GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); + anInt.Load(aDir1,aDir2); + anInt.Perform(); + C4 = anInt.Curve(); + B.MakeEdge(E4,anInt.Curve(),1.e-7); + B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD))); + B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED))); + VPE.Add(V1,E4); + } - TopoDS_Wire W; - B.MakeWire(W); - B.Add(W,E1); - B.Add(W,E2); - B.Add(W,E3); - B.Add(W,E4.Reversed()); - //cout<<" wire for edge "<IsKind(STANDARD_TYPE(Geom_Conic)) ) { - // IsConicC1 = true; - // cout<<"C1 - Geom_Conic"<IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic)) ) { - C1 = new Geom_TrimmedCurve(C1,fp,lp); - } - //if(IsConicC1) { - // double tol = BRep_Tool::Tolerance(E1); - // GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5); - // C1 = ApxC1.Curve(); - //} - Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp); - if( C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic)) ) { - C3 = new Geom_TrimmedCurve(C3,fp,lp); - } - //filebuf fic; - //ostream os(&fic); - //os.precision(15); - Handle(Geom_BSplineCurve) CE1 = - GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1); - if(CE1->Degree()<3) - CE1->IncreaseDegree(3); - Handle(Geom_BSplineCurve) CE2 = - GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1); - if(CE2->Degree()<3) - CE2->IncreaseDegree(3); - Handle(Geom_BSplineCurve) CE3 = - GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1); - if(CE3->Degree()<3) - CE3->IncreaseDegree(3); - Handle(Geom_BSplineCurve) CE4 = - GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1); - if(CE4->Degree()<3) - CE4->IncreaseDegree(3); - //cout<<"CE1->Degree()="<Degree()<<" CE2->Degree()="<Degree() - // <<" CE3->Degree()="<Degree()<<" CE4->Degree()="<Degree()<IsKind(STANDARD_TYPE(Geom_Conic)) ) { + // IsConicC1 = true; + // cout<<"C1 - Geom_Conic"<IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic)) ) { + C1 = new Geom_TrimmedCurve(C1,fp,lp); + } + //if(IsConicC1) { + // double tol = BRep_Tool::Tolerance(E1); + // GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5); + // C1 = ApxC1.Curve(); + //} + Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp); + if( C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic)) ) { + C3 = new Geom_TrimmedCurve(C3,fp,lp); + } + //filebuf fic; + //ostream os(&fic); + //os.precision(15); + Handle(Geom_BSplineCurve) CE1 = + GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1); + if(CE1->Degree()<3) + CE1->IncreaseDegree(3); + Handle(Geom_BSplineCurve) CE2 = + GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1); + if(CE2->Degree()<3) + CE2->IncreaseDegree(3); + Handle(Geom_BSplineCurve) CE3 = + GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1); + if(CE3->Degree()<3) + CE3->IncreaseDegree(3); + Handle(Geom_BSplineCurve) CE4 = + GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1); + if(CE4->Degree()<3) + CE4->IncreaseDegree(3); + //cout<<"CE1->Degree()="<Degree()<<" CE2->Degree()="<Degree() + // <<" CE3->Degree()="<Degree()<<" CE4->Degree()="<Degree()<D0(fp1,P1C1); - C1->D0(lp1,P2C1); - gp_Pnt P1C3,P2C3; - C3->D0(fp2,P1C3); - C3->D0(lp2,P2C3); - int n1,n2; - double fp,lp; - // get points from C1 - if(P1.Distance(P1C1)<1.e-6) { - fp = fp1; - lp = lp1; - } - else { - fp = lp1; - lp = fp1; - } - double step = (lp-fp)/(NbP-1); - Points.SetValue(1,1,P1); - double par = fp; - for(n1=2; n1D0(par,P); - Points.SetValue(1,n1,P); - } - Points.SetValue(1,NbP,P2); - // get points from C3 - if(P4.Distance(P1C3)<1.e-6) { - fp = fp2; - lp = lp2; - } - else { - fp = lp2; - lp = fp2; - } - step = (lp-fp)/(NbP-1); - Points.SetValue(NbP,1,P4); - par = fp; - for(n1=2; n1D0(par,P); - Points.SetValue(NbP,n1,P); - } - Points.SetValue(NbP,NbP,P3); - // create isolines and get points from them - for(n1=1; n1<=NbP; n1++) { - gp_Pnt PI1 = Points.Value(1,n1); - gp_Pnt PI2 = Points.Value(NbP,n1); - Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); - HAP->SetValue(1,PI1); - HAP->SetValue(2,PI2); - GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); - anInt.Load(aDir1,aDir2); - anInt.Perform(); - Handle(Geom_Curve) iso = anInt.Curve(); - fp = iso->FirstParameter(); - lp = iso->LastParameter(); - step = (lp-fp)/(NbP-1); - par = fp; - TopoDS_Compound VComp; - B.MakeCompound(VComp); - for(n2=2; n2D0(par,P); - Points.SetValue(n2,n1,P); - } - } - // create surface and face - //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points); - BS = new Geom_BezierSurface(Points); - } + Handle(Geom_Surface) BS; + try { + GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_CoonsStyle); + //GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_StretchStyle); + BS = GF.Surface(); + } + catch(...) { + MESSAGE (" can not create BSplineSurface - create Bezier"); + int NbP=26; + TColgp_Array2OfPnt Points(1,NbP,1,NbP); + double fp1,lp1,fp2,lp2; + Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp1,lp1); + Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp2,lp2); + gp_Pnt P1C1,P2C1; + C1->D0(fp1,P1C1); + C1->D0(lp1,P2C1); + gp_Pnt P1C3,P2C3; + C3->D0(fp2,P1C3); + C3->D0(lp2,P2C3); + int n1,n2; + double fp,lp; + // get points from C1 + if(P1.Distance(P1C1)<1.e-6) { + fp = fp1; + lp = lp1; + } + else { + fp = lp1; + lp = fp1; + } + double step = (lp-fp)/(NbP-1); + Points.SetValue(1,1,P1); + double par = fp; + for(n1=2; n1D0(par,P); + Points.SetValue(1,n1,P); + } + Points.SetValue(1,NbP,P2); + // get points from C3 + if(P4.Distance(P1C3)<1.e-6) { + fp = fp2; + lp = lp2; + } + else { + fp = lp2; + lp = fp2; + } + step = (lp-fp)/(NbP-1); + Points.SetValue(NbP,1,P4); + par = fp; + for(n1=2; n1D0(par,P); + Points.SetValue(NbP,n1,P); + } + Points.SetValue(NbP,NbP,P3); + // create isolines and get points from them + for(n1=1; n1<=NbP; n1++) { + gp_Pnt PI1 = Points.Value(1,n1); + gp_Pnt PI2 = Points.Value(NbP,n1); + Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); + HAP->SetValue(1,PI1); + HAP->SetValue(2,PI2); + GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); + anInt.Load(aDir1,aDir2); + anInt.Perform(); + Handle(Geom_Curve) iso = anInt.Curve(); + fp = iso->FirstParameter(); + lp = iso->LastParameter(); + step = (lp-fp)/(NbP-1); + par = fp; + TopoDS_Compound VComp; + B.MakeCompound(VComp); + for(n2=2; n2D0(par,P); + Points.SetValue(n2,n1,P); + } + } + // create surface and face + //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points); + BS = new Geom_BezierSurface(Points); + } - BRepBuilderAPI_MakeFace BB(BS,W); - TopoDS_Face NewF = BB.Face(); - Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF); - sff->Perform(); - sff->FixOrientation(); - TopoDS_Face FixedFace = sff->Face(); - aNewFs.Append(FixedFace); - VPE.Add(E1,FixedFace); - //cout<<" face for edge "<Perform(); + sff->FixOrientation(); + TopoDS_Face FixedFace = sff->Face(); + aNewFs.Append(FixedFace); + VPE.Add(E1,FixedFace); + //cout<<" face for edge "<SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - aSewing->Add(anExp.Current()); + aSewing->Add(anExp.Current()); } aSewing->Perform(); MESSAGE (" shell for face "<SewedShape(); //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep"); if( aSewShape.ShapeType() == TopAbs_SHELL ) { - aShell = TopoDS::Shell(aSewShape); - GProp_GProps aSystem; - BRepGProp::VolumeProperties(aShell, aSystem); - if(aSystem.Mass()<0) { - //cout<<"aSewShape is reversed"<Value(i); if(anItem.IsNull()) - continue; + continue; Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); if(aRefBase.IsNull()) - continue; + continue; TopoDS_Shape aShapeBase = aRefBase->GetValue(); if(aShapeBase.IsNull()) - continue; + continue; TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType(); //if for section was specified face with a few wires then a few // pipes were build and make solid Standard_Boolean NeedCreateSolid = Standard_False; if(aTypeBase == TopAbs_SHELL) { - // create wire as boundary contour if shell is no closed - // get free boundary shapes - ShapeAnalysis_FreeBounds anAnalizer( aShapeBase ); - TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); - TopExp_Explorer anExp; - TopoDS_Shape aWire; - Standard_Integer NbWires = 0; - for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { - NbWires++; - aWire = anExp.Current(); - } - if(NbWires!=1) { - // bad case - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Bad shell is used as section "); - } - NeedCreateSolid = Standard_True; + // create wire as boundary contour if shell is no closed + // get free boundary shapes + ShapeAnalysis_FreeBounds anAnalizer( aShapeBase ); + TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); + TopExp_Explorer anExp; + TopoDS_Shape aWire; + Standard_Integer NbWires = 0; + for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { + NbWires++; + aWire = anExp.Current(); + } + if(NbWires!=1) { + // bad case + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Bad shell is used as section "); + } + NeedCreateSolid = Standard_True; aSeqFaces.Append(aShapeBase); - aSeqBases.Append(aWire); + aSeqBases.Append(aWire); } else if(aTypeBase == TopAbs_FACE) { - NeedCreateSolid = Standard_True; - //for case one path should be used other type function + NeedCreateSolid = Standard_True; + //for case one path should be used other type function aSeqFaces.Append(aShapeBase); TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE); - for( ; aExpW.More(); aExpW.Next()) - { - TopoDS_Shape aWireProf = aExpW.Current(); - aSeqBases.Append(aWireProf); - } + for (; aExpW.More(); aExpW.Next()) + { + TopoDS_Shape aWireProf = aExpW.Current(); + aSeqBases.Append(aWireProf); + } } else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) { aSeqBases.Append(aShapeBase); } else if(aTypeBase == TopAbs_EDGE) { TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase); - TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge); - aSeqBases.Append(aWireProf); + TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge); + aSeqBases.Append(aWireProf); } if(nbLocs) { Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i); - if(anItemLoc.IsNull()) - continue; - Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc); + if(anItemLoc.IsNull()) + continue; + Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc); TopoDS_Shape aShapeLoc = aRefLoc->GetValue(); - if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX) - continue; - aSeqLocs.Append(aShapeLoc); + if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX) + continue; + aSeqLocs.Append(aShapeLoc); } } @@ -2084,13 +2071,13 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const // path and update aSeqLocs if it is needed (and possible) TColgp_SequenceOfPnt PLocs; for(i=1; i<=nbLocs; i++) { - TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i)); - PLocs.Append(BRep_Tool::Pnt(V)); + TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i)); + PLocs.Append(BRep_Tool::Pnt(V)); } //TopTools_SequenceOfShape Edges; TopExp_Explorer anExp; for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { - Edges.Append(anExp.Current()); + Edges.Append(anExp.Current()); } int nbEdges = Edges.Length(); ShapeAnalysis_Edge sae; @@ -2100,9 +2087,9 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const gp_Pnt PF = BRep_Tool::Pnt(VF); //cout<<"PF("< tol ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise - ("First location shapes is not coincided with first vertex of aWirePath"); + if(aCI) delete aCI; + Standard_ConstructionError::Raise + ("First location shapes is not coincided with first vertex of aWirePath"); } aSeqLocs.ChangeValue(1) = VF; edge = TopoDS::Edge(Edges.Last()); @@ -2110,78 +2097,78 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const TopoDS_Vertex VL = sae.LastVertex(edge); gp_Pnt PL = BRep_Tool::Pnt(VL); if( PL.Distance(PLocs.Last()) > tol ) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise - ("Last location shapes is not coincided with last vertex of aWirePath"); + if(aCI) delete aCI; + Standard_ConstructionError::Raise + ("Last location shapes is not coincided with last vertex of aWirePath"); } aSeqLocs.ChangeValue(nbLocs) = VL; int jcurr = 2; for(i=1; i<=Edges.Length() && jcurr0 && - PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { - double param = PPC.Parameter(1); - gp_Pnt PC1; - C->D0(param,PC1); - // split current edge - Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); - Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); - TopoDS_Edge E1,E2; - BRep_Builder B; - gp_Pnt Pfp; - C->D0(fp,Pfp); - if(Pfp.Distance(P1)0 && + PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { + double param = PPC.Parameter(1); + gp_Pnt PC1; + C->D0(param,PC1); + // split current edge + Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); + Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); + TopoDS_Edge E1,E2; + BRep_Builder B; + gp_Pnt Pfp; + C->D0(fp,Pfp); + if(Pfp.Distance(P1) we have to update WirePath - BRep_Builder B; - TopoDS_Wire W; - B.MakeWire(W); - for(i=1; i<=Edges.Length(); i++) { - B.Add(W,TopoDS::Edge(Edges.Value(i))); - } - aWirePath = W; + // one of edges was splitted => we have to update WirePath + BRep_Builder B; + TopoDS_Wire W; + B.MakeWire(W); + for(i=1; i<=Edges.Length(); i++) { + B.Add(W,TopoDS::Edge(Edges.Value(i))); + } + aWirePath = W; } } @@ -2210,18 +2197,18 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const double ang = fabs(Vec1.Angle(Vec2)); SumAng += ang; if(SumAng>4*PI) { - SumAng = ang; - SplitEdgeNums.Append(i-1); - int j; - for(j=LastLoc+1; j<=aSeqLocs.Length(); j++) { - TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j)); - gp_Pnt P = BRep_Tool::Pnt(aVert); - if( P1.Distance(P) < tol ) { - SplitLocNums.Append(j); - LastLoc = j; - break; - } - } + SumAng = ang; + SplitEdgeNums.Append(i-1); + int j; + for(j=LastLoc+1; j<=aSeqLocs.Length(); j++) { + TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j)); + gp_Pnt P = BRep_Tool::Pnt(aVert); + if( P1.Distance(P) < tol ) { + SplitLocNums.Append(j); + LastLoc = j; + break; + } + } } Vec1 = Vec2; P1 = P2; @@ -2233,61 +2220,61 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const TopTools_SequenceOfShape aSeqRes; int nn, num1 = 1, num2 = 1; for(nn=1; nn<=SplitEdgeNums.Length(); nn++) { - // create wirepath and sequences of shapes - BRep_Builder B; - TopoDS_Wire tmpW; - B.MakeWire(tmpW); - for(i=num1; i<=SplitEdgeNums.Value(nn); i++) { - B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); - } - num1 = SplitEdgeNums.Value(nn) + 1; - TopTools_SequenceOfShape aTmpSeqBases; - TopTools_SequenceOfShape aTmpSeqLocs; - for(i=num2; i<=SplitLocNums.Value(nn); i++) { - aTmpSeqBases.Append(aSeqBases.Value(i)); - aTmpSeqLocs.Append(aSeqLocs.Value(i)); - } - num2 = SplitLocNums.Value(nn); - // make pipe - BRepOffsetAPI_MakePipeShell aBuilder(tmpW); - Standard_Integer nbShapes = aTmpSeqBases.Length(); - for(i=1; i<=nbShapes; i++) { - TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); - TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); - aBuilder.Add(aTmpSeqBases.Value(i), aVert, aWithContact, aWithCorrect); - } - if(!aBuilder.IsReady()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); - } - aBuilder.Build(); - TopoDS_Shape resShape = aBuilder.Shape(); - aSeqRes.Append(resShape); + // create wirepath and sequences of shapes + BRep_Builder B; + TopoDS_Wire tmpW; + B.MakeWire(tmpW); + for(i=num1; i<=SplitEdgeNums.Value(nn); i++) { + B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); + } + num1 = SplitEdgeNums.Value(nn) + 1; + TopTools_SequenceOfShape aTmpSeqBases; + TopTools_SequenceOfShape aTmpSeqLocs; + for(i=num2; i<=SplitLocNums.Value(nn); i++) { + aTmpSeqBases.Append(aSeqBases.Value(i)); + aTmpSeqLocs.Append(aSeqLocs.Value(i)); + } + num2 = SplitLocNums.Value(nn); + // make pipe + BRepOffsetAPI_MakePipeShell aBuilder(tmpW); + Standard_Integer nbShapes = aTmpSeqBases.Length(); + for(i=1; i<=nbShapes; i++) { + TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); + TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); + aBuilder.Add(aTmpSeqBases.Value(i), aVert, aWithContact, aWithCorrect); + } + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + TopoDS_Shape resShape = aBuilder.Shape(); + aSeqRes.Append(resShape); } // create wirepath and sequences of shapes for last part BRep_Builder B; TopoDS_Wire tmpW; B.MakeWire(tmpW); for(i=num1; i<=Edges.Length(); i++) { - B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); + B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); } TopTools_SequenceOfShape aTmpSeqBases; TopTools_SequenceOfShape aTmpSeqLocs; for(i=num2; i<=aSeqLocs.Length(); i++) { - aTmpSeqBases.Append(aSeqBases.Value(i)); - aTmpSeqLocs.Append(aSeqLocs.Value(i)); + aTmpSeqBases.Append(aSeqBases.Value(i)); + aTmpSeqLocs.Append(aSeqLocs.Value(i)); } // make pipe for last part BRepOffsetAPI_MakePipeShell aBuilder(tmpW); Standard_Integer nbShapes = aTmpSeqBases.Length(); for(i=1; i<=nbShapes; i++) { - TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); - TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); - aBuilder.Add(aTmpSeqBases.Value(i), aVert, aWithContact, aWithCorrect); + TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); + TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); + aBuilder.Add(aTmpSeqBases.Value(i), aVert, aWithContact, aWithCorrect); } if(!aBuilder.IsReady()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } aBuilder.Build(); TopoDS_Shape resShape = aBuilder.Shape(); @@ -2299,7 +2286,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const aSewing->SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for(i=1; i<=aSeqRes.Length(); i++) { - aSewing->Add(aSeqRes.Value(i)); + aSewing->Add(aSeqRes.Value(i)); } aSewing->Perform(); aShape = aSewing->SewedShape(); @@ -2311,45 +2298,45 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const Standard_Integer nbShapes = aSeqBases.Length(); Standard_Integer step = nbShapes/nbBases; - if(nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid sections were specified for building pipe"); + if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid sections were specified for building pipe"); } Standard_Integer ind =0; - for( i=1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes - TopTools_SequenceOfShape usedBases; - Standard_Integer j = 1; - for( ; j <= nbBases ; j++) { - ind = i + (j-1)*step; - TopoDS_Shape aWireProf = aSeqBases.Value(ind); - usedBases.Append(aWireProf); - if(nbLocs) { - TopoDS_Shape aShapeLoc = aSeqLocs.Value(j); - TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); - aBuilder.Add(aWireProf,aVert,aWithContact,aWithCorrect); - } - else - aBuilder.Add(aWireProf,aWithContact,aWithCorrect); - } - if(!aBuilder.IsReady()) { - if(aCI) delete aCI; - Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); - } - aBuilder.Build(); - aShape = aBuilder.Shape(); - aSeqFaces.Append(aShape); - for( j = 1; j <=usedBases.Length(); j++) - aBuilder.Delete(usedBases.Value(j)); + for (i = 1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes + TopTools_SequenceOfShape usedBases; + Standard_Integer j = 1; + for (; j <= nbBases; j++) { + ind = i + (j-1)*step; + TopoDS_Shape aWireProf = aSeqBases.Value(ind); + usedBases.Append(aWireProf); + if(nbLocs) { + TopoDS_Shape aShapeLoc = aSeqLocs.Value(j); + TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); + aBuilder.Add(aWireProf,aVert,aWithContact,aWithCorrect); + } + else + aBuilder.Add(aWireProf,aWithContact,aWithCorrect); + } + if(!aBuilder.IsReady()) { + if(aCI) delete aCI; + Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); + } + aBuilder.Build(); + aShape = aBuilder.Shape(); + aSeqFaces.Append(aShape); + for( j = 1; j <=usedBases.Length(); j++) + aBuilder.Delete(usedBases.Value(j)); } //for case if section is face - if(aSeqFaces.Length() >1) { - BRep_Builder aB; - TopoDS_Compound aComp; - aB.MakeCompound(aComp); - for( i = 1; i <= aSeqFaces.Length(); i++) - aB.Add(aComp,aSeqFaces.Value(i)); - aShape = aComp; + if(aSeqFaces.Length() >1) { + BRep_Builder aB; + TopoDS_Compound aComp; + aB.MakeCompound(aComp); + for( i = 1; i <= aSeqFaces.Length(); i++) + aB.Add(aComp,aSeqFaces.Value(i)); + aShape = aComp; } } } @@ -2402,7 +2389,6 @@ Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const return 1; } - //======================================================================= //function : GEOMImpl_PipeDriver_Type_ //purpose : @@ -2417,13 +2403,12 @@ Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_() static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient); if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient); - static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver", - sizeof(GEOMImpl_PipeDriver), - 1, - (Standard_Address)_Ancestors, - (Standard_Address)NULL); + sizeof(GEOMImpl_PipeDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } @@ -2442,6 +2427,5 @@ const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Ha } } - return _anOtherObject ; + return _anOtherObject; } - diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx index f557dea20..17d810da9 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx @@ -421,15 +421,10 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const if ( ish == 0 ) return 0; BRepClass3d_SolidClassifier SC (Sol); SC.PerformInfinitePoint(Precision::Confusion()); - switch (SC.State()) { - case TopAbs_IN: - aShape = Sol.Reversed(); break; - case TopAbs_OUT: - aShape = Sol; break; - default: // not closed shell? - return 0; - } - + if (SC.State() == TopAbs_IN) + aShape = Sol.Reversed(); + else + aShape = Sol; } else if (aType == COMPOUND_SHAPES) { Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); diff --git a/src/GEOMImpl/GEOMImpl_SketcherDriver.cxx b/src/GEOMImpl/GEOMImpl_SketcherDriver.cxx index 6642592d1..cf2407d3f 100644 --- a/src/GEOMImpl/GEOMImpl_SketcherDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_SketcherDriver.cxx @@ -28,6 +28,8 @@ #include +#include + // OCCT Includes #include #include @@ -78,6 +80,9 @@ Standard_Integer GEOMImpl_SketcherDriver::Execute(TFunction_Logbook& log) const TopoDS_Shape aShape; + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; + // create sketcher Sketcher_Profile aProfile (aCommand.ToCString()); diff --git a/src/GEOMImpl/Makefile.am b/src/GEOMImpl/Makefile.am index 70820da32..948b0c0b1 100644 --- a/src/GEOMImpl/Makefile.am +++ b/src/GEOMImpl/Makefile.am @@ -229,7 +229,7 @@ libGEOMimpl_la_LDFLAGS = \ ../ShHealOper/libShHealOper.la \ ../ARCHIMEDE/libGEOMArchimede.la \ ../SKETCHER/libGEOMSketcher.la \ - $(KERNEL_LDFLAGS) -lSALOMELocalTrace \ + $(KERNEL_LDFLAGS) -lSALOMELocalTrace -lSALOMEBasics \ $(STDLIB) \ $(CAS_LDPATH) -lTKCAF -lTKFillet -lTKOffset diff --git a/src/GEOMToolsGUI/GEOMToolsGUI.cxx b/src/GEOMToolsGUI/GEOMToolsGUI.cxx index fceff718f..521e92e1b 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI.cxx @@ -407,6 +407,11 @@ bool GEOMToolsGUI::OnGUIEvent(int theCommandID, SUIT_Desktop* parent) OnShowHideChildren( theCommandID == 8037 ); break; } + case 8039: // POINT MARKER + { + OnPointMarker(); + break; + } case 9024 : // OPEN - OBJBROSER POPUP { OnOpen(); diff --git a/src/GEOMToolsGUI/GEOMToolsGUI.h b/src/GEOMToolsGUI/GEOMToolsGUI.h index 91d8db559..0f48e9dd1 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI.h +++ b/src/GEOMToolsGUI/GEOMToolsGUI.h @@ -72,6 +72,7 @@ private: void OnOpen(); void OnSelectOnly(int mode); void OnShowHideChildren( bool ); + void OnPointMarker(); // Recursive deletion of object with children void removeObjectWithChildren( _PTR(SObject), diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx index bc7e8fd23..f9b7e9544 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx @@ -28,6 +28,7 @@ #include "GEOMToolsGUI.h" #include "GEOMToolsGUI_TransparencyDlg.h" #include "GEOMToolsGUI_NbIsosDlg.h" +#include "GEOMToolsGUI_MarkerDlg.h" #include #include @@ -70,6 +71,7 @@ #include #include #include +#include // QT Includes #include @@ -257,7 +259,15 @@ void GEOMToolsGUI::OnAutoColor() Standard_Real aCurScale; Aspect_TypeOfMarker aCurTypeOfMarker; aCurPointAspect->Aspect()->Values( aCurColor, aCurTypeOfMarker, aCurScale ); - aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aCurTypeOfMarker, aQuanColor, aCurScale) ); + if ( aCurTypeOfMarker != Aspect_TOM_USERDEFINED ) { + aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aCurTypeOfMarker, aQuanColor, aCurScale) ); + } + else { + Standard_Integer aWidth, aHeight; + aCurPointAspect->GetTextureSize( aWidth, aHeight ); + Handle(Graphic3d_HArray1OfBytes) aTexture = aCurPointAspect->GetTexture(); + aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aQuanColor, 1, aWidth, aHeight, aTexture ) ); + } ic->SetLocalAttributes( io, aCurDrawer ); io->SetColor( aQuanColor ); @@ -348,7 +358,15 @@ void GEOMToolsGUI::OnColor() Standard_Real aCurScale; Aspect_TypeOfMarker aCurTypeOfMarker; aCurPointAspect->Aspect()->Values( aCurColor, aCurTypeOfMarker, aCurScale ); - aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aCurTypeOfMarker, aColor, aCurScale) ); + if ( aCurTypeOfMarker != Aspect_TOM_USERDEFINED ) { + aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aCurTypeOfMarker, aColor, aCurScale) ); + } + else { + Standard_Integer aWidth, aHeight; + aCurPointAspect->GetTextureSize( aWidth, aHeight ); + Handle(Graphic3d_HArray1OfBytes) aTexture = aCurPointAspect->GetTexture(); + aCurDrawer->SetPointAspect( new Prs3d_PointAspect( aColor, 1, aWidth, aHeight, aTexture ) ); + } ic->SetLocalAttributes(io, aCurDrawer); io->SetColor( aColor ); @@ -645,3 +663,9 @@ void GEOMToolsGUI::OnShowHideChildren( bool show ) app->updateActions(); } } + +void GEOMToolsGUI::OnPointMarker() +{ + GEOMToolsGUI_MarkerDlg dlg( SUIT_Session::session()->activeApplication()->desktop() ); + dlg.exec(); +} diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx new file mode 100644 index 000000000..cb5b81754 --- /dev/null +++ b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx @@ -0,0 +1,370 @@ +// Copyright (C) 2007-2009 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 +// +// File : GEOMToolsGUI_MarkerDlg.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#include "GEOMToolsGUI_MarkerDlg.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MARGIN 9 +#define SPACING 6 + +GEOMToolsGUI_MarkerDlg::GEOMToolsGUI_MarkerDlg( QWidget* parent ) + : QDialog ( parent ) +{ + setWindowTitle( tr( "SET_MARKER_TLT" ) ); + setSizeGripEnabled( true ); + setModal( true ); + + // --- + + QRadioButton* aStandardTypeRB = new QRadioButton( tr( "STANDARD_MARKER" ), this ); + QRadioButton* aCustomTypeRB = new QRadioButton( tr( "CUSTOM_MARKER" ), this ); + myTypeGroup = new QButtonGroup( this ); + myTypeGroup->addButton( aStandardTypeRB, 0 ); + myTypeGroup->addButton( aCustomTypeRB, 1 ); + + QHBoxLayout* aRadioLayout = new QHBoxLayout; + aRadioLayout->setMargin( 0 ); + aRadioLayout->setSpacing( SPACING ); + aRadioLayout->addWidget( aStandardTypeRB ); + aRadioLayout->addWidget( aCustomTypeRB ); + + // --- + + myWGStack = new QStackedWidget( this ); + myWGStack->setFrameStyle( QFrame::Box | QFrame::Sunken ); + + // --- + + QWidget* aStdWidget = new QWidget( myWGStack ); + + QLabel* aTypeLab = new QLabel( tr( "TYPE" ), aStdWidget ); + QLabel* aScaleLab = new QLabel( tr( "SCALE" ), aStdWidget ); + + myStdTypeCombo = new QtxComboBox( aStdWidget ); + myStdScaleCombo = new QtxComboBox( aStdWidget ); + + QGridLayout* aStdLayout = new QGridLayout; + aStdLayout->setMargin( MARGIN ); + aStdLayout->setSpacing( SPACING ); + aStdLayout->addWidget( aTypeLab, 0, 0 ); + aStdLayout->addWidget( myStdTypeCombo, 0, 1 ); + aStdLayout->addWidget( aScaleLab, 1, 0 ); + aStdLayout->addWidget( myStdScaleCombo, 1, 1 ); + aStdWidget->setLayout( aStdLayout ); + + // --- + + QWidget* aCustomWidget = new QWidget( myWGStack ); + + QLabel* aCustomLab = new QLabel( tr( "CUSTOM" ), aCustomWidget ); + myCustomTypeCombo = new QtxComboBox( aCustomWidget ); + QPushButton* aBrowseBtn = new QPushButton( tr( "BROWSE" ), aCustomWidget ); + + QGridLayout* aCustomLayout = new QGridLayout; + aCustomLayout->setMargin( MARGIN ); + aCustomLayout->setSpacing( SPACING ); + aCustomLayout->addWidget( aCustomLab, 0, 0 ); + aCustomLayout->addWidget( myCustomTypeCombo, 0, 1 ); + aCustomLayout->addWidget( aBrowseBtn, 0, 2 ); + aCustomLayout->setRowStretch( 1, 5 ); + aCustomWidget->setLayout( aCustomLayout ); + + // --- + + myWGStack->insertWidget( 0, aStdWidget ); + myWGStack->insertWidget( 1, aCustomWidget ); + + // --- + + QPushButton* aOkBtn = new QPushButton( tr( "OK_BTN" ), this ); + aOkBtn->setAutoDefault( true ); aOkBtn->setDefault( true ); + QPushButton* aCancelBtn = new QPushButton( tr( "CANCEL_BTN" ), this ); + aCancelBtn->setAutoDefault( true ); + QPushButton* aHelpBtn = new QPushButton( tr( "HELP_BTN" ), this ); + aHelpBtn->setAutoDefault( true ); + + QHBoxLayout* aBtnLayout = new QHBoxLayout; + aBtnLayout->setMargin( 0 ); + aBtnLayout->setSpacing( SPACING ); + aBtnLayout->addWidget( aOkBtn ); + aBtnLayout->addSpacing( 10 ); + aBtnLayout->addStretch(); + aBtnLayout->addWidget( aCancelBtn ); + aBtnLayout->addWidget( aHelpBtn ); + + // --- + + QVBoxLayout* aTopLayout = new QVBoxLayout; + aTopLayout->setMargin( MARGIN ); + aTopLayout->setSpacing( SPACING ); + aTopLayout->addLayout( aRadioLayout ); + aTopLayout->addWidget( myWGStack ); + aTopLayout->addLayout( aBtnLayout ); + setLayout( aTopLayout ); + + // --- + + connect( myTypeGroup, SIGNAL( buttonClicked( int ) ), myWGStack, SLOT( setCurrentIndex( int ) ) ); + connect( aBrowseBtn, SIGNAL( clicked() ), this, SLOT( browse() ) ); + connect( aOkBtn, SIGNAL( clicked() ), this, SLOT( accept() ) ); + connect( aCancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) ); + connect( aHelpBtn, SIGNAL( clicked() ), this, SLOT( help() ) ); + + // --- + + aStandardTypeRB->setChecked( true ); + init(); +} + +GEOMToolsGUI_MarkerDlg::~GEOMToolsGUI_MarkerDlg() +{ + myOperation->Destroy(); +} + +void GEOMToolsGUI_MarkerDlg::setStandardMarker( GEOM::marker_type type, GEOM::marker_size size ) +{ + if ( type > GEOM::MT_NONE && type < GEOM::MT_USER ) { + myTypeGroup->button( 0 )->setChecked( true ); + myWGStack->setCurrentIndex( 0 ); + myStdTypeCombo->setCurrentIndex( (int)type - 1 ); +#ifdef WNT + int asize = max( (int)GEOM::MS_10, min( (int)GEOM::MS_70, (int)size ) ); +#else + int asize = std::max( (int)GEOM::MS_10, std::min( (int)GEOM::MS_70, (int)size ) ); +#endif + myStdScaleCombo->setCurrentIndex( asize-1 ); + } +} + +void GEOMToolsGUI_MarkerDlg::setCustomMarker( int id ) +{ + if ( id > 0 ) { + myTypeGroup->button( 1 )->setChecked( true ); + myWGStack->setCurrentIndex( 1 ); + addTexture( id ); + myCustomTypeCombo->setCurrentId( id ); + } +} + +GEOM::marker_type GEOMToolsGUI_MarkerDlg::getMarkerType() const +{ + return myWGStack->currentIndex() == 0 ? (GEOM::marker_type)myStdTypeCombo->currentId() : GEOM::MT_USER; +} + +GEOM::marker_size GEOMToolsGUI_MarkerDlg::getStandardMarkerScale() const +{ + return myWGStack->currentIndex() == 0 ? (GEOM::marker_size)myStdScaleCombo->currentId() : GEOM::MS_NONE; +} + +int GEOMToolsGUI_MarkerDlg::getCustomMarkerID() const +{ + return myWGStack->currentIndex() == 1 ? myCustomTypeCombo->currentId() : 0; +} + +void GEOMToolsGUI_MarkerDlg::accept() +{ + if ( getStudy() ) { + LightApp_SelectionMgr* selMgr = qobject_cast( getStudy()->application() )->selectionMgr(); + if ( selMgr ) { + SALOME_ListIO selected; + selMgr->selectedObjects( selected ); + if ( !selected.IsEmpty() ) { + _PTR(Study) study = getStudy()->studyDS(); + for ( SALOME_ListIteratorOfListIO it( selected ); it.More(); it.Next() ) { + _PTR(SObject) aSObject( study->FindObjectID( it.Value()->getEntry() ) ); + GEOM::GEOM_Object_var anObject = + GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject( aSObject ) ); + if ( !anObject->_is_nil() ) { + if ( myWGStack->currentIndex() == 0 ) + anObject->SetMarkerStd( getMarkerType(), getStandardMarkerScale() ); + else if ( getCustomMarkerID() > 0 ) + anObject->SetMarkerTexture( getCustomMarkerID() ); + } + } + GEOM_Displayer displayer( getStudy() ); + displayer.Redisplay( selected, true ); + } + } + } + QDialog::accept(); +} + +void GEOMToolsGUI_MarkerDlg::keyPressEvent( QKeyEvent* e ) +{ + if ( e->key() == Qt::Key_F1 ) + help(); + QDialog::keyPressEvent( e ); +} + +void GEOMToolsGUI_MarkerDlg::init() +{ + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + + // --- + + for ( int i = GEOM::MT_POINT; i < GEOM::MT_USER; i++ ) { + QString icoFile = QString( "ICON_VERTEX_MARKER_%1" ).arg( i ); + QPixmap pixmap = resMgr->loadPixmap( "GEOM", tr( qPrintable( icoFile ) ) ); + myStdTypeCombo->addItem( pixmap, QString() ); + myStdTypeCombo->setId( myStdTypeCombo->count()-1, i ); + } + + // --- + + for ( int i = GEOM::MS_10; i <= GEOM::MS_70; i++ ) { + myStdScaleCombo->addItem( QString::number( (i-1)*0.5 + 1.0 ) ); + myStdScaleCombo->setId( myStdScaleCombo->count()-1, i ); + } + + // --- + + GEOM::GEOM_Gen_var engine = GeometryGUI::GetGeomGen(); + myOperation = engine->GetIInsertOperations( getStudy()->id() ); + GEOM::ListOfLong_var ids = myOperation->GetAllTextures(); + for ( int i = 0; i < ids->length(); i++ ) + addTexture( ids[i] ); + + // --- + + GEOM::marker_type aType = (GEOM::marker_type)-1; + GEOM::marker_size aSize = (GEOM::marker_size)-1; + int aTexture = 0; + if ( getStudy() ) { + LightApp_SelectionMgr* selMgr = qobject_cast( getStudy()->application() )->selectionMgr(); + if ( selMgr ) { + SALOME_ListIO selected; + selMgr->selectedObjects( selected ); + if ( !selected.IsEmpty() ) { + _PTR(Study) study = getStudy()->studyDS(); + for ( SALOME_ListIteratorOfListIO it( selected ); it.More(); it.Next() ) { + _PTR(SObject) aSObject( study->FindObjectID( it.Value()->getEntry() ) ); + GEOM::GEOM_Object_var anObject = + GEOM::GEOM_Object::_narrow( GeometryGUI::ClientSObjectToObject( aSObject ) ); + if ( !anObject->_is_nil() ) { + GEOM::marker_type mtype = anObject->GetMarkerType(); + if ( aType == -1 ) + aType = mtype; + else if ( aType != mtype ) { + aType = (GEOM::marker_type)-1; + break; + } + if ( mtype > GEOM::MT_NONE && mtype < GEOM::MT_USER ) { + GEOM::marker_size msize = anObject->GetMarkerSize(); + if ( aSize == -1 ) + aSize = msize; + else if ( aSize != msize ) + break; + } + else if ( mtype == GEOM::MT_USER ) { + int mtexture = anObject->GetMarkerTexture(); + if ( aTexture == 0 ) + aTexture = mtexture; + else if ( aTexture != mtexture ) + break; + } + } + } + } + } + } + if ( aType > GEOM::MT_NONE && aType < GEOM::MT_USER ) + setStandardMarker( aType, aSize ); + else if ( aType == GEOM::MT_USER ) + setCustomMarker( aTexture ); + else + setStandardMarker((GEOM::marker_type)(resMgr->integerValue("Geometry", "type_of_marker", (int)Aspect_TOM_PLUS) + 1), + (GEOM::marker_size)(resMgr->integerValue("Geometry", "marker_scale", 1))); +} + +void GEOMToolsGUI_MarkerDlg::addTexture( int id, bool select ) const +{ + if ( id > 0 && myCustomTypeCombo->index( id ) == -1 ) { + int tWidth, tHeight; + Handle(Graphic3d_HArray1OfBytes) texture = GeometryGUI::getTexture( getStudy(), id, tWidth, tHeight ); + if ( !texture.IsNull() && texture->Length() == tWidth*tHeight/8 ) { + QImage image( tWidth, tHeight, QImage::Format_Mono ); + image.setColor( 0, qRgba( 0, 0, 0, 0 ) ); + image.setColor( 1, qRgba( 0, 0, 0, 255 ) ); + int bytesperline = tWidth/8; + for ( int j = texture->Lower(); j <= texture->Upper(); j++ ) { + uchar val = (uchar)texture->Value( j ); + for ( int k = 0; k < 8; k++ ) { + int row = ( j - texture->Lower() ) / bytesperline; + int col = ( ( j - texture->Lower() ) % bytesperline ) * 8 + k; + image.setPixel( row, col, ( val & (1<<(8-k-1)) ) ? 1 : 0 ); + } + } + QPixmap pixmap = QPixmap::fromImage( image ); + if ( !pixmap.isNull() ) { + myCustomTypeCombo->addItem( pixmap, QString::number( id ) ); + myCustomTypeCombo->setId( myCustomTypeCombo->count()-1, id ); + if ( select ) myCustomTypeCombo->setCurrentId( id ); + } + } + } +} + +SalomeApp_Study* GEOMToolsGUI_MarkerDlg::getStudy() const +{ + return qobject_cast( SUIT_Session::session()->activeApplication()->activeStudy() ); +} + +void GEOMToolsGUI_MarkerDlg::browse() +{ + QStringList filters; + filters << tr( "Texture files (*.dat)" ) << tr( "All files (*)" ); + QString aFileName = SUIT_Session::session()->activeApplication()->getFileName( true, QString(), filters.join( ";;" ), tr( "LOAD_TEXTURE_TLT" ), this ); + if ( !aFileName.isEmpty() ) { + addTexture( myOperation->LoadTexture( aFileName.toLatin1().constData() ), true ); + } +} + +void GEOMToolsGUI_MarkerDlg::help() +{ + if ( getStudy() ) { + SalomeApp_Application* app = qobject_cast( getStudy()->application() ); + app->onHelpContextModule( "GEOM", "point_marker_page.html" ); + } +} diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.h b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.h new file mode 100644 index 000000000..e063c1424 --- /dev/null +++ b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.h @@ -0,0 +1,78 @@ +// Copyright (C) 2007-2009 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 +// +// File : GEOMToolsGUI_MarkerDlg.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +#ifndef GEOMTOOLSGUI_MARKERDLG_H +#define GEOMTOOLSGUI_MARKERDLG_H + +#include "GEOM_ToolsGUI.hxx" + +#include + +#include +#include CORBA_CLIENT_HEADER(GEOM_Gen) + +class QButtonGroup; +class QStackedWidget; +class QtxComboBox; +class SalomeApp_Study; + +class GEOMTOOLSGUI_EXPORT GEOMToolsGUI_MarkerDlg : public QDialog +{ + Q_OBJECT + +public: + GEOMToolsGUI_MarkerDlg( QWidget* = 0 ); + ~GEOMToolsGUI_MarkerDlg(); + + void setStandardMarker( GEOM::marker_type, GEOM::marker_size ); + void setCustomMarker( int ); + GEOM::marker_type getMarkerType() const; + GEOM::marker_size getStandardMarkerScale() const; + int getCustomMarkerID() const; + + void accept(); + +protected: + void keyPressEvent( QKeyEvent* ); + +private: + void init(); + void addTexture( int, bool = false ) const; + SalomeApp_Study* getStudy() const; + +private slots: + void browse(); + void help(); + +private: + GEOM::GEOM_IInsertOperations_var myOperation; + QButtonGroup* myTypeGroup; + QStackedWidget* myWGStack; + QtxComboBox* myStdTypeCombo; + QtxComboBox* myStdScaleCombo; + QtxComboBox* myCustomTypeCombo; +}; + +#endif // GEOMTOOLSGUI_MARKERDLG_H diff --git a/src/GEOMToolsGUI/Makefile.am b/src/GEOMToolsGUI/Makefile.am index 06fda8bf0..1a0a919b5 100644 --- a/src/GEOMToolsGUI/Makefile.am +++ b/src/GEOMToolsGUI/Makefile.am @@ -34,19 +34,22 @@ salomeinclude_HEADERS = \ GEOM_ToolsGUI.hxx \ GEOMToolsGUI_NbIsosDlg.h \ GEOMToolsGUI_TransparencyDlg.h \ - GEOMToolsGUI_DeleteDlg.h + GEOMToolsGUI_DeleteDlg.h \ + GEOMToolsGUI_MarkerDlg.h dist_libGEOMToolsGUI_la_SOURCES = \ GEOMToolsGUI.cxx \ GEOMToolsGUI_1.cxx \ GEOMToolsGUI_TransparencyDlg.cxx \ GEOMToolsGUI_NbIsosDlg.cxx \ - GEOMToolsGUI_DeleteDlg.cxx + GEOMToolsGUI_DeleteDlg.cxx \ + GEOMToolsGUI_MarkerDlg.cxx MOC_FILES = \ GEOMToolsGUI_TransparencyDlg_moc.cxx \ GEOMToolsGUI_NbIsosDlg_moc.cxx \ - GEOMToolsGUI_DeleteDlg_moc.cxx + GEOMToolsGUI_DeleteDlg_moc.cxx \ + GEOMToolsGUI_MarkerDlg_moc.cxx nodist_libGEOMToolsGUI_la_SOURCES = \ $(MOC_FILES) diff --git a/src/GEOM_I/GEOM_Gen_i.cc b/src/GEOM_I/GEOM_Gen_i.cc index 35d6d742d..58471eebb 100644 --- a/src/GEOM_I/GEOM_Gen_i.cc +++ b/src/GEOM_I/GEOM_Gen_i.cc @@ -66,11 +66,11 @@ // function : GEOM_Gen_i() // purpose : constructor to be called for servant creation. //============================================================================ -GEOM_Gen_i::GEOM_Gen_i(CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa, - PortableServer::ObjectId * contId, - const char *instanceName, - const char *interfaceName) : +GEOM_Gen_i::GEOM_Gen_i(CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, + const char* interfaceName) : Engines_Component_i(orb, poa, contId, instanceName, interfaceName) { _thisObj = this; @@ -1587,7 +1587,7 @@ GEOM::GEOM_Object_ptr GEOM_Gen_i::AddSubShape (GEOM::GEOM_Object_ptr theMainShap void GEOM_Gen_i::RemoveObject(GEOM::GEOM_Object_ptr theObject) { CORBA::String_var anEntry = theObject->GetEntry(); - Handle(GEOM_Object) anObject = _impl->GetObject(theObject->GetStudyID(), anEntry); + Handle(GEOM_Object) anObject = _impl->GetObject(theObject->GetStudyID(), anEntry, false); if (anObject.IsNull()) return; _impl->RemoveObject(anObject); return; @@ -1808,19 +1808,19 @@ char* GEOM_Gen_i::getObjectInfo(CORBA::Long studyId, const char* entry) //===================================================================================== extern "C" { -GEOM_I_EXPORT -PortableServer::ObjectId* GEOMEngine_factory(CORBA::ORB*, PortableServer::POA*, PortableServer::ObjectId*, const char*, const char*); - -GEOM_I_EXPORT - PortableServer::ObjectId * GEOMEngine_factory(CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa, - PortableServer::ObjectId * contId, - const char *instanceName, - const char * interfaceName) + /* + GEOM_I_EXPORT + PortableServer::ObjectId* GEOMEngine_factory(CORBA::ORB*, PortableServer::POA*, PortableServer::ObjectId*, const char*, const char*); + */ + + GEOM_I_EXPORT + PortableServer::ObjectId* GEOMEngine_factory(CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, + const char* interfaceName) { - GEOM_Gen_i * myGEOM_Gen_i = new GEOM_Gen_i(orb, poa, contId, instanceName, interfaceName); - // Don't understand the reason of this register ???? -// myGEOM_Gen_i->register_name("/myGEOM_Gen"); // NRI : 11/07/2002 : Add for Supervision example - return myGEOM_Gen_i->getId(); + GEOM_Gen_i* myGEOM_Gen_i = new GEOM_Gen_i(orb, poa, contId, instanceName, interfaceName); + return myGEOM_Gen_i->getId(); } } diff --git a/src/GEOM_I/GEOM_IInsertOperations_i.cc b/src/GEOM_I/GEOM_IInsertOperations_i.cc index b32b3eb71..c5570650e 100644 --- a/src/GEOM_I/GEOM_IInsertOperations_i.cc +++ b/src/GEOM_I/GEOM_IInsertOperations_i.cc @@ -35,6 +35,7 @@ #include "GEOM_Object.hxx" #include +#include //============================================================================= /*! @@ -215,3 +216,52 @@ void GEOM_IInsertOperations_i::ExportTranslators theFormats = aFormatsArray._retn(); thePatterns = aPatternsArray._retn(); } + +CORBA::Long GEOM_IInsertOperations_i::LoadTexture(const char* theTextureFile) +{ + GetOperations()->SetNotDone(); + return GetOperations()->LoadTexture( theTextureFile ); +} + +CORBA::Long GEOM_IInsertOperations_i::AddTexture(CORBA::Long theWidth, CORBA::Long theHeight, + const SALOMEDS::TMPFile& theTexture) +{ + GetOperations()->SetNotDone(); + Handle(TDataStd_HArray1OfByte) aTexture; + if ( theTexture.length() > 0 ) { + aTexture = new TDataStd_HArray1OfByte( 1, theTexture.length() ); + for ( int i = 0; i < theTexture.length(); i++ ) + aTexture->SetValue( i+1, (Standard_Byte)theTexture[i] ); + } + return GetOperations()->AddTexture( theWidth, theHeight, aTexture ); +} + +SALOMEDS::TMPFile* GEOM_IInsertOperations_i::GetTexture(CORBA::Long theID, + CORBA::Long& theWidth, + CORBA::Long& theHeight) +{ + int aWidth, aHeight; + Handle(TDataStd_HArray1OfByte) aTextureImpl = GetOperations()->GetTexture( theID, aWidth, aHeight ); + theWidth = aWidth; + theHeight = aHeight; + SALOMEDS::TMPFile_var aTexture; + if ( !aTextureImpl.IsNull() ) { + aTexture = new SALOMEDS::TMPFile; + aTexture->length( aTextureImpl->Length() ); + for ( int i = aTextureImpl->Lower(); i <= aTextureImpl->Upper(); i++ ) + aTexture[i-aTextureImpl->Lower()] = aTextureImpl->Value( i ); + } + return aTexture._retn(); +} + +GEOM::ListOfLong* GEOM_IInsertOperations_i::GetAllTextures() +{ + std::list localIDs = GetOperations()->GetAllTextures(); + GEOM::ListOfLong_var anIDs = new GEOM::ListOfLong(localIDs.size()); + anIDs->length(localIDs.size()); + std::list::const_iterator anIt; + int i = 0; + for( anIt = localIDs.begin(); anIt != localIDs.end(); ++anIt, i++) + anIDs[i] = *anIt; + return anIDs._retn(); +} diff --git a/src/GEOM_I/GEOM_IInsertOperations_i.hh b/src/GEOM_I/GEOM_IInsertOperations_i.hh index da29eabf0..49a426981 100644 --- a/src/GEOM_I/GEOM_IInsertOperations_i.hh +++ b/src/GEOM_I/GEOM_IInsertOperations_i.hh @@ -27,6 +27,7 @@ #include #include CORBA_SERVER_HEADER(GEOM_Gen) +#include CORBA_CLIENT_HEADER(SALOMEDS) #include "GEOM_IOperations_i.hh" #include "GEOM_Object_i.hh" @@ -56,6 +57,15 @@ class GEOM_I_EXPORT GEOM_IInsertOperations_i : void ExportTranslators (GEOM::string_array_out theFormats, GEOM::string_array_out thePatterns); + CORBA::Long LoadTexture(const char* theTextureFile); + CORBA::Long AddTexture(CORBA::Long theWidth, CORBA::Long theHeight, + const SALOMEDS::TMPFile& theTexture); + SALOMEDS::TMPFile* GetTexture(CORBA::Long theID, + CORBA::Long& theWidth, + CORBA::Long& theHeight); + + GEOM::ListOfLong* GetAllTextures(); + ::GEOMImpl_IInsertOperations* GetOperations() { return (::GEOMImpl_IInsertOperations*)GetImpl(); } }; diff --git a/src/GEOM_I/GEOM_Object_i.cc b/src/GEOM_I/GEOM_Object_i.cc index b99e24c22..f164b4ef4 100644 --- a/src/GEOM_I/GEOM_Object_i.cc +++ b/src/GEOM_I/GEOM_Object_i.cc @@ -184,6 +184,69 @@ CORBA::Boolean GEOM_Object_i::GetAutoColor() } +//============================================================================= +/*! + * SetMarkerStd + */ +//============================================================================= +void GEOM_Object_i::SetMarkerStd(GEOM::marker_type theType, GEOM::marker_size theSize) +{ + if ( theType == GEOM::MT_NONE || theSize == GEOM::MS_NONE ) { + _impl->UnsetMarker(); + } + else { + Aspect_TypeOfMarker aType = (Aspect_TypeOfMarker)( (int)theType-1 ); + double aSize = ((int)theSize+1)*0.5; + _impl->SetMarkerStd( aType, aSize ); + } +} + + +//============================================================================= +/*! + * SetMarkerTexture + */ +//============================================================================= +void GEOM_Object_i::SetMarkerTexture(CORBA::Long theTextureId) +{ + _impl->SetMarkerTexture( theTextureId ); +} + + +//============================================================================= +/*! + * GetMarkerType + */ +//============================================================================= +GEOM::marker_type GEOM_Object_i::GetMarkerType() +{ + return (GEOM::marker_type)( (int)_impl->GetMarkerType()+1 ); +} + + +//============================================================================= +/*! + * GetMarkerSize + */ +//============================================================================= +GEOM::marker_size GEOM_Object_i::GetMarkerSize() +{ + int aSize = (int)( _impl->GetMarkerSize()/0.5 ) - 1; + return aSize < GEOM::MS_10 || aSize > GEOM::MS_70 ? GEOM::MS_NONE : (GEOM::marker_size)aSize; +} + + +//============================================================================= +/*! + * GetMarkerTexture + */ +//============================================================================= +CORBA::Long GEOM_Object_i::GetMarkerTexture() +{ + return _impl->GetMarkerTexture(); +} + + //============================================================================= /*! * SetStudyEntry diff --git a/src/GEOM_I/GEOM_Object_i.hh b/src/GEOM_I/GEOM_Object_i.hh index 13bb0290f..b6f16c354 100644 --- a/src/GEOM_I/GEOM_Object_i.hh +++ b/src/GEOM_I/GEOM_Object_i.hh @@ -62,6 +62,16 @@ class GEOM_I_EXPORT GEOM_Object_i : public virtual POA_GEOM::GEOM_Object, public virtual CORBA::Boolean GetAutoColor(); + void SetMarkerStd(GEOM::marker_type theType, GEOM::marker_size theSize); + + void SetMarkerTexture(CORBA::Long theTextureId); + + GEOM::marker_type GetMarkerType(); + + GEOM::marker_size GetMarkerSize(); + + CORBA::Long GetMarkerTexture(); + virtual void SetStudyEntry(const char* theEntry); virtual char* GetStudyEntry(); diff --git a/src/GEOM_SWIG/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index e78b2aec4..fb8c18bf8 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -456,13 +456,13 @@ def TestOtherOperations (geompy, math): Shell_1 = geompy.MakeShell([Face_1, Rotation_1, Rotation_2, Rotation_3, Rotation_4, Rotation_5]) Solid_1 = geompy.MakeSolid([Shell_1]) - NoExtraEdges_1 = geompy.RemoveExtraEdges(Solid_1, 0) + NoExtraEdges_1 = geompy.RemoveExtraEdges(Solid_1, True) # doUnionFaces = True geompy.addToStudy(Shell_1, "Shell_1") geompy.addToStudy(Solid_1, "Solid_1") geompy.addToStudy(NoExtraEdges_1, "NoExtraEdges_1") - # RemoveExtraEdges + # RemoveExtraEdges (by default, doUnionFaces = False) freeFacesWithoutExtra = geompy.RemoveExtraEdges(freeFaces) geompy.addToStudy(freeFacesWithoutExtra, "freeFacesWithoutExtra") @@ -529,7 +529,7 @@ def TestOtherOperations (geompy, math): v_y, Loc, geompy.GEOM.ST_ON) for edge_i in edges_on_pln: geompy.addToStudy(edge_i, "Edge on Plane (N = (0, -1, 0) & Location = (0, -50, 0)") - + # GetShapesOnPlaneWithLocationIDs edges_on_pln_ids = geompy.GetShapesOnPlaneWithLocationIDs( blocksComp, geompy.ShapeType["EDGE"], v_y, Loc, geompy.GEOM.ST_ON) diff --git a/src/GEOM_SWIG/GEOM_example7.py b/src/GEOM_SWIG/GEOM_example7.py new file mode 100644 index 000000000..6cce391ef --- /dev/null +++ b/src/GEOM_SWIG/GEOM_example7.py @@ -0,0 +1,53 @@ +# 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 +# +# --- +# +# File : GEOM_example7.py +# Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +# +# --- + +import salome +import geompy +import os +import GEOM + +data_dir = os.getenv('DATA_DIR') +if data_dir: + texture_1 = geompy.LoadTexture(os.path.join(data_dir, "Textures", "texture1.dat")) + texture_2 = geompy.LoadTexture(os.path.join(data_dir, "Textures", "texture2.dat")) + texture_3 = geompy.LoadTexture(os.path.join(data_dir, "Textures", "texture3.dat")) + + Vertex_1 = geompy.MakeVertex(0, 0, 0) + Vertex_2 = geompy.MakeVertex(100, 0, 0) + Vertex_3 = geompy.MakeVertex(0, 100, 0) + Vertex_4 = geompy.MakeVertex(0, 0, 100) + Vertex_5 = geompy.MakeVertex(100, 0, 100) + Vertex_1.SetMarkerTexture(texture_1); + Vertex_2.SetMarkerTexture(texture_2); + Vertex_3.SetMarkerTexture(texture_3); + Vertex_4.SetMarkerStd(GEOM.MT_O_PLUS, GEOM.MS_25); + Vertex_5.SetMarkerStd(GEOM.MT_BALL, GEOM.MS_40); + geompy.addToStudy( Vertex_1, "Vertex_1" ) + geompy.addToStudy( Vertex_2, "Vertex_2" ) + geompy.addToStudy( Vertex_3, "Vertex_3" ) + geompy.addToStudy( Vertex_4, "Vertex_4" ) + geompy.addToStudy( Vertex_5, "Vertex_5" ) + pass diff --git a/src/GEOM_SWIG/Makefile.am b/src/GEOM_SWIG/Makefile.am index 3b7c921fb..11862eb9a 100644 --- a/src/GEOM_SWIG/Makefile.am +++ b/src/GEOM_SWIG/Makefile.am @@ -48,6 +48,7 @@ dist_salomescript_DATA = \ GEOM_example4.py \ GEOM_example5.py \ GEOM_example6.py \ + GEOM_example7.py \ GEOM_moteur.py \ GEOM_TestAll.py \ GEOM_TestOthers.py \ diff --git a/src/GEOM_SWIG/geompy.py b/src/GEOM_SWIG/geompy.py index 081435b2a..ebcb211ed 100644 --- a/src/GEOM_SWIG/geompy.py +++ b/src/GEOM_SWIG/geompy.py @@ -38,5 +38,5 @@ for k in dir(geom): if k[0] == '_':continue globals()[k]=getattr(geom,k) del k -from geompyDC import ShapeType,GEOM,kind, info +from geompyDC import ShapeType,GEOM,kind, info, PackData, ReadTexture diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index 309c667e8..c8ef92793 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -93,9 +93,9 @@ ShapeType = {"COMPOUND":0, "COMPSOLID":1, "SOLID":2, "SHELL":3, "FACE":4, "WIRE" def RaiseIfFailed (Method_name, Operation): if Operation.IsDone() == 0 and Operation.GetErrorCode() != "NOT_FOUND_ANY": raise RuntimeError, Method_name + " : " + Operation.GetErrorCode() - + ## Return list of variables value from salome notebook -## @ingroup l1_geompy_auxiliary +## @ingroup l1_geompy_auxiliary def ParseParameters(*parameters): Result = [] StringResult = "" @@ -108,16 +108,16 @@ def ParseParameters(*parameters): else: Result.append(parameter) pass - + StringResult = StringResult + str(parameter) StringResult = StringResult + ":" pass StringResult = StringResult[:len(StringResult)-1] Result.append(StringResult) return Result - + ## Return list of variables value from salome notebook -## @ingroup l1_geompy_auxiliary +## @ingroup l1_geompy_auxiliary def ParseList(list): Result = [] StringResult = "" @@ -128,15 +128,15 @@ def ParseList(list): else: Result.append(str(parameter)) pass - + StringResult = StringResult + str(parameter) StringResult = StringResult + ":" pass StringResult = StringResult[:len(StringResult)-1] return Result, StringResult - + ## Return list of variables value from salome notebook -## @ingroup l1_geompy_auxiliary +## @ingroup l1_geompy_auxiliary def ParseSketcherCommand(command): Result = "" StringResult = "" @@ -168,6 +168,88 @@ def ParseSketcherCommand(command): Result = Result[:len(Result)-1] return Result, StringResult +## Helper function which can be used to pack the passed string to the byte data. +## Only '1' an '0' symbols are valid for the string. The missing bits are replaced by zeroes. +## If the string contains invalid symbol (neither '1' nor '0'), the function raises an exception. +## For example, +## \code +## val = PackData("10001110") # val = 0xAE +## val = PackData("1") # val = 0x80 +## \endcode +## @param data unpacked data - a string containing '1' and '0' symbols +## @return data packed to the byte stream +## @ingroup l1_geompy_auxiliary +def PackData(data): + bytes = len(data)/8 + if len(data)%8: bytes += 1 + res = "" + for b in range(bytes): + d = data[b*8:(b+1)*8] + val = 0 + for i in range(8): + val *= 2 + if i < len(d): + if d[i] == "1": val += 1 + elif d[i] != "0": + raise "Invalid symbol %s" % d[i] + pass + pass + res += chr(val) + pass + return res + +## Read bitmap texture from the text file. +## In that file, any non-zero symbol represents '1' opaque pixel of the bitmap. +## A zero symbol ('0') represents transparent pixel of the texture bitmap. +## The function returns width and height of the pixmap in pixels and byte stream representing +## texture bitmap itself. +## +## This function can be used to read the texture to the byte stream in order to pass it to +## the AddTexture() function of geompy class. +## For example, +## \code +## import geompy +## geompy.init_geom(salome.myStudy) +## texture = geompy.readtexture('mytexture.dat') +## texture = geompy.AddTexture(*texture) +## obj.SetMarkerTexture(texture) +## \endcode +## @param fname texture file name +## @return sequence of tree values: texture's width, height in pixels and its byte stream +## @ingroup l1_geompy_auxiliary +def ReadTexture(fname): + try: + f = open(fname) + lines = [ l.strip() for l in f.readlines()] + f.close() + maxlen = 0 + if lines: maxlen = max([len(x) for x in lines]) + lenbytes = maxlen/8 + if maxlen%8: lenbytes += 1 + bytedata="" + for line in lines: + if len(line)%8: + lenline = (len(line)/8+1)*8 + pass + else: + lenline = (len(line)/8)*8 + pass + for i in range(lenline/8): + byte="" + for j in range(8): + if i*8+j < len(line) and line[i*8+j] != "0": byte += "1" + else: byte += "0" + pass + bytedata += PackData(byte) + pass + for i in range(lenline/8, lenbytes): + bytedata += PackData("0") + pass + return lenbytes*8, len(lines), bytedata + except: + pass + return 0, 0, "" + ## Kinds of shape enumeration # @ingroup l1_geompy_auxiliary kind = GEOM.GEOM_IKindOfShape @@ -179,7 +261,6 @@ class info: CLOSED = 1 UNCLOSED = 2 - class geompyDC(GEOM._objref_GEOM_Gen): def __init__(self): @@ -436,7 +517,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): anObj = self.BasicOp.MakeTangentOnCurve(theRefCurve, theParameter) RaiseIfFailed("MakeTangentOnCurve", self.BasicOp) return anObj - + ## Create a tangent plane, corresponding to the given parameter on the given face. # @param theFace The face for which tangent plane should be built. # @param theParameterV vertical value of the center point (0.0 - 1.0). @@ -559,7 +640,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakePlaneFace", self.BasicOp) anObj.SetParameters(Parameters) return anObj - + ## Create a plane, passing through the 2 vectors # with center in a start point of the first vector. # @param theVec1 Vector, defining center point and plane direction. @@ -575,7 +656,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakePlane2Vec", self.BasicOp) anObj.SetParameters(Parameters) return anObj - + ## Create a plane, based on a Local coordinate system. # @param theLCS coordinate system, defining plane. # @param theTrimSize Half size of a side of quadrangle face, representing the plane. @@ -600,7 +681,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): # @ref swig_MakeMarker "Example" def MakeMarker(self, OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ): # Example: see GEOM_TestAll.py - OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ, Parameters = ParseParameters(OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ); + OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ, Parameters = ParseParameters(OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ); anObj = self.BasicOp.MakeMarker(OX,OY,OZ, XDX,XDY,XDZ, YDX,YDY,YDZ) RaiseIfFailed("MakeMarker", self.BasicOp) anObj.SetParameters(Parameters) @@ -851,7 +932,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): anObj = self.CurvesOp.MakeSketcherOnPlane(theCommand, theWorkingPlane) RaiseIfFailed("MakeSketcherOnPlane", self.CurvesOp) return anObj - + ## Create a sketcher wire, following the numerical description, # passed through theCoordinates argument. \n # @param theCoordinates double values, defining points to create a wire, @@ -908,12 +989,12 @@ class geompyDC(GEOM._objref_GEOM_Gen): anObj = self.PrimOp.MakeBoxTwoPnt(thePnt1, thePnt2) RaiseIfFailed("MakeBoxTwoPnt", self.PrimOp) return anObj - + ## Create a face with specified dimensions along OX-OY coordinate axes, # with edges, parallel to this coordinate axes. # @param theH height of Face. # @param theW width of Face. - # @param theOrientation orientation belong axis OXY OYZ OZX + # @param theOrientation orientation belong axis OXY OYZ OZX # @return New GEOM_Object, containing the created face. # # @ref tui_creation_face "Example" @@ -970,7 +1051,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): ## Create a disk with specified dimensions along OX-OY coordinate axes. # @param theR Radius of Face. - # @param theOrientation set the orientation belong axis OXY or OYZ or OZX + # @param theOrientation set the orientation belong axis OXY or OYZ or OZX # @return New GEOM_Object, containing the created disk. # # @ref tui_creation_face "Example" @@ -1173,7 +1254,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakePrismVecH2Ways", self.PrimOp) anObj.SetParameters(Parameters) return anObj - + ## Create a shape by extrusion of the base shape along the dx, dy, dz direction # @param theBase Base shape to be extruded. # @param theDX, theDY, theDZ Directions of extrusion. @@ -1187,7 +1268,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakePrismDXDYDZ", self.PrimOp) anObj.SetParameters(Parameters) return anObj - + ## Create a shape by extrusion of the base shape along the dx, dy, dz direction # i.e. all the space, transfixed by the base shape during its translation # along the vector on the given distance in 2 Ways (forward/backward) . @@ -2749,15 +2830,17 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFilletFacesR1R2", self.LocalOp) anObj.SetParameters(Parameters) return anObj - - ## Perform a fillet on the specified edges of the given wire shape - # @param theShape - Wire Shape(with planar edges) to perform fillet on. + + ## Perform a fillet on the specified edges of the given shape + # @param theShape - Wire Shape to perform fillet on. # @param theR - Fillet radius. # @param theListOfVertexes Global indices of vertexes to perform fillet on. # \note Global index of sub-shape can be obtained, using method geompy.GetSubShapeID(). + # \note The list of vertices could be empty, + # in this case fillet will done done at all vertices in wire # @return New GEOM_Object, containing the result shape. # - # @ref tui_fillet1d "Example" + # @ref tui_fillet2d "Example" def MakeFillet1D(self,theShape, theR, theListOfVertexes): # Example: see GEOM_TestAll.py anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes) @@ -2778,22 +2861,6 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFillet2D", self.LocalOp) return anObj - ## Perform a fillet on the specified edges of the given shape - # @param theShape - Wire Shape to perform fillet on. - # @param theR - Fillet radius. - # @param theListOfVertexes Global indices of vertexes to perform fillet on. - # \note Global index of sub-shape can be obtained, using method geompy.GetSubShapeID(). - # \note The list of vertices could be empty, - # in this case fillet will done done at all vertices in wire - # @return New GEOM_Object, containing the result shape. - # - # @ref tui_fillet2d "Example" - def MakeFillet1D(self,theShape, theR, theListOfVertexes): - # Example: see GEOM_TestAll.py - anObj = self.LocalOp.MakeFillet1D(theShape, theR, theListOfVertexes) - RaiseIfFailed("MakeFillet1D", self.LocalOp) - return anObj - ## Perform a symmetric chamfer on all edges of the given shape. # @param theShape Shape, to perform chamfer on. # @param theD Chamfer size along each face. @@ -3560,16 +3627,16 @@ class geompyDC(GEOM._objref_GEOM_Gen): # Unite faces and edges, sharing one surface. It means that # this faces must have references to one C++ surface object (handle). # @param theShape The compound or single solid to remove irregular edges from. - # @param theOptimumNbFaces If more than zero, unite faces only for those solids, - # that have more than theOptimumNbFaces faces. If zero, unite faces always, - # regardsless their quantity in the solid. If negative (the default value), - # do not unite faces at all. For blocks repairing recommended value is 6. + # @param doUnionFaces If True, then unite faces. If False (the default value), + # do not unite faces. # @return Improved shape. # # @ref swig_RemoveExtraEdges "Example" - def RemoveExtraEdges(self,theShape,theOptimumNbFaces=-1): + def RemoveExtraEdges(self, theShape, doUnionFaces=False): # Example: see GEOM_TestOthers.py - anObj = self.BlocksOp.RemoveExtraEdges(theShape,theOptimumNbFaces) + nbFacesOptimum = -1 # -1 means do not unite faces + if doUnionFaces is True: nbFacesOptimum = 0 # 0 means unite faces + anObj = self.BlocksOp.RemoveExtraEdges(theShape, nbFacesOptimum) RaiseIfFailed("RemoveExtraEdges", self.BlocksOp) return anObj @@ -3890,6 +3957,37 @@ class geompyDC(GEOM._objref_GEOM_Gen): def addPath(self,Path): if (sys.path.count(Path) < 1): sys.path.append(Path) + pass + pass + + ## Load marker texture from the file + # @param Path a path to the texture file + # @return unique texture identifier + # @ingroup l1_geompy_auxiliary + def LoadTexture(self, Path): + # Example: see GEOM_TestAll.py + ID = self.InsertOp.LoadTexture(Path) + RaiseIfFailed("LoadTexture", self.InsertOp) + return ID + + ## Add marker texture. @a Width and @a Height parameters + # specify width and height of the texture in pixels. + # If @a RowData is @c True, @a Texture parameter should represent texture data + # packed into the byte array. If @a RowData is @c False (default), @a Texture + # parameter should be unpacked string, in which '1' symbols represent opaque + # pixels and '0' represent transparent pixels of the texture bitmap. + # + # @param Width texture width in pixels + # @param Height texture height in pixels + # @param Texture texture data + # @param RowData if @c True, @a Texture data are packed in the byte stream + # @ingroup l1_geompy_auxiliary + def AddTexture(self, Width, Height, Texture, RowData=False): + # Example: see GEOM_TestAll.py + if not RowData: Texture = PackData(Texture) + ID = self.InsertOp.AddTexture(Width, Height, Texture) + RaiseIfFailed("AddTexture", self.InsertOp) + return ID import omniORB #Register the new proxy for GEOM_Gen diff --git a/src/GroupGUI/GroupGUI_GroupDlg.cxx b/src/GroupGUI/GroupGUI_GroupDlg.cxx index 65daf0124..a1cc0bdb9 100644 --- a/src/GroupGUI/GroupGUI_GroupDlg.cxx +++ b/src/GroupGUI/GroupGUI_GroupDlg.cxx @@ -614,49 +614,50 @@ void GroupGUI_GroupDlg::selectAllSubShapes() return; GEOM::ListOfLong_var aSubShapes; - GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); - aSubShapes = aShOp->SubShapeAllIDs(myMainObj, getShapeType(), false); - if ( aSubShapes->length() > 0) { - // if ( !myPlaceCheckBox->isChecked() ) - if ( subSelectionWay() == ALL_SUBSHAPES ) - { - myIdList->clear(); - - if ( !aShOp->IsDone() ) - return; - } - else - { - aSubShapes = new GEOM::ListOfLong(); - aSubShapes->length( myMain2InPlaceIndices.Extent() ); - TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices ); - for ( int i = 0; m2ip.More(); i++, m2ip.Next() ) - aSubShapes[ i ] = m2ip.Key(); - } - bool isBlocked = myIdList->signalsBlocked(); - myIdList->blockSignals( true ); - - for ( int i = 0, n = aSubShapes->length(); i < n; i++ ) { - CORBA::Long anIndex = aSubShapes[i]; - if ( anIndex < 0 ) - continue; - - QListWidgetItem* anItem = 0; - QString text = QString( "%1" ).arg( anIndex ); - if ( !myInPlaceObj->_is_nil() ) { - QList found = myIdList->findItems( text, Qt::MatchExactly ); - if ( found.count() ) anItem = found[0]; - } - if ( !anItem ) { - anItem = new QListWidgetItem( text ); - myIdList->addItem( anItem ); - } - anItem->setSelected( true ); - } - myIdList->blockSignals( isBlocked ); - highlightSubShapes(); + // if ( !myPlaceCheckBox->isChecked() ) + if ( subSelectionWay() == ALL_SUBSHAPES ) + { + if ( !myIsShapeType ) + return; + myIdList->clear(); + GEOM::GEOM_IShapesOperations_var aShOp = getGeomEngine()->GetIShapesOperations( getStudyId() ); + aSubShapes = aShOp->SubShapeAllIDs(myMainObj, getShapeType(), false); + + if ( !aShOp->IsDone() ) + return; + } + else + { + aSubShapes = new GEOM::ListOfLong(); + aSubShapes->length( myMain2InPlaceIndices.Extent() ); + TColStd_DataMapIteratorOfDataMapOfIntegerInteger m2ip( myMain2InPlaceIndices ); + for ( int i = 0; m2ip.More(); i++, m2ip.Next() ) + aSubShapes[ i ] = m2ip.Key(); + } + bool isBlocked = myIdList->signalsBlocked(); + myIdList->blockSignals( true ); + + for ( int i = 0, n = aSubShapes->length(); i < n; i++ ) { + CORBA::Long anIndex = aSubShapes[i]; + if ( anIndex < 0 ) + continue; + + QListWidgetItem* anItem = 0; + QString text = QString( "%1" ).arg( anIndex ); + if ( !myInPlaceObj->_is_nil() ) { + QList found = myIdList->findItems( text, Qt::MatchExactly ); + if ( found.count() ) anItem = found[0]; + } + if ( !anItem ) { + anItem = new QListWidgetItem( text ); + myIdList->addItem( anItem ); + } + anItem->setSelected( true ); } + + myIdList->blockSignals( isBlocked ); + highlightSubShapes(); } //================================================================================= @@ -680,6 +681,17 @@ void GroupGUI_GroupDlg::add() aSelMgr->selectedSubOwners( aMap ); if ( aMap.Size() == 1 ) aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value(); + else { // selected the same subshape as the main object + SALOME_ListIO aSelList; + TColStd_IndexedMapOfInteger aMap; + aSelMgr->selectedObjects(aSelList); + if (aSelList.Extent() == 1) { + Standard_Boolean aRes = Standard_False; + GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aRes); + if ( aSelectedObject->_is_equivalent(myMainObj) ) + aMapIndex.Add(1); // add index of the only subshape of selected type + } + } } } GEOM::ListOfGO anObjects; @@ -859,6 +871,22 @@ void GroupGUI_GroupDlg::updateState() aSelMgr->selectedSubOwners( aMap ); if ( aMap.Size() == 1 ) aMapIndex = LightApp_SelectionMgr::MapEntryOfMapOfInteger::Iterator( aMap ).Value(); + else { // selected the same subshape as the main object + SALOME_ListIO aSelList; + aSelMgr->selectedObjects(aSelList); + if (aSelList.Extent() == 1) { + myBusy = true; + Standard_Boolean aRes = Standard_False; + GEOM::GEOM_Object_var aSelectedObject = GEOMBase::ConvertIOinGEOMObject(aSelList.First(), aRes); + if ( aSelectedObject->_is_equivalent(myMainObj) ) { + aMapIndex.Add(1); // add index of the only subshape of selected type + TColStd_MapOfInteger anIds; // higlight selected index + anIds.Add(1); + aSelMgr->AddOrRemoveIndex(aSelList.First(), anIds, false); + } + myBusy = false; + } + } } } diff --git a/src/IGESExport/IGESExport.cxx b/src/IGESExport/IGESExport.cxx index 23ecf22bc..72e6cb2fa 100644 --- a/src/IGESExport/IGESExport.cxx +++ b/src/IGESExport/IGESExport.cxx @@ -26,6 +26,8 @@ // #include "utilities.h" +#include + #include #include #include @@ -73,6 +75,9 @@ IGESEXPORT_EXPORT if (theFormatName.IsEqual("IGES_5_3")) aBrepMode = 1; + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; + // initialize writer IGESControl_Controller::Init(); //IGESControl_Writer ICW (Interface_Static::CVal("write.iges.unit"), @@ -83,7 +88,10 @@ IGESEXPORT_EXPORT // perform shape writing ICW.AddShape( theShape ); ICW.ComputeModel(); - if ( ICW.Write( theFileName.ToCString() ) ) + bool ok = ICW.Write( theFileName.ToCString() ); + + // Return previous locale + if ( ok ) return 1; } catch(Standard_Failure) diff --git a/src/IGESExport/Makefile.am b/src/IGESExport/Makefile.am index 317442f8a..3d1912bf5 100644 --- a/src/IGESExport/Makefile.am +++ b/src/IGESExport/Makefile.am @@ -42,4 +42,4 @@ libIGESExport_la_CPPFLAGS = \ libIGESExport_la_LDFLAGS = \ $(STDLIB) \ $(CAS_LDPATH) -lTKIGES \ - $(KERNEL_LDFLAGS) -lSALOMELocalTrace + $(KERNEL_LDFLAGS) -lSALOMELocalTrace -lSALOMEBasics diff --git a/src/IGESImport/IGESImport.cxx b/src/IGESImport/IGESImport.cxx index 3b28d2009..ec51293b0 100644 --- a/src/IGESImport/IGESImport.cxx +++ b/src/IGESImport/IGESImport.cxx @@ -26,6 +26,8 @@ // #include "utilities.h" +#include + #include #include #include @@ -71,6 +73,9 @@ IGESIMPORT_EXPORT TCollection_AsciiString& theError, const TDF_Label&) { + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; + IGESControl_Reader aReader; TopoDS_Shape aResShape; Interface_Static::SetCVal("xstep.cascade.unit","M"); diff --git a/src/IGESImport/Makefile.am b/src/IGESImport/Makefile.am index 0252162d6..d12dceda6 100644 --- a/src/IGESImport/Makefile.am +++ b/src/IGESImport/Makefile.am @@ -42,4 +42,4 @@ libIGESImport_la_CPPFLAGS = \ libIGESImport_la_LDFLAGS = \ $(STDLIB) \ $(CAS_LDPATH) -lTKIGES \ - $(KERNEL_LDFLAGS) -lSALOMELocalTrace + $(KERNEL_LDFLAGS) -lSALOMELocalTrace -lSALOMEBasics diff --git a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx index 11d0ab3e0..13d658028 100644 --- a/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_CheckCompoundOfBlocksDlg.cxx @@ -22,7 +22,7 @@ // GEOM GEOMGUI : GUI for Geometry component // File : MeasureGUI_CheckCompoundOfBlocksDlg.cxx // Author : Vladimir KLYACHIN, Open CASCADE S.A.S. (vladimir.klyachin@opencascade.com) -// + #include "MeasureGUI_CheckCompoundOfBlocksDlg.h" #include "MeasureGUI_Widgets.h" @@ -123,8 +123,8 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::Init() connect( myGrp->LineEdit1, SIGNAL( returnPressed() ), this, SLOT( LineEditReturnPressed() ) ); connect( myGrp->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); - connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ), - this, SLOT( SelectionIntoArgument() ) ); + connect( myGeomGUI->getApp()->selectionMgr(), SIGNAL( currentSelectionChanged() ), + this, SLOT( SelectionIntoArgument() ) ); initName( tr( "GEOM_BLOCKS_COMPOUND") ); buttonOk()->setEnabled( false ); @@ -236,7 +236,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::ActivateThisDialog() // purpose : //================================================================================= bool MeasureGUI_CheckCompoundOfBlocksDlg::getBCErrors( bool& theIsCompoundOfBlocks, - GEOM::GEOM_IBlocksOperations::BCErrors& theErrors) + GEOM::GEOM_IBlocksOperations::BCErrors& theErrors) { if ( myObj->_is_nil() ) return false; @@ -245,7 +245,9 @@ bool MeasureGUI_CheckCompoundOfBlocksDlg::getBCErrors( bool& theIsCompoundOfBloc try { GEOM::GEOM_IBlocksOperations::BCErrors_var aErrs; theIsCompoundOfBlocks = anOper->CheckCompoundOfBlocks( myObj, aErrs ); - theErrors = aErrs; + if (anOper->IsDone() && aErrs->length() > 0) + //if (anOper->IsDone() && !aErrs._is_nil()) + theErrors = aErrs; } catch ( const SALOME::SALOME_Exception& e ) { SalomeApp_Tools::QtCatchCorbaException( e ); @@ -266,6 +268,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() bool isCompoundOfBlocks; GEOM::GEOM_IBlocksOperations::BCErrors aErrs; if ( !getBCErrors( isCompoundOfBlocks, aErrs ) ) { + aMsg += tr( "GEOM_CHECK_BLOCKS_COMPOUND_FAILED" ); myGrp->TextView1->setText( aMsg ); myGrp->ListBox1->clear(); myGrp->ListBox2->clear(); @@ -277,7 +280,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() aMsg += tr( "GEOM_CHECK_BLOCKS_COMPOUND_HAS_NO_ERRORS" ); buttonOk()->setEnabled( false ); buttonApply()->setEnabled( false ); - } + } else { aMsg += tr( "GEOM_CHECK_BLOCKS_COMPOUND_HAS_ERRORS" ); buttonOk()->setEnabled( true ); @@ -295,29 +298,29 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::processObject() aErrStr = ""; switch ( aErrs[i].error ) { case GEOM::GEOM_IBlocksOperations::NOT_BLOCK : - aErrStr = "Not a Block"; + aErrStr = "Not a Block"; break; case GEOM::GEOM_IBlocksOperations::EXTRA_EDGE : - aErrStr = "Extra Edge"; + aErrStr = "Extra Edge"; break; case GEOM::GEOM_IBlocksOperations::INVALID_CONNECTION : - aErrStr = "Invalid Connection"; - aErrStr += aConSfx; - aErrStr += QString::number( aConNum ); - aConNum++; + aErrStr = "Invalid Connection"; + aErrStr += aConSfx; + aErrStr += QString::number( aConNum ); + aConNum++; break; case GEOM::GEOM_IBlocksOperations::NOT_CONNECTED : - aErrStr = "Not Connected"; + aErrStr = "Not Connected"; break; case GEOM::GEOM_IBlocksOperations::NOT_GLUED : - aErrStr = "Not Glued"; - aErrStr += aGluedSfx; - aErrStr += QString::number( aGluedNum ); - aGluedNum++; + aErrStr = "Not Glued"; + aErrStr += aGluedSfx; + aErrStr += QString::number( aGluedNum ); + aGluedNum++; break; default : - aErrStr = ""; - break; + aErrStr = ""; + break; } if ( !aErrStr.isEmpty() ) aErrList.append( aErrStr ); @@ -355,11 +358,11 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged() myGrp->ListBox2->clear(); return; } - + GEOM::GEOM_IBlocksOperations::BCError aErr = aErrs[aCurItem]; GEOM::ListOfLong aObjLst = aErr.incriminated; TopoDS_Shape aSelShape; - TopoDS_Shape aSubShape; + TopoDS_Shape aSubShape; TopTools_IndexedMapOfShape anIndices; QStringList aSubShapeList; QString aSubShapeName( "" ); @@ -369,8 +372,8 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onErrorsListSelectionChanged() for ( int i = 0, n = aObjLst.length(); i < n; i++ ) { aSubShapeName = ""; aSubShape = anIndices.FindKey(aObjLst[i]); - if ( GEOMBase::GetShapeTypeString( aSubShape, aTypeString ) ) - aSubShapeName = QString( aTypeString ) + QString( "_" ) + QString::number( aObjLst[i] ); + if ( GEOMBase::GetShapeTypeString( aSubShape, aTypeString ) ) + aSubShapeName = QString( aTypeString ) + QString( "_" ) + QString::number( aObjLst[i] ); if ( !aSubShapeName.isEmpty() ) aSubShapeList.append( aSubShapeName ); } @@ -391,7 +394,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() return; QList aIds; for ( int i = 0, n = myGrp->ListBox2->count(); i < n; i++ ) { - if ( myGrp->ListBox2->item( i )->isSelected() ) + if ( myGrp->ListBox2->item( i )->isSelected() ) aIds.append( i ); } if ( aIds.count() < 1 ) @@ -404,11 +407,11 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() myGrp->ListBox2->clear(); return; } - + GEOM::GEOM_IBlocksOperations::BCError aErr = aErrs[aErrCurItem]; GEOM::ListOfLong aObjLst = aErr.incriminated; TopoDS_Shape aSelShape; - TopoDS_Shape aSubShape; + TopoDS_Shape aSubShape; TopTools_IndexedMapOfShape anIndices; if ( !myObj->_is_nil() && GEOMBase::GetShape( myObj, aSelShape ) ) { QString aMess; @@ -426,7 +429,7 @@ void MeasureGUI_CheckCompoundOfBlocksDlg::onSubShapesListSelectionChanged() getDisplayer()->SetToActivate( false ); aPrs = !aSubShape.IsNull() ? getDisplayer()->BuildPrs( aSubShape ) : 0; if ( aPrs ) - displayPreview( aPrs, true ); + displayPreview( aPrs, true ); } catch ( const SALOME::SALOME_Exception& e ) { SalomeApp_Tools::QtCatchCorbaException( e ); diff --git a/src/OBJECT/GEOM_VTKTrihedron.cxx b/src/OBJECT/GEOM_VTKTrihedron.cxx index 113d7a931..b88a14528 100644 --- a/src/OBJECT/GEOM_VTKTrihedron.cxx +++ b/src/OBJECT/GEOM_VTKTrihedron.cxx @@ -44,6 +44,9 @@ #include #include #include +#include +#include +#include /* Class : GEOM_VTKTrihedron @@ -80,10 +83,7 @@ vtkStandardNewMacro( GEOM_VTKTrihedronAxis ); GEOM_VTKTrihedronAxis::GEOM_VTKTrihedronAxis() { - vtkProperty* aProperty = vtkProperty::New(); - aProperty->SetColor( 0.0, 0.0, 1.0 ); - SetProperty( aProperty ); - aProperty->Delete(); + VTKViewer_Axis::SetColor( 0.0, 0.0, 1.0 ); myMatrix = vtkMatrix4x4::New(); myTrsf = vtkTransform::New(); } @@ -122,15 +122,22 @@ void GEOM_VTKTrihedronAxis::SetSize( vtkFloatingPointType theSize ) myArrowActor->SetUserMatrix( myMatrix ); myArrowActor->SetPosition( aPosition ); +#ifdef IPAL21440 + if( vtkCoordinate* aCoord = myLabelActor->GetPositionCoordinate()->GetReferenceCoordinate() ) + aCoord->SetValue( aPosition ); +#else myLabelActor->SetPosition( 0, 0, 0 ); myLabelActor->AddPosition( aPosition ); +#endif } void GEOM_VTKTrihedronAxis::Render(vtkRenderer* theRenderer) { myLineActor->Render( theRenderer ); myArrowActor->Render( theRenderer ); +#ifndef IPAL21440 myLabelActor->Render( theRenderer ); +#endif vtkCamera* aCamera = theRenderer->GetActiveCamera(); SetCamera( aCamera ); @@ -158,25 +165,25 @@ void GEOM_VTKTrihedronAxis::SetAxis( const gp_Ax1& theAxis, vtkFloatingPointType aColor[ 3 ] = { 0, 0, 0 }; aColor[ theRot ] = 1; - vtkProperty* aProperty = vtkProperty::New(); if ( theColor[ 0 ] == -1 ) - aProperty->SetColor( aColor[ 0 ], aColor[ 1 ], aColor[ 2 ] ); + VTKViewer_Axis::SetColor( aColor[ 0 ], aColor[ 1 ], aColor[ 2 ] ); else - aProperty->SetColor( theColor[ 0 ], theColor[ 1 ], theColor[ 2 ] ); - SetProperty( aProperty ); - aProperty->Delete(); + VTKViewer_Axis::SetColor( theColor[ 0 ], theColor[ 1 ], theColor[ 2 ] ); +#ifdef IPAL21440 + if ( theRot == 0 ) myTextMapper->SetInput( "X" ); + else if ( theRot == 1 ) myTextMapper->SetInput( "Y" ); + else if ( theRot == 2 ) myTextMapper->SetInput( "Z" ); +#else if ( theRot == 0 ) myVectorText->SetText( "X" ); else if ( theRot == 1 ) myVectorText->SetText( "Y" ); else if ( theRot == 2 ) myVectorText->SetText( "Z" ); +#endif } void GEOM_VTKTrihedronAxis::SetColor( const vtkFloatingPointType theColor[ 3 ] ) { - vtkProperty* aProperty = vtkProperty::New(); - aProperty->SetColor( theColor[ 0 ], theColor[ 1 ], theColor[ 2 ] ); - SetProperty( aProperty ); - aProperty->Delete(); + VTKViewer_Axis::SetColor( theColor[ 0 ], theColor[ 1 ], theColor[ 2 ] ); } @@ -193,9 +200,18 @@ GEOM_VTKTrihedron::GEOM_VTKTrihedron() myMapper = vtkPolyDataMapper::New(); myAxis[ 0 ] = myAxis[ 1 ] = myAxis[ 2 ] = 0; mySize = 100; - SetInfinitive( true ); - myColor[ 0 ] = myColor[ 1 ] = myColor[ 1 ] = -1; - SetInfinitive( true ); + + myColor[ 0 ] = myColor[ 1 ] = myColor[ 2 ] = -1; + + myDefaultColor[ 0 ] = myDefaultColor[ 1 ] = myDefaultColor[ 2 ] = 1; + + myPreHighlightColor[ 0 ] = 0; + myPreHighlightColor[ 1 ] = myPreHighlightColor[ 2 ] = 1; + + myHighlightColor[ 0 ] = myHighlightColor[ 1 ] = myHighlightColor[ 2 ] = 1; + + //SetInfinitive( true ); + SetPickable( true ); } GEOM_VTKTrihedron::~GEOM_VTKTrihedron() @@ -247,6 +263,12 @@ void GEOM_VTKTrihedron::SetSize( vtkFloatingPointType theSize ) aRes->Delete(); } +void GEOM_VTKTrihedron::SetVisibility( int theVisibility ) +{ + Superclass::SetVisibility( theVisibility ); + SetVisibility( theVisibility == 1 ? VTKViewer_Trihedron::eOn : VTKViewer_Trihedron::eOff ); +} + void GEOM_VTKTrihedron::SetVisibility( VTKViewer_Trihedron::TVisibility theVis ) { for ( int i = 0; i < 3; i++ ) @@ -361,21 +383,48 @@ bool GEOM_VTKTrihedron::IsSetCamera() const bool GEOM_VTKTrihedron::IsResizable() const { - return true; + return false; } +void GEOM_VTKTrihedron::Highlight( bool theIsHighlight ) +{ + if( theIsHighlight ) + SetAxesColors( myHighlightColor ); + else + ResetAxesColors(); + Superclass::Highlight( theIsHighlight ); +} +bool GEOM_VTKTrihedron::PreHighlight( vtkInteractorStyle *theInteractorStyle, + SVTK_SelectionEvent* theSelectionEvent, + bool theIsHighlight ) +{ + if ( !GetPickable() ) + return false; + if ( !isHighlighted() ) + { + if( theIsHighlight ) + SetAxesColors( myPreHighlightColor ); + else + ResetAxesColors(); + } + return Superclass::PreHighlight( theInteractorStyle, theSelectionEvent, theIsHighlight ); +} +void GEOM_VTKTrihedron::ResetAxesColors() +{ + if( myColor[0] != -1 ) + SetAxesColors( myColor ); + else + SetAxesColors( myDefaultColor, true ); +} - - - - - - - - - +void GEOM_VTKTrihedron::SetAxesColors( vtkFloatingPointType theColor[3], bool theIsDiffuse ) +{ + myAxis[ 0 ]->SetColor( theColor[0], theIsDiffuse ? 0.0 : theColor[1], theIsDiffuse ? 0.0 : theColor[2] ); + myAxis[ 1 ]->SetColor( theIsDiffuse ? 0.0 : theColor[0], theColor[1], theIsDiffuse ? 0.0 : theColor[2] ); + myAxis[ 2 ]->SetColor( theIsDiffuse ? 0.0 : theColor[0], theIsDiffuse ? 0.0 : theColor[1], theColor[2] ); +} diff --git a/src/OBJECT/GEOM_VTKTrihedron.hxx b/src/OBJECT/GEOM_VTKTrihedron.hxx index 9dde2edd4..7808b0b60 100644 --- a/src/OBJECT/GEOM_VTKTrihedron.hxx +++ b/src/OBJECT/GEOM_VTKTrihedron.hxx @@ -57,6 +57,7 @@ public: virtual vtkFloatingPointType GetSize() { return mySize;} + virtual void SetVisibility( int theVisibility ); virtual void SetVisibility( VTKViewer_Trihedron::TVisibility theVis ); virtual void VisibilityOff() { SetVisibility( VTKViewer_Trihedron::eOff ); } virtual void VisibilityOn() { SetVisibility( VTKViewer_Trihedron::eOn ); } @@ -79,7 +80,16 @@ public: void SetColor( vtkFloatingPointType r, vtkFloatingPointType g, vtkFloatingPointType b ); void GetColor( vtkFloatingPointType& r, vtkFloatingPointType& g, vtkFloatingPointType& b ); - virtual bool hasHighlight() { return false; } + virtual bool hasHighlight() { return true; } + + virtual void Highlight( bool theHighlight ); + virtual bool PreHighlight( vtkInteractorStyle* theInteractorStyle, + SVTK_SelectionEvent* theSelectionEvent, + bool theIsHighlight ); + +protected: + virtual void ResetAxesColors(); + virtual void SetAxesColors( vtkFloatingPointType theColor[3], bool theIsDiffuse = false ); protected: VTKViewer_Axis* myAxis[3]; @@ -88,6 +98,9 @@ protected: gp_Pnt myLocation; gp_Dir myDirX, myDirY, myDirZ; vtkFloatingPointType myColor[ 3 ]; + vtkFloatingPointType myDefaultColor[ 3 ]; + vtkFloatingPointType myPreHighlightColor[ 3 ]; + vtkFloatingPointType myHighlightColor[ 3 ]; }; #endif diff --git a/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx index d3220fed8..56f9cb31a 100644 --- a/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx +++ b/src/OperationGUI/OperationGUI_Fillet1d2dDlg.cxx @@ -139,6 +139,8 @@ void OperationGUI_Fillet1d2dDlg::Init() initName(myIs1D ? tr("GEOM_FILLET_1D") : tr("GEOM_FILLET_2D")); GroupVertexes->PushButton1->click(); + + SelectionIntoArgument(); } //================================================================================= diff --git a/src/STEPExport/Makefile.am b/src/STEPExport/Makefile.am index 3748333cb..3371f0105 100644 --- a/src/STEPExport/Makefile.am +++ b/src/STEPExport/Makefile.am @@ -43,6 +43,6 @@ libSTEPExport_la_CPPFLAGS = \ $(KERNEL_CXXFLAGS) libSTEPExport_la_LDFLAGS = \ - $(KERNEL_LDFLAGS) -lSALOMELocalTrace \ + $(KERNEL_LDFLAGS) -lSALOMELocalTrace -lSALOMEBasics \ $(STDLIB) \ $(CAS_LDPATH) -lTKSTEP diff --git a/src/STEPExport/STEPExport.cxx b/src/STEPExport/STEPExport.cxx index 75fd79cfe..6c2e9fac1 100644 --- a/src/STEPExport/STEPExport.cxx +++ b/src/STEPExport/STEPExport.cxx @@ -26,6 +26,8 @@ // #include "utilities.h" +#include + #include #include @@ -67,6 +69,9 @@ STEPEXPORT_EXPORT try { + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; + IFSelect_ReturnStatus status ; //VRV: OCC 4.0 migration STEPControl_Writer aWriter; @@ -76,7 +81,9 @@ STEPEXPORT_EXPORT status = aWriter.Transfer( theShape, STEPControl_AsIs ); //VRV: OCC 4.0 migration if ( status == IFSelect_RetDone ) - status = aWriter.Write( theFileName.ToCString() ) ; + status = aWriter.Write( theFileName.ToCString() ); + + // Return previous locale if ( status == IFSelect_RetDone ) return 1; } diff --git a/src/STEPImport/Makefile.am b/src/STEPImport/Makefile.am index f5e90dabd..a03e4d782 100644 --- a/src/STEPImport/Makefile.am +++ b/src/STEPImport/Makefile.am @@ -43,6 +43,6 @@ libSTEPImport_la_CPPFLAGS = \ $(KERNEL_CXXFLAGS) libSTEPImport_la_LDFLAGS = \ - $(KERNEL_LDFLAGS) -lSALOMELocalTrace \ + $(KERNEL_LDFLAGS) -lSALOMELocalTrace -lSALOMEBasics \ $(STDLIB) \ $(CAS_LDPATH) -lTKSTEP diff --git a/src/STEPImport/STEPImport.cxx b/src/STEPImport/STEPImport.cxx index f021d3a79..e4786f2aa 100644 --- a/src/STEPImport/STEPImport.cxx +++ b/src/STEPImport/STEPImport.cxx @@ -26,6 +26,8 @@ // #include "utilities.h" +#include + #include #include @@ -74,6 +76,8 @@ STEPIMPORT_EXPORT const TDF_Label&) { MESSAGE("Import STEP model from file " << theFileName.ToCString()); + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; TopoDS_Shape aResShape; //VRV: OCC 4.0 migration STEPControl_Reader aReader; @@ -152,6 +156,7 @@ STEPIMPORT_EXPORT theError = aFail->GetMessageString(); aResShape.Nullify(); } + // Return previous locale return aResShape; } } diff --git a/src/TransformationGUI/TransformationGUI_MirrorDlg.cxx b/src/TransformationGUI/TransformationGUI_MirrorDlg.cxx index bb37c2f91..f5d58b658 100644 --- a/src/TransformationGUI/TransformationGUI_MirrorDlg.cxx +++ b/src/TransformationGUI/TransformationGUI_MirrorDlg.cxx @@ -289,10 +289,11 @@ void TransformationGUI_MirrorDlg::SelectionIntoArgument() } // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + /* disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); myGeomGUI->getApp()->selectionMgr()->clearSelected(); connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + this, SLOT(SelectionIntoArgument()));*/ + // here commented, because multiple objects can be selected IPAL 21437 displayPreview(); } diff --git a/src/TransformationGUI/TransformationGUI_PositionDlg.cxx b/src/TransformationGUI/TransformationGUI_PositionDlg.cxx index 6a04c1b98..8f01e5246 100644 --- a/src/TransformationGUI/TransformationGUI_PositionDlg.cxx +++ b/src/TransformationGUI/TransformationGUI_PositionDlg.cxx @@ -425,10 +425,11 @@ void TransformationGUI_PositionDlg::SelectionIntoArgument() } // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + /* disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); myGeomGUI->getApp()->selectionMgr()->clearSelected(); connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + this, SLOT(SelectionIntoArgument()));*/ + // here commented, because multiple objects can be selected IPAL 21437 displayPreview(); } diff --git a/src/TransformationGUI/TransformationGUI_RotationDlg.cxx b/src/TransformationGUI/TransformationGUI_RotationDlg.cxx index 5e68057be..1ff684460 100644 --- a/src/TransformationGUI/TransformationGUI_RotationDlg.cxx +++ b/src/TransformationGUI/TransformationGUI_RotationDlg.cxx @@ -332,10 +332,10 @@ void TransformationGUI_RotationDlg::SelectionIntoArgument() myEditCurrentArgument->setText(aName); if (myEditCurrentArgument == GroupPoints->LineEdit1) { - if (myObjects.length()) { + /* if (myObjects.length()) { if (getConstructorId() == 0 && myAxis->_is_nil() || getConstructorId() == 1 && myCentPoint->_is_nil() ) GroupPoints->PushButton2->click(); - } + }*/ // here commented, because multiple objects can be selected IPAL 21437 } else if (myEditCurrentArgument == GroupPoints->LineEdit2 && getConstructorId() == 0) { myAxis = aSelectedObject; @@ -359,10 +359,11 @@ void TransformationGUI_RotationDlg::SelectionIntoArgument() } // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + /* disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); myGeomGUI->getApp()->selectionMgr()->clearSelected(); connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + this, SLOT(SelectionIntoArgument()));*/ + // here commented, because multiple objects can be selected IPAL 21437 displayPreview(); } diff --git a/src/TransformationGUI/TransformationGUI_ScaleDlg.cxx b/src/TransformationGUI/TransformationGUI_ScaleDlg.cxx index 3384b1816..6ad61b4ec 100644 --- a/src/TransformationGUI/TransformationGUI_ScaleDlg.cxx +++ b/src/TransformationGUI/TransformationGUI_ScaleDlg.cxx @@ -344,10 +344,11 @@ void TransformationGUI_ScaleDlg::SelectionIntoArgument() } // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + /* disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); myGeomGUI->getApp()->selectionMgr()->clearSelected(); connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + this, SLOT(SelectionIntoArgument()));*/ + // here commented, because multiple objects can be selected IPAL 21437 displayPreview(); } diff --git a/src/TransformationGUI/TransformationGUI_TranslationDlg.cxx b/src/TransformationGUI/TransformationGUI_TranslationDlg.cxx index b498d5a68..5bdd8ee5f 100644 --- a/src/TransformationGUI/TransformationGUI_TranslationDlg.cxx +++ b/src/TransformationGUI/TransformationGUI_TranslationDlg.cxx @@ -396,10 +396,11 @@ void TransformationGUI_TranslationDlg::SelectionIntoArgument() } // clear selection - disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + /* disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); myGeomGUI->getApp()->selectionMgr()->clearSelected(); connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), - this, SLOT(SelectionIntoArgument())); + this, SLOT(SelectionIntoArgument()));*/ + // here commented, because multiple objects can be selected IPAL 21437 displayPreview(); }