23#include "grid_utils.h"
24#include "tree_utils.h"
41void error_handler(
const char *msg)
43 fprintf(stderr,
"FATAL Error: %s\n", msg );
45 MPI_Abort(MPI_COMM_WORLD, -1);
56double maxval_double(
int size,
const double *data)
62 for(n=1; n<size; n++){
63 if( data[n] > maxval ) maxval = data[n];
75double minval_double(
int size,
const double *data)
81 for(n=1; n<size; n++){
82 if( data[n] < minval ) minval = data[n];
93double avgval_double(
int size,
const double *data)
99 for(n=0; n<size; n++) avgval += data[n];
111void 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]);
127void 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];
154int 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];
164int 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--) {
178void v_print(
double x[],
double y[],
int n)
183 printf(
" %20g %20g\n", x[i], y[i]);
187int 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));
266double 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.)) ) );
290double 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 ));
331void 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];
346double dot(
const double *p1,
const double *p2)
349 return( p1[0]*p2[0] + p1[1]*p2[1] + p1[2]*p2[2] );
354double metric(
const double *p) {
355 return (sqrt(p[0]*p[0] + p[1]*p[1]+p[2]*p[2]) );
358void 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;
374void 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;
404int 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;
445void 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];
455int 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;
481int 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);
525int inside_a_polygon_(
double *lon1,
double *lat1,
int *npts,
double *lon2,
double *lat2)
530 isinside = inside_a_polygon(lon1, lat1, npts, lon2, lat2);
536double get_global_area(
void)
539 garea = 4*M_PI*RADIUS*RADIUS;
544double get_global_area_(
void)
547 garea = 4*M_PI*RADIUS*RADIUS;
552double 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;
584double 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;
616double 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));
649double 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;
682double 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;
722void get_grid_area_(
const int *nlon,
const int *nlat,
const double *lon,
const double *lat,
double *area)
724 get_grid_area(nlon, nlat, lon, lat, area);
727void 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);
756void get_grid_area_ug_(
const int *npts,
const double *lon,
const double *lat,
double *area)
758 get_grid_area_ug(npts, lon, lat, area);
761void 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);
785void get_grid_great_circle_area_(
const int *nlon,
const int *nlat,
const double *lon,
const double *lat,
double *area)
787 get_grid_great_circle_area(nlon, nlat, lon, lat, area);
791void 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);
831void 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);
837void 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);
874void 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);
900void 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);
929int 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;
1036int 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];
1115int 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);
1494int 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;
1641double 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);
1672double 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);
1729int 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.