From 4f1c67ad10c2f31a1a44c9b3c2213f22c0d74534 Mon Sep 17 00:00:00 2001 From: Paolo Calao Date: Sun, 7 Aug 2022 17:17:17 +0200 Subject: [PATCH] Add comments --- component/grid.go | 11 +++++++++++ component/rope.go | 10 +++++++++- line.go | 4 ++++ point.go | 17 ++++++++++++++++- vector.go | 1 + verlet.go | 29 ++++++++++++++++++++++++++--- 6 files changed, 67 insertions(+), 5 deletions(-) diff --git a/component/grid.go b/component/grid.go index 9483a39..9fda232 100644 --- a/component/grid.go +++ b/component/grid.go @@ -1,13 +1,21 @@ +// Package component leverages the basic verlet units to +// implement more complex components. +// It can be seen as an example to make custom components. package component import "github.com/polldo/verlet" +// Grid is a verlet component composed of a grid of points +// aligned by lines. +// The first point of the grid (index 0) is considered the origin +// and is fixed. type Grid struct { *verlet.Verlet Origin *verlet.Point Rows, Cols int } +// NewGrid builds and returns a grid. func NewGrid(cols, rows int, distance float64, opts ...verlet.Opt) *Grid { g := &Grid{ Verlet: verlet.New(opts...), @@ -39,11 +47,14 @@ func NewGrid(cols, rows int, distance float64, opts ...verlet.Opt) *Grid { return g } +// Extract allows to takes the reference of a grid's point +// that corresponds to the passed grid's coordinates. func (g *Grid) Extract(col, row int) *verlet.Point { idx := g.MatrixToArray(col, row) return g.Points[idx] } +// MatrixToArray converts grid's coordinates (2d) in array's index (1d). func (g *Grid) MatrixToArray(col, row int) int { return col*g.Rows + row } diff --git a/component/rope.go b/component/rope.go index 667d11d..81cf46e 100644 --- a/component/rope.go +++ b/component/rope.go @@ -1,25 +1,33 @@ +// Package component leverages the basic verlet units to +// implement more complex components. +// It can be seen as an example to make custom components. package component import "github.com/polldo/verlet" +// Rope is a component that represents a simple rope. +// It's composed of several concatenated lines. +// A fixed point is used as the rope's head. type Rope struct { *verlet.Verlet Head *verlet.Point } +// NewRope builds and returns a new rope. func NewRope(units int, distance float64, opts ...verlet.Opt) *Rope { r := &Rope{ Verlet: verlet.New(opts...), } + // Center the rope. x := r.Verlet.Bound.X / 2 y := r.Verlet.Bound.Y / 2 r.Head = r.NewPoint(x, y, verlet.Fix(), verlet.Radius(8.0)) + // Build and concatenate lines. for i := 1; i < units; i++ { r.NewPoint(x, y-float64(i)*distance) r.NewLine(r.Points[i], r.Points[i-1]) } - return r } diff --git a/line.go b/line.go index 613b145..5cd0f8e 100644 --- a/line.go +++ b/line.go @@ -1,11 +1,15 @@ +// Package verlet contains the basic units to build more complex verlet systems. package verlet +// Line constrains two points. type Line struct { A *Point B *Point Len float64 } +// Update tries to adjust the positiong of the points +// of a line according to its length. func (l *Line) Update() { distance := l.A.Distance(l.B) dL := (l.Len - distance) / distance / 2 diff --git a/point.go b/point.go index 366a7fa..c2c9594 100644 --- a/point.go +++ b/point.go @@ -1,42 +1,55 @@ +// Package verlet contains the basic units to build more complex verlet systems. package verlet import ( "math" ) +// PointOpt is the type representing a functional option +// for verlet points. type PointOpt func(*Point) +// SetOptions configures the point p with the passed +// functional options. func (p *Point) SetOptions(opts ...PointOpt) { for _, opt := range opts { opt(p) } } +// Fix returns a functional option to make a point fixed. +// Fixed points cannot move. func Fix() PointOpt { return func(p *Point) { p.Fixed = true } } +// Radius returns a functional option that sets the radius +// of points. func Radius(r float64) PointOpt { return func(p *Point) { p.Radius = r } } +// Point is the atom of every verlet system. type Point struct { - Fixed bool + Fixed bool // Fixed points cannot move. Radius float64 Position Vector OldPosition Vector } +// Distance returns the distance between two points. func (p *Point) Distance(other *Point) float64 { diff := p.Position.Sub(other.Position) dist := math.Sqrt(diff.X*diff.X + diff.Y*diff.Y) return dist } +// Update applies the given forces to the point and +// updates its point position accordingly. func (p *Point) Update(friction float64, gravity Vector) { if p.Fixed { return @@ -52,6 +65,8 @@ func (p *Point) Update(friction float64, gravity Vector) { p.Position = p.Position.Add(gravity) } +// Bounds handles collisions of the point with the boundaries +// of the system and regulates the point velocity accordingly. func (p *Point) Bounds(bound Vector) { vel := p.Position.Sub(p.OldPosition) // Check bounds diff --git a/vector.go b/vector.go index a31bee2..3170565 100644 --- a/vector.go +++ b/vector.go @@ -1,3 +1,4 @@ +// Package verlet contains the basic units to build more complex verlet systems. package verlet // Vector is a simple struct representing a 2d math vector. diff --git a/verlet.go b/verlet.go index 68be80d..91b2ce2 100644 --- a/verlet.go +++ b/verlet.go @@ -1,5 +1,7 @@ +// Package verlet contains the basic units to build more complex verlet systems. package verlet +// Opt represents a functional option for verlet. type Opt func(*Verlet) // Gravity sets the gravity option for verlet. @@ -23,14 +25,25 @@ func Friction(f float64) Opt { } } +// Verlet is the main unit of this library. +// It can be used to build complex shapes starting +// from lines and points. +// Its physics can be manipulated by properly +// setting its properties. +// +// It exposes all its points and line so that +// it can be iterated for rendering. +// TODO: Add an 'Apply' function that applies a +// certain function to all points of this system. type Verlet struct { Points []*Point Lines []*Line - Gravity Vector - Bound Vector - Friction float64 + Gravity Vector // Gravity force that acts on all points of this unit. + Bound Vector // Bound is the size of this system (boundaries). + Friction float64 // Resistance of verlet points. } +// New builds a new verlet unit and returns it. func New(opts ...Opt) *Verlet { v := &Verlet{ Gravity: Vector{X: 0.1, Y: -0.1}, @@ -41,12 +54,16 @@ func New(opts ...Opt) *Verlet { return v } +// SetOptions reconfigures the system with the passed +// functional options. func (v *Verlet) SetOptions(opts ...Opt) { for _, opt := range opts { opt(v) } } +// NewPoint add a new point to this verlet system and returns its pointer +// so that it can be manipulated, stored or used to build new lines. func (v *Verlet) NewPoint(x, y float64, opts ...PointOpt) *Point { p := &Point{ Fixed: false, @@ -59,6 +76,7 @@ func (v *Verlet) NewPoint(x, y float64, opts ...PointOpt) *Point { return p } +// NewLine add a new line to this verlet system and returns it. func (v *Verlet) NewLine(a, b *Point) *Line { ln := &Line{ A: a, @@ -69,6 +87,11 @@ func (v *Verlet) NewLine(a, b *Point) *Line { return ln } +// Update is the function that animates the entire system. +// It applies all the known forces to the points and updates +// their position accordingly. +// The count value could be tweaked to change the +// precision of the system simulation. func (v *Verlet) Update(count int) { for _, p := range v.Points { p.Update(v.Friction, v.Gravity)