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)
<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"/>
--- /dev/null
+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)
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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()
+"""
--- /dev/null
+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]
--- /dev/null
+<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>
--- /dev/null
+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)
--- /dev/null
+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())
--- /dev/null
+<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>
--- /dev/null
+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