#include #include #include #include "va_advanced.h" #define BREAKAXIS 5 #define BREAKALL 25 #define BREAKAXIST 8 #define BREAKALLT 64 static float aspect = 0; static int min_literal = 1; static int max_literal = 0; static int dist_pass = 0; static int recomp = 0; static float * xx, * yy, * zz; static unsigned char * assigned; static float * lats, * lons; static float * dist; static float * gooddist; static int * goodness; static double * goodcomp; static float weighting = 0.0; static int just_goodness = 0; static float dtr; /* This routine allows the client to place more importance on either user */ /* preferences or spatial uniformity in determining the visibility */ /* thresholds. 0 means only consider user preferences, 1 means only */ /* consider spatial uniformity. 0 is the default, values between 0 and 1 */ /* are meaningful. */ void va_weighting(float wgt) { weighting = wgt; } /* Normally, when selecting which station to include next, two things are */ /* considered. First, spatial uniformity, which means use the station */ /* furthest from any station currently included. Second, user preferences */ /* which are usually expressed in terms of the distance to the nearest */ /* other station with at least as great a goodness value. Expressing both */ /* in terms of a distance means that these two considerations can easily be */ /* blended. This routine allows one to just consider the goodness value as */ /* is for determining the next station to include. */ void va_just_goodness(int yes) { just_goodness = yes; } /* When this value is set to greater than one, it is assumed that the items */ /* being plotted using this progressive strategy are this factor wider than */ /* they are tall. */ void va_aspect(float a) { aspect = a; } /* Goodness values between these two numbers are taken literally as */ /* progressive disclosure distances. By default no goodness values will */ /* be treated this way. */ void va_literal(int mn, int mx) { min_literal = mn; max_literal = mx; } /* If this is set to true, then valid progressive disclosure distances in */ /* the array input_dist will be preserved. */ void va_dist_pass(int dp) { dist_pass = dp; } /* If this is set to true, then valid progressive disclosure distances in */ /* the array input_dist will be converted to goodness values. */ void va_recomp(int rc) { recomp = rc; } /* The job of this routine is to convert goodness values into a precursor */ /* to progressive disclosure distances, namely the distance to the nearest */ /* other station which has at least as great a goodness value. */ static int goodness_to_dist(float minlat, float maxlat, float minlon, float maxlon, int * active, int na) { float dis1; int best1; int * subactive[BREAKALL]; int ns[BREAKALL]; float mnlts[BREAKALL], mxlts[BREAKALL]; float mnlns[BREAKALL], mxlns[BREAKALL]; int **subim, **subjm, **submm; int *nsim, *nsjm, *nsmm; int * topactive; int nt; int i,j,k,kk,a,g,gg; float dlt,dln; float mnlt,mxlt,mnln,mxln; float dx,dy,dz,d,dd; if (na<=0) return -1; if (na>BREAKALL*2) { /* We still have too many stations in this sub area for this algorithm to work efficiently, divide this working area further into subareas. */ nt = 0; topactive = (int *)malloc(4*BREAKALL); dlt = (maxlat-minlat)/(1+BREAKAXIS); dln = (maxlon-minlon)/(1+BREAKAXIS); mnlt = minlat; mxlt = mnlt+2*dlt; for (k=0,j=0; jBREAKAXIS) i = BREAKAXIS; j = (int)((lats[g]-minlat)/dlt); if (j<0) j = 0; if (j>BREAKAXIS) j = BREAKAXIS; k = j*BREAKAXIS+i; if (i<=0) { if (j>0) subjm[k][nsjm[k]++] = g; if (j=BREAKAXIS) { if (j>0) submm[k][nsmm[k]++] = g; if (j0) { subjm[k][nsjm[k]++] = g; submm[k][nsmm[k]++] = g; }/*endif*/ if (j=0) topactive[nt++] = kk; free(subactive[k]); }/*end for gg*/ } else { nt = na; topactive = active; }/*endif*/ best1 = -1; dis1 = -1; /* We are finding the distance to the nearest station that is at least as desirable. */ for (k=0; kgooddist[gg]) dd = gooddist[g]; else dd = gooddist[gg]; dx = xx[g]-xx[gg]; if (dx>dd || -dx>dd) continue; dy = yy[g]-yy[gg]; if (dy>dd || -dy>dd) continue; dz = zz[g]-zz[gg]; if (dz>dd || -dz>dd) continue; d = sqrt(dx*dx+dy*dy+dz*dz); if (d>dd) continue; if (goodcomp[g]<=goodcomp[gg] && d=0) { assigned[i] = 1; dist[i] = 2*sin(dist[i]/12740.0); goodcomp[i] = (1+dist[i])*big; } else if (goodness[i]>=min_literal && goodness[i]<=max_literal) { assigned[i] = 1; dist[i] = 2*sin(goodness[i]/12740.0); goodcomp[i] = (1+dist[i])*big; } else { assigned[i] = 0; dist[i] = 2.0; goodcomp[i] = goodness[i]; }/*endif*/ if (recomp) { assigned[i] = 0; dist[i] = 2.0; } gooddist[i] = 2.0; if (lats[i]maxlat) maxlat = lats[i]; if (lons[i]maxlon) maxlon = lons[i]; }/*end for*/ /* try to account for the aspect ratio of what is being plotted if the area of coverage is small. */ myaspect = 1.0; while (aspect>1) { /* unit vector of mean point */ xxa /= ns; yya /= ns; zza /= ns; d = sqrt(xxa*xxa+yya*yya+zza*zza); xxa /= d; yya /= d; zza /= d; /* east unit vector at mean point */ xxe = -yya; yye = xxa; d = sqrt(xxe*xxe+yye*yye); xxe /= d; yye /= d; /* get the greatest east-west separation from center */ dx = 0; dd = 1.0; for (i=0; idx) dx = d; d = xxa*xx[i]+yya*yy[i]+zza*zz[i]; if (ddx) dx = dd; dd = 1.0-2*dx; if (dd<=0.0) break; myaspect = pow(aspect,dd); /* north unit vector at mean point (AxE) */ xxn = -zza*yye; yyn = zza*xxe; zzn = xxa*yye-yya*xxe; /* artificially sqeeze points in the east-west dimension */ for (i=0; i=na) { /* Determine next non-preassigned station for final resolution. */ dd2 = -big; g = -1; for (kk=na; kk=dd || -dx>=dd) continue; dy = yy[g]-yy[gg]; if (dy>=dd || -dy>=dd) continue; dz = zz[g]-zz[gg]; if (dz>=dd || -dz>=dd) continue; d = sqrt(dx*dx+dy*dy+dz*dz); if (d>=dd) continue; dist[gg] = d; }/*end for*/ }/*end for*/ /* convert point to point distances in unit vector space to real distances in kilometers. */ for (i=0; i