Example #1
0
File: s2.go Project: hailocab/geo
/**
 * Returns the true centroid of the spherical triangle ABC multiplied by the
 * signed area of spherical triangle ABC. The reasons for multiplying by the
 * signed area are (1) this is the quantity that needs to be summed to compute
 * the centroid of a union or difference of triangles, and (2) it's actually
 * easier to calculate this way.
 */
func TrueCentroid(a, b, c Point) Point {
	// I couldn't find any references for computing the true centroid of a
	// spherical triangle... I have a truly marvellous demonstration of this
	// formula which this margin is too narrow to contain :)

	// assert (isUnitLength(a) && isUnitLength(b) && isUnitLength(c));
	sina := b.Cross(c.Vector).Norm()
	sinb := c.Cross(a.Vector).Norm()
	sinc := a.Cross(b.Vector).Norm()
	var ra float64 = 1
	var rb float64 = 1
	var rc float64 = 1
	if sina != 0 {
		ra = math.Asin(sina) / sina
	}
	if sinb != 0 {
		rb = math.Asin(sinb) / sinb
	}
	if sinc != 0 {
		rc = math.Asin(sinc) / sinc
	}

	// Now compute a point M such that M.X = rX * det(ABC) / 2 for X in A,B,C.
	x := PointFromCoordsRaw(a.X, b.X, c.X)
	y := PointFromCoordsRaw(a.Y, b.Y, c.Y)
	z := PointFromCoordsRaw(a.Z, b.Z, c.Z)
	r := PointFromCoordsRaw(ra, rb, rc)
	return PointFromCoordsRaw(
		0.5*y.Cross(z.Vector).Dot(r.Vector),
		0.5*z.Cross(x.Vector).Dot(r.Vector),
		0.5*x.Cross(y.Vector).Dot(r.Vector),
	)
}
Example #2
0
// This is named GetDistance() in the C++ API.
func (x Point) DistanceToEdgeWithNormal(a, b, a_cross_b Point) s1.Angle {
	// There are three cases. If X is located in the spherical wedge
	// defined by A, B, and the axis A x B, then the closest point is on
	// the segment AB. Otherwise the closest point is either A or B; the
	// dividing line between these two cases is the great circle passing
	// through (A x B) and the midpoint of AB.
	if CCW(a_cross_b, a, x) && CCW(x, b, a_cross_b) {
		// The closest point to X lies on the segment AB. We compute
		// the distance to the corresponding great circle. The result
		// is accurate for small distances but not necessarily for
		// large distances (approaching Pi/2).
		//
		// TODO: sanity check a != b
		sin_dist := math.Abs(x.Dot(a_cross_b.Vector)) / a_cross_b.Norm()
		return s1.Angle(math.Asin(math.Min(1.0, sin_dist)))
	}
	// Otherwise, the closest point is either A or B. The cheapest method is
	// just to compute the minimum of the two linear (as opposed to spherical)
	// distances and convert the result to an angle. Again, this method is
	// accurate for small but not large distances (approaching Pi).
	xa := x.Sub(a.Vector).Norm2()
	xb := x.Sub(b.Vector).Norm2()
	linear_dist2 := math.Min(xa, xb)
	return s1.Angle(2 * math.Asin(math.Min(1.0, 0.5*math.Sqrt(linear_dist2))))
}
Example #3
0
/**
 * A slightly more efficient version of getDistance() where the cross product
 * of the two endpoints has been precomputed. The cross product does not need
 * to be normalized, but should be computed using S2.robustCrossProd() for the
 * most accurate results.
 */
func getDistanceWithCross(x, a, b, aCrossB Point) s1.Angle {
	if !x.IsUnit() || !a.IsUnit() || !b.IsUnit() {
		panic("x, a and b need to be unit length")
	}

	// There are three cases. If X is located in the spherical wedge defined by
	// A, B, and the axis A x B, then the closest point is on the segment AB.
	// Otherwise the closest point is either A or B; the dividing line between
	// these two cases is the great circle passing through (A x B) and the
	// midpoint of AB.

	if simpleCCW(aCrossB, a, x) && simpleCCW(x, b, aCrossB) {
		// The closest point to X lies on the segment AB. We compute the distance
		// to the corresponding great circle. The result is accurate for small
		// distances but not necessarily for large distances (approaching Pi/2).

		sinDist := math.Abs(x.Dot(aCrossB.Vector)) / aCrossB.Norm()
		return s1.Angle(math.Asin(math.Min(1.0, sinDist)))
	}

	// Otherwise, the closest point is either A or B. The cheapest method is
	// just to compute the minimum of the two linear (as opposed to spherical)
	// distances and convert the result to an angle. Again, this method is
	// accurate for small but not large distances (approaching Pi).

	linearDist2 := math.Min(x.Sub(a.Vector).Norm2(), x.Sub(b.Vector).Norm2())
	return s1.Angle(2 * math.Asin(math.Min(1.0, 0.5*math.Sqrt(linearDist2))))
}
Example #4
0
func getBoundingBox(rf Radiusfence) (x1, x2, y1, y2 float64) {
	var lat1, lat2, lon1, lon2 float64

	//Convert long,lat to rad
	latRad := rf.p.Latitude * DegToRad
	longRad := rf.p.Longitude * DegToRad

	northMost := math.Asin(math.Sin(latRad)*math.Cos(rf.r/Radius) + math.Cos(latRad)*math.Sin(rf.r/Radius)*math.Cos(North))
	southMost := math.Asin(math.Sin(latRad)*math.Cos(rf.r/Radius) + math.Cos(latRad)*math.Sin(rf.r/Radius)*math.Cos(South))
	eastMost := longRad + math.Atan2(math.Sin(East)*math.Sin(rf.r/Radius)*math.Cos(latRad), math.Cos(rf.r/Radius)-math.Sin(latRad)*math.Sin(latRad))
	westMost := longRad + math.Atan2(math.Sin(West)*math.Sin(rf.r/Radius)*math.Cos(latRad), math.Cos(rf.r/Radius)-math.Sin(latRad)*math.Sin(latRad))

	if northMost > southMost {
		lat1 = southMost
		lat2 = northMost
	} else {
		lat1 = northMost
		lat2 = southMost
	}

	if eastMost > westMost {
		lon1 = westMost
		lon2 = eastMost
	} else {
		lon1 = eastMost
		lon2 = westMost
	}

	return lat1, lat2, lon1, lon2
}
Example #5
0
// Grena3 calculates topocentric solar position following algorithm number 3
// described in Grena, 'Five new algorithms for the computation of sun position
// from 2010 to 2110', Solar Energy 86 (2012) pp. 1323-1337.
func Grena3(date time.Time,
	latitudeDegrees float64, longitudeDegrees float64,
	deltaTSeconds float64,
	pressureHPa float64, temperatureCelsius float64) (azimuthDegrees, zenithDegrees float64) {
	t := calcT(date)

	tE := t + 1.1574e-5*deltaTSeconds
	omegaAtE := 0.0172019715 * tE

	lambda := -1.388803 + 1.720279216e-2*tE + 3.3366e-2*math.Sin(omegaAtE-0.06172) +
		3.53e-4*math.Sin(2.0*omegaAtE-0.1163)

	epsilon := 4.089567e-1 - 6.19e-9*tE

	sLambda := math.Sin(lambda)
	cLambda := math.Cos(lambda)
	sEpsilon := math.Sin(epsilon)
	cEpsilon := math.Sqrt(1.0 - sEpsilon*sEpsilon)

	alpha := math.Atan2(sLambda*cEpsilon, cLambda)
	if alpha < 0 {
		alpha = alpha + 2*math.Pi
	}

	delta := math.Asin(sLambda * sEpsilon)

	h := 1.7528311 + 6.300388099*t + toRad(longitudeDegrees) - alpha
	h = math.Mod((h+math.Pi), (2*math.Pi)) - math.Pi
	if h < -math.Pi {
		h = h + 2*math.Pi
	}

	sPhi := math.Sin(toRad(latitudeDegrees))
	cPhi := math.Sqrt((1 - sPhi*sPhi))
	sDelta := math.Sin(delta)
	cDelta := math.Sqrt(1 - sDelta*sDelta)
	sH := math.Sin(h)
	cH := math.Cos(h)

	sEpsilon0 := sPhi*sDelta + cPhi*cDelta*cH
	eP := math.Asin(sEpsilon0) - 4.26e-5*math.Sqrt(1.0-sEpsilon0*sEpsilon0)
	gamma := math.Atan2(sH, cH*sPhi-sDelta*cPhi/cDelta)

	deltaRe := 0.0
	if eP > 0 && pressureHPa > 0.0 && pressureHPa < 3000.0 &&
		temperatureCelsius > -273 && temperatureCelsius < 273 {
		deltaRe = (0.08422 * (pressureHPa / 1000)) / ((273.0 + temperatureCelsius) *
			math.Tan(eP+0.003138/(eP+0.08919)))
	}

	z := math.Pi/2 - eP - deltaRe

	azimuthDegrees = convertAzimuth(gamma)
	zenithDegrees = toDeg(z)
	return
}
Example #6
0
func main() {
	fmt.Println("cos(pi/2):", math.Cos(math.Pi/2))
	fmt.Println("cos(0):", math.Cos(0))
	fmt.Println("sen(pi/2):", math.Sin(math.Pi/2))
	fmt.Println("sen(0):", math.Sin(0))
	fmt.Println("arccos(1):", math.Acos(1))
	fmt.Println("arccos(0):", math.Acos(0))
	fmt.Println("arcsen(1):", math.Asin(1))
	fmt.Println("arcsen(0):", math.Asin(0))
}
Example #7
0
// Given a point X and an edge AB, check that the distance from X to AB is
// "distance_radians" and the closest point on AB is "expected_closest"
func TestDistanceToEdge(t *testing.T) {
	tests := []struct {
		x                Point
		a                Point
		b                Point
		distance_radians float64
		expected_closest Point
	}{
		{pc(1, 0, 0), pc(1, 0, 0), pc(0, 1, 0), 0, pc(1, 0, 0)},
		{pc(0, 1, 0), pc(1, 0, 0), pc(0, 1, 0), 0, pc(0, 1, 0)},
		{pc(1, 3, 0), pc(1, 0, 0), pc(0, 1, 0), 0, pc(1, 3, 0)},
		{pc(0, 0, 1), pc(1, 0, 0), pc(0, 1, 0), math.Pi / 2, pc(1, 0, 0)},
		{pc(0, 0, -1), pc(1, 0, 0), pc(0, 1, 0), math.Pi / 2, pc(1, 0, 0)},
		{pc(-1, -1, 0), pc(1, 0, 0), pc(0, 1, 0), 0.75 * math.Pi, pc(0, 0, 0)},

		{pc(0, 1, 0), pc(1, 0, 0), pc(1, 1, 0), math.Pi / 4, pc(1, 1, 0)},
		{pc(0, -1, 0), pc(1, 0, 0), pc(1, 1, 0), math.Pi / 2, pc(1, 0, 0)},

		{pc(0, -1, 0), pc(1, 0, 0), pc(-1, 1, 0), math.Pi / 2, pc(1, 0, 0)},
		{pc(-1, -1, 0), pc(1, 0, 0), pc(-1, 1, 0), math.Pi / 2, pc(-1, 1, 0)},

		{pc(1, 1, 1), pc(1, 0, 0), pc(0, 1, 0), math.Asin(math.Sqrt(1. / 3)), pc(1, 1, 0)},
		{pc(1, 1, -1), pc(1, 0, 0), pc(0, 1, 0), math.Asin(math.Sqrt(1. / 3)), pc(1, 1, 0)},

		{pc(-1, 0, 0), pc(1, 1, 0), pc(1, 1, 0), 0.75 * math.Pi, pc(1, 1, 0)},
		{pc(0, 0, -1), pc(1, 1, 0), pc(1, 1, 0), math.Pi / 2, pc(1, 1, 0)},
		{pc(-1, 0, 0), pc(1, 0, 0), pc(1, 0, 0), math.Pi, pc(1, 0, 0)},
	}
	for _, test := range tests {
		test.x = Point{test.x.Normalize()}
		test.a = Point{test.a.Normalize()}
		test.b = Point{test.b.Normalize()}
		test.expected_closest = Point{test.expected_closest.Normalize()}

		got := test.x.DistanceToEdge(test.a, test.b).Radians()
		if math.Abs(got-test.distance_radians) > 1e-14 {
			t.Errorf("%v.DistanceToEdge(%v, %v) = %v, want %v",
				test.x, test.a, test.b, got, test.distance_radians)
		}

		closest := test.x.ClosestPoint(test.a, test.b)
		if test.expected_closest == pc(0, 0, 0) {
			if closest != test.a && closest != test.b {
				t.Errorf("NOT: %v == %v || %v == %v", closest, test.a, closest, test.b)
			}
		} else {
			if !closest.ApproxEqual(test.expected_closest) {
				t.Errorf("%v != %v", closest, test.expected_closest)
			}
		}
	}
}
Example #8
0
func Test_Mw02(tst *testing.T) {

	//verbose()
	chk.PrintTitle("Mw02")

	prms := []string{"φ", "Mfix"}
	vals := []float64{32, 0}
	var o NcteM
	o.Init(prms, vals)

	if SAVE_FIG {
		// rosette
		full, ref := false, true
		r := 1.1 * SQ2 * o.M(1) / 3.0
		PlotRosette(r, full, ref, true, 7)

		// NcteM
		npts := 201
		X := make([]float64, npts)
		Y := make([]float64, npts)
		W := utl.LinSpace(-1, 1, npts)
		for i, w := range W {
			θ := math.Asin(w) / 3.0
			r := SQ2 * o.M(w) / 3.0
			X[i] = -r * math.Sin(math.Pi/6.0-θ)
			Y[i] = r * math.Cos(math.Pi/6.0-θ)
			//plt.Text(X[i], Y[i], io.Sf("$\\\\theta=%.2f$", θ*180.0/math.Pi), "size=8, ha='center', color='red'")
			//plt.Text(X[i], Y[i], io.Sf("$w=%.2f$", w), "size=8, ha='center', color='red'")
		}
		plt.Plot(X, Y, "'b-'")

		// MC
		g := func(θ float64) float64 {
			return SQ2 * o.Sinφ / (SQ3*math.Cos(θ) - o.Sinφ*math.Sin(θ))
		}
		io.Pforan("M( 1) = %v\n", SQ2*o.M(1)/3.0)
		io.Pforan("g(30) = %v\n", g(math.Pi/6.0))
		for i, w := range W {
			θ := math.Asin(w) / 3.0
			r := g(θ)
			X[i] = -r * math.Sin(math.Pi/6.0-θ)
			Y[i] = r * math.Cos(math.Pi/6.0-θ)
		}
		plt.Plot(X, Y, "'k-'")

		// save
		plt.Equal()
		plt.SaveD("/tmp/gosl", "mw02.eps")
	}
}
func main() {
	fmt.Printf("sin(%9.6f deg) = %f\n", d, math.Sin(d*math.Pi/180))
	fmt.Printf("sin(%9.6f rad) = %f\n", r, math.Sin(r))
	fmt.Printf("cos(%9.6f deg) = %f\n", d, math.Cos(d*math.Pi/180))
	fmt.Printf("cos(%9.6f rad) = %f\n", r, math.Cos(r))
	fmt.Printf("tan(%9.6f deg) = %f\n", d, math.Tan(d*math.Pi/180))
	fmt.Printf("tan(%9.6f rad) = %f\n", r, math.Tan(r))
	fmt.Printf("asin(%f) = %9.6f deg\n", s, math.Asin(s)*180/math.Pi)
	fmt.Printf("asin(%f) = %9.6f rad\n", s, math.Asin(s))
	fmt.Printf("acos(%f) = %9.6f deg\n", c, math.Acos(c)*180/math.Pi)
	fmt.Printf("acos(%f) = %9.6f rad\n", c, math.Acos(c))
	fmt.Printf("atan(%f) = %9.6f deg\n", t, math.Atan(t)*180/math.Pi)
	fmt.Printf("atan(%f) = %9.6f rad\n", t, math.Atan(t))
}
Example #10
0
// Dist computes the spherical distance between two points on the unit sphere S².
func (p Geo) Dist(q Geo) float64 {
	u1 := p.c()
	v1 := q.c()
	dot := u1.dot(v1)
	if dot > 0 {
		t := u1.sub(v1)
		return 2 * math.Asin(0.5*t.abs())
	}
	if dot < 0 {
		t := u1.add(v1)
		return math.Pi - 2*math.Asin(0.5*t.abs())
	}
	return math.Pi / 2
}
Example #11
0
func geoBoundAroundPoint(center *Point, distance float64) *Bound {
	radDist := distance / EarthRadius
	radLat := deg2rad(center.Lat())
	radLon := deg2rad(center.Lng())
	minLat := radLat - radDist
	maxLat := radLat + radDist

	var minLon, maxLon float64
	if minLat > minLatitude && maxLat < maxLatitude {
		deltaLon := math.Asin(math.Sin(radDist) / math.Cos(radLat))
		minLon = radLon - deltaLon
		if minLon < minLongitude {
			minLon += 2 * math.Pi
		}
		maxLon = radLon + deltaLon
		if maxLon > maxLongitude {
			maxLon -= 2 * math.Pi
		}
	} else {
		minLat = math.Max(minLat, minLatitude)
		maxLat = math.Min(maxLat, maxLatitude)
		minLon = minLongitude
		maxLon = maxLongitude
	}
	return &Bound{
		sw: &Point{rad2deg(minLon), rad2deg(minLat)},
		ne: &Point{rad2deg(maxLon), rad2deg(maxLat)},
	}
}
Example #12
0
// u.sep(v) returns ∠(u,v) (angular separation).
func (u vec) sep(v vec) float64 {
	u1, v1 := u.hat(), v.hat()
	dot := u1.dot(v1)
	if dot > 0 {
		t := u1.sub(v1)
		return 2 * math.Asin(0.5*t.abs())
	}
	if dot < 0 {
		t := u1.add(v1)
		return math.Pi - 2*math.Asin(0.5*t.abs())
	}
	if u1.maxabs() == 0 || v1.maxabs() == 0 {
		return 0
	}
	return math.Pi / 2
}
Example #13
0
// ElasticInOut Acceleration until halfway, then deceleration
func ElasticInOut(t, b, c, d float64) float64 {
	if t > d {
		return c
	}

	s := math.SqrtPi
	p := d * (0.3 * 1.5)
	a := c

	if t == 0 {
		return b
	}

	t /= d / 2

	if t == 2 {
		return b + c
	}

	if a < math.Abs(c) {
		s = p / 4
	} else {
		s = p / DoublePi * math.Asin(c/a)
	}

	t--

	if t < 0 {
		return -0.5*(a*math.Pow(2, 10*t)*math.Sin((t*d-s)*DoublePi/p)) + b
	}

	return a*math.Pow(2, -10*t)*math.Sin((t*d-s)*DoublePi/p)*0.5 + c + b
}
Example #14
0
// ElasticOut Decelerating to zero velocity
func ElasticOut(t, b, c, d float64) float64 {
	if t > d {
		return c
	}

	s := math.SqrtPi
	p := d * 0.3
	a := c

	if t == 0 {
		return b
	}

	t /= d

	if t == 1 {
		return b + c
	}

	if a < math.Abs(c) {
		s = p / 4
	} else {
		s = p / DoublePi * math.Asin(c/a)
	}

	return a*math.Pow(2, -10*t)*math.Sin((t*d-s)*DoublePi/p) + c + b
}
Example #15
0
File: cone.go Project: fogleman/ln
func (c *OutlineCone) Paths() Paths {
	center := Vector{0, 0, 0}
	hyp := center.Sub(c.Eye).Length()
	opp := c.Radius
	theta := math.Asin(opp / hyp)
	adj := opp / math.Tan(theta)
	d := math.Cos(theta) * adj
	// r := math.Sin(theta) * adj
	w := center.Sub(c.Eye).Normalize()
	u := w.Cross(c.Up).Normalize()
	c0 := c.Eye.Add(w.MulScalar(d))
	a0 := c0.Add(u.MulScalar(c.Radius * 1.01))
	b0 := c0.Add(u.MulScalar(-c.Radius * 1.01))

	var p0 Path
	for a := 0; a < 360; a++ {
		x := c.Radius * math.Cos(Radians(float64(a)))
		y := c.Radius * math.Sin(Radians(float64(a)))
		p0 = append(p0, Vector{x, y, 0})
	}
	return Paths{
		p0,
		{{a0.X, a0.Y, 0}, {0, 0, c.Height}},
		{{b0.X, b0.Y, 0}, {0, 0, c.Height}},
	}
}
Example #16
0
// AstrometricJ2000 is a utility function for computing astrometric coordinates.
//
// It is used internally and only exported so that it can be used from
// multiple packages.  It is not otherwise expected to be used.
//
// Argument f is a function that returns J2000 equatorial rectangular
// coodinates of a body.
//
// Results are J2000 right ascention, declination, and elongation.
func AstrometricJ2000(f func(float64) (x, y, z float64), jde float64, e *pp.V87Planet) (α, δ, ψ float64) {
	X, Y, Z := solarxyz.PositionJ2000(e, jde)
	x, y, z := f(jde)
	// (33.10) p. 229
	ξ := X + x
	η := Y + y
	ζ := Z + z
	Δ := math.Sqrt(ξ*ξ + η*η + ζ*ζ)
	{
		τ := base.LightTime(Δ)
		x, y, z = f(jde - τ)
		ξ = X + x
		η = Y + y
		ζ = Z + z
		Δ = math.Sqrt(ξ*ξ + η*η + ζ*ζ)
	}
	α = math.Atan2(η, ξ)
	if α < 0 {
		α += 2 * math.Pi
	}
	δ = math.Asin(ζ / Δ)
	R0 := math.Sqrt(X*X + Y*Y + Z*Z)
	ψ = math.Acos((ξ*X + η*Y + ζ*Z) / R0 / Δ)
	return
}
Example #17
0
// Returns a Point populated with the lat and lng coordinates of transposing the origin point the distance (in meters) supplied by the compass bearing (in degrees) supplied.
// Original Implementation from: http://www.movable-type.co.uk/scripts/latlong.html
func (p *Point) PointAtDistanceAndBearing(dist float64, bearing float64) *Point {

	dr := dist / EARTH_RADIUS

	bearing = (bearing * (math.Pi / 180.0))

	lat1 := (p.lat * (math.Pi / 180.0))
	lng1 := (p.lng * (math.Pi / 180.0))

	lat2_part1 := math.Sin(lat1) * math.Cos(dr)
	lat2_part2 := math.Cos(lat1) * math.Sin(dr) * math.Cos(bearing)

	lat2 := math.Asin(lat2_part1 + lat2_part2)

	lng2_part1 := math.Sin(bearing) * math.Sin(dr) * math.Cos(lat1)
	lng2_part2 := math.Cos(dr) - (math.Sin(lat1) * math.Sin(lat2))

	lng2 := lng1 + math.Atan2(lng2_part1, lng2_part2)
	lng2 = math.Mod((lng2+3*math.Pi), (2*math.Pi)) - math.Pi

	lat2 = lat2 * (180.0 / math.Pi)
	lng2 = lng2 * (180.0 / math.Pi)

	return &Point{lat: lat2, lng: lng2}
}
Example #18
0
// EqToEcl converts equatorial coordinates to ecliptic coordinates.
func (ecl *Ecliptic) EqToEcl(eq *Equatorial, ε *Obliquity) *Ecliptic {
	sα, cα := eq.RA.Sincos()
	sδ, cδ := eq.Dec.Sincos()
	ecl.Lon = unit.Angle(math.Atan2(sα*ε.C+(sδ/cδ)*ε.S, cα)) // (13.1) p. 93
	ecl.Lat = unit.Angle(math.Asin(sδ*ε.C - cδ*ε.S*sα))      // (13.2) p. 93
	return ecl
}
Example #19
0
// EclToEq converts ecliptic coordinates to equatorial coordinates.
//
//	λ: ecliptic longitude coordinate to transform
//	β: ecliptic latitude coordinate to transform
//	sε: sine of obliquity of the ecliptic
//	cε: cosine of obliquity of the ecliptic
//
// Results:
//	α: right ascension
//	δ: declination
func EclToEq(λ, β unit.Angle, sε, cε float64) (α unit.RA, δ unit.Angle) {
	sλ, cλ := λ.Sincos()
	sβ, cβ := β.Sincos()
	α = unit.RAFromRad(math.Atan2(sλ*cε-(sβ/cβ)*sε, cλ)) // (13.3) p. 93
	δ = unit.Angle(math.Asin(sβ*cε + cβ*sε*sλ))          // (13.4) p. 93
	return
}
Example #20
0
// EqToEcl converts equatorial coordinates to ecliptic coordinates.
//
//	α: right ascension coordinate to transform, in radians
//	δ: declination coordinate to transform, in radians
//	sε: sine of obliquity of the ecliptic
//	cε: cosine of obliquity of the ecliptic
//
// Results:
//
//	λ: ecliptic longitude in radians
//	β: ecliptic latitude in radians
func EqToEcl(α, δ, sε, cε float64) (λ, β float64) {
	sα, cα := math.Sincos(α)
	sδ, cδ := math.Sincos(δ)
	λ = math.Atan2(sα*cε+(sδ/cδ)*sε, cα) // (13.1) p. 93
	β = math.Asin(sδ*cε - cδ*sε*sα)      // (13.2) p. 93
	return
}
Example #21
0
File: filter.go Project: jlep/steps
func (f *Filter) madgwick(timestamp int64, values []float32) {
	C.madgwick_update_array(
		f.orientation, C.float(sampleFreq), C.float(beta),
		(*_Ctype_float)(&values[0]))

	// quaternion slice
	o := f.orientation
	q := []float32{
		float32(o.q0),
		float32(o.q1),
		float32(o.q2),
		float32(o.q3),
	}
	q1 := float64(o.q0)
	q2 := float64(o.q1)
	q3 := float64(o.q2)
	q4 := float64(o.q3)

	// euler angles in radians (madgwick 2010)
	z := math.Atan2(2*q2*q3-2*q1*q4, 2*q1*q1+2*q2*q2-1) * rad2deg
	y := -math.Asin(2*q2*q4+2*q1*q3) * rad2deg
	x := math.Atan2(2*q3*q4-2*q1*q2, 2*q1*q1+2*q4*q4-1) * rad2deg
	e := []float64{z, y, x}

	if false {
		log.Println("qtn", timestamp, q)
		log.Println("eul", timestamp, e)
	}

	broadcast(timestamp, "qtn", q)
}
Example #22
0
// Generate a spiral
func GenerateSpiral(setup Spiral, plotCoords chan<- Coordinate) {
	defer close(plotCoords)

	// MM that will be moved in a single step, used to calc what the new position along spiral will be after one time slice
	moveDist := 4.0 * Settings.MaxSpeed_MM_S * TimeSlice_US / 1000000.0
	theta := 0.0

	for radius := setup.RadiusBegin; radius >= setup.RadiusEnd; {

		plotCoords <- Coordinate{X: radius * math.Cos(theta), Y: radius * math.Sin(theta)}

		// use right triangle to approximate arc distance along spiral, ignores radiusDelta for this calculation
		thetaDelta := 2.0 * math.Asin(moveDist/(2.0*radius))
		theta += thetaDelta
		if theta >= 2.0*math.Pi {
			theta -= 2.0 * math.Pi
		}

		radiusDelta := setup.RadiusDeltaPerRev * thetaDelta / (2.0 * math.Pi)
		radius -= radiusDelta

		//fmt.Println("Radius", radius, "Radius delta", radiusDelta, "Theta", theta, "Theta delta", thetaDelta)
	}
	plotCoords <- Coordinate{X: 0, Y: 0}
}
Example #23
0
// Generate a circle that slides along a given axis
func GenerateSlidingCircle(setup SlidingCircle, plotCoords chan<- Coordinate) {
	defer close(plotCoords)

	// MM that will be moved in a single step, used to calc what the new position along spiral will be after one time slice
	moveDist := 4.0 * Settings.MaxSpeed_MM_S * TimeSlice_US / 1000000.0
	displacement := Coordinate{X: setup.CircleDisplacement, Y: 0}

	theta := 0.0
	thetaDelta := 2.8 * math.Asin(moveDist/(2.0*setup.Radius))
	origin := Coordinate{X: 0.0, Y: 0.0}

	for drawnCircles := 0; drawnCircles < setup.NumbCircles; {

		circlePos := Coordinate{X: setup.Radius * math.Cos(theta), Y: setup.Radius * math.Sin(theta)}
		origin = origin.Add(displacement.Scaled(thetaDelta / (2.0 * math.Pi)))

		plotCoords <- circlePos.Add(origin)

		theta += thetaDelta
		if theta > 2.0*math.Pi {
			theta -= 2.0 * math.Pi
			drawnCircles++
		}
	}
	plotCoords <- Coordinate{X: 0, Y: 0}
}
Example #24
0
func TestTofloat(t *testing.T) {
	oldval := cfg.UseRadians
	cfg.UseRadians = true
	type test struct {
		in  string
		out float64
	}
	var tests []test = []test{
		{"2.5+2.5", 2.5 + 2.5},
		{"2.5*2.5", 2.5 * 2.5},
		{"3/2", 3. / 2.},
		{"2^10", math.Pow(2, 10)},
		{"sqrt(2)", math.Sqrt(2)},
		{"sin(2)", math.Sin(2)},
		{"cos(2)", math.Cos(2)},
		{"tan(2)", math.Tan(2)},
		{"arcsin(0.3)", math.Asin(0.3)},
		{"arccos(0.3)", math.Acos(0.3)},
		{"arctan(0.3)", math.Atan(0.3)},
		{"ln(2)", math.Log(2)},
		{"log(2)", math.Log10(2)},
	}
	for _, k := range tests {
		result := TextToCas(k.in).Tofloat()
		if result != k.out {
			t.Errorf("Tofloat: In:%v Out:%v Result:%v",
				k.in, k.out, result)
		}
	}
	cfg.UseRadians = oldval
}
Example #25
0
// EqToEcl converts equatorial coordinates to ecliptic coordinates.
//
//	α: right ascension coordinate to transform
//	δ: declination coordinate to transform
//	sε: sine of obliquity of the ecliptic
//	cε: cosine of obliquity of the ecliptic
//
// Results:
//
//	λ: ecliptic longitude
//	β: ecliptic latitude
func EqToEcl(α unit.RA, δ unit.Angle, sε, cε float64) (λ, β unit.Angle) {
	sα, cα := α.Sincos()
	sδ, cδ := δ.Sincos()
	λ = unit.Angle(math.Atan2(sα*cε+(sδ/cδ)*sε, cα)) // (13.1) p. 93
	β = unit.Angle(math.Asin(sδ*cε - cδ*sε*sα))      // (13.2) p. 93
	return
}
Example #26
0
// AngleError returns both an angle as in the function Angle, and an error
// as in the function Error.
//
// The algorithm is by B. Pessens.
func AngleError(r1, d1, r2, d2, r3, d3 float64) (ψ, ω float64) {
	sr1, cr1 := math.Sincos(r1)
	sd1, cd1 := math.Sincos(d1)
	sr2, cr2 := math.Sincos(r2)
	sd2, cd2 := math.Sincos(d2)
	sr3, cr3 := math.Sincos(r3)
	sd3, cd3 := math.Sincos(d3)
	a1 := cd1 * cr1
	a2 := cd2 * cr2
	a3 := cd3 * cr3
	b1 := cd1 * sr1
	b2 := cd2 * sr2
	b3 := cd3 * sr3
	c1 := sd1
	c2 := sd2
	c3 := sd3
	l1 := b1*c2 - b2*c1
	l2 := b2*c3 - b3*c2
	l3 := b1*c3 - b3*c1
	m1 := c1*a2 - c2*a1
	m2 := c2*a3 - c3*a2
	m3 := c1*a3 - c3*a1
	n1 := a1*b2 - a2*b1
	n2 := a2*b3 - a3*b2
	n3 := a1*b3 - a3*b1
	ψ = math.Acos((l1*l2 + m1*m2 + n1*n2) /
		(math.Sqrt(l1*l1+m1*m1+n1*n1) * math.Sqrt(l2*l2+m2*m2+n2*n2)))
	ω = math.Asin((a2*l3 + b2*m3 + c2*n3) /
		(math.Sqrt(a2*a2+b2*b2+c2*c2) * math.Sqrt(l3*l3+m3*m3+n3*n3)))
	return
}
Example #27
0
func TestRectBounderMaxLatitudeSimple(t *testing.T) {
	cubeLat := math.Asin(1 / math.Sqrt(3)) // 35.26 degrees
	cubeLatRect := Rect{r1.IntervalFromPoint(-cubeLat).AddPoint(cubeLat),
		s1.IntervalFromEndpoints(-math.Pi/4, math.Pi/4)}

	tests := []struct {
		a, b Point
		want Rect
	}{
		// Check cases where the min/max latitude is attained at a vertex.
		{
			a:    PointFromCoords(1, 1, 1),
			b:    PointFromCoords(1, -1, -1),
			want: cubeLatRect,
		},
		{
			a:    PointFromCoords(1, -1, 1),
			b:    PointFromCoords(1, 1, -1),
			want: cubeLatRect,
		},
	}

	for _, test := range tests {
		if got := rectBoundForPoints(test.a, test.b); !rectsApproxEqual(got, test.want, rectErrorLat, rectErrorLng) {
			t.Errorf("RectBounder for points (%v, %v) near max lat failed: got %v, want %v", test.a, test.b, got, test.want)
		}
	}
}
Example #28
0
// EclToEq converts ecliptic coordinates to equatorial coordinates.
func (eq *Equatorial) EclToEq(ecl *Ecliptic, ε *Obliquity) *Equatorial {
	sβ, cβ := ecl.Lat.Sincos()
	sλ, cλ := ecl.Lon.Sincos()
	eq.RA = unit.RAFromRad(math.Atan2(sλ*ε.C-(sβ/cβ)*ε.S, cλ)) // (13.3) p. 93
	eq.Dec = unit.Angle(math.Asin(sβ*ε.C + cβ*ε.S*sλ))         // (13.4) p. 93
	return eq
}
Example #29
0
// Sep returns the separation angle in radians between x and y.
// If any of x or y is zero-vector, it returns zero.
func (x Vec) Sep(y Vec) float64 {
	xhat, yhat := x.Hat(), y.Hat()
	dot := xhat.Dot(yhat)
	if dot > 0.0 {
		tmp := xhat.Sub(yhat)
		return 2.0 * math.Asin(bracket(tmp.Abs()/2.0, 0.0, 1.0))
	}
	if dot < 0.0 {
		tmp := xhat.Add(yhat)
		return math.Pi - 2.0*math.Asin(bracket(tmp.Abs()/2.0, 0.0, 1.0))
	}
	if xhat.Zero() || yhat.Zero() {
		return 0.0
	}
	return math.Pi / 2.0
}
Example #30
0
func EaseInOutElastic(start, end, value float32) float32 {
	end -= start

	var d float32 = 1.0
	var p float32 = d * 0.3
	var s float32 = 0.0
	var a float32 = 0.0

	if value == 0 {
		return start
	}
	value /= d
	if value == 1 {
		return start + end
	}
	if a == 0 || a < float32(math.Abs(float64(end))) {
		a = end
		s = p / 4
	} else {
		s = p / (2 * float32(math.Pi)) * float32(math.Asin(float64(end/a)))
	}
	if value < 1 {
		return -0.5*(a*float32(math.Pow(2, 10*(float64(value)-1)))*float32(math.Sin(float64((value*d-s)*(2*math.Pi)/p)))) + start
	}
	return a*float32(math.Pow(2, -10*(float64(value)-1)))*float32(math.Sin(float64((value*d-s)*(2*math.Pi)/p)))*0.5 + end + start
}