;+ ; $Id: line3d.pro,v 1.4 2012/03/01 16:44:29 nathan Exp $ ; ; Line3d is covered in the Sunloop User Guide: ; $SSW/stereo/secchi/idl/display/sunloop/sunloop_user_guide.pdf ; ; written by: Jeffrey.R.Hall@jpl.nasa.gov ; written for: Paulett.C.Liewer@jpl.nasa.gov ; STEREO/SECCHI Project ; ; "Copyright 2012, by the California Institute of Technology. ; ALL RIGHTS RESERVED. United States Government Sponsorship ; acknowledged. Any commercial use must be negotiated with the ; Office of Technology Transfer at the California Institute of ; Technology. ; This software may be subject to U.S. export control laws. ; By accepting this software, the user agrees to comply with ; all applicable U.S. export laws and regulations. User has ; the responsibility to obtain export licenses, or other ; export authority as may be required before exporting such ; information to foreign countries or providing access to ; foreign persons." ;- @build_frustrums_model @orb2__define.pro PRO draw_window_has_been_killed, infoPtr IF OBJ_VALID((*infoPtr).objectWindow) THEN DESTROY, (*infoPtr).objectWindow IF OBJ_VALID((*infoPtr).objectDrawWidget) THEN DESTROY, (*infoPtr).objectDrawWidget IF OBJ_VALID((*infoPtr).objectDrawBase) THEN DESTROY, (*infoPtr).objectDrawBase IF WIDGET_INFO((*infoPtr).tlb,/VALID_ID) THEN WIDGET_CONTROL,(*infoPtr).tlb,/DESTROY IF PTR_VALID(infoPtr) THEN PTR_FREE,infoPtr ; Lots more pointers and objects should be destroyed... END PRO redraw_polyLineView, infoPtr ;http://www.idlcoyote.com/code_tips/underflow.html ;Silently accumulate any subsequent math errors. ; d_volrendr.pro orig_except = !except ; subroutine: d_volrendrDraw !except = 0 ; (not sure what it all does) ;Silently flush any accumulated math error. ; copied from void = CHECK_MATH() ; IDL_DIR/examples/demo/demosrc/ IF (WIDGET_INFO((*infoPtr).objectDrawBase,/VALID_ID) EQ 0) THEN BEGIN draw_window_has_been_killed, infoPtr RETURN ENDIF ; Draw polyLine view to the window. wait,0.01 (*infoPtr).objectWindow -> Draw, (*infoPtr).polyLineView ;Ignore any accumulated floating underflow errors. (They are benign). ; copied from ;Display any other accumulated math errors. ; IDL_DIR/examples/demo/demosrc/ floating_point_underflow = 32 ; Per IDL Reference Guide: see CHECK_MATH(). ; d_volrendr.pro status = CHECK_MATH() ; Get status and reset. ; subroutine: d_volrendrDraw IF ( (status AND NOT floating_point_underflow) NE 0 ) THEN BEGIN ; (not sure what it all does) PRINT, 'IDL CHECK_MATH() error: ' + STRTRIM(status, 2) ; ENDIF ;Restore original math error behavior. ; !except = orig_except ; END PRO line3d_widgetdraw_event_handler, event, infoPtr IF (WIDGET_INFO((*infoPtr).objectDrawBase,/VALID_ID) EQ 0) THEN BEGIN draw_window_has_been_killed, infoPtr RETURN ENDIF ; Set mouse flag when mouse up or mouse down occurs. IF ( event.PRESS) THEN BEGIN (*infoPtr).mouseDown = 1 ENDIF IF ( event.RELEASE ) THEN BEGIN (*infoPtr).mouseDown = 0 ENDIF ; Rotate, scale and translate in screen coordinates. IF ( STRUPCASE( (*infoPtr).coordinatesFlag ) EQ 'SCREENCOORDINATES' ) THEN BEGIN ; If zoom is turned on, then just do scaling and return. IF ( (*infoPtr).zoomButtonStatus AND ( (*infoPtr).mouseDown OR event.RELEASE ) ) THEN BEGIN IF ( event.PRESS ) THEN BEGIN (*infoPtr).y_cursor_initial_value = event.Y ENDIF (*infoPtr).y_cursor_previous_diff = (*infoPtr).y_cursor_current_diff (*infoPtr).y_cursor_current_diff = event.Y - (*infoPtr).y_cursor_previous_value (*infoPtr).y_cursor_previous_value = event.Y IF ( (*infoPtr).y_cursor_current_diff LT (*infoPtr).y_cursor_preVious_diff ) THEN BEGIN (*infoPtr).y_cursor_initial_value = event.Y ENDIF zoom = (!D.Y_SIZE - FLOAT( event.Y )) / (!D.Y_SIZE - FLOAT( (*infoPtr).y_cursor_initial_value )) ;;;;;;;;;;;;;;;;;;;;;;;;WIDGET_CONTROL, (*infoPtr).zoomLabel, SET_VALUE = 'Zoom = ' + STRTRIM( STRING( zoom ), 2 ) ; Reset and render. (*infoPtr).current_zoom = zoom (*infoPtr).universe_model -> Scale, zoom, zoom, zoom ; Keep the labels positioned about 1/2 way between screen center and edge. FOR axisTextObj = 0, N_ELEMENTS( (*infoPtr).axisTextObjarr ) - 1 DO BEGIN (*infoPtr).axisTextObjarr[axisTextObj] -> GetProperty, LOCATIONS = locations (*infoPtr).axisTextObjarr[axisTextObj] -> SetProperty, LOCATIONS = locations / zoom ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr RETURN ENDIF ; Update trackball object, check if translate is on or off. IF ( (*infoPtr).translate ) THEN BEGIN ; Translation. bHaveTransform = (*infoPtr).myTrackBall -> Update( event, TRANSFORM = qmat, /TRANSLATE ) ENDIF ELSE BEGIN ; Rotation. bHaveTransform = (*infoPtr).myTrackBall -> Update( event, TRANSFORM = qmat ) ENDELSE ; On mouse down, draw polyLineView. IF ( event.PRESS ) THEN BEGIN ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ENDIF ; On mouse down + cursor motion + bHaveTransform, update position of and redraw polyLineView. IF ( event.TYPE EQ 2 ) AND ( (*infoPtr).mouseDown ) AND ( bHaveTransform ) THEN BEGIN ; Update old transform matrix by multiplying with new rotation transform matrix. (*infoPtr).universe_model -> GetProperty, TRANSFORM = t tq = t # qmat (*infoPtr).universe_model -> SetProperty, TRANSFORM = tq ; ; Do same thing for axis model. ; ; (Axis has independent transformation matrix. Polyline model was transformed from Jean Lorre's classic xyz to Heliographic-Cartesian xyz. The asis was not.) ; (*infoPtr).axisModel -> GetProperty, TRANSFORM = t ; tq = t # qmat ; (*infoPtr).axisModel -> SetProperty, TRANSFORM = tq ;; ; Get Euler angles from 3x3 subset of 4x4 rotation matrix. ;; CSPICE_M2EUL, qmat[0:2,0:2], 3, 2, 1, z, y, x ; Redraw polyline object with new view orientation. redraw_polyLineView, infoPtr ENDIF ; Translate the trackball center so that rotation in screen coordinates still works. ; THIS DOES NOT WORK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IF event.RELEASE THEN BEGIN ;print,'reset',(*infoPtr).center IF ((*infoPtr).rotateAxis EQ 3) THEN BEGIN (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0] ENDIF ELSE BEGIN (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis ENDELSE ENDIF ; ATTEMPT TO UPDATE THE VALUES IN THE ANGLE TEXT BOXES, WORK IN PROGRESS!! ; THIS WAS DONE BEFORE USING CSPICE_M2EUL, SO NOW WITH THAT IT COULD BE MADE TO WORK PROBABLY. ;print,'screen coords' ; (*infoPtr).polyLineModel -> GetProperty, TRANSFORM = t_polyLine ;print,'t_polyLine = ' ;print, t_polyLine ;print,'x = ',asin(t_polyLine[1,2])*!radeg ;print,'y = ',asin(t_polyLine[2,0])*!radeg ;print,'z = ',asin(t_polyLine[0,1])*!radeg ; ; Get floating point X,Y,Z angle values from the transform matrix. ; FltXangle = ASIN( t_polyLine[1,2] ) * !RADEG ;+ 90 ; FltYangle = ASIN( t_polyLine[2,0] ) * !RADEG ; FltZangle = ASIN( t_polyLine[0,1] ) * !RADEG ;print,'FltXangle = ',FltXangle ;print,'FltYangle = ',FltYangle ;print,'FltZangle = ',FltZangle ; ; Zero out very small angle values thereby eliminating values with scientific notation. ; IF ( FltXangle LT 0.01 ) AND ( FltXangle GT -0.01 ) THEN FltXangle = 0.0 ; IF ( FltYangle LT 0.01 ) AND ( FltYangle GT -0.01 ) THEN FltYangle = 0.0 ; IF ( FltZangle LT 0.01 ) AND ( FltZangle GT -0.01 ) THEN FltZangle = 0.0 ; ; Grab only the first 6 characters in the string for display in the text widget. ; StrXangle = STRMID(STRTRIM(STRING(FltXangle),2),0,6) ; StrYangle = STRMID(STRTRIM(STRING(FltYangle),2),0,6) ; StrZangle = STRMID(STRTRIM(STRING(FltZangle),2),0,6) ;print,'StrXangle = ',StrXangle ;print,'StrYangle = ',StrYangle ;print,'StrZangle = ',StrZangle ; ; Set the angle values in the text widgets. ; WIDGET_CONTROL, (*infoPtr).screenEntryTextX, SET_VALUE = StrXangle ; WIDGET_CONTROL, (*infoPtr).screenEntryTextY, SET_VALUE = StrYangle ; WIDGET_CONTROL, (*infoPtr).screenEntryTextZ, SET_VALUE = StrZangle RETURN ENDIF ; Rotate in data coordinates. IF ( STRUPCASE( (*infoPtr).coordinatesFlag ) EQ 'DATACOORDINATES' ) THEN BEGIN ; This is the key to controlling data coords. result = (*infoPtr).polyLineRotator -> Update(event) IF ( result EQ 1 ) THEN BEGIN ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ENDIF ENDIF ; On expose event, redraw polyLineView. IF ( event.TYPE EQ 4 ) AND ( NOT (*infoPtr).first_time_through ) THEN BEGIN ; Set hourglass only here, not every time through. WIDGET_CONTROL, /HOURGLASS ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ENDIF (*infoPtr).first_time_through = 0 END FUNCTION load_frustrums, infoPtr, ALL_STEPS=allsteps IF KEYWORD_SET(all_steps) THEN BEGIN all_steps=1 ENDIF ELSE BEGIN all_steps=0 ENDELSE ;;; IF (fits_data_access eq 1) THEN BEGIN FOR step=0,(*infoPtr).nsteps-1 DO BEGIN ;; Instead, initialize with step=0 of xyz_data. ;;if step gt 0 then continue ; frustrums_struct = BUILD_FRUSTRUMS_MODEL( $ ; step_state[step].date, $ ; step_state[step].time, $ ; step_state[step].stereoa_xyz, $ ; step_state[step].stereob_xyz, $ ; fits_data_access, $ ; tiff_data_access, $ ; /EXCLUDE_EUVI_TIFF ) ; KEEP STEP=0 FOR ALL FRUSTRUMS GEOMETRY. HAVING MULTIPLE FRUSTRUMS AT DIFFERENT TIME STEPS DOESN'T REALLY WORK VERY WELL. THEY TEND TO JITTER TOO MUCH. IF (all_steps EQ 1) THEN BEGIN frustrums_struct = BUILD_FRUSTRUMS_MODEL( $ (*infoPtr).step_state[step].date, $ (*infoPtr).step_state[step].time, $ (*infoPtr).step_state[step].stereoa_xyz, $ (*infoPtr).step_state[step].stereob_xyz, $ (*infoPtr).fits_data_access, $ (*infoPtr).tiff_data_access, $ step, $ (*infoPtr).nsteps, $ EXCLUDE_EUVI_TIFF = 1, $ SAVE_VRML = (*infoPtr).save_vrml, $ ONLY_SHOW_ONE_INST_IMAGE = (*infoPtr).only_show_one_inst_image, $ ONLY_SHOW_TWO_INST_IMAGE = (*infoPtr).only_show_two_inst_image, $ SYSTEM = (*infoPtr).system ) ENDIF ELSE BEGIN frustrums_struct = BUILD_FRUSTRUMS_MODEL( $ (*infoPtr).step_state[step].date, $ (*infoPtr).step_state[step].time, $ (*infoPtr).step_state[step].stereoa_xyz, $ (*infoPtr).step_state[step].stereob_xyz, $ (*infoPtr).fits_data_access, $ (*infoPtr).tiff_data_access, $ step, $ (*infoPtr).nsteps, $ EXCLUDE_EUVI_TIFF = 1, $ SAVE_VRML = (*infoPtr).save_vrml, $ ONLY_SHOW_ONE_INST_IMAGE = (*infoPtr).only_show_one_inst_image, $ ONLY_SHOW_TWO_INST_IMAGE = (*infoPtr).only_show_two_inst_image, $ SYSTEM = (*infoPtr).system ) ENDELSE IF (frustrums_struct.success EQ 0) THEN BEGIN RETURN, 0 ENDIF (*infoPtr).step_state[step].frustrumsModel = frustrums_struct.frustrumsModel (*infoPtr).step_state[step].imagesModel = frustrums_struct.imagesModel (*infoPtr).step_state[step].imageObjArr_ptr = PTR_NEW( frustrums_struct.imageObjArr, /NO_COPY ) (*infoPtr).step_state[step].fits_filenames_ptr = PTR_NEW( frustrums_struct.fits_filenames, /NO_COPY ) (*infoPtr).step_state[step].hdr_detector_ptr = PTR_NEW( frustrums_struct.hdr_detector, /NO_COPY ) (*infoPtr).step_state[step].hdr_wavelnth_ptr = PTR_NEW( frustrums_struct.hdr_wavelnth, /NO_COPY ) (*infoPtr).step_state[step].max_heights_of_frustrums = frustrums_struct.max_heights_of_frustrums FOR f=0,1 DO BEGIN FOR g=0,4 DO BEGIN IF (STRMID( (*(*infoPtr).step_state[step].fits_filenames_ptr)[f,g], 5, 10) NE 'not loaded' ) THEN BEGIN (*(*infoPtr).step_state[step].fits_filenames_ptr)[f,g] = FILE_SEARCH( (*(*infoPtr).step_state[step].fits_filenames_ptr)[f,g] ) ENDIF ENDFOR ENDFOR ; Shoehorn date and time into filename strarr. (*(*infoPtr).step_state[step].fits_filenames_ptr)[*,5] = [ '', 'MASTER TIME = '+(*infoPtr).step_state[step].date+'_'+(*infoPtr).step_state[step].time ] ; universe_model -> Add, step_state[step].frustrumsModel ; universe_model -> Add, step_state[step].imagesModel ENDFOR ;;; ENDIF ELSE BEGIN ;;; step_state.frustrumsModel = OBJ_NEW( 'IDLgrModel', HIDE = 1 ) ;;; step_state.imagesModel = OBJ_NEW( 'IDLgrModel', HIDE = 1 ) ;;; ENDELSE RETURN, 1 END PRO line3d_event, event WIDGET_CONTROL, /HOURGLASS WIDGET_CONTROL, event.TOP, GET_UVALUE = infoPtr IF (WIDGET_INFO((*infoPtr).objectDrawBase,/VALID_ID) EQ 0) THEN BEGIN draw_window_has_been_killed, infoPtr RETURN ENDIF ; Handle movie looping before any other events. IF (TAG_NAMES( event, /STRUCTURE_NAME ) EQ 'WIDGET_TIMER') THEN BEGIN IF ((*infoPtr).movie_timer_delay GT 0.0) THEN BEGIN ; Allow the slider to rest at zero for several seconds before stopping the movie. ; This allows the user to do a zero crossing without having the movie cancel immediately. several_seconds = 5 IF ((*infoPtr).movie_increment_degrees EQ 0.0) THEN BEGIN IF (*infoPtr).movie_zero_timer_now EQ 0.0 THEN BEGIN (*infoPtr).movie_zero_timer_initial = SYSTIME( /SECONDS ) ENDIF (*infoPtr).movie_zero_timer_now = ( SYSTIME( /SECONDS ) - (*infoPtr).movie_zero_timer_initial ) IF ((*infoPtr).movie_zero_timer_now GT several_seconds) THEN BEGIN WIDGET_CONTROL, (*infoPtr).movie_onoff_button, SET_VALUE='Start' (*infoPtr).movie_timer_delay = 0.0 (*infoPtr).movie_zero_timer_now = 0.0 ENDIF WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay ENDIF ELSE BEGIN (*infoPtr).movie_zero_timer_now = 0.0 ENDELSE ; Handle zooms. Do a short animated zoom when changing zoom level. zoom_nsteps = 10 IF ((*infoPtr).zoom_step EQ 1) THEN BEGIN (*infoPtr).zoom_increment = ((*infoPtr).new_zoom - (*infoPtr).current_zoom) / FLOAT(zoom_nsteps) ENDIF IF ((*infoPtr).zoom_step GE 1) AND ((*infoPtr).zoom_step LT zoom_nsteps) THEN BEGIN zoom_stepper = (*infoPtr).current_zoom + ( (*infoPtr).zoom_increment * (*infoPtr).zoom_step ) (*infoPtr).universe_model -> Reset (*infoPtr).universe_model -> Rotate, [1,0,0], 90 (*infoPtr).universe_model -> Scale, zoom_stepper, zoom_stepper, zoom_stepper ; Rotate around to last rotation point. FOR r = 0, (*infoPtr).cumulative_movie_rotation_increments - 1 DO BEGIN (*infoPtr).universe_model -> Rotate, [0,1,0], (*infoPtr).movie_increment_degrees ENDFOR (*infoPtr).zoom_step = (*infoPtr).zoom_step + 1 ENDIF IF ((*infoPtr).zoom_step GE zoom_nsteps) THEN BEGIN (*infoPtr).current_zoom = (*infoPtr).new_zoom (*infoPtr).universe_model -> Reset (*infoPtr).universe_model -> Rotate, [1,0,0], 90 (*infoPtr).universe_model -> Scale, (*infoPtr).current_zoom, (*infoPtr).current_zoom, (*infoPtr).current_zoom ; Rotate around to last rotation point. FOR r = 0, (*infoPtr).cumulative_movie_rotation_increments - 1 DO BEGIN (*infoPtr).universe_model -> Rotate, [0,1,0], (*infoPtr).movie_increment_degrees ENDFOR (*infoPtr).zoom_step = 0 ENDIF ; Perform one movie rotation step. (*infoPtr).universe_model -> Rotate, [0,1,0], (*infoPtr).movie_increment_degrees (*infoPtr).cumulative_movie_rotation_increments = ((*infoPtr).cumulative_movie_rotation_increments + 1) MOD 360 ; FOR line = 0, N_ELEMENTS( (*infoPtr).polylineobjarr ) - 1 DO BEGIN ; ((*infoPtr).polyLineObjArr)[line] -> SetProperty, HIDE = 1 ; ENDFOR ; ((*infoPtr).polyLineObjArr)[(*infoPtr).step] -> SetProperty, HIDE = 0 IF ((*infoPtr).hide_frustrums EQ 0) THEN BEGIN (*infoPtr).step_state[(*infoPtr).step].frustrumsModel -> SetProperty, HIDE = 1 ENDIF IF ((*infoPtr).hide_images EQ 0) THEN BEGIN (*infoPtr).step_state[(*infoPtr).step].imagesModel -> SetProperty, HIDE = 1 ENDIF (*infoPtr).step = ( (*infoPtr).step + 1 ) mod (*infoPtr).nsteps IF ((*infoPtr).hide_frustrums EQ 0) THEN BEGIN (*infoPtr).step_state[(*infoPtr).step].frustrumsModel -> SetProperty, HIDE = 0 ENDIF IF ((*infoPtr).hide_images EQ 0) THEN BEGIN (*infoPtr).step_state[(*infoPtr).step].imagesModel -> SetProperty, HIDE = 0 ENDIF ; IF (*infoPtr).hide_images THEN BEGIN ; (*infoPtr).draw_window_title = 'Date_Time = ' + (*infoPtr).timesteps[0] ; ENDIF ELSE BEGIN (*infoPtr).draw_window_title = 'Date_Time = ' + (*infoPtr).timesteps[(*infoPtr).step] ; ENDELSE (*infoPtr).draw_window_title = (*infoPtr).draw_window_title + ', Window size = ' + STRTRIM( FIX((*infoPtr).xdim), 2 ) + 'x' + STRTRIM( FIX((*infoPtr).ydim), 2 ) IF WIDGET_INFO((*infoPtr).objectDrawBase,/VALID_ID) THEN BEGIN WIDGET_CONTROL, (*infoPtr).objectDrawBase, BASE_SET_TITLE = (*infoPtr).draw_window_title ENDIF IF OBJ_VALID((*infoPtr).objectWindow) THEN BEGIN ;Silently accumulate any subsequent math errors. ; d_volrendr.pro orig_except = !except ; subroutine: d_volrendrDraw !except = 0 ; (not sure what it all does) ;Silently flush any accumulated math error. ; copied from void = CHECK_MATH() ; IDL_DIR/examples/demo/demosrc/ ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ;Ignore any accumulated floating underflow errors. (They are benign). ; copied from ;Display any other accumulated math errors. ; IDL_DIR/examples/demo/demosrc/ floating_point_underflow = 32 ; Per IDL Reference Guide: see CHECK_MATH(). ; d_volrendr.pro status = CHECK_MATH() ; Get status and reset. ; subroutine: d_volrendrDraw IF ( (status AND NOT floating_point_underflow) NE 0 ) THEN BEGIN ; (not sure what it all does) PRINT, 'IDL CHECK_MATH() error: ' + STRTRIM(status, 2) ; ENDIF ;Restore original math error behavior. ; !except = orig_except ; ENDIF IF (*infoPtr).moviesave_counter GT 0 THEN BEGIN WIDGET_CONTROL, (*infoPtr).moviesave_frame_label, SET_VALUE = ' Frame ' + STRTRIM( (*infoPtr).moviesave_counter, 2 ) + ' of 360' imageObject = (*infoPtr).objectWindow -> READ() imageObject -> GetProperty, DATA = imageData angle = (*infoPtr).moviesave_counter zpad = '' IF ( angle LT 100 ) THEN zpad = '0' IF ( angle LT 10 ) THEN zpad = '00' angle_string = zpad + STRTRIM( angle, 2 ) IF ((*infoPtr).xyz_filename NE '') THEN BEGIN filename_part1 = (STRSPLIT( (STRSPLIT( FILE_BASENAME( (*infoPtr).xyz_filename ), '.', /EXTRACT ))[0], '_' , /EXTRACT ))[1] IF (N_ELEMENTS(STRSPLIT( (STRSPLIT( FILE_BASENAME( (*infoPtr).xyz_filename ), '.', /EXTRACT ))[0], '_' , /EXTRACT )) GE 3) THEN BEGIN filename_part2 = (STRSPLIT( (STRSPLIT( FILE_BASENAME( (*infoPtr).xyz_filename ), '.', /EXTRACT ))[0], '_' , /EXTRACT ))[2] ENDIF ELSE BEGIN filename_part2 = 'frame' ENDELSE filename = filename_part1 + '_' + filename_part2 + '_' + angle_string + '.tiff' ENDIF ELSE BEGIN CASE 1 OF (*infoPtr).only_show_one_inst_image NE '' : BEGIN filename = (*infoPtr).only_show_one_inst_image + '_' + (*infoPtr).step_state[0].date + '_' + angle_string + '.tiff' END (*infoPtr).only_show_two_inst_image[0] NE '' : BEGIN filename = (*infoPtr).only_show_two_inst_image[0] + '_' + (*infoPtr).only_show_two_inst_image[1] filename = filename + '_' + (*infoPtr).step_state[0].date + '_' + angle_string + '.tiff' END ELSE : BEGIN filename = 'frame_' + (*infoPtr).step_state[0].date + '_' + angle_string + '.tiff' END ENDCASE ENDELSE WRITE_TIFF, filename, REVERSE(imageData,3), /COMPRESS (*infoPtr).moviesave_counter = (*infoPtr).moviesave_counter + 1 IF (*infoPtr).moviesave_counter GT 360 THEN BEGIN (*infoPtr).moviesave_counter = 0 (*infoPtr).movie_timer_delay = 0 WIDGET_CONTROL, (*infoPtr).moviesave_off_button, /SET_BUTTON WIDGET_CONTROL, (*infoPtr).moviesave_frame_label, SET_VALUE = '' ENDIF ENDIF IF OBJ_VALID((*infoPtr).objectWindow) THEN BEGIN WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay ENDIF ENDIF RETURN ENDIF ; Handle widget base resize events and return. IF ( TAG_NAMES( event, /STRUCTURE_NAME ) EQ 'WIDGET_BASE' ) THEN BEGIN ; Implies resize event for widget_base and widget_draw. IF ( event.X LT (*infoPtr).xdim + 10 ) AND ( event.X GT (*infoPtr).xdim - 10 ) $ AND ( event.Y LT (*infoPtr).ydim + 10 ) AND ( event.Y GT (*infoPtr).ydim - 10 ) THEN BEGIN ;print,'reset to current size and RETURN' ENDIF threshold = 10 oldSize = (*infoPtr).xdim newSize = event.X < event.Y < (*infoPtr).maxSizeAllowed IF ( newSize LT (oldSize - threshold) ) OR ( newSize GT (oldSize + threshold) ) OR ( newSize GT ((*infoPtr).maxSizeAllowed - threshold) ) THEN BEGIN (*infoPtr).xdim = newSize (*infoPtr).ydim = (*infoPtr).xdim ENDIF ELSE BEGIN ; If new size differs by less than threshold then disallow resize. ; (This catches events generated when the window is only moved.) ; ; (First hide, then resize to halfsize, then resize to original size, then show. ; Otherwise, resizing to original size doesn't seem to work.) ; WIDGET_CONTROL, (*infoPtr).objectDrawBase, MAP = 0 WIDGET_CONTROL, (*infoPtr).objectDrawBase, XSIZE = (*infoPtr).xdim, YSIZE = (*infoPtr).ydim / 2 WIDGET_CONTROL, (*infoPtr).objectDrawBase, XSIZE = (*infoPtr).xdim, YSIZE = (*infoPtr).ydim WIDGET_CONTROL, (*infoPtr).objectDrawWidget, XSIZE = (*infoPtr).xdim, YSIZE = (*infoPtr).ydim WIDGET_CONTROL, (*infoPtr).objectDrawBase, MAP = 1 RETURN ENDELSE WIDGET_CONTROL, (*infoPtr).objectDrawBase, XSIZE = (*infoPtr).xdim, YSIZE = (*infoPtr).ydim WIDGET_CONTROL, (*infoPtr).objectDrawWidget, XSIZE = (*infoPtr).xdim, YSIZE = (*infoPtr).ydim IF (*infoPtr).hide_images THEN BEGIN (*infoPtr).draw_window_title = 'Date_Time = ' + (*infoPtr).timesteps[0] ENDIF ELSE BEGIN (*infoPtr).draw_window_title = 'Date_Time = ' + (*infoPtr).timesteps[(*infoPtr).step] ENDELSE WIDGET_CONTROL, (*infoPtr).objectDrawBase, BASE_SET_TITLE = (*infoPtr).draw_window_title + ', Window size = ' + STRTRIM( FIX((*infoPtr).xdim), 2 ) + 'x' + STRTRIM( FIX((*infoPtr).ydim), 2 ) (*infoPtr).center[*] = (*infoPtr).center[0] * ( ( (*infoPtr).xdim / 2.0 ) / (*infoPtr).center[0] ) ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ; Resize the VRML destination object, too. (*infoPtr).myVRML -> SetProperty, DIMENSIONS = [(*infoPtr).xdim,(*infoPtr).ydim] RETURN ENDIF WIDGET_CONTROL, event.ID, GET_UVALUE = uval IF SIZE(uval,/TYPE) EQ 10 THEN BEGIN ; Skip over TLB events, where the UVALUE is always infoPtr. RETURN ENDIF uval_string = STRUPCASE( uval ) ; Send all mouse events to the subroutine line3d_widgetdraw_event_handler. IF uval_string EQ 'OBJECTDRAW' THEN BEGIN WIDGET_CONTROL, event.ID, SENSITIVE = 0 line3d_widgetdraw_event_handler, event, infoPtr WIDGET_CONTROL, event.ID,SENSITIVE = 1 RETURN ENDIF ; Handle all other events, such as widget buttons. CASE 1 OF ; Select coordinate system for rotation. uval_string EQ 'DATACOORD' : BEGIN WIDGET_CONTROL, (*infoPtr).dataCoordinatesBase, MAP = 1 WIDGET_CONTROL, (*infoPtr).screenCoordinatesBase, MAP = 0 (*infoPtr).coordinatesFlag = 'DATACOORDINATES' END uval_string EQ 'SCREENCOORD' : BEGIN WIDGET_CONTROL, (*infoPtr).dataCoordinatesBase, MAP = 0 WIDGET_CONTROL, (*infoPtr).screenCoordinatesBase, MAP = 1 (*infoPtr).coordinatesFlag = 'SCREENCOORDINATES' END ; Data coordinates, set the axis. uval_string EQ 'DATAX' OR uval_string EQ 'DATAY' OR uval_string EQ 'DATAZ' : BEGIN (*infoPtr).dataRotateXYZ = uval CASE 1 OF (*infoPtr).dataRotateXYZ EQ 'DATAX' : BEGIN (*infoPtr).polyLineRotator -> SetProperty, AXIS = 0, CONSTRAIN = 2 END (*infoPtr).dataRotateXYZ EQ 'DATAY' : BEGIN (*infoPtr).polyLineRotator -> SetProperty, AXIS = 1, CONSTRAIN = 2 END (*infoPtr).dataRotateXYZ EQ 'DATAZ' : BEGIN (*infoPtr).polyLineRotator -> SetProperty, AXIS = 2, CONSTRAIN = 2 END ELSE : BEGIN ; Just to avoid crashes if no CASE matches are found. END ENDCASE END ; Set object orientation back to initial data coordinates view. uval_string EQ 'DATACOORDSRESET' : BEGIN WIDGET_CONTROL, /HOURGLASS ;;;;;;;;;;;;;;;;;;;;;;;;WIDGET_CONTROL, (*infoPtr).zoomLabel, SET_VALUE = 'Zoom = 1.0' (*infoPtr).polyLineRotator -> Reset, (*infoPtr).center, ((*infoPtr).center)[0] ; Initial position is rotated 90 degrees in the X axis to effectively swap the Y and Z axes. transform = IDENTITY( 4 ) (*infoPtr).polyLineRotator -> SetProperty, TRANSFORM = transform ; Draw polyLine view to the window. redraw_polyLineView, infoPtr (*infoPtr).polyLineRotator -> SetProperty, AXIS = 0, CONSTRAIN = 2 WIDGET_CONTROL, (*infoPtr).dataRotateXButton, /SET_BUTTON END ; Screen coordinates, set the axis or free (the next 4 cases). uval_string EQ 'FREE' : BEGIN ; Set rotation to allow free-form rotation with cursor. (*infoPtr).rotateAxis = 3 (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0] END uval_string EQ 'SCREENX' : BEGIN ; Set rotation constraint to X axis only. (*infoPtr).rotateAxis = 0 (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis END uval_string EQ 'SCREENY' : BEGIN ; Set rotation constraint to Y axis only. (*infoPtr).rotateAxis = 1 (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis END uval_string EQ 'SCREENZ' : BEGIN ; Set rotation constraint to Z axis only. (*infoPtr).rotateAxis = 2 (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis END uval_string EQ 'TEXTX' : BEGIN WIDGET_CONTROL, /HOURGLASS WIDGET_CONTROL, (*infoPtr).screenEntryTextX, GET_VALUE = angle (*infoPtr).universe_model -> Rotate, [1,0,0], angle[0] ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'TEXTY' : BEGIN WIDGET_CONTROL, /HOURGLASS WIDGET_CONTROL, (*infoPtr).screenEntryTextY, GET_VALUE = angle (*infoPtr).universe_model -> Rotate, [0,1,0], angle[0] ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'TEXTZ' : BEGIN WIDGET_CONTROL, /HOURGLASS WIDGET_CONTROL, (*infoPtr).screenEntryTextZ, GET_VALUE = angle (*infoPtr).universe_model -> Rotate, [0,0,1], angle[0] ; polyLineRotator ??? ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END ; Transform (rotate or translation). uval_string EQ 'TRANS' : BEGIN (*infoPtr).zoomButtonStatus = 0 WIDGET_CONTROL, event.ID, GET_VALUE = val IF ( STRUPCASE(val) EQ 'TRANSLATE' ) THEN BEGIN ; Set translate mode. ; When going to Translate mode, turn off Free/X/Y/Z options. WIDGET_CONTROL, (*infoPtr).fxyzBase, SENSITIVE = 0 ; Set trackball to unconstrained for translation. (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0] (*infoPtr).translate = 1 ENDIF ELSE BEGIN ; Set rotate mode. ; When going to Rotate mode, turn on Free/X/Y/Z options. WIDGET_CONTROL, (*infoPtr).fxyzBase, SENSITIVE = 1 ; Reset trackball back to selected rotate axis. IF ( (*infoPtr).rotateAxis EQ 3 ) THEN BEGIN ; Axis = free (unconstrained) (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0] ENDIF ELSE BEGIN ; Axis = constrain to x, y, or z (*infoPtr).myTrackBall -> Reset, (*infoPtr).center, ((*infoPtr).center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis ENDELSE (*infoPtr).translate = 0 ENDELSE END uval_string EQ 'ZOOM' : BEGIN WIDGET_CONTROL, (*infoPtr).fxyzBase, SENSITIVE = 0 (*infoPtr).zoomButtonStatus = 1 END ; Set object orientation back to initial screen coordinates view, handy if object gets lost off screen. STRMID( uval_string, 0, 5 ) EQ 'SHOW_' : BEGIN WIDGET_CONTROL, /HOURGLASS ; Check if reset involves frustrums (EU, C1, C2, H1, H2 buttons). Load frustrums if necessary. IF (STRLEN( uval_string ) EQ 18) THEN BEGIN IF (STRMID( uval_string, 10, 8 ) EQ 'FRUSTRUM') THEN BEGIN IF ((*infoPtr).frustrums_are_loaded EQ 0) THEN BEGIN success = LOAD_FRUSTRUMS( infoPtr, ALL_STEPS=1 ) IF (success EQ 0) THEN BEGIN RETURN ENDIF FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].frustrumsModel (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].imagesModel ENDFOR (*infoPtr).frustrums_are_loaded = 1 WIDGET_CONTROL, (*infoPtr).fits_filenames_button, SENSITIVE = 1 (*infoPtr).hide_frustrums = 0 (*infoPtr).step_state[(*infoPtr).step].frustrumsModel -> SetProperty, HIDE = (*infoPtr).hide_frustrums WIDGET_CONTROL, (*infoPtr).frustrums_on_button, /SET_BUTTON ENDIF ENDIF ENDIF ; ; Reset and render polyLine. ; (*infoPtr).universe_model -> Reset ; ; length = (*infoPtr).axis_length ; ; Flip Z. ; (*infoPtr).axisTextObj -> SetProperty, LOCATIONS = [ [length*1.1,0.0,0.0], [0.0,length*1.1,0], [0.0,0.0,-length*1.1] ] ; ; ; Zero out the angle values in the text widgets. ; WIDGET_CONTROL, (*infoPtr).screenEntryTextX, SET_VALUE = STRTRIM(FLOAT(0),2) ; WIDGET_CONTROL, (*infoPtr).screenEntryTextY, SET_VALUE = STRTRIM(FLOAT(0),2) ; WIDGET_CONTROL, (*infoPtr).screenEntryTextZ, SET_VALUE = STRTRIM(FLOAT(0),2) ; ; ; Orient north up. ; (*infoPtr).universe_model -> Rotate, [1,0,0], 90 ; ; Constrain rotation to Y axis only (screen coordinates). ; (*infoPtr).rotateAxis = 1 center = [(*infoPtr).xdim,(*infoPtr).ydim]/2.0 IF ((*infoPtr).rotateAxis EQ 3) THEN BEGIN (*infoPtr).myTrackBall -> Reset, center, (center)[0] ENDIF ELSE BEGIN (*infoPtr).myTrackBall -> Reset, center, (center)[0], /CONSTRAIN, AXIS = (*infoPtr).rotateAxis ENDELSE CASE uval_string OF 'SHOW_CME' : zoom = (*infoPtr).cme_zoom 'SHOW_SPACECRAFT' : zoom = (*infoPtr).spacecraft_zoom 'SHOW_EUVI_FRUSTRUM' : zoom = 1.30 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,0] ) ; Use max of A or B. 'SHOW_EUVI_T_C1_FRUSTRUM' : zoom = 1.30 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,1] ) * 2 'SHOW_COR1_FRUSTRUM' : zoom = 1.30 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,1] ) 'SHOW_COR1_T_C2_FRUSTRUM' : zoom = 1.30 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,2] ) * 2 'SHOW_COR2_FRUSTRUM' : zoom = 1.20 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,2] ) 'SHOW_COR2_T_H1_FRUSTRUM' : zoom = 1.20 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,3] ) * 2 'SHOW_HI_1_FRUSTRUM' : zoom = 1.05 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,3] ) 'SHOW_HI_1_T_H2_FRUSTRUM' : zoom = 1.05 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,4] ) * 2 'SHOW_HI_2_FRUSTRUM' : zoom = 1.05 / MAX( (*infoPtr).step_state[(*infoPtr).step].max_heights_of_frustrums[*,4] ) ENDCASE ; In the case of "daily movies" where two instruments are being shown and when one of them is HI, then zoom in by 2 to focus on the transition area. ; This situation is easily detectable because one of the 2 instruments will be hi_1. IF ((WHERE((*infoPtr).only_show_two_inst_image EQ 'hi_1'))[0] GE 0) THEN BEGIN zoom = zoom * 2 ENDIF IF (zoom NE (*infoPtr).current_zoom) THEN BEGIN IF ((*infoPtr).movie_timer_delay NE 0.0) THEN BEGIN ; Handle this zoom in the movie loop area of the event handler. (*infoPtr).new_zoom = zoom (*infoPtr).zoom_step = 1 ENDIF ELSE BEGIN (*infoPtr).universe_model -> Reset (*infoPtr).universe_model -> Rotate, [1,0,0], 90 (*infoPtr).universe_model -> Scale, zoom, zoom, zoom ; Rotate around to last rotation point. FOR r = 0, (*infoPtr).cumulative_movie_rotation_increments - 1 DO BEGIN (*infoPtr).universe_model -> Rotate, [0,1,0], (*infoPtr).movie_increment_degrees ENDFOR (*infoPtr).current_zoom = zoom (*infoPtr).new_zoom = zoom ENDELSE ENDIF ELSE BEGIN (*infoPtr).universe_model -> Reset (*infoPtr).universe_model -> Rotate, [1,0,0], 90 (*infoPtr).universe_model -> Scale, zoom, zoom, zoom ; Rotate around to last rotation point. FOR r = 0, (*infoPtr).cumulative_movie_rotation_increments - 1 DO BEGIN (*infoPtr).universe_model -> Rotate, [0,1,0], (*infoPtr).movie_increment_degrees ENDFOR (*infoPtr).current_zoom = zoom (*infoPtr).new_zoom = zoom ENDELSE ;(*infoPtr).polyLineView -> Pan, 15.0, -5.0 ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'DEPTH_CUE_ON_BUTTON' : BEGIN WIDGET_CONTROL, /HOURGLASS (*infoPtr).polyLineView -> SetProperty, DEPTH_CUE = [-1,1] ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'DEPTH_CUE_OFF_BUTTON' : BEGIN WIDGET_CONTROL, /HOURGLASS (*infoPtr).polyLineView -> SetProperty, DEPTH_CUE = [0,0] ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'BACKGROUND_COLOR_BLACK_BUTTON' : BEGIN (*infoPtr).polyLineView -> SetProperty, COLOR = [0,0,0] FOR axisTextObj = 0, N_ELEMENTS( (*infoPtr).axisTextObjarr ) - 1 DO BEGIN (*infoPtr).axisTextObjarr[axisTextObj] -> SetProperty, COLOR = [255,255,255] ENDFOR (*infoPtr).earthTextObj -> SetProperty, COLOR = [255,255,255] (*infoPtr).thomsonsphereorb_a_color = [40,30,30] (*infoPtr).thomsonsphereorb_b_color = [30,30,40] (*infoPtr).thomsonsphereorb_brightenfactor = 3.0 ; Check to see if the thomsonsphereorb is already "Brigher" or "Dimmer", the reverse of what ihe Brighter/Dimmer buttons do. WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_button, GET_VALUE=brightness_value IF (brightness_value EQ 'Dimmer') THEN BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_a_color * (*infoPtr).thomsonsphereorb_brightenfactor (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_b_color * (*infoPtr).thomsonsphereorb_brightenfactor WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_Button, SET_VALUE = 'Dimmer' ENDIF ELSE BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_a_color (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_b_color WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_Button, SET_VALUE = 'Brighter' ENDELSE END uval_string EQ 'BACKGROUND_COLOR_WHITE_BUTTON' : BEGIN (*infoPtr).polyLineView -> SetProperty, COLOR = [255,255,255] FOR axisTextObj = 0, N_ELEMENTS( (*infoPtr).axisTextObjarr ) - 1 DO BEGIN (*infoPtr).axisTextObjarr[axisTextObj] -> SetProperty, COLOR = [0,0,0] ENDFOR (*infoPtr).earthTextObj -> SetProperty, COLOR = [0,0,0] (*infoPtr).thomsonsphereorb_a_color = [204,170,170] (*infoPtr).thomsonsphereorb_b_color = [170,170,204] (*infoPtr).thomsonsphereorb_brightenfactor = 1.25 ; Check to see if the thomsonsphereorb is already "Brigher" or "Dimmer", the reverse of what the Brighter/Dimmer buttons do. WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_button, GET_VALUE=brightness_value IF (brightness_value EQ 'Dimmer') THEN BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_a_color (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_b_color WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_Button, SET_VALUE = 'Brighter' ENDIF ELSE BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_a_color * (*infoPtr).thomsonsphereorb_brightenfactor (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_b_color * (*infoPtr).thomsonsphereorb_brightenfactor WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_Button, SET_VALUE = 'Dimmer' ENDELSE END uval_string EQ 'THOMSONSPHERE_ON_BUTTON' : BEGIN (*infoPtr).thomsonsphereModel -> SetProperty, HIDE = 0 ; Draw polyLine view to the window. redraw_polyLineView, infoPtr WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_button, SENSITIVE = 1 END uval_string EQ 'THOMSONSPHERE_OFF_BUTTON' : BEGIN (*infoPtr).thomsonsphereModel -> SetProperty, HIDE = 1 ; Draw polyLine view to the window. redraw_polyLineView, infoPtr WIDGET_CONTROL, (*infoPtr).thomsonsphere_brightness_button, SENSITIVE = 0 END uval_string EQ 'THOMSONSPHERE_BRIGHTNESS_BUTTON' : BEGIN WIDGET_CONTROL, event.id, GET_VALUE = thomsonsphere_bright_button_value CASE thomsonsphere_bright_button_value OF 'Brighter' : BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = FIX( (*infoPtr).thomsonsphereorb_a_color * (*infoPtr).thomsonsphereorb_brightenfactor ) (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = FIX( (*infoPtr).thomsonsphereorb_b_color * (*infoPtr).thomsonsphereorb_brightenfactor ) WIDGET_CONTROL, event.id, SET_VALUE = 'Dimmer' END 'Dimmer' : BEGIN (*infoPtr).thomsonsphereorb_a -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_a_color (*infoPtr).thomsonsphereorb_b -> SetProperty, COLOR = (*infoPtr).thomsonsphereorb_b_color WIDGET_CONTROL, event.id, SET_VALUE = 'Brighter' END ENDCASE ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'FRUSTRUMS_ON_BUTTON' : BEGIN IF ((*infoPtr).frustrums_are_loaded EQ 0) THEN BEGIN success = LOAD_FRUSTRUMS( infoPtr, ALL_STEPS=1 ) IF (success EQ 0) THEN BEGIN WIDGET_CONTROL, (*infoPtr).frustrums_off_button, /SET_BUTTON RETURN ENDIF FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].frustrumsModel (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].imagesModel ENDFOR (*infoPtr).frustrums_are_loaded = 1 WIDGET_CONTROL, (*infoPtr).fits_filenames_button, SENSITIVE = 1 ENDIF (*infoPtr).hide_frustrums = 0 (*infoPtr).step_state[(*infoPtr).step].frustrumsModel -> SetProperty, HIDE = (*infoPtr).hide_frustrums ;timing_seconds = SYSTIME( /SECONDS ) ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ;ddddd = DIALOG_MESSAGE( ['redrawing with frustrums:',STRING( SYSTIME( /SECONDS ) - timing_seconds )+' seconds'] ) END uval_string EQ 'FRUSTRUMS_OFF_BUTTON' : BEGIN FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).hide_frustrums = 1 IF OBJ_VALID( (*infoPtr).step_state[step].frustrumsModel ) THEN BEGIN (*infoPtr).step_state[step].frustrumsModel -> SetProperty, HIDE = (*infoPtr).hide_frustrums ENDIF ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'IMAGES_ON_BUTTON' : BEGIN ; Make sure frustrums are loaded. IF ((*infoPtr).frustrums_are_loaded EQ 0) THEN BEGIN success = LOAD_FRUSTRUMS( infoPtr, ALL_STEPS=1 ) IF (success EQ 0) THEN BEGIN WIDGET_CONTROL, (*infoPtr).images_off_button, SET_BUTTON = 1 RETURN ENDIF FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].frustrumsModel (*infoPtr).universe_model -> Add, (*infoPtr).step_state[step].imagesModel ENDFOR (*infoPtr).frustrums_are_loaded = 1 WIDGET_CONTROL, (*infoPtr).fits_filenames_button, SENSITIVE = 1 ENDIF ; Check if TIFF images have been loaded yet. If not then load them. ; (This is time-consuming so only do it when user requests that images be turned on.) IF ((*infoPtr).images_are_loaded EQ 0) THEN BEGIN FOR step = 0, (*infoPtr).nsteps - 1 DO BEGIN supply_struct = SUPPLY_IMAGES_TO_FRUSTRUMS_MODEL( $ (*infoPtr).step_state[step].date, $ (*infoPtr).step_state[step].time, $ *(*infoPtr).step_state[step].imageObjArr_ptr, $ *(*infoPtr).step_state[step].hdr_detector_ptr, $ *(*infoPtr).step_state[step].hdr_wavelnth_ptr, $ (*infoPtr).step_state, $ ; Needed to check if a tiff has already been used, if so then skip a step. step, $ (*infoPtr).nsteps, $ (*infoPtr).tlb, $ EXCLUDE_EUVI_TIFF = 1, $ SAVE_VRML = (*infoPtr).save_vrml, $ ONLY_SHOW_ONE_INST_IMAGE = (*infoPtr).only_show_one_inst_image, $ ONLY_SHOW_TWO_INST_IMAGE = (*infoPtr).only_show_two_inst_image ) (*infoPtr).images_are_loaded = supply_struct.success WIDGET_CONTROL, (*infoPtr).tiff_filenames_button, SENSITIVE = supply_struct.success IF (supply_struct.success EQ 0) THEN BEGIN WIDGET_CONTROL, (*infoPtr).images_off_Button, SET_BUTTON = 1 RETURN ENDIF (*infoPtr).step_state[step].tiff_filenames_ptr = PTR_NEW( supply_struct.tiff_filenames, /NO_COPY ) FOR sc=0,1 DO BEGIN FOR inst=0,4 DO BEGIN IF (STRMID( (*(*infoPtr).step_state[step].fits_filenames_ptr)[sc,inst], 5, 10) NE 'not loaded') THEN BEGIN ; Check that all TIFF images are loaded. Sometimes EUVI is purposely excluded. IF ((*(*infoPtr).step_state[step].tiff_filenames_ptr)[sc,inst] NE '') THEN BEGIN IF (STRMID((*(*infoPtr).step_state[step].tiff_filenames_ptr)[sc,inst],0,5,/REVERSE) EQ '.tiff') THEN BEGIN (*tiff_filenames_ptr)[sc,inst] = FILE_SEARCH( (*(*infoPtr).step_state[step].tiff_filenames_ptr)[sc,inst] ) ; dateTextObj = OBJ_NEW( 'IDLgrText', [(*infoPtr).step_state[step].date], $ ; LOCATIONS = [ [REFORM(step_state[step].earth_xyz)+[1,1,-1]] ], $ ; /ONGLASS, COLOR = 255 ) ENDIF ENDIF ENDIF ENDFOR ENDFOR ; Shoehorn date and time into filename strarr. (*(*infoPtr).step_state[step].tiff_filenames_ptr)[*,5] = [ '', 'MASTER TIME = '+(*infoPtr).step_state[step].date+'_'+(*infoPtr).step_state[step].time ] ENDFOR ENDIF (*infoPtr).hide_images = 0 (*infoPtr).step_state[(*infoPtr).step].imagesModel -> SetProperty, HIDE = (*infoPtr).hide_images ;timing_seconds = SYSTIME( /SECONDS ) ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ;ddddd = DIALOG_MESSAGE( ['redrawing with frustrums:',STRING( SYSTIME( /SECONDS ) - timing_seconds )+' seconds'] ) END uval_string EQ 'IMAGES_OFF_BUTTON' : BEGIN FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).hide_images = 1 IF OBJ_VALID( (*infoPtr).step_state[step].imagesModel ) THEN BEGIN (*infoPtr).step_state[step].imagesModel -> SetProperty, HIDE = (*infoPtr).hide_images ENDIF ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'FITS_FILENAMES' : BEGIN result = DIALOG_MESSAGE( *(*infoPtr).step_state[(*infoPtr).step].fits_filenames_ptr, /INFORMATION ) END uval_string EQ 'TIFF_FILENAMES' : BEGIN result = DIALOG_MESSAGE( *(*infoPtr).step_state[(*infoPtr).step].tiff_filenames_ptr, /INFORMATION ) END uval_string EQ 'CLEAR_DISK_ON_BUTTON' : BEGIN ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'CLEAR_DISK_OFF_BUTTON' : BEGIN ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'LINE_THICKNESS_SLIDER' : BEGIN WIDGET_CONTROL, (*infoPtr).line_thickness_slider, GET_VALUE = val IF ((*infoPtr).xyz_filename NE '') THEN BEGIN FOR line = 0ULL, N_ELEMENTS((*infoPtr).polyLineObjArr) - 1 DO BEGIN ((*infoPtr).polyLineObjArr)[line] -> SetProperty, THICK = val ENDFOR ENDIF FOR line = 0ULL, N_ELEMENTS((*infoPtr).referenceLineObjArr) - 1 DO BEGIN ((*infoPtr).referenceLineObjArr)[line] -> SetProperty, THICK = val ENDFOR IF (OBJ_VALID((*infoPtr).xyz_mean_line)) THEN BEGIN (*infoPtr).xyz_mean_line -> SetProperty, THICK = val ENDIF ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'XYZ_MEAN_LINE_ON_BUTTON' : BEGIN (*infoPtr).xyz_mean_line -> SetProperty, HIDE = 0 ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'XYZ_MEAN_LINE_OFF_BUTTON' : BEGIN (*infoPtr).xyz_mean_line -> SetProperty, HIDE = 1 ; Draw polyLine view to the window. redraw_polyLineView, infoPtr END uval_string EQ 'MOVIE_ONOFF_BUTTON' : BEGIN WIDGET_CONTROL, (*infoPtr).movie_onoff_button, GET_VALUE=val CASE (val) OF 'Start' : BEGIN ; IF (*infoPtr).movie_increment_degrees EQ 0 THEN BEGIN ; (*infoPtr).movie_increment_degrees = 1 ;3 ; WIDGET_CONTROL, (*infoPtr).movie_increment_slider, SET_VALUE = (*infoPtr).movie_increment_degrees ; ENDIF (*infoPtr).movie_timer_delay = 1/60. IF OBJ_VALID((*infoPtr).objectWindow) THEN BEGIN WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay ENDIF WIDGET_CONTROL, event.id, SET_VALUE = ' Stop' END ' Stop' : BEGIN (*infoPtr).movie_timer_delay = 0.0 WIDGET_CONTROL, event.id, SET_VALUE = 'Start' END ENDCASE END uval_string EQ 'MOVIE_INCREMENT_SLIDER' : BEGIN WIDGET_CONTROL, event.id, GET_VALUE = value ; Add 10 to account for slider range being -10 to 10. (*infoPtr).movie_increment_degrees = (*infoPtr).movie_degrees[value[0]+10] WIDGET_CONTROL, (*infoPtr).movie_increment_label, SET_VALUE = (*infoPtr).movie_increment_degrees + ' deg' END uval_string EQ 'ROTATE_AROUND_ORIGIN' : BEGIN result=WIDGET_EVENT( (*infoPtr).screenCoordsResetButton, /NOWAIT ) goto,skip (*infoPtr).polyLineModel -> GetProperty, TRANSFORM = t print,'before',t,t[3,0:2] IF (t[3,1] EQ -(*infoPtr).xyz_mean[1]) THEN BEGIN ; First un-rotate. (*infoPtr).polyLineModel -> Rotate, [1,0,0], -90 (*infoPtr).sunModel -> Rotate, [1,0,0], -90 (*infoPtr).referenceModel -> Rotate, [1,0,0], -90 (*infoPtr).axisModel -> Rotate, [1,0,0], -90 (*infoPtr).thomsonsphereModel -> Rotate, [1,0,0], -90 FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Rotate, [1,0,0], -90 (*infoPtr).step_state[step].imagesModel -> Rotate, [1,0,0], -90 ENDFOR ; Second, translate. (*infoPtr).polyLineModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] (*infoPtr).sunModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] (*infoPtr).referenceModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] (*infoPtr).axisModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] (*infoPtr).thomsonsphereModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] (*infoPtr).step_state[step].imagesModel -> Translate, (*infoPtr).xyz_mean[0], (*infoPtr).xyz_mean[1], (*infoPtr).xyz_mean[2] ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ; Third, re-rotate. (*infoPtr).polyLineModel -> Rotate, [1,0,0], 90 (*infoPtr).sunModel -> Rotate, [1,0,0], 90 (*infoPtr).referenceModel -> Rotate, [1,0,0], 90 (*infoPtr).axisModel -> Rotate, [1,0,0], 90 (*infoPtr).thomsonsphereModel -> Rotate, [1,0,0], 90 FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Rotate, [1,0,0], 90 (*infoPtr).step_state[step].imagesModel -> Rotate, [1,0,0], 90 ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ENDIF (*infoPtr).polyLineModel -> GetProperty, TRANSFORM = t print,'after',t,t[3,0:2] skip: END uval_string EQ 'ROTATE_AROUND_CENTROID' : BEGIN (*infoPtr).polyLineModel -> GetProperty, TRANSFORM = t print,'before',t,t[3,0:2],'xyz_mean = ',(*infoPtr).xyz_mean IF ((t[3,0] EQ 0) AND (t[3,1] EQ 0) AND (t[3,2] EQ 0)) THEN BEGIN result=WIDGET_EVENT( (*infoPtr).screenCoordsResetButton, /NOWAIT ) ; First un-rotate. (*infoPtr).polyLineModel -> Rotate, [1,0,0], -90 (*infoPtr).sunModel -> Rotate, [1,0,0], -90 (*infoPtr).referenceModel -> Rotate, [1,0,0], -90 (*infoPtr).axisModel -> Rotate, [1,0,0], -90 (*infoPtr).thomsonsphereModel -> Rotate, [1,0,0], -90 FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Rotate, [1,0,0], -90 (*infoPtr).step_state[step].imagesModel -> Rotate, [1,0,0], -90 ENDFOR ; Second, translate. (*infoPtr).polyLineModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] (*infoPtr).sunModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] (*infoPtr).referenceModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] (*infoPtr).axisModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] (*infoPtr).thomsonsphereModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] (*infoPtr).step_state[step].imagesModel -> Translate, -(*infoPtr).xyz_mean[0], -(*infoPtr).xyz_mean[1], -(*infoPtr).xyz_mean[2] ENDFOR ; Third, re-rotate. (*infoPtr).polyLineModel -> Rotate, [1,0,0], 90 (*infoPtr).sunModel -> Rotate, [1,0,0], 90 (*infoPtr).referenceModel -> Rotate, [1,0,0], 90 (*infoPtr).axisModel -> Rotate, [1,0,0], 90 (*infoPtr).thomsonsphereModel -> Rotate, [1,0,0], 90 FOR step=0,(*infoPtr).nsteps-1 DO BEGIN (*infoPtr).step_state[step].frustrumsModel -> Rotate, [1,0,0], 90 (*infoPtr).step_state[step].imagesModel -> Rotate, [1,0,0], 90 ENDFOR ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ENDIF (*infoPtr).polyLineModel -> GetProperty, TRANSFORM = t print,'after',t,t[3,0:2],'xyz_mean = ',(*infoPtr).xyz_mean END uval_string EQ 'MOVIE_ON_BUTTON' : BEGIN (*infoPtr).moviesave_counter = 1 ; (*infoPtr).movie_increment_degrees = 1 (*infoPtr).movie_timer_delay = 1/60. IF OBJ_VALID((*infoPtr).objectWindow) THEN BEGIN WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay ENDIF END uval_string EQ 'MOVIE_OFF_BUTTON' : BEGIN (*infoPtr).moviesave_counter = 0 ; (*infoPtr).movie_increment_degrees = 1 (*infoPtr).movie_timer_delay = 1/60. WIDGET_CONTROL, (*infoPtr).moviesave_frame_label, SET_VALUE = '' IF OBJ_VALID((*infoPtr).objectWindow) THEN BEGIN WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay ENDIF END uval_string EQ 'TIFF' : BEGIN fileName = DIALOG_PICKFILE() IF filename NE '' THEN BEGIN IF (FILE_SEARCH( filename ))[0] THEN BEGIN overwrite = DIALOG_MESSAGE( 'File exists, overwrite?', /QUESTION ) IF STRUPCASE( overwrite ) EQ 'YES' THEN BEGIN mssg = [ 'LAST CHANCE: OVERWRITE THIS FILE?','',filename ] to_be_certain = DIALOG_MESSAGE( mssg, /QUESTION ) IF STRUPCASE( to_be_certain ) EQ 'YES' THEN BEGIN ok_to_write_image_file = 1 ENDIF ELSE BEGIN ok_to_write_image_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_image_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_image_file = 1 ENDELSE IF ( ok_to_write_image_file ) THEN BEGIN WIDGET_CONTROL, /HOURGLASS imageObject = (*infoPtr).objectWindow -> READ() imageObject -> GetProperty, DATA = imageData WRITE_TIFF, fileName, REVERSE(imageData,3), /COMPRESS END ENDIF END uval_string EQ 'VRML' : BEGIN IF ((*infoPtr).save_vrml EQ 1) THEN BEGIN vrml_dir = '/ra/secchi2/vrml/'+STRMID((*infoPtr).timesteps[0],0,8) SPAWN,'mkdir -p '+vrml_dir fileName = vrml_dir+'/'+(*infoPtr).timesteps[0]+'.vrml' ENDIF ELSE BEGIN fileName = DIALOG_PICKFILE() ENDELSE IF filename NE '' THEN BEGIN IF (FILE_SEARCH( filename ))[0] THEN BEGIN IF ((*infoPtr).save_vrml EQ 1) THEN BEGIN PRINT,'File exists: ',fileName,' Please move or remove and try again.' RETURN ENDIF overwrite = DIALOG_MESSAGE( 'File exists, overwrite?', /QUESTION ) IF STRUPCASE( overwrite ) EQ 'YES' THEN BEGIN mssg = [ 'LAST CHANCE: OVERWRITE THIS FILE?','',filename ] to_be_certain = DIALOG_MESSAGE( mssg, /QUESTION ) IF STRUPCASE( to_be_certain ) EQ 'YES' THEN BEGIN ok_to_write_VRML_file = 1 ENDIF ELSE BEGIN ok_to_write_VRML_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_VRML_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_VRML_file = 1 ENDELSE IF ( ok_to_write_VRML_file ) THEN BEGIN (*infoPtr).myVRML -> SetProperty, FILENAME = filename (*infoPtr).myVRML -> Draw, (*infoPtr).polyLineView ENDIF ENDIF IF ((*infoPtr).save_vrml EQ 1) THEN BEGIN print,'VRML2 filename: '+fileName ENDIF END uval_string EQ 'WAVEFRONT' : BEGIN fileName = DIALOG_PICKFILE() IF filename NE '' THEN BEGIN IF (FILE_SEARCH( filename ))[0] THEN BEGIN overwrite = DIALOG_MESSAGE( 'File exists, overwrite?', /QUESTION ) IF STRUPCASE( overwrite ) EQ 'YES' THEN BEGIN mssg = [ 'LAST CHANCE: OVERWRITE THIS FILE?','',filename ] to_be_certain = DIALOG_MESSAGE( mssg, /QUESTION ) IF STRUPCASE( to_be_certain ) EQ 'YES' THEN BEGIN ok_to_write_WAVEFRONT_file = 1 ENDIF ELSE BEGIN ok_to_write_WAVEFRONT_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_WAVEFRONT_file = 0 ENDELSE ENDIF ELSE BEGIN ok_to_write_WAVEFRONT_file = 1 ENDELSE IF ( ok_to_write_WAVEFRONT_file ) THEN BEGIN ;WRITE_WAVE, File, Array [, /BIN] [, DATANAME=string] [, MESHNAME=string] [, /NOMESHDEF] [, /VECTOR] (*infoPtr).step_state[0].frustrumsModel->GetProperty,data=model_data help,model_data ; WRITE_WAVE, filename, Array, DATANAME=string, /VECTOR ENDIF ENDIF END uval_string EQ 'QUIT' : BEGIN IF ((*infoPtr).save_vrml EQ 1) THEN BEGIN yesno = 'YES' ENDIF ELSE BEGIN yesno = DIALOG_MESSAGE( 'Are you sure you want to quit line3d?', /QUESTION ) ENDELSE IF ( STRUPCASE( yesno ) EQ 'YES' ) THEN BEGIN ; Depointer destroys all objects referred to by the infoPtr structure. result = DEPOINTER( infoPtr ) WIDGET_CONTROL, event.TOP, /DESTROY RETURN ENDIF END uval_string EQ 'HELP' : BEGIN ddddd=DIALOG_MESSAGE(['Line3d is covered in the Sunloop User Guide:','','$SSW/stereo/secchi/idl/display/sunloop/sunloop_user_guide.pdf'],/INFORMATION) END ELSE : BEGIN ; Just to avoid crash if no CASE match is found. END ENDCASE END FUNCTION build_axis_model, length ; Line color alternates along lengths of solar radii. thick = 3 color1 = 100 color2 = 50 length = FLOAT( length ) axisModel = OBJ_NEW( 'IDLgrModel' ) axisTextObjarr = OBJARR(4) ; Radial line to start of polyline. FOR m = 0ULL, length - 1 DO BEGIN mm = FLOAT( m ) ; Integer intervals. axisObj_x = OBJ_NEW( 'IDLgrPolyline', [length*(mm/length),length*((mm+1)/length)], [0,0], [-0,-0], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisObj_y = OBJ_NEW( 'IDLgrPolyline', [0,0], [length*(mm/length),length*((mm+1)/length)], [-0,-0], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisObj_z = OBJ_NEW( 'IDLgrPolyline', [0,0], [0,0], [-length*(mm/length),-length*((mm+1)/length)], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisModel -> Add, axisObj_x axisModel -> Add, axisObj_y axisModel -> Add, axisObj_z CASE 1 OF length LE 5 : do_a_number = ((m MOD 1) EQ 0) length LE 10 : do_a_number = ((m MOD 2) EQ 0) length LE 25 : do_a_number = ((m MOD 5) EQ 0) length LE 50 : do_a_number = ((m MOD 10) EQ 0) length LE 100 : do_a_number = ((m MOD 20) EQ 0) length LE 250 : do_a_number = ((m MOD 50) EQ 0) length LE 500 : do_a_number = ((m MOD 100) EQ 0) length LE 1000 : do_a_number = ((m MOD 200) EQ 0) length LE 2500 : do_a_number = ((m MOD 500) EQ 0) length LE 5000 : do_a_number = ((m MOD 1000) EQ 0) length LE 10000 : do_a_number = ((m MOD 2000) EQ 0) length LE 25000 : do_a_number = ((m MOD 5000) EQ 0) length LE 50000 : do_a_number = ((m MOD 10000) EQ 0) length LE 100000 : do_a_number = ((m MOD 20000) EQ 0) ELSE : do_a_number = 0 ENDCASE IF (do_a_number EQ 1) THEN BEGIN axisTextObjarr[0] = OBJ_NEW( 'IDLgrText', [STRTRIM(m,2)], LOCATIONS = [mm,0.0,-0.0], /ONGLASS, ALIGNMENT = 0.5, VERTICAL_ALIGNMENT = 0.0, COLOR = 255 ) ; axisModel -> Add, axisTextObjarr[0] axisTextObjarr[1] = OBJ_NEW( 'IDLgrText', [STRTRIM(m,2)], LOCATIONS = [0.0,mm,-0.0], /ONGLASS, ALIGNMENT = 0.5, VERTICAL_ALIGNMENT = 0.0, COLOR = 255 ) ; axisModel -> Add, axisTextObjarr[1] axisTextObjarr[2] = OBJ_NEW( 'IDLgrText', [STRTRIM(m,2)], LOCATIONS = [0.0,0.0,-mm], /ONGLASS, ALIGNMENT = 0.0, VERTICAL_ALIGNMENT = 0.0, COLOR = 255 ) ; axisModel -> Add, axisTextObjarr[2] ENDIF ENDFOR ; Decimal remainder. axisObj_x = OBJ_NEW( 'IDLgrPolyline', [length*(LONG( length )/length),length], [0,0], [0,0], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisObj_y = OBJ_NEW( 'IDLgrPolyline', [0,0], [length*(LONG( length )/length),length], [0,0], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisObj_z = OBJ_NEW( 'IDLgrPolyline', [0,0], [0,0], [-length*(LONG( length )/length),-length], THICK = thick, COLOR = color1 + (color2*(m MOD 2)) ) axisModel -> Add, axisObj_x axisModel -> Add, axisObj_y axisModel -> Add, axisObj_z ; Flip Z. axisTextObjarr[3] = OBJ_NEW( 'IDLgrText', ['+X','+Y','+Z'], LOCATIONS = [ [length*1.1,0.0,0.0], [0.0,length*1.1,0], [0.0,0.0,-length*1.1] ], $ /ONGLASS, ALIGNMENT = 0.5, VERTICAL_ALIGNMENT = 0.5, COLOR = 255 ) axisModel -> Add, axisTextObjarr axis_struct = { axisModel:axisModel, axisTextObjarr:axisTextObjarr } RETURN, axis_struct END PRO line3d, $ xyz_data, $ xyz_filename, $ calling_tlb, $ XYZ_MEAN = xyz_mean, $ TIMESTEPS = timesteps, $ SYSTEM = system, $ SAVE_VRML = save_vrml, $ ONLY_SHOW_ONE_INST_IMAGE = only_show_one_inst_image, $ ONLY_SHOW_TWO_INST_IMAGE = only_show_two_inst_image IF (SIZE(xyz_filename,/TYPE) EQ 0) THEN xyz_filename = '' IF (SIZE(xyz_mean,/TYPE) EQ 0) THEN xyz_mean = -1 IF (SIZE(timesteps,/TYPE) EQ 0) THEN timesteps = -1 IF (SIZE(save_vrml,/TYPE) EQ 0) THEN save_vrml = 0 IF (SIZE(only_show_one_inst_image, /TYPE) EQ 0) THEN only_show_one_inst_image = '' ELSE only_show_one_inst_image = STRLOWCASE(only_show_one_inst_image) IF (SIZE(only_show_two_inst_image, /TYPE) EQ 0) THEN only_show_two_inst_image = '' ELSE only_show_two_inst_image = STRLOWCASE(only_show_two_inst_image) ; Error check. IF (only_show_one_inst_image NE '') AND (only_show_two_inst_image[0] NE '') THEN BEGIN ddddd=DIALOG_MESSAGE( 'Specify just one of these parameters: ONLY_SHOW_ONE_INST_IMAGE or ONLY_SHOW_TWO_INST_IMAGE.' ) RETURN ENDIF ; Error check. IF (only_show_two_inst_image[0] NE '') THEN BEGIN bad_pair = 0 CASE only_show_two_inst_image[0] OF 'euvi' : IF (only_show_two_inst_image[1] NE 'cor1') THEN bad_pair = 1 'cor1' : IF (only_show_two_inst_image[1] NE 'cor2') THEN bad_pair = 1 'cor2' : IF (only_show_two_inst_image[1] NE 'hi_1') THEN bad_pair = 1 'hi_1' : IF (only_show_two_inst_image[1] NE 'hi_2') THEN bad_pair = 1 ELSE : bad_pair = 1 ENDCASE IF (only_show_two_inst_image[1] EQ 'euvi') THEN bad_pair = 1 IF (only_show_two_inst_image[0] EQ 'hi_2') THEN bad_pair = 1 IF (bad_pair EQ 1) THEN BEGIN ddddd=DIALOG_MESSAGE([ $ 'Problem with parameter ONLY_SHOW_TWO_INST_IMAGE', $ 'Suggested solutions are:', $ '', $ 'Must contain adjacent image types, such as cor2 and hi_1.', $ 'The first element of pair must be the inner instrument, thus euvi cannot be the second and hi_2 cannot be the first.', $ 'Valid values are [''euvi'',''cor1''], [''cor1'',''cor2''], [''cor2'',''hi_1''] or [''hi_1'',''hi_2'']. Case does not matter.'] ) RETURN ENDIF ENDIF ; Master container for geometry purposes (rotation, zoom, etc.) universe_model = OBJ_NEW( 'IDLgrModel' ) nsteps = N_ELEMENTS( timesteps ) step_state = REPLICATE( { $ date : '', $ time : '', $ fits_filenames_ptr : PTR_NEW(), $ hdr_detector_ptr : PTR_NEW(), $ hdr_wavelnth_ptr : PTR_NEW(), $ tiff_filenames_ptr : PTR_NEW(), $ max_heights_of_frustrums : DBLARR( 2, 5 ), $ frustrumsModel : OBJ_NEW(), $ imagesModel : OBJ_NEW(), $ imageObjArr_ptr : PTR_NEW(), $ earth_xyz : DBLARR( 3 ), $ stereoa_xyz : DBLARR( 3 ), $ stereob_xyz : DBLARR( 3 ), $ mercury_xyz : DBLARR( 3 ), $ venus_xyz : DBLARR( 3 ), $ mars_xyz : DBLARR( 3 ), $ jupiter_xyz : DBLARR( 3 ), $ saturn_xyz : DBLARR( 3 ) }, nsteps ) ; IF (xyz_filename NE '') THEN BEGIN ; ; Get date,time from filename. ; ascii = READ_ASCII( xyz_filename, DATA_START=12 ) ; metadata_start = (WHERE( (ascii.(0))[0,*] EQ -9999 ))[0] ; ascii = '' ; OPENR, lun, xyz_filename, /GET_LUN ; FOR line = 0, 12+metadata_start+3 DO BEGIN ; READF, lun, ascii ; IF (line EQ 12+metadata_start+3) THEN BEGIN ; left_filename = FILE_BASENAME((STRSPLIT(ascii,' ',/EXTRACT))[0]) ; ENDIF ; ENDFOR ; FREE_LUN, lun ; ENDIF FOR step=0,nsteps-1 DO BEGIN step_state[step].date = (STRSPLIT( timesteps[step], '_', /EXTRACT ))[0] step_state[step].time = (STRSPLIT( timesteps[step], '_', /EXTRACT ))[1] ENDFOR ; Compile from RSI IDL library. RESOLVE_ROUTINE,'idlexrotator__define',/EITHER ;$IDL_PATH/examples/visual/utility/idlexrotator__define.pro RESOLVE_ROUTINE,'trackball__define',/EITHER ;$IDL_PATH/lib/trackball__define.pro ; Calculate xdim as a function of screen size and a buffer area. Window must be square, so ydim=xdim. available_wdth = (GET_SCREEN_SIZE())[0] * 0.9 available_hght = (GET_SCREEN_SIZE())[1] * 0.9 maxSizeAllowed = 1200 xdim = available_wdth < available_hght < maxSizeAllowed ydim = xdim tlb = WIDGET_BASE( /COLUMN, TITLE = 'line3d', GROUP_LEADER = calling_tlb ) coordinatesBase = WIDGET_BASE( tlb, /COLUMN, /FRAME ) coordinatesLabel = WIDGET_LABEL( coordinatesBase, VALUE = 'MOTION CONTROLS:' ) motionCoordsChoiceBase = WIDGET_BASE( coordinatesBase, /EXCLUSIVE, /ROW ) screenCoordinatesButton = WIDGET_BUTTON( motionCoordsChoiceBase, VALUE = 'SCREEN COORDINATES', UVALUE = 'SCREENCOORD' ) dataCoordinatesButton = WIDGET_BUTTON( motionCoordsChoiceBase, VALUE = 'DATA COORDINATES', UVALUE = 'DATACOORD' ) motionBase = WIDGET_BASE( coordinatesBase, /FRAME ) dataCoordinatesBase = WIDGET_BASE( motionBase, /COLUMN ) dataMotionLabel = WIDGET_LABEL( dataCoordinatesBase, VALUE = 'DATA COORDINATES' ) dataControlsBase = WIDGET_BASE( dataCoordinatesBase, /ROW ) dataRotateBase = WIDGET_BASE( dataControlsBase, /EXCLUSIVE ) dataRotateXButton = WIDGET_BUTTON( dataRotateBase, VALUE = 'ROTATE DATA X', UVALUE = 'DATAX' ) dataRotateYButton = WIDGET_BUTTON( dataRotateBase, VALUE = 'ROTATE DATA Y', UVALUE = 'DATAY' ) dataRotateZButton = WIDGET_BUTTON( dataRotateBase, VALUE = 'ROTATE DATA Z', UVALUE = 'DATAZ' ) WIDGET_CONTROL, dataRotateXButton, /SET_BUTTON dataCoordsResetButton = WIDGET_BUTTON( dataCoordinatesBase, VALUE = 'Data Coords Reset', UVALUE = 'DATACOORDSRESET' ) screenCoordinatesBase = WIDGET_BASE( motionBase, /COLUMN ) screenMotionLabel = WIDGET_LABEL( screenCoordinatesBase, VALUE = 'SCREEN COORDINATES' ) fxyzBase = WIDGET_BASE( screenCoordinatesBase, /EXCLUSIVE, /ROW ) screenRotateFButton = WIDGET_BUTTON( fxyzBase, VALUE = 'Free', UVALUE = 'FREE' ) screenRotateXButton = WIDGET_BUTTON( fxyzBase, VALUE = 'X', UVALUE = 'SCREENX' ) screenRotateYButton = WIDGET_BUTTON( fxyzBase, VALUE = 'Y', UVALUE = 'SCREENY' ) screenRotateZButton = WIDGET_BUTTON( fxyzBase, VALUE = 'Z', UVALUE = 'SCREENZ' ) transBase = WIDGET_BASE( screenCoordinatesBase, /EXCLUSIVE ) transformButton = WIDGET_BUTTON( transBase, VALUE = 'Rotate', UVALUE = 'TRANS' ) translateButton = WIDGET_BUTTON( transBase, VALUE = 'Translate', UVALUE = 'TRANS' ) zoomButton = WIDGET_BUTTON( transBase, VALUE = 'Zoom', UVALUE = 'ZOOM' ) ;;;;;;;;zoomLabel = WIDGET_LABEL( tlb, VALUE = 'Zoom = 1.0' ) screenEntryBase = WIDGET_BASE( screenCoordinatesBase, /COLUMN ) JunkBase0 = WIDGET_BASE( screenEntryBase, /ROW ) JunkLabel0 = WIDGET_LABEL( JunkBase0, VALUE = 'Rotate X:' ) screenEntryTextX = WIDGET_TEXT( JunkBase0, Value = STRTRIM(FLOAT(0),2), XSIZE = 6, /EDITABLE, UVALUE = 'TEXTX' ) JunkBase1 = WIDGET_BASE( screenEntryBase, /ROW ) JunkLabel1 = WIDGET_LABEL( JunkBase1, VALUE = 'Rotate Y:' ) screenEntryTextY = WIDGET_TEXT( JunkBase1, Value = STRTRIM(FLOAT(0),2), XSIZE = 6, /EDITABLE, UVALUE = 'TEXTY' ) JunkBase2 = WIDGET_BASE( screenEntryBase, /ROW ) JunkLabel2 = WIDGET_LABEL( JunkBase2, VALUE = 'Rotate Z:' ) screenEntryTextZ = WIDGET_TEXT( JunkBase2, Value = STRTRIM(FLOAT(0),2), XSIZE = 6, /EDITABLE, UVALUE = 'TEXTZ' ) showBase = WIDGET_BASE( screenCoordinatesBase, /ROW ) showLabel = WIDGET_LABEL( showBase, VALUE = 'Reset to View of: ' ) screenCoordsResetButton = WIDGET_BUTTON( showBase, VALUE = 'CME feature', UVALUE = 'SHOW_CME' ) showspacecraftButton = WIDGET_BUTTON( showBase, VALUE = 'Spacecraft', UVALUE = 'SHOW_SPACECRAFT' ) ; Slight misnomer. The widget "showFrustrumsBase" is for RESETTING THE VIEW to the extent that the frustrum screens occupy in 3D space, similar to "showspacecraftButton". showFrustrumsBase = WIDGET_BASE( screenCoordinatesBase, /ROW ) showEUVIfrustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 'EUVI', UVALUE = 'SHOW_EUVI_FRUSTRUM' ) showEUVI_T_C1frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 't', UVALUE = 'SHOW_EUVI_T_C1_FRUSTRUM' ) showCOR1frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 'COR1', UVALUE = 'SHOW_COR1_FRUSTRUM' ) showCOR1_T_C2frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 't', UVALUE = 'SHOW_COR1_T_C2_FRUSTRUM' ) showCOR2frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 'COR2', UVALUE = 'SHOW_COR2_FRUSTRUM' ) showCOR2_T_H1frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 't', UVALUE = 'SHOW_COR2_T_H1_FRUSTRUM' ) showHI_1frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 'HI_1', UVALUE = 'SHOW_HI_1_FRUSTRUM' ) showHI_1_T_H2frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 't', UVALUE = 'SHOW_HI_1_T_H2_FRUSTRUM' ) showHI_2frustrumButton = WIDGET_BUTTON( showFrustrumsBase, VALUE = 'HI_2', UVALUE = 'SHOW_HI_2_FRUSTRUM' ) options_base = WIDGET_BASE( tlb, /COLUMN, /FRAME ) ; depth_cue_Base = WIDGET_BASE( options_base, /ROW ) ; depth_cue_Label = WIDGET_LABEL( depth_cue_Base, VALUE = 'Depth Cue:' ) ; depth_cue_RadioButtonBase = WIDGET_BASE( depth_cue_Base, /ROW, /EXCLUSIVE ) ; depth_cue_on_Button = WIDGET_BUTTON( depth_cue_RadioButtonBase, VALUE = 'On', UVALUE = 'DEPTH_CUE_ON_BUTTON' ) ; depth_cue_off_Button = WIDGET_BUTTON( depth_cue_RadioButtonBase, VALUE = 'Off', UVALUE = 'DEPTH_CUE_OFF_BUTTON' ) thomsonsphere_Base = WIDGET_BASE( options_base, /ROW ) thomsonsphere_Label = WIDGET_LABEL( thomsonsphere_Base, VALUE = 'Thomson Spheres:' ) thomsonsphere_RadioButtonBase = WIDGET_BASE( thomsonsphere_Base, /ROW, /EXCLUSIVE ) thomsonsphere_on_Button = WIDGET_BUTTON( thomsonsphere_RadioButtonBase, VALUE = 'On', UVALUE = 'THOMSONSPHERE_ON_BUTTON' ) thomsonsphere_off_Button = WIDGET_BUTTON( thomsonsphere_RadioButtonBase, VALUE = 'Off', UVALUE = 'THOMSONSPHERE_OFF_BUTTON' ) thomsonsphere_brightness_Button = WIDGET_BUTTON( thomsonsphere_Base, VALUE = 'Brighter', UVALUE = 'THOMSONSPHERE_BRIGHTNESS_BUTTON' ) WIDGET_CONTROL, thomsonsphere_brightness_button, SENSITIVE = 0 frustrums_Base = WIDGET_BASE( options_base, /ROW ) frustrums_Label = WIDGET_LABEL( frustrums_Base, VALUE = 'Frustrum Lines: ' ) frustrums_RadioButtonBase = WIDGET_BASE( frustrums_Base, /ROW, /EXCLUSIVE ) frustrums_on_Button = WIDGET_BUTTON( frustrums_RadioButtonBase, VALUE = 'On', UVALUE = 'FRUSTRUMS_ON_BUTTON' ) frustrums_off_Button = WIDGET_BUTTON( frustrums_RadioButtonBase, VALUE = 'Off', UVALUE = 'FRUSTRUMS_OFF_BUTTON' ) fits_filenames_button = WIDGET_BUTTON( frustrums_Base, VALUE = 'FITS List', UVALUE = 'FITS_FILENAMES', SENSITIVE = 0 ) images_Base = WIDGET_BASE( options_base, /ROW ) images_Label = WIDGET_LABEL( images_Base, VALUE = 'Images: ' ) images_RadioButtonBase = WIDGET_BASE( images_Base, /ROW, /EXCLUSIVE ) images_on_Button = WIDGET_BUTTON( images_RadioButtonBase, VALUE = 'On', UVALUE = 'IMAGES_ON_BUTTON' ) images_off_Button = WIDGET_BUTTON( images_RadioButtonBase, VALUE = 'Off', UVALUE = 'IMAGES_OFF_BUTTON' ) tiff_filenames_button = WIDGET_BUTTON( images_Base, VALUE = 'TIFF List', UVALUE = 'TIFF_FILENAMES', SENSITIVE = 0 ) ; clear_disk_Base = WIDGET_BASE( options_base, /ROW ) ; clear_disk_Label = WIDGET_LABEL( clear_disk_base, VALUE = 'Solar Disk:' ) ; clear_disk_RadioButtonBase = WIDGET_BASE( clear_disk_base, /ROW, /EXCLUSIVE ) ; clear_disk_on_Button = WIDGET_BUTTON( clear_disk_RadioButtonBase, VALUE = 'Transparent', UVALUE = 'CLEAR_DISK_ON_BUTTON' ) ; clear_disk_off_Button = WIDGET_BUTTON( clear_disk_RadioButtonBase, VALUE = 'Opaque', UVALUE = 'CLEAR_DISK_OFF_BUTTON' ) background_color_Base = WIDGET_BASE( options_base, /ROW ) background_color_Label = WIDGET_LABEL( background_color_Base, VALUE = 'Background color:' ) background_color_RadioButtonBase= WIDGET_BASE( background_color_Base, /ROW, /EXCLUSIVE ) background_color_white_Button = WIDGET_BUTTON( background_color_RadioButtonBase, VALUE = 'white', UVALUE = 'BACKGROUND_COLOR_WHITE_BUTTON' ) background_color_black_Button = WIDGET_BUTTON( background_color_RadioButtonBase, VALUE = 'black', UVALUE = 'BACKGROUND_COLOR_BLACK_BUTTON' ) WIDGET_CONTROL, background_color_black_Button, /SET_BUTTON IF (N_ELEMENTS(xyz_mean[*]) EQ 3) THEN BEGIN xyz_mean_line_base = WIDGET_BASE( options_base, /ROW ) xyz_mean_line_label = WIDGET_LABEL( xyz_mean_line_base, VALUE = 'xyz mean line: ' ) xyz_mean_line_RadioButtonBase = WIDGET_BASE( xyz_mean_line_base, /ROW, /EXCLUSIVE ) xyz_mean_line_on_Button = WIDGET_BUTTON( xyz_mean_line_RadioButtonBase, VALUE = 'On', UVALUE = 'XYZ_MEAN_LINE_ON_BUTTON' ) xyz_mean_line_off_Button = WIDGET_BUTTON( xyz_mean_line_RadioButtonBase, VALUE = 'Off', UVALUE = 'XYZ_MEAN_LINE_OFF_BUTTON' ) WIDGET_CONTROL, xyz_mean_line_off_Button, /SET_BUTTON ENDIF line_thickness_base = WIDGET_BASE( options_base, /ROW ) line_thickness_label = WIDGET_LABEL( line_thickness_base, VALUE = 'Line Thickness:' ) line_thickness_slider = WIDGET_SLIDER( line_thickness_base, VALUE = 1, MINIMUM = 1, MAXIMUM = 10, UVALUE = 'LINE_THICKNESS_SLIDER', /DRAG ) movie_base = WIDGET_BASE( options_base, /ROW ) movie_Label = WIDGET_LABEL( movie_base, VALUE = 'Rotation Speed:' ) ; Range of values designed to go from -4 to 4, with very small increments around 0 and larger increments nearer to -4 and 4. movie_degrees = (FINDGEN( 21 ) - 10) ^ 2 / 10 ^ 2 * 4 * ([1,-1])[((FINDGEN( 21 ) - 10) lt 0)] movie_degrees = STRTRIM( movie_degrees, 2 ) ; Strip trailing zeroes from string. Assumes string contains a decimal dot. FOR d=0,20 DO BEGIN WHILE (STRMID( movie_degrees[d], 0, 1, /REVERSE ) EQ '0') DO BEGIN movie_degrees[d] = STRMID( movie_degrees[d], 0, STRLEN( movie_degrees[d] ) - 1 ) ENDWHILE ENDFOR FOR d=0,20 DO BEGIN IF STRMID( movie_degrees[d], 0, 1, /REVERSE ) EQ '.' THEN BEGIN movie_degrees[d] = movie_degrees[d] + '0' ENDIF ENDFOR movie_base2 = WIDGET_BASE( movie_base, /COLUMN ) movie_slider_value = 1 movie_slider_ndx = WHERE( FLOAT( movie_degrees ) EQ FLOAT( movie_slider_value ) ) movie_increment_degrees = movie_degrees[movie_slider_ndx[0]] movie_increment_label = WIDGET_LABEL( movie_base2, VALUE = movie_increment_degrees[0] + ' deg', /DYNAMIC_RESIZE ) movie_increment_slider = WIDGET_SLIDER( movie_base2, VALUE = movie_slider_ndx - 10, MINIMUM = -10, MAXIMUM = 10, UVALUE = 'MOVIE_INCREMENT_SLIDER', /DRAG, /SUPPRESS_VALUE ) movie_onoff_Button = WIDGET_BUTTON( movie_base, VALUE = ' Stop', UVALUE = 'MOVIE_ONOFF_BUTTON' ) ;THIS STUFF IS NOT WORKING. ;rotate_around_base = WIDGET_BASE( options_base, /ROW ) ;rotate_around_label = WIDGET_LABEL( rotate_around_base, VALUE = 'Rotate around:' ) ;rotate_around_button_base = WIDGET_BASE( rotate_around_base, /ROW, /EXCLUSIVE ) ;rotate_around_origin = WIDGET_BUTTON( rotate_around_button_base, VALUE = 'Origin', UVALUE = 'ROTATE_AROUND_ORIGIN' ) ;rotate_around_centroid = WIDGET_BUTTON( rotate_around_button_base, VALUE = 'Centroid', UVALUE = 'ROTATE_AROUND_CENTROID' ) save_base = WIDGET_BASE( tlb, /COLUMN, /FRAME ) moviesave_Base = WIDGET_BASE( save_base, /ROW ) moviesave_Label = WIDGET_LABEL( moviesave_base, VALUE = 'Save Movie:' ) moviesave_RadioButtonBase = WIDGET_BASE( moviesave_base, /ROW, /EXCLUSIVE ) moviesave_on_Button = WIDGET_BUTTON( moviesave_RadioButtonBase, VALUE = 'On', UVALUE = 'MOVIE_ON_BUTTON' ) moviesave_off_Button = WIDGET_BUTTON( moviesave_RadioButtonBase, VALUE = 'OFF', UVALUE = 'MOVIE_OFF_BUTTON' ) moviesave_frame_label = WIDGET_LABEL( moviesave_base, VALUE = '', /DYNAMIC_RESIZE ) WIDGET_CONTROL, moviesave_off_button, /SET_BUTTON saveBase = WIDGET_BASE( save_base, /ROW ) saveLabel = WIDGET_LABEL( saveBase, VALUE = 'Save Still:' ) tiffButton = WIDGET_BUTTON( saveBase, VALUE = 'TIFF', UVALUE = 'TIFF' ) VRMLButton = WIDGET_BUTTON( saveBase, VALUE = 'VRML 2.0', UVALUE = 'VRML' ) ; WAVEFRONTButton = WIDGET_BUTTON( saveBase, VALUE = 'WAVEFRONT', UVALUE = 'WAVEFRONT' ) ;widget_control,WAVEFRONTButton,sensitive=0 helpbase = WIDGET_BASE( tlb, /ROW ) helpButton = WIDGET_BUTTON( helpbase, VALUE = 'Help', UVALUE = 'HELP' ) quitButton = WIDGET_BUTTON( helpbase, VALUE = 'Quit', UVALUE = 'QUIT' ) WIDGET_CONTROL, tlb, /REALIZE WIDGET_CONTROL, screenRotateFButton, SET_BUTTON = 1 ; Initialize to Y (solar spin) axis control. WIDGET_CONTROL, dataCoordinatesBase, MAP = 0 WIDGET_CONTROL, screenCoordinatesBase, MAP = 1 WIDGET_CONTROL, screenCoordinatesButton, SET_BUTTON = 1 ; WIDGET_CONTROL, depth_cue_off_Button, SET_BUTTON = 1 WIDGET_CONTROL, thomsonsphere_off_Button, SET_BUTTON = 1 WIDGET_CONTROL, frustrums_off_Button, SET_BUTTON = 1 WIDGET_CONTROL, images_off_Button, SET_BUTTON = 1 ; WIDGET_CONTROL, clear_disk_off_Button, SET_BUTTON = 1 ; Set up trackball object. myTrackBall = OBJ_NEW( 'trackball', [xdim/2,ydim/2], xdim/2 ) ; Set up draw widget in a floating base. ; Initialize with step=0 of xyz_data. step = 0 draw_window_title = 'Date_Time = ' + timesteps[step] + ', Window size = ' + STRTRIM( FIX(xdim), 2 ) + 'x' + STRTRIM( FIX(ydim), 2 ) objectDrawBase = WIDGET_BASE( /FLOATING, GROUP_LEADER = tlb, /COLUMN, $ TITLE = draw_window_title, /TLB_SIZE_EVENTS, UVALUE = 'OBJECTDRAWBASE' ) objectDrawWidget = WIDGET_DRAW( objectDrawBase, XSIZE = xdim, YSIZE = ydim, GRAPHICS_LEVEL = 2, RETAIN = 0, $ /BUTTON_EVENTS, /MOTION_EVENTS, /EXPOSE_EVENTS, UVALUE = 'OBJECTDRAW' ) WIDGET_CONTROL, objectDrawBase, /REALIZE WIDGET_CONTROL, objectDrawWidget, GET_VALUE = objectWindow myVRML = OBJ_NEW( 'IDLgrVRML', DIMENSIONS = [xdim,ydim] ) polyLineRotator = OBJ_NEW( 'IDLexRotator', [xdim/2.0,ydim/2.0], xdim/2.0 ) ; Create polyLine view tree. polyLineView = OBJ_NEW( 'IDLgrView', VIEWPLANE_RECT = [-1,-1,2,2], ZCLIP = [3.5,-3.0], PROJECTION = 1, COLOR = [0,0,0], DEPTH_CUE = [0,0] ) ; De-sensitize the GUI interface. WIDGET_CONTROL, tlb, SENSITIVE = 0 WIDGET_CONTROL, /HOURGLASS WIDGET_CONTROL, transformButton, SET_BUTTON = 1 ; Find the min and max of highest point in all polyLines combined, needed for color calculation. ; (This method of finding min/max values is probably flawed, but works fine for doing color.) maxValue = 0 minValue = 1.0 IF (xyz_filename NE '') THEN BEGIN FOR i = 0, N_ELEMENTS( REFORM(xyz_data[0,*]) ) - 1 DO BEGIN x = REFORM(xyz_data[0,*]) y = REFORM(xyz_data[1,*]) * (-1) ; Flip upside down. z = REFORM(xyz_data[2,*]) * (-1) ; Flip upside down. maxValue = MAX( [ maxValue, SQRT( MAX(x)^2 + MAX(y)^2 + MAX(z)^2 ) ]) minValue = MIN( [ minValue, SQRT( MAX(x)^2 + MAX(y)^2 + MAX(z)^2 ) ]) ENDFOR ; Set up polyLine objects, put each object in the model, give each polyLine a color. polyLineModel = OBJ_NEW( 'IDLgrModel' ) IF SIZE(xyz_data,/N_DIMENSIONS) EQ 2 THEN BEGIN feature_count = 1 ENDIF ELSE BEGIN feature_count = N_ELEMENTS(xyz_data[0,0,*]) ENDELSE polyLineObjArr = OBJARR( feature_count ) tables = [1,2,3,4,5] new_rtab = BYTARR(256) new_gtab = new_rtab new_btab = new_rtab FOR t = 0,N_ELEMENTS(tables) - 1 DO BEGIN sublength = 255 / N_ELEMENTS( tables ) sx = t * sublength ex = sx + sublength - 1 IF (t EQ N_ELEMENTS( tables ) - 1) THEN BEGIN ex = 255 sublength = (ex - sx) + 1 ENDIF CASE tables[t] OF 1 : BEGIN old_rtab = BINDGEN(256) * 0.6 old_gtab = BINDGEN(256) * 0.6 old_btab = BINDGEN(256) * 1.0 END 2 : BEGIN old_rtab = BINDGEN(256) * 0.1 old_gtab = BINDGEN(256) * 1.0 old_btab = BINDGEN(256) * 0.1 END 3 : BEGIN old_rtab = BINDGEN(256) * 1.0 old_gtab = BINDGEN(256) * 1.0 old_btab = BINDGEN(256) * 0.0 END 4 : BEGIN old_rtab = BINDGEN(256) * 1.0 old_gtab = BINDGEN(256) * 0.5 old_btab = BINDGEN(256) * 0.0 END 5 : BEGIN old_rtab = BINDGEN(256) * 1.0 old_gtab = BINDGEN(256) * 0.2 old_btab = BINDGEN(256) * 0.2 END ENDCASE new_rtab[sx:ex] = CONGRID(old_rtab[80:255], sublength ) new_gtab[sx:ex] = CONGRID(old_gtab[80:255], sublength ) new_btab[sx:ex] = CONGRID(old_btab[80:255], sublength ) ENDFOR new_tab = LONARR( 3, N_ELEMENTS(polyLineObjArr) ) FOR c = 0, N_ELEMENTS(polyLineObjArr) - 1 DO BEGIN hue = c * (360. / N_ELEMENTS(polyLineObjArr)) COLOR_CONVERT, $ hue, $ 0.75, $ 1.00, $ rrr, $ ggg, $ bbb, $ /hls_rgb new_tab[0,c] = rrr new_tab[1,c] = ggg new_tab[2,c] = bbb ENDFOR max_height = 0 FOR i = 0, N_ELEMENTS( polyLineObjArr ) - 1 DO BEGIN IF feature_count EQ 1 THEN BEGIN ndx = WHERE((xyz_data[0,*] NE 0) AND (xyz_data[1,*] NE 0) AND (xyz_data[2,*] NE 0),count) x = REFORM(xyz_data[0,ndx]) y = REFORM(xyz_data[1,ndx]) * (-1) ; Flip upside down. z = REFORM(xyz_data[2,ndx]) * (-1) ; Flip upside down. max_height = MAX( SQRT( REFORM(xyz_data[0,*]) ^ 2 + REFORM(xyz_data[1,*]) ^ 2 + REFORM(xyz_data[2,*]) ^ 2 ) ) ENDIF ELSE BEGIN ndx = WHERE((xyz_data[0,*,i] NE 0) AND (xyz_data[1,*,i] NE 0) AND (xyz_data[2,*,i] NE 0),count) IF count GT 0 THEN BEGIN x = REFORM(xyz_data[0,ndx,i]) y = REFORM(xyz_data[1,ndx,i]) * (-1) ; Flip upside down. (Be sure to also flip positions of Earth, Stereo-A, Stereo-B, and any other reference graphics.) z = REFORM(xyz_data[2,ndx,i]) * (-1) ; Flip upside down. max_height = MAX( [ max_height, SQRT( REFORM(xyz_data[0,*,i]) ^ 2 + REFORM(xyz_data[1,*,i]) ^ 2 + REFORM(xyz_data[2,*,i]) ^ 2 ) ] ) ENDIF ENDELSE IF count GT 0 THEN BEGIN polyLineObjArr[i] = OBJ_NEW( 'IDLgrPolyline', x, y, z, THICK = 1 ) polyLineModel -> Add, polyLineObjArr[i] ; length = SQRT( x[0]^2 + y[0]^2 + z[0]^2 ) ENDIF ; Color smallest polyLines yellow and largest red, as defined by maximum altitude reached. ; red = 255 ; red = SIN( FLOAT(i+1) / N_ELEMENTS( polyLineObjArr ) ) * 255 ; grn = 255 - ( SQRT( MAX( x )^2 + MAX( y )^2 + MAX( z )^2 ) - minValue ) * 255 / ( maxValue - minValue ) ; grn = 255 - SIN( FLOAT(i+1) / N_ELEMENTS( polyLineObjArr ) ) * 255 ; blu = 0 ; blu = SIN( FLOAT(i+1) / N_ELEMENTS( polyLineObjArr ) ) * 255 ;red=(randomu(systime(/seconds))*0.75+0.25)*255 ;wait,1 ;grn=(randomu(systime(/seconds))*0.75+0.25)*255 ;wait,1 ;blu=(randomu(systime(/seconds))*0.75+0.25)*255 ; index=float(i)/(N_ELEMENTS( polyLineObjArr ))*255 ; red=new_rtab[index] ; grn=new_gtab[index] ; blu=new_btab[index] IF OBJ_VALID(polyLineObjArr[i]) THEN BEGIN ; polyLineObjArr[i] -> SetProperty, COLOR = [ red, grn, blu ] ; polyLineObjArr[i] -> SetProperty, COLOR = new_tab[i] polyLineObjArr[i] -> SetProperty, COLOR = new_tab[*,i] ENDIF ENDFOR universe_model -> Add, polyLineModel IF (xyz_filename NE '') THEN BEGIN ; Get coordinate system from metadata. ascii = READ_ASCII(xyz_filename,COUNT=count) ascii = STRARR(count) OPENR,lun,xyz_filename,/GET_LUN READF,lun,ascii FREE_LUN,lun metadata_start = WHERE(STRPOS(ascii,'-9999') EQ 0) ; Carrington or Stonyhurst. system = (ascii[metadata_start+1])[0] ENDIF ENDIF ELSE BEGIN polyLineModel = OBJ_NEW() polyLineObjArr = OBJARR( 1 ) system = 'STONYHURST' ENDELSE polyLineRotator -> Add, universe_model polyLineView -> Add, polyLineRotator polyLineView -> SetProperty, COLOR = [0,0,0] ; Initially enable data X axis rotation (solar tilt towards or away from viewer, similar to viewer's B-angle.) polyLineRotator -> SetProperty, AXIS = 0, CONSTRAIN = 2 ; Initialize model rotated 90 degrees X to switch Y and Z axes. initialZtransform = IDENTITY( 4 ) polyLineRotator -> SetProperty, TRANSFORM = initialZtransform IF (SIZE( max_height, /TYPE ) GT 0) THEN BEGIN axis_length = CEIL( max_height ) ENDIF ELSE BEGIN axis_length = 10 ENDELSE axis_struct = BUILD_AXIS_MODEL( axis_length ) axisModel = axis_struct.axisModel sunModel = OBJ_NEW( 'orb2', POS = [0,0,0], RADIUS = 1.0 ) ; IF (xyz_filename NE '') THEN BEGIN ; ; ; Get coordinate system from metadata. ; ascii = READ_ASCII(xyz_filename,COUNT=count) ; ascii = STRARR(count) ; OPENR,lun,xyz_filename,/GET_LUN ; READF,lun,ascii ; FREE_LUN,lun ; metadata_start = WHERE(STRPOS(ascii,'-9999') EQ 0) ; ; Carrington or Stonyhurst. ; system = (ascii[metadata_start+1])[0] ; ; ENDIF ELSE BEGIN ; ; system = 'CARRINGTON' ; ; ENDELSE IF ( STRUPCASE(system) EQ 'STONYHURST' ) THEN BEGIN system = 'HEEQ' ENDIF ; Use date to get XYZ for Earth, Stereo-A and Stereo-B. FOR step=0,nsteps-1 DO BEGIN timestep = step_state[step].date+'_'+step_state[step].time step_state[step].earth_xyz = (GET_STEREO_COORD( timestep, 'Earth', SYSTEM=system ))[0:2] step_state[step].stereoa_xyz = (GET_STEREO_COORD( timestep, 'A', SYSTEM=system ))[0:2] step_state[step].stereob_xyz = (GET_STEREO_COORD( timestep, 'B', SYSTEM=system ))[0:2] step_state[step].mercury_xyz = (GET_STEREO_COORD( timestep, 'Mercury', SYSTEM=system ))[0:2] step_state[step].venus_xyz = (GET_STEREO_COORD( timestep, 'Venus', SYSTEM=system ))[0:2] step_state[step].mars_xyz = (GET_STEREO_COORD( timestep, 'Mars', SYSTEM=system ))[0:2] step_state[step].jupiter_xyz = (GET_STEREO_COORD( timestep, 'Jupiter barycenter', SYSTEM=system ))[0:2] step_state[step].saturn_xyz = (GET_STEREO_COORD( timestep, 'Saturn barycenter', SYSTEM=system ))[0:2] ENDFOR ; Convert earth coordinates to xyz. solar_radius_km = (6.96e08 / 1000) ; Solar Radius == 6.960 x 10^8 meters FOR step=0,nsteps-1 DO BEGIN step_state[step].earth_xyz = step_state[step].earth_xyz / solar_radius_km step_state[step].stereoa_xyz = step_state[step].stereoa_xyz / solar_radius_km step_state[step].stereob_xyz = step_state[step].stereob_xyz / solar_radius_km step_state[step].mercury_xyz = step_state[step].mercury_xyz / solar_radius_km step_state[step].venus_xyz = step_state[step].venus_xyz / solar_radius_km step_state[step].mars_xyz = step_state[step].mars_xyz / solar_radius_km step_state[step].jupiter_xyz = step_state[step].jupiter_xyz / solar_radius_km step_state[step].saturn_xyz = step_state[step].saturn_xyz / solar_radius_km ENDFOR FOR step=0,nsteps-1 DO BEGIN step_state[step].earth_xyz = step_state[step].earth_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].stereoa_xyz = step_state[step].stereoa_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].stereob_xyz = step_state[step].stereob_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].mercury_xyz = step_state[step].mercury_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].venus_xyz = step_state[step].venus_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].mars_xyz = step_state[step].mars_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) step_state[step].saturn_xyz = step_state[step].saturn_xyz * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) ENDFOR IF (N_ELEMENTS(xyz_mean[*]) EQ 3) THEN BEGIN xyz_mean[*] = xyz_mean[*] * [1,-1,-1] ; Flip upside down. (As is done with the XYZ data.) ENDIF referenceModel = OBJ_NEW( 'IDLgrModel' ) ; Initialize with step=0 of xyz_data. step = 0 earthModel = OBJ_NEW( 'orb2', POS = step_state[step].earth_xyz, RADIUS = 1 ) stereoaModel = OBJ_NEW( 'orb2', POS = step_state[step].stereoa_xyz, RADIUS = 1 ) stereobModel = OBJ_NEW( 'orb2', POS = step_state[step].stereob_xyz, RADIUS = 1 ) venusModel = OBJ_NEW( 'orb2', POS = step_state[step].venus_xyz, RADIUS = 1 ) mercuryModel = OBJ_NEW( 'orb2', POS = step_state[step].mercury_xyz, RADIUS = 1 ) marsModel = OBJ_NEW( 'orb2', POS = step_state[step].mars_xyz, RADIUS = 1 ) jupiterModel = OBJ_NEW( 'orb2', POS = step_state[step].jupiter_xyz, RADIUS = 1 ) saturnModel = OBJ_NEW( 'orb2', POS = step_state[step].saturn_xyz, RADIUS = 1 ) referenceLineObjarr = OBJARR( 3 ) ; Initialize with step=0 of xyz_data. step = 0 referenceLineObjarr[0] = OBJ_NEW( 'IDLgrPolyline', [0,step_state[step].earth_xyz[0]], [0,step_state[step].earth_xyz[1]], [0,step_state[step].earth_xyz[2]], THICK=1 ) referenceLineObjarr[1] = OBJ_NEW( 'IDLgrPolyline', [0,step_state[step].stereoa_xyz[0]], [0,step_state[step].stereoa_xyz[1]], [0,step_state[step].stereoa_xyz[2]], THICK=1 ) referenceLineObjarr[2] = OBJ_NEW( 'IDLgrPolyline', [0,step_state[step].stereob_xyz[0]], [0,step_state[step].stereob_xyz[1]], [0,step_state[step].stereob_xyz[2]], THICK=1 ) IF (N_ELEMENTS(xyz_mean) EQ 3) THEN BEGIN xyz_mean_line = OBJ_NEW( 'IDLgrPolyline', [0,xyz_mean[0]], [0,xyz_mean[1]], [0,xyz_mean[2]], THICK = 1, HIDE = 1 ) ENDIF ELSE BEGIN xyz_mean_line = -1 ENDELSE referenceModel -> Add, earthModel referenceModel -> Add, stereoaModel referenceModel -> Add, stereobModel referenceModel -> Add, referenceLineObjArr referenceModel -> Add, mercuryModel referenceModel -> Add, venusModel referenceModel -> Add, marsModel referenceModel -> Add, jupiterModel referenceModel -> Add, saturnModel IF (N_ELEMENTS(xyz_mean) EQ 3) THEN BEGIN referenceModel -> Add, xyz_mean_Line ENDIF ; Initialize with step=0 of xyz_data. step = 0 earthTextObj = OBJ_NEW( 'IDLgrText', ['Earth','Ahead','Behind','Mercury','Venus','Mars','Jupiter','Saturn'], $ LOCATIONS = [ $ [REFORM(step_state[step].earth_xyz)+[1,1,-1]], $ [REFORM(step_state[step].stereoa_xyz)+[1,1,-1]], $ [REFORM(step_state[step].stereob_xyz)+[1,1,-1]], $ [REFORM(step_state[step].mercury_xyz)+[1,1,-1]], $ [REFORM(step_state[step].venus_xyz)+[1,1,-1]], $ [REFORM(step_state[step].mars_xyz)+[1,1,-1]], $ [REFORM(step_state[step].jupiter_xyz)+[1,1,-1]], $ [REFORM(step_state[step].saturn_xyz)+[1,1,-1]] ], $ /ONGLASS, COLOR = 255 ) referenceModel -> Add, earthTextObj spacecraft_height = 0 ; Initialize with step=0 of xyz_data. step = 0 spacecraft_height = MAX( [ spacecraft_height, SQRT( REFORM(step_state[step].earth_xyz[0]) ^ 2 + REFORM(step_state[step].earth_xyz[1]) ^ 2 + REFORM(step_state[step].earth_xyz[2]) ^ 2 ) ] ) spacecraft_height = MAX( [ spacecraft_height, SQRT( REFORM(step_state[step].stereoa_xyz[0]) ^ 2 + REFORM(step_state[step].stereoa_xyz[1]) ^ 2 + REFORM(step_state[step].stereoa_xyz[2]) ^ 2 ) ] ) spacecraft_height = MAX( [ spacecraft_height, SQRT( REFORM(step_state[step].stereob_xyz[0]) ^ 2 + REFORM(step_state[step].stereob_xyz[1]) ^ 2 + REFORM(step_state[step].stereob_xyz[2]) ^ 2 ) ] ) spacecraft_zoom = 0.98 / spacecraft_height thomsonsphereModel = OBJ_NEW( 'IDLgrModel', HIDE = 1 ) ; Initialize with step=0 of xyz_data. step = 0 thomsonsphereOrb_a = OBJ_NEW( 'orb2', POS = step_state[step].stereoa_xyz/2, RADIUS = SQRT( TOTAL( step_state[step].stereoa_xyz^2, /DOUBLE ) ) / 2 ) thomsonsphereOrb_b = OBJ_NEW( 'orb2', POS = step_state[step].stereob_xyz/2, RADIUS = SQRT( TOTAL( step_state[step].stereob_xyz^2, /DOUBLE ) ) / 2 ) thomsonsphereModel -> Add, thomsonsphereOrb_a thomsonsphereModel -> Add, thomsonsphereOrb_b IF (save_vrml EQ 0) THEN BEGIN universe_model -> Add, referenceModel universe_model -> Add, thomsonsphereModel universe_model -> Add, sunModel universe_model -> Add, axisModel ENDIF ; Determine if data access is available for building frustrums. fits_data_access = 0 data_path=GETENV('secchi') IF (data_path NE '') THEN fits_data_access=1 data_path=GETENV('SECCHI_LZ') IF (data_path NE '') THEN fits_data_access=1 data_path=GETENV('SECCHI_DATA_AHEAD') IF (data_path NE '') THEN fits_data_access=1 ; Determine if tiff access is available for adding images to frustrums. secchi_tiff_location=GETENV('secchi_tiff_location') tiff_data_access = 0 IF ( secchi_tiff_location NE '' ) THEN BEGIN IF ( STRMID((FILE_SEARCH(secchi_tiff_location+'/tiff*/'+step_state[0].date+'/..'))[0],0,4) NE '' ) THEN BEGIN tiff_data_access = 1 ENDIF ELSE BEGIN IF ( STRMID((FILE_SEARCH(secchi_tiff_location+'/tiff*/'+step_state[0].date+'/..'))[0],0,4) NE '' ) THEN BEGIN tiff_data_access = 1 ENDIF ENDELSE ENDIF WIDGET_CONTROL, showFrustrumsBase, SENSITIVE = fits_data_access WIDGET_CONTROL, frustrums_base, SENSITIVE = fits_data_access WIDGET_CONTROL, images_Base, SENSITIVE = tiff_data_access ; WIDGET_CONTROL, screenCoordsResetButton, SENSITIVE = (xyz_filename NE '') ;DENSITY IS NOW SET INSIDE orb2__define.pro ..... (? unresolved how to handle that, exactly.) ; sunModel -> SetProperty, DENSITY = 1.00 ; 1.25 = 15 degree spacing of grid lines. sunModel -> SetProperty, COLOR = [75,150,150] ; Color of wireframe. sunModel -> SetProperty, STYLE = 1 sunModel -> SetProperty, HIDE = 0 ; Initially show wireframe Sun. ; earthModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. earthModel -> SetProperty, COLOR = [127,191,127] ; Color of wireframe. earthModel -> SetProperty, STYLE = 1 earthModel -> SetProperty, HIDE = 0 ; Initially show wireframe Earth. ; stereoaModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. stereoaModel -> SetProperty, COLOR = [191,127,127] ; Color of wireframe. stereoaModel -> SetProperty, STYLE = 1 stereoaModel -> SetProperty, HIDE = 0 ; Initially show wireframe orb representing STEREO-A. ; stereobModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. stereobModel -> SetProperty, COLOR = [127,127,191] ; Color of wireframe. stereobModel -> SetProperty, STYLE = 1 stereobModel -> SetProperty, HIDE = 0 ; Initially show wireframe orb representing STEREO-B. ; mercuryModel -> SetProperty, DENSITY = 0.5 ; Reducedspacing of grid lines. mercuryModel -> SetProperty, COLOR = [191,191,63] ; Color of wireframe. mercuryModel -> SetProperty, STYLE = 1 mercuryModel -> SetProperty, HIDE = 0 ; Initially show wireframe Mercury. ; venusModel -> SetProperty, DENSITY = 0.5 ; Reducedspacing of grid lines. venusModel -> SetProperty, COLOR = [191,191,63] ; Color of wireframe. venusModel -> SetProperty, STYLE = 1 venusModel -> SetProperty, HIDE = 0 ; Initially show wireframe Venus. ; marsModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. marsModel -> SetProperty, COLOR = [191,191,63] ; Color of wireframe. marsModel -> SetProperty, STYLE = 1 marsModel -> SetProperty, HIDE = 0 ; Initially show wireframe Mars. ; jupiterModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. jupiterModel -> SetProperty, COLOR = [191,191,63] ; Color of wireframe. jupiterModel -> SetProperty, STYLE = 1 jupiterModel -> SetProperty, HIDE = 0 ; Initially show wireframe Jupiter. ; saturnModel -> SetProperty, DENSITY = 0.5 ; Reduced spacing of grid lines. saturnModel -> SetProperty, COLOR = [191,191,63] ; Color of wireframe. saturnModel -> SetProperty, STYLE = 1 saturnModel -> SetProperty, HIDE = 0 ; Initially show wireframe Saturn. thomsonsphereorb_a_color = [40,20,20] thomsonsphereorb_b_color = [20,20,40] ; thomsonsphereOrb_a -> SetProperty, DENSITY = 1.25 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_a -> SetProperty, LAT_DENSITY = 2.0 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_a -> SetProperty, LON_DENSITY = 1.5 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_a -> SetProperty, COLOR = thomsonsphereorb_a_color ; Color of wireframe. thomsonsphereOrb_a -> SetProperty, STYLE = 1 thomsonsphereOrb_a -> SetProperty, HIDE = 0 ; Initially show wireframe sphere. ; thomsonsphereOrb_b -> SetProperty, DENSITY = 1.25 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_b -> SetProperty, LAT_DENSITY = 2.0 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_b -> SetProperty, LON_DENSITY = 1.5 ; 1.25 = 15 degree spacing of grid lines. thomsonsphereOrb_b -> SetProperty, COLOR = thomsonsphereorb_b_color ; Color of wireframe. thomsonsphereOrb_b -> SetProperty, STYLE = 1 thomsonsphereOrb_b -> SetProperty, HIDE = 0 ; Initially show wireframe sphere. ; earth referenceLineObjArr[0] -> SetProperty, COLOR = [127,191,127] ; stereoa referenceLineObjArr[1] -> SetProperty, COLOR = [191,127,127] ; stereob referenceLineObjArr[2] -> SetProperty, COLOR = [127,127,191] IF (N_ELEMENTS(xyz_mean) EQ 3) THEN BEGIN xyz_mean_Line -> SetProperty, COLOR = [127,127,127] ENDIF referenceLineObjArr[0] -> SetProperty, HIDE = 0 ; Initially show reference lines to earth. referenceLineObjArr[1] -> SetProperty, HIDE = 0 ; Initially show reference lines to stereoa. referenceLineObjArr[2] -> SetProperty, HIDE = 0 ; Initially show reference lines to stereob. ; Orient north up. universe_model -> Rotate, [1,0,0], 90 ; Constrain rotation to Y axis only (screen coordinates). center = [xdim,ydim]/2.0 rotateAxis = 3 IF (rotateAxis EQ 3) THEN BEGIN myTrackBall -> Reset, center, (center)[0] ENDIF ELSE BEGIN myTrackBall -> Reset, center, (center)[0], /CONSTRAIN, AXIS = rotateAxis ENDELSE IF (xyz_filename NE '') THEN BEGIN ; Zoom out a little. cme_zoom = 1.0 / max_height ENDIF ELSE BEGIN cme_zoom = spacecraft_zoom ENDELSE current_zoom = cme_zoom universe_model -> Scale, current_zoom, current_zoom, current_zoom ; polyLineModel -> GetProperty, TRANSFORM = t ; qmat=[[1,0,0,xyz_mean[0]],[0,1,0,xyz_mean[1]],[0,0,1,xyz_mean[2]],[0,0,0,1]] ; tq = t # qmat ; polyLineModel -> SetProperty, TRANSFORM = tq infoPtr = PTR_NEW( { $ tlb : tlb ,$ objectDrawBase : objectDrawBase ,$ objectDrawWidget : objectDrawWidget ,$ objectWindow : objectWindow ,$ draw_window_title : draw_window_title ,$ myTrackBall : myTrackBall ,$ myVRML : myVRML ,$ save_vrml : save_vrml ,$ mouseDown : 0 ,$ center : center ,$ rotateAxis : rotateAxis ,$ ; 0=X, 1=Y, 2=Z, 3=Free(Unconstrained). fxyzBase : fxyzBase ,$ translate : 0 ,$ universe_model : universe_model ,$ ; Master model for geometry purposes (rotation, zoom, etc.) polyLineRotator : polyLineRotator ,$ polyLineView : polyLineView ,$ polyLineModel : polyLineModel ,$ polyLineObjArr : polyLineObjArr ,$ fits_data_access : fits_data_access ,$ tiff_data_access : tiff_data_access ,$ timesteps : timesteps ,$ nsteps : nsteps ,$ step : 0 ,$ step_state : step_state ,$ hide_frustrums : 1 ,$ hide_images : 1 ,$ only_show_one_inst_image : only_show_one_inst_image ,$ only_show_two_inst_image : only_show_two_inst_image ,$ sunModel : sunModel ,$ referenceModel : referenceModel ,$ referenceLineObjArr : referenceLineObjArr ,$ axisModel : axisModel ,$ thomsonsphereModel : thomsonsphereModel ,$ thomsonsphereorb_a : thomsonsphereorb_a ,$ thomsonsphereorb_b : thomsonsphereorb_b ,$ thomsonsphereorb_a_color : thomsonsphereorb_a_color ,$ thomsonsphereorb_b_color : thomsonsphereorb_b_color ,$ thomsonsphereorb_brightenfactor : 3.0 ,$ thomsonsphere_brightness_button : thomsonsphere_brightness_button ,$ xyz_mean_line : xyz_mean_line ,$ axis_length : axis_length ,$ axisTextObjarr : axis_struct.axisTextObjarr ,$ earthTextObj : earthTextObj ,$ zoomButtonStatus : 0 ,$ ;;;;;;;;;;;;;;;;zoomLabel : zoomLabel ,$ y_cursor_initial_value : 0L ,$ y_cursor_current_value : 0L ,$ y_cursor_previous_value : 0L ,$ y_cursor_current_diff : -1L ,$ y_cursor_previous_diff : -1L ,$ x_prev : 0L ,$ y_prev : 0L ,$ maxSizeAllowed : maxSizeAllowed ,$ xdim : xdim ,$ ; window x size ydim : ydim ,$ ; window y size dataCoordinatesBase : dataCoordinatesBase ,$ screenCoordinatesBase : screenCoordinatesBase ,$ screenCoordsResetButton : screenCoordsResetButton ,$ coordinatesFlag : 'SCREENCOORDINATES' ,$ dataRotateXYZ : 'DATAZ' ,$ screenEntryTextX : screenEntryTextX ,$ screenEntryTextY : screenEntryTextY ,$ screenEntryTextZ : screenEntryTextZ ,$ dataTransform : initialZtransform ,$ dataRotateXButton : dataRotateXButton ,$ depth_cue : [0,0] ,$ line_thickness_slider : line_thickness_slider ,$ system : system ,$ frustrums_on_Button : frustrums_on_Button ,$ frustrums_off_Button : frustrums_off_Button ,$ fits_filenames_button : fits_filenames_button ,$ tiff_filenames_button : tiff_filenames_button ,$ images_off_Button : images_off_Button ,$ movie_onoff_button : movie_onoff_button ,$ movie_increment_label : movie_increment_label ,$ movie_increment_degrees : movie_increment_degrees ,$ movie_degrees : movie_degrees ,$ cumulative_movie_rotation_increments : 0 ,$ movie_timer_delay : 1/60. ,$ movie_zero_timer_initial : 0.0d ,$ movie_zero_timer_now : 0.0d ,$ moviesave_counter : 0L ,$ moviesave_off_button : moviesave_off_button ,$ moviesave_frame_label : moviesave_frame_label ,$ xyz_filename : xyz_filename ,$ xyz_mean : xyz_mean ,$ cme_zoom : cme_zoom ,$ spacecraft_zoom : spacecraft_zoom ,$ current_zoom : current_zoom ,$ new_zoom : current_zoom ,$ zoom_increment : 0.0 ,$ zoom_step : 0 ,$ frustrums_are_loaded : 0 ,$ images_are_loaded : 0 ,$ helpButton : 0L ,$ quitButton : 0L ,$ first_time_through : 1 } ) ; Put infoPtr in the uvalue of both floating bases. WIDGET_CONTROL, tlb, SET_UVALUE = infoPtr IF (WIDGET_INFO((*infoPtr).objectDrawBase,/VALID_ID) EQ 0) THEN BEGIN draw_window_has_been_killed, infoPtr RETURN ENDIF WIDGET_CONTROL, objectDrawBase, SET_UVALUE = infoPtr ; Draw polyLine view to the window. redraw_polyLineView, infoPtr ; Re-sensitize the GUI interface. WIDGET_CONTROL, tlb, SENSITIVE = 1 XMANAGER, 'line3d', tlb, EVENT_HANDLER = 'line3d_event', /NO_BLOCK XMANAGER, 'line3d display', ObjectDrawBase, EVENT_HANDLER = 'line3d_event', /NO_BLOCK IF (only_show_one_inst_image NE '') THEN BEGIN line3d_event, { ID:frustrums_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, frustrums_on_Button, SET_BUTTON = 1 WIDGET_CONTROL, fits_filenames_button, SENSITIVE = 1 CASE only_show_one_inst_image OF 'euvi' : line3d_event, { ID:showEUVIfrustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'cor1' : line3d_event, { ID:showCOR1frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'cor2' : line3d_event, { ID:showCOR2frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'hi_1' : line3d_event, { ID:showHI_1frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'hi_2' : line3d_event, { ID:showHI_2frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } ENDCASE line3d_event, { ID:images_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, images_on_Button, SET_BUTTON = 1 WIDGET_CONTROL, tiff_filenames_button, SENSITIVE = 1 line3d_event, { ID:frustrums_off_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, fits_filenames_button, SENSITIVE = 0 ENDIF IF (only_show_two_inst_image[0] NE '') THEN BEGIN line3d_event, { ID:frustrums_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, fits_filenames_button, SENSITIVE = 1 ; Frame the view to show the larger of the two chosen instruments. (Thus, EUVI is not an option.) CASE only_show_two_inst_image[1] OF 'cor1' : line3d_event, { ID:showCOR1frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'cor2' : line3d_event, { ID:showCOR2frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'hi_1' : line3d_event, { ID:showHI_1frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } 'hi_2' : line3d_event, { ID:showHI_2frustrumButton, TOP:tlb, HANDLER:tlb, SELECT:1 } ENDCASE line3d_event, { ID:images_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, images_on_Button, SET_BUTTON = 1 WIDGET_CONTROL, tiff_filenames_button, SENSITIVE = 1 line3d_event, { ID:frustrums_off_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } WIDGET_CONTROL, fits_filenames_button, SENSITIVE = 0 ; ; Range of values designed to go from -4 to 4, with very small increments around 0 and larger increments nearer to -4 and 4. ; movie_degrees = (FINDGEN( 21 ) - 10) ^ 2 / 10 ^ 2 * 4 * ([1,-1])[((FINDGEN( 21 ) - 10) lt 0)] ; movie_degrees = STRTRIM( movie_degrees, 2 ) ; ; Strip trailing zeroes from string. Assumes string contains a decimal dot. ; FOR d=0,20 DO BEGIN ; WHILE (STRMID( movie_degrees[d], 0, 1, /REVERSE ) EQ '0') DO BEGIN ; movie_degrees[d] = STRMID( movie_degrees[d], 0, STRLEN( movie_degrees[d] ) - 1 ) ; ENDWHILE ; ENDFOR ; FOR d=0,20 DO BEGIN ; IF STRMID( movie_degrees[d], 0, 1, /REVERSE ) EQ '.' THEN BEGIN ; movie_degrees[d] = movie_degrees[d] + '0' ; ENDIF ; ENDFOR ; movie_base2 = WIDGET_BASE( movie_base, /COLUMN ) ; movie_slider_value = 1 ; movie_slider_ndx = WHERE( FLOAT( movie_degrees ) EQ FLOAT( movie_slider_value ) ) ; movie_increment_degrees = movie_degrees[movie_slider_ndx[0]] ; movie_increment_label = WIDGET_LABEL( movie_base2, VALUE = movie_increment_degrees[0] + ' deg', /DYNAMIC_RESIZE ) ; movie_increment_slider = WIDGET_SLIDER( movie_base2, VALUE = movie_slider_ndx - 10, MINIMUM = -10, MAXIMUM = 10, UVALUE = 'MOVIE_INCREMENT_SLIDER', /DRAG, /SUPPRESS_VALUE ) ; IF (nsteps GT (360 / movie_degrees(movie_slider_ndx)) ) THEN BEGIN ; line3d_event, { ID:movie_increment_slider, TOP:tlb, HANDLER:tlb, VALUE: ; ENDIF ENDIF IF (save_vrml EQ 1) THEN BEGIN line3d_event, { ID:frustrums_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } line3d_event, { ID:images_on_Button, TOP:tlb, HANDLER:tlb, SELECT:1 } line3d_event, { ID:VRMLButton, TOP:tlb, HANDLER:tlb, SELECT:1 } line3d_event, { ID:quitButton, TOP:tlb, HANDLER:tlb, SELECT:1 } RETURN ENDIF WIDGET_CONTROL, (*infoPtr).tlb, TIMER=(*infoPtr).movie_timer_delay END