1 #process geometry framework
2 #provides code to interpret geometrical constraints and carry out random operations
4 import random
, sys
, functools
7 from OCC
.Geom2d
import *
8 from OCC
.Geom2dAdaptor
import *
9 from OCC
.Geom2dAPI
import *
10 from OCC
.GCPnts
import *
13 from OCC
.GccEnt
import *
14 from OCC
.GccAna
import *
15 from OCC
.Geom2dGcc
import *
16 from OCC
.GCE2d
import *
18 from OCC
.Precision
import *
19 from OCC
.Display
.wxSamplesGui
import display
21 import math
#OCC.math gets in the way? wtf
24 from skdb
.core
import *
25 from skdb
.core
.interface
import FakeIGraph
29 current
= gp_Pnt2d(0,0)
31 def random_line(scale
=10):
33 p1
= current
#should be a gp_Pnt2d
34 p2
= gp_Pnt2d(random
.randint(0, scale
), random
.randint(0, scale
))
36 current
= p1
.Translated(v2
)
37 return GCE2d_MakeSegment(p1
, p2
).Value()
39 def random_arc(scale
=10):
41 p1
= current
#should be a gp_Pnt2d
42 p2
= gp_Pnt2d(random
.randint(0, scale
), random
.randint(0, scale
))
43 p3
= gp_Pnt2d(random
.randint(0, scale
), random
.randint(0, scale
))
45 current
= p1
.Translated(v3
)
46 return GCE2d_MakeArcOfCircle(p1
, p2
, p3
).Value()
48 def draw_random_line(event
=None):
49 display
.DisplayShape([make_edge2d(random_line())])
51 def draw_random_arc(event
=None):
52 display
.DisplayShape([make_edge2d(random_arc())])
54 def line_arc_line_path(event
=None):
56 mkwire
= BRepBuilderAPI_MakeWire()
59 edge
= BRepBuilderAPI_MakeEdge2d(random_line()).Edge()
63 face
= BRepBuilderAPI_MakeFace(wire
).Face()
64 fillet
= BRepFilletAPI_MakeFillet2d(face
)
65 #print fillet.Status()
67 explorer
= TopExp_Explorer(face
, TopAbs_VERTEX
)
69 while explorer
.More():
71 vertex
= TopoDS().Vertex(explorer
.Current())
72 make_vertex(BRep_Tool().Pnt(vertex
))
73 #help( vertex.Location().Value())
74 fillet
.AddFillet(vertex
, radius
)
76 print fillet
.NbFillet()
77 #print fillet.IsDone()
78 #while not fillet.IsDone(): pass
82 display
.DisplayShape([face
])
85 def random_cone(event
=None):
86 #p1, p2, p3, p4 = None, None, None, None #ew
87 #for i in p1, p2, p3, p4:
88 #i = gp_Pnt(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))
94 cone
= gce_MakeCone(p1
, p2
, p3
, p4
).Value()
95 cone
= BRepPrimAPI_MakeCone(gp
.gp().XOY(), 1,1.1,1)
97 cone
= BRepPrimAPI_MakeCone(gp
.gp().XOY(), random
.uniform(0,1), random
.uniform(0,1), random
.uniform(0,1)).Shape()
98 display
.DisplayShape([cone
])
99 except RuntimeError: cone
= random_cone()
102 def sweep_path(path
, shape
):
105 assert type(shape
) == TopoDS_Shape
106 #assert type(path) == TopoDS_Wire #bah
107 sweep
= BRepOffsetAPI_MakePipe(path
, shape
).Shape()
110 def random_sweep(event
=None):
111 display
.DisplayShape([sweep_path( line_arc_line_path(), random_cone())])
113 def tangents(curve1
, curve2
, radius
=2):
114 '''only works for lines and circles atm'''
115 #if type(curve1) == gp_Lin2d:
116 QC
= GccEnt
.GccEnt().Unqualified(curve1
)
117 QL
= GccEnt
.GccEnt().Unqualified(curve2
)
118 TR
= GccAna_Circ2d2TanRad(QC
,QL
,radius
,Precision().Confusion())
120 #TR = Geom2dGcc_Lin2d2Tan(QC, QL, Precision().Confusion()) #curve, curve, tol; or curve, point, tol
123 NbSol
= TR
.NbSolutions()
125 for k
in range(1,NbSol
+1):
126 circ
= TR
.ThisSolution(k
)
127 display
.DisplayShape(make_edge2d(circ
))
128 # find the solution circle ( index, outvalue, outvalue, gp_Pnt2d )
130 # find the first tangent point
131 parsol
,pararg
= TR
.Tangency1(k
, pnt1
) #gross
132 display
.DisplayShape(make_vertex(pnt1
))
135 # find the second tangent point
136 parsol
,pararg
= TR
.Tangency2(k
, pnt2
)
137 display
.DisplayShape(make_vertex(pnt2
))
138 solutions
+= (circ
, pnt1
, pnt2
)
141 print "TR didnt finish!"
146 def draw_all_tangents(event
=None):
151 point
= gp_Pnt2d(random
.randint(0,10), random
.randint(0,10))
153 make_text('P'+str(i
), point
, 6)
154 display
.DisplayShape(make_vertex(point
))
156 C
= GCE2d_MakeArcOfCircle(points
[0], points
[1], points
[2]).Value()
157 display
.DisplayShape(make_edge2d(C
))
158 C_gp
= gce_MakeCirc2d(points
[0], points
[1], points
[2]).Value() #ew. same thing; tangent solver wants a circle, not arc
160 L
= GCE2d_MakeSegment(points
[3], points
[4]).Value()
161 #L = GccAna_Lin2d2Tan(points[3], points[4],Precision().Confusion()).ThisSolution(1)
162 display
.DisplayShape([make_edge2d(L
)])
163 L_gp
= gce_MakeLin2d(points
[3], points
[4]).Value() #yuck. same thing; tangent solver wants a line, not segment
165 tangents(C_gp
, L_gp
, radius
=2)
168 from copy
import copy
, deepcopy
169 from random
import randint
171 #move most of this into the lego package
172 lego
= Package("lego")
175 app
.display
= display
178 '''returns a basic lego brick part from the catalog (no side effects)'''
179 brick
= deepcopy(lego
.parts
[random
.randint(0,len(lego
.parts
)-1)])
182 #not sure where to move this
185 display
.DisplayShape([brick
.shapes
[0] for brick
in app
.all_bricks
])
187 def make_lego(event
=None, brick
=None, app
=app
):
188 if brick
is None: brick
= get_brick() #load a brick from the catalog
189 app
.current_brick
= brick
191 #give it an interesting starting orientation (not 0)
192 tmp
.SetTranslation(Point(0,0,0), Point(3.14, 3.14, 3.14))
193 tmp
.SetRotation(gp_Ax1(Point(0,0,0), Direction(1,0,0)), 3.14/3)
194 #orient the part so that i[0] is aligned with the origin's z-axis
195 i
= app
.current_brick
.interfaces
[0]
196 trsf
= i
.get_transformation().Inverted()
197 trsf
.Multiply(tmp
.Inverted()) #side effect
198 app
.current_brick
.transformation
= trsf
#side effect
199 shapes
= app
.current_brick
.shapes
200 shapes
[0] = BRepBuilderAPI_Transform(shapes
[0], trsf
, True).Shape() #move it
201 app
.current_brick
.AIS_handle
= display
.DisplayColoredShape(shapes
[0], 'RED')
202 app
.all_bricks
.append(app
.current_brick
)
203 app
.cgraph
.add_part(app
.current_brick
)
205 def pick_interface(brick
):
206 tmp
= copy(brick
.interfaces
)
211 raise Warning, "no more interfaces to choose from: "+str([i
for i
in brick
.interfaces
])
213 def valid_options(options
, working_brick
=None, app
=app
):
214 '''uses bounding boxes interference detection to figure out which among a list of options are not going to totally suck'''
215 if working_brick
is None: working_brick
= app
.working_brick()
217 shape1
= deepcopy(options
[0].interface1
.part
.shapes
[0])
218 box1
= BoundingBox(shape
=shape1
)
219 for connection
in options
:
220 if connection
.interface1
.connected
or connection
.interface2
.connected
: next
222 trsf
= mate_connection(connection
)
223 #shape1 = deepcopy(connection.interface1.part.shapes[0])
224 #box1 = BoundingBox(shape1)
225 shape2
= deepcopy(connection
.interface2
.part
.shapes
[0])
226 shape2
= BRepBuilderAPI_Transform(shape2
, trsf
, True).Shape()
227 box2
= BoundingBox(shape
=shape2
)
228 #we're going to assume it can connect to the target brick .. sorry.
229 for brick
in app
.all_bricks
:
230 if brick
is not connection
.interface1
.part
and brick
is not working_brick
: #but! it can still connect and interfere simultaneously
231 #recalculate bounding box because the shape may have updated since load_CAD
232 tmp_box
= BoundingBox(shape
=brick
.shapes
[0])
233 if box2
.interferes(tmp_box
) is True:
235 print "ok it was bad."
238 results
.append(connection
)
241 def add_valid_lego(event
=None, brick
=None, n
=0, app
=app
):
243 assert OverflowError, "too many iterations"
245 #different configurations for this function:
246 #working_brick = app.all_bricks[random.randint(0, len(app.all_bricks)-1)]
247 working_brick
= app
.working_brick()
250 if brick
is not None:
252 else: brick2
= get_brick()
256 options
= pick_interface(working_brick
).options(brick2
)
258 elif j
>20: raise OverflowError, "can't figure it out"
259 else: brick2
= get_brick() #try again
261 #make sure the options don't suck too much
262 valid_opts
= valid_options(options
, working_brick
=working_brick
)
264 #raise ValueError, "collision detected for all possibilities. trying again.."
265 print "colllision detected for all possibilities. trying again.."
266 add_valid_lego(event
=event
, brick
=get_brick(), n
=n
+1)
270 connection
= valid_opts
[random
.randint(0, len(valid_opts
)-1)]
271 trsf
= mate_connection(connection
)
272 brick2
.transformation
= trsf
273 brick2
.shapes
[0] = BRepBuilderAPI_Transform(brick2
.shapes
[0], trsf
, True).Shape()
276 app
.all_bricks
.append(brick2
)
277 app
.current_brick
= brick2
280 connection
.interface1
.show()
281 connection
.interface2
.show()
282 brick2
.AIS_handle
= display
.DisplayShape(brick2
.shapes
[0])
284 def show_bounding_box(event
=None, app
=app
):
285 brick
= app
.working_brick()
286 displayed_shape
= display
.DisplayShape(BoundingBox(brick
.shapes
[0]).make_box())
287 display
.Context
.SetTransparency( displayed_shape
, 0.3 )
289 def add_lego(event
=None, brick
=None, app
=app
):
292 if brick
is not None: brick2
= brick
293 else: brick2
= get_brick()
295 i1
= app
.current_brick
.interfaces
[random
.randint(0, len(app
.current_brick
.interfaces
)-1)]
296 opts
= i1
.options(brick2
)
298 elif n
> 20: raise OverflowError, "I can't figure it out!" #timeout; impossible situation
299 else: brick2
= get_brick() #try again
301 conn
=opts
[random
.randint(0, len(opts
)-1)]
303 #i1 = app.current_brick.interfaces[3]
304 #i2 = brick2.interfaces[7]
305 #conn = skdb.Connection(i1, i2)
307 trsf
= mate_connection(conn
)
308 brick2
.transformation
= trsf
309 #brick2.shapes[0] keeps on being overwritten. what's the point of having it be a list?
310 brick2
.shapes
[0] = BRepBuilderAPI_Transform(brick2
.shapes
[0], trsf
, True).Shape() #move it
311 conn
.interface1
.show()
312 print "%.2f %.2f %.2f" % Point(conn
.interface1
.point
).Transformed(conn
.interface1
.part
.transformation
).Coord()
313 conn
.interface2
.show()
314 print "%.2f %.2f %.2f" % Point(conn
.interface2
.point
).Transformed(conn
.interface2
.part
.transformation
).Coord()
316 app
.all_bricks
.append(brick2
)
318 app
.cgraph
.add_part(brick2
)
319 naive_coincidence_fixer(app
.all_bricks
, cgraph
=app
.cgraph
)
321 app
.cgraph
.del_part(brick2
)
322 add_lego() #try again
323 #conn.connect(cgraph=app.cgraph) #this should whine about interface busy
325 brick2
.AIS_handle
= display
.DisplayShape(brick2
.shapes
[0])
326 app
.current_brick
= brick2
328 app
.current_brick
= get_brick()
330 opts
= app
.current_brick
.options(brick2
)
333 def clear(event
=None, app
=app
):
334 app
.current_brick
= None
336 app
.cgraph
= FakeIGraph()
339 def save(event
=None):
340 '''dump the current construction'''
341 app
.cgraph
.graph
.write('cgraph.dot', format
='graphviz')
343 add_key('a', add_lego
)
344 add_key('n', add_valid_lego
)
345 add_key('b', show_bounding_box
)
346 add_key('c', functools
.partial(clear
, app
=app
))
347 add_key('d', app
.delete
)
348 add_key('m', make_lego
)
349 add_key('i', functools
.partial(show_interfaces
, app
=app
))
350 add_key(' ', show_next_mate
)
353 if __name__
== '__main__':
354 from OCC
.Display
.wxSamplesGui
import add_function_to_menu
, add_menu
, start_display
367 #test_coordinate_arrows,
375 add_function_to_menu('demo', f
)
381 #test_transformation()