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