Salome HOME
Merge branch 'python_parametric_api' of https://git.salome-platform.org/git/modules...
[modules/shaper.git] / src / PythonAPI / model / sketcher / sketch.py
1 """Sketch Feature Interface
2 Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
3 Copyright (C) 2014-20xx CEA/DEN, EDF R&D
4 """
5
6 from ModelAPI import modelAPI_ResultConstruction, featureToCompositeFeature
7 from GeomDataAPI import geomDataAPI_Point, geomDataAPI_Dir
8 from GeomAlgoAPI import GeomAlgoAPI_SketchBuilder, ShapeList
9 from model.sketcher.point import Point
10 from model.sketcher.line import Line
11 from model.sketcher.circle import Circle
12 from model.sketcher.arc import Arc
13
14 def addSketch(doc, plane):
15     """Add a Sketch feature to the Part or PartSet and return an interface
16     on it.
17     
18     A Sketch object is instanciated with a feature as input parameter
19     it provides an interface for manipulation of the feature data.
20     :return: interface on the feature
21     :rtype: Sketch"""
22     feature = featureToCompositeFeature(doc.addFeature("Sketch"))
23     return Sketch(feature, plane)
24
25 class Sketch():
26     """Interface on a Sketch feature."""
27     def __init__(self, feature, plane):
28         """Initialize a 2D Sketch on the given plane.
29         
30         The plane can be defined either by:
31         - a 3D axis system (geom.Ax3),
32         - an existing face identified by its topological name.
33         """
34         self._feature = feature
35         # Entities used for building the result shape
36         self._selection = None
37         #   self.resultype ="Face" # Type of Sketch result
38         if isinstance(plane, str):
39             self.__sketchOnFace(plane)
40         else:
41             self.__sketchOnPlane(plane)
42
43     def __sketchOnPlane(self, plane):
44         """Create the sketch on a plane."""
45         origin = plane.location()
46         normal = plane.direction()
47         x_direction = plane.xDirection()
48         geomDataAPI_Point( 
49             self._feature.data().attribute("Origin") 
50             ).setValue(origin.x(), origin.y(), origin.z())
51         geomDataAPI_Dir( 
52             self._feature.data().attribute("DirX") 
53             ).setValue(x_direction.x(), x_direction.y(), x_direction.z())
54         geomDataAPI_Dir( 
55             self._feature.data().attribute("Norm") 
56             ).setValue(normal.x(), normal.y(), normal.z() )
57
58     def __sketchOnFace(self, name):
59         """Initialize the sketch on a face given by its name."""
60         self._feature.data().selection("External").selectSubShape("FACE", name)
61
62     #-------------------------------------------------------------
63     #
64     # Creation of Geometries
65     #
66     #-------------------------------------------------------------
67
68     def addPoint(self, *args):
69         """Add a point to this Sketch."""
70         point_feature = self._feature.addFeature("SketchPoint")
71         return Point(point_feature, *args)
72
73     def addLine(self, *args):
74         """Add a line to this Sketch."""
75         line_feature = self._feature.addFeature("SketchLine")
76         line_interface = Line(line_feature, *args)
77         # if the line is created by name add a rigid constraint
78         # to the created line
79         if len(args) == 1 and isinstance(args[0], str):
80             constraint = sketch.addFeature("SketchConstraintRigid")
81             constraint.refattr("ConstraintEntityA").setObject(
82                 line_feature.firstResult()
83                 )
84         return line_interface
85     
86     def addCircle(self, *args):
87         """Add a circle to this Sketch."""
88         circle_feature = self._feature.addFeature("SketchCircle")
89         return Circle(circle_feature, *args)
90     
91     def addArc(self, *args):
92         """Add an arc to this Sketch."""
93         arc_feature = self._feature.addFeature("SketchArc")
94         return Arc(arc_feature, *args)
95   
96     #-------------------------------------------------------------
97     #
98     # Creation of Geometrical and Dimensional Constraints
99     #
100     #-------------------------------------------------------------
101
102     def setCoincident(self, p1, p2):
103         """Set coincident the two given points and add the corresponding 
104         constraint to this Sketch."""
105         constraint = self._feature.addFeature("SketchConstraintCoincidence")
106         constraint.data().refattr("ConstraintEntityA").setAttr(p1)
107         constraint.data().refattr("ConstraintEntityB").setAttr(p2)
108         return constraint
109
110     def setParallel(self, l1, l2):
111         """Set parallel the two given lines and add the corresponding 
112         constraint to this Sketch."""
113         constraint = self._feature.addFeature("SketchConstraintParallel")
114         constraint.data().refattr("ConstraintEntityA").setObject(l1)
115         constraint.data().refattr("ConstraintEntityB").setObject(l2)
116         return constraint
117
118     def setPerpendicular(self, l1, l2):
119         """Set perpendicular the two given lines and add the corresponding 
120         constraint to this Sketch."""
121         constraint = self._feature.addFeature("SketchConstraintPerpendicular")
122         constraint.data().refattr("ConstraintEntityA").setObject(l1)
123         constraint.data().refattr("ConstraintEntityB").setObject(l2)
124         return constraint
125     
126     def setHorizontal(self, line):
127         """Set horizontal the given line and add the corresponding 
128         constraint to this Sketch."""
129         constraint = self._feature.addFeature("SketchConstraintHorizontal")
130         constraint.data().refattr("ConstraintEntityA").setObject(line)
131         return constraint
132     
133     def setVertical(self, line):
134         """Set vertical the given line and add the corresponding 
135         constraint to this Sketch."""
136         constraint = self._feature.addFeature("SketchConstraintVertical")
137         constraint.data().refattr("ConstraintEntityA").setObject(line)
138         return constraint
139
140     def setDistance(self, point, line, length):
141         """Set the distance between the given point and line, and add
142         the corresponding constraint to this Sketch."""
143         constraint = self._feature.addFeature("SketchConstraintDistance")
144         if isinstance(line, str):
145             # Add the edge identified by the given topological name 
146             # to this Sketch
147             line = self.addLine(line).result()   
148         constraint.data().refattr("ConstraintEntityA").setAttr(point)
149         constraint.data().refattr("ConstraintEntityB").setObject(line)
150         constraint.data().real("ConstraintValue").setValue(length)
151         self._feature.execute()
152         return constraint
153
154     def setLength(self, line, length):
155         """Set the length of the given line and add the corresponding 
156         constraint to this Sketch."""
157         constraint = self._feature.addFeature("SketchConstraintLength")
158         constraint.data().refattr("ConstraintEntityA").setObject(line)
159         constraint.data().real("ConstraintValue").setValue(length)
160         self._feature.execute()
161         return constraint
162     
163     def setRadius(self, circle, radius):
164         """Set the radius of the given circle and add the corresponding 
165         constraint to this Sketch."""
166         constraint = self._feature.addFeature("SketchConstraintRadius")
167         constraint.data().refattr("ConstraintEntityA").setObject(circle)
168         constraint.data().real("ConstraintValue").setValue(radius)
169         return constraint
170     
171     def setEqual(self, object_1, object_2):
172         """Set the radii of two circles or the length of two lines equal.
173         
174         The corresponding constraint is added to the sketch"""
175         constraint = self._feature.addFeature("SketchConstraintEqual")
176         constraint.data().refattr("ConstraintEntityA").setObject(object_1)
177         constraint.data().refattr("ConstraintEntityB").setObject(object_2)
178         self._feature.execute()
179         return constraint
180     
181     def setAngle(self, line_1, line_2, angle):
182         """Set the angle between the given 2 lines and add the corresponding 
183         constraint to the sketch."""
184         constraint = self._feature.addFeature("SketchConstraintAngle")
185         constraint.data().refattr("ConstraintEntityA").setObject(line_1)
186         constraint.data().refattr("ConstraintEntityB").setObject(line_2)
187         constraint.data().real("ConstraintValue").setValue(angle)
188         self._feature.execute()
189         return constraint
190     
191     def setTangent(self, object_1, object_2):
192         """Set a tangential continuity between two objects 
193         at their coincidence point."""
194         constraint = self._feature.addFeature("SketchConstraintTangent")
195         constraint.data().refattr("ConstraintEntityA").setObject(object_1)
196         constraint.data().refattr("ConstraintEntityB").setObject(object_2)
197         self._feature.execute()
198         return constraint
199     
200     def setFillet(self, line_1, line_2, radius):
201         """Set a fillet constraint between the 3 given lines with the given 
202         filleting radius."""
203         constraint = self._feature.addFeature("SketchConstraintFillet")
204         constraint.data().refattr("ConstraintEntityA").setObject(line_1)
205         constraint.data().refattr("ConstraintEntityB").setObject(line_2)
206         constraint.data().real("ConstraintValue").setValue(radius)
207         self._feature.execute()
208         return constraint
209
210     #-------------------------------------------------------------
211     #
212     # Edition of Dimensional Constraints
213     #
214     #-------------------------------------------------------------
215
216     def setValue(self, constraint, value):
217         """Modify the value of the given dimensional constraint."""
218         constraint.data().real("ConstraintValue").setValue(value)
219      
220     #-------------------------------------------------------------
221     #
222     # Macro functions combining geometry creation and constraints
223     #
224     #-------------------------------------------------------------
225      
226     def addPolyline(self, *coords):
227         """Add a poly-line to this Sketch.
228         
229         The end of consecutive segments are defined as coincident.
230         """
231         c0 = coords[0]
232         c1 = coords[1]
233         polyline = []
234         line_1 = self.addLine(c0, c1)
235         polyline.append(line_1)
236         # Adding and connecting next lines
237         for c2 in coords[2:]:
238             line_2 = self.addLine(c1, c2)
239             self.setCoincident(line_1.endPointData(), line_2.startPointData())
240             polyline.append(line_2)
241             c1 = c2
242             line_1 = line_2
243         return polyline
244
245     def addPolygon(self, *coords):
246         """Add a polygon to this Sketch.
247         
248         The end of consecutive segments are defined as coincident.
249         """
250         pg = self.addPolyline(*coords)
251         # Closing the poly-line supposed being defined by at least 3 points
252         c0 = coords[0]
253         cn = coords[len(coords) - 1]
254         ln = self.addLine(cn, c0)
255         self.setCoincident(
256             pg[len(coords) - 2].endPointData(), ln.startPointData()
257             )
258         self.setCoincident(
259             ln.endPointData(), pg[0].startPointData()
260             )
261         pg.append(ln)
262         return pg
263
264     #-------------------------------------------------------------
265     #
266     # Getters
267     #
268     #-------------------------------------------------------------
269
270     def selectFace(self, *args):
271         """Select the geometrical entities of this Sketch on which 
272         the result Face must be built.
273         
274         When no entity is given, the face is based on all existing 
275         geometry of this Sketch.
276         """
277         if len(args) == 0:
278             self._selection = modelAPI_ResultConstruction( 
279                 self._feature.firstResult()).shape()
280         elif len(args) == 1:
281             self._selection = args[0].shape()
282         else:
283             raise Exception("not yet implemented")
284         return self
285
286     def buildShape(self):
287         """Build the result Shape of this Sketch according to the 
288         selected geometrical entities."""
289         o  = geomDataAPI_Point( self._feature.data().attribute("Origin") ).pnt()
290         dx = geomDataAPI_Dir( self._feature.data().attribute("DirX") ).dir()
291         n  = geomDataAPI_Dir( self._feature.data().attribute("Norm") ).dir()
292
293         # The faces are kept otherwise they are destroyed at exit
294         faces = ShapeList()
295         GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, self._selection, faces)
296         #TODO: Deal with several faces 
297         return faces[0]
298
299     def result(self):
300         """Returns the result data of this Feature."""
301         return self._feature.firstResult()