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
7 from ModelAPI import modelAPI_ResultConstruction, featureToCompositeFeature
8 from GeomDataAPI import geomDataAPI_Point, geomDataAPI_Dir
9 from GeomAlgoAPI import GeomAlgoAPI_SketchBuilder, ShapeList
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
19 def addSketch(doc, plane):
20 """Add a Sketch feature to the Part or PartSet and return an interface
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
27 feature = featureToCompositeFeature(doc.addFeature("Sketch"))
28 return Sketch(feature, plane)
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.
35 The plane can be defined either by:
36 - a 3D axis system (geom.Ax3),
37 - an existing face identified by its topological name.
39 Interface.__init__(self, feature)
40 assert(self._feature.getKind() == "Sketch")
42 self._origin = geomDataAPI_Point(
43 self._feature.data().attribute("Origin")
45 self._dir_x = geomDataAPI_Dir(
46 self._feature.data().attribute("DirX")
48 self._norm = geomDataAPI_Dir(
49 self._feature.data().attribute("Norm")
51 self._external = self._feature.data().selection("External")
53 # If no arguments are given the attributes of the feature
57 if isinstance(plane, str):
58 self.__sketchOnFace(plane)
60 self.__sketchOnPlane(plane)
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())
71 def __sketchOnFace(self, name):
72 """Initialize the sketch on a face given by its name."""
73 self._external.selectSubShape("FACE", name)
75 #-------------------------------------------------------------
77 # Creation of Geometries
79 #-------------------------------------------------------------
81 def addPoint(self, *args):
82 """Add a point to this Sketch."""
84 raise TypeError("No arguments given")
85 point_feature = self._feature.addFeature("SketchPoint")
86 return Point(point_feature, *args)
88 def addLine(self, *args):
89 """Add a line to this Sketch."""
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
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()
101 return line_interface
103 def addCircle(self, *args):
104 """Add a circle to this Sketch."""
106 raise TypeError("No arguments given")
107 circle_feature = self._feature.addFeature("SketchCircle")
108 return Circle(circle_feature, *args)
110 def addArc(self, *args):
111 """Add an arc to this Sketch."""
113 raise TypeError("No arguments given")
114 arc_feature = self._feature.addFeature("SketchArc")
115 return Arc(arc_feature, *args)
117 #-------------------------------------------------------------
119 # Creation of Geometrical and Dimensional Constraints
121 #-------------------------------------------------------------
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
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)
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)
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)
160 def setHorizontal(self, line):
161 """Set horizontal the given line and add the corresponding
162 constraint to this Sketch."""
164 raise TypeError("NoneType argument given")
165 constraint = self._feature.addFeature("SketchConstraintHorizontal")
166 constraint.data().refattr("ConstraintEntityA").setObject(line)
170 def setVertical(self, line):
171 """Set vertical the given line and add the corresponding
172 constraint to this Sketch."""
174 raise TypeError("NoneType argument given")
175 constraint = self._feature.addFeature("SketchConstraintVertical")
176 constraint.data().refattr("ConstraintEntityA").setObject(line)
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
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)
196 def setLength(self, line, length):
197 """Set the length of the given line and add the corresponding
198 constraint to this Sketch."""
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)
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)
216 def setEqual(self, object_1, object_2):
217 """Set the radii of two circles or the length of two lines equal.
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)
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)
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)
245 def setFillet(self, line_1, line_2, radius):
246 """Set a fillet constraint between the 2 given lines with the given
248 constraint = self._feature.addFeature("SketchConstraintFillet")
249 constraint.data().refattr("ConstraintEntityA").setObject(line_1)
250 constraint.data().reflist("ConstraintEntityB").clear
251 constraint.data().reflist("ConstraintEntityB").append(line_1)
256 #-------------------------------------------------------------
258 # Edition of Dimensional Constraints
260 #-------------------------------------------------------------
262 def setValue(self, constraint, value):
263 """Modify the value of the given dimensional constraint."""
264 constraint.data().real("ConstraintValue").setValue(value)
266 #-------------------------------------------------------------
268 # Macro functions combining geometry creation and constraints
270 #-------------------------------------------------------------
272 def addPolyline(self, *coords):
273 """Add a poly-line to this Sketch.
275 The end of consecutive segments are defined as coincident.
280 line_1 = self.addLine(c0, c1)
281 polyline.append(line_1)
282 # Adding and connecting next lines
283 for c2 in coords[2:]:
284 line_2 = self.addLine(c1, c2)
285 self.setCoincident(line_1.endPointData(), line_2.startPointData())
286 polyline.append(line_2)
291 def addPolygon(self, *coords):
292 """Add a polygon to this Sketch.
294 The end of consecutive segments are defined as coincident.
296 pg = self.addPolyline(*coords)
297 # Closing the poly-line supposed being defined by at least 3 points
299 cn = coords[len(coords) - 1]
300 ln = self.addLine(cn, c0)
302 pg[len(coords) - 2].endPointData(), ln.startPointData()
305 ln.endPointData(), pg[0].startPointData()
310 #-------------------------------------------------------------
314 #-------------------------------------------------------------
316 def selectFace(self, *args):
317 """Select the geometrical entities of this Sketch on which
318 the result Face must be built.
320 When no entity is given, the face is based on all existing
321 geometry of this Sketch.
324 wire = modelAPI_ResultConstruction(
325 self._feature.firstResult()
328 wire = args[0].shape()
330 raise Exception("not yet implemented")
331 # TODO: simple version now, should be a list of selected faces
332 return [Selection(self.result(), self.buildShape(wire))]
334 def buildShape(self, wire):
335 """Build the result Shape of this Sketch according to the
336 selected geometrical entities."""
337 o = self._origin.pnt()
338 dx = self._dir_x.dir()
341 # The faces are kept otherwise they are destroyed at exit
343 GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, wire, faces)
344 # TODO: Deal with several faces
348 """Returns the result data of this Feature."""
349 return self._feature.firstResult()