Documentation
¶
Overview ¶
Package model2d provides various tools for loading, manipulating, saving, and using 2D shapes. It is also intended to aid in creating 3D models which incorporate 2D shapes in some way.
Index ¶
- func ColliderContains(c Collider, coord Coord, margin float64) bool
- func EncodeSVG(m *Mesh) []byte
- func GroupSegments(segs []*Segment)
- func InBounds(b Bounder, c Coord) bool
- func Triangulate(polygon []Coord) [][3]Coord
- type BezierCurve
- type Bitmap
- type Bounder
- type Collider
- type ColliderSolid
- type ColorBitFunc
- type Coord
- func (c Coord) Add(c1 Coord) Coord
- func (c Coord) Array() [2]float64
- func (c Coord) Dist(c1 Coord) float64
- func (c Coord) Dot(c1 Coord) float64
- func (c Coord) Max(c1 Coord) Coord
- func (c Coord) Mid(c1 Coord) Coord
- func (c Coord) Min(c1 Coord) Coord
- func (c Coord) Mul(c1 Coord) Coord
- func (c Coord) Norm() float64
- func (c Coord) Normalize() Coord
- func (c Coord) ProjectOut(c1 Coord) Coord
- func (c Coord) Reflect(c1 Coord) Coord
- func (c Coord) Scale(s float64) Coord
- func (c Coord) Sub(c1 Coord) Coord
- func (c Coord) Sum() float64
- type InterpBitmap
- func (b *InterpBitmap) Bitmap() *Bitmap
- func (b *InterpBitmap) Contains(c Coord) bool
- func (b *InterpBitmap) FlipX() *InterpBitmap
- func (b *InterpBitmap) FlipY() *InterpBitmap
- func (b *InterpBitmap) Get(x, y int) color.RGBA
- func (b *InterpBitmap) Invert() *InterpBitmap
- func (b *InterpBitmap) Max() Coord
- func (b *InterpBitmap) Min() Coord
- type Interpolator
- type JoinedCollider
- type JoinedSolid
- type Matrix2
- type Mesh
- func (m *Mesh) Add(s *Segment)
- func (m *Mesh) AddMesh(m1 *Mesh)
- func (m *Mesh) Blur(rate float64) *Mesh
- func (m *Mesh) Contains(s *Segment) bool
- func (m *Mesh) Find(ps ...Coord) []*Segment
- func (m *Mesh) Iterate(f func(s *Segment))
- func (m *Mesh) IterateSorted(f func(s *Segment), cmp func(s1, s2 *Segment) bool)
- func (m *Mesh) IterateVertices(f func(c Coord))
- func (m *Mesh) Manifold() bool
- func (m *Mesh) MapCoords(f func(Coord) Coord) *Mesh
- func (m *Mesh) Max() Coord
- func (m *Mesh) Min() Coord
- func (m *Mesh) Neighbors(s *Segment) []*Segment
- func (m *Mesh) Remove(s *Segment)
- func (m *Mesh) SaveSVG(path string) error
- func (m *Mesh) SegmentsSlice() []*Segment
- func (m *Mesh) Smooth(iters int) *Mesh
- func (m *Mesh) SmoothSq(iters int) *Mesh
- func (m *Mesh) Subdivide(iters int) *Mesh
- func (m *Mesh) VertexSlice() []Coord
- type Ray
- type RayCollision
- type Segment
- func (s *Segment) CircleCollision(c Coord, r float64) bool
- func (s *Segment) FirstRayCollision(r *Ray) (RayCollision, bool)
- func (s Segment) Length() float64
- func (s Segment) Max() Coord
- func (s Segment) Mid() Coord
- func (s Segment) Min() Coord
- func (s *Segment) Normal() Coord
- func (s *Segment) RayCollisions(r *Ray, f func(RayCollision)) int
- type Solid
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ColliderContains ¶
ColliderContains checks if a point is within a Collider and at least margin away from the border.
If the margin is negative, points are also conatined if the point is less than -margin away from the surface.
func GroupSegments ¶
func GroupSegments(segs []*Segment)
GroupSegments sorts the segments recursively by their x and y values. This can be used to prepare segments for GroupedSegmentsToCollider.
func Triangulate ¶
Triangulate turns any simple polygon into a set of equivalent triangles.
The polygon is passed as a series of points, in order. The first point is re-used as the ending point, so no ending should be explicitly specified.
Types ¶
type BezierCurve ¶
type BezierCurve []Coord
BezierCurve implements an arbitrarily high-dimensional Bezier curve.
func (BezierCurve) Eval ¶
func (b BezierCurve) Eval(t float64) Coord
Eval evaluates the curve at time t, where 0 <= t <= 1.
func (BezierCurve) EvalX ¶
func (b BezierCurve) EvalX(x float64) float64
EvalX finds the y value that occurs at the given x value, assuming that the curve is monotonic in x.
If the y value cannot be found, NaN is returned.
func (BezierCurve) InverseX ¶
func (b BezierCurve) InverseX(x float64) float64
InverseX gets the t value between 0 and 1 where the x value is equal to some x, assuming the curve is monotonic in x.
If the t cannot be found, NaN is returned.
func (BezierCurve) Transpose ¶
func (b BezierCurve) Transpose() BezierCurve
Transpose generates a BezierCurve where x and y are swapped.
type Bitmap ¶
A Bitmap is a two-dimensional image with boolean values. The data is stored in row-major order.
func MustReadBitmap ¶
func MustReadBitmap(path string, c ColorBitFunc) *Bitmap
MustReadBitmap is like ReadBitmap, except that it panics if the bitmap cannot be read.
func NewBitmapImage ¶
func NewBitmapImage(img image.Image, c ColorBitFunc) *Bitmap
NewBitmapImage creates a Bitmap from an image, by calling c for each pixel and using the result as the bit.
If c is nil, then the mean RGBA is computed, and pixels are considered true if they are closer to the mean in L2 distance than they are to the top-left pixel. For images with two dominant colors, this is equivalent to making the background false, and the foreground true, assuming that the first pixel is background.
func ReadBitmap ¶
func ReadBitmap(path string, c ColorBitFunc) (*Bitmap, error)
ReadBitmap is like NewBitmapImage, except that it reads the image from a file.
func (*Bitmap) Get ¶
Get gets the bit at the coordinate.
If the coordinate is out of bounds, false is returned.
type Bounder ¶
type Bounder interface { // Get the corners of a bounding rectangle. // // A point p satisfies p >= Min and p <= Max if it is // within the bounds. Min() Coord Max() Coord }
A Bounder is an object contained in a rectangle.
type Collider ¶
type Collider interface { Bounder // RayCollisions enumerates the collisions with a ray. // It returns the total number of collisions. // // f may be nil, in which case this is simply used for // counting. RayCollisions(r *Ray, f func(RayCollision)) int // FirstRayCollision gets the ray collision with the // lowest scale. // // The second return value is false if no collisions // were found. FirstRayCollision(r *Ray) (collision RayCollision, collides bool) // CircleCollision checks if the collider touches a // circle with origin c and radius r. CircleCollision(c Coord, r float64) bool }
A Collider is the outline of a 2-dimensional shape. It can count its intersections with a ray, and check if any part of the outline is inside a circle.
All methods of a Collider are safe for concurrency.
func GroupedSegmentsToCollider ¶
GroupedSegmentsToCollider converts pre-grouped segments into an efficient collider. If the segments were not grouped with GroupSegments, then the resulting collider may be highly inefficient.
func MeshToCollider ¶
MeshToCollider converts a mesh to an efficient Collider.
type ColliderSolid ¶
type ColliderSolid struct {
// contains filtered or unexported fields
}
ColliderSolid is a Solid which uses the even-odd test for a Collider.
func NewColliderSolid ¶
func NewColliderSolid(c Collider) *ColliderSolid
NewColliderSolid creates a basic ColliderSolid.
func NewColliderSolidHollow ¶
func NewColliderSolidHollow(c Collider, r float64) *ColliderSolid
NewColliderSolidHollow creates a ColliderSolid that only reports containment around the edges.
func NewColliderSolidInset ¶
func NewColliderSolidInset(c Collider, inset float64) *ColliderSolid
NewColliderSolidInset creates a ColliderSolid that only reports containment at some distance from the surface.
If inset is negative, then the solid is outset from the collider.
func (*ColliderSolid) Contains ¶
func (c *ColliderSolid) Contains(coord Coord) bool
Contains checks if coord is in the solid.
func (*ColliderSolid) Max ¶
func (c *ColliderSolid) Max() Coord
Max gets the maximum of the bounding box.
func (*ColliderSolid) Min ¶
func (c *ColliderSolid) Min() Coord
Min gets the minimum of the bounding box.
type ColorBitFunc ¶
ColorBitFunc turns colors into single bits.
type Coord ¶
A Coord is a coordinate in 2-D Euclidean space.
func NewCoordArray ¶
NewCoordArray creates a Coord from an array of x and y.
func NewCoordRandNorm ¶
func NewCoordRandNorm() Coord
NewCoordRandNorm creates a random Coord with normally distributed components.
func NewCoordRandUnit ¶
func NewCoordRandUnit() Coord
NewCoordRandUnit creates a random Coord with magnitude 1.
func (Coord) ProjectOut ¶
ProjectOut projects the c1 direction out of c.
type InterpBitmap ¶
type InterpBitmap struct { Data []color.RGBA Width int Height int Model color.Model F ColorBitFunc // Interp is the interpolation function. // A zero value is Bicubic. Interp Interpolator }
An InterpBitmap is a dynamic Bitmap backed by an image with a color interpolation scheme.
func MustReadInterpBitmap ¶
func MustReadInterpBitmap(path string, c ColorBitFunc) *InterpBitmap
MustReadInterpBitmap is like ReadInterpBitmap, except that it panics if the InterpBitmap cannot be read.
func NewInterpBitmap ¶
func NewInterpBitmap(img image.Image, c ColorBitFunc) *InterpBitmap
NewInterpBitmap creates a InterpBitmap from an image.
If c is nil, then the mean RGBA is computed, and pixels are considered true if they are closer to the mean in L2 distance than they are to the top-left pixel. For images with two dominant colors, this is equivalent to making the background false, and the foreground true, assuming that the first pixel is background.
func ReadInterpBitmap ¶
func ReadInterpBitmap(path string, c ColorBitFunc) (*InterpBitmap, error)
ReadInterpBitmap is like NewInterpBitmap, except that it reads the image from a file.
func (*InterpBitmap) Bitmap ¶
func (b *InterpBitmap) Bitmap() *Bitmap
Bitmap gets an uninterpolated bitmap from b.
func (*InterpBitmap) Contains ¶
func (b *InterpBitmap) Contains(c Coord) bool
Contains gets the bit at the interpolated coordinate.
If the coordinate is out of bounds, false is returned.
func (*InterpBitmap) FlipX ¶
func (b *InterpBitmap) FlipX() *InterpBitmap
FlipX reverses the x-axis.
func (*InterpBitmap) FlipY ¶
func (b *InterpBitmap) FlipY() *InterpBitmap
FlipY reverses the y-axis.
func (*InterpBitmap) Get ¶
func (b *InterpBitmap) Get(x, y int) color.RGBA
Get gets the color at the coordinate.
If the coordinate is out of bounds, a the edge of the image is extended.
func (*InterpBitmap) Invert ¶
func (b *InterpBitmap) Invert() *InterpBitmap
Invert creates a new InterpBitmap with the opposite color bitmap values.
func (*InterpBitmap) Max ¶
func (b *InterpBitmap) Max() Coord
Max gets the maximum of the pixel bounding box.
func (*InterpBitmap) Min ¶
func (b *InterpBitmap) Min() Coord
Min gets the minimum of the pixel bounding box.
type Interpolator ¶
type Interpolator int
Interpolator is a 1-dimensional interpolation kernel.
const ( Bicubic Interpolator = iota Bilinear )
func (Interpolator) Kernel ¶
func (i Interpolator) Kernel(t float64) []float64
type JoinedCollider ¶
type JoinedCollider struct {
// contains filtered or unexported fields
}
A JoinedCollider wraps multiple other Colliders and only passes along rays and circles that enter their combined bounding box.
func NewJoinedCollider ¶
func NewJoinedCollider(other []Collider) *JoinedCollider
NewJoinedCollider creates a JoinedCollider which combines zero or more other colliders.
func (*JoinedCollider) CircleCollision ¶
func (j *JoinedCollider) CircleCollision(center Coord, r float64) bool
func (*JoinedCollider) FirstRayCollision ¶
func (j *JoinedCollider) FirstRayCollision(r *Ray) (RayCollision, bool)
func (*JoinedCollider) Max ¶
func (j *JoinedCollider) Max() Coord
func (*JoinedCollider) Min ¶
func (j *JoinedCollider) Min() Coord
func (*JoinedCollider) RayCollisions ¶
func (j *JoinedCollider) RayCollisions(r *Ray, f func(RayCollision)) int
type JoinedSolid ¶
type JoinedSolid []Solid
JoinedSolid combines one or more other solids into a single union.
func (JoinedSolid) Contains ¶
func (j JoinedSolid) Contains(c Coord) bool
func (JoinedSolid) Max ¶
func (j JoinedSolid) Max() Coord
func (JoinedSolid) Min ¶
func (j JoinedSolid) Min() Coord
type Matrix2 ¶
type Matrix2 [4]float64
Matrix2 is a 2x2 matrix, stored in row-major order.
func NewMatrix2Columns ¶
NewMatrix2Columns creates a Matrix2 with the given coordinates as column entries.
func NewMatrix2Rotation ¶
NewMatrix2Rotation creates a rotation matrix that rotates column vectors by theta.
func (*Matrix2) InvertInPlace ¶
func (m *Matrix2) InvertInPlace()
InvertInPlace moves the inverse of m into m without causing any new allocations.
type Mesh ¶
type Mesh struct {
// contains filtered or unexported fields
}
A Mesh is a collection of segments.
The segments are uniquely identified as pointers, not as values. This is important for methods which reference existing segments, such as Remove and Neighbors.
Segments in a mesh are "connected" when they contain exactly identical points. Thus, small rounding errors can cause segments to incorrectly be disassociated with each other.
A Mesh can be read safely from concurrent Goroutines, but modifications must not be performed concurrently with any mesh operations.
func MarchingSquares ¶
MarchingSquares turns a Solid into a mesh using a 2D version of the marching cubes algorithm.
func MarchingSquaresSearch ¶
MarchingSquaresSearch is like MarchingSquares, but applies an additional search step to move the vertices along the edges of each square.
The tightness of the triangulation will double for every iteration.
func NewMeshSegments ¶
NewMeshSegments creates a mesh with the given collection of Segments.
func (*Mesh) Blur ¶
Blur moves each vertex closer to the average of its neighbors.
The rate argument controls how much the vertices move. If it is 1, then the vertices become the average of their neighbors. If it is 0, then the vertices remain where they are.
func (*Mesh) Find ¶
Find gets all the Segments that contain all of the passed points.
This is only useful with one or two coordinates.
func (*Mesh) Iterate ¶
Iterate calls f for every Segment in m in an arbitrary order.
If f adds or removes Segments, they will not be visited.
func (*Mesh) IterateSorted ¶
IterateSorted is like Iterate, but it first sorts all the Segments according to a less than function, cmp.
func (*Mesh) IterateVertices ¶ added in v0.1.1
IterateVertices calls f for every vertex in m in an arbitrary order.
If f adds or removes vertices, they will not be visited.
func (*Mesh) Manifold ¶
Manifold checks if the mesh is manifold, i.e. if every vertex has two segments.
func (*Mesh) MapCoords ¶
MapCoords creates a new mesh by transforming all of the coordinates according to the function f.
func (*Mesh) Neighbors ¶
Neighbors gets all the Segments with a vertex touching a given Segment s.
The Segment s itself is not included in the results.
The Segment s needn't be in the mesh. However, if it is not in the mesh, but an equivalent Segment is, then said equivalent Segment will be in the results.
func (*Mesh) Remove ¶
Remove removes the Segment t from the mesh.
It looks at t as a pointer, so the pointer must be exactly the same as a Segment passed to Add.
func (*Mesh) SegmentsSlice ¶
SegmentsSlice gets a snapshot of all the Segments currently in the mesh. The resulting slice is a copy, and will not change as the mesh is updated.
func (*Mesh) Smooth ¶
Smooth is similar to Blur, but it is less sensitive to differences in segment length.
func (*Mesh) SmoothSq ¶
SmoothSq is like Smooth, but it minimizes the sum of squared segment lengths rather than the sum of lengths directly. Thus, SmoothSq produces more even segments than Smooth.
func (*Mesh) Subdivide ¶
Subdivide uses Chaikin subdivision to add segments between every vertex.
This can only be applied to manifold meshes. This can be checked with m.Manifold().
func (*Mesh) VertexSlice ¶ added in v0.1.1
VertexSlice gets a snapshot of all the vertices currently in the mesh.
The result is a copy and is in no way connected to the mesh in memory.
type Ray ¶
A Ray is a line originating at a point and extending infinitely in some (positive) direction.
type RayCollision ¶
type RayCollision struct { // The amount of the ray direction to add to the ray // origin to hit the point in question. // // The scale should be non-negative. Scale float64 // The normal pointing outward from the outline at the // point of collision. Normal Coord }
RayCollision is a point where a ray intersects a 2-dimensional outline.
type Segment ¶
type Segment [2]Coord
A Segment is a 2-dimensional line segment.
The order determines the normal direction.
In particular, if the segments in a polygon go in the clockwise direction (assuming the y-axis faces down), then the normals face outwards from the polygon.
func (*Segment) CircleCollision ¶
CircleCollision checks if the circle intersects the segment s.
func (*Segment) FirstRayCollision ¶
func (s *Segment) FirstRayCollision(r *Ray) (RayCollision, bool)
FirstRayCollision gets the ray collision if there is one.
func (*Segment) Normal ¶
Normal computes the normal vector to the segment, facing outwards from the surface.
func (*Segment) RayCollisions ¶
func (s *Segment) RayCollisions(r *Ray, f func(RayCollision)) int
RayCollisions calls f (if non-nil) with a collision (if applicable) and returns the collisions count (0 or 1).
type Solid ¶
type Solid interface { // Contains must always return false outside of the // boundaries of the solid. Bounder Contains(c Coord) bool }
A Solid defines a two-dimensional shape.
For any given coordinate, the solid can check if the shape contains that coordinate.
All methods of a Solid are safe for concurrency.
func BitmapToSolid ¶
BitmapToSolid creates a Solid which is true at pixels where the bitmap is true, and false elsewhere.
func ScaleSolid ¶
ScaleSolid creates a new Solid that scales incoming coordinates c by 1/s. Thus, the new solid is s times larger.