Calculation error with area of shapes in GoLang [duplicate] - go

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/

Related

Banding in radial gradient

I generate a radial gradient with this code:
func GenerateGradient(center ds.Coord, radius int, dMethod string) *[]GradientRecord {
var r []GradientRecord
for y := center.Y - radius; y <= center.Y+radius; y++ {
for x := center.X - radius; x <= center.X+radius; x++ {
d := float64(DCalc(center, ds.Coord{X: x, Y: y}, dMethod))
p := ds.Coord{X: x, Y: y}
var v float64
v = Lerp(float64(radius), d, 1)
record := GradientRecord{Point: p.Wrap("t"), Value: v}
r = append(r, record)
}
}
return &r
}
DCalc is using the Euclidean distance.
Producing this:
As you can see, it's smooth. But I want the gradient to finish where the radious, so in the Lerp line I change it to:
v = 1 - Lerp(float64(radius), d/float64(radius), 1)
Producing this:
As you can see there is a cross shaped banding. Wonder if there is a way to remove it? I actually do not need to generate an image, just a smooth gradient transition array for other stuff. I made a picture to expain better the issue..
Thanks!
func Lerp(v0, v1, t float64) float64 {
return (1-t)*v0 + t*v1
}

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)
}

Calculating and storing pixelated ellipse

I was wondering if it is possible to create a function (arbitrary of language) that has as input a width and height.
This function would then calculate the biggest ellipse that would fit inside of the dimensions that it is given, and store this in a matrix such as these two examples;
In the left example, the width is 14 and height is 27, where the white part is the ellipse.
In the right example, the width is 38 and height is 21, where, once again, the white part is the ellipse.
Of course, the black and white parts can be seen as true/false values if they are part of the ellipse or not.
Yes it is possible. The process is called ellipse rasterization. Here few methods to do so:
let our image has xs,ys resolution so center (x0,y0) and semiaxises a,b are:
x0=xs/2
y0=y2/2
a =x0-1
b =y0-1
using ellipse equation
so 2 nested for loops + if condition deciding if you are inside or outside ellipse.
for (y=0;y<ys;y++)
for (x=0;x<xs;x++)
if (((x-x0)*(x-x0)/(a*a))+((y-y0)*(y-y0)/(b*b))<=1.0) pixel[y][x]=color_inside;
else pixel[y][x]=color_outside;
You can optimize this quite a lot by pre-computing the parts of the equations only if thy change so some are computed just once others on each x iteration and the rest on each y iteration. Also is better to multiply instead of dividing.
using parametric ellipse equation
x(t) = x0 + a*cos(t)
y(t) = y0 + b*sin(t)
t = <0,2.0*M_PI> // for whole ellipse
so one for loop creating quadrant coordinates and filling lines inside and outside for the 3 mirrors of the quadrant using only horizontal or only vertical lines. However this approach need a buffer to store the circumference points of one quadrant.
Using Bresenham ellipse algorithm
Using any Circle algorithm and stretch to ellipse
so simply use square area of size of the lesser resolution from xs,ys render circle and than stretch back to xs,ys. If you do not stretch during rasterization than you might create artifacts. In such case is better to use the bigger resolution and stretch down but that is slower of coarse.
Drawing an ellipse and storing it in a matrix can be accomplished with two different methods: either Rasterization (the recommended way) or pixel-by-pixel rendering. According to #Spektre's comment, I wonder if both methods are called "rasterization" since they both render the ellipse to raster image. Anyway, I'll explain how to use both methods in C++ to draw an ellipse and store it in your matrix.
Note: Here I'll assume that the origin of your matrix matrix[0][0] refers to the upper-left corner of the image. So points on the matrix are described by x- and y-coordinate pairs, such that x-coordinates increase to the right; y-coordinates increase from top to bottom.
Pixel-by-pixel ellipse rendering
With this method, you loop over all the pixels in your matrix to determine whether each pixel is inside or outside of the ellipse. If the pixel is inside, you make it white, otherwise, you make it black.
In the following example code, the isPointOnEllipse function determines the status of a point relative to the ellipse. It takes the coordinates of the point, coordinates of the center of the ellipse, and the lengths of semi-major and semi-minor axes as parameters. It then returns either one of the values PS_OUTSIDE, PS_ONPERIM, or PS_INSIDE, which indicate that the point lies outside of the ellipse, the point lies exactly on the ellipse's perimeter, or the point lies inside of the ellipse, respectively.
Obviously, if the point status is PS_ONPERIM, then the point is also part of the ellipse and must be made white; because the ellipse's outline must be colored in addition to its inner area.
You must call ellipseInMatrixPBP function to draw an ellipse, passing it a pointer to your matrix, and the width and height of your matrix. This function loops through every pixel in your matrix, and then calls isPointOnEllipse for every pixel to see if it is inside or outside of the ellipse. Finally, it modifies the pixel accordingly.
#include <math.h>
// Indicates the point lies outside of the ellipse.
#define PS_OUTSIDE (0)
// Indicates the point lies exactly on the perimeter of the ellipse.
#define PS_ONPERIM (1)
// Indicates the point lies inside of the ellipse.
#define PS_INSIDE (2)
short isPointOnEllipse(int cx, int cy, int rx, int ry, int x, int y)
{
double m = (x - cx) * ((double) ry) / ((double) rx);
double n = y - cy;
double h = sqrt(m * m + n * n);
if (h == ry)
return PS_ONPERIM;
else if (h < ry)
return PS_INSIDE;
else
return PS_OUTSIDE;
}
void ellipseInMatrixPBP(bool **matrix, int width, int height)
{
// So the ellipse shall be stretched to the whole matrix
// with a one-pixel margin.
int cx = width / 2;
int cy = height / 2;
int rx = cx - 1;
int ry = cy - 1;
int x, y;
short pointStatus;
// Loop through all the pixels in the matrix.
for (x = 0;x < width;x++)
{
for (y = 0;y < height;y++)
{
pointStatus = isPointOnEllipse(cx, cy, rx, ry, x, y);
// If the current pixel is outside of the ellipse,
// make it black (false).
// Else if the pixel is inside of the ellipse or on its perimeter,
// make it white (true).
if (pointStatus == PS_OUTSIDE)
matrix[x][y] = false;
else
matrix[x][y] = true;
}
}
}
Ellipse rasterization
If the pixel-by-pixel approach to rendering is too slow, then use the rasterization method. Here you determine which pixels in the matrix the ellipse affects, and then you modify those pixels (e.g. you turn them white). Unlike pixel-by-pixel rendering, rasterization does not have to pass through the pixels that are outside of the ellipse shape, which is why this approach is so faster.
To rasterize the ellipse, it is recommended that you use the so-called Mid-point Ellipse algorithm, which is an extended form of Bresenham's circle algorithm.
However, I've discovered an ellipse-drawing algorithm which is probably sophisticated enough (except for its performance) to compete with Bresenham's! So I'll post the function that you want - written in C++.
The following code defines a function named ellipseInMatrix that draws an ellipse with a one-pixel stroke, but does not fill that ellipse. You need to pass this function a pointer to the matrix that you have already allocated and initialized to false values, plus the dimensions of the matrix as integers. Note that ellipseInMatrix internally calls the rasterizeEllipse function which performs the main rasterizing operation. Whenever this function finds a point of the ellipse, it sets the corresponding pixel in the matrix to true, which causes the pixel to turn white.
#define pi (2 * acos(0.0))
#define coord_nil (-1)
struct point
{
int x;
int y;
};
double getEllipsePerimeter(int rx, int ry)
{
return pi * sqrt(2 * (rx * rx + ry * ry));
}
void getPointOnEllipse(int cx, int cy, int rx, int ry, double d, struct point *pp)
{
double theta = d * sqrt(2.0 / (rx * rx + ry * ry));
// double theta = 2 * pi * d / getEllipsePerimeter(rx, ry);
pp->x = (int) floor(cx + cos(theta) * rx);
pp->y = (int) floor(cy - sin(theta) * ry);
}
void rasterizeEllipse(bool **matrix, int cx, int cy, int rx, int ry)
{
struct point currentPoint, midPoint;
struct point previousPoint = {coord_nil, coord_nil};
double perimeter = floor(getEllipsePerimeter(rx, ry));
double i;
// Loop over the perimeter of the ellipse to determine all points on the ellipse path.
for (i = 0.0;i < perimeter;i++)
{
// Find the current point and determine its coordinates.
getPointOnEllipse(cx, cy, rx, ry, i, &currentPoint);
// So color the current point.
matrix[currentPoint.x][currentPoint.y] = true;
// So check if the previous point exists. Please note that if the current
// point is the first point (i = 0), then there will be no previous point.
if (previousPoint.x != coord_nil)
{
// Now check if there is a gap between the current point and the previous
// point. We know it's not OK to have gaps along the ellipse path!
if (!((currentPoint.x - 1 <= previousPoint.x) && (previousPoint.x <= currentPoint.x + 1) &&
(currentPoint.y - 1 <= previousPoint.y) && (previousPoint.y <= currentPoint.y + 1)))
{
// Find the missing point by defining its offset as a fraction
// between the current point offset and the previous point offset.
getPointOnEllipse(cx, cy, rx, ry, i - 0.5, &midPoint);
matrix[midPoint.x][midPoint.y] = true;
}
}
previousPoint.x = currentPoint.x;
previousPoint.y = currentPoint.y;
}
}
void ellipseInMatrix(bool **matrix, int width, int height)
{
// So the ellipse shall be stretched to the whole matrix
// with a one-pixel margin.
int cx = width / 2;
int cy = height / 2;
int rx = cx - 1;
int ry = cy - 1;
// Call the general-purpose ellipse rasterizing function.
rasterizeEllipse(matrix, cx, cy, rx, ry);
}
If you need to fill the ellipse with white pixels like the examples that you provided, you can use the following code instead to rasterize a filled ellipse. Call the filledEllipseInMatrix function with a similar syntax to the previous function.
#define pi (2 * acos(0.0))
#define coord_nil (-1)
struct point
{
int x;
int y;
};
double getEllipsePerimeter(int rx, int ry)
{
return pi * sqrt(2 * (rx * rx + ry * ry));
}
void getPointOnEllipse(int cx, int cy, int rx, int ry, double d, struct point *pp)
{
double theta = d * sqrt(2.0 / (rx * rx + ry * ry));
// double theta = 2 * pi * d / getEllipsePerimeter(rx, ry);
pp->x = (int) floor(cx + cos(theta) * rx);
pp->y = (int) floor(cy - sin(theta) * ry);
}
void fillBar(struct point seed, bool **matrix, int cx)
{
int bx;
if (seed.x > cx)
{
for (bx = seed.x;bx >= cx;bx--)
matrix[bx][seed.y] = true;
}
else
{
for (bx = seed.x;bx <= cx;bx++)
matrix[bx][seed.y] = true;
}
}
void rasterizeFilledEllipse(bool **matrix, int cx, int cy, int rx, int ry)
{
struct point currentPoint, midPoint;
struct point previousPoint = {coord_nil, coord_nil};
double perimeter = floor(getEllipsePerimeter(rx, ry));
double i;
// Loop over the perimeter of the ellipse to determine all points on the ellipse path.
for (i = 0.0;i < perimeter;i++)
{
// Find the current point and determine its coordinates.
getPointOnEllipse(cx, cy, rx, ry, i, &currentPoint);
// So fill the bar (horizontal line) that leads from
// the current point to the minor axis.
fillBar(currentPoint, matrix, cx);
// So check if the previous point exists. Please note that if the current
// point is the first point (i = 0), then there will be no previous point.
if (previousPoint.x != coord_nil)
{
// Now check if there is a gap between the current point and the previous
// point. We know it's not OK to have gaps along the ellipse path!
if (!((currentPoint.x - 1 <= previousPoint.x) && (previousPoint.x <= currentPoint.x + 1) &&
(currentPoint.y - 1 <= previousPoint.y) && (previousPoint.y <= currentPoint.y + 1)))
{
// Find the missing point by defining its offset as a fraction
// between the current point offset and the previous point offset.
getPointOnEllipse(cx, cy, rx, ry, i - 0.5, &midPoint);
fillBar(midPoint, matrix, cx);
}
}
previousPoint.x = currentPoint.x;
previousPoint.y = currentPoint.y;
}
}
void filledEllipseInMatrix(bool **matrix, int width, int height)
{
// So the ellipse shall be stretched to the whole matrix
// with a one-pixel margin.
int cx = width / 2;
int cy = height / 2;
int rx = cx - 1;
int ry = cy - 1;
// Call the general-purpose ellipse rasterizing function.
rasterizeFilledEllipse(matrix, cx, cy, rx, ry);
}

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

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.

Go image manipulation

I need to load an image and search for colors and replace them. For example on an image I need to search for all red pixels and convert them to purple.
I am doing the following (img is a valid .png image):
func colorize(img image.Image) {
b := image.NewRGBA(img.Bounds())
draw.Draw(b, b.Bounds(), img, image.ZP, draw.Src)
for x := 0; x < b.Bounds().Dx(); x++ {
for y := 0; y < b.Bounds().Dy(); y++ {
log.Println(b.At(x, y).RGBA())
}
}
}
Thing is img.At().RGBA() doesn't seem to return the proper R, G, B, A codes? I am getting numbers bigger than 255 for example.
So how should I read all the image pixels while being able to know the x and y position of them?
img.At().RGBA() is Color.RGBA(). Quoting its doc:
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
// for the color. Each value ranges within [0, 0xffff], but is represented
// by a uint32 so that multiplying by a blend factor up to 0xffff will not
// overflow.
//
// An alpha-premultiplied color component c has been scaled by alpha (a),
// so has valid values 0 <= c <= a.
Components returned by RGBA() are in range 0..0xffff, not 0..0xff, and they are also alpha-premultiplied.
Manual decoding
One way to get back the red, green, blue components in the 0..255 range is to shift right by 8 for example:
r, g, b, a := b.At(x, y).RGBA()
r, g, b, a = r>>8, g>>8, b>>8, a>>8
log.Println(r, g, b) // Now in range 0..255
Converting to color.RGBA
Another way is to convert the color to color.RGBA which is a struct, containing the components plain and simple:
type RGBA struct {
R, G, B, A uint8
}
Since you are using image.NewRGBA() which returns an image of type image.RGBA, the colors returned by the Image.At() method will be of dynamic type color.RGBA, so you can simply use a type assertion:
rgbacol := b.At(x, y).(color.RGBA)
log.Println(rgbacol.R, rgbacol.G, rgbacol.B, rgbacol.A)
In general (if image is not of type image.RGBA), Image.At() may or may not be of concrete type color.RGBA.
So in the general case you need to convert the color to a value of type color.RGBA. Conversions between color models are modeled by color.Model, and the image/color package has predefined converters. What you need is color.RGBAModel. color.RGBAModel.Convert() will return a color.Color value whose dynamic type is surely color.RGBA.
Example using color.RGBAModel:
var c color.Color
c = color.Gray{160}
rgbacol := color.RGBAModel.Convert(c).(color.RGBA)
fmt.Println(rgbacol.R, rgbacol.G, rgbacol.B, rgbacol.A)
Output (try it on the Go Playground):
160 160 160 255
So in your loop do:
rgbacol := color.RGBAModel.Convert(b.At(x, y).(color.RGBA)
// rgbacol is a struct of type color.RGBA, components are in range 0..255
Note:
Above solutions still give you back the alpha pre-multiplied components. If you want to undo the alpha pre-multiplication, you may use color.NRGBAModel converter (instead of color.RGBAModel).

Resources