!! Copyright (C) Stichting Deltares, 2005-2014. !! !! 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_INTERSECT USE MOD_POLINT, ONLY : POL1LOCATE USE MOD_INTERSECT_PAR PRIVATE :: INTERSECT_EQUATION,INTERSECT_SORT DOUBLE PRECISION,PRIVATE :: XBEGIN,YBEGIN,A,B INTEGER,PRIVATE :: IHOR,IVER CONTAINS !###====================================================================== SUBROUTINE INTERSECT_EQUI(XMIN,XMAX,YMIN,YMAX,CSZ,X1,X2,Y1,Y2,N) !###====================================================================== IMPLICIT NONE REAL,INTENT(IN) :: XMIN,XMAX,YMIN,YMAX,CSZ REAL,INTENT(INOUT) :: X1,X2,Y1,Y2 INTEGER,INTENT(INOUT) :: N DOUBLE PRECISION :: X,Y,XMN,XMX,YMN,YMX,DX,DY,LENG,CS !,BLENG INTEGER :: I,ICOL,IROW,N_IN IF(.NOT.ASSOCIATED(XA))ALLOCATE(XA(1000)) IF(.NOT.ASSOCIATED(YA))ALLOCATE(YA(1000)) IF(.NOT.ASSOCIATED(LN))ALLOCATE(LN(1000)) N_IN=N CS=CSZ IF(.NOT.INTERSECT_EQUATION(XMIN,XMAX,YMIN,YMAX,X1,X2,Y1,Y2,N))RETURN !## find search box - result can be negative, does not matter! I=1 XMN=XMIN+CS*(INT((X1-XMIN)/CS)+I) I=0 DX=X2-XMIN IF(MOD(DX,CS).EQ.0.0)I=-1 XMX=XMIN+CS*(INT((X2-XMIN)/CS)+I) Y =MIN(Y1,Y2) I =0 DY=YMAX-Y IF(MOD(DY,CS).EQ.0.0)I=-1 YMN=YMAX-CS*(INT((YMAX-Y)/CS)+I) Y =MAX(Y1,Y2) I =1 YMX=YMAX-CS*(INT((YMAX-Y)/CS)+I) !## continue seach rest of intersections !## try intersections with y-axes firstly Y=YMN-CS DO Y=Y+CS IF(Y.GT.YMX)EXIT N=N+1 CALL INTERSECT_RESIZEVECTORS(N) YA(N)=Y IF(IVER.EQ.1)THEN XA(N)=X1 !## same as xmx ELSE XA(N)=(Y-B)/A ENDIF ENDDO !## try intersections with x-axes secondly X=XMN-CS DO X=X+CS IF(X.GT.XMX)EXIT N=N+1 CALL INTERSECT_RESIZEVECTORS(N) XA(N)=X IF(IHOR.EQ.1)THEN YA(N)=Y1 !MN !## same as ymx ELSE YA(N)=A*X+B ENDIF ENDDO DX=X1-X2; DY=Y2-Y1 CALL INTERSECT_SORT(DX,DY,N_IN+1,N) !## sample each of the point to determine irow/icol, overwrite point with this !## skip first and last, they represented already by the second and one-last point DO I=N_IN+2,N !## mid point X =(XA(I-1)+XA(I))/2.0 Y =(YA(I-1)+YA(I))/2.0 ICOL = INT((X-XMIN)/CS)+1 IROW = INT((YMAX-Y)/CS)+1 DX = XA(I)-XA(I-1) DY = YA(I)-YA(I-1) LENG=DX**2.0+DY**2.0; IF(LENG.GT.0.0)LENG=SQRT(LENG) !## store results XA(I-1)= REAL(ICOL) YA(I-1)= REAL(IROW) LN(I-1)= LENG END DO N=N-1 END SUBROUTINE INTERSECT_EQUI !###====================================================================== SUBROUTINE INTERSECT_NONEQUI(DELR,DELC,NROW,NCOL,X1,X2,Y1,Y2,N) !###====================================================================== IMPLICIT NONE INTEGER,INTENT(IN) :: NROW,NCOL REAL,INTENT(IN),DIMENSION(0:NCOL) :: DELR REAL,INTENT(IN),DIMENSION(0:NROW) :: DELC REAL,INTENT(INOUT) :: X1,X2,Y1,Y2 INTEGER,INTENT(INOUT) :: N DOUBLE PRECISION :: X,Y,DX,DY,LENG INTEGER :: I,ICOL,IROW,IMN,IMX,N_IN IF(.NOT.ASSOCIATED(XA))ALLOCATE(XA(1000)) IF(.NOT.ASSOCIATED(YA))ALLOCATE(YA(1000)) IF(.NOT.ASSOCIATED(LN))ALLOCATE(LN(1000)) N_IN=N IF(.NOT.INTERSECT_EQUATION(DELR(0),DELR(NCOL),DELC(NROW),DELC(0),X1,X2,Y1,Y2,N))RETURN !## continue seach rest of intersections !## try intersections with y-axes firstly IMN=NROW IF(MIN(Y1,Y2).GT.DELC(NROW))CALL POL1LOCATE(DELC,NROW+1,REAL(MIN(Y1,Y2),8),IMN) IMX=1 IF(MAX(Y1,Y2).LT.DELC(0))CALL POL1LOCATE(DELC,NROW+1,REAL(MAX(Y1,Y2),8),IMX) IMX=IMX-1 !## need only in between lines! DO I=IMX+1,IMN-1 N =N+1 CALL INTERSECT_RESIZEVECTORS(N) Y =DELC(I) YA(N)=Y IF(IVER.EQ.1)THEN XA(N)=X1 !## same as xmx ELSE XA(N)=(Y-B)/A ENDIF END DO !## try intersections with x-axes secondly IMN=1 IF(MIN(X1,X2).GT.DELR(0))CALL POL1LOCATE(DELR,NCOL+1,REAL(MIN(X1,X2),8),IMN) IMN=IMN-1 IMX=NCOL IF(MAX(X1,X2).LT.DELR(NCOL))CALL POL1LOCATE(DELR,NCOL+1,REAL(MAX(X1,X2),8),IMX) !## need only in between lines DO I=IMN+1,IMX-1 N =N+1 CALL INTERSECT_RESIZEVECTORS(N) X =DELR(I) XA(N)=X IF(IHOR.EQ.1)THEN YA(N)=Y1 !MN !## same as ymx ELSE YA(N)=A*X+B ENDIF END DO DX=X1-X2; DY=Y2-Y1 CALL INTERSECT_SORT(DX,DY,N_IN+1,N) !## sample each of the point to determine irow/icol, overwrite point with this !## skip first and last, they represented already by the second and one-last point DO I=2,N !## mid point X =(XA(I-1)+XA(I))/2.0 Y =(YA(I-1)+YA(I))/2.0 CALL POL1LOCATE(DELR,NCOL+1,REAL(X,8),ICOL) CALL POL1LOCATE(DELC,NROW+1,REAL(Y,8),IROW) DX =XA(I)-XA(I-1) DY =YA(I)-YA(I-1) LENG=SQRT(DX**2.0+DY**2.0) !## store results XA(I-1)=REAL(ICOL) YA(I-1)=REAL(IROW) LN(I-1)=LENG END DO N=N-1 END SUBROUTINE INTERSECT_NONEQUI !###====================================================================== SUBROUTINE INTERSECT_NULLIFY() !###====================================================================== IMPLICIT NONE NULLIFY(XA,YA,LN) END SUBROUTINE INTERSECT_NULLIFY !###====================================================================== SUBROUTINE INTERSECT_DEALLOCATE() !###====================================================================== IMPLICIT NONE IF(ASSOCIATED(XA))DEALLOCATE(XA) IF(ASSOCIATED(YA))DEALLOCATE(YA) IF(ASSOCIATED(LN))DEALLOCATE(LN) END SUBROUTINE INTERSECT_DEALLOCATE !###====================================================================== SUBROUTINE INTERSECT_RESIZEVECTORS(N) !###====================================================================== IMPLICIT NONE INTEGER,PARAMETER :: DN=100 INTEGER,INTENT(IN) :: N INTEGER :: MM,NN IF(N.LE.SIZE(XA))RETURN NN=SIZE(XA) MM=NN+DN ALLOCATE(XA_DUMMY(MM),YA_DUMMY(MM),LN_DUMMY(MM)) XA_DUMMY(1:NN)=XA(1:NN); YA_DUMMY(1:NN)=YA(1:NN); LN_DUMMY(1:NN)=LN(1:NN) DEALLOCATE(XA,YA,LN) XA=>XA_DUMMY; YA=>YA_DUMMY; LN=>LN_DUMMY END SUBROUTINE INTERSECT_RESIZEVECTORS !###====================================================================== LOGICAL FUNCTION INTERSECT_EQUATION(XMIN,XMAX,YMIN,YMAX,X1,X2,Y1,Y2,N) !###====================================================================== IMPLICIT NONE REAL,INTENT(IN) :: XMIN,XMAX,YMIN,YMAX REAL,INTENT(INOUT) :: X1,X2,Y1,Y2 INTEGER,INTENT(INOUT) :: N DOUBLE PRECISION :: X,Y,DX,DY INTERSECT_EQUATION=.FALSE. IF((MIN(X1,X2).GT.XMAX.OR.MAX(X1,X2).LT.XMIN).OR. & (MIN(Y1,Y2).GT.YMAX.OR.MAX(Y1,Y2).LT.YMIN))RETURN XBEGIN=X1; YBEGIN=Y1 !## arrange x1,x2,y1,y2 such that x1