00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010       subroutine prismtrs_pole_intersection(location, &
00011                       intrsct_lat,intrsct_lon,lcoinc,lthresh, &
00012                       beglat, beglon, endlat, endlon, begseg, lrevers, &
00013                       num_srch_cells, id_nbcorners, &
00014                       srch_corner_lat, srch_corner_lon, srch_add)
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022         
00023       USE PRISMDrv, dummy_INTERFACE => PRISMTrs_pole_intersection
00024       IMPLICIT NONE
00025 
00026 
00027 
00028       INTEGER, INTENT(in) :: num_srch_cells, id_nbcorners
00029       DOUBLE PRECISION, DIMENSION(id_nbcorners, num_srch_cells), INTENT(in) ::
00030            srch_corner_lat, srch_corner_lon
00031       INTEGER, DIMENSION(num_srch_cells), INTENT(in) :: srch_add
00032         
00033       DOUBLE PRECISION, intent(in) :: 
00034            beglat, beglon,  
00035            endlat, endlon   
00036 
00037       DOUBLE PRECISION, dimension(2), intent(inout) :: 
00038            begseg 
00039 
00040       logical, intent(in) :: 
00041               lrevers   
00042 
00043 
00044 
00045       integer, intent(inout) :: 
00046               location  
00047                         
00048                         
00049 
00050       logical, intent(out) :: 
00051              lcoinc    
00052 
00053       logical, intent(inout) :: 
00054              lthresh   
00055 
00056       DOUBLE PRECISION, intent(out) :: 
00057           intrsct_lat, intrsct_lon 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081   CHARACTER(LEN=len_cvs_string), SAVE  :: mycvs = 
00082      '$Id: prismtrs_pole_intersection.F90 2082 2009-10-21 13:31:19Z hanke $'
00083       integer  :: n, next_n, cell, srch_corners
00084 
00085       logical  :: loutside 
00086 
00087       DOUBLE PRECISION :: pi4, rns,  
00088           x1, x2,       
00089           y1, y2,       
00090           begx, begy,   
00091           endx, endy,   
00092           begsegx, begsegy,   
00093           grdx1, grdx2,  
00094           grdy1, grdy2,  
00095           vec1_y, vec1_x,  
00096           vec2_y, vec2_x,  
00097           cross_product, eps,  
00098           s1, s2, determ,     
00099           mat1, mat2, mat3, mat4, rhs1, rhs2  
00100 
00101       DOUBLE PRECISION, dimension(:,:), allocatable :: 
00102            srch_corner_x,  
00103            srch_corner_y   
00104 
00105       
00106       
00107       
00108       
00109 
00110       logical, save :: luse_last = .false.
00111 
00112       DOUBLE PRECISION, save :: 
00113            intrsct_x, intrsct_y  
00114 
00115       
00116       
00117       
00118 
00119       integer, save :: 
00120            avoid_pole_count = 0  
00121 
00122       DOUBLE PRECISION, save :: 
00123            avoid_pole_offset = tiny  
00124 
00125 #ifdef VERBOSE
00126   PRINT *, '| | | | | | | Enter PRISMTrs_pole_intersection'
00127   call psmile_flushstd
00128 #endif
00129 
00130 
00131 
00132 
00133 
00134 
00135       if (.not. lthresh) location = 0
00136       lcoinc = .false.
00137       intrsct_lat = endlat
00138       intrsct_lon = endlon
00139 
00140       loutside = .false.
00141       s1 = zero
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149       allocate(srch_corner_x(size(srch_corner_lat,DIM=1), &
00150                              size(srch_corner_lat,DIM=2)), &
00151                srch_corner_y(size(srch_corner_lat,DIM=1), &
00152                             size(srch_corner_lat,DIM=2)))
00153 
00154       if (beglat > zero) then
00155         pi4 = quart*dble_pi
00156         rns = one
00157       else
00158         pi4 = -quart*dble_pi
00159         rns = -one
00160       endif
00161 
00162       if (luse_last) then
00163         x1 = intrsct_x
00164         y1 = intrsct_y
00165       else
00166         x1 = rns*two*sin(pi4 - half*beglat)*cos(beglon)
00167         y1 =     two*sin(pi4 - half*beglat)*sin(beglon)
00168         luse_last = .true.
00169       endif
00170       x2 = rns*two*sin(pi4 - half*endlat)*cos(endlon)
00171       y2 =     two*sin(pi4 - half*endlat)*sin(endlon)
00172       srch_corner_x = rns*two*sin(pi4 - half*srch_corner_lat)* &
00173                               cos(srch_corner_lon)
00174       srch_corner_y =     two*sin(pi4 - half*srch_corner_lat)* &
00175                               sin(srch_corner_lon)
00176 
00177       begx = x1
00178       begy = y1
00179       endx = x2
00180       endy = y2
00181       begsegx = rns*two*sin(pi4 - half*begseg(1))*cos(begseg(2))
00182       begsegy =     two*sin(pi4 - half*begseg(1))*sin(begseg(2))
00183       intrsct_x = endx
00184       intrsct_y = endy
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193       
00194       srch_corners = size(srch_corner_lat,DIM=1)
00195       srch_loop: do
00196 
00197         
00198         
00199         
00200 
00201         if (lthresh) then
00202           do cell=1,num_srch_cells
00203             if (srch_add(cell) == location) then
00204               eps = tiny
00205               exit srch_loop
00206             endif
00207           end do
00208         endif
00209 
00210         
00211         
00212         
00213 
00214         cell_loop: do cell=1,num_srch_cells
00215           corner_loop: do n=1,srch_corners
00216             next_n = MOD(n,srch_corners) + 1
00217 
00218             
00219             
00220             
00221             
00222             
00223             
00224 
00225             vec1_x = srch_corner_x(next_n,cell) -  &
00226                     srch_corner_x(n     ,cell)
00227             vec1_y = srch_corner_y(next_n,cell) -  &
00228                     srch_corner_y(n     ,cell)
00229             vec2_x = x1 - srch_corner_x(n,cell)
00230             vec2_y = y1 - srch_corner_y(n,cell)
00231 
00232             
00233             
00234             
00235             
00236 
00237             if (vec2_x == 0 .and. vec2_y == 0) then
00238               x1 = x1 + 1.d-10*(x2-x1)
00239               y1 = y1 + 1.d-10*(y2-y1)
00240               vec2_x = x1 - srch_corner_x(n,cell)
00241               vec2_y = y1 - srch_corner_y(n,cell)
00242             endif
00243 
00244             cross_product = vec1_x*vec2_y - vec2_x*vec1_y
00245 
00246             
00247             
00248             
00249             
00250             
00251             
00252             
00253             
00254             
00255             
00256             
00257 
00258             if (cross_product == zero) then
00259               if (vec1_x /= zero .or. vec1_y /= 0) then
00260                 vec2_x = x2 - x1
00261                 vec2_y = y2 - y1
00262                 cross_product = vec1_x*vec2_y - vec2_x*vec1_y
00263               else
00264                 cross_product = one
00265               endif
00266 
00267               if (cross_product == zero) then
00268                 lcoinc = .true.
00269                 cross_product = vec1_x*vec2_x + vec1_y*vec2_y
00270                 if (lrevers) cross_product = -cross_product
00271               endif
00272             endif
00273 
00274             
00275             
00276             
00277             
00278 
00279             if (cross_product < zero) exit corner_loop
00280 
00281           end do corner_loop
00282 
00283           
00284           
00285           
00286 
00287           if (n > srch_corners) then
00288             location = srch_add(cell)
00289 
00290             
00291             
00292             
00293             
00294             
00295 
00296             if (loutside) then
00297               x2 = begx
00298               y2 = begy
00299               location = 0
00300               eps  = -tiny
00301             else
00302               eps  = tiny
00303             endif
00304 
00305             exit srch_loop
00306           endif
00307 
00308           
00309           
00310           
00311 
00312         end do cell_loop
00313 
00314         
00315         
00316         
00317         
00318         
00319 
00320         loutside = .true.
00321         s1 = s1 + baby
00322         x1 = begx + s1*(x2 - begx)
00323         y1 = begy + s1*(y2 - begy)
00324 
00325         
00326         
00327         
00328         
00329 
00330         if (s1 >= one) then
00331           deallocate(srch_corner_x, srch_corner_y)
00332           luse_last = .false.
00333           return
00334         endif
00335 
00336       end do srch_loop
00337       
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347       
00348       intrsct_loop: do n=1,srch_corners
00349         next_n = mod(n,srch_corners) + 1
00350 
00351         grdy1 = srch_corner_y(n     ,cell)
00352         grdy2 = srch_corner_y(next_n,cell)
00353         grdx1 = srch_corner_x(n     ,cell)
00354         grdx2 = srch_corner_x(next_n,cell)
00355 
00356         
00357         
00358         
00359 
00360         mat1 = x2 - x1
00361         mat2 = grdx1 - grdx2
00362         mat3 = y2 - y1
00363         mat4 = grdy1 - grdy2
00364         rhs1 = grdx1 - x1
00365         rhs2 = grdy1 - y1
00366 
00367         determ = mat1*mat4 - mat2*mat3
00368 
00369         
00370         
00371         
00372         
00373         
00374         
00375         
00376         
00377         
00378         
00379         
00380 
00381         if (abs(determ) > 1.e-30) then
00382 
00383           s1 = (rhs1*mat4 - mat2*rhs2)/determ
00384           s2 = (mat1*rhs2 - rhs1*mat3)/determ
00385  
00386           if (s2 >= zero .and. s2 <= one .and.   &
00387               s1 >  zero .and. s1 <= one) then
00388 
00389             
00390             
00391             
00392             
00393 
00394             if (.not. loutside) then
00395               mat1 = x2 - begsegx
00396               mat3 = y2 - begsegy
00397               rhs1 = grdx1 - begsegx
00398               rhs2 = grdy1 - begsegy
00399             else 
00400               mat1 = x2 - endx
00401               mat3 = y2 - endy
00402               rhs1 = grdx1 - endx
00403               rhs2 = grdy1 - endy
00404             endif
00405 
00406             determ = mat1*mat4 - mat2*mat3
00407 
00408             
00409             
00410             
00411             
00412             
00413             
00414 
00415             if (determ /= zero) then
00416               s1 = (rhs1*mat4 - mat2*rhs2)/determ
00417               s2 = (mat1*rhs2 - rhs1*mat3)/determ
00418 
00419               if (.not. loutside) then
00420                 intrsct_x = begsegx + s1*mat1
00421                 intrsct_y = begsegy + s1*mat3
00422               else 
00423                 intrsct_x = endx + s1*mat1
00424                 intrsct_y = endy + s1*mat3
00425               endif
00426 
00427               
00428               
00429               
00430 
00431               intrsct_lon = rns*atan2(intrsct_y,intrsct_x)
00432               if (intrsct_lon < zero)  &
00433                 intrsct_lon = intrsct_lon + dble_pi2
00434 
00435               if (abs(intrsct_x) > 1.d-10) then
00436                 intrsct_lat = (pi4 -  &
00437                   asin(rns*half*intrsct_x/cos(intrsct_lon)))*two
00438               else if (abs(intrsct_y) > 1.d-10) then
00439                 intrsct_lat = (pi4 -  &
00440                   asin(half*intrsct_y/sin(intrsct_lon)))*two
00441               else
00442                 intrsct_lat = two*pi4
00443               endif
00444 
00445               
00446               
00447               
00448 
00449               if (s1 - eps/determ < one) then
00450                 intrsct_x = intrsct_x - mat1*(eps/determ)
00451                 intrsct_y = intrsct_y - mat3*(eps/determ)
00452               else
00453                 if (.not. loutside) then
00454                   intrsct_x = endx
00455                   intrsct_y = endy
00456                   intrsct_lat = endlat
00457                   intrsct_lon = endlon
00458                 else 
00459                   intrsct_x = begsegx
00460                   intrsct_y = begsegy
00461                   intrsct_lat = begseg(1)
00462                   intrsct_lon = begseg(2)
00463                 endif
00464               endif
00465 
00466               exit intrsct_loop
00467             endif
00468           endif
00469         endif
00470 
00471         
00472         
00473         
00474 
00475       end do intrsct_loop
00476       
00477 
00478       deallocate(srch_corner_x, srch_corner_y)
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488       if (abs(intrsct_x) < 1.e-10 .and. abs(intrsct_y) < 1.e-10 .and. &
00489          (endx /= zero .and. endy /=0)) then
00490         if (avoid_pole_count > 2) then
00491            avoid_pole_count = 0
00492            avoid_pole_offset = 10.*avoid_pole_offset
00493         endif
00494 
00495         cross_product = begsegx*(endy-begsegy) - begsegy*(endx-begsegx)
00496         intrsct_lat = begseg(1)
00497         if (cross_product*intrsct_lat > zero) then
00498           intrsct_lon = beglon    + avoid_pole_offset
00499           begseg(2)   = begseg(2) + avoid_pole_offset
00500         else
00501           intrsct_lon = beglon    - avoid_pole_offset
00502           begseg(2)   = begseg(2) - avoid_pole_offset
00503         endif
00504 
00505         avoid_pole_count = avoid_pole_count + 1
00506         luse_last = .false.
00507       else
00508         avoid_pole_count = 0
00509         avoid_pole_offset = tiny
00510       endif
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522       if (lthresh) then
00523         if (intrsct_lat > north_thresh .or. intrsct_lat < south_thresh) &
00524          lthresh = .false.
00525       else if (beglat > zero .and. intrsct_lat < north_thresh) then
00526         mat4 = endlat - begseg(1)
00527         mat3 = endlon - begseg(2)
00528         if (mat3 >  dble_pi) mat3 = mat3 - dble_pi2
00529         if (mat3 < -dble_pi) mat3 = mat3 + dble_pi2
00530         intrsct_lat = north_thresh - tiny
00531         s1 = (north_thresh - begseg(1))/mat4
00532         intrsct_lon = begseg(2) + s1*mat3
00533         luse_last = .false.
00534         lthresh = .true.
00535       else if (beglat < zero .and. intrsct_lat > south_thresh) then
00536         mat4 = endlat - begseg(1)
00537         mat3 = endlon - begseg(2)
00538         if (mat3 >  dble_pi) mat3 = mat3 - dble_pi2
00539         if (mat3 < -dble_pi) mat3 = mat3 + dble_pi2
00540         intrsct_lat = south_thresh + tiny
00541         s1 = (south_thresh - begseg(1))/mat4
00542         intrsct_lon = begseg(2) + s1*mat3
00543         luse_last = .false.
00544         lthresh = .true.
00545       endif
00546 
00547       
00548       
00549       
00550       
00551 
00552       if (intrsct_lat == endlat .and. intrsct_lon == endlon) then
00553         luse_last = .false.
00554       endif
00555 #ifdef VERBOSE
00556   PRINT *, '| | | | | | | Quit PRISMTrs_pole_intersection'
00557   call psmile_flushstd
00558 #endif
00559 
00560 
00561       end subroutine PRISMTrs_pole_intersection
00562