Salome HOME
Debug of Box macro feature to the updated architecture
[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     self.my.execute()
126     return constraint
127
128   def setRadius (self, circle, radius):
129     """Sets the radius of the given circle and adds the corresponding constraint to this Sketch."""
130     constraint = self.my.addFeature("SketchConstraintRadius")
131     constraint.data().refattr("ConstraintEntityA").setObject(circle)
132     constraint.data().real("ConstraintValue").setValue(radius)
133     return constraint
134
135
136 # Edition of Dimensional Constraints
137
138   def setValue (self, constraint, value):
139     """Modifies the value of the given dimensional constraint."""
140     constraint.data().real("ConstraintValue").setValue(value)
141
142
143 # Getters
144
145   def selectFace (self, *args):
146     """Selects the geometrical entities of this Sketch on which the result Face must be built.
147         When no entity is given, the face is based on all existing geometry of this Sketch.
148         """
149     #self.resultype ="Face"
150     if   len(args) == 0:
151       self.selection = modelAPI_ResultConstruction( self.my.firstResult() ).shape()
152     elif len(args) == 1:
153       self.selection = args[0].shape()
154     else:
155       raise Exception("not yet implemented")
156     return self
157
158   def buildShape (self):
159     """Builds the result Shape of this Sketch according to the selected geometrical entities."""
160     o  = geomDataAPI_Point( self.my.data().attribute("Origin") ).pnt()
161     dx = geomDataAPI_Dir( self.my.data().attribute("DirX") ).dir()
162     n  = geomDataAPI_Dir( self.my.data().attribute("Norm") ).dir()
163
164     self.faces = ShapeList()      # The faces are kept otherwise they are destroyed at exit
165     GeomAlgoAPI_SketchBuilder.createFaces(o, dx, n, self.selection, self.faces)
166 #TODO: Deal with several faces 
167     return self.faces[0]
168
169   def result (self):
170     """Returns the result data of this Feature."""
171     return self.my.firstResult()
172
173
174 # Class definitions of Sketch features
175
176 class Point():
177
178   def __init__(self, sketch, x, y):
179     self.my = sketch.addFeature("SketchPoint")
180     geomDataAPI_Point2D( self.my.data().attribute("PointCoordindates") ).setValue(x, y)
181     self.my.execute()
182
183   def pointData (self):
184     return geomDataAPI_Point2D( self.my.data().attribute("PointCoordindates") )
185
186   def result (self):
187     return self.my.firstResult()
188
189
190 class Line():
191
192   def __init__(self, sketch, *args):
193     self.my = sketch.addFeature("SketchLine")
194     if   len(args) == 4:
195       self.__createByCoordinates(*args)
196     elif len(args) == 2:
197       self.__createByPoints(*args)
198     elif len(args) == 1:
199           self.__createByName(sketch, *args)
200     else:
201       raise Exception("cannot create the Line")
202
203   def __createByCoordinates(self, x1, y1, x2, y2):
204     geomDataAPI_Point2D( self.my.data().attribute("StartPoint") ).setValue(x1, y1)
205     geomDataAPI_Point2D( self.my.data().attribute("EndPoint") ).setValue(x2, y2)
206     self.my.execute()
207
208   def __createByPoints(self, p1, p2):
209     geomDataAPI_Point2D( self.my.data().attribute("StartPoint") ).setValue(p1.x(), p1.y())
210     geomDataAPI_Point2D( self.my.data().attribute("EndPoint") ).setValue(p2.x(), p2.y())
211     self.my.execute()
212
213   def __createByName(self, sketch, name):
214     self.my.data().selection("External").selectSubShape("EDGE", name)
215     self.my.execute()
216     rigid = sketch.addFeature("SketchConstraintRigid")
217     rigid.refattr("ConstraintEntityA").setObject( self.my.firstResult() )
218
219   def startPointData (self):
220     return geomDataAPI_Point2D( self.my.data().attribute("StartPoint") )
221
222   def endPointData (self):
223     return geomDataAPI_Point2D( self.my.data().attribute("EndPoint") )
224
225   def result (self):
226     return self.my.firstResult()
227
228
229 class Circle():
230
231   def __init__(self, sketch, x, y, r):
232     self.my = sketch.addFeature("SketchCircle")
233     geomDataAPI_Point2D( self.my.data().attribute("CircleCenter") ).setValue(x, y)
234     self.my.data().real("CircleRadius").setValue(r)
235     self.my.execute()
236
237   def centerData (self):
238     return geomDataAPI_Point2D( self.my.data().attribute("CircleCenter") )
239
240   def result (self):
241     return self.my.lastResult()   # Returns the circular line attribute
242
243