summaryrefslogtreecommitdiff
path: root/gui/gui.py
blob: ca0d3c3767e5ec68b6682884e8852e5d2f33357b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/python
import sys
import functools
from OCC.gp import *
from OCC.TopoDS import *
from OCC.BRepBuilderAPI import *
from OCC.BRepPrimAPI import *
from OCC.BRepAlgoAPI import *
from OCC.AIS import *
from OCC.Graphic3d import *
from OCC.Prs3d import *
from OCC.TCollection import *
from OCC.Display.wxSamplesGui import add_function_to_menu, add_menu, start_display, display
import OCC.Display.wxSamplesGui
from skdb.geom import Point, Direction, move_shape, point_along
from skdb import Interface
from skdb.core.interface import FakeIGraph

class App:
    def __init__(self):
        self.current_brick = None
        self.all_bricks = []
        self.cgraph = FakeIGraph()
        self.display = None
        
    def working_brick(self):
        working_brick = None
        if self.display.selected_shape: #should I use AIS/Context stuff instead?
            working_brick = self.find_part(self.display.selected_shape)
        if not working_brick: #find_part might not find a brick that matches, or maybe nothing was clicked
            working_brick = self.current_brick
        return working_brick

    def find_part(self, shape):
            for brick in self.all_bricks:
                if brick.shapes[0] == shape:
                    return brick
            raise Warning, "selected shape not found:" + str(shape)
            return False
            
    def delete(self, shape):
        '''erase selected shape and remove it from the connection graph if it's there'''
        done = False
        if self.display.selected_shape:
            for brick in self.all_bricks:
                if hasattr(brick, 'AIS_handle'):
                    if brick.shapes[0] == self.display.selected_shape:
                        self.display.Context.Erase(brick.AIS_handle) #should be the same as EraseSelected
                        self.cgraph.del_part(brick)
                        self.all_bricks.remove(brick)
                        done = True
        if not done: self.display.Context.EraseSelected()
                    
            
class Arrow(TopoDS_Shape):
    def __init__(self, origin=gp_Pnt(0,0,0), direction=gp_Dir(0,0,1), scale=1):
        self.origin = Point(origin)
        self.direction = Direction(direction)
        self.scale = scale
        self.build_shape()
        #apparently this screws up later transformations somehow
        ##apparently we must translate and then rotate
        tmp = gp_Trsf()
        tmp.SetTranslation(gp_Pnt(0,0,0), origin)
        #self.transformation = tmp.Multiplied(point_along(direction))
        self.transformation = gp_Trsf()
        self.to(point_along(direction))
        self.to(tmp)


        #tmp = point_along(direction)
        #self.transformation.Multiply(tmp)
    def build_shape(self):
        scale = self.scale
        body = BRepPrimAPI_MakeCylinder(0.02*scale, 0.7*scale).Shape()
        head = BRepPrimAPI_MakeCone(0.1*scale,0.001,0.3*scale).Shape()
        head = move_shape(head, gp_Pnt(0,0,0), gp_Pnt(0,0,0.7*scale)) #move cone to top of arrow
        self._shape =  BRepAlgoAPI_Fuse(head, body).Shape()

    def Shape(self):
        return BRepBuilderAPI_Transform(self._shape, self.transformation).Shape()

    def to(self, dest):
        assert isinstance(dest, gp_Trsf)
        self.transformation.Multiply(dest)
        return self.Shape()

class Flag(Arrow):
    def __init__(self, origin=gp_Pnt(0,0,0), direction=gp_Dir(0,0,1), scale=1):
        Arrow.__init__(self, origin=origin, direction=direction, scale=scale)
    def build_shape(self):
        scale = self.scale
        body = BRepPrimAPI_MakeCylinder(0.02*scale, 1*scale).Shape()
        head = BRepPrimAPI_MakeWedge (0.3*scale, 0.05*scale, 0.3*scale, 0.1).Shape() #dx, dy, dz, ltx(?)
        head = move_shape(head, gp_Pnt(0,0,0), gp_Pnt(0,0,0.7*scale)) #move flag to top of arrow
        self._shape = BRepAlgoAPI_Fuse(head, body).Shape()

def show_interfaces(event=None, brick=None, app=None):
    if brick is None: brick = app.current_brick
    for i in brick.interfaces:
        i.show()

def show_interface_arrow(self, color=None):
        tmp = self.part.transformation
        tmp2 = self.get_transformation()
        trsf1 = tmp.Multiplied(tmp2)
        arrow = Arrow(scale=5)
        arrow.transformation = trsf1
        if color:
            display.DisplayColoredShape(make_vertex(Point(0,0,0).Transformed(trsf1)), color)
            display.DisplayColoredShape(arrow.Shape(), color)
        else:
            display.DisplayShape(make_vertex(Point(0,0,0).Transformed(trsf1)))
            display.DisplayShape(arrow.Shape())

Interface.show = show_interface_arrow

def make_text(string, pnt, height):
    '''render a bunch of text at pnt's location
    myGroup should be an OCC.Graphic3d.Graphic3d_Group instance.
    call init_display before calling this function.
    '''
    global display
    _string = TCollection_ExtendedString(string)
    if isinstance( pnt, gp_Pnt2d):
        _vertex = Graphic3d_Vertex(pnt.X(), pnt.Y(), 0)
    else:
        _vertex = Graphic3d_Vertex(pnt.X(), pnt.Y(), pnt.Z())
    myGroup.Text(_string, _vertex, height)

def make_arrow(event=None, origin=gp_Pnt(0,0,0), direction=gp_Dir(0,0,1), scale=1, text=None, color="YELLOW"):
    '''draw a small arrow from origin to dest, labeled with 2d text'''
    arrow = Arrow(origin=origin, direction=direction, scale=scale).Shape()
    display.DisplayColoredShape(arrow, color)
    if text is not None:
        make_text(text, origin, 6)

def coordinate_arrow(direction, color='YELLOW', flag=False, scale=3):
    if flag: shape = Flag(scale=scale, direction=direction).Shape()
    else: shape = Arrow(scale=scale, direction=direction).Shape()
    display.DisplayColoredShape(shape, color)

def coordinate_arrows(event=None):
    #typical origin symbol
    display.DisplayShape(make_vertex(gp_Pnt(0,0,0)))
    for (v, c) in [[(1,0,0), 'RED'], [(0,1,0), 'GREEN'], [(0,0,1), 'BLUE']]:
        coordinate_arrow(v, c)

def chain_arrows(event=None):
    #a silly chain of arrows
    make_arrow(origin=gp_Pnt(0,0,1), direction=gp_Dir(1,1,1))
    display.DisplayShape(make_vertex(gp_Pnt(1,1,2)))
    s=math.sqrt(3)/3
    make_arrow(origin=gp_Pnt(s,s,s+1), direction=gp_Dir(1,1,1), text='hmm')

def add_key(key,method_to_call,**keywords):
    '''binds a key to a particular method
    ex: add_key("G",some_method)
    '''
    upper_case = key.upper()
    orded = ord(upper_case) #see wxDisplay.py line 171
    OCC.Display.wxSamplesGui.frame.canva._key_map[orded] = functools.partial(method_to_call, keywords)
    print "key '", orded, "' mapped to ", method_to_call
    return

def init_display():
    '''The reason for recreating is that myGroup is gone after an EraseAll call'''
    global myGroup
    global myPresentation
    # now we have to make a presenation for a stupid sphere as a workaround to get to the object
    stupid_sphere = BRepPrimAPI_MakeSphere(1,1,1,1)
    prs_sphere = AIS_Shape(stupid_sphere.Shape())
    d_ctx           = display.GetContext().GetObject()
    prsMgr          = d_ctx.CollectorPrsMgr().GetObject()
    d_ctx.Display(prs_sphere.GetHandle(), 1)
    myPresentation   = prsMgr.CastPresentation(prs_sphere.GetHandle()).GetObject()
    myGroup = Prs3d_Root().CurrentGroup(myPresentation.Presentation()).GetObject()

def clear(event=None):
    display.EraseAll()

def show_next_mate(event=None, mate=None):
    '''cycle through available options and display them with each keypress'''
    global opt
    display.EraseAll()
    display.DisplayColoredShape(current_brick.shapes[0], 'RED')
    conn=opts[opt]
    opt += 1
    trsf = mate_connection(conn)

    display.DisplayShape(BRepBuilderAPI_Transform(conn.interface2.part.shapes[0], trsf, True).Shape())
    display.DisplayShape(make_vertex(Point(conn.interface1.point).Transformed(trsf)))
    display.DisplayShape(make_vertex(Point(conn.interface2.point).Transformed(trsf)))


def make_vertex(pnt):
    if isinstance(pnt, gp_Pnt2d):
        vertex = BRepBuilderAPI_MakeVertex( gp_Pnt(pnt.X(), pnt.Y(), 0))
    else:
        vertex = BRepBuilderAPI_MakeVertex( pnt )
    vertex.Build()
    return vertex.Vertex()



def exit(event=None):
    sys.exit()