22 #include "grid_utils.h"
23 #include "tree_utils.h"
40 void error_handler(
const char *msg)
42 fprintf(
stderr,
"FATAL Error: %s\n", msg );
44 MPI_Abort(MPI_COMM_WORLD, -1);
55 double maxval_double(
int size,
const double *data)
61 for(n=1; n<size; n++){
62 if( data[n] > maxval ) maxval = data[n];
74 double minval_double(
int size,
const double *data)
80 for(n=1; n<size; n++){
81 if( data[n] < minval ) minval = data[n];
92 double avgval_double(
int size,
const double *data)
98 for(n=0; n<size; n++) avgval += data[n];
110 void latlon2xyz(
int size,
const double *lon,
const double *lat,
double *x,
double *y,
double *z)
114 for(n=0; n<size; n++) {
115 x[n] = cos(lat[n])*cos(lon[n]);
116 y[n] = cos(lat[n])*sin(lon[n]);
126 void xyz2latlon(
int np,
const double *x,
const double *y,
const double *z,
double *lon,
double *lat)
133 for(i=0; i<np; i++) {
137 dist = sqrt(xx*xx+yy*yy+zz*zz);
142 if ( fabs(xx)+fabs(yy) < EPSLN10 )
145 lon[i] = atan2(yy, xx);
148 if ( lon[i] < 0.) lon[i] = 2.*M_PI + lon[i];
153 int delete_vtx(
double x[],
double y[],
int n,
int n_del)
155 for (;n_del<n-1;n_del++) {
156 x[n_del] = x[n_del+1];
157 y[n_del] = y[n_del+1];
163 int insert_vtx(
double x[],
double y[],
int n,
int n_ins,
double lon_in,
double lat_in)
167 for (i=n-1;i>=n_ins;i--) {
177 void v_print(
double x[],
double y[],
int n)
182 printf(
" %20g %20g\n", x[i], y[i]);
186 int fix_lon(
double x[],
double y[],
int n,
double tlon)
188 double x_sum, dx, dx_;
189 int i, nn = n, pole = 0;
191 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) pole = 1;
193 printf(
"fixing pole cell\n");
199 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) {
200 int im=(i+nn-1)%nn, ip=(i+1)%nn;
202 if (y[im]==y[i] && y[ip]==y[i]) {
203 nn = delete_vtx(x, y, nn, i);
205 }
else if (y[im]!=y[i] && y[ip]!=y[i]) {
206 nn = insert_vtx(x, y, nn, i, x[i], y[i]);
212 for (i=0;i<nn;i++)
if (fabs(y[i])>=HPI-TOLERANCE) {
213 int im=(i+nn-1)%nn, ip=(i+1)%nn;
232 if (dx_ < -M_PI) dx_ = dx_ + TPI;
233 else if (dx_ > M_PI) dx_ = dx_ - TPI;
234 x_sum += (x[i] = x[i-1] + dx_);
237 dx = (x_sum/nn)-tlon;
250 printf(
"area=%g\n", poly_area(x, y,nn));
265 double great_circle_distance(
double *p1,
double *p2)
272 beta = 2.*asin( sqrt( sin((p1[1]-p2[1])/2.)*sin((p1[1]-p2[1])/2.) +
273 cos(p1[1])*cos(p2[1])*(sin((p1[0]-p2[0])/2.)*sin((p1[0]-p2[0])/2.)) ) );
289 double spherical_angle(
const double *v1,
const double *v2,
const double *v3)
292 long double px, py, pz, qx, qy, qz, ddd;
295 px = v1[1]*v2[2] - v1[2]*v2[1];
296 py = v1[2]*v2[0] - v1[0]*v2[2];
297 pz = v1[0]*v2[1] - v1[1]*v2[0];
299 qx = v1[1]*v3[2] - v1[2]*v3[1];
300 qy = v1[2]*v3[0] - v1[0]*v3[2];
301 qz = v1[0]*v3[1] - v1[1]*v3[0];
303 ddd = (px*px+py*py+pz*pz)*(qx*qx+qy*qy+qz*qz);
307 ddd = (px*qx+py*qy+pz*qz) / sqrtl(ddd);
308 if( fabsl(ddd-1) < EPSLN30 ) ddd = 1;
309 if( fabsl(ddd+1) < EPSLN30 ) ddd = -1;
310 if ( ddd>1. || ddd<-1. ) {
318 angle = ((double)acosl( ddd ));
330 void vect_cross(
const double *p1,
const double *p2,
double *e )
333 e[0] = p1[1]*p2[2] - p1[2]*p2[1];
334 e[1] = p1[2]*p2[0] - p1[0]*p2[2];
335 e[2] = p1[0]*p2[1] - p1[1]*p2[0];
345 double dot(
const double *p1,
const double *p2)
348 return( p1[0]*p2[0] + p1[1]*p2[1] + p1[2]*p2[2] );
353 double metric(
const double *p) {
354 return (sqrt(p[0]*p[0] + p[1]*p[1]+p[2]*p[2]) );
357 void normalize_vect(
double *e)
362 pdot = e[0]*e[0] + e[1] * e[1] + e[2] * e[2];
365 for(k=0; k<3; k++) e[k] /= pdot;
373 void unit_vect_latlon(
int size,
const double *lon,
const double *lat,
double *vlon,
double *vlat)
375 double sin_lon, cos_lon, sin_lat, cos_lat;
378 for(n=0; n<size; n++) {
379 sin_lon = sin(lon[n]);
380 cos_lon = cos(lon[n]);
381 sin_lat = sin(lat[n]);
382 cos_lat = cos(lat[n]);
384 vlon[3*n] = -sin_lon;
385 vlon[3*n+1] = cos_lon;
388 vlat[3*n] = -sin_lat*cos_lon;
389 vlat[3*n+1] = -sin_lat*sin_lon;
390 vlat[3*n+2] = cos_lat;
403 int intersect_tri_with_line(
const double *plane,
const double *l1,
const double *l2,
double *p,
406 long double M[3*3], inv_M[3*3];
411 const double *pnt0=plane;
412 const double *pnt1=plane+3;
413 const double *pnt2=plane+6;
418 M[0]=l1[0]-l2[0]; M[1]=pnt1[0]-pnt0[0]; M[2]=pnt2[0]-pnt0[0];
419 M[3]=l1[1]-l2[1]; M[4]=pnt1[1]-pnt0[1]; M[5]=pnt2[1]-pnt0[1];
420 M[6]=l1[2]-l2[2]; M[7]=pnt1[2]-pnt0[2]; M[8]=pnt2[2]-pnt0[2];
424 is_invert = invert_matrix_3x3(M,inv_M);
425 if (!is_invert)
return 0;
444 void mult(
long double m[],
long double v[],
long double out_v[]) {
446 out_v[0]=m[0]*v[0]+m[1]*v[1]+m[2]*v[2];
447 out_v[1]=m[3]*v[0]+m[4]*v[1]+m[5]*v[2];
448 out_v[2]=m[6]*v[0]+m[7]*v[1]+m[8]*v[2];
454 int invert_matrix_3x3(
long double m[],
long double m_inv[]) {
457 const long double det = m[0] * (m[4]*m[8] - m[5]*m[7])
458 -m[1] * (m[3]*m[8] - m[5]*m[6])
459 +m[2] * (m[3]*m[7] - m[4]*m[6]);
460 if (fabsl(det) < EPSLN15 )
return 0;
462 const long double deti = 1.0/det;
464 m_inv[0] = (m[4]*m[8] - m[5]*m[7]) * deti;
465 m_inv[1] = (m[2]*m[7] - m[1]*m[8]) * deti;
466 m_inv[2] = (m[1]*m[5] - m[2]*m[4]) * deti;
468 m_inv[3] = (m[5]*m[6] - m[3]*m[8]) * deti;
469 m_inv[4] = (m[0]*m[8] - m[2]*m[6]) * deti;
470 m_inv[5] = (m[2]*m[3] - m[0]*m[5]) * deti;
472 m_inv[6] = (m[3]*m[7] - m[4]*m[6]) * deti;
473 m_inv[7] = (m[1]*m[6] - m[0]*m[7]) * deti;
474 m_inv[8] = (m[0]*m[4] - m[1]*m[3]) * deti;
480 int inside_a_polygon(
double *lon1,
double *lat1,
int *npts,
double *lon2,
double *lat2)
483 double x2[20], y2[20], z2[20];
485 double min_x2, max_x2, min_y2, max_y2, min_z2, max_z2;
488 struct Node *grid1=NULL, *grid2=NULL;
494 max_x2 = maxval_double(*npts, x2);
495 if(x1 >= max_x2+RANGE_CHECK_CRITERIA)
return 0;
496 min_x2 = minval_double(*npts, x2);
497 if(min_x2 >= x1+RANGE_CHECK_CRITERIA)
return 0;
499 max_y2 = maxval_double(*npts, y2);
500 if(y1 >= max_y2+RANGE_CHECK_CRITERIA)
return 0;
501 min_y2 = minval_double(*npts, y2);
502 if(min_y2 >= y1+RANGE_CHECK_CRITERIA)
return 0;
504 max_z2 = maxval_double(*npts, z2);
505 if(z1 >= max_z2+RANGE_CHECK_CRITERIA)
return 0;
506 min_z2 = minval_double(*npts, z2);
507 if(min_z2 >= z1+RANGE_CHECK_CRITERIA)
return 0;
515 addEnd(grid1, x1, y1, z1, 0, 0, 0, -1);
516 for(i=0; i<*npts; i++) addEnd(grid2, x2[i], y2[i], z2[i], 0, 0, 0, -1);
518 isinside = insidePolygon(grid1, grid2);
524 int inside_a_polygon_(
double *lon1,
double *lat1,
int *npts,
double *lon2,
double *lat2)
529 isinside = inside_a_polygon(lon1, lat1, npts, lon2, lat2);
535 double get_global_area(
void)
538 garea = 4*M_PI*RADIUS*RADIUS;
543 double get_global_area_(
void)
546 garea = 4*M_PI*RADIUS*RADIUS;
551 double poly_area(
const double x[],
const double y[],
int n)
558 double dx = (x[ip]-x[i]);
564 if(dx > M_PI) dx = dx - 2.0*M_PI;
565 if(dx < -M_PI) dx = dx + 2.0*M_PI;
566 if (dx==0.0)
continue;
568 if ( fabs(lat1-lat2) < SMALL_VALUE)
569 area -= dx*sin(0.5*(lat1+lat2));
571 dy = 0.5*(lat1-lat2);
573 area -= dx*sin(0.5*(lat1+lat2))*dat;
577 return -
area*RADIUS*RADIUS;
579 return area*RADIUS*RADIUS;
583 double poly_area_no_adjust(
const double x[],
const double y[],
int n)
590 double dx = (x[ip]-x[i]);
595 if (dx==0.0)
continue;
597 if ( fabs(lat1-lat2) < SMALL_VALUE)
598 area -= dx*sin(0.5*(lat1+lat2));
600 area += dx*(cos(lat1)-cos(lat2))/(lat1-lat2);
603 return area*RADIUS*RADIUS;
605 return area*RADIUS*RADIUS;
615 double poly_area_dimensionless(
const double x[],
const double y[],
int n)
622 double dx = (x[ip]-x[i]);
628 if(dx > M_PI) dx = dx - 2.0*M_PI;
629 if(dx < -M_PI) dx = dx + 2.0*M_PI;
630 if (dx==0.0)
continue;
632 if ( fabs(lat1-lat2) < SMALL_VALUE)
633 area -= dx*sin(0.5*(lat1+lat2));
635 dy = 0.5*(lat1-lat2);
637 area -= dx*sin(0.5*(lat1+lat2))*dat;
641 return (-
area/(4*M_PI));
643 return (
area/(4*M_PI));
648 double great_circle_area(
int n,
const double *x,
const double *y,
const double *z) {
650 double pnt0[3], pnt1[3], pnt2[3];
655 for ( i=0; i<n; i++) {
660 pnt1[0] = x[(i+1)%n];
661 pnt1[1] = y[(i+1)%n];
662 pnt1[2] = z[(i+1)%n];
663 pnt2[0] = x[(i+2)%n];
664 pnt2[1] = y[(i+2)%n];
665 pnt2[2] = z[(i+2)%n];
668 sum += spherical_angle(pnt1, pnt2, pnt0);
671 area = (sum - (n-2.)*M_PI) * RADIUS* RADIUS;
681 double spherical_excess_area(
const double* p_ll,
const double* p_ul,
682 const double* p_lr,
const double* p_ur,
double radius)
684 double area, ang1, ang2, ang3, ang4;
685 double v1[3], v2[3], v3[3];
691 ang1 = spherical_angle(v1, v2, v3);
697 ang2 = spherical_angle(v1, v2, v3);
703 ang3 = spherical_angle(v1, v2, v3);
709 ang4 = spherical_angle(v1, v2, v3);
711 area = (ang1 + ang2 + ang3 + ang4 - 2.*M_PI) * radius* radius;
721 void get_grid_area_(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
726 void get_grid_area(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
728 int nx, ny, nxp, i, j, n_in;
729 double x_in[20], y_in[20];
735 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
736 x_in[0] = lon[j*nxp+i];
737 x_in[1] = lon[j*nxp+i+1];
738 x_in[2] = lon[(j+1)*nxp+i+1];
739 x_in[3] = lon[(j+1)*nxp+i];
740 y_in[0] = lat[j*nxp+i];
741 y_in[1] = lat[j*nxp+i+1];
742 y_in[2] = lat[(j+1)*nxp+i+1];
743 y_in[3] = lat[(j+1)*nxp+i];
744 n_in = fix_lon(x_in, y_in, 4, M_PI);
745 area[j*nx+i] = poly_area(x_in, y_in, n_in);
755 void get_grid_area_ug_(
const int *npts,
const double *lon,
const double *lat,
double *
area)
757 get_grid_area_ug(npts, lon, lat,
area);
760 void get_grid_area_ug(
const int *npts,
const double *lon,
const double *lat,
double *
area)
763 double x_in[20], y_in[20];
768 for(l=0; l<nl; l++) {
770 x_in[1] = lon[l*nv+1];
771 x_in[2] = lon[l*nv+2];
772 x_in[3] = lon[l*nv+3];
774 y_in[1] = lat[l*nv+1];
775 y_in[2] = lat[l*nv+2];
776 y_in[3] = lat[l*nv+3];
777 n_in = fix_lon(x_in, y_in, nv, M_PI);
778 area[l] = poly_area(x_in, y_in, n_in);
784 void get_grid_great_circle_area_(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
790 void get_grid_great_circle_area(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
792 int nx, ny, nxp, nyp, i, j;
794 struct Node *grid=NULL;
795 double *x=NULL, *y=NULL, *z=NULL;
803 x = (
double *)malloc(nxp*nyp*
sizeof(
double));
804 y = (
double *)malloc(nxp*nyp*
sizeof(
double));
805 z = (
double *)malloc(nxp*nyp*
sizeof(
double));
809 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
817 addEnd(grid, x[n0], y[n0], z[n0], 0, 0, 0, -1);
818 addEnd(grid, x[n1], y[n1], z[n1], 0, 0, 0, -1);
819 addEnd(grid, x[n2], y[n2], z[n2], 0, 0, 0, -1);
820 addEnd(grid, x[n3], y[n3], z[n3], 0, 0, 0, -1);
821 area[j*nx+i] = gridArea(grid);
830 void get_grid_great_circle_area_ug_(
const int *npts,
const double *lon,
const double *lat,
double *
area)
832 get_grid_great_circle_area_ug(npts, lon, lat,
area);
836 void get_grid_great_circle_area_ug(
const int *npts,
const double *lon,
const double *lat,
double *
area)
840 struct Node *grid=NULL;
841 double *x=NULL, *y=NULL, *z=NULL;
846 x = (
double *)malloc(nl*nv*
sizeof(
double));
847 y = (
double *)malloc(nl*nv*
sizeof(
double));
848 z = (
double *)malloc(nl*nv*
sizeof(
double));
852 for(l=0; l<nv; l++) {
860 addEnd(grid, x[n0], y[n0], z[n0], 0, 0, 0, -1);
861 addEnd(grid, x[n1], y[n1], z[n1], 0, 0, 0, -1);
862 addEnd(grid, x[n2], y[n2], z[n2], 0, 0, 0, -1);
863 addEnd(grid, x[n3], y[n3], z[n3], 0, 0, 0, -1);
864 area[l] = gridArea(grid);
873 void get_grid_area_dimensionless(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
875 int nx, ny, nxp, i, j, n_in;
876 double x_in[20], y_in[20];
882 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
883 x_in[0] = lon[j*nxp+i];
884 x_in[1] = lon[j*nxp+i+1];
885 x_in[2] = lon[(j+1)*nxp+i+1];
886 x_in[3] = lon[(j+1)*nxp+i];
887 y_in[0] = lat[j*nxp+i];
888 y_in[1] = lat[j*nxp+i+1];
889 y_in[2] = lat[(j+1)*nxp+i+1];
890 y_in[3] = lat[(j+1)*nxp+i];
891 n_in = fix_lon(x_in, y_in, 4, M_PI);
892 area[j*nx+i] = poly_area_dimensionless(x_in, y_in, n_in);
899 void get_grid_area_no_adjust(
const int *
nlon,
const int *
nlat,
const double *lon,
const double *lat,
double *
area)
901 int nx, ny, nxp, i, j, n_in;
902 double x_in[20], y_in[20];
908 for(j=0; j<ny; j++)
for(i=0; i < nx; i++) {
909 x_in[0] = lon[j*nxp+i];
910 x_in[1] = lon[j*nxp+i+1];
911 x_in[2] = lon[(j+1)*nxp+i+1];
912 x_in[3] = lon[(j+1)*nxp+i];
913 y_in[0] = lat[j*nxp+i];
914 y_in[1] = lat[j*nxp+i+1];
915 y_in[2] = lat[(j+1)*nxp+i+1];
916 y_in[3] = lat[(j+1)*nxp+i];
918 area[j*nx+i] = poly_area_no_adjust(x_in, y_in, n_in);
928 int clip(
const double lon_in[],
const double lat_in[],
int n_in,
double ll_lon,
double ll_lat,
929 double ur_lon,
double ur_lat,
double lon_out[],
double lat_out[])
931 double x_tmp[MV], y_tmp[MV], x_last, y_last;
932 int i_in, i_out, n_out, inside_last, inside;
935 x_last = lon_in[n_in-1];
936 y_last = lat_in[n_in-1];
937 inside_last = (x_last >= ll_lon);
938 for (i_in=0,i_out=0;i_in<n_in;i_in++) {
941 if ((inside=(lon_in[i_in] >= ll_lon))!=inside_last) {
942 x_tmp[i_out] = ll_lon;
943 y_tmp[i_out++] = y_last + (ll_lon - x_last) * (lat_in[i_in] - y_last) / (lon_in[i_in] - x_last);
948 x_tmp[i_out] = lon_in[i_in];
949 y_tmp[i_out++] = lat_in[i_in];
951 x_last = lon_in[i_in];
952 y_last = lat_in[i_in];
953 inside_last = inside;
955 if (!(n_out=i_out))
return(0);
958 x_last = x_tmp[n_out-1];
959 y_last = y_tmp[n_out-1];
960 inside_last = (x_last <= ur_lon);
961 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
964 if ((inside=(x_tmp[i_in] <= ur_lon))!=inside_last) {
965 lon_out[i_out] = ur_lon;
966 lat_out[i_out++] = y_last + (ur_lon - x_last) * (y_tmp[i_in] - y_last)
967 / (x_tmp[i_in] - x_last);
972 lon_out[i_out] = x_tmp[i_in];
973 lat_out[i_out++] = y_tmp[i_in];
976 x_last = x_tmp[i_in];
977 y_last = y_tmp[i_in];
978 inside_last = inside;
980 if (!(n_out=i_out))
return(0);
983 x_last = lon_out[n_out-1];
984 y_last = lat_out[n_out-1];
985 inside_last = (y_last >= ll_lat);
986 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
989 if ((inside=(lat_out[i_in] >= ll_lat))!=inside_last) {
990 y_tmp[i_out] = ll_lat;
991 x_tmp[i_out++] = x_last + (ll_lat - y_last) * (lon_out[i_in] - x_last) / (lat_out[i_in] - y_last);
996 x_tmp[i_out] = lon_out[i_in];
997 y_tmp[i_out++] = lat_out[i_in];
999 x_last = lon_out[i_in];
1000 y_last = lat_out[i_in];
1001 inside_last = inside;
1003 if (!(n_out=i_out))
return(0);
1006 x_last = x_tmp[n_out-1];
1007 y_last = y_tmp[n_out-1];
1008 inside_last = (y_last <= ur_lat);
1009 for (i_in=0,i_out=0;i_in<n_out;i_in++) {
1012 if ((inside=(y_tmp[i_in] <= ur_lat))!=inside_last) {
1013 lat_out[i_out] = ur_lat;
1014 lon_out[i_out++] = x_last + (ur_lat - y_last) * (x_tmp[i_in] - x_last) / (y_tmp[i_in] - y_last);
1019 lon_out[i_out] = x_tmp[i_in];
1020 lat_out[i_out++] = y_tmp[i_in];
1022 x_last = x_tmp[i_in];
1023 y_last = y_tmp[i_in];
1024 inside_last = inside;
1035 int clip_2dx2d(
const double lon1_in[],
const double lat1_in[],
int n1_in,
1036 const double lon2_in[],
const double lat2_in[],
int n2_in,
1037 double lon_out[],
double lat_out[])
1039 double lon_tmp[MV], lat_tmp[MV];
1040 double x1_0, y1_0, x1_1, y1_1, x2_0, y2_0, x2_1, y2_1;
1041 double dx1, dy1, dx2, dy2, determ, ds1, ds2;
1042 int i_out, n_out, inside_last, inside, i1, i2;
1047 for(i1=0; i1<n1_in; i1++) {
1048 lon_tmp[i1] = lon1_in[i1];
1049 lat_tmp[i1] = lat1_in[i1];
1051 x2_0 = lon2_in[n2_in-1];
1052 y2_0 = lat2_in[n2_in-1];
1053 for(i2=0; i2<n2_in; i2++) {
1056 x1_0 = lon_tmp[n_out-1];
1057 y1_0 = lat_tmp[n_out-1];
1058 inside_last = inside_edge( x2_0, y2_0, x2_1, y2_1, x1_0, y1_0);
1059 for(i1=0, i_out=0; i1<n_out; i1++) {
1062 if((inside = inside_edge(x2_0, y2_0, x2_1, y2_1, x1_1, y1_1)) != inside_last ) {
1070 ds1 = y1_0*x1_1 - y1_1*x1_0;
1071 ds2 = y2_0*x2_1 - y2_1*x2_0;
1072 determ = dy2*dx1 - dy1*dx2;
1073 if(fabs(determ) < EPSLN30) {
1074 error_handler(
"the line between <x1_0,y1_0> and <x1_1,y1_1> should not parallel to "
1075 "the line between <x2_0,y2_0> and <x2_1,y2_1>");
1077 lon_out[i_out] = (dx2*ds1 - dx1*ds2)/determ;
1078 lat_out[i_out++] = (dy2*ds1 - dy1*ds2)/determ;
1083 lon_out[i_out] = x1_1;
1084 lat_out[i_out++] = y1_1;
1088 inside_last = inside;
1090 if(!(n_out=i_out))
return 0;
1091 for(i1=0; i1<n_out; i1++) {
1092 lon_tmp[i1] = lon_out[i1];
1093 lat_tmp[i1] = lat_out[i1];
1114 int clip_2dx2d_great_circle(
const double x1_in[],
const double y1_in[],
const double z1_in[],
int n1_in,
1115 const double x2_in[],
const double y2_in[],
const double z2_in [],
int n2_in,
1116 double x_out[],
double y_out[],
double z_out[])
1118 struct Node *grid1List=NULL;
1119 struct Node *grid2List=NULL;
1120 struct Node *intersectList=NULL;
1121 struct Node *polyList=NULL;
1122 struct Node *curList=NULL;
1123 struct Node *firstIntersect=NULL, *curIntersect=NULL;
1124 struct Node *temp1=NULL, *temp2=NULL, *temp=NULL;
1126 int i1, i2, i1p, i2p, i2p2, npts1, npts2;
1127 int nintersect, n_out;
1128 int maxiter1, maxiter2, iter1, iter2;
1129 int found1, found2, curListNum;
1130 int has_inbound, inbound;
1131 double pt1[MV][3], pt2[MV][3];
1132 double *p1_0=NULL, *p1_1=NULL;
1133 double *p2_0=NULL, *p2_1=NULL, *p2_2=NULL;
1134 double intersect[3];
1136 double min_x1, max_x1, min_y1, max_y1, min_z1, max_z1;
1137 double min_x2, max_x2, min_y2, max_y2, min_z2, max_z2;
1141 min_x1 = minval_double(n1_in, x1_in);
1142 max_x2 = maxval_double(n2_in, x2_in);
1143 if(min_x1 >= max_x2+RANGE_CHECK_CRITERIA)
return 0;
1144 max_x1 = maxval_double(n1_in, x1_in);
1145 min_x2 = minval_double(n2_in, x2_in);
1146 if(min_x2 >= max_x1+RANGE_CHECK_CRITERIA)
return 0;
1148 min_y1 = minval_double(n1_in, y1_in);
1149 max_y2 = maxval_double(n2_in, y2_in);
1150 if(min_y1 >= max_y2+RANGE_CHECK_CRITERIA)
return 0;
1151 max_y1 = maxval_double(n1_in, y1_in);
1152 min_y2 = minval_double(n2_in, y2_in);
1153 if(min_y2 >= max_y1+RANGE_CHECK_CRITERIA)
return 0;
1155 min_z1 = minval_double(n1_in, z1_in);
1156 max_z2 = maxval_double(n2_in, z2_in);
1157 if(min_z1 >= max_z2+RANGE_CHECK_CRITERIA)
return 0;
1158 max_z1 = maxval_double(n1_in, z1_in);
1159 min_z2 = minval_double(n2_in, z2_in);
1160 if(min_z2 >= max_z1+RANGE_CHECK_CRITERIA)
return 0;
1164 grid1List = getNext();
1165 grid2List = getNext();
1166 intersectList = getNext();
1167 polyList = getNext();
1170 for(i1=0; i1<n1_in; i1++) addEnd(grid1List, x1_in[i1], y1_in[i1], z1_in[i1], 0, 0, 0, -1);
1171 for(i2=0; i2<n2_in; i2++) addEnd(grid2List, x2_in[i2], y2_in[i2], z2_in[i2], 0, 0, 0, -1);
1172 npts1 = length(grid1List);
1173 npts2 = length(grid2List);
1181 if(insidePolygon(temp, grid2List))
1185 temp = getNextNode(temp);
1192 if(insidePolygon(temp, grid1List))
1196 temp = getNextNode(temp);
1202 if( gridArea(grid1List) <= 0 )
1203 error_handler(
"create_xgrid.c(clip_2dx2d_great_circle): grid box 1 is not convex");
1204 if( gridArea(grid2List) <= 0 )
1205 error_handler(
"create_xgrid.c(clip_2dx2d_great_circle): grid box 2 is not convex");
1212 for(i1=0; i1<npts1; i1++) {
1213 getCoordinates(temp, pt1[i1]);
1217 for(i2=0; i2<npts2; i2++) {
1218 getCoordinates(temp, pt2[i2]);
1222 firstIntersect=getNext();
1223 curIntersect = getNext();
1227 for(i1=0; i1<npts1; i1++) {
1231 for(i2=0; i2<npts2; i2++) {
1233 i2p2 = (i2+2)%npts2;
1237 if( line_intersect_2D_3D(p1_0, p1_1, p2_0, p2_1, p2_2, intersect, &u1, &u2, &inbound) ) {
1243 if(addIntersect(intersectList, intersect[0], intersect[1], intersect[2], 1, u1, u2, inbound, i1, i1p, i2, i2p)) {
1247 insertIntersect(grid1List, intersect[0], intersect[1], intersect[2], 0.0, u2, inbound, p1_1[0], p1_1[1], p1_1[2]);
1250 insertIntersect(grid1List, intersect[0], intersect[1], intersect[2], u1, u2, inbound, p1_0[0], p1_0[1], p1_0[2]);
1253 p1_1[0] = intersect[0];
1254 p1_1[1] = intersect[1];
1255 p1_1[2] = intersect[2];
1258 p1_0[0] = intersect[0];
1259 p1_0[1] = intersect[1];
1260 p1_0[2] = intersect[2];
1264 insertIntersect(grid2List, intersect[0], intersect[1], intersect[2], 0.0, u1, 0, p2_1[0], p2_1[1], p2_1[2]);
1266 insertIntersect(grid2List, intersect[0], intersect[1], intersect[2], u2, u1, 0, p2_0[0], p2_0[1], p2_0[2]);
1269 p2_1[0] = intersect[0];
1270 p2_1[1] = intersect[1];
1271 p2_1[2] = intersect[2];
1274 p2_0[0] = intersect[0];
1275 p2_0[1] = intersect[1];
1276 p2_0[2] = intersect[2];
1290 temp = intersectList;
1291 nintersect = length(intersectList);
1292 if(nintersect > 1) {
1293 getFirstInbound(intersectList, firstIntersect);
1294 if(firstIntersect->initialized) {
1300 if( !has_inbound && nintersect > 1) {
1301 setInbound(intersectList, grid1List);
1302 getFirstInbound(intersectList, firstIntersect);
1303 if(firstIntersect->initialized) has_inbound = 1;
1310 maxiter1 = nintersect;
1311 temp1 = getNode(grid1List, *firstIntersect);
1312 if( temp1 == NULL) {
1313 double lon[10], lat[10];
1315 xyz2latlon(n1_in, x1_in, y1_in, z1_in, lon, lat);
1316 for(i=0; i< n1_in; i++) printf(
"lon1 = %g, lat1 = %g\n", lon[i]*R2D, lat[i]*R2D);
1318 xyz2latlon(n2_in, x2_in, y2_in, z2_in, lon, lat);
1319 for(i=0; i< n2_in; i++) printf(
"lon2 = %g, lat2 = %g\n", lon[i]*R2D, lat[i]*R2D);
1322 error_handler(
"firstIntersect is not in the grid1List");
1324 addNode(polyList, *firstIntersect);
1328 curList = grid1List;
1334 copyNode(curIntersect, *firstIntersect);
1338 while( iter1 < maxiter1 ) {
1340 temp1 = getNode(curList, *curIntersect);
1341 temp2 = temp1->Next;
1342 if( temp2 == NULL ) temp2 = curList;
1344 maxiter2 = length(curList);
1348 while( iter2 < maxiter2 ) {
1349 int temp2IsIntersect;
1351 temp2IsIntersect = 0;
1352 if( isIntersect( *temp2 ) ) {
1356 if( sameNode( *temp2, *firstIntersect) ) {
1361 temp3 = temp2->Next;
1362 if( temp3 == NULL) temp3 = curList;
1363 if( temp3 == NULL) error_handler(
"creat_xgrid.c: temp3 can not be NULL");
1368 temp2IsIntersect = 1;
1369 if( isIntersect(*temp3) || (temp3->isInside == 1) ) found2 = 0;
1372 copyNode(curIntersect, *temp2);
1376 addNode(polyList, *temp2);
1377 if(temp2IsIntersect) {
1381 temp2 = temp2->Next;
1382 if( temp2 == NULL ) temp2 = curList;
1387 if( !found2 ) error_handler(
" not found the next intersection ");
1390 if( sameNode( *curIntersect, *firstIntersect) ) {
1396 addNode(polyList, *curIntersect);
1401 if( curListNum == 0) {
1402 curList = grid2List;
1406 curList = grid1List;
1411 if(!found1) error_handler(
"not return back to the first intersection");
1414 if( nintersect > 0) error_handler(
"After clipping, nintersect should be 0");
1418 while (temp1 != NULL) {
1419 getCoordinate(*temp1, x_out+n_out, y_out+n_out, z_out+n_out);
1420 temp1 = temp1->Next;
1425 if( n_out < 3) n_out = 0;
1436 if(temp->intersect != 1) {
1437 if( temp->isInside == 1) n1in2++;
1439 temp = getNextNode(temp);
1446 getCoordinate(*temp, &x_out[n], &y_out[n], &z_out[n]);
1448 temp = getNextNode(temp);
1451 if(n_out>0)
return n_out;
1461 if(temp->intersect != 1) {
1462 if( temp->isInside == 1) n2in1++;
1464 temp = getNextNode(temp);
1472 getCoordinate(*temp, &x_out[n], &y_out[n], &z_out[n]);
1474 temp = getNextNode(temp);
1493 int line_intersect_2D_3D(
double *a1,
double *a2,
double *q1,
double *q2,
double *q3,
1494 double *intersect,
double *u_a,
double *u_q,
int *inbound){
1503 double p1[3], v1[3], v2[3];
1504 double c1[3], c2[3], c3[3];
1505 double coincident,
sense, norm;
1507 int is_inter1, is_inter2;
1512 if(samePoint(a1[0], a1[1], a1[2], q1[0], q1[1], q1[2])) {
1515 intersect[0] = a1[0];
1516 intersect[1] = a1[1];
1517 intersect[2] = a1[2];
1520 else if (samePoint(a1[0], a1[1], a1[2], q2[0], q2[1], q2[2])) {
1523 intersect[0] = a1[0];
1524 intersect[1] = a1[1];
1525 intersect[2] = a1[2];
1528 else if(samePoint(a2[0], a2[1], a2[2], q1[0], q1[1], q1[2])) {
1531 intersect[0] = a2[0];
1532 intersect[1] = a2[1];
1533 intersect[2] = a2[2];
1536 else if (samePoint(a2[0], a2[1], a2[2], q2[0], q2[1], q2[2])) {
1539 intersect[0] = a2[0];
1540 intersect[1] = a2[1];
1541 intersect[2] = a2[2];
1558 is_inter1 = intersect_tri_with_line(plane, a1, a2, plane_p, u_a);
1563 if(fabs(*u_a) < EPSLN8) *u_a = 0;
1564 if(fabs(*u_a-1) < EPSLN8) *u_a = 1;
1567 if( (*u_a < 0) || (*u_a > 1) )
return 0;
1581 is_inter2 = intersect_tri_with_line(plane, q1, q2, plane_p, u_q);
1586 if(fabs(*u_q) < EPSLN8) *u_q = 0;
1587 if(fabs(*u_q-1) < EPSLN8) *u_q = 1;
1590 if( (*u_q < 0) || (*u_q > 1) )
return 0;
1595 vect_cross(a1, a2, c1);
1596 vect_cross(q1, q2, c2);
1597 vect_cross(c1, c2, c3);
1598 coincident = metric(c3);
1600 if(fabs(coincident) < EPSLN30)
return 0;
1603 intersect[0]=a1[0] + u*(a2[0]-a1[0]);
1604 intersect[1]=a1[1] + u*(a2[1]-a1[1]);
1605 intersect[2]=a1[2] + u*(a2[2]-a1[2]);
1607 norm = metric( intersect );
1608 for(i = 0; i < 3; i ++) intersect[i] /= norm;
1611 if(*u_q != 0 && *u_q != 1){
1613 p1[0] = a2[0]-a1[0];
1614 p1[1] = a2[1]-a1[1];
1615 p1[2] = a2[2]-a1[2];
1616 v1[0] = q2[0]-q1[0];
1617 v1[1] = q2[1]-q1[1];
1618 v1[2] = q2[2]-q1[2];
1619 v2[0] = q3[0]-q2[0];
1620 v2[1] = q3[1]-q2[1];
1621 v2[2] = q3[2]-q2[2];
1623 vect_cross(v1, v2, c1);
1624 vect_cross(v1, p1, c2);
1626 sense = dot(c1, c2);
1628 if(
sense > 0) *inbound = 2;
1640 double poly_ctrlat(
const double x[],
const double y[],
int n)
1642 double ctrlat = 0.0;
1647 double dx = (x[ip]-x[i]);
1648 double dy, avg_y, hdy;
1654 avg_y = (lat1+lat2)*0.5;
1655 if (dx==0.0)
continue;
1656 if(dx > M_PI) dx = dx - 2.0*M_PI;
1657 if(dx < -M_PI) dx = dx + 2.0*M_PI;
1659 if ( fabs(hdy)< SMALL_VALUE )
1660 ctrlat -= dx*(2*cos(avg_y) + lat2*sin(avg_y) - cos(lat1) );
1662 ctrlat -= dx*( (sin(hdy)/hdy)*(2*cos(avg_y) + lat2*sin(avg_y)) - cos(lat1) );
1664 return (ctrlat*RADIUS*RADIUS);
1671 double poly_ctrlon(
const double x[],
const double y[],
int n,
double clon)
1673 double ctrlon = 0.0;
1678 double phi1, phi2, dphi, lat1, lat2, dphi1, dphi2;
1679 double f1, f2, fac, fint;
1686 if (dphi==0.0)
continue;
1688 f1 = 0.5*(cos(lat1)*sin(lat1)+lat1);
1689 f2 = 0.5*(cos(lat2)*sin(lat2)+lat2);
1693 if(dphi > M_PI) dphi = dphi - 2.0*M_PI;
1694 if(dphi < -M_PI) dphi = dphi + 2.0*M_PI;
1695 dphi1 = phi1 - clon;
1696 if( dphi1 > M_PI) dphi1 -= 2.0*M_PI;
1697 if( dphi1 <-M_PI) dphi1 += 2.0*M_PI;
1699 if( dphi2 > M_PI) dphi2 -= 2.0*M_PI;
1700 if( dphi2 <-M_PI) dphi2 += 2.0*M_PI;
1702 if(fabs(dphi2 -dphi1) < M_PI) {
1703 ctrlon -= dphi * (dphi1*f1+dphi2*f2)/2.0;
1710 fint = f1 + (f2-f1)*(fac-dphi1)/fabs(dphi);
1711 ctrlon -= 0.5*dphi1*(dphi1-fac)*f1 - 0.5*dphi2*(dphi2+fac)*f2
1712 + 0.5*fac*(dphi1+dphi2)*fint;
1716 return (ctrlon*RADIUS*RADIUS);
1728 int inside_edge(
double x0,
double y0,
double x1,
double y1,
double x,
double y)
1730 const double SMALL = 1.e-12;
1733 product = ( x-x0 )*(y1-y0) + (x0-x1)*(y-y0);
1734 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.