int UpdateInteriorFlag(Vec *p, int interiorFlag, int pEndpointFromQdir, int qEndpointFromPdir) { double lon, lat; if(debug >= 4) { lon = atan2(p->y, p->x)/dtr; lat = asin(p->z)/dtr; printf(" intersection [%13.6e,%13.6e,%13.6e] -> (%10.6f,%10.6f) (UpdateInteriorFlag)\n", p->x, p->y, p->z, lon, lat); fflush(stdout); } SaveVertex(p); /* Update interiorFlag. */ if(pEndpointFromQdir == COUNTERCLOCKWISE) return P_IN_Q; else if(qEndpointFromPdir == COUNTERCLOCKWISE) return Q_IN_P; else /* Keep status quo. */ return interiorFlag; }
void SaveSharedSeg(Vec *p, Vec *q) { if(debug >= 4) { printf("\n SaveSharedSeg(): from [%13.6e,%13.6e,%13.6e]\n", p->x, p->y, p->z); printf(" SaveSharedSeg(): to [%13.6e,%13.6e,%13.6e]\n\n", q->x, q->y, q->z); fflush(stdout); } SaveVertex(p); SaveVertex(q); }
/* * Print out the second point of intersection and toggle in/out flag. */ int UpdateInteriorFlag(Vec *p, int interiorFlag, int pEndpointFromQdir, int qEndpointFromPdir) { double lon, lat; if (DEBUG >= 4) { lon = atan2(p->y, p->x) / DEG_TO_RADIANS; lat = asin(p->z) / DEG_TO_RADIANS; printf(" intersection [%13.6e,%13.6e,%13.6e] " "-> (%10.6f,%10.6f) (UpdateInteriorFlag)\n", p->x, p->y, p->z, lon, lat); fflush(stdout); } SaveVertex(p); // Update interiorFlag. if (pEndpointFromQdir == COUNTERCLOCKWISE) return P_IN_Q; else if (qEndpointFromPdir == COUNTERCLOCKWISE) return Q_IN_P; else // Keep status quo. return interiorFlag; }
/* * Sets up the polygons, runs the overlap computation, and returns the area of overlap. */ double computeOverlap(double *ilon, double *ilat, double *olon, double *olat, int energyMode, double refArea, double *areaRatio) { int i; double thisPixelArea; *areaRatio = 1.; if (energyMode) { nv = 0; for (i = 0; i < 4; ++i) SaveVertex(&P[i]); thisPixelArea = Girard(); *areaRatio = thisPixelArea / refArea; } nv = 0; if (DEBUG >= 4) { printf("Input (P):\n"); for (i = 0; i < 4; ++i) printf("%10.6f %10.6f\n", ilon[i], ilat[i]); printf("\nOutput (Q):\n"); for (i = 0; i < 4; ++i) printf("%10.6f %10.6f\n", olon[i], olat[i]); printf("\n"); fflush(stdout); } for (i = 0; i < 4; ++i) { P[i].x = cos(ilon[i]) * cos(ilat[i]); P[i].y = sin(ilon[i]) * cos(ilat[i]); P[i].z = sin(ilat[i]); } for (i = 0; i < 4; ++i) { Q[i].x = cos(olon[i]) * cos(olat[i]); Q[i].y = sin(olon[i]) * cos(olat[i]); Q[i].z = sin(olat[i]); } ComputeIntersection(P, Q); return (Girard()); }
/* * Advances and prints out an inside vertex if appropriate. */ int Advance(int ip, int *p_advances, int n, int inside, Vec *v) { double lon, lat; lon = atan2(v->y, v->x) / DEG_TO_RADIANS; lat = asin(v->z) / DEG_TO_RADIANS; if (inside) { if (DEBUG >= 4) { printf(" Advance(): inside vertex " "[%13.6e,%13.6e,%13.6e] -> (%10.6f,%10.6f)n", v->x, v->y, v->z, lon, lat); fflush(stdout); } SaveVertex(v); } (*p_advances)++; return (ip + 1) % n; }
void ComputeIntersection(Vec *P, Vec *Q) { Vec Pdir, Qdir; /* "Current" directed edges on P and Q */ Vec other; /* Temporary "edge-like" variable */ int ip, iq; /* Indices of ends of Pdir, Qdir */ int ip_begin, iq_begin; /* Indices of beginning of Pdir, Qdir */ int PToQDir; /* Qdir direction relative to Pdir */ /* (e.g. CLOCKWISE) */ int qEndpointFromPdir; /* End P vertex as viewed from beginning */ /* of Qdir relative to Qdir */ int pEndpointFromQdir; /* End Q vertex as viewed from beginning */ /* of Pdir relative to Pdir */ Vec firstIntersection; /* Point of intersection of Pdir, Qdir */ Vec secondIntersection; /* Second point of intersection */ /* (if there is one) */ int interiorFlag; /* Which polygon is inside the other */ int contained; /* Used for "completely contained" check */ int p_advances, q_advances; /* Number of times we've advanced */ /* P and Q indices */ int isFirstPoint; /* Is this the first point? */ int intersectionCode; /* SegSegIntersect() return code. */ /* Check for Q contained in P */ contained = TRUE; for(ip=0; ip<np; ++ip) { ip_begin = (ip + np - 1) % np; Cross(&P[ip_begin], &P[ip], &Pdir); Normalize(&Pdir); for(iq=0; iq<nq; ++iq) { if(debug >= 4) { printf("Q in P: Dot%d%d = %12.5e\n", ip, iq, Dot(&Pdir, &Q[iq])); fflush(stdout); } if(Dot(&Pdir, &Q[iq]) < -tolerance) { contained = FALSE; break; } } if(!contained) break; } if(contained) { if(debug >= 4) { printf("Q is entirely contained in P (output pixel is in input pixel)\n"); fflush(stdout); } for(iq=0; iq<nq; ++iq) SaveVertex(&Q[iq]); return; } /* Check for P contained in Q */ contained = TRUE; for(iq=0; iq<nq; ++iq) { iq_begin = (iq + nq - 1) % nq; Cross(&Q[iq_begin], &Q[iq], &Qdir); Normalize(&Qdir); for(ip=0; ip<np; ++ip) { if(debug >= 4) { printf("P in Q: Dot%d%d = %12.5e\n", iq, ip, Dot(&Qdir, &P[ip])); fflush(stdout); } if(Dot(&Qdir, &P[ip]) < -tolerance) { contained = FALSE; break; } } if(!contained) break; } if(contained) { if(debug >= 4) { printf("P is entirely contained in Q (input pixel is in output pixel)\n"); fflush(stdout); } nv = 0; for(ip=0; ip<np; ++ip) SaveVertex(&P[ip]); return; } /* Then check for polygon overlap */ ip = 0; iq = 0; p_advances = 0; q_advances = 0; interiorFlag = UNKNOWN; isFirstPoint = TRUE; while(FOREVER) { if(p_advances >= 2*np) break; if(q_advances >= 2*nq) break; if(p_advances >= np && q_advances >= nq) break; if(debug >= 4) { printf("-----\n"); if(interiorFlag == UNKNOWN) { printf("Before advances (UNKNOWN interiorFlag): ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d)\n", p_advances, q_advances); } else if(interiorFlag == P_IN_Q) { printf("Before advances (P_IN_Q): ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d)\n", p_advances, q_advances); } else if(interiorFlag == Q_IN_P) { printf("Before advances (Q_IN_P): ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d)\n", p_advances, q_advances); } else printf("\nBAD INTERIOR FLAG. Shouldn't get here\n"); fflush(stdout); } /* Previous point in the polygon */ ip_begin = (ip + np - 1) % np; iq_begin = (iq + nq - 1) % nq; /* The current polygon edges are given by */ /* the cross product of the vertex vectors */ Cross(&P[ip_begin], &P[ip], &Pdir); Cross(&Q[iq_begin], &Q[iq], &Qdir); PToQDir = DirectionCalculator(&P[ip], &Pdir, &Qdir); Cross(&Q[iq_begin], &P[ip], &other); pEndpointFromQdir = DirectionCalculator(&Q[iq_begin], &Qdir, &other); Cross(&P[ip_begin], &Q[iq], &other); qEndpointFromPdir = DirectionCalculator(&P[ip_begin], &Pdir, &other); if(debug >= 4) { printf(" "); printDir("P", "Q", PToQDir); printDir("pEndpoint", "Q", pEndpointFromQdir); printDir("qEndpoint", "P", qEndpointFromPdir); printf("\n"); fflush(stdout); } /* Find point(s) of intersection between edges */ intersectionCode = SegSegIntersect(&Pdir, &Qdir, &P[ip_begin], &P[ip], &Q[iq_begin], &Q[iq], &firstIntersection, &secondIntersection); if(intersectionCode == NORMAL_INTERSECT || intersectionCode == ENDPOINT_ONLY) { if(interiorFlag == UNKNOWN && isFirstPoint) { p_advances = 0; q_advances = 0; isFirstPoint = FALSE; } interiorFlag = UpdateInteriorFlag(&firstIntersection, interiorFlag, pEndpointFromQdir, qEndpointFromPdir); if(debug >= 4) { if(interiorFlag == UNKNOWN) printf(" interiorFlag -> UNKNOWN\n"); else if(interiorFlag == P_IN_Q) printf(" interiorFlag -> P_IN_Q\n"); else if(interiorFlag == Q_IN_P) printf(" interiorFlag -> Q_IN_P\n"); else printf(" BAD interiorFlag. Shouldn't get here\n"); fflush(stdout); } } /*-----Advance rules-----*/ /* Special case: Pdir & Qdir overlap and oppositely oriented. */ if((intersectionCode == COLINEAR_SEGMENTS) && (Dot(&Pdir, &Qdir) < 0)) { if(debug >= 4) { printf(" ADVANCE: Pdir and Qdir are colinear.\n"); fflush(stdout); } SaveSharedSeg(&firstIntersection, &secondIntersection); RemoveDups(); return; } /* Special case: Pdir & Qdir parallel and separated. */ if((PToQDir == PARALLEL) && (pEndpointFromQdir == CLOCKWISE) && (qEndpointFromPdir == CLOCKWISE)) { if(debug >= 4) { printf(" ADVANCE: Pdir and Qdir are disjoint.\n"); fflush(stdout); } RemoveDups(); return; } /* Special case: Pdir & Qdir colinear. */ else if((PToQDir == PARALLEL) && (pEndpointFromQdir == PARALLEL) && (qEndpointFromPdir == PARALLEL)) { if(debug >= 4) { printf(" ADVANCE: Pdir and Qdir are colinear.\n"); fflush(stdout); } /* Advance but do not output point. */ if(interiorFlag == P_IN_Q) iq = Advance(iq, &q_advances, nq, interiorFlag == Q_IN_P, &Q[iq]); else ip = Advance(ip, &p_advances, np, interiorFlag == P_IN_Q, &P[ip]); } /* Generic cases. */ else if(PToQDir == COUNTERCLOCKWISE || PToQDir == PARALLEL) { if(qEndpointFromPdir == COUNTERCLOCKWISE) { if(debug >= 4) { printf(" ADVANCE: Generic: PToQDir is COUNTERCLOCKWISE "); printf("|| PToQDir is PARALLEL, "); printf("qEndpointFromPdir is COUNTERCLOCKWISE\n"); fflush(stdout); } ip = Advance(ip, &p_advances, np, interiorFlag == P_IN_Q, &P[ip]); } else { if(debug >= 4) { printf(" ADVANCE: Generic: PToQDir is COUNTERCLOCKWISE "); printf("|| PToQDir is PARALLEL, qEndpointFromPdir is CLOCKWISE\n"); fflush(stdout); } iq = Advance(iq, &q_advances, nq, interiorFlag == Q_IN_P, &Q[iq]); } } else { if(pEndpointFromQdir == COUNTERCLOCKWISE) { if(debug >= 4) { printf(" ADVANCE: Generic: PToQDir is CLOCKWISE, "); printf("pEndpointFromQdir is COUNTERCLOCKWISE\n"); fflush(stdout); } iq = Advance(iq, &q_advances, nq, interiorFlag == Q_IN_P, &Q[iq]); } else { if(debug >= 4) { printf(" ADVANCE: Generic: PToQDir is CLOCKWISE, "); printf("pEndpointFromQdir is CLOCKWISE\n"); fflush(stdout); } ip = Advance(ip, &p_advances, np, interiorFlag == P_IN_Q, &P[ip]); } } if(debug >= 4) { if(interiorFlag == UNKNOWN) { printf("After advances: ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d) interiorFlag=UNKNOWN\n", p_advances, q_advances); } else if(interiorFlag == P_IN_Q) { printf("After advances: ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d) interiorFlag=P_IN_Q\n", p_advances, q_advances); } else if(interiorFlag == Q_IN_P) { printf("After advances: ip=%d, iq=%d ", ip, iq); printf("(p_advances=%d, q_advances=%d) interiorFlag=Q_IN_P\n", p_advances, q_advances); } else printf("BAD INTERIOR FLAG. Shouldn't get here\n"); printf("-----\n\n"); fflush(stdout); } } RemoveDups(); return; }
double computeOverlap(double *ilon, double *ilat, double *olon, double *olat, int energyMode, double refArea, double *areaRatio) { int i; double thisPixelArea; pi = atan(1.0) * 4.; dtr = pi / 180.; *areaRatio = 1.; if(energyMode) { nv = 0; for(i=0; i<4; ++i) SaveVertex(&P[i]); thisPixelArea = Girard(); *areaRatio = thisPixelArea / refArea; } nv = 0; if(debug >= 4) { printf("\n-----------------------------------------------\n\nAdding pixel (%d,%d) to pixel (%d,%d)\n\n", inRow, inColumn, outRow, outColumn); printf("Input (P):\n"); for(i=0; i<4; ++i) printf("%10.6f %10.6f\n", ilon[i], ilat[i]); printf("\nOutput (Q):\n"); for(i=0; i<4; ++i) printf("%10.6f %10.6f\n", olon[i], olat[i]); printf("\n"); fflush(stdout); } for(i=0; i<4; ++i) { P[i].x = cos(ilon[i]*dtr) * cos(ilat[i]*dtr); P[i].y = sin(ilon[i]*dtr) * cos(ilat[i]*dtr); P[i].z = sin(ilat[i]*dtr); } for(i=0; i<4; ++i) { Q[i].x = cos(olon[i]*dtr) * cos(olat[i]*dtr); Q[i].y = sin(olon[i]*dtr) * cos(olat[i]*dtr); Q[i].z = sin(olat[i]*dtr); } ComputeIntersection(P, Q); return(Girard()); }