Connector plug-in
=================
+
+To export Results, Groups, Fields created in active part into GEOM module:
+
+#. select in the Main Menu *Feature - > Export to GEOM* item or
+#. click **Export to GEOM** button in Shaper toolbar:
+
+.. image:: images/geom_export.png
+ :align: center
+
+.. centered::
+ Export to GEOM button
+
+**TUI Command**: *model.exportGEOM(part)*
+
+**Arguments**: 1 part
+
+Result can be checked in GEOM module.
\ No newline at end of file
.. _partPlugin:
Part plug-in
-=============
+============
+
+New Part
+--------
+
+To create a New Part:
+
+#. select in the Main Menu *Part - > New part* item or
+#. click **New part** button in Shaper toolbar:
+
+.. image:: images/new_part.png
+ :align: center
+
+.. centered::
+ New part button
+
+**TUI Command**: *model.addPart(partSet)*
+
+**Arguments**: 1 partset
+
+Result
+""""""
+
+Created empty part is activated and appears in the object browser.
+
+**See Also** a sample TUI Script of a :ref:`tui_create_part` operation.
+
+Duplicate Part
+--------------
+
+To duplicate active Part:
+
+#. select in the Main Menu *Part - > Duplicate part* item or
+#. click **Duplicate part** button in Shaper toolbar:
+
+.. image:: images/duplicate.png
+ :align: center
+
+.. centered::
+ Duplicate part button
+
+Result
+""""""
+
+Created copied part is activated and appears in the object browser.
+
+Copied part contains all objects existing in the source part.
+
+Remove Part
+-----------
+
+To remove active Part:
+
+#. select in the Main Menu *Part - > Remove part* item or
+#. click **Remove part** button in Shaper toolbar:
+
+.. image:: images/remove.png
+ :align: center
+
+.. centered::
+ Remove part button
+
+Result
+""""""
+
+Selected part is removed together with all its objects.
-New Part can be created using *Part* - *New part* main menu item or-
--- /dev/null
+
+ .. _tui_create_part:
+
+Create Part
+===========
+
+.. literalinclude:: examples/new_part.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/new_part.py>`
--- /dev/null
+# -*- coding: utf-8 -*-
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.do()
+model.end()
.. image:: images/Box_dimensions.png
:align: center
-In this case it is necessary to specify **DX**, **DY**, **DZ** sizes of the box along corresponded coordinate axes. The box will be created starting from the origin.
+In this case it is necessary to specify **DX**, **DY**, **DZ** sizes of the box along corresponding coordinate axes. The box will be created starting from the origin.
**TUI Command**: *model.addBox(Part_doc, DX, DY, DZ)*
Python addons
=============
+User can create his own custom features.
+
+Corresponding folder should be created for each feature at ..\sources\src\PythonAddons\macros\.
+
+Feature description includes 4 files:
+
+- widget.xml,
+- __init__.py,
+- feature.py,
+- icon.png located at sub-folder \icons.
+
+Two examples of custom features already created are:
+
.. toctree::
:titlesonly:
:maxdepth: 1
Box
===
+
+Custom feature box is located at ..\sources\src\PythonAddons\macros\box.
+
+.. literalinclude:: examples/box/feature.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/box/feature.py>`
+
+.. literalinclude:: examples/box/widget.xml
+ :linenos:
+ :language: html
+
+:download:`Download this script <examples/box/widget.xml>`
+
+The feature Box creates a box solid by extrusion of rectangle.
+
+Result in Shaper module is described below.
+
+To create a Box in the active part:
+
+#. select in the Main Menu *Macros - > Box* item or
+#. click **Box** button in the Macros toolbar:
+
+.. image:: images/box.png
+ :align: center
+
+.. centered::
+ **Box** button
+
+The following property panel appears.
+
+.. image:: images/box_property_panel.png
+ :align: center
+
+.. centered::
+ Create a box
+
+Input fields:
+
+- **DX**, **DY**, **DZ** sizes of the box along corresponded coordinate axes. The box will be created starting from the origin.
+
+Result
+""""""
+
+The Result of operation will be a SOLID. The edges of the box will be parallel to the coordinate axes.
+
+Name is assigned automatically:
+
+* **Box_1**, **Box_2**, ... to Feature;
+* **Box_1_1**, **Box_2_1**, ... to Result.
+
+Example is shown below.
+
+.. image:: images/Boxes.png
+ :align: center
+
+.. centered::
+ Box created
--- /dev/null
+## Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""Box macro-feature
+Authors: Renaud Nedelec - Daniel Brunier-Coulin
+Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+"""
+
+from salome.shaper import model
+from salome.shaper import geom
+
+
+class BoxFeature(model.Feature):
+ """An example of Box feature implementation.
+
+ BoxFeature() -> Box
+ """
+
+# Initializations
+
+ def __init__(self):
+ """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+ model.Feature.__init__(self)
+
+ @staticmethod
+ def ID():
+ """Return Id of the feature."""
+ return "Box_script"
+
+ @staticmethod
+ def WIDTH_ID():
+ """Returns ID of Width parameter."""
+ return "width"
+
+ @staticmethod
+ def LENGTH_ID():
+ """Returns ID of Length parameter."""
+ return "length"
+
+ @staticmethod
+ def HEIGHT_ID():
+ """Returns ID of Height parameter."""
+ return "height"
+
+ def getKind(self):
+ """Override Feature.getKind()"""
+ return BoxFeature.ID()
+
+
+# Creation of the box at default size
+
+ def initAttributes(self):
+ """Override Feature.initAttributes()"""
+ # Creating the input arguments of the feature
+ self.addRealInput(self.WIDTH_ID())
+ self.addRealInput(self.LENGTH_ID())
+ self.addRealInput(self.HEIGHT_ID())
+
+ # Creating the base of the box with unit values
+ mypart = model.activeDocument()
+ xoy = model.defaultPlane("XOY")
+
+ # A base of the geometry
+ self.base = model.addSketch(mypart, xoy)
+
+ p1 = geom.Pnt2d(0, 0)
+ p2 = geom.Pnt2d(0, 1)
+ p3 = geom.Pnt2d(1, 1)
+ p4 = geom.Pnt2d(1, 0)
+
+ line = model.addPolygon(self.base, p1, p2, p3, p4)
+
+ self.base.setFixed(line[0].startPoint())
+ self.base.setVertical(line[0])
+
+ # Setting the size of the base with default values
+ # Width
+ self.width = self.base.setLength(line[3], 50) # Keeps the constraint for edition
+ # Length
+ self.length = self.base.setLength(line[0], 50) # Keeps the constraint for edition
+
+ # Keeping the rectangle
+ self.base.setParallel(line[0], line[2])
+ self.base.setParallel(line[1], line[3])
+ self.base.setPerpendicular(line[0], line[3])
+
+ # execute sketch
+ mypart.setCurrentFeature(self.base.feature(), False)
+ model.updateFeatures()
+
+ # Creating the extrusion (the box) at default size
+ # A box result
+ self.box = model.addExtrusion(mypart, self.base.selectFace(), 50)
+
+# Edition of the box at user size
+
+ def execute(self):
+ """F.execute() -- execute the feature"""
+ # Retrieving the user inputs
+ width = self.real(self.WIDTH_ID())
+ length = self.real(self.LENGTH_ID())
+ height = self.real(self.HEIGHT_ID())
+
+ # Editing the box
+ if width.text() == "":
+ self.base.setValue(self.width, width.value())
+ else:
+ self.base.setValue(self.width, width.text())
+
+ if length.text() == "":
+ self.base.setValue(self.length, length.value())
+ else:
+ self.base.setValue(self.length, length.text())
+
+ if (height.text() == ""):
+ self.box.setSize(height.value())
+ else:
+ self.box.setSize(height.text())
+
+ # Publishing the result: not needed for Macro feature
+ # self.addResult( self.box.result() )
+
+ def isMacro(self):
+ """Override Feature.initAttributes().
+ F.isMacro() -> True
+
+ Box feature is macro: removes itself on the creation transaction
+ finish.
+ """
+ return True
--- /dev/null
+<!--
+Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+ <workbench id="Macros" document="Part">
+ <group id="Samples">
+
+ <feature id="Box_script" title="Box" tooltip="Create a box parallel to xyz by extruding a rectangular" icon="icons/Addons/box_ico.png"
+ helpfile="boxFeature.html">
+ <doublevalue id="width" label="Width: " min="0" step="1.0" default="50" tooltip="Box width">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ <doublevalue id="length" label="Length: " min="0" step="1.0" default="50" tooltip="Box length">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ <doublevalue id="height" label="Height: " min="0" step="1.0" default="50" tooltip="Box height">
+ <validator id="GeomValidators_Positive"/>
+ </doublevalue>
+ </feature>
+
+ </group>
+ </workbench>
+</source>
--- /dev/null
+## Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+Macro-feature to produce rectangle in the sketcher
+Author: Artem ZHIDKOV
+Copyright (C) 2016-20xx CEA/DEN, EDF R&D
+"""
+
+from salome.shaper import model
+import ModelAPI
+import GeomDataAPI
+
+class SketchPlugin_Rectangle(model.Feature):
+ """
+ Implementation of rectangle creation.
+
+ It produced 2 horizontal lines and 2 vertical lines connected by coincidence constraints
+ """
+
+# Initializations
+
+ def __init__(self):
+ """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
+ model.Feature.__init__(self)
+
+ @staticmethod
+ def ID():
+ """Rectangle feature kind."""
+ return "SketchRectangle"
+
+ @staticmethod
+ def START_ID():
+ """Returns ID of first corner."""
+ return "RectStartPoint"
+
+ @staticmethod
+ def END_ID():
+ """Returns ID of second corner."""
+ return "RectEndPoint"
+
+ @staticmethod
+ def AUXILIARY_ID():
+ """Returns whether the rectangle is accessory."""
+ return "Auxiliary"
+
+ @staticmethod
+ def LINES_LIST_ID():
+ """Returns ID of list containing lines created."""
+ return "RectangleList"
+
+ def getKind(self):
+ """Override Feature.getKind()"""
+ return SketchPlugin_Rectangle.ID()
+
+
+# Initialization of the rectangle
+
+ def initAttributes(self):
+ """Override Feature.initAttributes()"""
+ # Flag whether the rectangle is accessory
+ self.data().addAttribute(self.AUXILIARY_ID(), ModelAPI.ModelAPI_AttributeBoolean_typeId())
+ # Creating corners of the rectangle
+ self.data().addAttribute(self.START_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
+ self.data().addAttribute(self.END_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
+ # Creating list to store lines
+ self.data().addAttribute(self.LINES_LIST_ID(), ModelAPI.ModelAPI_AttributeRefList_typeId())
+ ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.LINES_LIST_ID())
+
+ def isMacro(self):
+ """
+ Override Feature.isMacro().
+ Rectangle feature is macro: removes itself on the creation transaction finish.
+ """
+ return True
+
+# Edition of the rectangle
+
+ def execute(self):
+ # Retrieving list of already created lines
+ aLinesList = self.reflist(self.LINES_LIST_ID())
+ aNbLines = aLinesList.size()
+ if aNbLines == 1:
+ # Create 1-4 lines to compose the rectangle
+ for i in range (0, 3):
+ aLine = self.__sketch.addFeature("SketchLine")
+ aLinesList.append(aLine)
+ self.updateLines()
+ aNbLines = aLinesList.size()
+ # Create constraints to keep the rectangle
+ for i in range (0, aNbLines):
+ aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+ # connect neighbor lines by coincidence
+ iPrev = i - 1
+ if iPrev < 0:
+ iPrev = aNbLines - 1
+ aPrevLine = ModelAPI.objectToFeature(aLinesList.object(iPrev))
+ aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
+ aRefAttrA = aCoincidence.refattr("ConstraintEntityA")
+ aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
+ aRefAttrA.setAttr(aPrevLine.attribute("EndPoint"))
+ aRefAttrB.setAttr(aLine.attribute("StartPoint"))
+ # Flags which show horizontal or vertical constraint is build for correponding line
+ self.__isHV = [False, False, False, False]
+ # Update coordinates of created lines
+ self.updateLines()
+ # Add horizontal and vertical constraint for the lines which already have result
+ for i in range (0, aNbLines):
+ if self.__isHV[i]:
+ continue
+ aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+ aLineResult = aLine.lastResult()
+ if aLineResult is None:
+ continue
+ aHVName = "SketchConstraintHorizontal"
+ if i % 2 == 1:
+ aHVName = "SketchConstraintVertical"
+ aHVConstraint = self.__sketch.addFeature(aHVName)
+ aRefAttrA = aHVConstraint.refattr("ConstraintEntityA")
+ aRefAttrA.setObject(aLine.lastResult())
+ self.__isHV[i] = True
+
+ def attributeChanged(self, theID):
+ if theID == self.START_ID() or theID == self.END_ID():
+ # Search the sketch containing this rectangle
+ self.__sketch = None
+ aRefs = self.data().refsToMe();
+ for iter in aRefs:
+ aFeature = ModelAPI.objectToFeature(iter.owner())
+ if aFeature.getKind() == "Sketch":
+ self.__sketch = ModelAPI.featureToCompositeFeature(aFeature)
+ break
+
+ aLinesList = self.reflist(self.LINES_LIST_ID())
+ aNbLines = aLinesList.size()
+ if aNbLines == 0:
+ # Create first line to be able to create a coincidence with selected point/feature
+ for i in range (0, 1):
+ aLine = self.__sketch.addFeature("SketchLine")
+ aLinesList.append(aLine)
+
+ aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
+ aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
+ if aStartPoint.isInitialized() and aEndPoint.isInitialized():
+ self.updateLines()
+ else:
+ self.updateStartPoint()
+ if theID == self.AUXILIARY_ID():
+ anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
+ aLinesList = self.reflist(self.LINES_LIST_ID())
+ aNbLines = aLinesList.size()
+ # Update coordinates of rectangle lines
+ for i in range (0, aNbLines):
+ aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+ aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
+
+
+ def updateLines(self):
+ # Retrieving list of already created lines
+ aLinesList = self.reflist(self.LINES_LIST_ID())
+ aNbLines = aLinesList.size()
+ aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
+ aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
+ aX = [aStartPoint.x(), aStartPoint.x(), aEndPoint.x(), aEndPoint.x()]
+ aY = [aStartPoint.y(), aEndPoint.y(), aEndPoint.y(), aStartPoint.y()]
+ anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
+
+ # Update coordinates of rectangle lines
+ for i in range (0, aNbLines):
+ aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+ aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+ aLineEnd = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+ aLineStart.setValue(aX[i-1], aY[i-1])
+ aLineEnd.setValue(aX[i], aY[i])
+ aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
+
+ def updateStartPoint(self):
+ # Retrieving list of already created lines
+ aLinesList = self.reflist(self.LINES_LIST_ID())
+ aNbLines = aLinesList.size()
+
+ aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
+ aX = aStartPoint.x()
+ aY = aStartPoint.y()
+
+ # Update coordinates of rectangle lines
+ for i in range (0, aNbLines):
+ aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+ aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+ aLineStart.setValue(aX, aY)
--- /dev/null
+<!--
+Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See http:##www.salome-platform.org/ or
+email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+ <workbench id="Sketch">
+ <group id="Linear geometry">
+
+ <!-- SketchRectangle (python feature) -->
+ <feature
+ id="SketchRectangle"
+ title="Rectangle"
+ tooltip="Create rectangle"
+ icon="icons/Addons/rectangle.png"
+ helpfile="rectangleFeature.html">
+ <sketch-2dpoint_selector id="RectStartPoint" accept_expressions="0" title="Start point" tooltip="Start point coordinates"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="RectEndPoint" accept_expressions="0" title="End point" tooltip="End point coordinates"
+ enable_value="enable_by_preferences"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <validator id="GeomValidators_Different" parameters="RectStartPoint,RectEndPoint"/>
+ </feature>
+
+ </group>
+ </workbench>
+</source>