//GridToGeodetic converts RT90 coordinates to WGS84 func GridToGeodetic(x, y float64) (float64, float64) { if CentralMeridian == 31337.0 { return 0.0, 0.0 } e2 := Flattening * (2.0 - Flattening) n := Flattening / (2.0 - Flattening) a_roof := Axis / (1.0 + n) * (1.0 + n*n/4.0 + n*n*n*n/64.0) delta1 := n/2.0 - 2.0*n*n/3.0 + 37.0*n*n*n/96.0 - n*n*n*n/360.0 delta2 := n*n/48.0 + n*n*n/15.0 - 437.0*n*n*n*n/1440.0 delta3 := 17.0*n*n*n/480.0 - 37*n*n*n*n/840.0 delta4 := 4397.0 * n * n * n * n / 161280.0 Astar := e2 + e2*e2 + e2*e2*e2 + e2*e2*e2*e2 Bstar := -(7.0*e2*e2 + 17.0*e2*e2*e2 + 30.0*e2*e2*e2*e2) / 6.0 Cstar := (224.0*e2*e2*e2 + 889.0*e2*e2*e2*e2) / 120.0 Dstar := -(4279.0 * e2 * e2 * e2 * e2) / 1260.0 DegToRad := math.Pi / 180 LambdaZero := CentralMeridian * DegToRad xi := (x - FalseNorthing) / (Scale * a_roof) eta := (y - FalseEasting) / (Scale * a_roof) xi_prim := xi - delta1*math.Sin(2.0*xi)*math.Cosh(2.0*eta) - delta2*math.Sin(4.0*xi)*math.Cosh(4.0*eta) - delta3*math.Sin(6.0*xi)*math.Cosh(6.0*eta) - delta4*math.Sin(8.0*xi)*math.Cosh(8.0*eta) eta_prim := eta - delta1*math.Cos(2.0*xi)*math.Sinh(2.0*eta) - delta2*math.Cos(4.0*xi)*math.Sinh(4.0*eta) - delta3*math.Cos(6.0*xi)*math.Sinh(6.0*eta) - delta4*math.Cos(8.0*xi)*math.Sinh(8.0*eta) phi_star := math.Asin(math.Sin(xi_prim) / math.Cosh(eta_prim)) delta_lambda := math.Atan(math.Sinh(eta_prim) / math.Cos(xi_prim)) lon_radian := LambdaZero + delta_lambda lat_radian := phi_star + math.Sin(phi_star)*math.Cos(phi_star)*(Astar+Bstar*math.Pow(math.Sin(phi_star), 2)+Cstar*math.Pow(math.Sin(phi_star), 4)+Dstar*math.Pow(math.Sin(phi_star), 6)) return lat_radian * 180.0 / math.Pi, lon_radian * 180.0 / math.Pi }
// Tanh 返回 x 的双曲正切。 func Tanh(x complex128) complex128 { d := math.Cosh(2*real(x)) + math.Cos(2*imag(x)) if d == 0 { return Inf() } return complex(math.Sinh(2*real(x))/d, math.Sin(2*imag(x))/d) }
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Tile_numbers_to_lon..2Flat. func getLonLatFromTileName(x, y, zoom int64) Point { n := math.Pow(2, float64(zoom)) lon := (float64(x) / n * 360) - 180 latRad := math.Atan(math.Sinh(math.Pi * (1 - (2 * float64(y) / n)))) lat := latRad * 180 / math.Pi return Point{lon, lat} }
func xyz_lonlat(x, y, z int) (lon, lat float64) { n := 1 << uint(z) fact := tilesize * float64(n) lon = float64(x)*360/fact - 180 prj := (1 - float64(y)*2/fact)*math.Pi lat = rad_deg(math.Atan(math.Sinh(prj))) return }
// 计算 sinh 和 cosh func sinhcosh(x float64) (sh, ch float64) { if math.Abs(x) <= 0.5 { return math.Sinh(x), math.Cosh(x) } e := math.Exp(x) ei := 0.5 / e e *= 0.5 return e - ei, e + ei }
// SinH returns the Cosine of a given angle func SinH(number float64) (float64, error) { if math.IsNaN(number) { return 0.0, errors.New("#VALUE! - Occurred because the supplied number argument is non-numeric") } // Sinh returns the hyperbolic sine of x. return math.Sinh(number), nil }
// Cot returns the cotangent of x. func Cot(x complex128) complex128 { d := math.Cosh(2*imag(x)) - math.Cos(2*real(x)) if math.Fabs(d) < 0.25 { d = tanSeries(x) } if d == 0 { return Inf() } return cmplx(math.Sin(2*real(x))/d, -math.Sinh(2*imag(x))/d) }
// Tan 返回 x 的正切值。 func Tan(x complex128) complex128 { d := math.Cos(2*real(x)) + math.Cosh(2*imag(x)) if math.Abs(d) < 0.25 { d = tanSeries(x) } if d == 0 { return Inf() } return complex(math.Sin(2*real(x))/d, math.Sinh(2*imag(x))/d) }
//GeodeticToGrid converts WGS84 coordinates to RT90 func GeodeticToGrid(lat, lon float64) (x, y float64) { // Prepare ellipsoid-based stuff. e2 := Flattening * (2.0 - Flattening) n := Flattening / (2.0 - Flattening) a_roof := Axis / (1.0 + n) * (1.0 + n*n/4.0 + n*n*n*n/64.0) A := e2 B := (5.0*e2*e2 - e2*e2*e2) / 6.0 C := (104.0*e2*e2*e2 - 45.0*e2*e2*e2*e2) / 120.0 D := (1237.0 * e2 * e2 * e2 * e2) / 1260.0 beta1 := n/2.0 - 2.0*n*n/3.0 + 5.0*n*n*n/16.0 + 41.0*n*n*n*n/180.0 beta2 := 13.0*n*n/48.0 - 3.0*n*n*n/5.0 + 557.0*n*n*n*n/1440.0 beta3 := 61.0*n*n*n/240.0 - 103.0*n*n*n*n/140.0 beta4 := 49561.0 * n * n * n * n / 161280.0 // Convert. DegToRad := math.Pi / 180.0 phi := lat * DegToRad lambd := lon * DegToRad lambda_zero := CentralMeridian * DegToRad phi_star := phi - math.Sin(phi)*math.Cos(phi)*(A+ B*math.Pow(math.Sin(phi), 2)+ C*math.Pow(math.Sin(phi), 4)+ D*math.Pow(math.Sin(phi), 6)) delta_lambda := lambd - lambda_zero xi_prim := math.Atan(math.Tan(phi_star) / math.Cos(delta_lambda)) eta_prim := math.Atanh(math.Cos(phi_star) * math.Sin(delta_lambda)) x = Scale*a_roof*(xi_prim+ beta1*math.Sin(2.0*xi_prim)*math.Cosh(2.0*eta_prim)+ beta2*math.Sin(4.0*xi_prim)*math.Cosh(4.0*eta_prim)+ beta3*math.Sin(6.0*xi_prim)*math.Cosh(6.0*eta_prim)+ beta4*math.Sin(8.0*xi_prim)*math.Cosh(8.0*eta_prim)) + FalseNorthing y = Scale*a_roof*(eta_prim+ beta1*math.Cos(2.0*xi_prim)*math.Sinh(2.0*eta_prim)+ beta2*math.Cos(4.0*xi_prim)*math.Sinh(4.0*eta_prim)+ beta3*math.Cos(6.0*xi_prim)*math.Sinh(6.0*eta_prim)+ beta4*math.Cos(8.0*xi_prim)*math.Sinh(8.0*eta_prim)) + FalseEasting return x, y }
func XYToLonLat(xtile, ytile int, zoom uint) Point { var lon_deg, lat_deg float64 var rt Point b := (1 << zoom) n := float64(b) lon_deg = (float64)(xtile*360)/n - 180 lat_deg = math.Atan(math.Sinh(math.Pi*(1-2*(float64)(ytile)/n))) * 180 / math.Pi rt.lon = lon_deg rt.lat = lat_deg return rt }
// returns coordinates of central point of tile by tile-hash func CentralPoint(hash int64) [2]float32 { z, x, y := HashtoZXY(hash) n := math.Pow(2, float64(z)) lon_deg := ((float64(x)+0.5)/n)*360.0 - 180.0 lat_rad := math.Atan(math.Sinh(math.Pi * (1 - (2*(float64(y)+0.5))/n))) lat_deg := lat_rad * (180.0 / math.Pi) return [2]float32{float32(lat_deg), float32(lon_deg)} }
func TestMathSinh(t *testing.T) { // This is just an interface to Go's function, so just a quick simple test ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) val := 1.12 ret := mm.math_Sinh(runtime.Number(val)) exp := math.Sinh(val) if ret.Float() != exp { t.Errorf("expected %f, got %f", exp, ret.Float()) } }
//CscH Returns the hyperbolic cosecant of an angle func CscH(number float64) (float64, error) { if number == 0 { return 0.0, errors.New("#DIV/0! - Occurred because the supplied number argument is equal to zero") } if number < -134217728 || number > 134217728 { return 0.0, errors.New("#NUM! - Occurred because the supplied number argument is less than -2^27 or is greater than 2^27") } if math.IsNaN(number) { return 0.0, errors.New("#VALUE! - Occurred because the supplied number argument is non-numeric") } return 1 / math.Sinh(number), nil }
// Func SinK computes the curvature dependent distance func SinK(omkh2, d float64) float64 { k := math.Sqrt(math.Abs(omkh2)) kd := k * d var ret float64 switch { case (omkh2 > 0) && (kd > 1.e-2): ret = math.Sinh(kd) / k case (omkh2 < 0) && (kd > 1.e-2): ret = math.Sin(kd) / k case (omkh2 >= 0) && (kd < 1.e-2): ret = d + kd*kd*d/6 case (omkh2 < 0) && (kd < 1.e-2): ret = d - kd*kd*d/6 } return ret }
// that will only work well +-10 degrees around longitude 0. var TransverseMercator = Projection{ Project: func(p *Point) { radLat := deg2rad(p.Lat()) radLng := deg2rad(p.Lng()) sincos := math.Sin(radLng) * math.Cos(radLat) p.SetX(0.5 * math.Log((1+sincos)/(1-sincos)) * EarthRadius) p.SetY(math.Atan(math.Tan(radLat)/math.Cos(radLng)) * EarthRadius) }, Inverse: func(p *Point) { x := p.X() / EarthRadius y := p.Y() / EarthRadius lng := math.Atan(math.Sinh(x) / math.Cos(y)) lat := math.Asin(math.Sin(y) / math.Cosh(x)) p.SetLng(rad2deg(lng)) p.SetLat(rad2deg(lat)) }, } // ScalarMercator converts from lng/lat float64 to x,y uint64. // This is the same as Google's world coordinates. var ScalarMercator struct { Level uint64 Project func(lng, lat float64, level ...uint64) (x, y uint64) Inverse func(x, y uint64, level ...uint64) (lng, lat float64) }
// Inverse transverse mercator projection: Projection of an cylinder onto the surface of // of an ellipsoid. Also known as reverse Gauss-Krüger projection. Input parameters: // // pt *GeoPoint: Easting(Y) and Northing(X) of map point to be projected; in meters // latO, longO: Shifted origin of latitude and longitude in decimal degrees // fe, fn: False easting and northing respectively in meters // scale: Projection scaling; Dimensionless, typically 1 or little bellow // // This algorithm uses the algorithm described by Redfearn // http://en.wikipedia.org/wiki/Transverse_Mercator:_Redfearn_series // // Taken from "OGP Publication 373-7-2 – Surveying and Positioning Guidance Note number 7, part 2 – November 2010", // pp. 48 - 51 // // More accurate, iterative but slower algorithmic implementation func InverseTransverseMercator(pt *GeoPoint, latO, longO, scale, fe, fn float64) *PolarCoord { var gc PolarCoord el := pt.El latOrad := degtorad(latO) longOrad := degtorad(longO) f := 1 - el.b/el.a esq := math.Sqrt(2.0*f - f*f) n := f / (2.0 - f) B := (el.a / (1 + n)) * (1 + n*n/4.0 + n*n*n*n/64.0) var SO float64 if latOrad != 0.0 { h1 := n/2.0 - (2.0/3.0)*n*n + (5.0/16.0)*n*n*n + (41.0/180.0)*n*n*n*n h2 := (13.0/48.0)*n*n - (3.0/5.0)*n*n*n + (557.0/1440.0)*n*n*n*n h3 := (61.0/240.0)*n*n*n - (103.0/140.0)*n*n*n*n h4 := (49561.0 / 161280.0) * n * n * n * n QO := math.Asinh(math.Tan(latOrad)) - (esq * math.Atanh(esq*math.Sin(latOrad))) bO := math.Atan(math.Sinh(QO)) xiO0 := bO // math.Asin(math.Sin(bO)) xiO1 := h1 * math.Sin(2.0*xiO0) xiO2 := h2 * math.Sin(4.0*xiO0) xiO3 := h3 * math.Sin(6.0*xiO0) xiO4 := h4 * math.Sin(8.0*xiO0) xiO := xiO0 + xiO1 + xiO2 + xiO3 + xiO4 SO = B * xiO } h1i := n/2.0 - (2.0/3.0)*n*n + (37.0/96.0)*n*n*n - (1.0/360.0)*n*n*n*n h2i := (1.0/48.0)*n*n + (1.0/15.0)*n*n*n - (437.0/1440.0)*n*n*n*n h3i := (17.0/480.0)*n*n*n - (37.0/840.0)*n*n*n*n h4i := (4397.0 / 161280.0) * n * n * n * n etai := (pt.X - fe) / (B * scale) xii := ((pt.Y - fn) + scale*SO) / (B * scale) xi1i := h1i * math.Sin(2*xii) * math.Cosh(2*etai) xi2i := h2i * math.Sin(4*xii) * math.Cosh(4*etai) xi3i := h3i * math.Sin(6*xii) * math.Cosh(6*etai) xi4i := h4i * math.Sin(8*xii) * math.Cosh(8*etai) eta1i := h1i * math.Cos(2*xii) * math.Sinh(2*etai) eta2i := h2i * math.Cos(4*xii) * math.Sinh(4*etai) eta3i := h3i * math.Cos(6*xii) * math.Sinh(6*etai) eta4i := h4i * math.Cos(8*xii) * math.Sinh(8*etai) xi0i := xii - (xi1i + xi2i + xi3i + xi4i) eta0i := etai - (eta1i + eta2i + eta3i + eta4i) bi := math.Asin(math.Sin(xi0i) / math.Cosh(eta0i)) Qi := math.Asinh(math.Tan(bi)) Qiiold := Qi + (esq * math.Atanh(esq*math.Tanh(Qi))) Qii := Qi + (esq * math.Atanh(esq*math.Tanh(Qiiold))) for math.Abs(Qiiold-Qii) > 1e-12 { Qiiold = Qii Qii = Qi + (esq * math.Atanh(esq*math.Tanh(Qiiold))) } gc.Latitude = radtodeg(math.Atan(math.Sinh(Qii))) gc.Longitude = radtodeg(longOrad + math.Asin(math.Tanh(eta0i)/math.Cos(bi))) gc.El = el return &gc }
// Direct transverse mercator projection: Projection of an ellipsoid onto the surface of // of a cylinder. Also known as Gauss-Krüger projection. Input parameters: // // gc *PolarCoord: Latitude and Longitude or point to be projected; in decimal degrees // latO, longO: Shifted origin of latitude and longitude in decimal degrees // fe, fn: False easting and northing respectively in meters // scale: Projection scaling; Dimensionless, typically 1 or little bellow // // This algorithm uses the algorithm described by Redfearn // http://en.wikipedia.org/wiki/Transverse_Mercator:_Redfearn_series // // Taken from "OGP Publication 373-7-2 – Surveying and Positioning Guidance Note number 7, part 2 – November 2010", // pp. 48 - 51 func DirectTransverseMercator(gc *PolarCoord, latO, longO, scale, fe, fn float64) *GeoPoint { var pt GeoPoint el := gc.El latOrad := degtorad(latO) longOrad := degtorad(longO) latrad := degtorad(gc.Latitude) longrad := degtorad(gc.Longitude) f := 1 - el.b/el.a esq := math.Sqrt(2.0*f - f*f) n := f / (2.0 - f) B := (el.a / (1 + n)) * (1 + n*n/4.0 + n*n*n*n/64.0) h1 := n/2.0 - (2.0/3.0)*(n*n) + (5.0/16.0)*(n*n*n) + (41.0/180.0)*(n*n*n*n) h2 := (13.0/48.0)*(n*n) - (3.0/5.0)*(n*n*n) + (557.0/1440.0)*(n*n*n*n) h3 := (61.0/240.0)*(n*n*n) - (103.0/140.0)*(n*n*n*n) h4 := (49561.0 / 161280.0) * (n * n * n * n) var SO float64 if latOrad != 0.0 { QO := math.Asinh(math.Tan(latOrad)) - (esq * math.Atanh(esq*math.Sin(latOrad))) bO := math.Atan(math.Sinh(QO)) xiO0 := bO // math.Asin(math.Sin(bO)) xiO1 := h1 * math.Sin(2.0*xiO0) xiO2 := h2 * math.Sin(4.0*xiO0) xiO3 := h3 * math.Sin(6.0*xiO0) xiO4 := h4 * math.Sin(8.0*xiO0) xiO := xiO0 + xiO1 + xiO2 + xiO3 + xiO4 SO = B * xiO } Q := math.Asinh(math.Tan(latrad)) - (esq * math.Atanh(esq*math.Sin(latrad))) b := math.Atan(math.Sinh(Q)) eta0 := math.Atanh(math.Cos(b) * math.Sin(longrad-longOrad)) xi0 := math.Asin(math.Sin(b) * math.Cosh(eta0)) xi1 := h1 * math.Sin(2*xi0) * math.Cosh(2*eta0) xi2 := h2 * math.Sin(4*xi0) * math.Cosh(4*eta0) xi3 := h3 * math.Sin(6*xi0) * math.Cosh(6*eta0) xi4 := h4 * math.Sin(8*xi0) * math.Cosh(8*eta0) xi := xi0 + xi1 + xi2 + xi3 + xi4 eta1 := h1 * math.Cos(2*xi0) * math.Sinh(2*eta0) eta2 := h2 * math.Cos(4*xi0) * math.Sinh(4*eta0) eta3 := h3 * math.Cos(6*xi0) * math.Sinh(6*eta0) eta4 := h4 * math.Cos(8*xi0) * math.Sinh(8*eta0) eta := eta0 + eta1 + eta2 + eta3 + eta4 pt.X = fe + scale*B*eta pt.Y = fn + scale*(B*xi-SO) pt.El = el return &pt }
func mathSinh(L *LState) int { L.Push(LNumber(math.Sinh(float64(L.CheckNumber(1))))) return 1 }
//Y2Lat transforms y into a latitude in degree at a given level. func Y2Lat(level int, y int) float64 { var yosm = y latitudeRad := math.Atan(math.Sinh(math.Pi * (1. - 2.*float64(yosm)/float64(n(level))))) return -(latitudeRad * 180.0 / math.Pi) }
func LongRunningFuncion() { for i := 0; i < LONG; i++ { math.Sinh(float64(i)) } }
func TilePos2LL(x float64, y float64) (lat float64, lon float64) { var tilesOnOneEdge float64 = math.Pow(2.0, zoomLevel) lon = (x * (360 / (tilesOnOneEdge))) - 180 lat = rad2deg * (math.Atan(math.Sinh((1 - y*(2/(tilesOnOneEdge))) * math.Pi))) return }
//define the integral of the kernel func K(t float64) float64 { return math.Sinh(t) }
func FunctionVal(f Function, x float64) float64 { // switch f { case Floor: i, _ := math.Modf(x) return i case Fract: _, f := math.Modf(x) return f case Chs: return -x case Rec: if x == 0 { // TODO return math.NaN() } return 1 / x case Sqr: return x * x case Sqrt: return math.Sqrt(x) case Exp: return math.Exp(x) case Exp10: return math.Exp(x * math.Ln10) case Exp2: return math.Exp(x * math.Ln2) case Log: return math.Log(x) case Lg: return math.Log10(x) case Ld: return math.Log2(x) case Sin: return math.Sin(x) case Cos: return math.Cos(x) case Tan: return math.Tan(x) case Cot: return 1 / math.Tan(x) case Arcsin: return math.Asin(x) case Arccos: return math.Acos(x) case Arctan: return math.Atan(x) case Arccot: return math.Atan(x) case Sinh: return math.Sinh(x) case Cosh: return (math.Exp(x) + math.Exp(-x)) / 2 case Tanh: return math.Tanh(x) case Coth: return (math.Exp(x) + math.Exp(-x)) / (math.Exp(x) - math.Exp(-x)) case Arsinh: return math.Asinh(x) case Arcosh: return math.Log(x + math.Sqrt(x*x-1)) case Artanh: return math.Atanh(x) case Arcoth: return math.Log((x+1)/(x-1)) / 2 case Gamma: return math.Gamma(x) } return math.NaN() }
// float32 version of math.Sinhf func Sinh(x float32) float32 { return float32(math.Sinh(float64(x))) }
func (m *MathMod) math_Sinh(args ...runtime.Val) runtime.Val { runtime.ExpectAtLeastNArgs(1, args) return runtime.Number(math.Sinh(args[0].Float())) }
// Chebyshev biquad (2-poles) recursive coefficients // Adapted from The Scientist and Engineer's Guide to Digital Signal Processing, Steven W. Smith // poleIndex = [0, poleCount) // percentRipple in the pass band can range from 0 for a butterworth to about 0.29. Something like 0.005 is a good trade-off. func chebyshevBiquad(freq, percentRipple float64, poleIndex, poleCount int, highpass bool) (stageAs, stageBs []float64) { // We start off by designing a low-pass filter with unity cut-off frequency // Location of pole on unit circle, real and imaginary parts // The maximally flat butterworth filter positions the poles so that // they form a semi-circle on the left side of the s-plane (sigma < 0) // The half offset keeps the poles evenly spaced and off of the sigma=0 line // s-plane s = sigma + i * omega = poleR + i * poleI poleI, poleR := math.Sincos((float64(poleIndex) + 0.5) * math.Pi / float64(poleCount)) poleR = -poleR // The chebyshev filter uses an ellipse to move all of the poles closer to the sigma=0 line // This causes pass-band ripple and sharpens the drop off // Warp coordinates from being on a circle to an ellipse if percentRipple != 0.0 { e := math.Sqrt(1/((1-percentRipple)*(1-percentRipple)) - 1) v := math.Asinh(1/e) / float64(poleCount) k := math.Acosh(1/e) / float64(poleCount) k = math.Cosh(k) poleR = poleR * math.Sinh(v) / k poleI = poleI * math.Cosh(v) / k } // bilinear s-domain to z-domain transformation t := 2 * math.Tan(0.5) w := 2 * math.Pi * freq m := poleR*poleR + poleI*poleI d := 4 - 4*poleR*t + m*t*t x0 := t * t / d x1 := 2 * t * t / d x2 := t * t / d y1 := (8 - 2*m*t*t) / d y2 := (-4 - 4*poleR*t - m*t*t) / d // We now have the coefficients of a low-pass filter with a cutoff frequency of 1 (2 times the nyquist)... // We must now apply our desired frequency and convert to a high-pass filter if necessary // as with the bilinear tranform, these are the results of a substitution in the transfer function... var k float64 if highpass { k = -math.Cos(w/2+0.5) / math.Cos(w/2-0.5) } else { k = math.Sin(0.5-w/2) / math.Sin(0.5+w/2) } d = 1 + (y1*k - y2*k*k) a0 := (x0 - x1*k + x2*k*k) / d a1 := (-2*x0*k + x1 + (x1*k*k - 2*x2*k)) / d a2 := (x0*k*k - x1*k + x2) / d b1 := (2*k + y1 + y1*k*k - 2*y2*k) / d b2 := (-k*k - y1*k + y2) / d if highpass { a1, b1 = -a1, -b1 } // we now have the desired coefficients of our low/high pass filter with the desired cutoff frequency // however, the gain has not been normalized, if that is desired... stageAs = []float64{a0, a1, a2} stageBs = []float64{0, b1, b2} return }
//func (*Tile) Num2deg(t *Tile) (lat float64, lon float64) { func Num2deg(t *Tile) (lat float64, lon float64) { n := math.Exp2(float64(t.Z)) lat = 180.0 / math.Pi * math.Atan(math.Sinh(math.Pi*(1-2*float64(t.Y)/n))) lon = float64(t.X)/n*360.0 - 180.0 return lat, lon }