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")
56 assert(self._external)
58 # If no arguments are given the attributes of the feature
62 if isinstance(plane, str):
63 self.__sketchOnFace(plane)
65 self.__sketchOnPlane(plane)
67 def __sketchOnPlane(self, plane):
68 """Create the sketch on a plane."""
69 origin = plane.location()
70 normal = plane.direction()
71 x_direction = plane.xDirection()
72 self._origin.setValue(origin.x(), origin.y(), origin.z())
73 self._norm.setValue(normal.x(), normal.y(), normal.z())
74 self._dir_x.setValue(x_direction.x(), x_direction.y(), x_direction.z())
76 def __sketchOnFace(self, name):
77 """Initialize the sketch on a face given by its name."""
78 self._external.selectSubShape("FACE", name)
80 #-------------------------------------------------------------
82 # Creation of Geometries
84 #-------------------------------------------------------------
86 def addPoint(self, *args):
87 """Add a point to this Sketch."""
88 point_feature = self._feature.addFeature("SketchPoint")
89 return Point(point_feature, *args)
91 def addLine(self, *args):
92 """Add a line to this Sketch."""
93 line_feature = self._feature.addFeature("SketchLine")
94 line_interface = Line(line_feature, *args)
95 # if the line is created by name add a rigid constraint
97 if len(args) == 1 and isinstance(args[0], str):
98 constraint = self._feature.addFeature("SketchConstraintRigid")
99 constraint.refattr("ConstraintEntityA").setObject(
100 line_feature.firstResult()
102 return line_interface
104 def addCircle(self, *args):
105 """Add a circle to this Sketch."""
106 circle_feature = self._feature.addFeature("SketchCircle")
107 return Circle(circle_feature, *args)
109 def addArc(self, *args):
110 """Add an arc to this Sketch."""
111 arc_feature = self._feature.addFeature("SketchArc")
112 return Arc(arc_feature, *args)
114 #-------------------------------------------------------------
116 # Creation of Geometrical and Dimensional Constraints
118 #-------------------------------------------------------------
120 def setCoincident(self, p1, p2):
121 """Set coincident the two given points and add the corresponding
122 constraint to this Sketch."""
124 constraint = self._feature.addFeature("SketchConstraintCoincidence")
125 constraint.data().refattr("ConstraintEntityA").setAttr(p1)
126 constraint.data().refattr("ConstraintEntityB").setAttr(p2)
130 def setParallel(self, l1, l2):
131 """Set parallel the two given lines and add the corresponding
132 constraint to this Sketch."""
134 constraint = self._feature.addFeature("SketchConstraintParallel")
135 constraint.data().refattr("ConstraintEntityA").setObject(l1)
136 constraint.data().refattr("ConstraintEntityB").setObject(l2)
140 def setPerpendicular(self, l1, l2):
141 """Set perpendicular the two given lines and add the corresponding
142 constraint to this Sketch."""
144 constraint = self._feature.addFeature("SketchConstraintPerpendicular")
145 constraint.data().refattr("ConstraintEntityA").setObject(l1)
146 constraint.data().refattr("ConstraintEntityB").setObject(l2)
150 def setHorizontal(self, line):
151 """Set horizontal the given line and add the corresponding
152 constraint to this Sketch."""
153 constraint = self._feature.addFeature("SketchConstraintHorizontal")
154 constraint.data().refattr("ConstraintEntityA").setObject(line)
158 def setVertical(self, line):
159 """Set vertical the given line and add the corresponding
160 constraint to this Sketch."""
161 constraint = self._feature.addFeature("SketchConstraintVertical")
162 constraint.data().refattr("ConstraintEntityA").setObject(line)
166 def setDistance(self, point, line, length):
167 """Set the distance between the given point and line, and add
168 the corresponding constraint to this Sketch."""
169 assert(point and line)
170 constraint = self._feature.addFeature("SketchConstraintDistance")
171 if isinstance(line, basestring):
172 # Add the edge identified by the given topological name
174 line = self.addLine(line).result()
176 constraint.data().refattr("ConstraintEntityA").setAttr(point)
177 constraint.data().refattr("ConstraintEntityB").setObject(line)
178 constraint.data().real("ConstraintValue").setValue(length)
182 def setLength(self, line, length):
183 """Set the length of the given line and add the corresponding
184 constraint to this Sketch."""
186 constraint = self._feature.addFeature("SketchConstraintLength")
187 constraint.data().refattr("ConstraintEntityA").setObject(line)
188 constraint.data().real("ConstraintValue").setValue(length)
192 def setRadius(self, circle, radius):
193 """Set the radius of the given circle and add the corresponding
194 constraint to this Sketch."""
195 constraint = self._feature.addFeature("SketchConstraintRadius")
196 constraint.data().refattr("ConstraintEntityA").setObject(circle)
197 constraint.data().real("ConstraintValue").setValue(radius)
201 def setEqual(self, object_1, object_2):
202 """Set the radii of two circles or the length of two lines equal.
204 The corresponding constraint is added to the sketch"""
205 constraint = self._feature.addFeature("SketchConstraintEqual")
206 constraint.data().refattr("ConstraintEntityA").setObject(object_1)
207 constraint.data().refattr("ConstraintEntityB").setObject(object_2)
211 def setAngle(self, line_1, line_2, angle):
212 """Set the angle between the given 2 lines and add the corresponding
213 constraint to the sketch."""
214 constraint = self._feature.addFeature("SketchConstraintAngle")
215 constraint.data().refattr("ConstraintEntityA").setObject(line_1)
216 constraint.data().refattr("ConstraintEntityB").setObject(line_2)
217 constraint.data().real("ConstraintValue").setValue(angle)
221 def setTangent(self, object_1, object_2):
222 """Set a tangential continuity between two objects
223 at their coincidence point."""
224 constraint = self._feature.addFeature("SketchConstraintTangent")
225 constraint.data().refattr("ConstraintEntityA").setObject(object_1)
226 constraint.data().refattr("ConstraintEntityB").setObject(object_2)
230 def setFillet(self, line_1, line_2, radius):
231 """Set a fillet constraint between the 3 given lines with the given
233 constraint = self._feature.addFeature("SketchConstraintFillet")
234 constraint.data().refattr("ConstraintEntityA").setObject(line_1)
235 constraint.data().refattr("ConstraintEntityB").setObject(line_2)
236 constraint.data().real("ConstraintValue").setValue(radius)
240 #-------------------------------------------------------------
242 # Edition of Dimensional Constraints
244 #-------------------------------------------------------------
246 def setValue(self, constraint, value):
247 """Modify the value of the given dimensional constraint."""
248 constraint.data().real("ConstraintValue").setValue(value)
250 #-------------------------------------------------------------
252 # Macro functions combining geometry creation and constraints
254 #-------------------------------------------------------------
256 def addPolyline(self, *coords):
257 """Add a poly-line to this Sketch.
259 The end of consecutive segments are defined as coincident.
264 line_1 = self.addLine(c0, c1)
265 polyline.append(line_1)
266 # Adding and connecting next lines
267 for c2 in coords[2:]:
268 line_2 = self.addLine(c1, c2)
269 self.setCoincident(line_1.endPointData(), line_2.startPointData())
270 polyline.append(line_2)
275 def addPolygon(self, *coords):
276 """Add a polygon to this Sketch.
278 The end of consecutive segments are defined as coincident.
280 pg = self.addPolyline(*coords)
281 # Closing the poly-line supposed being defined by at least 3 points
283 cn = coords[len(coords) - 1]
284 ln = self.addLine(cn, c0)
286 pg[len(coords) - 2].endPointData(), ln.startPointData()
289 ln.endPointData(), pg[0].startPointData()
294 #-------------------------------------------------------------
298 #-------------------------------------------------------------
300 def selectFace(self, *args):
301 """Select the geometrical entities of this Sketch on which
302 the result Face must be built.
304 When no entity is given, the face is based on all existing
305 geometry of this Sketch.
308 wire = modelAPI_ResultConstruction(
309 self._feature.firstResult()
312 wire = args[0].shape()
314 raise Exception("not yet implemented")
315 # TODO: simple version now, should be a list of selected faces
316 return [Selection(self.result(), self.buildShape(wire))]
318 def buildShape(self, wire):
319 """Build the result Shape of this Sketch according to the
320 selected geometrical entities."""
321 o = self._origin.pnt()
322 dx = self._dir_x.dir()
325 # The faces are kept otherwise they are destroyed at exit
327 GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, wire, faces)
328 # TODO: Deal with several faces
332 """Returns the result data of this Feature."""
333 return self._feature.firstResult()