Skip to content

Commit

Permalink
Add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
polldo committed Aug 7, 2022
1 parent e5573cb commit 4f1c67a
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 5 deletions.
11 changes: 11 additions & 0 deletions component/grid.go
Original file line number Diff line number Diff line change
@@ -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...),
Expand Down Expand Up @@ -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
}
10 changes: 9 additions & 1 deletion component/rope.go
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 4 additions & 0 deletions line.go
Original file line number Diff line number Diff line change
@@ -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
Expand Down
17 changes: 16 additions & 1 deletion point.go
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions vector.go
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
29 changes: 26 additions & 3 deletions verlet.go
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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},
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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)
Expand Down

0 comments on commit 4f1c67a

Please sign in to comment.