;+ FUNCTION fly,cube,R=r,CLICK=click,UNDER=under ; PURPOSE: Cursor-controlled flight around 3D object ; ; METHOD: Window x-y coordinates of cursor define viewpoint relative to ; intrinsic x-y coordinates of object. I.e. move cursor to ; left side (-ve x-axis of window) to view object from its ; -ve x-axis side, as defined by its intrinsic coordinates. ; ; USAGE: WHILE fly(cube) DO drawit ; "drawit" (which is defined by the user and can have arbitrary ; arguments) should draw the object. ; ; ARGUMENTS: Cube = [xmin,ymin,zmin,xmax,ymax,zmax] defines the extent in ; data coordinates of the data cube which is rotated. ; The system variable !P.T3D is also used. It is assumed ; to be unset on initial entry. It is set by fly for ; the duration of the flying to enable the 3D->2D projection. ; ; KEYWORDS: R=r defines distance of viewpoint from centre of unit cube ; to which data is mapped. Default is infinity (i.e. no ; perspective effect). R=2 or R=3 helps in interpretation. ; *NOTE* that SURFACE and SHADE_SURF do not work with ; perspective. Must use default R=infinity with them. ; /CLICK to specify wait for left button click before redrawing ; image, rather than redrawing whenever the cursor moves. ; Recommmended for complex images (~> few hundred line segments). ; Note also that although in SunView image motion follows cursor ; if it has moved since last time cursor was read, in Xwindows ; it seems to need an event (wiggle mouse or press button) ; after the cursor routine is entered. ; /UNDER to enable flying under the cube. It is disabled by ; default because viewpoint is quite sensitive to cursor ; position with /UNDER and it can get confusing as to whether ; you are looking at it from above or below. Without it you ; are restricted to looking down on the cube. ; ; EXAMPLE: Try fly_demo.pro ; ; BUGS: The method of cursor control is not very intuitive. Should ; be changed to make cube rotate in (or against) direction ; of motion of cursor. ; ; COMMON: References dbcom, to know whether to call flash. ; ; AUTHOR: ANM 910325 ; ANM 911017 Modified theta treatment, added double-buffering ; stuff. ; ANM 911021 Add UNDER keyword, use !P.T3D to determine initial ; entry, rather than INIT parameter. ; ANM 911022 Rotate about centre of base of cube rather than ; center of cube (TR=[.5,.5,.0] rather than [.5,.5,.5]) ;- COMMON dbcom,w ; double-buffering routines common IF N_ELEMENTS(w) EQ 0 THEN w=-1 IF w GE 0 THEN BEGIN ; double buffering is in effect flash & pix = !D.WINDOW & WSET,w ; flush the image, get real window ENDIF IF N_ELEMENTS(click) EQ 0 THEN click=0 IF NOT !P.T3D THEN BEGIN PRINT,'Move the cursor to the x-y position in the window to view object' PRINT,'from that side e.g. cursor on left to view from -ve x-axis.' IF click THEN PRINT,'Click left button to redraw image.' PRINT,'Hit right button to exit.' !X.S=[-cube(0),1.0]/(cube(3)-cube(0)) !Y.S=[-cube(1),1.0]/(cube(4)-cube(1)) !Z.S=[-cube(2),1.0]/(cube(5)-cube(2)) cx = -1.0/3 & cy = SQRT(3)*cx IF KEYWORD_SET(under) THEN BEGIN cx = 0.5*cx & cy = 0.5*cy & END cx=(cx+1)/2 & cy=(cy+1)/2 & TVCRS,cx,cy,/NORM ; initial cx,cy correspond to theta=60 phi=240 IF w GE 0 THEN WSET,pix !P.T3D = 1 ; do after TVCRS END ELSE BEGIN IF w EQ -1 THEN EMPTY CURSOR,cx,cy,/NORM,2-click;;;/CHANGE ; select viewpoint IF w GE 0 THEN WSET,pix IF !ERR EQ 4 THEN BEGIN !P.T3D=0 & RETURN,0 & END ; exit loop on right button ENDELSE cx = 2*cx-1 & cy = 2*cy-1 ; put origin in centre phi = ATAN(cy,cx)*180/!PI ; spherical coordinates of viewpoint ;;theta = ASIN(SQRT(MIN([cx^2+cy^2,1.0])))*180/!PI ; above is too sensitive near theta=90. Also cant look from below. Try linear: theta=90*SQRT(MIN([cx^2+cy^2,1.0])) & IF KEYWORD_SET(under) THEN theta=2*theta T3D,/RESET,TR=-[.5,.5,.0],SCALE=[1,1,1]/SQRT(3) T3D,ROT=[-90,-90-phi,0] & T3D,ROT=[90-theta,0,0] IF N_ELEMENTS(r) GT 0 THEN T3D,PERS=r T3D,TR=[.5,.5,.0] ERASE RETURN,1 END