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