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