1 # Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
2 # finalized by Renaud Nedelec and Sergey Pokhodenko
3 # Copyright (C) 2014-20xx CEA/DEN, EDF R&D
6 This interface allows to add a sketch
8 The created sketch object provides all the needed methods
9 for sketch modification and constraint edition.
17 >>> partset = model.moduleDocument()
18 >>> part = model.addPart(partset).document()
19 >>> plane = model.defaultPlane("XOY")
20 >>> sketch = model.addSketch(part, plane)
21 >>> line = sketch.addLine(0, 0, 0, 1)
24 from ModelAPI import modelAPI_ResultConstruction, featureToCompositeFeature
25 from GeomDataAPI import geomDataAPI_Point, geomDataAPI_Dir
26 from GeomAlgoAPI import GeomAlgoAPI_SketchBuilder, ShapeList
28 from model.sketcher.point import Point
29 from model.sketcher.line import Line
30 from model.sketcher.circle import Circle
31 from model.sketcher.arc import Arc
32 from model.sketcher.mirror import Mirror
33 from model.roots import Interface
34 from model.tools import Selection
37 def addSketch(document, plane):
38 """Add a sketch to a Part or PartSet.
41 document(ModelAPI_Document): part or partset document
42 plane(geom.Ax3): plane on wich the sketch is built
47 feature = featureToCompositeFeature(document.addFeature("Sketch"))
48 return Sketch(feature, plane)
50 class Sketch(Interface):
51 """Interface class for Sketch feature."""
52 def __init__(self, feature, *args):
53 """Initialize a 2D Sketch on the given plane.
55 The plane can be defined either by:
56 - a 3D axis system (geom.Ax3),
57 - an existing face identified by its topological name.
59 Interface.__init__(self, feature)
60 assert(self._feature.getKind() == "Sketch")
62 self._origin = geomDataAPI_Point(
63 self._feature.data().attribute("Origin")
65 self._dir_x = geomDataAPI_Dir(
66 self._feature.data().attribute("DirX")
68 self._norm = geomDataAPI_Dir(
69 self._feature.data().attribute("Norm")
71 self._external = self._feature.data().selection("External")
73 # If no arguments are given the attributes of the feature
77 if isinstance(plane, str):
78 self.__sketchOnFace(plane)
80 self.__sketchOnPlane(plane)
82 def __sketchOnPlane(self, plane):
83 """Create the sketch on a plane."""
84 origin = plane.location()
85 normal = plane.direction()
86 x_direction = plane.xDirection()
87 self._origin.setValue(origin.x(), origin.y(), origin.z())
88 self._norm.setValue(normal.x(), normal.y(), normal.z())
89 self._dir_x.setValue(x_direction.x(), x_direction.y(), x_direction.z())
91 def __sketchOnFace(self, name):
92 """Initialize the sketch on a face given by its name."""
93 self._external.selectSubShape("FACE", name)
95 #-------------------------------------------------------------
97 # Creation of Geometries
99 #-------------------------------------------------------------
101 def addPoint(self, *args):
102 """Add a point to the sketch."""
104 raise TypeError("No arguments given")
105 point_feature = self._feature.addFeature("SketchPoint")
106 return Point(point_feature, *args)
108 def addLine(self, *args):
109 """Add a line to the sketch.
111 .. function:: addLine(name)
112 Select an existing line. The line is added to the sketch with a rigid
113 constraint (it cannot be modified by the sketch)
116 name(str): name of an existing line
118 .. function:: addLine(start, end)
119 Create a line by points
122 start(point): start point of the line
123 end(point): end point of the line
125 .. function:: addLine(start_x, start_y, end_x, end_y)
126 Create a line by coordinates
129 start_x(double): start point x coordinate
132 raise TypeError("No arguments given")
133 line_feature = self._feature.addFeature("SketchLine")
134 line_interface = Line(line_feature, *args)
135 # if the line is created by name add a rigid constraint
136 # to the created line
137 if len(args) == 1 and isinstance(args[0], str):
138 constraint = self._feature.addFeature("SketchConstraintRigid")
139 constraint.refattr("ConstraintEntityA").setObject(
140 line_feature.firstResult()
142 return line_interface
144 def addCircle(self, *args):
145 """Add a circle to this Sketch."""
147 raise TypeError("No arguments given")
148 circle_feature = self._feature.addFeature("SketchCircle")
149 return Circle(circle_feature, *args)
151 def addArc(self, *args):
152 """Add an arc of circle to the sketch and return an arc object.
154 Two different syntaxes are allowed:
156 .. function:: addArc(center, start, end)
159 center (point): center of the arc
160 start (point): start point of the arc
161 end (point): end point of the arc
163 .. function:: addArc(center_x, center_y, start_x, start_y, end_x, end_y)
165 Same as above but with coordinates
170 TypeError: if no argument is provided
173 raise TypeError("No arguments given")
174 arc_feature = self._feature.addFeature("SketchArc")
175 return Arc(arc_feature, *args)
177 #-------------------------------------------------------------
179 # Creation of Geometrical and Dimensional Constraints
181 #-------------------------------------------------------------
183 def setCoincident(self, p1, p2):
184 """Set coincident the two given points and add the corresponding
185 constraint to this Sketch."""
186 # assert(p1 and p2) NOTE : if an argument is missing python
187 # will raise TypeError by itself.
188 # It seems better to check only that provided arguments are not
190 if p1 is None or p2 is None:
191 raise TypeError("NoneType argument given")
192 constraint = self._feature.addFeature("SketchConstraintCoincidence")
193 constraint.data().refattr("ConstraintEntityA").setAttr(p1)
194 constraint.data().refattr("ConstraintEntityB").setAttr(p2)
198 def setParallel(self, l1, l2):
199 """Set parallel the two given lines and add the corresponding
200 constraint to this Sketch."""
201 if l1 is None or l2 is None:
202 raise TypeError("NoneType argument given")
203 constraint = self._feature.addFeature("SketchConstraintParallel")
204 constraint.data().refattr("ConstraintEntityA").setObject(l1)
205 constraint.data().refattr("ConstraintEntityB").setObject(l2)
209 def setPerpendicular(self, l1, l2):
210 """Set perpendicular the two given lines and add the corresponding
211 constraint to this Sketch."""
212 if l1 is None or l2 is None:
213 raise TypeError("NoneType argument given")
214 constraint = self._feature.addFeature("SketchConstraintPerpendicular")
215 constraint.data().refattr("ConstraintEntityA").setObject(l1)
216 constraint.data().refattr("ConstraintEntityB").setObject(l2)
220 def setHorizontal(self, line):
221 """Set horizontal the given line and add the corresponding
222 constraint to this Sketch."""
224 raise TypeError("NoneType argument given")
225 constraint = self._feature.addFeature("SketchConstraintHorizontal")
226 constraint.data().refattr("ConstraintEntityA").setObject(line)
230 def setVertical(self, line):
231 """Set vertical the given line and add the corresponding
232 constraint to this Sketch."""
234 raise TypeError("NoneType argument given")
235 constraint = self._feature.addFeature("SketchConstraintVertical")
236 constraint.data().refattr("ConstraintEntityA").setObject(line)
240 def setDistance(self, point, line, length):
241 """Set the distance between the given point and line, and add
242 the corresponding constraint to this Sketch."""
243 if point is None or line is None:
244 raise TypeError("NoneType argument given")
245 constraint = self._feature.addFeature("SketchConstraintDistance")
246 if isinstance(line, basestring):
247 # Add the edge identified by the given topological name
249 line = self.addLine(line).result()
250 constraint.data().refattr("ConstraintEntityA").setAttr(point)
251 constraint.data().refattr("ConstraintEntityB").setObject(line)
252 constraint.data().real("ConstraintValue").setValue(length)
256 def setLength(self, line, length):
257 """Set the length of the given line and add the corresponding
258 constraint to this Sketch."""
260 raise TypeError("NoneType argument given")
261 constraint = self._feature.addFeature("SketchConstraintLength")
262 constraint.data().refattr("ConstraintEntityA").setObject(line)
263 constraint.data().real("ConstraintValue").setValue(length)
267 def setRadius(self, circle, radius):
268 """Set the radius of the given circle and add the corresponding
269 constraint to this Sketch."""
270 constraint = self._feature.addFeature("SketchConstraintRadius")
271 constraint.data().refattr("ConstraintEntityA").setObject(circle)
272 constraint.data().real("ConstraintValue").setValue(radius)
276 def setEqual(self, object_1, object_2):
277 """Set the radii of two circles or the length of two lines equal.
279 The corresponding constraint is added to the sketch"""
280 constraint = self._feature.addFeature("SketchConstraintEqual")
281 constraint.data().refattr("ConstraintEntityA").setObject(object_1)
282 constraint.data().refattr("ConstraintEntityB").setObject(object_2)
286 def setAngle(self, line_1, line_2, angle):
287 """Set the angle between the given 2 lines and add the corresponding
288 constraint to the sketch."""
289 constraint = self._feature.addFeature("SketchConstraintAngle")
290 constraint.data().refattr("ConstraintEntityA").setObject(line_1)
291 constraint.data().refattr("ConstraintEntityB").setObject(line_2)
292 constraint.data().real("ConstraintValue").setValue(angle)
296 def setTangent(self, object_1, object_2):
297 """Set a tangential continuity between two objects
298 at their coincidence point."""
299 if object_1 is None or object_2 is None:
300 raise TypeError("NoneType argument given")
301 constraint = self._feature.addFeature("SketchConstraintTangent")
302 constraint.data().refattr("ConstraintEntityA").setObject(object_1)
303 constraint.data().refattr("ConstraintEntityB").setObject(object_2)
307 def setFillet(self, line_1, line_2, radius):
308 """Set a fillet constraint between the 2 given lines with the given
310 constraint = self._feature.addFeature("SketchConstraintFillet")
311 constraint.data().refattr("ConstraintEntityA").setObject(line_1)
312 constraint.data().reflist("ConstraintEntityB").clear()
313 constraint.data().reflist("ConstraintEntityB").append(line_2)
317 def setRigid(self, object_):
318 """Set a rigid constraint on a given object."""
319 constraint = self._feature.addFeature("SketchConstraintRigid")
320 constraint.data().refattr("ConstraintEntityA").setObject(object_)
324 #-------------------------------------------------------------
326 # Transformation constraints
328 #-------------------------------------------------------------
330 def addMirror(self, mirror_line, sketch_objects):
331 """Add a mirror transformation of the given objects to the sketch.
333 This transformation is a constraint.
335 :return: interface to the constraint
336 :rtype: Mirror object
338 mirror_constraint = self._feature.addFeature("SketchConstraintMirror")
339 mirror_interface = Mirror(mirror_constraint, mirror_line, sketch_objects)
341 return mirror_interface
344 #-------------------------------------------------------------
346 # Edition of Dimensional Constraints
348 #-------------------------------------------------------------
350 def setValue(self, constraint, value):
351 """Modify the value of the given dimensional constraint."""
352 constraint.data().real("ConstraintValue").setValue(value)
354 #-------------------------------------------------------------
356 # Macro functions combining geometry creation and constraints
358 #-------------------------------------------------------------
360 def addPolyline(self, *coords):
361 """Add a poly-line to this Sketch.
363 The end of consecutive segments are defined as coincident.
368 line_1 = self.addLine(c0, c1)
369 polyline.append(line_1)
370 # Adding and connecting next lines
371 for c2 in coords[2:]:
372 line_2 = self.addLine(c1, c2)
373 self.setCoincident(line_1.endPointData(), line_2.startPointData())
374 polyline.append(line_2)
379 def addPolygon(self, *coords):
380 """Add a polygon to this Sketch.
382 The end of consecutive segments are defined as coincident.
384 pg = self.addPolyline(*coords)
385 # Closing the poly-line supposed being defined by at least 3 points
387 cn = coords[len(coords) - 1]
388 ln = self.addLine(cn, c0)
390 pg[len(coords) - 2].endPointData(), ln.startPointData()
393 ln.endPointData(), pg[0].startPointData()
398 #-------------------------------------------------------------
402 #-------------------------------------------------------------
404 def selectFace(self, *args):
405 """Select the geometrical entities of this Sketch on which
406 the result Face must be built.
408 When no entity is given, the face is based on all existing
409 geometry of this Sketch.
412 wire = modelAPI_ResultConstruction(
413 self._feature.firstResult()
416 wire = args[0].shape()
418 raise Exception("not yet implemented")
419 # TODO: simple version now, should be a list of selected faces
420 return [Selection(self.result(), self.buildShape(wire))]
422 def buildShape(self, wire):
423 """Build the result Shape of this Sketch according to the
424 selected geometrical entities."""
425 o = self._origin.pnt()
426 dx = self._dir_x.dir()
429 # The faces are kept otherwise they are destroyed at exit
431 GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, wire, faces)
432 # TODO: Deal with several faces
436 """Returns the result data of this Feature."""
437 return self._feature.firstResult()