Draw Bezier curves with Go

Draw Bezier curves with Go

I would like to give a detailed explanation, but for the time being the source code

Source code

package bezier

import (
  "math"
)

type Point struct{
  X,Y float64
}

// n! (factorial of n)
func factorial(n int)(int){
  if n == 0{
    return 1
  }
  return n * factorial(n-1)
}

func biCoe(n,i int)(float64){
  return float64(factorial(n) / (factorial(n-i) * factorial(i)))
}

func bernstein(n,i int,t float64)(float64){
  var N float64 = float64(n)
  var I float64 = float64(i)
  return biCoe(n,i) * math.Pow(t,I ) * math.Pow(1-t,N-I)
}

func BezierCurve(p []Point,t float64)(result Point){
  for i,v := range p{
    B := bernstein(len(p)-1,i,t)
    result.X += v.X*B
    result.Y += v.Y*B
  }
  return
}

//If the amount of change value is increased, a becomes a crisp curve.
func Curve(p []Point,a float64)(result []Point){
  var t float64
  for {
    result = append(result, BezierCurve(p,t) )
    t += a
    if t >= 1{
      break
    }
  }
  return
}

Curve ([] Point, float64) is a function that gives the control point and the amount of change in t and returns a slice of P (t, 0> = t <= 1).

The user usually draws using this function (assuming that).

Usage example

package bezier

import (
  "testing"
  "github.com/fogleman/gg"
)

func TestBezierCurve(t *testing.T){
  //Control point
  P := []Point{Point{10,10},Point{10,590},Point{590,590}}

  //Amount of change
  const A = 0.01
  result := Curve(P,A)

  dc := gg.NewContext(600,600)
  dc.SetHexColor("#fff")
  dc.Clear()

  //Drawing control points
  dc.Push()
  dc.SetHexColor("#0000ff")
  for _,v :=range P{
    dc.DrawCircle(v.X,v.Y,4)
    dc.Fill()
  }
  dc.Pop()

  //Draw a curve
  dc.Push()
  dc.SetHexColor("#000")
  //Move to the starting point
  dc.MoveTo(P[0].X,P[0].Y)
  for _,v :=range result{
    dc.LineTo(v.X,v.Y)
  }
  dc.Stroke()
  dc.Pop()

  // P(t)Drawing of
  dc.Push()
  dc.SetHexColor("#f01000")
  for _,v :=range result{
    dc.DrawCircle(v.X,v.Y,3)
  }
  dc.Stroke()
  dc.Pop()

  dc.SavePNG("out.png ")
}

Test execution result

実行結果

The blue point is the control point and the red is the circle centered on the coordinates of P (t).

in conclusion

I'm not good at mathematics, but I came up with an implementation in a few hours (too much time) by staring at mathematical formulas. There was a great sense of accomplishment. (Impression of elementary school students)

I would like to update it little by little when I am fine.

I hope this article will be useful to someone.

Acknowledgments

I am always indebted to http://github.com/fogleman/gg.

The article by @Rahariku was very helpful. Thank you very much.

reference

Recommended Posts

Draw Bezier curves with Go
Python with Go
Operate Db2 container with Go
Draw a graph with NetworkX
Getting Started with Go Assembly
Draw hello world with mod_wsgi
Draw netCDF file with python
Bit full search with Go
Connect to Postgresql with GO
Hot reload with Go + Air
Try implementing perfume with Go
Draw a graph with networkx
Draw unblurred sprites with cocos2d / pyglet
Draw a graph with Julia + PyQtGraph (2)
Try to draw a Bezier curve
GUI development with Fyne by Go
Go see whales with combinatorial optimization
Tips for running Go with docker
Draw Japanese with matplotlib on Ubuntu
Draw a loose graph with matplotlib
Draw a beautiful circle with numpy
Draw a graph with Julia + PyQtGraph (1)
Upload & move GCS files with Go
Draw a graph with Julia + PyQtGraph (3)
Using Lambda with AWS Amplify with Go
Draw Koch curve with Python Turtle
Using cgo with the go command
Metaprogram go with YAML + Mustache + go-generate
Use curl / jq library with Go
Draw a graph with pandas + XlsxWriter
Draw an illustration with Python + OpenCV
Easy to draw graphs with matplotlib
Draw Lyapunov Fractal with Python, matplotlib
Draw a graph with PySimple GUI
Draw with PyOpenGL. Confusion around VBO
Easily draw a map with matplotlib.basemap
Draw shapes with OpenCV and PIL
Draw arrows (vectors) with opencv / python
Operate Linux Network Namespace with Go