goutil/image/path/path.go

86 lines
2.5 KiB
Go

package upath
import "math"
import "image"
// P creates a path fom a list of integers that form X-Y pairs.
func P (data ...int) []image.Point {
result := make([]image.Point, len(data) / 2)
for index := range result {
result[index].X = data[index * 2]
result[index].Y = data[index * 2 + 1]
}
return result
}
// Lerp linearally interpolates between two paths. If the paths differ in
// length, the returned path will only be as long as the smaller one. This
// function will always return a new slice.
func Lerp (fac float64, start, end []image.Point) []image.Point {
result := make([]image.Point, len(start))
for index, startPt := range start {
if index >= len(end) { return result[:index] }
endPt := end[index]
result[index] = image.Pt (
lerp(fac, startPt.X, endPt.X),
lerp(fac, startPt.Y, endPt.Y))
}
return result
}
// MultiLerp is like Lerp, but interpolates through several "stages". This
// function will always return a new slice. If no stages are provided, it will
// return nil.
func MultiLerp (fac float64, stages ...[]image.Point) []image.Point {
if len(stages) == 0 { return nil }
if len(stages) == 1 {
result := make([]image.Point, len(stages[0]))
copy(result, stages[0])
return result
}
expandedFac := fac * float64(len(stages) - 1)
startIndex := int(expandedFac)
if startIndex >= len(stages) { startIndex = len(stages) - 1 }
endIndex := startIndex + 1
if endIndex >= len(stages) { endIndex = len(stages) - 1 }
start := stages[startIndex]
end := stages[endIndex]
partialFac := expandedFac - float64(startIndex)
return Lerp(partialFac, start, end)
}
// Distance returns the distance between two points.
func Distance (start, end image.Point) float64 {
delta := start.Sub(end)
return math.Sqrt(float64(delta.X * delta.X) + float64(delta.Y * delta.Y))
}
// DistanceToLine calculates the distance from a point to a line which passes
// through points line1 and line2.
func DistanceToLine (point, line1, line2 image.Point) float64 {
x := float64(point.X)
y := float64(point.Y)
x1 := float64(line1.X)
y1 := float64(line1.Y)
x2 := float64(line2.X)
y2 := float64(line2.Y)
triangle := math.Abs((y2 - y1)*x - (x2 - x1)*y + x2*y1 - y2*x1)
return triangle / Distance(line1, line2)
}
// Translate adds delta to all points in path. This modifies the slice contents.
func Translate (delta image.Point, path []image.Point) {
for index, point := range path {
path[index] = point.Add(delta)
}
}
func lerp (fac float64, x, y int) int {
return int(float64(x) * (1.0 - fac) + float64(y) * fac)
}