Curve that touches three points: Difference between revisions
m (changed a (¿ non-task thingy ?) to a "draft task".) |
(Added Go) |
||
Line 5: | Line 5: | ||
::# Do not use functions of a library, implement the curve() function yourself |
::# Do not use functions of a library, implement the curve() function yourself |
||
::# coordinates:(x,y) starting point (10,10) medium point (100,200) final point (200,10) |
::# coordinates:(x,y) starting point (10,10) medium point (100,200) final point (200,10) |
||
=={{header|Go}}== |
|||
{{libheader|Go Graphics}} |
|||
<br> |
|||
There are, of course, an infinity of curves which can be fitted to 3 points. The most obvious solution is to fit a quadratic curve (using Lagrange interpolation) and so that's what we do here. |
|||
As we're not allowed to use library functions to draw the curve, we instead divide the x-axis of the curve between successive points into equal segments and then join the resulting points with straight lines. |
|||
The resulting 'curve' is then saved to a .png file where it can be viewed with a utility such as EOG. |
|||
<lang go>package main |
|||
import "github.com/fogleman/gg" |
|||
var p = [3]gg.Point{{10, 10}, {100, 200}, {200, 10}} |
|||
func lagrange(x float64) float64 { |
|||
return (x-p[1].X)*(x-p[2].X)/(p[0].X-p[1].X)/(p[0].X-p[2].X)*p[0].Y + |
|||
(x-p[0].X)*(x-p[2].X)/(p[1].X-p[0].X)/(p[1].X-p[2].X)*p[1].Y + |
|||
(x-p[0].X)*(x-p[1].X)/(p[2].X-p[0].X)/(p[2].X-p[1].X)*p[2].Y |
|||
} |
|||
func getPoints(n int) []gg.Point { |
|||
pts := make([]gg.Point, 2*n+1) |
|||
dx := (p[1].X - p[0].X) / float64(n) |
|||
for i := 0; i < n; i++ { |
|||
x := p[0].X + dx*float64(i) |
|||
pts[i] = gg.Point{x, lagrange(x)} |
|||
} |
|||
dx = (p[2].X - p[1].X) / float64(n) |
|||
for i := n; i < 2*n+1; i++ { |
|||
x := p[1].X + dx*float64(i-n) |
|||
pts[i] = gg.Point{x, lagrange(x)} |
|||
} |
|||
return pts |
|||
} |
|||
func main() { |
|||
const n = 50 // more than enough for this |
|||
dc := gg.NewContext(210, 210) |
|||
dc.SetRGB(1, 1, 1) // White background |
|||
dc.Clear() |
|||
for _, pt := range getPoints(n) { |
|||
dc.LineTo(pt.X, pt.Y) |
|||
} |
|||
dc.SetRGB(0, 0, 0) // Black curve |
|||
dc.SetLineWidth(1) |
|||
dc.Stroke() |
|||
dc.SavePNG("quadratic_curve.png") |
|||
}</lang> |
Revision as of 13:03, 12 November 2018
Draw a curve that touches 3 points (1 starting point, 2 medium, 3 final point)
- Do not use functions of a library, implement the curve() function yourself
- coordinates:(x,y) starting point (10,10) medium point (100,200) final point (200,10)
Go
There are, of course, an infinity of curves which can be fitted to 3 points. The most obvious solution is to fit a quadratic curve (using Lagrange interpolation) and so that's what we do here.
As we're not allowed to use library functions to draw the curve, we instead divide the x-axis of the curve between successive points into equal segments and then join the resulting points with straight lines.
The resulting 'curve' is then saved to a .png file where it can be viewed with a utility such as EOG. <lang go>package main
import "github.com/fogleman/gg"
var p = [3]gg.Point{{10, 10}, {100, 200}, {200, 10}}
func lagrange(x float64) float64 {
return (x-p[1].X)*(x-p[2].X)/(p[0].X-p[1].X)/(p[0].X-p[2].X)*p[0].Y + (x-p[0].X)*(x-p[2].X)/(p[1].X-p[0].X)/(p[1].X-p[2].X)*p[1].Y + (x-p[0].X)*(x-p[1].X)/(p[2].X-p[0].X)/(p[2].X-p[1].X)*p[2].Y
}
func getPoints(n int) []gg.Point {
pts := make([]gg.Point, 2*n+1) dx := (p[1].X - p[0].X) / float64(n) for i := 0; i < n; i++ { x := p[0].X + dx*float64(i) pts[i] = gg.Point{x, lagrange(x)} } dx = (p[2].X - p[1].X) / float64(n) for i := n; i < 2*n+1; i++ { x := p[1].X + dx*float64(i-n) pts[i] = gg.Point{x, lagrange(x)} } return pts
}
func main() {
const n = 50 // more than enough for this dc := gg.NewContext(210, 210) dc.SetRGB(1, 1, 1) // White background dc.Clear() for _, pt := range getPoints(n) { dc.LineTo(pt.X, pt.Y) } dc.SetRGB(0, 0, 0) // Black curve dc.SetLineWidth(1) dc.Stroke() dc.SavePNG("quadratic_curve.png")
}</lang>