From 0c8b32d61712fe0e783ea11770a631ab573087c2 Mon Sep 17 00:00:00 2001 From: sbh Date: Fri, 27 Feb 2015 18:20:15 +0300 Subject: [PATCH] Restore PythonFeaturesPLugin --- CMakeLists.txt | 1 + src/Config/plugins.xml | 1 + src/PythonFeaturesPlugin/CMakeLists.txt | 17 +++ src/PythonFeaturesPlugin/FeaturesAPI.py | 47 ++++++ .../PythonFeaturesPlugin.py | 20 +++ .../PythonFeaturesPlugin_Box.py | 130 +++++++++++++++++ src/PythonFeaturesPlugin/SketchResult.py | 26 ++++ src/PythonFeaturesPlugin/box_widget.xml | 11 ++ src/PythonFeaturesPlugin/examples.py | 51 +++++++ src/PythonFeaturesPlugin/extrusion.py | 15 ++ .../plugin-PythonFeatures.xml | 9 ++ src/PythonFeaturesPlugin/sketch.py | 134 ++++++++++++++++++ 12 files changed, 462 insertions(+) create mode 100644 src/PythonFeaturesPlugin/CMakeLists.txt create mode 100644 src/PythonFeaturesPlugin/FeaturesAPI.py create mode 100644 src/PythonFeaturesPlugin/PythonFeaturesPlugin.py create mode 100644 src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py create mode 100644 src/PythonFeaturesPlugin/SketchResult.py create mode 100644 src/PythonFeaturesPlugin/box_widget.xml create mode 100644 src/PythonFeaturesPlugin/examples.py create mode 100644 src/PythonFeaturesPlugin/extrusion.py create mode 100644 src/PythonFeaturesPlugin/plugin-PythonFeatures.xml create mode 100644 src/PythonFeaturesPlugin/sketch.py diff --git a/CMakeLists.txt b/CMakeLists.txt index ea51439df..726fbacaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/Config/plugins.xml b/src/Config/plugins.xml index e8d43ed02..bf95bc97c 100644 --- a/src/Config/plugins.xml +++ b/src/Config/plugins.xml @@ -6,6 +6,7 @@ + diff --git a/src/PythonFeaturesPlugin/CMakeLists.txt b/src/PythonFeaturesPlugin/CMakeLists.txt new file mode 100644 index 000000000..1e600b3df --- /dev/null +++ b/src/PythonFeaturesPlugin/CMakeLists.txt @@ -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 index 000000000..f47ba3f70 --- /dev/null +++ b/src/PythonFeaturesPlugin/FeaturesAPI.py @@ -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 index 000000000..ca671e144 --- /dev/null +++ b/src/PythonFeaturesPlugin/PythonFeaturesPlugin.py @@ -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 index 000000000..b150690de --- /dev/null +++ b/src/PythonFeaturesPlugin/PythonFeaturesPlugin_Box.py @@ -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 index 000000000..8d8b77a32 --- /dev/null +++ b/src/PythonFeaturesPlugin/SketchResult.py @@ -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 index 000000000..7c1a2c553 --- /dev/null +++ b/src/PythonFeaturesPlugin/box_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/PythonFeaturesPlugin/examples.py b/src/PythonFeaturesPlugin/examples.py new file mode 100644 index 000000000..9f68e9234 --- /dev/null +++ b/src/PythonFeaturesPlugin/examples.py @@ -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 index 000000000..9008479a0 --- /dev/null +++ b/src/PythonFeaturesPlugin/extrusion.py @@ -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 index 000000000..2f7b97bc5 --- /dev/null +++ b/src/PythonFeaturesPlugin/plugin-PythonFeatures.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/PythonFeaturesPlugin/sketch.py b/src/PythonFeaturesPlugin/sketch.py new file mode 100644 index 000000000..ca13a707d --- /dev/null +++ b/src/PythonFeaturesPlugin/sketch.py @@ -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 -- 2.39.2