40 assert(
abs( sqrt(
dx*
dx + dy*dy + dz*dz ) - 1 ) < 1e-6 );
46 const double coslat = cos(
DEG2RAD * lat );
47 const double sinlat = sin(
DEG2RAD * lat );
48 const double coslon = cos(
DEG2RAD * lon );
49 const double sinlon = sin(
DEG2RAD * lon );
50 const double dr = coslat*coslon*
dx + coslat*sinlon*dy + sinlat*dz;
51 const double dlat = -sinlat*coslon/r*
dx - sinlat*sinlon/r*dy + coslat/r*dz;
52 const double dlon = -sinlon/coslat/r*
dx + coslon/coslat/r*dy;
57 if( za < ANGTOL || za > 180-
ANGTOL )
104 r = sqrt( x*x + y*y + z*z );
149 sqrt( r1*r1 + r2*r2 - 2 * r1 * r2 * cos(
DEG2RAD * dlat ) ) );
204 assert( lat_start >= -90 );
205 assert( lat_start <= 90 );
206 assert( lat_hit >= -90 );
207 assert( lat_hit <= 90 );
210 if( za_start == 0 || za_start == 180 ||
abs(lat_hit) == 90 )
214 else if(
abs( lat_hit ) < 1e-7 )
221 const Numeric b = 2 * ( t2 * ( x*
dx + y*dy ) - z*dz );
222 const Numeric c = t2 * ( x*x + y*y ) - z*z;
232 const Numeric e = -0.5*sqrt(b*b-4*a*c)/a;
241 if( l1 > 0 &&
abs(
sign(z+dz*l1)-zsign)>0.01 )
243 if( l2 > 0 &&
abs(
sign(z+dz*l2)-zsign)>0.01 )
253 if( lmin >= 0 && lmax < 1e-6 )
259 else if( lmax > 1e-6 )
271 r = sqrt( pow(xp,2.0) + pow(yp,2.0) + pow(z+dz*l,2.0) );
272 lon =
RAD2DEG * atan2( yp, xp );
326 if( lon_hit == lon_start || za_start == 0 || za_start == 180 ||
327 aa_start == 0 ||
abs(aa_start) == 180 )
332 const double tanlon = tan(
DEG2RAD * lon_hit );
333 l = ( y - x*tanlon ) / (
dx*tanlon - dy );
342 r = sqrt( pow(x+
dx*l,2.0) + pow(y+dy*l,2.0) + pow(zp,2.0) );
343 lat =
RAD2DEG * asin( zp / r );
411 assert( za_start <= 180 );
412 assert( lat_start >=lat1 && lat_start <= lat3 );
413 assert( lon_start >=lon5 && lon_start <= lon6 );
427 l =
max( 1e-9, r - r_start0 );
432 else if( za_start > 180-
ANGTOL )
440 l =
max( 1e-9, r_start0 - r );
454 if( rmax-rmin <
RTOL/10 )
460 {
if( r_start < rmax ) { r_start = r = rmax; } }
462 {
if( r_start > rmin ) { r_start = r = rmin; } }
464 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
465 za_start, ppc, x, y, z,
dx, dy, dz );
468 if( lat > lat3 || lat < lat1 || lon > lon6 || lon < lon5 )
478 {
if( r_start < rmin ) { r_start = rmin; } }
480 {
if( r_start > rmax ) { r_start = rmax; } }
486 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
487 za_start, ppc, x, y, z,
dx, dy, dz );
489 else if( r_start < rmin )
492 r_crossing_3d( lat, lon, l, r, r_start, lat_start, lon_start,
493 za_start, ppc, x, y, z,
dx, dy, dz );
496 { r = r_start; lat = lat_start; lon = lon_start; l = 0; }
499 if( lat < lat1 || lat > lat3 || lon < lon5 || lon > lon6 )
507 r15, r35, r36, r16, lat, lon );
511 {
if( r < rpl ) { r = rpl; } }
513 {
if( r > rpl ) { r = rpl; } }
518 { za = za_start; aa = aa_start; }
521 dx, dy, dz, ppc, lat_start, lon_start,
522 za_start, aa_start );
523 assert(
abs(d1-r) < 1e-3 );
524 assert(
abs(d2-lat) < 1e-8 );
525 assert(
abs(d3-lon) < 1e-8 );
531 r15, r35, r36, r16, lat, lon, aa );
545 if( lat < lat1 || lat > lat3 || lon < lon5 || lon > lon6 )
551 r15, r35, r36, r16, lat, lon );
552 distance3D( l, r_start, lat_start, lon_start, r, lat, lon );
652 poslos2cart( x, y, z,
dx, dy, dz, r_start, lat_start, lon_start,
653 za_start, aa_start );
657 za_start, aa_start, x, y, z,
dx, dy, dz, ppc,
658 lat1, lat3, lon5, lon6, r15a, r35a, r36a, r16a,
true );
663 if( rsurface15 >= r15a || rsurface35 >= r35a ||
664 rsurface36 >= r36a || rsurface16 >= r16a )
668 za_start, aa_start, x, y, z,
dx, dy, dz, ppc,
669 lat1, lat3, lon5, lon6, rsurface15, rsurface35,
670 rsurface36, rsurface16,
true );
672 if( rt > 0 && lt <= l )
673 { endface = 7; r = rt; lat = latt; lon = lont; l = lt; }
681 za_start, aa_start, x, y, z,
dx, dy, dz, ppc,
682 lat1, lat3, lon5, lon6, r15b, r35b, r36b, r16b,
684 if( rt > 0 && lt < l )
685 { endface = 4; r = rt; lat = latt; lon = lont; l = lt; }
692 x, y, z,
dx, dy, dz );
693 if( rt > 0 && lt < l )
694 { endface = 1; r = rt; lat = lat1; lon = lont; l = lt; }
701 x, y, z,
dx, dy, dz );
702 if( rt > 0 && lt < l )
703 { endface = 3; r = rt; lat = lat3; lon = lont; l = lt; }
707 if( !( r>0 && lat>=lat1 && lat<=lat3 && lon>=lon5 && lon<=lon6 ) )
711 x, y, z,
dx, dy, dz );
712 if( rt > 0 && lt < l )
713 { endface = 5; r = rt; lat = latt; lon = lon5; l = lt; }
717 if( !( r>0 && lat>=lat1 && lat<=lat3 && lon>=lon5 && lon<=lon6 ) )
721 x, y, z,
dx, dy, dz );
722 if( rt > 0 && lt < l )
723 { endface = 6; r = rt; lat = latt; lon = lon6; l = lt; }
736 za_start, aa_start, ppc );
749 n =
Index( ceil(
abs( l / lmax ) ) );
761 lat_v[0] = lat_start;
762 lon_v[0] = lon_start;
768 for(
Index j=1; j<=n; j++ )
772 cart2poslos( r_v[j], lat_v[j], lon_v[j], za_v[j], aa_v[j],
773 x+
dx*lj, y+dy*lj, z+dz*lj,
dx, dy, dz, ppc,
774 lat_start, lon_start, za_start, aa_start );
874 if( rsurface1 >= r1a || rsurface3 >= r3a )
878 lat1, lat3, rsurface1, rsurface3,
true );
880 if( rt > 0 && lt <= l )
881 { endface = 7; r = rt; lat = latt; l = lt; }
888 lat1, lat3, r1b, r3b,
false );
889 if( rt > 0 && lt < l )
890 { endface = 4; r = rt; lat = latt; }
897 { endface = 1; lat = lat1; }
899 { endface = 3; lat = lat3; }
908 if( absza > 90 && ( absza -
abs(lat_start-lat) ) < 90 )
911 { tanpoint =
false; }
914 za_start, r, tanpoint, lmax );
917 if( endface == 1 || endface == 3 )
918 { lat_v[lat_v.
nelem()-1] = lat; }
987 const Agenda& refr_index_air_agenda,
1010 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1011 t_field, vmr_field, f_grid, r1 );
1013 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1014 t_field, vmr_field, f_grid, r3 );
1015 if( refr3 < refr1 * (r1/r3) * sin(
DEG2RAD *
abs(za) ) )
1018 os <<
"For path between r1=" << r1 <<
"(n-1=" << refr1-1. <<
") and r2="
1019 << r3 <<
"(n-1=" << refr3-1. <<
"),\n"
1020 <<
"path calculation will run into refractive back-bending issues.\n"
1021 <<
"We are currently NOT ABLE to handle them. Consider repeating\n"
1022 <<
"your calculation without taking refraction into account.";
1023 throw runtime_error(os.str());
1031 Numeric refr_index_air, refr_index_air_group;
1033 refr_index_air_agenda, p_grid, refellipsoid, z_field,
1034 t_field, vmr_field, f_grid, r );
1035 r_array.push_back( r );
1036 lat_array.push_back( lat );
1037 za_array.push_back( za );
1038 n_array.push_back( refr_index_air );
1039 ng_array.push_back( refr_index_air_group );
1055 if( ( r < r1 -
RTOL ) || ( r > r3 +
RTOL ) )
1057 throw runtime_error(
1058 "Ooops. Path undetectedly left the grid cell.\n"
1059 "This should not happen. But there are issues with cases of high\n"
1060 "refractivity gradients. Seems you unfortunately encountered such\n"
1061 "a case. Little to be done about this now (if this is an option\n"
1062 "for you, run the case without considering refraction). For further\n"
1063 "details, contact Patrick Eriksson.");
1067 do_gridrange_1d( r_v, lat_v, za_v, lstep, endface, r, lat, za, ppc_step,
1068 -1, r1, r3, r_surface );
1069 assert( r_v.
nelem() == 2 );
1073 if( lstep <= lraytrace )
1078 za_flagside = za_v[1];
1090 { za_flagside = 80; }
1102 refr_index_air_agenda, p_grid, refellipsoid,
1103 z_field, t_field, vmr_field, f_grid, r );
1107 const Numeric ppc_local = ppc / refr_index_air;
1109 if( r >= ppc_local )
1118 if( ready || ( lmax > 0 && lcum + lraytrace > lmax ) )
1120 r_array.push_back( r );
1121 lat_array.push_back( lat );
1122 za_array.push_back( za );
1123 n_array.push_back( refr_index_air );
1124 ng_array.push_back( refr_index_air_group );
1125 l_array.push_back( lcum );