// generate double bivariate Chebychev polynomial public static bool bchgen(projUV a, projUV b, int nu, int nv, projUV[][] f, ProjFunc func) { projUV arg, bma, bpa; projUV[] t, c; bma.u = 0.5 * (b.u - a.u); bma.v = 0.5 * (b.v - a.v); bpa.u = 0.5 * (b.u + a.u); bpa.v = 0.5 * (b.v + a.v); for (int i = 0; i < nu; i++) { arg.u = Math.Cos(Proj.PI * (i + 0.5) / nu) * bma.u + bpa.u; for (int j = 0; j < nv; j++) { arg.v = Math.Cos(Proj.PI * (j + 0.5) / nv) * bma.v + bpa.v; f[i][j] = func(arg); if (f[i][j].u == Libc.HUGE_VAL) { return(true); } } } try { c = new projUV[nu]; } catch { return(true); } double fac = 2.0 / nu; for (int j = 0; j < nv; j++) { for (int i = 0; i < nu; i++) { arg.u = arg.v = 0.0; for (int k = 0; k < nu; k++) { double d = Math.Cos(Proj.PI * i * (k + 0.5) / nu); arg.u += f[k][j].u * d; arg.v += f[k][j].v * d; } arg.u *= fac; arg.v *= fac; c[i] = arg; } for (int i = 0; i < nu; i++) { f[i][j] = c[i]; } } try { c = new projUV[nv]; } catch { return(true); } fac = 2.0 / nv; for (int i = 0; i < nu; i++) { t = f[i]; for (int j = 0; j < nv; j++) { arg.u = arg.v = 0.0; for (int k = 0; k < nv; k++) { double d = Math.Cos(Proj.PI * j * (k + 0.5) / nv); arg.u += t[k].u * d; arg.v += t[k].v * d; } arg.u *= fac; arg.v *= fac; c[j] = arg; } f[i] = c; c = t; } return(false); }
public static Tseries mk_cheby(projUV a, projUV b, double res, ref projUV resid, ProjFunc func, int nu, int nv, bool power) { try { projUV[][] w = new projUV[nu][]; for (int k = 0; k < nu; k++) { w[k] = new projUV[nv]; } if (bchgen(a, b, nu, nv, w, func)) { return(null); } // analyse coefficients and adjust until residual OK double cutres = res; int i = 4; for (; i > 0; i--) { eval(w, nu, nv, cutres, ref resid); if (resid.u < res && resid.v < res) { break; } cutres *= 0.5; } // warn of too many tries if (i <= 0) { resid.u = -resid.u; } double ab; double[] p; int[] ncu = new int[nu]; int[] ncv = new int[nv]; // apply cut resolution and set pointers int nru = 0, nrv = 0; for (int j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; // clear column maxes projUV[] s = w[j]; for (i = 0; i < nv; i++) { // < resolution ? ab = Math.Abs(s[i].u); if (ab < cutres) { s[i].u = 0.0; // clear coefficient } else { ncu[j] = i + 1; // update column max } ab = Math.Abs(s[i].v); if (ab < cutres) { s[i].v = 0.0; // same for v coef's } else { ncv[j] = i + 1; } } if (ncu[j] != 0) { nru = j + 1; // update row max } if (ncv[j] != 0) { nrv = j + 1; } } if (power) { // convert to bivariate power series if (!bch2bps(a, b, w, nu, nv)) { return(null); } // possible change in some row counts, so readjust nru = nrv = 0; for (int j = 0; j < nu; ++j) { ncu[j] = ncv[j] = 0; // clear column maxes projUV[] s = w[j]; for (i = 0; i < nv; i++) { if (s[i].u != 0) { ncu[j] = i + 1; // update column max } if (s[i].v != 0) { ncv[j] = i + 1; } } if (ncu[j] != 0) { nru = j + 1; // update row max } if (ncv[j] != 0) { nrv = j + 1; } } Tseries T = makeT(nru, nrv); if (T != null) { T.a = a; T.b = b; T.mu = nru - 1; T.mv = nrv - 1; T.power = 1; for (i = 0; i < nru; ++i) // store coefficient rows for u { T.cu[i].m = ncu[i]; if (T.cu[i].m != 0) { p = T.cu[i].c = new double[ncu[i]]; projUV[] s = w[i]; for (int j = 0; j < ncu[i]; j++) { p[j] = s[j].u; } } } for (i = 0; i < nrv; ++i) // same for v { T.cv[i].m = ncv[i]; if (T.cv[i].m != 0) { p = T.cv[i].c = new double[ncv[i]]; projUV[] s = w[i]; for (int j = 0; j < ncv[i]; j++) { p[j] = s[j].v; } } } } return(T); } else { Tseries T = makeT(nru, nrv); if (T != null) { // else make returned Chebyshev coefficient structure T.mu = nru - 1; // save row degree T.mv = nrv - 1; T.a.u = a.u + b.u; // set argument scaling T.a.v = a.v + b.v; T.b.u = 1.0 / (b.u - a.u); T.b.v = 1.0 / (b.v - a.v); T.power = 0; for (i = 0; i < nru; ++i) // store coefficient rows for u { T.cu[i].m = ncu[i]; if (T.cu[i].m != 0) { p = T.cu[i].c = new double[ncu[i]]; projUV[] s = w[i]; for (int j = 0; j < ncu[i]; j++) { p[j] = s[j].u; } } } for (i = 0; i < nrv; ++i) // same for v { T.cv[i].m = ncv[i]; if (T.cv[i].m != 0) { p = T.cv[i].c = new double[ncv[i]]; projUV[] s = w[i]; for (int j = 0; j < ncv[i]; j++) { p[j] = s[j].v; } } } } return(T); } } catch { return(null); } }
public static Tseries mk_cheby(projUV a, projUV b, double res, ref projUV resid, ProjFunc func, int nu, int nv, bool power) { try { projUV[][] w=new projUV[nu][]; for(int k=0; k<nu; k++) w[k]=new projUV[nv]; if(bchgen(a, b, nu, nv, w, func)) return null; // analyse coefficients and adjust until residual OK double cutres=res; int i=4; for(; i>0; i--) { eval(w, nu, nv, cutres, ref resid); if(resid.u<res&&resid.v<res) break; cutres*=0.5; } // warn of too many tries if(i<=0) resid.u=-resid.u; double ab; double[] p; int[] ncu=new int[nu]; int[] ncv=new int[nv]; // apply cut resolution and set pointers int nru=0, nrv=0; for(int j=0; j<nu; ++j) { ncu[j]=ncv[j]=0; // clear column maxes projUV[] s=w[j]; for(i=0; i<nv; i++) { // < resolution ? ab=Math.Abs(s[i].u); if(ab<cutres) s[i].u=0.0; // clear coefficient else ncu[j]=i+1; // update column max ab=Math.Abs(s[i].v); if(ab<cutres) s[i].v=0.0; // same for v coef's else ncv[j]=i+1; } if(ncu[j]!=0) nru=j+1; // update row max if(ncv[j]!=0) nrv=j+1; } if(power) { // convert to bivariate power series if(!bch2bps(a, b, w, nu, nv)) return null; // possible change in some row counts, so readjust nru=nrv=0; for(int j=0; j<nu; ++j) { ncu[j]=ncv[j]=0; // clear column maxes projUV[] s=w[j]; for(i=0; i<nv; i++) { if(s[i].u!=0) ncu[j]=i+1; // update column max if(s[i].v!=0) ncv[j]=i+1; } if(ncu[j]!=0) nru=j+1; // update row max if(ncv[j]!=0) nrv=j+1; } Tseries T=makeT(nru, nrv); if(T!=null) { T.a=a; T.b=b; T.mu=nru-1; T.mv=nrv-1; T.power=1; for(i=0; i<nru; ++i) // store coefficient rows for u { T.cu[i].m=ncu[i]; if(T.cu[i].m!=0) { p=T.cu[i].c=new double[ncu[i]]; projUV[] s=w[i]; for(int j=0; j<ncu[i]; j++) p[j]=s[j].u; } } for(i=0; i<nrv; ++i) // same for v { T.cv[i].m=ncv[i]; if(T.cv[i].m!=0) { p=T.cv[i].c=new double[ncv[i]]; projUV[] s=w[i]; for(int j=0; j<ncv[i]; j++) p[j]=s[j].v; } } } return T; } else { Tseries T=makeT(nru, nrv); if(T!=null) { // else make returned Chebyshev coefficient structure T.mu=nru-1; // save row degree T.mv=nrv-1; T.a.u=a.u+b.u; // set argument scaling T.a.v=a.v+b.v; T.b.u=1.0/(b.u-a.u); T.b.v=1.0/(b.v-a.v); T.power=0; for(i=0; i<nru; ++i) // store coefficient rows for u { T.cu[i].m=ncu[i]; if(T.cu[i].m!=0) { p=T.cu[i].c=new double[ncu[i]]; projUV[] s=w[i]; for(int j=0; j<ncu[i]; j++) p[j]=s[j].u; } } for(i=0; i<nrv; ++i) // same for v { T.cv[i].m=ncv[i]; if(T.cv[i].m!=0) { p=T.cv[i].c=new double[ncv[i]]; projUV[] s=w[i]; for(int j=0; j<ncv[i]; j++) p[j]=s[j].v; } } } return T; } } catch { return null; } }
public static void gen_cheb(bool inverse, ProjFunc proj, string s, PJ P, int iargc, string[] iargv) { InputFunc input=Proj.dmstor; if(inverse) input=Libc.strtod; int errin=0; projUV low, upp; low.u=low.v=upp.u=upp.v=0; if(s.Length>0) low.u=input(s, out s); else errin++; if(s.Length>1&&s[0]==',') upp.u=input(s.Substring(1), out s); else errin++; if(s.Length>1&&s[0]==',') low.v=input(s.Substring(1), out s); else errin++; if(s.Length>1&&s[0]==',') upp.v=input(s.Substring(1), out s); else errin++; if(errin!=0) emess(16, "null or absent -T parameters"); int NU=15, NV=15, res=-1; if(s.Length>1&&s[0]==',') { s=s.Substring(1); if(s[0]!=',') res=Libc.strtol(s, out s, 10); } if(s.Length>1&&s[0]==',') { s=s.Substring(1); if(s[0]!=',') NU=Libc.strtol(s, out s, 10); } if(s.Length>1&&s[0]==',') { s=s.Substring(1); if(s[0]!=',') NV=Libc.strtol(s, out s, 10); } bool pwr=s.Length>0&&s.StartsWith(",P"); Console.WriteLine("#proj_{0}\n#\trun-line:", pwr?"Power":"Chebyshev"); // proj execution audit trail if(iargc>0) { int n=0; for(int i=0; i<iargc; i++) { string arg=iargv[i]; if(arg[0]!='+') { if(n==0) { Console.Write("#"); n++; } Console.Write(" "+arg); n+=arg.Length+1; if(n>50) { Console.WriteLine(); n=0; } } } if(n!=0) Console.WriteLine(); } Console.WriteLine("# projection parameters"); Console.WriteLine("#"+P.DescriptionName); Console.WriteLine("#"+P.DescriptionParameters); Console.WriteLine("#"+P.DescriptionType); Console.WriteLine("#"+P.ToProj4String()); if(low.u==upp.u||low.v>=upp.v) emess(16, "approx. argument range error"); if(low.u>upp.u) low.u-=Proj.TWOPI; if(NU<2||NV<2) emess(16, "approx. work dimensions ({0} {1}) too small", NU, NV); projUV resid=new projUV(); Tseries F=mk_cheby(low, upp, Math.Pow(10.0, res)*0.5, ref resid, proj, NU, NV, pwr); if(F==null) emess(16, "generation of approx failed\nreason: {0}\n", Proj.pj_strerrno(Libc.errno)); Console.WriteLine("{0},{1:G12},{2:G12},{3:G12},{4:G12},{5:G12}", inverse?'I':'F', P.lam0*Proj.RAD_TO_DEG, low.u*(inverse?1.0:Proj.RAD_TO_DEG), upp.u*(inverse?1.0:Proj.RAD_TO_DEG), low.v*(inverse?1.0:Proj.RAD_TO_DEG), upp.v*(inverse?1.0:Proj.RAD_TO_DEG)); string fmt; if(pwr) fmt="G15"; else if(res<=0) fmt=string.Format("F{0}", -res+1); else fmt="F0"; p_series(F, Console.Out, fmt); Console.WriteLine("# |u,v| sums {0} {1}\n#end_proj_{2}", resid.u, resid.v, pwr?"Power":"Chebyshev"); }
// generate double bivariate Chebychev polynomial public static bool bchgen(projUV a, projUV b, int nu, int nv, projUV[][] f, ProjFunc func) { projUV arg, bma, bpa; projUV[] t, c; bma.u=0.5*(b.u-a.u); bma.v=0.5*(b.v-a.v); bpa.u=0.5*(b.u+a.u); bpa.v=0.5*(b.v+a.v); for(int i=0; i<nu; i++) { arg.u=Math.Cos(Proj.PI*(i+0.5)/nu)*bma.u+bpa.u; for(int j=0; j<nv; j++) { arg.v=Math.Cos(Proj.PI*(j+0.5)/nv)*bma.v+bpa.v; f[i][j]=func(arg); if(f[i][j].u==Libc.HUGE_VAL) return true; } } try { c=new projUV[nu]; } catch { return true; } double fac=2.0/nu; for(int j=0; j<nv; j++) { for(int i=0; i<nu; i++) { arg.u=arg.v=0.0; for(int k=0; k<nu; k++) { double d=Math.Cos(Proj.PI*i*(k+0.5)/nu); arg.u+=f[k][j].u*d; arg.v+=f[k][j].v*d; } arg.u*=fac; arg.v*=fac; c[i]=arg; } for(int i=0; i<nu; i++) f[i][j]=c[i]; } try { c=new projUV[nv]; } catch { return true; } fac=2.0/nv; for(int i=0; i<nu; i++) { t=f[i]; for(int j=0; j<nv; j++) { arg.u=arg.v=0.0; for(int k=0; k<nv; k++) { double d=Math.Cos(Proj.PI*j*(k+0.5)/nv); arg.u+=t[k].u*d; arg.v+=t[k].v*d; } arg.u*=fac; arg.v*=fac; c[j]=arg; } f[i]=c; c=t; } return false; }
public static void gen_cheb(bool inverse, ProjFunc proj, string s, PJ P, int iargc, string[] iargv) { InputFunc input = Proj.dmstor; if (inverse) { input = Libc.strtod; } int errin = 0; projUV low, upp; low.u = low.v = upp.u = upp.v = 0; if (s.Length > 0) { low.u = input(s, out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { upp.u = input(s.Substring(1), out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { low.v = input(s.Substring(1), out s); } else { errin++; } if (s.Length > 1 && s[0] == ',') { upp.v = input(s.Substring(1), out s); } else { errin++; } if (errin != 0) { emess(16, "null or absent -T parameters"); } int NU = 15, NV = 15, res = -1; if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { res = Libc.strtol(s, out s, 10); } } if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { NU = Libc.strtol(s, out s, 10); } } if (s.Length > 1 && s[0] == ',') { s = s.Substring(1); if (s[0] != ',') { NV = Libc.strtol(s, out s, 10); } } bool pwr = s.Length > 0 && s.StartsWith(",P"); Console.WriteLine("#proj_{0}\n#\trun-line:", pwr?"Power":"Chebyshev"); // proj execution audit trail if (iargc > 0) { int n = 0; for (int i = 0; i < iargc; i++) { string arg = iargv[i]; if (arg[0] != '+') { if (n == 0) { Console.Write("#"); n++; } Console.Write(" " + arg); n += arg.Length + 1; if (n > 50) { Console.WriteLine(); n = 0; } } } if (n != 0) { Console.WriteLine(); } } Console.WriteLine("# projection parameters"); Console.WriteLine("#" + P.DescriptionName); Console.WriteLine("#" + P.DescriptionParameters); Console.WriteLine("#" + P.DescriptionType); Console.WriteLine("#" + P.ToProj4String()); if (low.u == upp.u || low.v >= upp.v) { emess(16, "approx. argument range error"); } if (low.u > upp.u) { low.u -= Proj.TWOPI; } if (NU < 2 || NV < 2) { emess(16, "approx. work dimensions ({0} {1}) too small", NU, NV); } projUV resid = new projUV(); Tseries F = mk_cheby(low, upp, Math.Pow(10.0, res) * 0.5, ref resid, proj, NU, NV, pwr); if (F == null) { emess(16, "generation of approx failed\nreason: {0}\n", Proj.pj_strerrno(Libc.errno)); } Console.WriteLine("{0},{1:G12},{2:G12},{3:G12},{4:G12},{5:G12}", inverse?'I':'F', P.lam0 * Proj.RAD_TO_DEG, low.u * (inverse?1.0:Proj.RAD_TO_DEG), upp.u * (inverse?1.0:Proj.RAD_TO_DEG), low.v * (inverse?1.0:Proj.RAD_TO_DEG), upp.v * (inverse?1.0:Proj.RAD_TO_DEG)); string fmt; if (pwr) { fmt = "G15"; } else if (res <= 0) { fmt = string.Format("F{0}", -res + 1); } else { fmt = "F0"; } p_series(F, Console.Out, fmt); Console.WriteLine("# |u,v| sums {0} {1}\n#end_proj_{2}", resid.u, resid.v, pwr?"Power":"Chebyshev"); }