23 #include "grid_utils.h"
24 #include "tree_utils.h"
41 void error_handler(
const char *msg)
43 fprintf(
stderr,
"FATAL Error: %s\n", msg );
45 MPI_Abort(MPI_COMM_WORLD, -1);
56 double maxval_double(
int size,
const double *data)
62 for(n=1; n<size; n++){
63 if( data[n] > maxval ) maxval = data[n];
75 double minval_double(
int size,
const double *data)
81 for(n=1; n<size; n++){
82 if( data[n] < minval ) minval = data[n];
93 double avgval_double(
int size,
const double *data)
99 for(n=0; n<size; n++) avgval += data[n];
111 void latlon2xyz(
int size,
const double *lon,
const double *lat,
double *x,
double *y,
double *z)
115 for(n=0; n<size; n++) {
116 x[n] = cos(lat[n])*cos(lon[n]);
117 y[n] = cos(lat[n])*sin(lon[n]);
127 void xyz2latlon(
int np,
const double *x,
const double *y,
const double *z,
double *lon,
double *lat)
134 for(i=0; i<np; i++) {
138 dist = sqrt(xx*xx+yy*yy+zz*zz);
143 if ( fabs(xx)+fabs(yy) < EPSLN10 )
146 lon[i] = atan2(yy, xx);
149 if ( lon[i] < 0.) lon[i] = 2.*M_PI + lon[i];
154 int delete_vtx(
double x[],
double y[],
int n,
int n_del)
156 for (;n_del<n-1;n_del++) {
157 x[n_del] = x[n_del+1];
158 y[n_del] = y[n_del+1];
164 int insert_vtx(
double x[],
double y[],
int n,
int n_ins,
double lon_in,
double lat_in)
168 for (i=n-1;i>=n_ins;i--) {
178 void v_print(
double x[],
double y[],
int n)
183 printf(
" %20g %20g\n", x[i], y[i]);
187 int fix_lon(
double x[],
double y[],
int n,
double tlon)
189 double x_sum, dx, dx_;
190 int i, nn = n, pole = 0;
192 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) pole = 1;
194 printf(
"fixing pole cell\n");
200 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) {
201 int im=(i+nn-1)%nn, ip=(i+1)%nn;
203 if (y[im]==y[i] && y[ip]==y[i]) {
204 nn = delete_vtx(x, y, nn, i);
206 }
else if (y[im]!=y[i] && y[ip]!=y[i]) {
207 nn = insert_vtx(x, y, nn, i, x[i], y[i]);
213 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) {
214 int im=(i+nn-1)%nn, ip=(i+1)%nn;
233 if (dx_ < -M_PI) dx_ = dx_ + TPI;
234 else if (dx_ > M_PI) dx_ = dx_ - TPI;
235 x_sum += (x[i] = x[i-1] + dx_);
238 dx = (x_sum/nn)-tlon;
251 printf(
"area=%g\n", poly_area(x, y,nn));
266 double great_circle_distance(
double *p1,
double *p2)
273 beta = 2.*asin( sqrt( sin((p1[1]-p2[1])/2.)*sin((p1[1]-p2[1])/2.) +
274 cos(p1[1])*cos(p2[1])*(sin((p1[0]-p2[0])/2.)*sin((p1[0]-p2[0])/2.)) ) );
290 double spherical_angle(
const double *v1,
const double *v2,
const double *v3)
293 long double px, py, pz, qx, qy, qz, ddd;
296 px = v1[1]*v2[2] - v1[2]*v2[1];
297 py = v1[2]*v2[0] - v1[0]*v2[2];
298 pz = v1[0]*v2[1] - v1[1]*v2[0];
300 qx = v1[1]*v3[2] - v1[2]*v3[1];
301 qy = v1[2]*v3[0] - v1[0]*v3[2];
302 qz = v1[0]*v3[1] - v1[1]*v3[0];
304 ddd = (px*px+py*py+pz*pz)*(qx*qx+qy*qy+qz*qz);
308 ddd = (px*qx+py*qy+pz*qz) / sqrtl(ddd);
309 if( fabsl(ddd-1) < EPSLN30 ) ddd = 1;
310 if( fabsl(ddd+1) < EPSLN30 ) ddd = -1;
311 if ( ddd>1. || ddd<-1. ) {
319 angle = ((double)acosl( ddd ));
331 void vect_cross(
const double *p1,
const double *p2,
double *e )
334 e[0] = p1[1]*p2[2] - p1[2]*p2[1];
335 e[1] = p1[2]*p2[0] - p1[0]*p2[2];
336 e[2] = p1[0]*p2[1] - p1[1]*p2[0];
346 double dot(
const double *p1,
const double *p2)
349 return( p1[0]*p2[0] + p1[1]*p2[1] + p1[2]*p2[2] );
354 double metric(
const double *p) {
355 return (sqrt(p[0]*p[0] + p[1]*p[1]+p[2]*p[2]) );
358 void normalize_vect(
double *e)
363 pdot = e[0]*e[0] + e[1] * e[1] + e[2] * e[2];
366 for(k=0; k<3; k++) e[k] /= pdot;
374 void unit_vect_latlon(
int size,
const double *lon,
const double *lat,
double *vlon,
double *vlat)
376 double sin_lon, cos_lon, sin_lat, cos_lat;
379 for(n=0; n<size; n++) {
380 sin_lon = sin(lon[n]);
381 cos_lon = cos(lon[n]);
382 sin_lat = sin(lat[n]);
383 cos_lat = cos(lat[n]);
385 vlon[3*n] = -sin_lon;
386 vlon[3*n+1] = cos_lon;
389 vlat[3*n] = -sin_lat*cos_lon;
390 vlat[3*n+1] = -sin_lat*sin_lon;
391 vlat[3*n+2] = cos_lat;
404 int intersect_tri_with_line(
const double *plane,
const double *l1,
const double *l2,
double *p,
407 long double M[3*3], inv_M[3*3];
412 const double *pnt0=plane;
413 const double *pnt1=plane+3;
414 const double *pnt2=plane+6;
419 M[0]=l1[0]-l2[0]; M[1]=pnt1[0]-pnt0[0]; M[2]=pnt2[0]-pnt0[0];
420 M[3]=l1[1]-l2[1]; M[4]=pnt1[1]-pnt0[1]; M[5]=pnt2[1]-pnt0[1];
421 M[6]=l1[2]-l2[2]; M[7]=pnt1[2]-pnt0[2]; M[8]=pnt2[2]-pnt0[2];
425 is_invert = invert_matrix_3x3(M,inv_M);
426 if (!is_invert)
return 0;
445 void mult(
long double m[],
long double v[],
long double out_v[]) {
447 out_v[0]=m[0]*v[0]+m[1]*v[1]+m[2]*v[2];
448 out_v[1]=m[3]*v[0]+m[4]*v[1]+m[5]*v[2];
449 out_v[2]=m[6]*v[0]+m[7]*v[1]+m[8]*v[2];
455 int invert_matrix_3x3(
long double m[],
long double m_inv[]) {
458 const long double det = m[0] * (m[4]*m[8] - m[5]*m[7])
459 -m[1] * (m[3]*m[8] - m[5]*m[6])
460 +m[2] * (m[3]*m[7] - m[4]*m[6]);
461 if (fabsl(det) < EPSLN15 )
return 0;
463 const long double deti = 1.0/det;
465 m_inv[0] = (m[4]*m[8] - m[5]*m[7]) * deti;
466 m_inv[1] = (m[2]*m[7] - m[1]*m[8]) * deti;
467 m_inv[2] = (m[1]*m[5] - m[2]*m[4]) * deti;
469 m_inv[3] = (m[5]*m[6] - m[3]*m[8]) * deti;
470 m_inv[4] = (m[0]*m[8] - m[2]*m[6]) * deti;
471 m_inv[5] = (m[2]*m[3] - m[0]*m[5]) * deti;
473 m_inv[6] = (m[3]*m[7] - m[4]*m[6]) * deti;
474 m_inv[7] = (m[1]*m[6] - m[0]*m[7]) * deti;
475 m_inv[8] = (m[0]*m[4] - m[1]*m[3]) * deti;
481 int inside_a_polygon(
double *lon1,
double *lat1,
int *npts,
double *lon2,
double *lat2)
484 double x2[20], y2[20], z2[20];
486 double min_x2, max_x2, min_y2, max_y2, min_z2, max_z2;
489 struct Node *grid1=NULL, *grid2=NULL;
495 max_x2 = maxval_double(*npts, x2);
496 if(x1 >= max_x2+RANGE_CHECK_CRITERIA)
return 0;
497 min_x2 = minval_double(*npts, x2);
498 if(min_x2 >= x1+RANGE_CHECK_CRITERIA)
return 0;
500 max_y2 = maxval_double(*npts, y2);
501 if(y1 >= max_y2+RANGE_CHECK_CRITERIA)
return 0;
502 min_y2 = minval_double(*npts, y2);
503 if(min_y2 >= y1+RANGE_CHECK_CRITERIA)
return 0;
505 max_z2 = maxval_double(*npts, z2);
506 if(z1 >= max_z2+RANGE_CHECK_CRITERIA)
return 0;
507 min_z2 = minval_double(*npts, z2);
508 if(min_z2 >= z1+RANGE_CHECK_CRITERIA)
return 0;
516 addEnd(grid1, x1, y1, z1, 0, 0, 0, -1);
517 for(i=0; i<*npts; i++) addEnd(grid2, x2[i], y2[i], z2[i], 0, 0, 0, -1);
519 isinside = insidePolygon(grid1, grid2);
525 int inside_a_polygon_(
double *lon1,
double *lat1,
int *npts,
double *lon2,
double *lat2)
530 isinside = inside_a_polygon(lon1, lat1, npts, lon2, lat2);
536 double get_global_area(
void)
539 garea = 4*M_PI*RADIUS*RADIUS;
544 double get_global_area_(
void)
547 garea = 4*M_PI*RADIUS*RADIUS;
552 double poly_area(
const double x[],
const double y[],
int n)
559 double dx = (x[ip]-x[i]);
565 if(dx > M_PI) dx = dx - 2.0*M_PI;
566 if(dx < -M_PI) dx = dx + 2.0*M_PI;
567 if (dx==0.0)
continue;
569 if ( fabs(lat1-lat2) < SMALL_VALUE)
570 area -= dx*sin(0.5*(lat1+lat2));
572 dy = 0.5*(lat1-lat2);
574 area -= dx*sin(0.5*(lat1+lat2))*dat;
578 return -
area*RADIUS*RADIUS;
580 return area*RADIUS*RADIUS;
584 double poly_area_no_adjust(
const double x[],
const double y[],
int n)
591 double dx = (x[ip]-x[i]);
596 if (dx==0.0)
continue;
598 if ( fabs(lat1-lat2) < SMALL_VALUE)
599 area -= dx*sin(0.5*(lat1+lat2));
601 area += dx*(cos(lat1)-cos(lat2))/(lat1-lat2);
604 return area*RADIUS*RADIUS;
606 return area*RADIUS*RADIUS;
616 double poly_area_dimensionless(
const double x[],
const double y[],
int n)
623 double dx = (x[ip]-x[i]);
629 if(dx > M_PI) dx = dx - 2.0*M_PI;
630 if(dx < -M_PI) dx = dx + 2.0*M_PI;
631 if (dx==0.0)
continue;
633 if ( fabs(lat1-lat2) < SMALL_VALUE)
634 area -= dx*sin(0.5*(lat1+lat2));
636 dy = 0.5*(lat1-lat2);
638 area -= dx*sin(0.5*(lat1+lat2))*dat;
642 return (-
area/(4*M_PI));
644 return (
area/(4*M_PI));
649 double great_circle_area(
int n,
const double *x,
const double *y,
const double *z) {
651 double pnt0[3], pnt1[3], pnt2[3];
656 for ( i=0; i<n; i++) {
661 pnt1[0] = x[(i+1)%n];
662 pnt1[1] = y[(i+1)%n];
663 pnt1[2] = z[(i+1)%n];
664 pnt2[0] = x[(i+2)%n];
665 pnt2[1] = y[(i+2)%n];
666 pnt2[2] = z[(i+2)%n];
669 sum += spherical_angle(pnt1, pnt2, pnt0);
672 area = (sum - (n-2.)*M_PI) * RADIUS* RADIUS;
682 double spherical_excess_area(
const double* p_ll,
const double* p_ul,
683 const double* p_lr,
const double* p_ur,
double radius)
685 double area, ang1, ang2, ang3, ang4;
686 double v1[3], v2[3], v3[3];
692 ang1 = spherical_angle(v1, v2, v3);
698 ang2 = spherical_angle(v1, v2, v3);
704 ang3 = spherical_angle(v1, v2, v3);
710 ang4 = spherical_angle(v1, v2, v3);
712 area = (ang1 + ang2 + ang3 + ang4 - 2.*M_PI) * radius* radius;
722 void get_grid_area_(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
727 void get_grid_area(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
729 int nx, ny, nxp, i, j, n_in;
730 double x_in[20], y_in[20];
736 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
737 x_in[0] = lon[j*nxp+i];
738 x_in[1] = lon[j*nxp+i+1];
739 x_in[2] = lon[(j+1)*nxp+i+1];
740 x_in[3] = lon[(j+1)*nxp+i];
741 y_in[0] = lat[j*nxp+i];
742 y_in[1] = lat[j*nxp+i+1];
743 y_in[2] = lat[(j+1)*nxp+i+1];
744 y_in[3] = lat[(j+1)*nxp+i];
745 n_in = fix_lon(x_in, y_in, 4, M_PI);
746 area[j*nx+i] = poly_area(x_in, y_in, n_in);
756 void get_grid_area_ug_(
const int *npts,
const double *lon,
const double *lat,
double *
area)
758 get_grid_area_ug(npts, lon, lat,
area);
761 void get_grid_area_ug(
const int *npts,
const double *lon,
const double *lat,
double *
area)
764 double x_in[20], y_in[20];
769 for(l=0; l<nl; l++) {
771 x_in[1] = lon[l*nv+1];
772 x_in[2] = lon[l*nv+2];
773 x_in[3] = lon[l*nv+3];
775 y_in[1] = lat[l*nv+1];
776 y_in[2] = lat[l*nv+2];
777 y_in[3] = lat[l*nv+3];
778 n_in = fix_lon(x_in, y_in, nv, M_PI);
779 area[l] = poly_area(x_in, y_in, n_in);
785 void get_grid_great_circle_area_(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
791 void get_grid_great_circle_area(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
793 int nx, ny, nxp, nyp, i, j;
795 struct Node *grid=NULL;
796 double *x=NULL, *y=NULL, *z=NULL;
804 x = (
double *)malloc(nxp*nyp*
sizeof(
double));
805 y = (
double *)malloc(nxp*nyp*
sizeof(
double));
806 z = (
double *)malloc(nxp*nyp*
sizeof(
double));
810 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
818 addEnd(grid, x[n0], y[n0], z[n0], 0, 0, 0, -1);
819 addEnd(grid, x[n1], y[n1], z[n1], 0, 0, 0, -1);
820 addEnd(grid, x[n2], y[n2], z[n2], 0, 0, 0, -1);
821 addEnd(grid, x[n3], y[n3], z[n3], 0, 0, 0, -1);
822 area[j*nx+i] = gridArea(grid);
831 void get_grid_great_circle_area_ug_(
const int *npts,
const double *lon,
const double *lat,
double *
area)
833 get_grid_great_circle_area_ug(npts, lon, lat,
area);
837 void get_grid_great_circle_area_ug(
const int *npts,
const double *lon,
const double *lat,
double *
area)
841 struct Node *grid=NULL;
842 double *x=NULL, *y=NULL, *z=NULL;
847 x = (
double *)malloc(nl*nv*
sizeof(
double));
848 y = (
double *)malloc(nl*nv*
sizeof(
double));
849 z = (
double *)malloc(nl*nv*
sizeof(
double));
853 for(l=0; l<nv; l++) {
861 addEnd(grid, x[n0], y[n0], z[n0], 0, 0, 0, -1);
862 addEnd(grid, x[n1], y[n1], z[n1], 0, 0, 0, -1);
863 addEnd(grid, x[n2], y[n2], z[n2], 0, 0, 0, -1);
864 addEnd(grid, x[n3], y[n3], z[n3], 0, 0, 0, -1);
865 area[l] = gridArea(grid);
874 void get_grid_area_dimensionless(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
876 int nx, ny, nxp, i, j, n_in;
877 double x_in[20], y_in[20];
883 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
884 x_in[0] = lon[j*nxp+i];
885 x_in[1] = lon[j*nxp+i+1];
886 x_in[2] = lon[(j+1)*nxp+i+1];
887 x_in[3] = lon[(j+1)*nxp+i];
888 y_in[0] = lat[j*nxp+i];
889 y_in[1] = lat[j*nxp+i+1];
890 y_in[2] = lat[(j+1)*nxp+i+1];
891 y_in[3] = lat[(j+1)*nxp+i];
892 n_in = fix_lon(x_in, y_in, 4, M_PI);
893 area[j*nx+i] = poly_area_dimensionless(x_in, y_in, n_in);
900 void get_grid_area_no_adjust(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
902 int nx, ny, nxp, i, j, n_in;
903 double x_in[20], y_in[20];
909 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
910 x_in[0] = lon[j*nxp+i];
911 x_in[1] = lon[j*nxp+i+1];
912 x_in[2] = lon[(j+1)*nxp+i+1];
913 x_in[3] = lon[(j+1)*nxp+i];
914 y_in[0] = lat[j*nxp+i];
915 y_in[1] = lat[j*nxp+i+1];
916 y_in[2] = lat[(j+1)*nxp+i+1];
917 y_in[3] = lat[(j+1)*nxp+i];
919 area[j*nx+i] = poly_area_no_adjust(x_in, y_in, n_in);
929 int clip(
const double lon_in[],
const double lat_in[],
int n_in,
double ll_lon,
double ll_lat,
930 double ur_lon,
double ur_lat,
double lon_out[],
double lat_out[])
932 double x_tmp[MV], y_tmp[MV], x_last, y_last;
933 int i_in, i_out, n_out, inside_last, inside;
936 x_last = lon_in[n_in-1];
937 y_last = lat_in[n_in-1];
938 inside_last = (x_last >= ll_lon);
939 for (i_in=0,i_out=0;i_in<n_in;i_in++) {
942 if ((inside=(lon_in[i_in] >= ll_lon))!=inside_last) {
943 x_tmp[i_out] = ll_lon;
944 y_tmp[i_out++] = y_last + (ll_lon - x_last) * (lat_in[i_in] - y_last) / (lon_in[i_in] - x_last);
949 x_tmp[i_out] = lon_in[i_in];
950 y_tmp[i_out++] = lat_in[i_in];
952 x_last = lon_in[i_in];
953 y_last = lat_in[i_in];
954 inside_last = inside;
956 if (!(n_out=i_out))
return(0);
959 x_last = x_tmp[n_out-1];
960 y_last = y_tmp[n_out-1];
961 inside_last = (x_last <= ur_lon);
962 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
965 if ((inside=(x_tmp[i_in] <= ur_lon))!=inside_last) {
966 lon_out[i_out] = ur_lon;
967 lat_out[i_out++] = y_last + (ur_lon - x_last) * (y_tmp[i_in] - y_last)
968 / (x_tmp[i_in] - x_last);
973 lon_out[i_out] = x_tmp[i_in];
974 lat_out[i_out++] = y_tmp[i_in];
977 x_last = x_tmp[i_in];
978 y_last = y_tmp[i_in];
979 inside_last = inside;
981 if (!(n_out=i_out))
return(0);
984 x_last = lon_out[n_out-1];
985 y_last = lat_out[n_out-1];
986 inside_last = (y_last >= ll_lat);
987 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
990 if ((inside=(lat_out[i_in] >= ll_lat))!=inside_last) {
991 y_tmp[i_out] = ll_lat;
992 x_tmp[i_out++] = x_last + (ll_lat - y_last) * (lon_out[i_in] - x_last) / (lat_out[i_in] - y_last);
997 x_tmp[i_out] = lon_out[i_in];
998 y_tmp[i_out++] = lat_out[i_in];
1000 x_last = lon_out[i_in];
1001 y_last = lat_out[i_in];
1002 inside_last = inside;
1004 if (!(n_out=i_out))
return(0);
1007 x_last = x_tmp[n_out-1];
1008 y_last = y_tmp[n_out-1];
1009 inside_last = (y_last <= ur_lat);
1010 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
1013 if ((inside=(y_tmp[i_in] <= ur_lat))!=inside_last) {
1014 lat_out[i_out] = ur_lat;
1015 lon_out[i_out++] = x_last + (ur_lat - y_last) * (x_tmp[i_in] - x_last) / (y_tmp[i_in] - y_last);
1020 lon_out[i_out] = x_tmp[i_in];
1021 lat_out[i_out++] = y_tmp[i_in];
1023 x_last = x_tmp[i_in];
1024 y_last = y_tmp[i_in];
1025 inside_last = inside;
1036 int clip_2dx2d(
const double lon1_in[],
const double lat1_in[],
int n1_in,
1037 const double lon2_in[],
const double lat2_in[],
int n2_in,
1038 double lon_out[],
double lat_out[])
1040 double lon_tmp[MV], lat_tmp[MV];
1041 double x1_0, y1_0, x1_1, y1_1, x2_0, y2_0, x2_1, y2_1;
1042 double dx1, dy1, dx2, dy2, determ, ds1, ds2;
1043 int i_out, n_out, inside_last, inside, i1, i2;
1048 for(i1=0; i1<n1_in; i1++) {
1049 lon_tmp[i1] = lon1_in[i1];
1050 lat_tmp[i1] = lat1_in[i1];
1052 x2_0 = lon2_in[n2_in-1];
1053 y2_0 = lat2_in[n2_in-1];
1054 for(i2=0; i2<n2_in; i2++) {
1057 x1_0 = lon_tmp[n_out-1];
1058 y1_0 = lat_tmp[n_out-1];
1059 inside_last = inside_edge( x2_0, y2_0, x2_1, y2_1, x1_0, y1_0);
1060 for(i1=0, i_out=0; i1<n_out; i1++) {
1063 if((inside = inside_edge(x2_0, y2_0, x2_1, y2_1, x1_1, y1_1)) != inside_last ) {
1071 ds1 = y1_0*x1_1 - y1_1*x1_0;
1072 ds2 = y2_0*x2_1 - y2_1*x2_0;
1073 determ = dy2*dx1 - dy1*dx2;
1074 if(fabs(determ) < EPSLN30) {
1075 error_handler(
"the line between <x1_0,y1_0> and <x1_1,y1_1> should not parallel to "
1076 "the line between <x2_0,y2_0> and <x2_1,y2_1>");
1078 lon_out[i_out] = (dx2*ds1 - dx1*ds2)/determ;
1079 lat_out[i_out++] = (dy2*ds1 - dy1*ds2)/determ;
1084 lon_out[i_out] = x1_1;
1085 lat_out[i_out++] = y1_1;
1089 inside_last = inside;
1091 if(!(n_out=i_out))
return 0;
1092 for(i1=0; i1<n_out; i1++) {
1093 lon_tmp[i1] = lon_out[i1];
1094 lat_tmp[i1] = lat_out[i1];
1115 int clip_2dx2d_great_circle(
const double x1_in[],
const double y1_in[],
const double z1_in[],
int n1_in,
1116 const double x2_in[],
const double y2_in[],
const double z2_in [],
int n2_in,
1117 double x_out[],
double y_out[],
double z_out[])
1119 struct Node *grid1List=NULL;
1120 struct Node *grid2List=NULL;
1121 struct Node *intersectList=NULL;
1122 struct Node *polyList=NULL;
1123 struct Node *curList=NULL;
1124 struct Node *firstIntersect=NULL, *curIntersect=NULL;
1125 struct Node *temp1=NULL, *temp2=NULL, *temp=NULL;
1127 int i1, i2, i1p, i2p, i2p2, npts1, npts2;
1128 int nintersect, n_out;
1129 int maxiter1, maxiter2, iter1, iter2;
1130 int found1, found2, curListNum;
1131 int has_inbound, inbound;
1132 double pt1[MV][3], pt2[MV][3];
1133 double *p1_0=NULL, *p1_1=NULL;
1134 double *p2_0=NULL, *p2_1=NULL, *p2_2=NULL;
1135 double intersect[3];
1137 double min_x1, max_x1, min_y1, max_y1, min_z1, max_z1;
1138 double min_x2, max_x2, min_y2, max_y2, min_z2, max_z2;
1142 min_x1 = minval_double(n1_in, x1_in);
1143 max_x2 = maxval_double(n2_in, x2_in);
1144 if(min_x1 >= max_x2+RANGE_CHECK_CRITERIA)
return 0;
1145 max_x1 = maxval_double(n1_in, x1_in);
1146 min_x2 = minval_double(n2_in, x2_in);
1147 if(min_x2 >= max_x1+RANGE_CHECK_CRITERIA)
return 0;
1149 min_y1 = minval_double(n1_in, y1_in);
1150 max_y2 = maxval_double(n2_in, y2_in);
1151 if(min_y1 >= max_y2+RANGE_CHECK_CRITERIA)
return 0;
1152 max_y1 = maxval_double(n1_in, y1_in);
1153 min_y2 = minval_double(n2_in, y2_in);
1154 if(min_y2 >= max_y1+RANGE_CHECK_CRITERIA)
return 0;
1156 min_z1 = minval_double(n1_in, z1_in);
1157 max_z2 = maxval_double(n2_in, z2_in);
1158 if(min_z1 >= max_z2+RANGE_CHECK_CRITERIA)
return 0;
1159 max_z1 = maxval_double(n1_in, z1_in);
1160 min_z2 = minval_double(n2_in, z2_in);
1161 if(min_z2 >= max_z1+RANGE_CHECK_CRITERIA)
return 0;
1165 grid1List = getNext();
1166 grid2List = getNext();
1167 intersectList = getNext();
1168 polyList = getNext();
1171 for(i1=0; i1<n1_in; i1++) addEnd(grid1List, x1_in[i1], y1_in[i1], z1_in[i1], 0, 0, 0, -1);
1172 for(i2=0; i2<n2_in; i2++) addEnd(grid2List, x2_in[i2], y2_in[i2], z2_in[i2], 0, 0, 0, -1);
1173 npts1 = length(grid1List);
1174 npts2 = length(grid2List);
1182 if(insidePolygon(temp, grid2List))
1186 temp = getNextNode(temp);
1193 if(insidePolygon(temp, grid1List))
1197 temp = getNextNode(temp);
1203 if( gridArea(grid1List) <= 0 )
1204 error_handler(
"create_xgrid.c(clip_2dx2d_great_circle): grid box 1 is not convex");
1205 if( gridArea(grid2List) <= 0 )
1206 error_handler(
"create_xgrid.c(clip_2dx2d_great_circle): grid box 2 is not convex");
1213 for(i1=0; i1<npts1; i1++) {
1214 getCoordinates(temp, pt1[i1]);
1218 for(i2=0; i2<npts2; i2++) {
1219 getCoordinates(temp, pt2[i2]);
1223 firstIntersect=getNext();
1224 curIntersect = getNext();
1228 for(i1=0; i1<npts1; i1++) {
1232 for(i2=0; i2<npts2; i2++) {
1234 i2p2 = (i2+2)%npts2;
1238 if( line_intersect_2D_3D(p1_0, p1_1, p2_0, p2_1, p2_2, intersect, &u1, &u2, &inbound) ) {
1244 if(addIntersect(intersectList, intersect[0], intersect[1], intersect[2], 1, u1, u2, inbound, i1, i1p, i2, i2p)) {
1248 insertIntersect(grid1List, intersect[0], intersect[1], intersect[2], 0.0, u2, inbound, p1_1[0], p1_1[1], p1_1[2]);
1251 insertIntersect(grid1List, intersect[0], intersect[1], intersect[2], u1, u2, inbound, p1_0[0], p1_0[1], p1_0[2]);
1254 p1_1[0] = intersect[0];
1255 p1_1[1] = intersect[1];
1256 p1_1[2] = intersect[2];
1259 p1_0[0] = intersect[0];
1260 p1_0[1] = intersect[1];
1261 p1_0[2] = intersect[2];
1265 insertIntersect(grid2List, intersect[0], intersect[1], intersect[2], 0.0, u1, 0, p2_1[0], p2_1[1], p2_1[2]);
1267 insertIntersect(grid2List, intersect[0], intersect[1], intersect[2], u2, u1, 0, p2_0[0], p2_0[1], p2_0[2]);
1270 p2_1[0] = intersect[0];
1271 p2_1[1] = intersect[1];
1272 p2_1[2] = intersect[2];
1275 p2_0[0] = intersect[0];
1276 p2_0[1] = intersect[1];
1277 p2_0[2] = intersect[2];
1291 temp = intersectList;
1292 nintersect = length(intersectList);
1293 if(nintersect > 1) {
1294 getFirstInbound(intersectList, firstIntersect);
1295 if(firstIntersect->initialized) {
1301 if( !has_inbound && nintersect > 1) {
1302 setInbound(intersectList, grid1List);
1303 getFirstInbound(intersectList, firstIntersect);
1304 if(firstIntersect->initialized) has_inbound = 1;
1311 maxiter1 = nintersect;
1312 temp1 = getNode(grid1List, *firstIntersect);
1313 if( temp1 == NULL) {
1314 double lon[10], lat[10];
1316 xyz2latlon(n1_in, x1_in, y1_in, z1_in, lon, lat);
1317 for(i=0; i< n1_in; i++) printf(
"lon1 = %g, lat1 = %g\n", lon[i]*R2D, lat[i]*R2D);
1319 xyz2latlon(n2_in, x2_in, y2_in, z2_in, lon, lat);
1320 for(i=0; i< n2_in; i++) printf(
"lon2 = %g, lat2 = %g\n", lon[i]*R2D, lat[i]*R2D);
1323 error_handler(
"firstIntersect is not in the grid1List");
1325 addNode(polyList, *firstIntersect);
1329 curList = grid1List;
1335 copyNode(curIntersect, *firstIntersect);
1339 while( iter1 < maxiter1 ) {
1341 temp1 = getNode(curList, *curIntersect);
1342 temp2 = temp1->Next;
1343 if( temp2 == NULL ) temp2 = curList;
1345 maxiter2 = length(curList);
1349 while( iter2 < maxiter2 ) {
1350 int temp2IsIntersect;
1352 temp2IsIntersect = 0;
1353 if( isIntersect( *temp2 ) ) {
1357 if( sameNode( *temp2, *firstIntersect) ) {
1362 temp3 = temp2->Next;
1363 if( temp3 == NULL) temp3 = curList;
1364 if( temp3 == NULL) error_handler(
"creat_xgrid.c: temp3 can not be NULL");
1369 temp2IsIntersect = 1;
1370 if( isIntersect(*temp3) || (temp3->isInside == 1) ) found2 = 0;
1373 copyNode(curIntersect, *temp2);
1377 addNode(polyList, *temp2);
1378 if(temp2IsIntersect) {
1382 temp2 = temp2->Next;
1383 if( temp2 == NULL ) temp2 = curList;
1388 if( !found2 ) error_handler(
" not found the next intersection ");
1391 if( sameNode( *curIntersect, *firstIntersect) ) {
1397 addNode(polyList, *curIntersect);
1402 if( curListNum == 0) {
1403 curList = grid2List;
1407 curList = grid1List;
1412 if(!found1) error_handler(
"not return back to the first intersection");
1415 if( nintersect > 0) error_handler(
"After clipping, nintersect should be 0");
1419 while (temp1 != NULL) {
1420 getCoordinate(*temp1, x_out+n_out, y_out+n_out, z_out+n_out);
1421 temp1 = temp1->Next;
1426 if( n_out < 3) n_out = 0;
1437 if(temp->intersect != 1) {
1438 if( temp->isInside == 1) n1in2++;
1440 temp = getNextNode(temp);
1447 getCoordinate(*temp, &x_out[n], &y_out[n], &z_out[n]);
1449 temp = getNextNode(temp);
1452 if(n_out>0)
return n_out;
1462 if(temp->intersect != 1) {
1463 if( temp->isInside == 1) n2in1++;
1465 temp = getNextNode(temp);
1473 getCoordinate(*temp, &x_out[n], &y_out[n], &z_out[n]);
1475 temp = getNextNode(temp);
1494 int line_intersect_2D_3D(
double *a1,
double *a2,
double *q1,
double *q2,
double *q3,
1495 double *intersect,
double *u_a,
double *u_q,
int *inbound){
1504 double p1[3], v1[3], v2[3];
1505 double c1[3], c2[3], c3[3];
1506 double coincident,
sense, norm;
1508 int is_inter1, is_inter2;
1513 if(samePoint(a1[0], a1[1], a1[2], q1[0], q1[1], q1[2])) {
1516 intersect[0] = a1[0];
1517 intersect[1] = a1[1];
1518 intersect[2] = a1[2];
1521 else if (samePoint(a1[0], a1[1], a1[2], q2[0], q2[1], q2[2])) {
1524 intersect[0] = a1[0];
1525 intersect[1] = a1[1];
1526 intersect[2] = a1[2];
1529 else if(samePoint(a2[0], a2[1], a2[2], q1[0], q1[1], q1[2])) {
1532 intersect[0] = a2[0];
1533 intersect[1] = a2[1];
1534 intersect[2] = a2[2];
1537 else if (samePoint(a2[0], a2[1], a2[2], q2[0], q2[1], q2[2])) {
1540 intersect[0] = a2[0];
1541 intersect[1] = a2[1];
1542 intersect[2] = a2[2];
1559 is_inter1 = intersect_tri_with_line(plane, a1, a2, plane_p, u_a);
1564 if(fabs(*u_a) < EPSLN8) *u_a = 0;
1565 if(fabs(*u_a-1) < EPSLN8) *u_a = 1;
1568 if( (*u_a < 0) || (*u_a > 1) )
return 0;
1582 is_inter2 = intersect_tri_with_line(plane, q1, q2, plane_p, u_q);
1587 if(fabs(*u_q) < EPSLN8) *u_q = 0;
1588 if(fabs(*u_q-1) < EPSLN8) *u_q = 1;
1591 if( (*u_q < 0) || (*u_q > 1) )
return 0;
1596 vect_cross(a1, a2, c1);
1597 vect_cross(q1, q2, c2);
1598 vect_cross(c1, c2, c3);
1599 coincident = metric(c3);
1601 if(fabs(coincident) < EPSLN30)
return 0;
1604 intersect[0]=a1[0] + u*(a2[0]-a1[0]);
1605 intersect[1]=a1[1] + u*(a2[1]-a1[1]);
1606 intersect[2]=a1[2] + u*(a2[2]-a1[2]);
1608 norm = metric( intersect );
1609 for(i = 0; i < 3; i ++) intersect[i] /= norm;
1612 if(*u_q != 0 && *u_q != 1){
1614 p1[0] = a2[0]-a1[0];
1615 p1[1] = a2[1]-a1[1];
1616 p1[2] = a2[2]-a1[2];
1617 v1[0] = q2[0]-q1[0];
1618 v1[1] = q2[1]-q1[1];
1619 v1[2] = q2[2]-q1[2];
1620 v2[0] = q3[0]-q2[0];
1621 v2[1] = q3[1]-q2[1];
1622 v2[2] = q3[2]-q2[2];
1624 vect_cross(v1, v2, c1);
1625 vect_cross(v1, p1, c2);
1627 sense = dot(c1, c2);
1629 if(
sense > 0) *inbound = 2;
1641 double poly_ctrlat(
const double x[],
const double y[],
int n)
1643 double ctrlat = 0.0;
1648 double dx = (x[ip]-x[i]);
1649 double dy, avg_y, hdy;
1655 avg_y = (lat1+lat2)*0.5;
1656 if (dx==0.0)
continue;
1657 if(dx > M_PI) dx = dx - 2.0*M_PI;
1658 if(dx < -M_PI) dx = dx + 2.0*M_PI;
1660 if ( fabs(hdy)< SMALL_VALUE )
1661 ctrlat -= dx*(2*cos(avg_y) + lat2*sin(avg_y) - cos(lat1) );
1663 ctrlat -= dx*( (sin(hdy)/hdy)*(2*cos(avg_y) + lat2*sin(avg_y)) - cos(lat1) );
1665 return (ctrlat*RADIUS*RADIUS);
1672 double poly_ctrlon(
const double x[],
const double y[],
int n,
double clon)
1674 double ctrlon = 0.0;
1679 double phi1, phi2, dphi, lat1, lat2, dphi1, dphi2;
1680 double f1, f2, fac, fint;
1687 if (dphi==0.0)
continue;
1689 f1 = 0.5*(cos(lat1)*sin(lat1)+lat1);
1690 f2 = 0.5*(cos(lat2)*sin(lat2)+lat2);
1694 if(dphi > M_PI) dphi = dphi - 2.0*M_PI;
1695 if(dphi < -M_PI) dphi = dphi + 2.0*M_PI;
1696 dphi1 = phi1 - clon;
1697 if( dphi1 > M_PI) dphi1 -= 2.0*M_PI;
1698 if( dphi1 <-M_PI) dphi1 += 2.0*M_PI;
1700 if( dphi2 > M_PI) dphi2 -= 2.0*M_PI;
1701 if( dphi2 <-M_PI) dphi2 += 2.0*M_PI;
1703 if(fabs(dphi2 -dphi1) < M_PI) {
1704 ctrlon -= dphi * (dphi1*f1+dphi2*f2)/2.0;
1711 fint = f1 + (f2-f1)*(fac-dphi1)/fabs(dphi);
1712 ctrlon -= 0.5*dphi1*(dphi1-fac)*f1 - 0.5*dphi2*(dphi2+fac)*f2
1713 + 0.5*fac*(dphi1+dphi2)*fint;
1717 return (ctrlon*RADIUS*RADIUS);
1729 int inside_edge(
double x0,
double y0,
double x1,
double y1,
double x,
double y)
1731 const double SMALL = 1.e-12;
1734 product = ( x-x0 )*(y1-y0) + (x0-x1)*(y-y0);
1735 return (product<=SMALL) ? 1:0;
pure elemental type(point) function latlon2xyz(lat, lon)
Return the (x,y,z) position of a given (lat,lon) point.
real(r8_kind), dimension(:,:), allocatable area
area of each grid box
integer nlat
No description.
integer nlon
No description.
integer sense
No description.
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.