1 #include "AntarcticaGeometry.h" 2 #include "AnitaGeomTool.h" 3 #include "RampdemReader.h" 6 #include "UsefulAdu5Pat.h" 12 #ifdef USE_GEOGRAPHIC_LIB 13 #include "GeographicLib/GeodesicLine.hpp" 14 #include "GeographicLib/Geodesic.hpp" 22 template <
int coarseness>
27 double compute(
double E,
double N)
30 return map->Interpolate(E,N);
46 template <
int coarseness>
49 if (
set == RampdemReader::surface)
64 void AntarcticCoord::asString(TString * s)
const 69 s->Form(
"%g N %g E %g m",x,y,z);
72 if (type == STEREOGRAPHIC)
74 s->Form(
"%g m(E), %g m(N), %g m",x,y,z);
77 if (type == CARTESIAN)
79 s->Form(
"(%g,%g,%g) m",x,y,z);
85 : payload(
AntarcticCoord::WGS84, gps->latitude, gps->longitude, gps->altitude),
89 payload.to(AntarcticCoord::CARTESIAN);
92 TVector3 p = payload.v();
93 TVector3 s = source.v();
95 #ifndef USE_GEOGRAPHIC_LIB 99 sprime.RotateZ(-1 * p.Phi());
100 sprime.RotateY(-1 * p.Theta());
101 sprime[2]=p.Mag()-fabs(sprime.z());
103 sprime.RotateZ(gps->
heading*TMath::DegToRad());
106 sprime.RotateY(-AnitaStaticAdu5Offsets::pitch *TMath::DegToRad());
107 sprime.RotateX(-AnitaStaticAdu5Offsets::roll *TMath::DegToRad());
109 source_phi =
FFTtools::wrap(sprime.Phi() * TMath::RadToDeg(),360);
110 source_theta = 90 - sprime.Theta() * TMath::RadToDeg();
114 pprime.RotateZ(-1*s.Phi());
115 pprime.RotateY(-1*s.Theta());
116 pprime[2] = s.Mag() - fabs(pprime.z());
117 payload_el = -
FFTtools::wrap( 90 - pprime.Theta() * TMath::RadToDeg(), 180, 0);
118 payload_az = pprime.Phi() * TMath::RadToDeg();
125 source_theta = p.Angle(v) * TMath::RadToDeg() - 90;
126 payload_el = s.Angle(v) * TMath::RadToDeg() - 90;
130 GeographicLib::Geodesic::WGS84().Inverse(gps->
latitude, gps->
longitude, swgs84.x, swgs84.y, source_phi, payload_az);
137 apparent_source_theta = source_theta;
138 apparent_payload_el = payload_el;
143 double payload_el_correction = 0;
144 apparent_source_theta -= refract->getElevationCorrection(gps, &source, &payload_el_correction);
145 apparent_payload_el+= payload_el_correction;
150 distance = (source.v() - payload.v()).Mag();
153 static void cart2stereo(
double*,
double*,
double*)
__attribute__((optimize(
"fast-math"),optimize(
"O3")));
154 static void stereo2cart(
double*,
double*,
double*)
__attribute__((optimize(
"fast-math"),optimize(
"O3")));
157 static const double a = 6378137;
158 static const double b = 6356752.31424518;
159 static const double binv = 1./6356752.31424518;
160 static const double e = sqrt((a*a-b*b)/(a*a));
161 static const double ep = e * a/b;
164 static const double scale_factor=0.97276901289;
165 static const double ellipsoid_inv_f = 298.257223563;
166 static const double eccentricity = sqrt((1/ellipsoid_inv_f)*(2-(1/ellipsoid_inv_f)));
167 static const double c_0 = (2*R_EARTH / sqrt(1-pow(eccentricity,2))) * pow(( (1-eccentricity) / (1+eccentricity) ),eccentricity/2);
168 static const double a_bar = pow(eccentricity,2)/2 + 5*pow(eccentricity,4)/24 + pow(eccentricity,6)/12 + 13*pow(eccentricity,8)/360;
169 static const double b_bar = 7*pow(eccentricity,4)/48 + 29*pow(eccentricity,6)/240 + 811*pow(eccentricity,8)/11520;
170 static const double c_bar = 7*pow(eccentricity,6)/120 + 81*pow(eccentricity,8)/1120;
171 static const double d_bar = 4279*pow(eccentricity,8)/161280;
174 static void cart2stereo(
double *x,
double * y,
double *z)
184 double H = sqrt(X*X+
Y*
Y);
187 double sin_lon =
Y*Hinv;
188 double cos_lon =
Y!=0 ? (X/
Y * sin_lon) : ( (X > 0) - (X < 0));
190 double tan_theta = Z*Hinv*(a*binv);
191 double cos_theta = pow(1+ tan_theta* tan_theta,-0.5);
192 double sin_theta = tan_theta * cos_theta;
195 double num = Z + (ep *ep*b) * (sin_theta * sin_theta * sin_theta);
196 double denom = H - (e *e*a) * (cos_theta * cos_theta * cos_theta);
198 double H2inv = pow(num*num + denom*denom,-0.5);
199 double sin_lat = num * H2inv * ( (denom > 0) - ( denom < 0) );
200 double cos_lat = denom / num * sin_lat;
203 double N = a * pow(1. - (e*e) * sin_lat * sin_lat,-0.5);
205 *z = H / cos_lat - N;
209 double R = scale_factor * c_0 * pow( (1 + eccentricity * sin_lat ) / (1 - eccentricity * sin_lat), eccentricity/2) ;
212 double tan_lat_over_2 = sin_lat / (1 + cos_lat);
213 R *= (1 - tan_lat_over_2) / (1 + tan_lat_over_2);
222 static void stereo2cart(
double *x,
double *y,
double *z)
235 double H2 = E*E + N *N;
238 double sin_lon = E*Hinv;
239 double cos_lon = N*Hinv;
249 double tan2_factor = H2 /(scale_factor * scale_factor * c_0 * c_0);
250 double sin_iso_lat = (1 - tan2_factor) / (1 + tan2_factor);
251 double cos_iso_lat = 2 * H/(scale_factor * c_0) / (1 + tan2_factor);
254 double s2 = sin_iso_lat * sin_iso_lat;
255 double sc = sin_iso_lat * cos_iso_lat;
256 double s3c = s2 * sc;
257 double s5c = s2 * s3c;
258 double s7c = s2 * s5c;
260 double sin2_iso_lat = 2 * sc;
261 double sin4_iso_lat = 4 * sc - 8 * s3c;
262 double sin6_iso_lat = 6 * sc - 32 * s3c + 32 *s5c;
263 double sin8_iso_lat = 8 * sc - 80 * s3c + 192* s5c - 128* s7c;
268 double correction = a_bar * sin2_iso_lat + b_bar * sin4_iso_lat + c_bar * sin6_iso_lat + d_bar * sin8_iso_lat;
271 double sin_corr = sin(correction);
272 double cos_corr = cos(correction);
273 double sin_lat = fabs(sin_iso_lat * cos_corr + cos_iso_lat * sin_corr);
274 double cos_lat = cos_iso_lat * cos_corr - sin_iso_lat * sin_corr;
280 const double C1 = (1-FLATTENING_FACTOR) * (1-FLATTENING_FACTOR);
282 double C2 = pow(cos_lat * cos_lat + C1 * sin_lat*sin_lat,-0.5);
285 double C3 = R_EARTH * C2 + alt;
288 *x = C3 * cos_lat * sin_lon;
289 *y = C3 * cos_lat * cos_lon;
290 *z = (R_EARTH * Q2 + alt) * sin_lat;
295 void AntarcticCoord::convert(CoordType t)
309 else if ( t==STEREOGRAPHIC)
316 else if (type == STEREOGRAPHIC)
325 else if (t == CARTESIAN)
329 stereo2cart(&x,&y,&z);
334 else if (type == CARTESIAN)
345 else if ( t== STEREOGRAPHIC)
351 cart2stereo(&x,&y,&z);
358 fprintf(stderr,
"Invalid CoordType: %d!", type);
372 if (strstr(key,
"stereographic_grid"))
379 sscanf(key,
"stereographic_grid_%d_%d_%d_%d", &nx, &ny, &maxN, &maxE);
388 const int nsamples = 64;
390 void AntarcticSegmentationScheme::DrawI(
const char * opt,
const int * idata,
const double * range)
const 396 data =
new double[N];
397 for (
int i = 0; i < N; i++) { data[i] = idata[i]; }
398 Draw(opt,data,range);
407 TGraph2D * g =
new TGraph2D(N*nsamples);
408 g->SetBit(kCanDelete);
412 for (
int i =0; i < N; i++)
417 for (
int j =0; j< nsamples; j++)
419 samples[j].to(AntarcticCoord::STEREOGRAPHIC);
420 g->SetPoint(nsamples*i+j,samples[j].x,samples[j].y,data ? data[i] : i);
426 g->GetXaxis()->SetRangeUser(range[0],range[1]);
427 g->GetYaxis()->SetRangeUser(range[2],range[3]);
435 StereographicGrid::StereographicGrid(
int NX,
int NY,
double MAX_E,
double MAX_N)
447 if (stereo.x > max_E || stereo.x < -max_E || stereo.y > max_N || stereo.y < -max_N)
return -1;
450 int xbin = nx/2 + stereo.x / dx;
451 int ybin = ny/2 - stereo.y / dy;
453 return xbin + nx * ybin;
462 double x = (xbin +0.5) *dx - max_E;
463 double y = max_N - (ybin +0.5) *dy ;
464 double z = fillalt ? getSurface<4> (dataset).compute(x,y): 0;
465 fillme->set(AntarcticCoord::STEREOGRAPHIC,x,y,z);
476 double lx = (xbin) *dx - max_E;
477 double ly = max_N - (ybin) *dy ;
482 for (
int i = 0; i < N; i++)
484 double x = gRandom->Uniform(lx, lx+dx);
485 double y = gRandom->Uniform(ly, ly-dy);
486 double z = fillalt ? getSurface<4> (dataset).compute(x,y): 0;
487 fill[i].set(AntarcticCoord::STEREOGRAPHIC,x,y,z);
492 int grid = sqrt(N) + 0.5 ;
494 for (
int i = 0; i < N; i++)
497 double x = lx + (dx / (grid-1)) * ((i % grid));
498 double y = ly - (dy / (grid-1)) * ((i / grid));
499 double z = fillalt ? getSurface<4> (dataset).compute(x,y): 0;
500 fill[i].set(AntarcticCoord::STEREOGRAPHIC,x,y,z);
511 if(gDirectory->Get(
"tmp")){
512 delete gDirectory->Get(
"tmp");
520 if (stropt.Contains(
"MAP"))
522 stropt.ReplaceAll(
"MAP",
"");
526 for (
int i = 0; i < NSegments(); i++)
529 c.to(AntarcticCoord::WGS84);
530 h->Fill(c.y, c.x, data ? data[i]: i);
536 h =
new TH2D(
"tmp",
"Stereographic Grid", nx, -max_E, max_E, ny, -max_N, max_N);
538 for (
int i = 0; i < NSegments(); i++)
541 h->Fill(c.x, c.y, data ? data[i]: i);
553 h->GetXaxis()->SetRangeUser(range[0], range[1]);
554 h->GetYaxis()->SetRangeUser(range[2], range[3]);
563 void StereographicGrid::asString(TString * str)
const 565 str->Form(
"stereographic_grid_%d_%d_%d_%d", nx,ny,(
int) max_E,(
int) max_N);
575 bool left_edge = (segment % nx ) == 0;
576 bool right_edge = (segment % nx ) == nx-1 ;
577 bool top_edge = (segment / ny ) == 0;
578 bool bottom_edge = (segment / ny ) == ny-1 ;
580 int start_x = left_edge ? 0 : -1;
581 int end_x = right_edge ? 0 : 1;
582 int start_y = top_edge ? 0 : -1;
583 int end_y = bottom_edge ? 0 : 1;
585 for (
int i = start_x; i <= end_x; i++)
587 for (
int j = start_y; j <= end_y; j++)
589 if (i == 0 && j == 0)
continue;
590 if (i * j != 0)
continue;
593 if (neighbors) neighbors->push_back(segment + i + j *nx);
605 if (d == RampdemReader::surface)
618 bool PayloadParameters::checkForCollision(
double dx,
AntarcticCoord * w,
AntarcticCoord * w_exit, RampdemReader::dataSet d,
double grace,
bool reverse)
const 621 AntarcticCoord x = (reverse ? payload: source).as(AntarcticCoord::CARTESIAN);
622 TVector3 v = (reverse ? -1 : 1) * (payload.v() - source.v()).Unit() * dx;
627 x.to(AntarcticCoord::CARTESIAN);
632 double height_above_surface = cartmap(d).metersAboveIce(x.x, x.y, x.z);
634 if ( (!reverse && height_above_surface> 5000) || (reverse && (x.v() - source.v()).Mag2() < dx*dx))
637 if (height_above_surface + grace < 0 )
653 height_above_surface = cartmap(d).metersAboveIce(x.x, x.y, x.z);
655 if (height_above_surface + grace >=0 )
660 else if ( reverse && (x.v() - source.v()).Mag2() < dx*dx)
682 source_phi = other.source_phi;
683 source_theta = other.source_theta;
684 payload_el = other.payload_el;
685 payload_az = other.payload_az;
686 distance = other.distance;
687 payload = other.payload;
688 source = other.source;
692 #ifdef USE_GEOGRAPHIC_LIB 693 GeographicLib::GeodesicLine gl(GeographicLib::Geodesic::WGS84(), gps->
latitude, gps->
longitude, gps->
heading - phi);
695 double high = 1000 * 1000 ;
700 double mid = (low + high)/2.0;
702 gl.Position(mid, lat, lon);
706 if (fabs(payloadParameter.payload_el) < tol or count > 100){
708 std::cout<<
"The loop never stop. the last payload elevation(0 is better) is: "<<payloadParameter.payload_el<<std::endl;
714 return payloadParameter.source_theta;
716 if (payloadParameter.payload_el > 0 ){
728 double collision_check_dx,
729 double min_dx,
double tol,
double min_el,
730 RampdemReader::dataSet d)
742 #ifdef USE_GEOGRAPHIC_LIB 743 GeographicLib::GeodesicLine gl(GeographicLib::Geodesic::WGS84(), gps->
latitude, gps->
longitude, gps->
heading - phi);
746 double step = 1000*300;
749 while (loopCount<100)
753 gl.Position(i * step, lat, lon);
761 if (fabs(p->source_phi -phi) < tol && fabs(p->source_theta - theta) < tol && p->apparent_payload_el>= min_el)
765 if (collision_check_dx && p->checkForCollision( TMath::Min(collision_check_dx,step), 0, &c, d))
767 step= TMath::Min(collision_check_dx, step) ;
778 if (p->source_theta < theta || (p->payload_el < min_el && step > min_dx))
784 else if (p->payload_el < min_el)
789 else if ( step < min_dx)
795 if (p->payload_el >= min_el)
846 CartesianSurfaceMap::CartesianSurfaceMap(
double resolution , RampdemReader::dataSet d)
868 sa.to(AntarcticCoord::CARTESIAN);
869 sb.to(AntarcticCoord::CARTESIAN);
870 sc.to(AntarcticCoord::CARTESIAN);
871 sd.to(AntarcticCoord::CARTESIAN);
873 double xmin = TMath::Min ( TMath::Min( sa.x,sb.x), TMath::Min(sc.x,sd.x));
874 double xmax = TMath::Max ( TMath::Max( sa.x,sb.x), TMath::Max(sc.x,sd.x));
875 double ymin = TMath::Min ( TMath::Min( sa.y,sb.y), TMath::Min(sc.y,sd.y));
876 double ymax = TMath::Max ( TMath::Max( sa.y,sb.y), TMath::Max(sc.y,sd.y));
879 int nbinsx = (xmax - xmin)/ resolution;
880 int nbinsy = (ymax - ymin)/ resolution;
881 map =
new TH2D(
"cartmap",
"Cartesian Map", nbinsx, xmin, xmax, nbinsy, ymin,ymax);
882 map->SetDirectory(0);
884 for (
int i = 1; i <= nbinsx; i++)
886 for (
int j = 1; j <= nbinsy; j++)
889 double x = map->GetXaxis()->GetBinCenter(i);
890 double y = map->GetYaxis()->GetBinCenter(j);
892 static const double a = 6378137;
893 static const double b = 6356752.31424518;
894 double z = b * sqrt( 1 - (1./(a*a))*(x*x+y*y));
897 double R = c.v().Mag();
899 c.to(AntarcticCoord::STEREOGRAPHIC);
901 if (c.x > xl && c.x < xu && c.y > yl && c.y < yu)
903 alt = getSurface<4>(d).map->Interpolate(c.x, c.y);
906 map->SetBinContent(i,j, R + alt);
912 double CartesianSurfaceMap::CartesianSurfaceMap::surface(
double x,
double y)
const 914 return map->Interpolate(x,y);
917 double CartesianSurfaceMap::CartesianSurfaceMap::z(
double x,
double y)
const 919 double r = surface(x,y);
920 return sqrt( r*r - x*x - y*y);
925 double CartesianSurfaceMap::metersAboveIce(
double x,
double y,
double z)
const 927 return sqrt(x*x + y*y+z*z) - surface(x,y);
932 #ifndef USE_GEOGRAPHIC_LIB 933 static int nagged_about_surface = 0;
934 static double hav(
double phi) {
return ((1.-cos(phi))/2.); }
947 if (lat0 < -90 || lat0 < -90 || lon0 < -180 || lon1 < -180)
return -999;
948 #ifndef USE_GEOGRAPHIC_LIB 950 if (!nagged_about_surface)
952 nagged_about_surface++;
953 fprintf(stderr,
"WARNING: compiled without geographic lib support. Using haversine distance between points\n");
955 lat0 *= TMath::DegToRad();
956 lat1 *= TMath::DegToRad();
957 lon0 *= TMath::DegToRad();
958 lon1 *= TMath::DegToRad();
959 double a = hav(lat1-lat0) + cos(lat0) * cos(lat1) * hav(lon1-lon0);
960 double c = 2 * atan2(sqrt(a), sqrt(1-a));
961 double d = R_EARTH * c;
966 GeographicLib::Geodesic::WGS84().Inverse( lat0,lon0,lat1,lon1, distance);
struct __attribute__((packed))
Debugging use only TURF scaler data.
static TProfile2D * getMap(RampdemReader::dataSet dataSet, int coarseness_factor)
virtual void Draw(const char *opt="colz", const double *data=0, const double *range=0) const
static Double_t SurfaceAboveGeoid(Double_t longitude, Double_t latitude, RampdemReader::dataSet=rampdem)
virtual AntarcticCoord * sampleSegment(int idx, int N, AntarcticCoord *fillus=0, bool random=true, bool fillalt=true) const
Adu5Pat – The ADU5 Position and Attitude Data.
Float_t latitude
In degrees.
virtual AntarcticCoord * sampleSegment(int idx, int N, AntarcticCoord *fillus=0, bool random=true, bool fillalt=true) const =0
Float_t longitude
In degrees.
static double getHorizon(double phi, const Adu5Pat *gps, const Refraction::Model *refractionModel=0, double tol=5e-6, RampdemReader::dataSet rampdemData=RampdemReader::rampdem)
static void getMapCoordinates(double &xMin, double &yMin, double &xMax, double &yMax, RampdemReader::dataSet=rampdem)
virtual void getSegmentCenter(int idx, AntarcticCoord *fill, bool fillalt=true) const
Float_t altitude
In metres.
static AntarcticSegmentationScheme * factory(const char *key)
Inelasticity distributions: stores parametrizations and picks inelasticities.
static void LonLatToEastingNorthing(Double_t lon, Double_t lat, Double_t &easting, Double_t &northing)
static double surfaceDistance(const AntarcticCoord &a, const AntarcticCoord &b)
virtual void Draw(const char *opt="colz", const double *data=0, const double *range=0) const
virtual int getNeighbors(int segment, std::vector< int > *neighbors=NULL) const
virtual int getSegmentIndex(const AntarcticCoord &coord) const
Float_t heading
0 is facing north, 180 is facing south
static void EastingNorthingToLonLat(Double_t easting, Double_t northing, Double_t &lon, Double_t &lat)