MODULE Space USE f90_kind PRIVATE ! 2D coordinate ! point = Coordinate(X,Y) ! X = Pitch(point) ! Y = Length(point) PUBLIC :: Coordinate, Pitch, Length ! straight line ! track = Line(X,Phi) ! track = Line(point,phi) ! track = Line(pointA,pointB) ! track = Line(XYtrack,Y) ! getLine(track,X,Phi) ! X = getLineX(track,Y) ! Y = getLineY(track,X) PUBLIC :: Line, getLine, getLineX, getLineY ! curve with radius ! XYtrack = XYTrack(track,invRad) ! getXYTrack(myTrack,X,Phi,invRad) PUBLIC :: XYTrack, getXYTrack ! pad-types, pad can be rectangle or grid ! point = getCentre(pad) PUBLIC :: getCentre ! distance between two objects (1st argument has higher dimension): ! coordinate, line, rectangle, grid ! dist = Distance(A,B) PUBLIC :: Distance ! FillLoc(cX,cY,sX,sY,rect) ! FillLoc(cX,cY,sX,sY,mapNumber,grid) ! AllocBitMap(NumMaps) ! FillBitMap(mapNumber,bits) PUBLIC :: FillLoc, AllocBitMap, FillBitMap ! printGrid(grid) PUBLIC :: printGrid ! integral of Line over a pad (=rectangle or grid) ! integral = intTrackPad(track,width,pad) PUBLIC :: intTrackPad ! just for fun ! == (.EQ.) defined for coordinate and line PUBLIC :: OPERATOR(+), OPERATOR(-), OPERATOR(*), OPERATOR(==), ASSIGNMENT(=) PRIVATE :: assigna2i,assigna2r,assigna2d PRIVATE :: bitmap,recty PRIVATE :: FillRect,FillGrid PRIVATE :: getCentreRect,getCentreGrid,getCoordinate PRIVATE :: CoordinateD,CoordinateR,CoordinateRD,CoordinateDR PRIVATE :: assignCoord,assignCoordR,addCoord,subCoord,scaleCoordR,scaleCoordD PRIVATE :: prodCoord,sameCoord PRIVATE :: LineAngleD,LineAngleR,LinePktR,LinePktD,Line2Pkt PRIVATE :: LineXYTrackD,LineXYTrackR,XYTrackD,XYTrackR,sameLine PRIVATE :: getLineXD,getLineXR,getLineYD,getLineYR,sameXYTrack PRIVATE :: intTrackRect,eta,Corners,intTrackGrid PRIVATE :: DistXRect2Point,DistYRect2Point,DistXRect2Rect,DistYRect2Rect PRIVATE :: DistPoint2Point,SignDistLine2Point,DistLine2Point PRIVATE :: DistRect2Point,DistRect2Line,DistRect2Rect PRIVATE :: DistGrid2Point,DistGrid2Line,DistGrid2Grid ! if f90_kind is not available, select depending on compiler option ! kind parameter sequential byte ! integer: int8 1 1 ! int16 2 2 ! int32 3 4 ! int64 4 8 ! real: single 1 4 ! double 2 8 ! quad 3 16 ! logical: byte 1 1 ! twobyte 2 2 ! word 3 4 ! size of bitmap, can be adjusted INTEGER,PARAMETER,PRIVATE :: mapPrec=int32 INTEGER,PARAMETER,PUBLIC :: spPrec=double REAL(KIND=spPrec),PRIVATE :: sqrt2=1.414213562 , sqrt2pi=2.506628275 ! ###################### ! ! all measurements in mm ! ! ###################### ! TYPE,PUBLIC :: Coordinate_type PRIVATE REAL(KIND=spPrec) :: X , Y END TYPE Coordinate_type TYPE,PUBLIC :: Line_type PRIVATE REAL(KIND=spPrec) :: X0 , Phi END TYPE Line_type TYPE,PUBLIC :: XYTrack_type PRIVATE ! Slope: track at Y=0 ! invRadius > 0 : left part of circle ! invRadius < 0 : right part of circle ! |invRadius| < 1E-6 : straight Track ! -> sagitta of 125um for 1m long track TYPE(Line_type) :: Slope REAL(KIND=spPrec) :: invRadius END TYPE XYTrack_type TYPE,PUBLIC :: Rectangle_type PRIVATE TYPE(Coordinate_type) :: centre , size END TYPE Rectangle_type TYPE,PUBLIC :: Grid_type PRIVATE TYPE(Coordinate_type) :: centre , size INTEGER :: mapID END TYPE Grid_type TYPE,PRIVATE :: bitmap_type PRIVATE INTEGER :: nx,ny INTEGER(KIND=mapPrec),ALLOCATABLE,DIMENSION(:) :: bmap END TYPE bitmap_type TYPE(bitmap_type),PRIVATE,SAVE,ALLOCATABLE,DIMENSION(:) :: gridMap INTERFACE ASSIGNMENT (=) MODULE PROCEDURE assignCoord,assignCoordR & ,assigna2i,assigna2r,assigna2d END INTERFACE INTERFACE OPERATOR (+) MODULE PROCEDURE addCoord END INTERFACE INTERFACE OPERATOR (-) MODULE PROCEDURE subCoord END INTERFACE INTERFACE OPERATOR (*) MODULE PROCEDURE prodCoord, scaleCoordR, scaleCoordD END INTERFACE INTERFACE OPERATOR (==) MODULE PROCEDURE sameCoord, sameLine, sameXYtrack END INTERFACE INTERFACE Coordinate MODULE PROCEDURE CoordinateD,CoordinateR,CoordinateDR,CoordinateRD END INTERFACE INTERFACE Line MODULE PROCEDURE LineAngleD,LineAngleR,LinePktR,LinePktD,& Line2Pkt,LineXYTrackR,LineXYTrackD END INTERFACE INTERFACE getLineX MODULE PROCEDURE getLineXR,getLineXD END INTERFACE INTERFACE getLineY MODULE PROCEDURE getLineYR,getLineYD END INTERFACE INTERFACE XYTrack MODULE PROCEDURE XYTrackR,XYTrackD END INTERFACE INTERFACE Distance MODULE PROCEDURE DistPoint2Point,DistLine2Point,& DistRect2Point,DistRect2Line,DistRect2Rect,& DistGrid2Point,DistGrid2Line,DistGrid2Grid END INTERFACE ! need soubroutines since the return type of a function ! does not belong to the signature INTERFACE FillLoc MODULE PROCEDURE FillRect ,FillGrid END INTERFACE INTERFACE getCentre MODULE PROCEDURE getCentreRect,getCentreGrid END INTERFACE INTERFACE intTrackPad MODULE PROCEDURE intTrackRect,intTrackGrid END INTERFACE CONTAINS ! ******************************************************************* PURE SUBROUTINE assigna2i (i,a) INTEGER,INTENT(OUT) :: i INTEGER,DIMENSION(1),INTENT(IN) :: a i = a(1) END SUBROUTINE assigna2i PURE SUBROUTINE assigna2r (r,a) REAL,INTENT(OUT) :: r REAL,DIMENSION(1),INTENT(IN) :: a r = a(1) END SUBROUTINE assigna2r PURE SUBROUTINE assigna2d (d,a) REAL(KIND=double),INTENT(OUT) :: d REAL(KIND=double),DIMENSION(1),INTENT(IN) :: a d = a(1) END SUBROUTINE assigna2d ! ******************************************************************* PURE FUNCTION CoordinateD (X,Y) RESULT(point) TYPE(Coordinate_type) :: point REAL(KIND=spPrec),INTENT(IN) :: X,Y point%X = X point%Y = Y END FUNCTION CoordinateD PURE FUNCTION CoordinateR (X,Y) RESULT(point) TYPE(Coordinate_type) :: point REAL,INTENT(IN) :: X,Y point = CoordinateD(REAL(X,spPrec),REAL(Y,spPrec)) END FUNCTION CoordinateR PURE FUNCTION CoordinateRD (X,Y) RESULT(point) TYPE(Coordinate_type) :: point REAL,INTENT(IN) :: X REAL(KIND=spPrec),INTENT(IN) :: Y point = CoordinateD(REAL(X,spPrec),Y) END FUNCTION CoordinateRD PURE FUNCTION CoordinateDR (X,Y) RESULT(point) TYPE(Coordinate_type) :: point REAL(KIND=spPrec),INTENT(IN) :: X REAL,INTENT(IN) :: Y point = CoordinateD(X,REAL(Y,spPrec)) END FUNCTION CoordinateDR PURE SUBROUTINE assignCoord (point,X) TYPE(Coordinate_type),INTENT(OUT) :: point REAL(KIND=spPrec),DIMENSION(2),INTENT(IN) :: X point%X = X(1) point%Y = X(2) END SUBROUTINE assignCoord PURE SUBROUTINE assignCoordR (point,X) TYPE(Coordinate_type),INTENT(OUT) :: point REAL,DIMENSION(2),INTENT(IN) :: X point%X = X(1) point%Y = X(2) END SUBROUTINE assignCoordR PURE SUBROUTINE getCoordinate (point,X,Y) TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec),INTENT(OUT) :: X,Y X = point%X Y = point%Y END SUBROUTINE getCoordinate PURE FUNCTION Pitch(point) RESULT(w) TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: w w = point%x END FUNCTION Pitch PURE FUNCTION Length(point) RESULT(h) TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: h h = point%y END FUNCTION Length PURE FUNCTION addCoord (A,B) RESULT (AB) TYPE(Coordinate_type),INTENT(IN) :: A,B TYPE(Coordinate_type) :: AB AB%X = A%X + B%X AB%Y = A%Y + B%Y END FUNCTION addCoord PURE FUNCTION subCoord (A,B) RESULT (AB) TYPE(Coordinate_type),INTENT(IN) :: A,B TYPE(Coordinate_type) :: AB AB%X = A%X - B%X AB%Y = A%Y - B%Y END FUNCTION subCoord PURE FUNCTION scaleCoordD (A,R) RESULT (AR) TYPE(Coordinate_type),INTENT(IN) :: A REAL(KIND=spPrec),INTENT(IN) :: R TYPE(Coordinate_type) :: AR AR%X = A%X * R AR%Y = A%Y * R END FUNCTION scaleCoordD PURE FUNCTION scaleCoordR (A,R) RESULT (AR) TYPE(Coordinate_type),INTENT(IN) :: A REAL,INTENT(IN) :: R TYPE(Coordinate_type) :: AR AR = scaleCoordD (A,REAL(R,kind=spPrec)) END FUNCTION scaleCoordR PURE FUNCTION prodCoord (A,B) RESULT (AB) TYPE(Coordinate_type),INTENT(IN) :: A,B REAL(KIND=spPrec) :: AB,dX,dY dX = A%X * B%X dY = A%Y * B%Y AB = dX + dY END FUNCTION prodCoord PURE FUNCTION sameCoord (A,B) RESULT (same) TYPE(Coordinate_type),INTENT(IN) :: A,B LOGICAL :: same IF( A%X == B%X .and. A%Y == B%Y )THEN same = .TRUE. ELSE same = .FALSE. ENDIF END FUNCTION sameCoord ! ***************************************************************** PURE FUNCTION LineAngleD(X,P) RESULT(myLine) TYPE(Line_type) :: myLine REAL(KIND=spPrec),INTENT(IN) :: X,P REAL(KIND=spPrec) :: PP,PI,PI2 PARAMETER (PI=3.1415927_spPrec,PI2=PI/2.0_spPrec) PP = P IF( PP<-PI2 ) PP = -PI2 IF( PP> PI2 ) PP = PI2 myLine%X0 = X myLine%Phi = PP END FUNCTION LineAngleD PURE FUNCTION LineAngleR(X,P) RESULT(myLine) TYPE(Line_type) :: myLine REAL,INTENT(IN) :: X,P myLine = LineAngleD(REAL(X,spPrec),REAL(P,spPrec)) END FUNCTION LineAngleR PURE FUNCTION LinePktR(Point,P) RESULT(myLine) TYPE(Line_type) :: myLine TYPE(Coordinate_type),INTENT(IN) :: Point REAL,INTENT(IN) :: P myLine = LinePktD(Point,REAL(P,spPrec)) END FUNCTION LinePktR PURE FUNCTION LinePktD(Point,P) RESULT(myLine) TYPE(Line_type) :: myLine TYPE(Coordinate_type),INTENT(IN) :: Point REAL(KIND=spPrec),INTENT(IN) :: P REAL(KIND=spPrec) :: X0,PP,PI,PI2 PARAMETER (PI=3.1415927_spPrec,PI2=PI/2.0_spPrec) PP = P IF( PP<-PI2 ) PP = -PI2 IF( PP> PI2 ) PP = PI2 X0 = Point%X - TAN(PP)*Point%Y myLine = LineAngleD(X0,PP) END FUNCTION LinePktD PURE FUNCTION Line2Pkt(A,B) RESULT(myLine) TYPE(Line_type) :: myLine TYPE(Coordinate_type),INTENT(IN) :: A,B REAL(KIND=spPrec) :: Phi,dx,dy,PI,PI2 PARAMETER (PI=3.1415927,PI2=PI/2.0) dx = A%X - B%X dy = A%Y - B%Y Phi = PI2-ATAN2(dy,dx) IF( Phi > PI2 ) Phi = Phi - PI myLine = LinePktD(A,Phi) END FUNCTION Line2Pkt PURE FUNCTION LineXYTrackD(myTrack,Y) RESULT(myLine) TYPE(XYTrack_type),INTENT(IN) :: myTrack REAL(KIND=spPrec),INTENT(IN) :: Y TYPE(Line_type) :: myLine REAL(KIND=spPrec) :: Radius,PhiNew,X,RR,PhiTrk,X0Trk IF( ABS(myTrack%invRadius)<1.0E-16_spPrec )THEN myLine = myTrack%Slope ELSE Radius = 1.0_spPrec/myTrack%invRadius X0Trk = myTrack%Slope%X0 PhiTrk = myTrack%Slope%Phi ! center of circle ! CenterX = X0Trk + cos(PhiTrk) * Radius ! CenterY = - sin(PhiTrk) * Radius ! PhiNew = asin((Y-CenterY)/Radius) ! X = CenterX - cos(PhiNew)*Radius ! or X = X0Trk + (cos(PhiTrk)-cos(PhiNew))*Radius ! numerically more stable: RR = Y/Radius + sin(PhiTrk) IF( abs(RR)<1.0 )THEN PhiNew = asin( Y/Radius + sin(PhiTrk) ) X = X0Trk + Y * tan((PhiTrk+PhiNew)*0.5_spPrec) myLine = Line(Coordinate(X,Y),PhiNew) ELSE ! can't deal with curlers myLine = myTrack%Slope ENDIF ENDIF END FUNCTION LineXYTrackD PURE FUNCTION LineXYTrackR(myTrack,Y) RESULT(myLine) TYPE(XYTrack_type),INTENT(IN) :: myTrack REAL,INTENT(IN) :: Y TYPE(Line_type) :: myLine myLine = LineXYTrackD(myTrack,REAL(Y,spPrec)) END FUNCTION LineXYTrackR PURE SUBROUTINE getLine(myLine,X,P) TYPE(Line_type),INTENT(IN) :: myLine REAL(KIND=spPrec),INTENT(OUT) :: X,P X = myLine%X0 P = myLine%Phi END SUBROUTINE getLine PURE FUNCTION getLineXD(myLine,Y) RESULT(X) ! line X at a given Y TYPE(Line_type),INTENT(IN) :: myLine REAL(KIND=spPrec),INTENT(IN) :: Y REAL(KIND=spPrec) :: X X = myLine%X0 + TAN(myLine%Phi)*Y END FUNCTION getLineXD PURE FUNCTION getLineXR(myLine,Y) RESULT(X) ! line X at a given Y TYPE(Line_type),INTENT(IN) :: myLine REAL,INTENT(IN) :: Y REAL(KIND=spPrec) :: X X = getLineXD(myLine,REAL(Y,spPrec)) END FUNCTION getLineXR PURE FUNCTION getLineYD(myLine,X) RESULT(Y) ! line Y at a given X TYPE(Line_type),INTENT(IN) :: myLine REAL(KIND=spPrec),INTENT(IN) :: X REAL(KIND=spPrec) :: Y Y = (X - myLine%X0)/TAN(myLine%Phi) END FUNCTION getLineYD PURE FUNCTION getLineYR(myLine,X) RESULT(Y) ! line Y at a given X TYPE(Line_type),INTENT(IN) :: myLine REAL,INTENT(IN) :: X REAL(KIND=spPrec) :: Y Y = getLineYD(myLine,REAL(X,spPrec)) END FUNCTION getLineYR FUNCTION sameLine (A,B) RESULT (same) TYPE(Line_type),INTENT(IN) :: A,B LOGICAL :: same IF( A%X0 == B%X0 .and. A%PHI == B%PHI )THEN same = .TRUE. ELSE same = .FALSE. ENDIF END FUNCTION sameLine ! ***************************************************************** PURE FUNCTION XYTrackD(myLine,invRad) RESULT(myTrack) TYPE(Line_type),INTENT(IN) :: myLine REAL(KIND=spPrec),INTENT(IN) :: invRad TYPE(XYTrack_type) :: myTrack myTrack%Slope = myLine myTrack%invRadius = invRad END FUNCTION XYTrackD PURE FUNCTION XYTrackR(myLine,invRad) RESULT(myTrack) TYPE(Line_type),INTENT(IN) :: myLine REAL,INTENT(IN) :: invRad TYPE(XYTrack_type) :: myTrack myTrack = XYTrackD(myLine,REAL(invRad,spPrec)) END FUNCTION XYTrackR PURE SUBROUTINE getXYTrack(myTrack,X,P,iR) TYPE(XYTrack_type),INTENT(IN) :: myTrack REAL(KIND=spPrec),INTENT(OUT) :: X,P,iR CALL getLine(myTrack%Slope,X,P) iR = myTrack%invRadius END SUBROUTINE getXYTrack FUNCTION sameXYTrack (A,B) RESULT (same) TYPE(XYTrack_type),INTENT(IN) :: A,B LOGICAL :: same IF( A%slope == B%slope .and. A%invRadius == B%invRadius )THEN same = .TRUE. ELSE same = .FALSE. ENDIF END FUNCTION sameXYTrack ! ***************************************************************** PURE SUBROUTINE FillRect(cX,cY,sX,sY,rect) REAL(KIND=spPrec),INTENT(IN) :: cX,cY,sX,sY TYPE(Rectangle_type),INTENT(OUT) :: rect rect%centre%X = cX rect%centre%Y = cY rect%size%X = sX rect%size%Y = sY END SUBROUTINE FillRect PURE FUNCTION getCentreRect(rect) RESULT(point) TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type) :: point point = rect%centre END FUNCTION getCentreRect ! ***************************************************************** PURE SUBROUTINE FillGrid(cX,cY,sX,sY,mapNumber,grid) REAL(KIND=spPrec),INTENT(IN) :: cX,cY,sX,sY INTEGER ,INTENT(IN):: mapNumber TYPE(Grid_type),INTENT(OUT) :: grid grid%centre%X = cX grid%centre%Y = cY grid%size%X = sX grid%size%Y = sY grid%mapID = mapNumber END SUBROUTINE FillGrid PURE FUNCTION getCentreGrid(grid) RESULT(point) TYPE(Grid_type),INTENT(IN) :: grid TYPE(Coordinate_type) :: point INTEGER :: ix,iy REAL(KIND=spPrec) :: nRect TYPE(bitmap_type) :: thismap INTEGER(KIND=mapPrec) :: mapline ! very short version ! X = grid%centre%X ! Y = grid%centre%Y thismap = gridMap(grid%mapID) Point = Coordinate(0.0,0.0) nRect = 0.0 DO ix = 1,thismap%nx mapline = thismap%bmap(ix) DO iy = 1,thismap%ny IF( btest(mapline,iy) ) THEN Point = Point + getCentreRect(recty(grid,ix,iy)) nRect = nRect + 1.0 ENDIF ENDDO ENDDO nRect = 1.0 / nRect Point = Point * nRect END FUNCTION getCentreGrid SUBROUTINE printGrid(grid) TYPE(Grid_type),INTENT(IN) :: grid INTEGER :: ix,iy REAL(KIND=spPrec) :: X,Y TYPE(bitmap_type) :: thismap INTEGER(KIND=mapPrec) :: mapline CHARACTER(LEN=30) :: CHLINE CHLINE=" " CALL getCoordinate(getCentreGrid(grid),X,Y) thismap = gridMap(grid%mapID) print*,thismap%nx," * ",thismap%ny," center:",x,y DO ix = 1,thismap%nx mapline = thismap%bmap(ix) DO iy = 1,thismap%ny IF( btest(mapline,iy) ) THEN CHLINE(iy:iy)="X" ELSE CHLINE(iy:iy)="." ENDIF ENDDO print*,CHLINE ENDDO print*,"----------------------------------------" END SUBROUTINE printGrid PURE FUNCTION bitmap(bits) RESULT(mymap) TYPE(bitmap_type) :: mymap CHARACTER(LEN=1),DIMENSION(:,:),INTENT(IN) :: bits INTEGER :: nx,ny,ix,iy INTEGER(KIND=mapPrec) :: mapline nx = size(bits,1) ny = size(bits,2) IF( bit_size(mapline) < ny)THEN mymap%nx = -1 mymap%ny = -1 RETURN ENDIF ALLOCATE( mymap%bmap(nx) ) mymap%nx = nx mymap%ny = ny DO ix = 1,nx mapline = 0 DO iy = 1,ny IF( bits(ix,iy)/=" " .AND. bits(ix,iy)/=".") & mapline = ibset( mapline,iy ) ENDDO mymap%bmap(ix) = mapline ENDDO END FUNCTION bitmap SUBROUTINE AllocBitMap(NumMaps) INTEGER,INTENT(IN) :: NumMaps ALLOCATE(gridMap(NumMaps)) END SUBROUTINE AllocBitMap SUBROUTINE FillBitMap(mapNumber,bits) INTEGER,INTENT(IN) :: mapNumber CHARACTER(LEN=1),DIMENSION(:,:),INTENT(IN) :: bits gridMap(mapNumber) = bitmap(bits) END SUBROUTINE FillBitMap PURE FUNCTION recty(grid,ix,iy) RESULT(rect) TYPE(Grid_type),INTENT(IN) :: grid INTEGER,INTENT(IN) :: ix,iy TYPE(Rectangle_type) :: rect REAL(KIND=spPrec) :: nx,ny,cX,cY,sX,sY nx = gridMap(grid%mapID)%nx ny = gridMap(grid%mapID)%ny sX = grid%size%X / nx sY = grid%size%Y / ny cX = grid%centre%X + (REAL(ix)-0.5-nx/2.0)*sX cY = grid%centre%Y + (REAL(iy)-0.5-ny/2.0)*sY CALL FillLoc(cX,cY,sX,sY,rect) END FUNCTION recty ! *** help routines for distance *********************************** PURE SUBROUTINE Corners(rect,point) ! returns the four corners of a rectangle ! corner index: 3 4 ! 1 2 TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type),DIMENSION(4),INTENT(OUT) :: point REAL(KIND=spPrec) :: dx , dy dx = rect%size%X / 2.0 dy = rect%size%Y / 2.0 point(1)%x = rect%centre%X - dx point(1)%y = rect%centre%Y - dy point(2)%x = rect%centre%X + dx point(2)%y = rect%centre%Y - dy point(3)%x = rect%centre%X - dx point(3)%y = rect%centre%Y + dy point(4)%x = rect%centre%X + dx point(4)%y = rect%centre%Y + dy END SUBROUTINE Corners FUNCTION DistXRect2Point(rect,point) RESULT(dist) TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type),INTENT(IN) :: point TYPE(Coordinate_type),DIMENSION(4) :: rectCorner REAL(KIND=spPrec) :: dist, distRight, distLeft CALL Corners(rect,rectCorner) distRight = point%X - rectCorner(2)%X distLeft = - point%X + rectCorner(1)%X dist = max( distRight,distLeft ) END FUNCTION DistXRect2Point FUNCTION DistYRect2Point(rect,point) RESULT(dist) TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type),INTENT(IN) :: point TYPE(Coordinate_type),DIMENSION(4) :: rectCorner REAL(KIND=spPrec) :: dist, distUp, distLow CALL Corners(rect,rectCorner) distUp = point%Y - rectCorner(3)%Y distLow = - point%Y + rectCorner(1)%Y dist = max( distUp,distLow ) END FUNCTION DistYRect2Point FUNCTION DistXRect2Rect(A,B) RESULT(mindist) ! distance LC(RR) - RC(LR) ! (= left corner (right rectangle) - right corner (left rectangle)) ! LC(LR) - RC(RR) is always (more) negative TYPE(Rectangle_type),INTENT(IN) :: A,B TYPE(Coordinate_type),DIMENSION(4) :: PointA,PointB REAL(KIND=spPrec) :: mindist,dist1,dist2 CALL Corners(A,PointA) ! get the 4 corners of A CALL Corners(B,PointB) ! get the 4 corners of B dist1 = PointA(1)%X - PointB(2)%X dist2 = PointB(1)%X - PointA(2)%X mindist = max(dist1,dist2) END FUNCTION DistXRect2Rect FUNCTION DistYRect2Rect(A,B) RESULT(mindist) ! distance LC(UR) - UC(LR) ! (= lower corner (upper rectangle) - upper corner (lower rectangle)) ! LC(LR) - UC(UR) is always (more) negative TYPE(Rectangle_type),INTENT(IN) :: A,B TYPE(Coordinate_type),DIMENSION(4) :: PointA,PointB REAL(KIND=spPrec) :: mindist,dist1,dist2 CALL Corners(A,PointA) ! get the 4 corners of A CALL Corners(B,PointB) ! get the 4 corners of B dist1 = PointA(1)%Y - PointB(3)%Y dist2 = PointB(1)%Y - PointA(3)%Y mindist = max(dist1,dist2) END FUNCTION DistYRect2Rect FUNCTION SignDistLine2Point(myline,point) RESULT(dist) TYPE(Line_type),INTENT(IN) :: myline TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: dist,dx ! signed distance: line passes to the right >0 ; left <0 dx = myline%X0 + point%Y*TAN(myline%Phi) - point%X dist = dx*COS(myline%Phi) END FUNCTION SignDistLine2Point ! *** routines for Distance: *************************************** FUNCTION DistPoint2Point(A,B) RESULT(dist) TYPE(Coordinate_type),INTENT(IN) :: A,B TYPE(Coordinate_type) :: AsubB REAL(KIND=spPrec) :: dist AsubB = A - B dist = SQRT( AsubB*AsubB ) END FUNCTION DistPoint2Point FUNCTION DistLine2Point(myline,point) RESULT(dist) TYPE(Line_type),INTENT(IN) :: myline TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: dist dist = ABS( SignDistLine2Point(myline,point) ) END FUNCTION DistLine2Point FUNCTION DistRect2Point(rect,point) RESULT(dist) TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: dist,dX,dY dX = DistXRect2Point(rect,point) dY = DistYRect2Point(rect,point) IF( dX<=0 .AND. dY<=0 )THEN ! point is inside rectangle, distance to border (negative) dist = max(dX,dY) ELSE dX = max(dX,0.0_spPrec) dY = max(dY,0.0_spPrec) dist = SQRT( dX**2 + dY**2 ) ENDIF END FUNCTION DistRect2Point FUNCTION DistRect2Line(rect,myline) RESULT(dist) TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Line_type),INTENT(IN) :: myline TYPE(Coordinate_type),DIMENSION(4) :: reCorner REAL(KIND=spPrec) :: dist,mindist,cd,distA,distB,dx,dy,fac,PI,PI4 REAL(KIND=spPrec),DIMENSION(4) :: cdist PARAMETER (PI=3.1415927,PI4=PI/4.0) INTEGER :: npos,nneg,I CALL Corners(rect,reCorner) mindist = huge(mindist) npos = 0 nneg = 0 DO I=1,4 cd = SignDistLine2Point(myline,reCorner(I)) cdist(I) = cd IF( cd > 1.0E-5 )THEN npos = npos+1 ELSEIF( cd < -1.0E-5 )THEN nneg = nneg+1 ENDIF mindist = MIN( mindist,ABS(cd) ) ENDDO IF( npos == 4 .OR. nneg==4 )THEN ! all corners pointing to same direction dist = mindist ELSE ! line passes through rectangle ; it's supposed to be ! the largest circle with centre on the line ! that fits into the rectangle (negative) fac = COS( ABS(myline%Phi)-PI4 )*SQRT(2.0) IF( myline%Phi > 0.0 )THEN distA = -cdist(2)/fac distB = cdist(3)/fac ELSE distA = cdist(1)/fac distB = -cdist(4)/fac ENDIF IF( distA < 0.0 .OR. distB < 0.0 )THEN IF( distA < -1.0E-5 ) print*,"WARNING: DistRect2Line> distA should be >0",distA IF( distB < -1.0E-5 ) print*,"WARNING: DistRect2Line> distB should be >0",distB dist = 0.0 ELSE dx = rect%size%X / 2.0 dy = rect%size%Y / 2.0 dist = -min(distA,distB,dx,dy) ENDIF ENDIF END FUNCTION DistRect2Line FUNCTION DistRect2Rect(A,B) RESULT(dist) TYPE(Rectangle_type),INTENT(IN) :: A,B REAL(KIND=spPrec) :: dist,dX,dY dX = DistXRect2Rect(A,B) dY = DistYRect2Rect(A,B) IF( dX<=0.0 .AND. dY<=0.0 )THEN ! rectangles overlap by (negative) dist = max(dX,dY) ELSE dX = max(dX,0.0_spPrec) dY = max(dY,0.0_spPrec) dist = SQRT( dX**2 + dY**2 ) ENDIF END FUNCTION DistRect2Rect FUNCTION DistGrid2Point(grid,point) RESULT(dist) TYPE(Grid_type),INTENT(IN) :: grid TYPE(Coordinate_type),INTENT(IN) :: point REAL(KIND=spPrec) :: dist INTEGER :: ix,iy TYPE(bitmap_type) :: thismap INTEGER(KIND=mapPrec) :: mapline thismap = gridMap(grid%mapID) dist = huge(dist) DO ix = 1,thismap%nx mapline = thismap%bmap(ix) DO iy = 1,thismap%ny IF( btest(mapline,iy) ) & dist = min(dist,Distance( recty(grid,ix,iy),point )) ENDDO ENDDO END FUNCTION DistGrid2Point FUNCTION DistGrid2Line(grid,myline) RESULT(dist) TYPE(Grid_type),INTENT(IN) :: grid TYPE(Line_type),INTENT(IN) :: myline REAL(KIND=spPrec) :: dist INTEGER :: ix,iy TYPE(bitmap_type) :: thismap INTEGER(KIND=mapPrec) :: mapline thismap = gridMap(grid%mapID) dist = huge(dist) DO ix = 1,thismap%nx mapline = thismap%bmap(ix) DO iy = 1,thismap%ny IF( btest(mapline,iy) ) & dist = min(dist,Distance( recty(grid,ix,iy),myline )) ENDDO ENDDO END FUNCTION DistGrid2Line FUNCTION DistGrid2Grid(A,B) RESULT(dist) TYPE(Grid_type),INTENT(IN) :: A,B REAL(KIND=spPrec) :: dist INTEGER :: ixA,iyA,ixB,iyB TYPE(bitmap_type) :: Amap,Bmap TYPE(Rectangle_type) :: Arect,Brect INTEGER(KIND=mapPrec) :: Aline,Bline Amap = gridMap(A%mapID) Bmap = gridMap(B%mapID) dist = huge(dist) DO ixA = 1,Amap%nx Aline = Amap%bmap(ixA) DO iyA = 1,Amap%ny IF( btest(Aline,iyA) ) THEN Arect = recty(A,ixA,iyA) DO ixB = 1,Bmap%nx Bline = Bmap%bmap(ixB) DO iyB = 1,Bmap%ny IF( btest(Bline,iyB) ) THEN Brect = recty(B,ixB,iyB) dist = min(dist,distance(Arect,Brect)) ENDIF ENDDO ENDDO ENDIF ENDDO ENDDO END FUNCTION DistGrid2Grid ! ******************************************************************* ! integral of a track over a pad FUNCTION intTrackRect(track,width,rect) RESULT(integral) TYPE(Line_type),INTENT(IN) :: track REAL(KIND=spPrec),INTENT(IN) :: width TYPE(Rectangle_type),INTENT(IN) :: rect TYPE(Coordinate_type),DIMENSION(4) :: point REAL(KIND=spPrec),DIMENSION(4) :: dPkt REAL(KIND=spPrec) :: tpcchr,integral,X,P,sinP,cosP,X1,X2,dfreq,mindist INTEGER :: I CALL Corners(rect,point) DO I=1,4 dPkt(I) = SignDistLine2Point(track,point(I)) ENDDO CALL getLine(track,X,P) sinP = sin(P) cosP = cos(P) mindist = minval(abs(dPkt)) IF( mindist > 5.0 * width )THEN ! track more than 5 sigma away from pad tpcchr = 0.0 ELSEIF( mindist > 3.0*width .AND. mindist> 5.0*rect%size%x)THEN ! track more than 3 sigma away from pad and more than 5 pads between tpcchr = 0.0 ELSE IF( abs(sinP)<1.0E-5_spPrec )THEN ! track parallel to pad X1 = (dPkt(1)+dPkt(3)) / (2.0*width) X2 = (dPkt(2)+dPkt(4)) / (2.0*width) tpcchr = ( dfreq(X1)-dfreq(X2) )*rect%size%Y ELSE ! Deans formula tpcchr = eta(dPkt(3),width)-eta(dPkt(1),width) & +eta(dPkt(2),width)-eta(dPkt(4),width) tpcchr = tpcchr / sinP/cosP ENDIF ENDIF IF( tpcchr<0.0 )THEN print*,"WARNING: intTrackRect> numerical problems",P,tpcchr tpcchr = 0.0 ENDIF integral = tpcchr END FUNCTION intTrackRect FUNCTION ETA(u,s) RESULT(x) REAL(KIND=spPrec),INTENT(IN) :: u,s REAL(KIND=spPrec) :: expo,x,derf expo = max(-100.0_spPrec,-u*u/s/s/2.0_spPrec) x = u/2.0_spPrec*derf(u/sqrt2/s) + s/sqrt2pi*exp(expo) END FUNCTION ETA FUNCTION intTrackGrid(track,width,grid) RESULT(integral) TYPE(Line_type),INTENT(IN) :: track REAL(KIND=spPrec),INTENT(IN) :: width TYPE(Grid_type),INTENT(IN) :: grid TYPE(Rectangle_type) :: rect TYPE(bitmap_type) :: thismap INTEGER(KIND=mapPrec) :: mapline REAL(KIND=spPrec) :: dist,integral,X,P,nRect INTEGER :: ix,iy CALL getLine(track,X,P) thismap = gridMap(grid%mapID) integral = 0.0 nRect = 0.0 DO ix = 1,thismap%nx mapline = thismap%bmap(ix) DO iy = 1,thismap%ny IF( btest(mapline,iy) ) THEN rect = recty(grid,ix,iy) dist = Distance(track,rect%centre) integral = integral + & exp(- (dist/width)**2/2.0_spPrec ) / width / sqrt2pi nRect = nRect + 1.0 ENDIF ENDDO ENDDO integral = integral/nRect END FUNCTION intTrackGrid END MODULE Space