diff -urN v1/cube.yaml v2/cube.yaml --- v1/cube.yaml 2018-11-02 03:28:27.000000000 +0900 +++ v2/cube.yaml 2018-11-02 23:18:05.000000000 +0900 @@ -12,6 +12,7 @@ - [0,1,2,3,0,4,5,6,7,4,1,5,0] - [2,6] - [3,7] +- [4,6] eye_p: [0,-20,0] eye_t: [0,0,0] diff -urN v1/p3d.py v2/p3d.py --- v1/p3d.py 2018-11-02 03:28:06.000000000 +0900 +++ v2/p3d.py 2018-11-02 23:18:05.000000000 +0900 @@ -6,29 +6,39 @@ import opt import wfrm +# l, m, r +btn_downs = ( wx.EVT_LEFT_DOWN.typeId, wx.EVT_MIDDLE_DOWN.typeId, wx.EVT_RIGHT_DOWN.typeId ) +btn_ups = ( wx.EVT_LEFT_UP.typeId, wx.EVT_MIDDLE_UP.typeId, wx.EVT_RIGHT_UP.typeId ) + def new_dclick(): e = ut.Empty() e.timer = None e.pos = None + e.i = -1 def cancel(): + e.i = -1 if e.timer: e.timer.cancel() e.timer = None def check(event): typeId = event.GetEventType() - if typeId != wx.EVT_LEFT_UP.typeId: - cancel() - return False - pos = event.GetPosition() + if not e.timer: - e.pos = pos - e.timer = threading.Timer(0.3, cancel) - e.timer.start() - return False - cancel() - return pos == e.pos + if typeId in btn_ups: + e.i = btn_ups.index(typeId) + e.pos = pos + e.timer = threading.Timer(0.3, cancel) + e.timer.start() + return '' + + i = e.i + if typeId != btn_downs[i]: + cancel() + if typeId == btn_ups[i]: + return 'lmr'[i] + return '' e.check = check return e @@ -68,26 +78,21 @@ dc.DrawLine(x1, y1, x2, y2) def hdr(self, event): - if self.dclick.check(event): + dck = self.dclick.check(event) + if dck == 'r': + self.wf.turn_view() + elif dck == 'l': self.wf.reset() + if dck: self.panel.Refresh() return typeId = event.GetEventType() (x, y) = event.GetPosition() - d = { - wx.EVT_RIGHT_DOWN.typeId: 'zoom', - wx.EVT_MIDDLE_DOWN.typeId: 'move', - wx.EVT_LEFT_DOWN.typeId: 'rot', - } - u = [ - wx.EVT_RIGHT_UP.typeId, - wx.EVT_MIDDLE_UP.typeId, - wx.EVT_LEFT_UP.typeId, - ] - if typeId in d: - self.wf.down(x, y, d.get(typeId) ) - elif typeId in u: + if typeId in btn_downs: + mode = ('rot', 'move', 'zoom')[ btn_downs.index(typeId) ] + self.wf.down(x, y, mode) + elif typeId in btn_ups: self.wf.up() elif typeId == wx.EVT_MOTION.typeId and self.wf.mode: self.wf.drag(x, y) diff -urN v1/sinc.py v2/sinc.py --- v1/sinc.py 1970-01-01 09:00:00.000000000 +0900 +++ v2/sinc.py 2018-11-02 23:18:05.000000000 +0900 @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +import yaml +import math +import numpy as np + +if __name__ == "__main__": + nx = 31 + ny = 11 + w = 10.0 + h = w * 0.5 + + ps = [] + idxs = [] + + for iy in range(ny): + y = w * ( iy / float(ny-1) - 0.5 ) + for ix in range(nx): + x = w * ( ix / float(nx-1) - 0.5 ) + z = float( h * np.sinc( math.sqrt( x*x + y*y ) ) ) + ps.append( [x,y,z] ) + + for i in range(ny): + idxs.append( list( range(i*nx, (i+1)*nx) ) ) + + eye_p = [ w*2, -w*5, w*3 ] + eye_t = [ 0, 0, 0 ] + + d = { 'ps': ps, 'idxs': idxs, 'eye_p': eye_p, 'eye_t': eye_t } + s = yaml.dump( d, default_flow_style=False ) + print(s) +# EOF diff -urN v1/wfrm.py v2/wfrm.py --- v1/wfrm.py 2018-11-02 03:28:20.000000000 +0900 +++ v2/wfrm.py 2018-11-02 23:18:05.000000000 +0900 @@ -1,7 +1,9 @@ #!/usr/bin/env python +import sys import yaml import math +import numpy as np import ut import mt import v @@ -47,9 +49,12 @@ return list( map( f, p2s ) ) def load(fn_yaml): - f = open(fn_yaml, 'r') - s = f.read() - f.close() + def f_read(fn): + f = open(fn, 'r') + s = f.read() + f.close() + return s + s = sys.stdin.read() if fn_yaml == '-' else f_read(fn_yaml) d = yaml.load(s) ks = ( 'ps', 'idxs', 'eye_p', 'eye_t' ) @@ -63,12 +68,14 @@ def new(fn_yaml, f_wh, w_deg=30): ( ps, idxs, eye_p, eye_t ) = load(fn_yaml) + views = ( 'XYOrbit', 'TopDownOrtho' ) e = ut.Empty() e.p = eye_p e.t = eye_t e.org = ( e.p, e.t ) e.mode = '' + e.view = views[0] dz = 1.0 / math.tan( 0.5 * mt.deg_to_rad(w_deg) ) @@ -77,6 +84,13 @@ sc_sz = (w, h, dz*w) wh2eye = lstx.opt( [ ax.wh_map(w, h), fcx.new(dz), ax.zoom_z(-1), ax.rot_x(90) ] ) eye2g = ax.new_line( line.new_p2( e.p, e.t ) ) + + if e.view == 'TopDownOrtho': + a = v.unit( e.p - e.t ) + deg = mt.rad_to_deg( math.acos( np.dot( a, v.z1 ) ) ) + l = line.new( e.t, v.cross_product_unit( a, v.z1 ) ) + eye2g = eye2g.compo( ax.rot(l, deg) ) + return cvt(ps, idxs, eye2g, wh2eye, sc_sz) e.get_lst = get_lst @@ -97,11 +111,18 @@ if e.mode == 'zoom': e.p = bp + (-ry) * (bt - bp) elif e.mode == 'move': - dzw = dz * w - rx = math.atan2(x - w2, dzw) - math.atan2(bx - w2, dzw) - ry = math.atan2(y - h2, dzw) - math.atan2(by - h2, dzw) - ax_p = ax.new_line( line.new_p2( bp, bt ) ) - e.t = lstx.tr( [ ax_p, ax.rot_z(rx*90), ax.rot_x(ry*90), ax_p.rev() ], 'g2l', bt ) + if e.view == 'TopDownOrtho': + vy = e.t - e.p + vy[2] = 0 + vx = ax.rot_z(-90).tr( 'l2g', vy ) + mv = ( -rx * vx + ry * vy ) * 0.1 + ( e.t, e.p ) = ( bt + mv, bp + mv ) + else: + dzw = dz * w + rx = math.atan2(x - w2, dzw) - math.atan2(bx - w2, dzw) + ry = math.atan2(y - h2, dzw) - math.atan2(by - h2, dzw) + ax_p = ax.new_line( line.new_p2( bp, bt ) ) + e.t = lstx.tr( [ ax_p, ax.rot_z(rx*90), ax.rot_x(ry*90), ax_p.rev() ], 'g2l', bt ) elif e.mode == 'rot': ax_t = ax.new_line( line.new_p2( bt, bp ) ) e.p = lstx.tr( [ ax_t, ax.rot_z(rx*90), ax.rot_x(-ry*90), ax_t.rev() ], 'g2l', bp ) @@ -109,7 +130,12 @@ def reset(): (e.p, e.t) = e.org + e.view = views[0] e.reset = reset + def turn_view(): + e.view = views[ ( views.index(e.view) + 1 ) % len(views) ] + e.turn_view = turn_view + return e # EOF