; docformat = 'rst' ;+ ; Demonstrates changing attributes of axis' text so they are always facing the ; viewer. ;- function mg_show_axis_updir, transform, axis_dir compile_opt strictarr ; compute up direction updir = [0., 1., 0., 0.] axis_dir = [axis_dir, 0.] # transform ; project up direction onto plane through axis to keep updir orthogonal to ; baseline updir -= (transpose(reform(updir)) # reform(axis_dir))[0] * axis_dir ; go back to absolute coordinates updir = updir # invert(transform) ; go back to 3-dimensional vector return, updir[0:2] end ;+ ; Handle all events. ; ; :Params: ; event : in, required, type=structure ; any event generated by widget program ;- pro mg_show_axes_event, event compile_opt strictarr widget_control, event.top, get_uvalue=pstate uname = widget_info(event.id, /uname) case uname of 'draw' : begin update = (*pstate).track->update(event, transform=rotation) if (update) then begin ; normal trackball rotation stuff here model = (*pstate).view->getByName('model') model->getProperty, transform=transform newTransform = transform # rotation model->setProperty, transform=newTransform ; instead of storing each axis object in state structure, find by name xaxis = model->getByName('x') yaxis = model->getByName('y') zaxis = model->getByName('z') ; set textbaseline so text faces viewer if (~(*pstate).noSwitch) then begin flipxy = newTransform[2, 2] gt 0. ? 1. : -1. flipz = newTransform[1, 2] gt 0. ? -1. : 1. xaxis->setProperty, textbaseline=[flipxy, 0., 0.] yaxis->setProperty, textbaseline=[0., flipxy, 0.] zaxis->setProperty, textbaseline=[0., 0., flipz] xaxis->getProperty, title=xtitle yaxis->getProperty, title=ytitle zaxis->getProperty, title=ztitle xtitle->setProperty, baseline=[flipxy, 0., 0.] ytitle->setProperty, baseline=[0., flipxy, 0.] ztitle->setProperty, baseline=[0., 0., flipz] ;xtitle->setProperty, updir=mg_show_axis_updir(newTransform, [1., 0., 0.]) ;ytitle->setProperty, updir=mg_show_axis_updir(newTransform, [0., 1., 0.]) ;ztitle->setProperty, updir=mg_show_axis_updir(newTransform, [0., 0., 1.]) endif ; remember to redraw or you won't see any changes (*pstate).window->draw, (*pstate).view endif end endcase end ;+ ; Cleanup resources. ; ; :Params: ; tlb : in, required, type=long ; widget identifier of the top-level base ;- pro mg_show_axes_cleanup, tlb compile_opt strictarr widget_control, tlb, get_uvalue=pstate model = (*pstate).view->getByName('model') xaxis = model->getByName('x') yaxis = model->getByName('y') zaxis = model->getByName('z') xaxis->getProperty, title=xtitle yaxis->getProperty, title=ytitle zaxis->getProperty, title=ztitle ; titles and trackball not part of hierarchy, so must be destroyed separately obj_destroy, [xtitle, ytitle, ztitle, (*pstate).view, (*pstate).track] ptr_free, pstate end ;+ ; Demonstrates changing attributes of axis' text so they are always facing the ; viewer. ; ; :Keywords: ; no_switch : in, optional, type=boolean ; set to not switch the text baseline to face the viewer ; renderer : in, optional, type=long ; set to 0 for hardware rendering, 1 for software rendering ;- pro mg_show_axes, no_switch=noSwitch, renderer=renderer compile_opt strictarr ; create simple widget hierarchy tlb = widget_base(title='Axes demo', /column) draw = widget_draw(tlb, xsize=400, ysize=400, $ graphics_level=2, renderer=renderer, $ /button_events, /motion_events, uname='draw') widget_control, tlb, /realize widget_control, draw, get_value=window view = obj_new('IDLgrView', color=background) model = obj_new('IDLgrModel', name='model') view->add, model cr = [0, 1] cc = norm_coord(cr) cc[0] -= 0.5 xaxis_title = obj_new('IDLgrText', 'X-axis') xaxis = obj_new('IDLgrAxis', 0, range=cr, /exact, $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='x', $ title=xaxis_title) model->add, xaxis yaxis_title = obj_new('IDLgrText', 'Y-axis') yaxis = obj_new('IDLgrAxis', 1, range=cr, /exact, $ textbaseline=[0, 1, 0], textupdir=[-1, 0, 0], $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='y', $ title=yaxis_title) model->add, yaxis zaxis_title = obj_new('IDLgrText', 'Z-axis') zaxis = obj_new('IDLgrAxis', 2, range=cr, /exact, $ textbaseline=[0, 0, -1], textupdir=[-1, 0, 0], $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='z', $ title=zaxis_title) model->add, zaxis ; rotate to get a nicer original orientation model->rotate, [1, 0, 0], 5 model->rotate, [0, 1, 0], -30 ; initial rendering window->draw, view ; trackball handles converting mouse motions to transformations track = obj_new('Trackball', [200, 200], 200) ; "pstate" data passing strategy for a widget program state = { view: view, $ window: window, $ track: track, $ noSwitch: keyword_set(noSwitch) $ } pstate = ptr_new(state, /no_copy) widget_control, tlb, set_uvalue=pstate xmanager, 'mg_show_axes', tlb, /no_block, $ cleanup='mg_show_axes_cleanup', $ event_handler='mg_show_axes_event' end