various methods to parse pages from thingiverse
[skdb.git] / paths.py
blobcb642e70655230694d7ed2eb53ff4de333d86f87
1 #process geometry framework
2 #provides code to interpret geometrical constraints and carry out random operations
4 import random, sys, functools
6 from OCC.gp import *
7 from OCC.Geom2d import *
8 from OCC.Geom2dAdaptor import *
9 from OCC.Geom2dAPI import *
10 from OCC.GCPnts import *
11 from OCC.GC import *
13 from OCC.GccEnt import *
14 from OCC.GccAna import *
15 from OCC.Geom2dGcc import *
16 from OCC.GCE2d import *
17 from OCC.gce import *
18 from OCC.Precision import *
19 from OCC.Display.wxSamplesGui import display
21 import math #OCC.math gets in the way? wtf
23 import skdb
24 from skdb.core import *
25 from skdb.core.interface import FakeIGraph
26 from geom import *
27 from gui import *
29 current = gp_Pnt2d(0,0)
31 def random_line(scale=10):
32 global current
33 p1 = current #should be a gp_Pnt2d
34 p2 = gp_Pnt2d(random.randint(0, scale), random.randint(0, scale))
35 v2 = gp_Vec2d(p1, p2)
36 current = p1.Translated(v2)
37 return GCE2d_MakeSegment(p1, p2).Value()
39 def random_arc(scale=10):
40 global current
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))
44 v3 = gp_Vec2d(p1, p3)
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):
55 radius = 10
56 mkwire = BRepBuilderAPI_MakeWire()
57 print "create edges"
58 for i in range(3):
59 edge = BRepBuilderAPI_MakeEdge2d(random_line()).Edge()
60 mkwire.Add(edge)
61 wire = mkwire.Wire()
62 print "create face"
63 face = BRepBuilderAPI_MakeFace(wire).Face()
64 fillet = BRepFilletAPI_MakeFillet2d(face)
65 #print fillet.Status()
66 print "explore face"
67 explorer = TopExp_Explorer(face, TopAbs_VERTEX)
68 i=0
69 while explorer.More():
70 print "vertex: ", i
71 vertex = TopoDS().Vertex(explorer.Current())
72 make_vertex(BRep_Tool().Pnt(vertex))
73 #help( vertex.Location().Value())
74 fillet.AddFillet(vertex, radius)
75 fillet.Build()
76 print fillet.NbFillet()
77 #print fillet.IsDone()
78 #while not fillet.IsDone(): pass
79 explorer.Next()
80 i+=1
82 display.DisplayShape([face])
83 return wire
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))
89 #print i.Coord()
90 p1 = gp_Pnt(0,0,0)
91 p2 = gp_Pnt(0,0,1)
92 p3 = 1
93 p4 = 2
94 cone = gce_MakeCone(p1, p2, p3, p4).Value()
95 cone = BRepPrimAPI_MakeCone(gp.gp().XOY(), 1,1.1,1)
96 try:
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()
100 return cone
102 def sweep_path(path, shape):
103 print type(shape)
104 print type(path)
105 assert type(shape) == TopoDS_Shape
106 #assert type(path) == TopoDS_Wire #bah
107 sweep = BRepOffsetAPI_MakePipe(path, shape).Shape()
108 return sweep
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
121 def find_solns(TR):
122 if TR.IsDone():
123 NbSol = TR.NbSolutions()
124 solutions = []
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 )
129 pnt1 = gp_Pnt2d()
130 # find the first tangent point
131 parsol,pararg = TR.Tangency1(k, pnt1) #gross
132 display.DisplayShape(make_vertex(pnt1))
134 pnt2 = gp_Pnt2d()
135 # find the second tangent point
136 parsol,pararg = TR.Tangency2(k, pnt2)
137 display.DisplayShape(make_vertex(pnt2))
138 solutions += (circ, pnt1, pnt2)
139 return solutions
140 else:
141 print "TR didnt finish!"
142 return
144 find_solns(TR)
146 def draw_all_tangents(event=None):
147 display.EraseAll()
148 init_display()
149 points = []
150 for i in range(5):
151 point = gp_Pnt2d(random.randint(0,10), random.randint(0,10))
152 points += [point]
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")
174 app = App()
175 app.display = display
177 def get_brick():
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)])
180 return brick
182 #not sure where to move this
183 def show_bricks():
184 display.EraseAll()
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
190 tmp = gp_Trsf()
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)
207 random.shuffle(tmp)
208 for i in tmp:
209 if not i.is_busy():
210 return i
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()
216 results = []
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
221 bad = False
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:
234 bad=True
235 print "ok it was bad."
236 break
237 if not bad:
238 results.append(connection)
239 return results
241 def add_valid_lego(event=None, brick=None, n=0, app=app):
242 if n>20:
243 assert OverflowError, "too many iterations"
244 return
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()
249 #get a second brick
250 if brick is not None:
251 brick2 = brick
252 else: brick2 = get_brick()
255 while True:
256 options = pick_interface(working_brick).options(brick2)
257 if options: break
258 elif j>20: raise OverflowError, "can't figure it out"
259 else: brick2 = get_brick() #try again
260 j+=1
261 #make sure the options don't suck too much
262 valid_opts = valid_options(options, working_brick=working_brick)
263 if not valid_opts:
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)
267 return
269 #now pick one
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()
275 #set the globals
276 app.all_bricks.append(brick2)
277 app.current_brick = brick2
279 #visual stuff
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):
290 opts = None
292 if brick is not None: brick2 = brick
293 else: brick2 = get_brick()
294 while True:
295 i1 = app.current_brick.interfaces[random.randint(0, len(app.current_brick.interfaces)-1)]
296 opts = i1.options(brick2)
297 if opts: break
298 elif n > 20: raise OverflowError, "I can't figure it out!" #timeout; impossible situation
299 else: brick2 = get_brick() #try again
300 n+=1
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)
317 try:
318 app.cgraph.add_part(brick2)
319 naive_coincidence_fixer(app.all_bricks, cgraph=app.cgraph)
320 except GayError:
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()
329 brick2 = get_brick()
330 opts = app.current_brick.options(brick2)
331 opt = 0
333 def clear(event=None, app=app):
334 app.current_brick = None
335 app.all_bricks=[]
336 app.cgraph = FakeIGraph()
337 display.EraseAll()
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)
351 add_key('v', save)
353 if __name__ == '__main__':
354 from OCC.Display.wxSamplesGui import add_function_to_menu, add_menu, start_display
355 add_menu('demo')
356 for f in [
357 add_valid_lego,
358 draw_all_tangents,
359 draw_random_line,
360 draw_random_arc,
361 line_arc_line_path,
362 random_cone,
363 random_sweep,
364 make_arrow,
365 chain_arrows,
366 coordinate_arrows,
367 #test_coordinate_arrows,
368 show_interfaces,
369 make_lego,
370 add_lego,
371 clear,
372 save,
373 exit
375 add_function_to_menu('demo', f)
376 #random_sweep()
377 init_display()
378 make_lego()
379 add_lego()
380 coordinate_arrows()
381 #test_transformation()
382 start_display()