How can I move between 2 gps points at a set speed? - go

I'm trying to create a function that will let me give 2 arguments, a new location and a speed to travel at (in meters / second)
It looks like this:
func (l *Location) Move(newLoc *Location, speed float64) {
R := 6371.0 // Kilometers
lat1 := l.Latitude * math.Pi / 180
lat2 := l.Longitude * math.Pi / 180
diffLat := (newLoc.Latitude - l.Latitude) * math.Pi / 180
diffLon := (newLoc.Longitude - l.Longitude) * math.Pi / 180
a := math.Sin(diffLat/2)*math.Sin(diffLat/2) +
math.Cos(lat1)*math.Cos(lat2)*math.Sin(diffLon/2)*math.Sin(diffLon/2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
distanceToMove := R * c // Distance to travel in a straight line, in Kilometers
}
The only thing I'm having trouble with is thinking of the formula to make the latitude, start at its current position, and end up at its new position over a set amount of time.
So say the person changed the latitude from 56.65 to 58.12 and I told it to travel at 1.3m/s how can I accomplish this. Thanks.

If I understand your question, your goal is to compute all the intermediate points between two location, starting from one location and going to the second one using a specified speed.
If I'm correct, the following is how I would get a first solution. If anyone can improve this, I'd appreciate.
On the proj4 documentation, you can find a lot of information on how to compute distance between two points.
Starting from points A to reach B with a given speed (m/s), just means to compute each seconds a point A' that is at a distance m from A on the line AB.
In a more algorithmic way (based on Vincenty's formula):
func (l *Location) Move(newLoc *Location, speed float64) Location {
azimuthA, azimuthB, d := inverseVincenty(l, newLoc)
// Use the direct vincenty's formula.
// Here transform speed to get the correct value
// without transformation, since speed is in m/s,
// the resulting point will be at speed(m) distance from l.
res := directVincenty(l, speed, azimuthA)
// Now res shall contain your new point.
return res
}
func main() {
// init A and B and speed values.
C := A // to conserve A position.
t := time.Tick(1* time.Second)
for stop := false; !stop; {
select {
case <- t:
C = C.Move(B, speed)
case // here a break condition:
stop = true
}
}
}
I think thats a start, any comment is appreciate on this answer.

Related

Drawing Circles with two radius in Golang

I've looked around but can't find anything useful for drawing circles in golang.
I'd like to draw a draw with 2 given (inner and outer) radius and color all pixels in between.
One possible method would be to iterate through each pixel and color it until the ring has been created. Although, that seems really inefficient.
Any help on this would be greatly appreciated! :)
Please read this related question: Draw a rectangle in Golang?
To sum it up: the standard Go library does not provide primitive drawing or painting capabilities.
So yes, either you have to use a 3rd party library to draw a circle (such as github.com/llgcode/draw2d), or you have to do it yourself. Don't worry, it's not hard at all.
Drawing a single circle
First pick a circle drawing algorithm which is simple and efficient. I recommend the Midpoint circle algorithm.
You will find the algorithm on the linked Wikipedia page. Note: you do not have to understand it if you want to use it.
But we do need to implement the algorithm in Go. Which is rather simple:
func drawCircle(img draw.Image, x0, y0, r int, c color.Color) {
x, y, dx, dy := r-1, 0, 1, 1
err := dx - (r * 2)
for x > y {
img.Set(x0+x, y0+y, c)
img.Set(x0+y, y0+x, c)
img.Set(x0-y, y0+x, c)
img.Set(x0-x, y0+y, c)
img.Set(x0-x, y0-y, c)
img.Set(x0-y, y0-x, c)
img.Set(x0+y, y0-x, c)
img.Set(x0+x, y0-y, c)
if err <= 0 {
y++
err += dy
dy += 2
}
if err > 0 {
x--
dx += 2
err += dx - (r * 2)
}
}
}
That's all it takes. Just pass a draw.Image you want to draw on, and the parameters of the circle you want to draw (center point, radius and the color).
Let's see it in action. Let's create an image, draw a circle on it, and save the image to a file. This is all it takes:
img := image.NewRGBA(image.Rect(0, 0, 100, 100))
drawCircle(img, 40, 40, 30, color.RGBA{255, 0, 0, 255})
buf := &bytes.Buffer{}
if err := png.Encode(buf, img); err != nil {
panic(err)
}
if err := ioutil.WriteFile("circle.png", buf.Bytes(), 0666); err != nil {
panic(err)
}
Note: you could also encode the image directly to an os.File and "skip" the in-memory buffer. This is just for demonstration, and to verify our implementation works.
Drawing a ring (filling space between 2 circles)
This one isn't that trivial if you want to implement it yourself, but using a 3rd party lib here could really come handy.
Although most of them don't contain ring-painting support, they do have circle drawing support, and you can set the width of the line used to draw the circle.
So, set the line width to the value that is the difference of the 2 radius of your circles. And draw a circle with a new radius that is the arithmetic center of the 2 original radius.
Here's the algorithm (this is not runnable code):
// Helper functions abstracting the library you choose:
func setColor(c color.Color) {}
func setLineWidth(width float64) {}
func drawCircle(r, x, y float64) {}
// fillRing draws a ring, where r1 and r2 are 2 concentric circles,
// the boundaries of the ring, (x, y) being the center point.
func fillRing(r1, r2, x, y float64, c color.color) {
// Set drawing color:
setColor(c)
// Set line width:
width := r2 - r1
if width < 0 {
width = -width
}
setLineWidth(width)
// And finally draw a circle which will be a ring:
r := (r2 + r1) / 2
drawCircle(r, x, y)
}

How to get the geometry of a specific pixel in an image.RGBA or any other type?

I wish there was something like image.Point struct but instead it was pixel based, if that makes sense.
Say I have loaded and decoded an image.RGBA with size(bounds) of 300x300. How can I get the exact coordinate of the middle of the image in image.Point or fixed.Point26_6?
image.RGBA is a concrete implementation of the general image.Image interface.
It has an Image.Bounds() method:
// Bounds returns the domain for which At can return non-zero color.
// The bounds do not necessarily contain the point (0, 0).
Bounds() Rectangle
Important to note that the top-left corner of the image might not be at the zero point (0, 0) (although generally it is).
So the geometry of the image is handed to you as a value of image.Rectangle:
type Rectangle struct {
Min, Max Point
}
To handle the general case (where top-left might not be (0, 0)), you have to account both the Min and Max points to to calculate the center point:
cx := (r.Min.X + r.Max.X)/2
cy := (r.Min.Y + r.Max.Y)/2
Another solution is to use Rectangle.Dx() and Rectangle.Dy():
cx := r.Min.X + r.Dx()/2
cy := r.Min.Y + r.Dy()/2
And there is an image.Point struct type. To get the center point as a value of image.Point:
cp := image.Point{(r.Min.X + r.Max.X) / 2, (r.Min.Y + r.Max.Y) / 2}
Or:
cp := image.Point{r.Min.X + r.Dx()/2, r.Min.Y + r.Dy()/2}
See this example:
r := image.Rect(0, 0, 300, 100)
fmt.Println(r)
cp := image.Point{(r.Min.X + r.Max.X) / 2, (r.Min.Y + r.Max.Y) / 2}
fmt.Println(cp)
cp = image.Point{r.Min.X + r.Dx()/2, r.Min.Y + r.Dy()/2}
fmt.Println(cp)
Output (try it on the Go Playground):
(0,0)-(300,100)
(150,50)
(150,50)

Calculation error with area of shapes in GoLang [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I have this piece of code that is suppose to print the area of individual shapes and then print the total area (sum of the individual areas), but there seem to be a problem somewhere in the addition when I use interfaces and variadic functions. The program is written in GoLang and below is the code;
/* Program that interacts with shapes */
/* Calculating the area of basic shapes e.g Circle, Rectangle */
package main
import ("fmt"; "math")
/* Adding the interface support */
type Shape interface {
area() float64
}
/* Struct for Circle */
type Circle struct {
x, y, r float64
}
/* Struct for Rectangle */
type Rectangle struct {
x1, y1, x2, y2 float64
}
/* Calculation of distance */
func distance(x1, y1, x2, y2 float64) float64 {
a := x2 - x1
b := y2 - y1
return math.Sqrt(a*a + b*b)
}
/* Area of the rectangle */
func (r *Rectangle) area() float64 {
l := distance(r.x1, r.y1, r.x1, r.y2)
w := distance(r.x1, r.y1, r.x2, r.y1)
return l * w
}
/* Area of the circle */
func (c *Circle) area() float64 {
return math.Pi * c.r * c.r
}
/* Interface is really useful when finding the total area i.e. the sum of
all the areas of each of the shapes
*/
func totalArea(shapes ...Shape) float64 {
var area float64
for _, s := range shapes {
area += s.area()
}
return area
}
/* This is the main function */
func main() {
c := Circle{0, 0, 5}
r := Rectangle{0, 0, 10, 10}
fmt.Println("Area of the rectangle is: ", r.area())
fmt.Println("Area of the circle is: ", c.area())
fmt.Println("Sum of the areas: ", totalArea(&c, &r))
}
I ran this code on my Mac OS X El Capitan, core i5, 8GB RAM and below is my output
Area of the rectangle is: 100
Area of the circle is: 78.53981633974483
Sum of the areas: 178.53981633974485
From the results as you can see, there is a small issue, the expected sum of the areas should be: 178.53981633974483 but I get 178.53981633974485 which is 0.00000000000002 different or deviation from the expected results, please can anyone help me out with why it is like this?
I am not quite sure if its a problem with the math library in GoLang since it just has to do a normal addition of the two areas? Or is it that GoLang recalculates the area before passing it to totalArea() then does some approximation I don't quite get it? Or is it my computer (one can never tell)?
Thanks for your help in advance.
This is the behaviour of floating point arithmetic and its precision rather than anything specific to golang.
Theres a few good resources regarding float precision.
here is a snippet that illustrates your issue more simply:
https://play.golang.org/p/Jhlnt0L13T
If you do need arbitrary precision then you may want to look at:
https://golang.org/pkg/math/big/

Coordinates of every point on a circle's circumference

First, please note, that this question is not a duplicate of these: 1st , 2nd , and 3rd.
I am using delphi and openCV, but I am looking for an algorithm, a solution regardless of the language.
For the purpose of a precise image analysis, I need to check for changes in pixel intensity in circular areas. So I read pixel values on a circumference of continuously growing circle. To be able to do that, I of course need to know coordinates of the pixels.
The best solution I found is y:= Round(centerY + radius * sin(angle)), x:= Round(centerX + radius * cos(angle)), while because counting with only 360 degrees is hardly enough, when the radius of the circle is larger, than circa 60px, the angle is being counted like this angle:= angle + (360 / (2 * 3.14 * currentRadius)) -> I sweep through every value from 0 to 360, while the value is being incremented by a fraction of 360/circumference of the circle in pixels. But this approach is not very precise. The larger the circle, the smaller the fraction of the angle needs to be and the precission suffers from the inaccuracy of Pi, plus the rounding.
If I use the mentioned method, and try to draw the counted pixels with this code:
centerX:= 1700;
centerY:= 1200;
maxRadius:= 500;
for currentRadius:= 80 to maxRadius do
begin
angle:= 0;
while angle < 360 do
begin
xI:= Round(centerX + currentRadius * cos(angle));
yI:= Round(centerY + currentRadius * sin(angle));
angle:= angle + (360 / (2 * 3.14 * currentRadius));
//this is openCV function, to test the code, you can use anything, that will draw a dot...
cvLine(image,cvPoint(xI,yI),cvPoint(xI,yI),CV_RGB(0, 255, 0));
end;
end;
the result is this:
It is not bad, but taking into account, that rougly a third of all pixels in the circular area are black, you realize, that a lot of pixels has been "skipped". Plus looking closely on the edge of the last circle, there is clearly visible, that some dots are off the actual circumference - another result of the inaccuracy...
I could possibly use a formula (x - xorig)^2 + (y - yorig)^2 = r^2 to check every possible pixel in a rectangular area around the center, slightly bigger, than a diameter of the circle, if it does, or does't fall onto the cirle's circumference. But that would be very slow to repeat it all the time, as the circle grows.
Is there something, that could be done better? Could anyone help me to improve this? I don't insist on anything from my solution at all, and will accept any other solution, as long as it gives the desired results => let me read values of all (or the vast majority - 95%+) pixels on a circumference of a circle with given center and radius. The faster, the better...
1) Build a list of pixels of the smallest radius circumference. It is enough to
keep the first octant (range 0..Pi/4 in the 1st quadrant of coordinate system) of circle, and get symmetric points with reflections.
You can use, for example, Bresenham circle algorithm or just circle equation.
2) For the next iteration walk through all coordinates in the list (use right one, if there are two points with the same Y value) and check whether right neighbor (or two neighbors!) lies inside the next radius. For the last point check also top, right-top neighbor (at Pi/4 diagonal).
Insert good neighbors (one or two) into the next coordinate list.
Example for Y=5.
R=8 X=5,6 //note that (5,5) point is not inside r=7 circle
R=9 X=7
R=10 X=8
R=11 X=9
R=12 X=10
R=13 X=11,12 //!
R=14 X=13
With this approach you will use all the pixels in maximal radius circle without gaps, and checking process for list generation is rather fast.
Edit:
Code implements slightly another approach, it uses lower line pixel limit to built upper line.
It generates circles in given range, paints them to psychedelic colors. All math is in integers, no floats, no trigonometric functions! Pixels are used only for demonstration purposes.
procedure TForm1.Button16Click(Sender: TObject);
procedure FillCircles(CX, CY, RMin, RMax: Integer);
//control painting, slow due to Pixels using
procedure PaintPixels(XX, YY, rad: Integer);
var
Color: TColor;
r, g, B: Byte;
begin
g := (rad mod 16) * 16;
r := (rad mod 7) * 42;
B := (rad mod 11) * 25;
Color := RGB(r, g, B);
// Memo1.Lines.Add(Format('%d %d %d', [rad, XX, YY]));
Canvas.Pixels[CX + XX, CY + YY] := Color;
Canvas.Pixels[CX - YY, CY + XX] := Color;
Canvas.Pixels[CX - XX, CY - YY] := Color;
Canvas.Pixels[CX + YY, CY - XX] := Color;
if XX <> YY then begin
Canvas.Pixels[CX + YY, CY + XX] := Color;
Canvas.Pixels[CX - XX, CY + YY] := Color;
Canvas.Pixels[CX - YY, CY - XX] := Color;
Canvas.Pixels[CX + XX, CY - YY] := Color;
end;
end;
var
Pts: array of array [0 .. 1] of Integer;
iR, iY, SqD, SqrLast, SqrCurr, MX, LX, cnt: Integer;
begin
SetLength(Pts, RMax);
for iR := RMin to RMax do begin
SqrLast := Sqr(iR - 1) + 1;
SqrCurr := Sqr(iR);
LX := iR; // the most left X to check
for iY := 0 to RMax do begin
cnt := 0;
Pts[iY, 1] := 0; // no second point at this Y-line
for MX := LX to LX + 1 do begin
SqD := MX * MX + iY * iY;
if InRange(SqD, SqrLast, SqrCurr) then begin
Pts[iY, cnt] := MX;
Inc(cnt);
end;
end;
PaintPixels(Pts[iY, 0], iY, iR);
if cnt = 2 then
PaintPixels(Pts[iY, 1], iY, iR);
LX := Pts[iY, 0] - 1; // update left limit
if LX < iY then // angle Pi/4 is reached
Break;
end;
end;
// here Pts contains all point coordinates for current iR radius
//if list is not needed, remove Pts, just use PaintPixels-like output
end;
begin
FillCircles(100, 100, 10, 100);
//enlarge your first quadrant to check for missed points
StretchBlt(Canvas.Handle, 0, 200, 800, 800, Canvas.Handle, 100, 100, 100,
100, SRCCOPY);
end;
If you want to make your code faster, don't call trigonometric functions inside the inner loop, increment sin(angle) and cos(angle) using
sin(n*step)=sin((n-1)*step)*cos(step)+sin(step)*cos((n-1)*step)
cos(n*step)=cos((n-1)*step)*cos(step)-sin(step)*sin((n-1)*step)
that is
...
for currentRadius:= 80 to maxRadius do
begin
sinangle:= 0;
cosangle:= 1;
step:= 1 / currentRadius; // ?
sinstep:= sin(step);
cosstep:= cos(step);
while {? } do
begin
xI:= Round(centerX + currentRadius * cosangle);
yI:= Round(centerY + currentRadius * sinangle);
newsin:= sinangle*cosstep + sinstep*cosangle;
newcos:= cosangle*cosstep - sinstep*sinangle;
sinangle:= newsin;
cosangle:= newcos;
...
end;
end;
First of all: you want all the points on a circle circumference. If you use any (good) algorithm, also some built-in circle function, you get indeed all the points, since the circumference is connected.
What your picture shows, there are holes between neighbour circles, say r=100 and r=101. This is so for circumference drawing functions.
Now if you want that the pixels in your pixel set to cover all the pixels with incrementing radii, you can simply use following approach:
Build a set of filled circle pixels, say r = 101
Build a set of filled circle pixel with r = 100
Exclude set 2 from set 1
Filled circle algorithm is generally more efficient and simpler than connected circumference so you'll not loose much performance.
So you get a circumference which is slightly thicker than 1 px, but this set will surely cover the surface with growing radii without any holes. But it can also happen that the set built in such a way has overlapping pixels with previous set (r-1), so you'd know it better if you test it.
PS: Also it is not clear how any trigonometric functions appear in your code. I don't know any effective circle algorithm which use anything other than square root.
Why don't you simply use more digits for Pi and stop rounding to improve accuracy?
Further I suggest you use subpixel coordinates to get more accurate intensity values if you can afford the interpolation.
It's also very uncommon to use degrees in calculations. I highly recommend using radians. Not sure which functions you use here but Delphi's cos and sin seem to expect radians!

how convert easting northing coordinates to latitude longitude?

I need to convert Eastings and Northings OSGB36 coordinates into latitude and longitude coordinates using Go. Therefore I'm wondering if there is any package that do just this. Writing one from scratch doesn't seem trivial. I'm running the code in a sandboxed VM so the code must be pure Go.
Input:
Northing - Distance in metres north of National Grid origin.
Easting - Distance in metres east of National Grid origin.
Example:
348356,862582
Output (Decimal degrees -DDD):
Latitude
Longitude
Example:
41.40338, 2.17403
You could try the go-proj-4 library which is a wrapper to the comprehensive PROJ.4 - Cartographic Projections Library.
I haven't tried either but it looks like it should do the job.
Alternatively you could port the code on this page
The code below is very naively ported from the javascript (© 2005-2014 Chris Veness) at the link Nick Craig-Wood provided. I've only ported the OsGridToLatLong() function, but the others shouldn't be too difficult. Also, this treats all values as float64. You may want to treat northing and easting as int.
package main
import (
"fmt"
"math"
)
const (
radToDeg = 180 / math.Pi
degToRad = math.Pi / 180
a = 6377563.396
b = 6356256.909 // Airy 1830 major & minor semi-axes
f0 = 0.9996012717 // NatGrid scale factor on central meridian
lat0 = 49 * degToRad
lon0 = -2 * degToRad // NatGrid true origin
n0 = -100000.0
e0 = 400000.0 // northing & easting of true origin, metres
e2 = 1 - (b*b)/(a*a) // eccentricity squared
n = (a - b) / (a + b)
n2 = n * n
n3 = n * n * n
)
func OsGridToLatLong(northing, easting float64) (float64, float64) {
lat := lat0
m := 0.0
for northing-n0-m >= 1e-5 { // until < 0.01mm
lat = (northing-n0-m)/(a*f0) + lat
ma := (1 + n + (5/4)*n2 + (5/4)*n3) * (lat - lat0)
mb := (3*n + 3*n*n + (21/8)*n3) * math.Sin(lat-lat0) * math.Cos(lat+lat0)
mc := ((15/8)*n2 + (15/8)*n3) * math.Sin(2*(lat-lat0)) * math.Cos(2*(lat+lat0))
md := (35 / 24) * n3 * math.Sin(3*(lat-lat0)) * math.Cos(3*(lat+lat0))
m = b * f0 * (ma - mb + mc - md) // meridional arc
}
cosLat := math.Cos(lat)
sinLat := math.Sin(lat)
nu := a * f0 / math.Sqrt(1-e2*sinLat*sinLat) // transverse radius of curvature
rho := a * f0 * (1 - e2) / math.Pow(1-e2*sinLat*sinLat, 1.5) // meridional radius of curvature
eta2 := nu/rho - 1
tanLat := math.Tan(lat)
tan2lat := tanLat * tanLat
tan4lat := tan2lat * tan2lat
tan6lat := tan4lat * tan2lat
secLat := 1 / cosLat
nu3 := nu * nu * nu
nu5 := nu3 * nu * nu
nu7 := nu5 * nu * nu
vii := tanLat / (2 * rho * nu)
viii := tanLat / (24 * rho * nu3) * (5 + 3*tan2lat + eta2 - 9*tan2lat*eta2)
ix := tanLat / (720 * rho * nu5) * (61 + 90*tan2lat + 45*tan4lat)
x := secLat / nu
xi := secLat / (6 * nu3) * (nu/rho + 2*tan2lat)
xii := secLat / (120 * nu5) * (5 + 28*tan2lat + 24*tan4lat)
xiia := secLat / (5040 * nu7) * (61 + 662*tan2lat + 1320*tan4lat + 720*tan6lat)
de := easting - e0
de2 := de * de
de3 := de2 * de
de4 := de2 * de2
de5 := de3 * de2
de6 := de4 * de2
de7 := de5 * de2
lat = lat - vii*de2 + viii*de4 - ix*de6
lon := lon0 + x*de - xi*de3 + xii*de5 - xiia*de7
return lat * radToDeg, lon * radToDeg
}
func main() {
lat, lon := OsGridToLatLong(348356.0, 862582.0)
fmt.Printf("Latitude: %fN\nLongitude: %fE\n", lat, lon)
}
Produces:
Latitude: 52.833026N
Longitude: 4.871525E
These are OSGB-36 coordinates.
From Chris Veness's original post:
"The Ordnance Survey uses ‘OSGB-36’, based on an elliptical model of the earth’s surface which is a good fit to the UK. GPS systems generally use the world-wide ‘WGS-84’, based on an elliptical model which is a best approximation to the entire earth. At Greenwich, these differ by about 126m (they coincide somewhere in the Atlantic ocean; there’s more on Wikipedia)"
I have no idea if this is where the OSGB-36 coords for Northing: 348356, Easting: 862582 are meant to be, but the code above, and the javascript code (JSFiddle), put it somewhere in the northern Netherlands. (Although the coords shown on the map are WGS-84, and not OSGB-36. See converting between OSGB-36 & WGS-84 for more details.)
This code hasn't been properly tested (It produces the same output as the original javascript code, but that's no guarantee of correctness), and may have hideous bugs, but it should point you in the right direction (no pun intended).
Playground
Hi I had the same problem.
I was porting our codebase from python. We used this library - (UTM python version) by Tobias Bieniek. It is public on github.
I didn't find something good and lightweight. I just ported this library on golang - UTM golang library. It's pure go which contain only two methods. You can find badge-link to godoc in repository. I use it in a production.
For speed use:
go get github.com/im7mortal/UTM

Resources