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