!! Copyright (C) Stichting Deltares, 2005-2020. !! !! This file is part of iMOD. !! !! This program is free software: you can redistribute it and/or modify !! it under the terms of the GNU General Public License as published by !! the Free Software Foundation, either version 3 of the License, or !! (at your option) any later version. !! !! This program is distributed in the hope that it will be useful, !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! GNU General Public License for more details. !! !! You should have received a copy of the GNU General Public License !! along with this program. If not, see . !! !! Contact: imod.support@deltares.nl !! Stichting Deltares !! P.O. Box 177 !! 2600 MH Delft, The Netherlands. !! MODULE MOD_3D_PROCESS USE MOD_3D_PAR USE MOD_DBL USE MOD_IDF, ONLY : IDFNULLIFY USE MOD_UTL, ONLY : UTL_MESSAGEHANDLE,UTL_ROTATE_XYZ,UTL_DIST,UTL_DIALOGSHOW USE MOD_3D_DISPLAY, ONLY : IMOD3D_DISPLAY,IMOD3D_RESET_TO_INIT USE MOD_3D_UTL, ONLY : IMOD3D_CLOSE,IMOD3D_GET_HEADING_TILE,IMOD3D_MAPWINDOWTOOBJ USE MOD_3D_ENGINE, ONLY : IMOD3D_SETUPAXES_LABELS,IMOD3D_LEGEND_MAIN,IMOD3D_IPF_LABELS,IMOD3D_SOL_ADD,IMOD3D_ADDARTIFICIALWELLS CONTAINS !###====================================================================== SUBROUTINE IMOD3D_FENCEINIT() !###====================================================================== IMPLICIT NONE CALL WDIALOGLOAD(ID_D3DSETTINGS_FENCES,ID_D3DSETTINGS_FENCES) CALL UTL_DIALOGSHOW(-1,-1,0,2) CALL WDIALOGFIELDOPTIONS(IDF_INTEGER1,3,1) CALL WDIALOGFIELDOPTIONS(IDF_INTEGER2,3,1) CALL WDIALOGFIELDOPTIONS(IDF_REAL3,3,1) IDRAWCROSS=-1; NXYZCROSS=0 END SUBROUTINE IMOD3D_FENCEINIT !###====================================================================== SUBROUTINE IMOD3D_FENCECOMPUTE() !###====================================================================== IMPLICIT NONE REAL(KIND=DP_KIND) :: A,X1,X2,Y1,Y2,DX,DY,X,Y,DXY,XM,YM,ZM,XP,YP,ZP,XX1,XX2,YY1,YY2, & XINTER,YINTER INTEGER :: J,K,KK,NX,NY,ISTATUS IF(.NOT.ASSOCIATED(XYZCROSS))RETURN CALL WDIALOGSELECT(ID_D3DSETTINGS_FENCES) CALL WDIALOGGETINTEGER(IDF_INTEGER1,NX) CALL WDIALOGGETINTEGER(IDF_INTEGER2,NY) CALL WDIALOGGETDOUBLE(IDF_REAL3,A) !## radians A=A/(360.0D0/(2.0D0*PI_OPENGL)) X1=BOT%X; X2=TOP%X; DX=X2-X1 Y1=BOT%Y; Y2=TOP%Y; DY=Y2-Y1 DXY=MAX(DX,DY) DX =DX/REAL(NX+1.0D0) DY =DY/REAL(NY+1.0D0) NXYZCROSS=0 K=0; X=X1 DO J=1,NX X=X+DX K=K+1 NXYZCROSS(K) =NXYZCROSS(K)+1 XYZCROSS(NXYZCROSS(K),K)%X=X XYZCROSS(NXYZCROSS(K),K)%Y=Y1 NXYZCROSS(K) =NXYZCROSS(K)+1 XYZCROSS(NXYZCROSS(K),K)%X=X XYZCROSS(NXYZCROSS(K),K)%Y=Y2 ENDDO Y=Y1 DO J=1,NY Y=Y+DY K=K+1 NXYZCROSS(K) =NXYZCROSS(K)+1 XYZCROSS(NXYZCROSS(K),K)%X=X1 XYZCROSS(NXYZCROSS(K),K)%Y=Y NXYZCROSS(K) =NXYZCROSS(K)+1 XYZCROSS(NXYZCROSS(K),K)%X=X2 XYZCROSS(NXYZCROSS(K),K)%Y=Y ENDDO !## rotate coordinates IF(A.NE.0.0D0)THEN XM=(TOP%X+BOT%X)/2.0 YM=(TOP%Y+BOT%Y)/2.0 ZM=0.0D0; ZP=0.0D0 DO K=1,SIZE(NXYZCROSS) DO KK=1,NXYZCROSS(K) XP=XYZCROSS(KK,K)%X-XM YP=XYZCROSS(KK,K)%Y-YM CALL UTL_ROTATE_XYZ(XP,YP,ZP,0.0D0,0.0D0,A) XYZCROSS(KK,K)%X=XM+XP XYZCROSS(KK,K)%Y=YM+YP ENDDO ENDDO !## get intersections with xy DO K=1,SIZE(NXYZCROSS) IF(NXYZCROSS(K).EQ.0)CYCLE X1=XYZCROSS(1,K)%X; Y1=XYZCROSS(1,K)%Y X2=XYZCROSS(2,K)%X; Y2=XYZCROSS(2,K)%Y !## compute intersection with west boundary XX1=BOT%X; XX2=BOT%X; YY1=BOT%Y; YY2=TOP%Y CALL DBL_IGRINTERSECTLINE(X1,Y1,X2,Y2,XX1,YY1,XX2,YY2,XINTER,YINTER,ISTATUS) IF(ISTATUS.EQ.4.OR.ISTATUS.EQ.5)THEN !## adjust nearest point IF(UTL_DIST(X1,Y1,XINTER,YINTER).LE.UTL_DIST(X2,Y2,XINTER,YINTER))THEN X1=XINTER; Y1=YINTER ELSE X2=XINTER; Y2=YINTER ENDIF ENDIF !## compute intersection with east boundary XX1=TOP%X; XX2=TOP%X; YY1=BOT%Y; YY2=TOP%Y CALL DBL_IGRINTERSECTLINE(X1,Y1,X2,Y2,XX1,YY1,XX2,YY2,XINTER,YINTER,ISTATUS) IF(ISTATUS.EQ.4.OR.ISTATUS.EQ.5)THEN !## adjust nearest point IF(UTL_DIST(X1,Y1,XINTER,YINTER).LE.UTL_DIST(X2,Y2,XINTER,YINTER))THEN X1=XINTER; Y1=YINTER ELSE X2=XINTER; Y2=YINTER ENDIF ENDIF !## compute intersection with north boundary XX1=BOT%X; XX2=TOP%X; YY1=TOP%Y; YY2=TOP%Y CALL DBL_IGRINTERSECTLINE(X1,Y1,X2,Y2,XX1,YY1,XX2,YY2,XINTER,YINTER,ISTATUS) IF(ISTATUS.EQ.4.OR.ISTATUS.EQ.5)THEN !## adjust nearest point IF(UTL_DIST(X1,Y1,XINTER,YINTER).LE.UTL_DIST(X2,Y2,XINTER,YINTER))THEN X1=XINTER; Y1=YINTER ELSE X2=XINTER; Y2=YINTER ENDIF ENDIF !## compute intersection with south boundary XX1=BOT%X; XX2=TOP%X; YY1=BOT%Y; YY2=BOT%Y CALL DBL_IGRINTERSECTLINE(X1,Y1,X2,Y2,XX1,YY1,XX2,YY2,XINTER,YINTER,ISTATUS) IF(ISTATUS.EQ.4.OR.ISTATUS.EQ.5)THEN !## adjust nearest point IF(UTL_DIST(X1,Y1,XINTER,YINTER).LE.UTL_DIST(X2,Y2,XINTER,YINTER))THEN X1=XINTER; Y1=YINTER ELSE X2=XINTER; Y2=YINTER ENDIF ENDIF XYZCROSS(1,K)%X=X1; XYZCROSS(1,K)%Y=Y1 XYZCROSS(2,K)%X=X2; XYZCROSS(2,K)%Y=Y2 ENDDO ENDIF CALL WDIALOGSELECT(ID_D3DSETTINGS) !## update display CALL IMOD3D_DISPLAY(1) END SUBROUTINE IMOD3D_FENCECOMPUTE !###====================================================================== SUBROUTINE IMOD3D_FENCECLOSE() !###====================================================================== IMPLICIT NONE CALL WDIALOGSELECT(ID_D3DSETTINGS_FENCES) CALL WDIALOGUNLOAD() CALL WDIALOGSELECT(ID_D3DSETTINGS) IDRAWCROSS=0; IDRAWCROSS=0; NXYZCROSS=0 END SUBROUTINE IMOD3D_FENCECLOSE !###====================================================================== SUBROUTINE IMOD3D_PROCESSKEYS(IKEY) !###====================================================================== IMPLICIT NONE INTEGER, INTENT(IN) :: IKEY REAL(KIND=DP_KIND) :: FACTOR SELECT CASE(CURSOR_KEY_FUNC) CASE (ZOOM) SELECT CASE(IKEY) CASE(KEYCURSORDOWN) FACTOR = 1.0_GLDOUBLE + .02_GLDOUBLE CASE (KEYCURSORUP) FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + .02_GLDOUBLE) CASE DEFAULT FACTOR = 1.0_GLDOUBLE END SELECT SHIFT%Z = FACTOR*SHIFT%Z CASE (PAN) SELECT CASE(IKEY) CASE (KEYCURSORRIGHT) SHIFT%X = SHIFT%X - 0.0D075 CASE (KEYCURSORLEFT) SHIFT%X = SHIFT%X + 0.0D075 CASE (KEYCURSORUP) SHIFT%Y = SHIFT%Y - 0.0D075 CASE (KEYCURSORDOWN) SHIFT%Y = SHIFT%Y + 0.0D075 END SELECT CASE (ROTATE) SELECT CASE(IKEY) CASE (KEYCURSORRIGHT) ANGLE%X = ANGLE%X - 1.0_GLDOUBLE CASE (KEYCURSORLEFT) ANGLE%X = ANGLE%X + 1.0_GLDOUBLE CASE (KEYCURSORUP) ANGLE%Y = ANGLE%Y + 1.0_GLDOUBLE CASE (KEYCURSORDOWN) ANGLE%Y = ANGLE%Y - 1.0_GLDOUBLE END SELECT CASE (SCALEX) SELECT CASE(IKEY) CASE (KEYCURSORDOWN) FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + .02_GLDOUBLE) CASE (KEYCURSORUP) FACTOR = 1.0_GLDOUBLE + .02_GLDOUBLE CASE DEFAULT FACTOR = 1.0_GLDOUBLE END SELECT XSCALE_FACTOR = XSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEY) SELECT CASE(IKEY) CASE (KEYCURSORDOWN) FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + .02_GLDOUBLE) CASE (KEYCURSORUP) FACTOR = 1.0_GLDOUBLE + .02_GLDOUBLE CASE DEFAULT FACTOR = 1.0_GLDOUBLE END SELECT YSCALE_FACTOR = YSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEZ) SELECT CASE(IKEY) CASE (KEYCURSORDOWN) FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + .02_GLDOUBLE) CASE (KEYCURSORUP) FACTOR = 1.0_GLDOUBLE + .02_GLDOUBLE CASE DEFAULT FACTOR = 1.0_GLDOUBLE END SELECT ZSCALE_FACTOR = ZSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEXY) SELECT CASE(IKEY) CASE (KEYCURSORDOWN,KEYCURSORLEFT) FACTOR = 1.0_GLDOUBLE + .02_GLDOUBLE CASE (KEYCURSORUP,KEYCURSORRIGHT) FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + .02_GLDOUBLE) CASE DEFAULT FACTOR = 1.0_GLDOUBLE END SELECT XSCALE_FACTOR = XSCALE_FACTOR * FACTOR YSCALE_FACTOR = YSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() END SELECT !## update display CALL IMOD3D_DISPLAY(1) END SUBROUTINE IMOD3D_PROCESSKEYS !###====================================================================== SUBROUTINE IMOD3D_PROCESSKEYS_WALK(IKEY) !###====================================================================== IMPLICIT NONE INTEGER, INTENT(IN) :: IKEY REAL(GLDOUBLE):: PERP REAL(GLDOUBLE) :: MAXSTEP=1.0_GLDOUBLE,MINSTEP=0.1_GLDOUBLE,STEP PERP=90.0D0/(360.0D0/(2.0D0*PI_OPENGL)) SELECT CASE (IKEY) !## elevator up CASE (KEYPAGEUP) STEP=MINSTEP LOOKFROM%Z=LOOKFROM%Z+SIN(TILT)*STEP LOOKAT%Z =LOOKAT%Z +SIN(TILT)*STEP !## elevator down CASE (KEYPAGEDOWN) STEP=-MINSTEP LOOKFROM%Z=LOOKFROM%Z+SIN(TILT)*STEP LOOKAT%Z =LOOKAT%Z +SIN(TILT)*STEP CASE (KEYDOWNEXTREME,KEYCURSORDOWN,KEYUPEXTREME,KEYCURSORUP) IF(IKEY.EQ.KEYCURSORUP) STEP=-MINSTEP IF(IKEY.EQ.KEYUPEXTREME) STEP=-MAXSTEP IF(IKEY.EQ.KEYCURSORDOWN) STEP= MINSTEP IF(IKEY.EQ.KEYDOWNEXTREME)STEP= MAXSTEP LOOKFROM%X=LOOKFROM%X-COS(HEADING)*STEP LOOKFROM%Y=LOOKFROM%Y-SIN(HEADING)*STEP LOOKFROM%Z=LOOKFROM%Z-SIN(TILT)*STEP LOOKAT%X =LOOKAT%X -COS(HEADING)*STEP LOOKAT%Y =LOOKAT%Y -SIN(HEADING)*STEP LOOKAT%Z =LOOKAT%Z -SIN(TILT)*STEP CASE (KEYCURSORLEFT) STEP =MINSTEP HEADING =HEADING-PERP LOOKFROM%X=LOOKFROM%X-COS(HEADING)*STEP LOOKFROM%Y=LOOKFROM%Y-SIN(HEADING)*STEP LOOKAT%X =LOOKAT%X-COS(HEADING)*STEP LOOKAT%Y =LOOKAT%Y-SIN(HEADING)*STEP HEADING =HEADING+PERP CASE (KEYCURSORRIGHT) STEP =MINSTEP HEADING =HEADING+PERP LOOKFROM%X=LOOKFROM%X-COS(HEADING)*STEP LOOKFROM%Y=LOOKFROM%Y-SIN(HEADING)*STEP LOOKAT%X =LOOKAT%X-COS(HEADING)*STEP LOOKAT%Y =LOOKAT%Y-SIN(HEADING)*STEP HEADING =HEADING-PERP END SELECT CALL IMOD3D_RESET_TO_INIT() CALL IMOD3D_DISPLAY(1) END SUBROUTINE IMOD3D_PROCESSKEYS_WALK !###====================================================================== SUBROUTINE IMOD3D_PROCESSMOUSEBUTTON(ITYPE,IBUTTON,X_WINT,Y_WINT) !###====================================================================== IMPLICIT NONE INTEGER,INTENT(IN) :: ITYPE,IBUTTON,X_WINT,Y_WINT REAL(KIND=DP_KIND) :: X,Y INTEGER :: I !## convert winteracter window units to pixels X=X_WINT Y=Y_WINT SELECT CASE (ITYPE) CASE (MOUSEBUTDOWN) SELECT CASE (IBUTTON) CASE (LEFTBUTTON) IF(IDRAWWELL.EQ.1.AND.IVALIDPOS.EQ.1)THEN !## add current point to list of points I=NXYZWELL; I=I+1; NXYZWELL=I XYZWELL(NXYZWELL)%X=INDPOS%X XYZWELL(NXYZWELL)%Y=INDPOS%Y XYZWELL(NXYZWELL)%Z=INDPOS%Z ELSEIF(IDRAWCROSS.EQ.1.AND.IVALIDPOS.EQ.1)THEN !## add current point to list of points NXYZCROSS(1)=NXYZCROSS(1)+1 XYZCROSS(NXYZCROSS(1),1)%X=INDPOS%X XYZCROSS(NXYZCROSS(1),1)%Y=INDPOS%Y ELSE MOVING_LEFT = .TRUE. BEGIN_LEFT = CART2D(X,Y) ENDIF CASE (MIDDLEBUTTON) MOVING_MIDDLE = .TRUE. BEGIN_MIDDLE = CART2D(X,Y) CASE (RIGHTBUTTON) !## stop adding a well IF(IDRAWWELL.EQ.1)THEN IDRAWWELL=0 !## add the wells CALL IMOD3D_ADDARTIFICIALWELLS(3,0.0D0,0.0D0,'') NXYZWELL=0; IDRAWWELL=0 IF(WMENUGETSTATE(ID_SHOW3DCOORDINATES,2).EQ.0)ISHOW3DCRD=0 ELSEIF(IDRAWCROSS.EQ.1)THEN !## stop drawing a cross-section - create the cross-section IDRAWCROSS=0 IF(IMOD3D_SOL_ADD())THEN; ENDIF ELSE MOVING_RIGHT = .TRUE. BEGIN_RIGHT = CART2D(X,Y) ENDIF END SELECT IMOUSEMOVE=1 CASE (MOUSEBUTUP) SELECT CASE (IBUTTON) CASE (LEFTBUTTON) MOVING_LEFT = .FALSE. CASE (MIDDLEBUTTON) MOVING_MIDDLE = .FALSE. CASE (RIGHTBUTTON) MOVING_RIGHT = .FALSE. END SELECT IMOUSEMOVE=0 END SELECT END SUBROUTINE IMOD3D_PROCESSMOUSEBUTTON !###====================================================================== SUBROUTINE IMOD3D_PROCESSMOUSEMOVE(MESSAGE) !###====================================================================== IMPLICIT NONE TYPE(WIN_MESSAGE),INTENT(IN) :: MESSAGE INTEGER :: X_WINT,Y_WINT REAL(KIND=DP_KIND) :: X,Y,Z INTEGER :: BUTTON_FUNCTION,IX,IY TYPE(CART2D) :: BEGIN LOGICAL :: LINDPOS=.FALSE. X_WINT=MESSAGE%X Y_WINT=MESSAGE%Y !## no mouse move currently active IF(IMOUSEMOVE.EQ.0)THEN CALL IMOD3D_MAPWINDOWTOOBJ(MESSAGE,X,Y,Z) CALL IMOD3D_DISPLAY(1) RETURN ENDIF !## convert winteracter window units to pixels IX=X_WINT IY=Y_WINT IF (MOVING_LEFT) THEN BUTTON_FUNCTION = LEFT_BUTTON_FUNC BEGIN = BEGIN_LEFT ELSE IF (MOVING_MIDDLE) THEN BUTTON_FUNCTION = MIDDLE_BUTTON_FUNC BEGIN = BEGIN_MIDDLE ELSE IF (MOVING_RIGHT) THEN BUTTON_FUNCTION = RIGHT_BUTTON_FUNC BEGIN = BEGIN_RIGHT ELSE RETURN END IF X=IX Y=IY IF(MOVING_MIDDLE.AND.LINDPOS)THEN INDPOS%X = INDPOS%X + .01*(X - BEGIN%X) INDPOS%Y = INDPOS%Y - .01*(Y - BEGIN%Y) CALL IMOD3D_DISPLAY(1) BEGIN_MIDDLE = CART2D(X,Y) ELSE CALL IMOD3D_PROCESSMOUSEMOVE_ADJUST(X,Y,BUTTON_FUNCTION,BEGIN) ENDIF END SUBROUTINE IMOD3D_PROCESSMOUSEMOVE !###====================================================================== SUBROUTINE IMOD3D_PROCESSMOUSEMOVE_ADJUST(X,Y,BUTTON_FUNCTION,BEGIN) !###====================================================================== REAL(KIND=DP_KIND),INTENT(IN) :: X,Y INTEGER,INTENT(IN) :: BUTTON_FUNCTION TYPE(CART2D),INTENT(IN) :: BEGIN REAL(KIND=GLDOUBLE) :: FACTOR REAL(KIND=GLDOUBLE) :: FSCALE_ZOOM=0.05_GLDOUBLE REAL(KIND=GLDOUBLE) :: FPAN ! =5.0_GLDOUBLE !## dependent content REAL(KIND=GLDOUBLE) :: FROTATE =2.00_GLDOUBLE ! TYPE (SPHERE3D) :: SLOOKFROM !## apply zoom level to it ... FPAN=(TOP%X-BOT%X)/500.0D0 SELECT CASE(BUTTON_FUNCTION) CASE (ZOOM) IF (Y < BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + FSCALE_ZOOM*(BEGIN%Y-Y)) ELSE IF (Y > BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE + FSCALE_ZOOM*(Y-BEGIN%Y) ELSE FACTOR = 1.0_GLDOUBLE END IF SHIFT%Z = FACTOR*SHIFT%Z CASE (PAN) SHIFT%X = SHIFT%X + FPAN*(X - BEGIN%X) SHIFT%Y = SHIFT%Y - FPAN*(Y - BEGIN%Y) ! SLOOKFROM = CART2SPHERE(LOOKFROM-LOOKAT) !WRITE(*,*) SLOOKFROM ! SHIFT%X = INIT_SHIFTX ! SHIFT%Y = INIT_SHIFTY ! SHIFT%Z = INIT_SHIFTZ-SLOOKFROM%RHO ! LOOKAT%X=LOOKAT%X-SHIFT%X ! LOOKAT%Y=LOOKAT%Y-SHIFT%Y ! LOOKAT%Z=LOOKAT%Z+SHIFT%Z ! SLOOKFROM = CART2SPHERE(LOOKFROM-LOOKAT) ! SHIFT%X=INIT_SHIFTX ! SHIFT%Y=INIT_SHIFTY ! SHIFT%Z=INIT_SHIFTZ !-SLOOKFROM%RHO !WRITE(*,*) SLOOKFROM ! CALL IMOD3D_SETLOOKAT_LOOKFROM() !## rest point of rotation CASE (ROTATE) ANGLE%X = ANGLE%X + (X - BEGIN%X) /FROTATE ANGLE%Y = ANGLE%Y + (Y - BEGIN%Y) /FROTATE CASE (SCALEX) IF (Y < BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE + FSCALE_ZOOM*(BEGIN%Y-Y) ELSE IF (Y > BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + FSCALE_ZOOM*(Y-BEGIN%Y)) ELSE FACTOR = 1.0_GLDOUBLE END IF XSCALE_FACTOR = XSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEY) IF (Y < BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE + FSCALE_ZOOM*(BEGIN%Y-Y) ELSE IF (Y > BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + FSCALE_ZOOM*(Y-BEGIN%Y)) ELSE FACTOR = 1.0_GLDOUBLE END IF YSCALE_FACTOR = YSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEZ) IF (Y < BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE + FSCALE_ZOOM*(BEGIN%Y-Y) ELSE IF (Y > BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + FSCALE_ZOOM*(Y-BEGIN%Y)) ELSE FACTOR = 1.0_GLDOUBLE END IF ZSCALE_FACTOR = ZSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() CASE (SCALEXY) IF (Y < BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE + FSCALE_ZOOM*(BEGIN%Y-Y) ELSE IF (Y > BEGIN%Y) THEN FACTOR = 1.0_GLDOUBLE/(1.0_GLDOUBLE + FSCALE_ZOOM*(Y-BEGIN%Y)) ELSE FACTOR = 1.0_GLDOUBLE END IF XSCALE_FACTOR = XSCALE_FACTOR * FACTOR YSCALE_FACTOR = YSCALE_FACTOR * FACTOR CALL IMOD3D_SETUPAXES_LABELS() CALL IMOD3D_IPF_LABELS() END SELECT IF (MOVING_LEFT .OR. MOVING_RIGHT .OR. MOVING_MIDDLE) CALL IMOD3D_DISPLAY(1) !## update variables and redisplay IF (MOVING_LEFT) THEN BEGIN_LEFT = CART2D(X,Y) ELSE IF (MOVING_MIDDLE) THEN BEGIN_MIDDLE = CART2D(X,Y) ELSE IF (MOVING_RIGHT) THEN BEGIN_RIGHT = CART2D(X,Y) END IF END SUBROUTINE IMOD3D_PROCESSMOUSEMOVE_ADJUST !###====================================================================== SUBROUTINE IMOD3D_PROCESSMOUSEMOVE_WALK(X_WINT,Y_WINT) !###====================================================================== IMPLICIT NONE INTEGER,INTENT(IN) :: X_WINT,Y_WINT INTEGER :: IX,IY REAL(KIND=GLDOUBLE) :: DX,DZ,ANGLE REAL(KIND=DP_KIND) :: WX,WY !## not left mouse button pressed IF(.NOT.MOVING_LEFT)RETURN !## convert winteracter window units to pixels IX=X_WINT IY=Y_WINT !## get current heading and tilt CALL IMOD3D_GET_HEADING_TILE(LENXY=DX,LENXZ=DZ) WX=REAL(IX); WY=REAL(IY) !## viewable angle (radians) ANGLE=(FOVY/(360.0D0/(2.0D0*PI_OPENGL)))/(REAL(IWINWIDTH)/10.0D0) !## change heading/tilt according to mouse movement HEADING=HEADING+(BEGIN_LEFT%X-WX)*ANGLE TILT =TILT +(BEGIN_LEFT%Y-WY)*ANGLE LOOKAT%X=LOOKFROM%X+COS(HEADING)*DX LOOKAT%Y=LOOKFROM%Y+SIN(HEADING)*DX LOOKAT%Z=LOOKFROM%Z+SIN(TILT)*DZ CALL IMOD3D_RESET_TO_INIT() CALL IMOD3D_DISPLAY(1) BEGIN_LEFT%X=WX BEGIN_LEFT%Y=WY END SUBROUTINE IMOD3D_PROCESSMOUSEMOVE_WALK !###====================================================================== SUBROUTINE IMOD3D_PROCESSRESIZE(ID1,ID2) !###====================================================================== IMPLICIT NONE INTEGER,INTENT(IN) :: ID1,ID2 IWINWIDTH =ID1 ! GET NEW WINDOW SIZE IWINHEIGHT =ID2 CALL GLDRAWBUFFER(GL_FRONT_AND_BACK) !## reinitialize perspective settings RAT=REAL(ID1)/REAL(ID2) CALL GLMATRIXMODE(GL_PROJECTION) CALL GLLOADIDENTITY() IF(IORTHO.EQ.0)THEN CALL GLUPERSPECTIVE(FOVY,RAT,ZNEAR,ZFAR) ELSEIF(IORTHO.EQ.1)THEN CALL GLORTHO(BOT%X,TOP%X,BOT%Y,TOP%Y,ZNEAR,ZFAR) !ZLEFT,ZRIGHT,ZTOP,ZBOTTOM ENDIF CALL GLMATRIXMODE(GL_MODELVIEW) CALL GLVIEWPORT(0_GLSIZEI,0_GLSIZEI,IWINWIDTH,IWINHEIGHT) ! ADJUST VIEWPORT CALL GLDRAWBUFFER(GL_BACK) CALL IMOD3D_LEGEND_MAIN() CALL IMOD3D_DISPLAY(1) ! RE-DO CURRENT DISPLAY END SUBROUTINE END MODULE MOD_3D_PROCESS