Salome HOME
Added support of python high level API addons proposed by DBC as test of this approach.
[modules/shaper.git] / src / PythonAPI / modeler / sketcher.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 *
7 from GeomDataAPI import *
8 from GeomAlgoAPI import *
9
10
11 class Sketch():
12
13   def __init__(self, doc, plane):
14     """Initializes a 2D Sketch on the given plane and adds the Sketch to the given Part or Partset.
15         The plane can be defined either by:
16         - a 3D axis system (geom.Ax3),
17         - an existing face identified by its topological name.
18     """
19     self.my = featureToCompositeFeature( doc.addFeature("Sketch") )
20     self.selection = None         # Entities used for building the result shape
21 #   self.resultype ="Face"        # Type of Sketch result
22     if isinstance(plane, str):
23       self.__sketchOnFace(doc, plane)
24     else:
25       self.__sketchOnPlane(doc, plane)
26
27   def __sketchOnPlane (self, doc, plane):
28     o  = plane.location()
29     d  = plane.direction()
30     dx = plane.xDirection()
31     geomDataAPI_Point( self.my.data().attribute("Origin") ).setValue( o.x(), o.y(), o.z() )
32     geomDataAPI_Dir( self.my.data().attribute("DirX") ).setValue( dx.x(), dx.y(), dx.z() )
33     geomDataAPI_Dir( self.my.data().attribute("Norm") ).setValue( d.x(),  d.y(),  d.z()  )
34
35   def __sketchOnFace (self, doc, plane):
36     self.my.data().selection("External").selectSubShape("FACE", plane)
37
38
39 # Creation of Geometries
40
41   def addPoint (self, *args):
42     """Adds a point to this Sketch."""
43     return Point(self.my, *args)
44
45   def addLine (self, *args):
46     """Adds a line to this Sketch."""
47     return Line(self.my, *args)
48
49   def addPolyline (self, *coords):
50     """Adds a poly-line to this Sketch.
51     The end of consecutive segments are defined as coincident.
52     """
53     c0 = coords[0]
54     c1 = coords[1]
55     pl = []
56     l1 = self.addLine(c0, c1)
57     pl.append(l1)
58     # Adding and connecting next lines
59     for c2 in coords[2:]:
60       l2 = self.addLine(c1, c2)
61       self.setCoincident( l1.endPointData(), l2.startPointData() )
62       pl.append(l2)
63       c1 = c2
64       l1 = l2
65     return pl
66
67   def addPolygon (self, *coords):
68     """Adds a polygon to this Sketch.
69     The end of consecutive segments are defined as coincident.
70     """
71     pg = self.addPolyline(*coords)
72         # Closing the poly-line supposed being defined by at least 3 points
73     c0 = coords[0]
74     cn = coords[len(coords)-1]
75     ln = self.addLine(cn, c0)
76     self.setCoincident( pg[len(coords)-2].endPointData(), ln.startPointData() )
77     self.setCoincident( ln.endPointData(), pg[0].startPointData() )
78     pg.append(ln)
79     return pg
80
81   def addCircle (self, *args):
82     """Adds a circle to this Sketch."""
83     return Circle(self.my, *args)
84
85
86 # Creation of Geometrical and Dimensional Constraints
87
88   def setCoincident (self, p1, p2):
89     """Sets coincident the two given points and adds the corresponding constraint to this Sketch."""
90     constraint = self.my.addFeature("SketchConstraintCoincidence")
91     constraint.data().refattr("ConstraintEntityA").setAttr(p1)
92     constraint.data().refattr("ConstraintEntityB").setAttr(p2)
93     return constraint
94
95   def setParallel (self, l1, l2):
96     """Sets parallel the two given lines and adds the corresponding constraint to this Sketch."""
97     constraint = self.my.addFeature("SketchConstraintParallel")
98     constraint.data().refattr("ConstraintEntityA").setObject(l1)
99     constraint.data().refattr("ConstraintEntityB").setObject(l2)
100     return constraint
101
102   def setPerpendicular (self, l1, l2):
103     """Sets perpendicular the two given lines and adds the corresponding constraint to this Sketch."""
104     constraint = self.my.addFeature("SketchConstraintPerpendicular")
105     constraint.data().refattr("ConstraintEntityA").setObject(l1)
106     constraint.data().refattr("ConstraintEntityB").setObject(l2)
107     return constraint
108
109   def setDistance (self, point, line, length):
110     """Sets the distance between the given point and line, and adds the corresponding constraint to this Sketch."""
111     constraint = self.my.addFeature("SketchConstraintDistance")
112     if isinstance(line, str):
113       line = self.addLine(line).result()   # Adds the edge identified by the given topological name to this Sketch
114     constraint.data().refattr("ConstraintEntityA").setAttr(point)
115     constraint.data().refattr("ConstraintEntityB").setObject(line)
116     constraint.data().real("ConstraintValue").setValue(length)
117     self.my.execute()
118     return constraint
119
120   def setLength (self, line, length):
121     """Sets the length of the given line and adds the corresponding constraint to this Sketch."""
122     constraint = self.my.addFeature("SketchConstraintLength")
123     constraint.data().refattr("ConstraintEntityA").setObject(line)
124     constraint.data().real("ConstraintValue").setValue(length)
125     return constraint
126
127   def setRadius (self, circle, radius):
128     """Sets the radius of the given circle and adds the corresponding constraint to this Sketch."""
129     constraint = self.my.addFeature("SketchConstraintRadius")
130     constraint.data().refattr("ConstraintEntityA").setObject(circle)
131     constraint.data().real("ConstraintValue").setValue(radius)
132     return constraint
133
134
135 # Edition of Dimensional Constraints
136
137   def setValue (self, constraint, value):
138     """Modifies the value of the given dimensional constraint."""
139     constraint.data().real("ConstraintValue").setValue(value)
140
141
142 # Getters
143
144   def selectFace (self, *args):
145     """Selects the geometrical entities of this Sketch on which the result Face must be built.
146         When no entity is given, the face is based on all existing geometry of this Sketch.
147         """
148     #self.resultype ="Face"
149     if   len(args) == 0:
150       self.selection = modelAPI_ResultConstruction( self.my.firstResult() ).shape()
151     elif len(args) == 1:
152       self.selection = args[0].shape()
153     else:
154       raise Exception("not yet implemented")
155     return self
156
157   def buildShape (self):
158     """Builds the result Shape of this Sketch according to the selected geometrical entities."""
159     o  = geomDataAPI_Point( self.my.data().attribute("Origin") ).pnt()
160     dx = geomDataAPI_Dir( self.my.data().attribute("DirX") ).dir()
161     n  = geomDataAPI_Dir( self.my.data().attribute("Norm") ).dir()
162
163     self.faces = ShapeList()      # The faces are kept otherwise they are destroyed at exit
164     GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, self.selection, self.faces)
165 #TODO: Deal with several faces 
166     return self.faces[0]
167
168   def result (self):
169     """Returns the result data of this Feature."""
170     return self.my.firstResult()
171
172
173 # Class definitions of Sketch features
174
175 class Point():
176
177   def __init__(self, sketch, x, y):
178     self.my = sketch.addFeature("SketchPoint")
179     geomDataAPI_Point2D( self.my.data().attribute("PointCoordindates") ).setValue(x, y)
180     self.my.execute()
181
182   def pointData (self):
183     return geomDataAPI_Point2D( self.my.data().attribute("PointCoordindates") )
184
185   def result (self):
186     return self.my.firstResult()
187
188
189 class Line():
190
191   def __init__(self, sketch, *args):
192     self.my = sketch.addFeature("SketchLine")
193     if   len(args) == 4:
194       self.__createByCoordinates(*args)
195     elif len(args) == 2:
196       self.__createByPoints(*args)
197     elif len(args) == 1:
198           self.__createByName(sketch, *args)
199     else:
200       raise Exception("cannot create the Line")
201
202   def __createByCoordinates(self, x1, y1, x2, y2):
203     geomDataAPI_Point2D( self.my.data().attribute("StartPoint") ).setValue(x1, y1)
204     geomDataAPI_Point2D( self.my.data().attribute("EndPoint") ).setValue(x2, y2)
205     self.my.execute()
206
207   def __createByPoints(self, p1, p2):
208     geomDataAPI_Point2D( self.my.data().attribute("StartPoint") ).setValue(p1.x(), p1.y())
209     geomDataAPI_Point2D( self.my.data().attribute("EndPoint") ).setValue(p2.x(), p2.y())
210     self.my.execute()
211
212   def __createByName(self, sketch, name):
213     self.my.data().selection("External").selectSubShape("EDGE", name)
214     self.my.execute()
215     rigid = sketch.addFeature("SketchConstraintRigid")
216     rigid.refattr("ConstraintEntityA").setObject( self.my.firstResult() )
217
218   def startPointData (self):
219     return geomDataAPI_Point2D( self.my.data().attribute("StartPoint") )
220
221   def endPointData (self):
222     return geomDataAPI_Point2D( self.my.data().attribute("EndPoint") )
223
224   def result (self):
225     return self.my.firstResult()
226
227
228 class Circle():
229
230   def __init__(self, sketch, x, y, r):
231     self.my = sketch.addFeature("SketchCircle")
232     geomDataAPI_Point2D( self.my.data().attribute("CircleCenter") ).setValue(x, y)
233     self.my.data().real("CircleRadius").setValue(r)
234     self.my.execute()
235
236   def centerData (self):
237     return geomDataAPI_Point2D( self.my.data().attribute("CircleCenter") )
238
239   def result (self):
240     return self.my.lastResult()   # Returns the circular line attribute
241
242