// entry point public static bool bch2bps(projUV a, projUV b, projUV[][] c, int nu, int nv) { if(nu<1||nv<1) return false; try { projUV[][] d=new projUV[nu][]; for(int i=0; i<nu; i++) { d[i]=new projUV[nv]; // do rows to power series rows(c[i], d[i], nv); rowshft(a.v, b.v, d[i], nv); } // do columns to power series cols(d, c, nu, nv); colshft(a.u, b.u, c, nu, nv); return true; } catch { return false; } }
// convert columns to power series static void cols(projUV[][] c, projUV[][] d, int nu, int nv) { projUV[][] dd=new projUV[nu][]; for(int i=0; i<nu; i++) dd[i]=new projUV[nv]; projUV[] sv=new projUV[nv]; bclear(d, nu, nv); bclear(dd, nu, nv); bmove(d[0], c[nu-1], nv); for(int j=nu-2; j>=1; j--) { for(int k=nu-j; k>=1; k--) { bmove(sv, d[k], nv); submop(d[k], 2.0, d[k-1], dd[k], nv); bmove(dd[k], sv, nv); } bmove(sv, d[0], nv); subop(d[0], c[j], dd[0], nv); bmove(dd[0], sv, nv); } for(int j=nu-1; j>=1; j--) subop(d[j], d[j-1], dd[j], nv); submop(d[0], 0.5, c[0], dd[0], nv); }
// entry point public static bool bch2bps(projUV a, projUV b, projUV[][] c, int nu, int nv) { if (nu < 1 || nv < 1) { return(false); } try { projUV[][] d = new projUV[nu][]; for (int i = 0; i < nu; i++) { d[i] = new projUV[nv]; // do rows to power series rows(c[i], d[i], nv); rowshft(a.v, b.v, d[i], nv); } // do columns to power series cols(d, c, nu, nv); colshft(a.u, b.u, c, nu, nv); return(true); } catch { return(false); } }
// convert columns to power series static void cols(projUV[][] c, projUV[][] d, int nu, int nv) { projUV[][] dd = new projUV[nu][]; for (int i = 0; i < nu; i++) { dd[i] = new projUV[nv]; } projUV[] sv = new projUV[nv]; bclear(d, nu, nv); bclear(dd, nu, nv); bmove(d[0], c[nu - 1], nv); for (int j = nu - 2; j >= 1; j--) { for (int k = nu - j; k >= 1; k--) { bmove(sv, d[k], nv); submop(d[k], 2.0, d[k - 1], dd[k], nv); bmove(dd[k], sv, nv); } bmove(sv, d[0], nv); subop(d[0], c[j], dd[0], nv); bmove(dd[0], sv, nv); } for (int j = nu - 1; j >= 1; j--) { subop(d[j], d[j - 1], dd[j], nv); } submop(d[0], 0.5, c[0], dd[0], nv); }
// bivariate power polynomial entry point public static projUV bpseval(projUV @in, Tseries T) { projUV @out; @[email protected]=0.0; for(int i=T.mu; i>=0; --i) { double row=0.0; int m=T.cu[i].m; if(m!=0) { int c=m; while((m--)!=0) row=T.cu[i].c[--c][email protected]*row; } @[email protected]*@out.u; } for(int i=T.mv; i>=0; --i) { double row=0.0; int m=T.cv[i].m; if(m!=0) { int c=m; while((m--)!=0) row=T.cv[i].c[--c][email protected]*row; } @[email protected]*@out.v; } return @out; }
// general entry point selecting evaluation mode public static projUV biveval(projUV @in, Tseries T) { if (T.power != 0) { return(bpseval(@in, T)); } return(bcheval(@in, T)); }
//单点-正投影 public PointF GetXYFromLatLon(PointF pointOrg, MapHandle.config.ProjPara proj) { pointOrg.X = (float)(pointOrg.X * DEG2RAD); pointOrg.Y = (float)(pointOrg.Y * DEG2RAD); //投影参数初始化 IntPtr pj = ProjWrapper.pj_init_plus(getSrcProj(proj)); projUV temp = new projUV(pointOrg.X, pointOrg.Y); projUV coord = ProjWrapper.pj_fwd(temp, pj); PointF pointPrj = new PointF(); pointPrj.X = (float)(coord.U); pointPrj.Y = (float)(coord.V); return pointPrj; }
//单点-反投影 public PointF GetLatLonFromXY(PointF pointXY, MapHandle.config.ProjPara proj) { //投影参数初始化 PointF result = new PointF(); IntPtr pj = ProjWrapper.pj_init_plus(getSrcProj(proj)); projUV temp = new projUV(pointXY.X, pointXY.Y); projUV coord = ProjWrapper.pj_inv(temp, pj); result.X = (float)(coord.U); result.Y = (float)(coord.V); result.X = (float)(result.X * RAD2DEG); result.Y = (float)(result.Y * RAD2DEG); return result; }
//单点-反投影 public PointF GetLatLonFromXY(PointF pointXY, MapHandle.config.ProjPara proj) { //投影参数初始化 PointF result = new PointF(); IntPtr pj = ProjWrapper.pj_init_plus(getSrcProj(proj)); projUV temp = new projUV(pointXY.X, pointXY.Y); projUV coord = ProjWrapper.pj_inv(temp, pj); result.X = (float)(coord.U); result.Y = (float)(coord.V); result.X = (float)(result.X * RAD2DEG); result.Y = (float)(result.Y * RAD2DEG); return(result); }
//单点-正投影 public PointF GetXYFromLatLon(PointF pointOrg, MapHandle.config.ProjPara proj) { pointOrg.X = (float)(pointOrg.X * DEG2RAD); pointOrg.Y = (float)(pointOrg.Y * DEG2RAD); //投影参数初始化 IntPtr pj = ProjWrapper.pj_init_plus(getSrcProj(proj)); projUV temp = new projUV(pointOrg.X, pointOrg.Y); projUV coord = ProjWrapper.pj_fwd(temp, pj); PointF pointPrj = new PointF(); pointPrj.X = (float)(coord.U); pointPrj.Y = (float)(coord.V); return(pointPrj); }
// column adjust for range -1 to 1 to a to b static void colshft(double a, double b, projUV[][] d, int n, int m) { double cnst=2.0/(b-a); double fac=cnst; for(int j=1; j<n; j++) { dmult(d[j], fac, m); fac*=cnst; } cnst=0.5*(a+b); for(int j=0; j<=n-2; j++) for(int k=n-2; k>=j; k--) dadd(d[k], d[k+1], cnst, m); }
static double ceval(PW_COEF[] C, int n, projUV w, projUV w2) { double d = 0, dd = 0; int j; PW_COEF C1; for (; n != 0; n--) { C1 = C[n]; j = C1.m; double tmp = d; if (j != 0) { double vd = 0.0, vdd = 0.0; j--; for (; j != 0; j--) { double tmp2 = vd; vd = w2.v * tmp2 - vdd + C1.c[j]; vdd = tmp2; } d = w2.u * tmp - dd + w.v * vd - vdd + 0.5 * C1.c[j]; } else { d = w2.u * tmp - dd; } dd = tmp; } C1 = C[0]; j = C1.m; if (j != 0) { double vd = 0.0, vdd = 0.0; j--; for (; j != 0; j--) { double tmp2 = vd; vd = w2.v * tmp2 - vdd + C1.c[j]; vdd = tmp2; } return(w.u * d - dd + 0.5 * (w.v * vd - vdd + 0.5 * C1.c[j])); } return(w.u * d - dd); }
static double ceval(PW_COEF[] C, int n, projUV w, projUV w2) { double d=0, dd=0; int j; PW_COEF C1; for(; n!=0; n--) { C1=C[n]; j=C1.m; double tmp=d; if(j!=0) { double vd=0.0, vdd=0.0; j--; for(; j!=0; j--) { double tmp2=vd; vd=w2.v*tmp2-vdd+C1.c[j]; vdd=tmp2; } d=w2.u*tmp-dd+w.v*vd-vdd+0.5*C1.c[j]; } else d=w2.u*tmp-dd; dd=tmp; } C1=C[0]; j=C1.m; if(j!=0) { double vd=0.0, vdd=0.0; j--; for(; j!=0; j--) { double tmp2=vd; vd=w2.v*tmp2-vdd+C1.c[j]; vdd=tmp2; } return w.u*d-dd+0.5*(w.v*vd-vdd+0.5*C1.c[j]); } return w.u*d-dd; }
// sum coefficients less than res static void eval(projUV[][] w, int nu, int nv, double res, ref projUV resid) { resid.u = resid.v = 0.0; for (int i = 0; i < nu; i++) { for (int j = 0; j < nv; j++) { projUV s = w[i][j]; double ab = Math.Abs(s.u); if (ab < res) { resid.u += ab; } ab = Math.Abs(s.v); if (ab < res) { resid.v += ab; } } } }
// bivariate power polynomial entry point public static projUV bpseval(projUV @in, Tseries T) { projUV @out; @out.u = @out.v = 0.0; for (int i = T.mu; i >= 0; --i) { double row = 0.0; int m = T.cu[i].m; if (m != 0) { int c = m; while ((m--) != 0) { row = T.cu[i].c[--c] + @in.v * row; } } @out.u = row + @in.u * @out.u; } for (int i = T.mv; i >= 0; --i) { double row = 0.0; int m = T.cv[i].m; if (m != 0) { int c = m; while ((m--) != 0) { row = T.cv[i].c[--c] + @in.v * row; } } @out.v = row + @in.u * @out.v; } return(@out); }
// bivariate Chebyshev polynomial entry point public static projUV bcheval(projUV @in, Tseries T) { projUV w2, w, @out; // scale to +-1 w.u = (@in.u + @in.u - T.a.u) * T.b.u; w.v = (@in.v + @in.v - T.a.v) * T.b.v; if (Math.Abs(w.u) > NEAR_ONE || Math.Abs(w.v) > NEAR_ONE) { @out.u = @out.v = Libc.HUGE_VAL; Proj.pj_errno = -36; } else { // double evaluation w2.u = w.u + w.u; w2.v = w.v + w.v; @out.u = ceval(T.cu, T.mu, w, w2); @out.v = ceval(T.cv, T.mv, w, w2); } return(@out); }
// bivariate Chebyshev polynomial entry point public static projUV bcheval(projUV @in, Tseries T) { projUV w2, w, @out; // scale to +-1 w.u=(@[email protected])*T.b.u; w.v=(@[email protected])*T.b.v; if(Math.Abs(w.u)>NEAR_ONE||Math.Abs(w.v)>NEAR_ONE) { @[email protected]=Libc.HUGE_VAL; Proj.pj_errno=-36; } else { // double evaluation w2.u=w.u+w.u; w2.v=w.v+w.v; @out.u=ceval(T.cu, T.mu, w, w2); @out.v=ceval(T.cv, T.mv, w, w2); } return @out; }
// convert row to pover series static void rows(projUV[] c, projUV[] d, int n) { projUV[] dd = new projUV[n]; projUV sv; sv.u = sv.v = 0.0; for (int j = 0; j < n; j++) { d[j] = dd[j] = sv; } d[0] = c[n - 1]; for (int j = n - 2; j >= 1; j--) { for (int k = n - j; k >= 1; k--) { sv = d[k]; d[k].u = 2.0 * d[k - 1].u - dd[k].u; d[k].v = 2.0 * d[k - 1].v - dd[k].v; dd[k] = sv; } sv = d[0]; d[0].u = -dd[0].u + c[j].u; d[0].v = -dd[0].v + c[j].v; dd[0] = sv; } for (int j = n - 1; j >= 1; j--) { d[j].u = d[j - 1].u - dd[j].u; d[j].v = d[j - 1].v - dd[j].v; } d[0].u = -dd[0].u + 0.5 * c[0].u; d[0].v = -dd[0].v + 0.5 * c[0].v; }
// 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; }
// move vector static void bmove(projUV[] a, projUV[] b, int n) { for(int i=0; i<n; i++) a[i]=b[i]; }
// basic support procedures // clear matrix rows to zero static void bclear(projUV[][] p, int n, int m) { for(int i=0; i<n; i++) for(int j=0; j<m; j++) p[i][j].u=p[i][j].v=0; }
// a = b - c static void subop(projUV[] a, projUV[] b, projUV[] c, int n) { for(int i=0; i<n; i++) { a[i].u=b[i].u-c[i].u; a[i].v=b[i].v-c[i].v; } }
// row adjust a = a - m * b static void dadd(projUV[] a, projUV[] b, double m, int n) { for(int i=0; i<n; i++) { a[i].u-=m*b[i].u; a[i].v-=m*b[i].v; } }
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; } }
// sum coefficients less than res static void eval(projUV[][] w, int nu, int nv, double res, ref projUV resid) { resid.u=resid.v=0.0; for(int i=0; i<nu; i++) { for(int j=0; j<nv; j++) { projUV s=w[i][j]; double ab=Math.Abs(s.u); if(ab<res) resid.u+=ab; ab=Math.Abs(s.v); if(ab<res) resid.v+=ab; } } }
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"); }
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); } }
// multiply vector a by scalar m static void dmult(projUV[] a, double m, int n) { for(int i=0; i<n; i++) { a[i].u*=m; a[i].v*=m; } }
// 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); }
// convert row to pover series static void rows(projUV[] c, projUV[] d, int n) { projUV[] dd=new projUV[n]; projUV sv; sv.u=sv.v=0.0; for(int j=0; j<n; j++) d[j]=dd[j]=sv; d[0]=c[n-1]; for(int j=n-2; j>=1; j--) { for(int k=n-j; k>=1; k--) { sv=d[k]; d[k].u=2.0*d[k-1].u-dd[k].u; d[k].v=2.0*d[k-1].v-dd[k].v; dd[k]=sv; } sv=d[0]; d[0].u=-dd[0].u+c[j].u; d[0].v=-dd[0].v+c[j].v; dd[0]=sv; } for(int j=n-1; j>=1; j--) { d[j].u=d[j-1].u-dd[j].u; d[j].v=d[j-1].v-dd[j].v; } d[0].u=-dd[0].u+0.5*c[0].u; d[0].v=-dd[0].v+0.5*c[0].v; }
// general entry point selecting evaluation mode public static projUV biveval(projUV @in, Tseries T) { if(T.power!=0) return bpseval(@in, T); return bcheval(@in, T); }
// row adjust for range -1 to 1 to a to b static void rowshft(double a, double b, projUV[] d, int n) { double cnst=2.0/(b-a); double fac=cnst; for(int j=1; j<n; j++) { d[j].u*=fac; d[j].v*=fac; fac*=cnst; } cnst=0.5*(a+b); for(int j=0; j<=n-2; ++j) { for(int k=n-2; k>=j; k--) { d[k].u-=cnst*d[k+1].u; d[k].v-=cnst*d[k+1].v; } } }
// a = m * b - c static void submop(projUV[] a, double m, projUV[] b, projUV[] c, int n) { for(int i=0; i<n; i++) { a[i].u=m*b[i].u-c[i].u; a[i].v=m*b[i].v-c[i].v; } }
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"); }