|
|
@@ -5,6 +5,7 @@ import ( |
|
|
"git.wtrh.nl/patterns/gopatterns/pkg/pattern/point" |
|
|
"git.wtrh.nl/patterns/gopatterns/pkg/pattern/point" |
|
|
"github.com/tdewolff/canvas" |
|
|
"github.com/tdewolff/canvas" |
|
|
splines "gitlab.com/Achilleshiel/gosplines" |
|
|
splines "gitlab.com/Achilleshiel/gosplines" |
|
|
|
|
|
"log/slog" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
const resolution = 40 |
|
|
const resolution = 40 |
|
|
@@ -44,8 +45,41 @@ func NewSpline(opts SplineOpts) Spline { |
|
|
|
|
|
|
|
|
// Draw the spline to the provided [canvas.Canvas]. |
|
|
// Draw the spline to the provided [canvas.Canvas]. |
|
|
func (s Spline) Draw(c *canvas.Canvas) error { |
|
|
func (s Spline) Draw(c *canvas.Canvas) error { |
|
|
|
|
|
points, err := s.build() |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return fmt.Errorf("generating spline: %w", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
path := NewPath(points, s.style) |
|
|
|
|
|
|
|
|
|
|
|
if err = path.Draw(c); err != nil { |
|
|
|
|
|
return fmt.Errorf("draw spline points to canvas: %w", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
length, _ := s.Length() |
|
|
|
|
|
slog.Debug("Draw spline", "length", length, "from", points[0].Name(), "to", points[len(points)-1].Name()) |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s Spline) Length() (float64, error) { |
|
|
|
|
|
points, err := s.build() |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return 0.0, fmt.Errorf("generating spline: %w", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
length := 0.0 |
|
|
|
|
|
|
|
|
|
|
|
for i := range points[1:] { |
|
|
|
|
|
length += points[i].Position().Distance(points[i+1].Position()) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return length, nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s Spline) build() (points []point.Point, err error) { |
|
|
if len(s.points) < 2 { |
|
|
if len(s.points) < 2 { |
|
|
return nil |
|
|
|
|
|
|
|
|
return s.points, nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
x := make([]float64, len(s.points)) |
|
|
x := make([]float64, len(s.points)) |
|
|
@@ -60,15 +94,15 @@ func (s Spline) Draw(c *canvas.Canvas) error { |
|
|
|
|
|
|
|
|
xCoefficient, err := splines.SolveSplineWithConstraint(x, diffStart.X, diffEnd.X) |
|
|
xCoefficient, err := splines.SolveSplineWithConstraint(x, diffStart.X, diffEnd.X) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return fmt.Errorf("unable to calculate coefficients for x: %w", err) |
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to calculate coefficients for x: %w", err) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
yCoefficient, err := splines.SolveSplineWithConstraint(y, diffStart.Y, diffEnd.Y) |
|
|
yCoefficient, err := splines.SolveSplineWithConstraint(y, diffStart.Y, diffEnd.Y) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return fmt.Errorf("unable to calculate coefficients for y: %w", err) |
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to calculate coefficients for y: %w", err) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
points := make([]point.Point, 0, len(x)*resolution) |
|
|
|
|
|
|
|
|
points = make([]point.Point, 0, len(x)*resolution) |
|
|
stepSize := 1.0 / float64(resolution-1) |
|
|
stepSize := 1.0 / float64(resolution-1) |
|
|
|
|
|
|
|
|
for i := range len(s.points) - 1 { |
|
|
for i := range len(s.points) - 1 { |
|
|
@@ -83,11 +117,5 @@ func (s Spline) Draw(c *canvas.Canvas) error { |
|
|
|
|
|
|
|
|
points = append(points, s.points[len(s.points)-1]) |
|
|
points = append(points, s.points[len(s.points)-1]) |
|
|
|
|
|
|
|
|
path := NewPath(points, s.style) |
|
|
|
|
|
|
|
|
|
|
|
if err = path.Draw(c); err != nil { |
|
|
|
|
|
return fmt.Errorf("draw spline points to canvas: %w", err) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
|
return points, nil |
|
|
} |
|
|
} |