]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Restore PythonFeaturesPLugin
authorsbh <sergey.belash@opencascade.com>
Fri, 27 Feb 2015 15:20:15 +0000 (18:20 +0300)
committersbh <sergey.belash@opencascade.com>
Fri, 27 Feb 2015 15:20:15 +0000 (18:20 +0300)
12 files changed:
CMakeLists.txt
src/Config/plugins.xml
src/PythonFeaturesPlugin/CMakeLists.txt [new file with mode: 0644]
src/PythonFeaturesPlugin/FeaturesAPI.py [new file with mode: 0644]
src/PythonFeaturesPlugin/PythonFeaturesPlugin.py [new file with mode: 0644]
src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py [new file with mode: 0644]
src/PythonFeaturesPlugin/SketchResult.py [new file with mode: 0644]
src/PythonFeaturesPlugin/box_widget.xml [new file with mode: 0644]
src/PythonFeaturesPlugin/examples.py [new file with mode: 0644]
src/PythonFeaturesPlugin/extrusion.py [new file with mode: 0644]
src/PythonFeaturesPlugin/plugin-PythonFeatures.xml [new file with mode: 0644]
src/PythonFeaturesPlugin/sketch.py [new file with mode: 0644]

index ea51439dfafdc64027a31c58cb1a4e4e09503e9f..726fbacaaaa1da43b8bf6781252b4125bc6e89d5 100644 (file)
@@ -54,6 +54,7 @@ ADD_SUBDIRECTORY (src/GeomDataAPI)
 ADD_SUBDIRECTORY (src/PartSetPlugin)
 ADD_SUBDIRECTORY (src/ConstructionPlugin)
 ADD_SUBDIRECTORY (src/FeaturesPlugin)
+ADD_SUBDIRECTORY (src/PythonFeaturesPlugin)
 ADD_SUBDIRECTORY (src/SketchPlugin)
 ADD_SUBDIRECTORY (src/SketchSolver)
 ADD_SUBDIRECTORY (src/ModuleBase)
index e8d43ed022a5ef39b45c1d4462b06fd55edf69db..bf95bc97c3f353b7ec5df0f734ca915d4e0c56a9 100644 (file)
@@ -6,6 +6,7 @@
   <plugin library="ConstructionPlugin" configuration="plugin-Construction.xml"/>
   <plugin library="FeaturesPlugin" configuration="plugin-Features.xml"/>
   <plugin library="ExchangePlugin" configuration="plugin-Exchange.xml"/>
+  <plugin script="PythonFeaturesPlugin" configuration="plugin-PythonFeatures.xml"/>
   <plugin script="ConnectorPlugin" configuration="plugin-Connector.xml" dependency="Geometry"/>
   <plugin library="SketchSolver"/>
   <plugin library="GeomValidators"/>
diff --git a/src/PythonFeaturesPlugin/CMakeLists.txt b/src/PythonFeaturesPlugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1e600b3
--- /dev/null
@@ -0,0 +1,17 @@
+INCLUDE(Common)
+
+SET(PYTHON_FILES
+  PythonFeaturesPlugin_Box.py
+  PythonFeaturesPlugin.py
+  sketch.py
+  extrusion.py
+  examples.py
+  SketchResult.py
+)
+
+SET(XML_RESSOURCES
+  plugin-PythonFeatures.xml
+  box_widget.xml
+)
+
+INSTALL(FILES ${PYTHON_FILES} ${XML_RESSOURCES} DESTINATION plugins)
diff --git a/src/PythonFeaturesPlugin/FeaturesAPI.py b/src/PythonFeaturesPlugin/FeaturesAPI.py
new file mode 100644 (file)
index 0000000..f47ba3f
--- /dev/null
@@ -0,0 +1,47 @@
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+
+# NOTE : I think this style should be chosen
+# for function as recommended by Python programming
+# standards
+
+
+def build_face_from_sketch(sketch, edges=None):
+    # If no edges have been selected, get the whole sketch
+    # edges
+    if edges == None:
+        result = sketch.firstResult()
+        edges = modelAPI_ResultConstruction(result).shape()
+
+    # Build the face
+    origin = geomDataAPI_Point(sketch.attribute("Origin")).pnt()
+    dirX = geomDataAPI_Dir(sketch.attribute("DirX")).dir()
+    dirY = geomDataAPI_Dir(sketch.attribute("DirY")).dir()
+    normal = geomDataAPI_Dir(sketch.attribute("Norm")).dir()
+    faces = ShapeList()
+    GeomAlgoAPI_SketchBuilder.createFaces(
+        origin, dirX, dirY, normal, edges, faces)
+    return faces[0]
+
+# NOTE : with an optional argument it is not
+# a so good idea to put part as last argument
+# it would result in a mandatory argument
+# put after an optionnal one
+
+
+def addExtrusion(part, sketch, size, reverse=False, subshapes=None):
+    feature = part.addFeature("Extrusion")
+
+    # Build apropriate face
+    face = build_face_from_sketch(sketch, subshapes)
+    # Get sketch result
+    sketchResult = sketch.firstResult()
+
+    # Set attributes and execute the feature
+    feature.selection("extrusion_face").setValue(sketchResult, face)
+    feature.real("extrusion_size").setValue(size)
+    feature.boolean("extrusion_reverse").setValue(False)
+    feature.execute()
+
+    return feature
diff --git a/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py b/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py
new file mode 100644 (file)
index 0000000..ca671e1
--- /dev/null
@@ -0,0 +1,20 @@
+import ModelAPI
+from PythonFeaturesPlugin_Box import PythonFeaturesPlugin_Box
+
+
+class PythonFeaturesPlugin(ModelAPI.ModelAPI_Plugin):
+
+    def __init__(self):
+        ModelAPI.ModelAPI_Plugin.__init__(self)
+        pass
+
+    def createFeature(self, theFeatureID):
+        if theFeatureID == PythonFeaturesPlugin_Box.ID():
+            return PythonFeaturesPlugin_Box().__disown__()
+        else:
+            raise StandardError("No such feature %s" % theFeatureID)
+
+plugin = PythonFeaturesPlugin()
+aSession = ModelAPI.ModelAPI_Session.get()
+print "Module loaded. Session", aSession
+aSession.registerPlugin(plugin)
diff --git a/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py b/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py
new file mode 100644 (file)
index 0000000..b150690
--- /dev/null
@@ -0,0 +1,130 @@
+import ModelAPI
+
+from SketchResult import SketchResult
+import extrusion
+import sketch
+
+
+class PythonFeaturesPlugin_Box(ModelAPI.ModelAPI_Feature):
+
+    "Feature to create a box by drawing a sketch and extruding it"
+
+    def __init__(self):
+        ModelAPI.ModelAPI_Feature.__init__(self)
+
+    @staticmethod
+    def ID():
+        return "Box"
+
+    @staticmethod
+    def WIDTH_ID():
+        return "box_width"
+
+    @staticmethod
+    def LENGTH_ID():
+        return "box_length"
+
+    @staticmethod
+    def HEIGHT_ID():
+        return "box_height"
+
+    @staticmethod
+    def WIDTH_REF_ID():
+        return "box_ref_width"
+
+    @staticmethod
+    def LENGTH_REF_ID():
+        return "box_ref_length"
+
+    @staticmethod
+    def HEIGHT_REF_ID():
+        return "box_ref_height"
+
+    def getKind(self):
+        return PythonFeaturesPlugin_Box.ID()
+
+    def initAttributes(self):
+        # C++ static methods (in example "type()" of the ModelAPI_AttributeDouble
+        # should be called like this: moduleName.ClassName_staticMethod()
+        self.data().addAttribute(self.WIDTH_ID(), ModelAPI.ModelAPI_AttributeDouble_type())
+        self.data().addAttribute(self.LENGTH_ID(), ModelAPI.ModelAPI_AttributeDouble_type())
+        self.data().addAttribute(self.HEIGHT_ID(), ModelAPI.ModelAPI_AttributeDouble_type())
+        self.data().addAttribute(self.WIDTH_REF_ID(), ModelAPI.ModelAPI_AttributeReference_type())
+        self.data().addAttribute(self.LENGTH_REF_ID(), ModelAPI.ModelAPI_AttributeReference_type())
+        self.data().addAttribute(self.HEIGHT_REF_ID(), ModelAPI.ModelAPI_AttributeReference_type())
+        aSession = ModelAPI.ModelAPI_Session.get()
+        aSession.validators().registerNotObligatory(self.getKind(), self.WIDTH_REF_ID())
+        aSession.validators().registerNotObligatory(self.getKind(), self.LENGTH_REF_ID())
+        aSession.validators().registerNotObligatory(self.getKind(), self.HEIGHT_REF_ID())
+        aSession.validators().registerConcealment(self.getKind(), self.HEIGHT_REF_ID())
+
+    def execute(self):
+        aWidth = self.real(self.WIDTH_ID()).value()
+        aLength = self.real(self.LENGTH_ID()).value()
+        aHeight = self.real(self.HEIGHT_ID()).value()
+        aWidthRefValue = self.reference(self.WIDTH_REF_ID()).value()
+        aLengthRefValue = self.reference(self.LENGTH_REF_ID()).value()
+        aHeightRefValue = self.reference(self.HEIGHT_REF_ID()).value()
+        aResult = None
+        if not all((aWidthRefValue, aLengthRefValue, aHeightRefValue)):
+            aResult = extrusion.getBody(self.makeBox(aLength, aWidth, aHeight))
+        else:
+            aHeightProxyResult = ModelAPI.modelAPI_Result(aHeightRefValue)
+            aWidthFeature = ModelAPI.modelAPI_Feature(aWidthRefValue)
+            aLengthFeature = ModelAPI.modelAPI_Feature(aLengthRefValue)
+            aHeightResult = ModelAPI.modelAPI_ResultBody(aHeightProxyResult)
+            aWidthFeature.real("ConstraintValue").setValue(aWidth)
+            aLengthFeature.real("ConstraintValue").setValue(aLength)
+            if aHeightResult is not None:
+                aHeightFeature = aHeightResult.document().feature(aHeightResult)
+                aHeightFeature.real("extrusion_size").setValue(aHeight)
+                aResult = extrusion.getBody(aHeightFeature)
+        self.setResult(aResult)
+
+    def makeBox(self, aWidth, aLength, aHeight):
+        aSession = ModelAPI.ModelAPI_Session.get()
+        aPart = aSession.activeDocument()
+        # Starting the Sketch
+        aSketch = sketch.addTo(aPart)
+        sketch.setXOYPlane(aSketch)
+        # Creating the lines
+        l1 = sketch.addLine(10, 10, 10, 50, aSketch)
+        l2 = sketch.addLine(10, 50, 60, 60, aSketch)
+        l3 = sketch.addLine(60, 60, 50, 10, aSketch)
+        l4 = sketch.addLine(50, 10, 10, 10, aSketch)
+        aSketch.execute()
+        # Creating the constraints
+        sketch.makeCoincident(sketch.getEndPoint(l1), sketch.getStartPoint(l2), aSketch)
+        sketch.makeCoincident(sketch.getEndPoint(l2), sketch.getStartPoint(l3), aSketch)
+        sketch.makeCoincident(sketch.getEndPoint(l3), sketch.getStartPoint(l4), aSketch)
+        sketch.makeCoincident(sketch.getEndPoint(l4), sketch.getStartPoint(l1), aSketch)
+        sketch.makeParallel(sketch.getGeometry(l1), sketch.getGeometry(l3), aSketch)
+        sketch.makeParallel(sketch.getGeometry(l2), sketch.getGeometry(l4), aSketch)
+        sketch.makePerpendicular(sketch.getGeometry(l1), sketch.getGeometry(l4), aSketch)
+        # Set to 0X and 0Y lines defined length
+        aWidthFeature = sketch.makeConstantLength(sketch.getGeometry(l4), aWidth, aSketch)
+        aLengthFeature = sketch.makeConstantLength(sketch.getGeometry(l1), aLength, aSketch)
+        # Finalisation of the operation
+        builder = SketchResult(aSketch)
+        # Creating a feature Extrusion
+        aHeightFeature = extrusion.addNew(builder, aHeight, aPart)
+        # Store features...
+        self.reference(self.WIDTH_REF_ID()).setValue(aWidthFeature)
+        self.reference(self.LENGTH_REF_ID()).setValue(aLengthFeature)
+        self.reference(self.HEIGHT_REF_ID()).setValue(aHeightFeature.firstResult())
+        return aHeightFeature
+
+
+# TEST
+"""
+if __name__=='__main__':
+  session = ModelAPI.ModelAPI_Session.get()
+  part = session.activeDocument()
+  session.startOperation()
+  feature = part.addFeature('Box')
+  feature.real('box_width').setValue(10)
+  feature.real('box_length').setValue(10)
+  feature.real('box_height').setValue(10)
+  feature.execute()
+  session.finishOperation()
+"""
diff --git a/src/PythonFeaturesPlugin/SketchResult.py b/src/PythonFeaturesPlugin/SketchResult.py
new file mode 100644 (file)
index 0000000..8d8b77a
--- /dev/null
@@ -0,0 +1,26 @@
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+
+
+class SketchResult:
+
+    def __init__(self, sketch):
+        self.geom = sketch.firstResult()
+        self.faces = ShapeList()
+        self.edges = modelAPI_ResultConstruction(self.geom).shape()
+        self.origin = geomDataAPI_Point(sketch.attribute("Origin")).pnt()
+        self.dirX = geomDataAPI_Dir(sketch.attribute("DirX")).dir()
+        self.dirY = geomDataAPI_Dir(sketch.attribute("DirY")).dir()
+        self.normal = geomDataAPI_Dir(sketch.attribute("Norm")).dir()
+
+    def setEdges(self, edges):
+        self.edges = edges
+
+    def geometry(self):
+        return self.geom
+
+    def face(self):
+        GeomAlgoAPI_SketchBuilder.createFaces(
+            self.origin, self.dirX, self.dirY, self.normal, self.edges, self.faces)
+        return self.faces[0]
diff --git a/src/PythonFeaturesPlugin/box_widget.xml b/src/PythonFeaturesPlugin/box_widget.xml
new file mode 100644 (file)
index 0000000..7c1a2c5
--- /dev/null
@@ -0,0 +1,11 @@
+<source>
+  <doublevalue id="box_width" label="Width" min="0" step="1.0" default="50" icon=":icons/dimension_v.png" tooltip="Set width of the box">
+    <validator id="GeomValidators_Positive"/>
+  </doublevalue>
+  <doublevalue id="box_length" label="Length" min="0" step="1.0" default="50" icon=":icons/dimension_v.png" tooltip="Set length of the box">
+    <validator id="GeomValidators_Positive"/>
+  </doublevalue>
+  <doublevalue id="box_height" label="Height" min="0" step="1.0" default="50" icon=":icons/dimension_v.png" tooltip="Set height of the box">
+    <validator id="GeomValidators_Positive"/>
+  </doublevalue>
+</source>
diff --git a/src/PythonFeaturesPlugin/examples.py b/src/PythonFeaturesPlugin/examples.py
new file mode 100644 (file)
index 0000000..9f68e92
--- /dev/null
@@ -0,0 +1,51 @@
+from ModelAPI import *
+from SketchResult import *
+import sketch
+import extrusion
+# reload(sketch) # Pour tester plus facilement
+# reload(extrusion) # Pour tester plus facilement
+
+
+def makeBox(aLength, aWidth, aHeight):
+    # Getting the active document
+    session = ModelAPI_Session.get()
+    part = session.activeDocument()
+
+    # Starting the Sketch
+    base = sketch.addTo(part)
+    sketch.setXOYPlane(base)
+
+    # Creating the lines
+    l1 = sketch.addLine(10, 10, 10, 50, base)
+    l2 = sketch.addLine(10, 50, 60, 60, base)
+    l3 = sketch.addLine(60, 60, 50, 10, base)
+    l4 = sketch.addLine(50, 10, 10, 10, base)
+    base.execute()
+
+    # Creating the constraints
+    sketch.makeCoincident(sketch.getEndPoint(l1),
+                          sketch.getStartPoint(l2), base)
+    sketch.makeCoincident(sketch.getEndPoint(l2),
+                          sketch.getStartPoint(l3), base)
+    sketch.makeCoincident(sketch.getEndPoint(l3),
+                          sketch.getStartPoint(l4), base)
+    sketch.makeCoincident(sketch.getEndPoint(l4),
+                          sketch.getStartPoint(l1), base)
+
+    sketch.makeParallel(sketch.getGeometry(l1), sketch.getGeometry(l3), base)
+    sketch.makeParallel(sketch.getGeometry(l2), sketch.getGeometry(l4), base)
+
+    sketch.makePerpendicular(sketch.getGeometry(l1),
+                             sketch.getGeometry(l4), base)
+    # Set to 0X and 0Y lines defined length
+    sketch.makeConstantLength(sketch.getGeometry(l1), aLength, base)
+    sketch.makeConstantLength(sketch.getGeometry(l4), aWidth, base)
+
+    # Finalisation of the operation
+    builder = SketchResult(base)
+
+    # Creating a feature Extrusion
+    box = extrusion.addNew(builder, aHeight, part)
+
+    # return base.lastResult()
+    return extrusion.getBody(box)
diff --git a/src/PythonFeaturesPlugin/extrusion.py b/src/PythonFeaturesPlugin/extrusion.py
new file mode 100644 (file)
index 0000000..9008479
--- /dev/null
@@ -0,0 +1,15 @@
+from ModelAPI import *
+
+
+def addNew(builder, length, part, edges=None, reverse=False):
+    feature = part.addFeature("Extrusion")
+    feature.selection("extrusion_face").setValue(builder.geometry(),
+                                                 builder.face())
+    feature.real("extrusion_size").setValue(length)
+    feature.boolean("extrusion_reverse").setValue(reverse)
+    feature.execute()
+    return feature
+
+
+def getBody(extrusion):
+    return modelAPI_ResultBody(extrusion.firstResult())
diff --git a/src/PythonFeaturesPlugin/plugin-PythonFeatures.xml b/src/PythonFeaturesPlugin/plugin-PythonFeatures.xml
new file mode 100644 (file)
index 0000000..2f7b97b
--- /dev/null
@@ -0,0 +1,9 @@
+<plugin>
+  <workbench id="Features" document="Part">
+    <group id="Basic">
+      <feature id="Box" title="Box" tooltip="Create a box" icon=":pictures/part_ico.png">
+          <source path="box_widget.xml"/>
+      </feature>
+    </group>
+  </workbench>  
+</plugin>
diff --git a/src/PythonFeaturesPlugin/sketch.py b/src/PythonFeaturesPlugin/sketch.py
new file mode 100644 (file)
index 0000000..ca13a70
--- /dev/null
@@ -0,0 +1,134 @@
+from ModelAPI import *
+from GeomDataAPI import *
+
+
+# Initialization of the Sketch
+# ----------------------------
+
+def addTo(doc):
+    return modelAPI_CompositeFeature(doc.addFeature("Sketch"))
+
+
+def setXOYPlane(sketch):
+    geomDataAPI_Point(sketch.attribute("Origin")).setValue(0, 0, 0)
+    geomDataAPI_Dir(sketch.attribute("DirX")).setValue(1, 0, 0)
+    geomDataAPI_Dir(sketch.attribute("DirY")).setValue(0, 1, 0)
+    geomDataAPI_Dir(sketch.attribute("Norm")).setValue(0, 0, 1)
+
+
+# Point geometry
+# --------------
+
+def addPoint(x, y, sketch):
+    point = sketch.addFeature("SketchPoint")
+    geomDataAPI_Point2D(point.attribute("PointCoordindates")).setValue(x, y)
+    # Required to get the result, if needed for creating constraints
+    point.execute()
+    return point
+
+
+def getGeometry(point):
+    return geomDataAPI_Point2D(point.attribute("PointCoordindates"))
+
+
+# Line geometry
+# -------------
+
+def addClosedBrokenLine(coords, sketch):
+    c0 = coords[0]
+    c1 = coords[1]
+    bl = []
+    l1 = sketch.addFeature("SketchLine")
+    geomDataAPI_Point2D(l1.attribute("StartPoint")).setValue(c0.x(), c0.y())
+    geomDataAPI_Point2D(l1.attribute("EndPoint")).setValue(c1.x(), c1.y())
+    l1.execute()
+    bl.append(l1)
+    l0 = l1
+
+    for c2 in coords[2:]:
+        l2 = sketch.addFeature("SketchLine")
+        geomDataAPI_Point2D(
+            l2.attribute("StartPoint")).setValue(c1.x(), c1.y())
+        geomDataAPI_Point2D(l2.attribute("EndPoint")).setValue(c2.x(), c2.y())
+        l2.execute()
+        bl.append(l2)
+        constraint = sketch.addFeature("SketchConstraintCoincidence")
+        constraint.refattr("ConstraintEntityA").setAttr(
+            l1.attribute("EndPoint"))
+        constraint.refattr("ConstraintEntityB").setAttr(
+            l2.attribute("StartPoint"))
+        c1 = c2
+        l1 = l2
+
+    if len(coords) > 2:
+        l2 = sketch.addFeature("SketchLine")
+        geomDataAPI_Point2D(
+            l2.attribute("StartPoint")).setValue(c1.x(), c1.y())
+        geomDataAPI_Point2D(l2.attribute("EndPoint")).setValue(c0.x(), c0.y())
+        l2.execute()
+        bl.append(l2)
+        constraint = sketch.addFeature("SketchConstraintCoincidence")
+        constraint.refattr("ConstraintEntityA").setAttr(
+            l1.attribute("EndPoint"))
+        constraint.refattr("ConstraintEntityB").setAttr(
+            l2.attribute("StartPoint"))
+
+        constraint = sketch.addFeature("SketchConstraintCoincidence")
+        constraint.refattr("ConstraintEntityA").setAttr(
+            l2.attribute("EndPoint"))
+        constraint.refattr("ConstraintEntityB").setAttr(
+            l0.attribute("StartPoint"))
+
+    return bl
+
+
+def addLine(x1, y1, x2, y2, sketch):
+    line = sketch.addFeature("SketchLine")
+    geomDataAPI_Point2D(line.attribute("StartPoint")).setValue(x1, y1)
+    geomDataAPI_Point2D(line.attribute("EndPoint")).setValue(x2, y2)
+    # Required to get the result, if needed for creating constraints
+    line.execute()
+    return line
+
+
+def getGeometry(line):
+    return modelAPI_ResultConstruction(line.firstResult())
+
+
+def getStartPoint(line):
+    return geomDataAPI_Point2D(line.attribute("StartPoint"))
+
+
+def getEndPoint(line):
+    return geomDataAPI_Point2D(line.attribute("EndPoint"))
+
+
+# Constraints
+# -----------
+
+def makeCoincident(p1, p2, sketch):
+    constraint = sketch.addFeature("SketchConstraintCoincidence")
+    constraint.refattr("ConstraintEntityA").setAttr(p1)
+    constraint.refattr("ConstraintEntityB").setAttr(p2)
+    return constraint
+
+
+def makeParallel(l1, l2, sketch):
+    constraint = sketch.addFeature("SketchConstraintParallel")
+    constraint.refattr("ConstraintEntityA").setObject(l1)
+    constraint.refattr("ConstraintEntityB").setObject(l2)
+    return constraint
+
+
+def makePerpendicular(l1, l2, sketch):
+    constraint = sketch.addFeature("SketchConstraintPerpendicular")
+    constraint.refattr("ConstraintEntityA").setObject(l1)
+    constraint.refattr("ConstraintEntityB").setObject(l2)
+    return constraint
+
+
+def makeConstantLength(line, length, sketch):
+    constraint = sketch.addFeature("SketchConstraintLength")
+    constraint.refattr("ConstraintEntityA").setObject(line)
+    constraint.real("ConstraintValue").setValue(length)
+    return constraint