mirror of
https://github.com/mum4k/termdash.git
synced 2025-05-08 19:29:25 +08:00
Bugfix - correctly filling partial circles.
This commit is contained in:
parent
286731aa62
commit
9d2a639791
@ -22,7 +22,7 @@ import (
|
||||
|
||||
"github.com/mum4k/termdash/canvas/braille"
|
||||
"github.com/mum4k/termdash/cell"
|
||||
"github.com/mum4k/termdash/numbers"
|
||||
"github.com/mum4k/termdash/trig"
|
||||
)
|
||||
|
||||
// BrailleCircleOption is used to provide options to BrailleCircle.
|
||||
@ -55,16 +55,6 @@ func (opts *brailleCircleOptions) validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
min = 0
|
||||
max = 360
|
||||
)
|
||||
if got := opts.startDegree; got < min || got > max {
|
||||
return fmt.Errorf("invalid starting degree for the arc %d, must be in range %d <= degree <= %d", got, min, max)
|
||||
}
|
||||
if got := opts.endDegree; got < min || got > max {
|
||||
return fmt.Errorf("invalid ending degree for the arc %d, must be in range %d <= degree <= %d", got, min, max)
|
||||
}
|
||||
if opts.startDegree == opts.endDegree {
|
||||
return fmt.Errorf("invalid degree range, start %d and end %d cannot be equal", opts.startDegree, opts.endDegree)
|
||||
}
|
||||
@ -79,7 +69,7 @@ func (o brailleCircleOption) set(opts *brailleCircleOptions) {
|
||||
o(opts)
|
||||
}
|
||||
|
||||
// BrailleCircleCellOpts sets options on the cells that contain the line.
|
||||
// BrailleCircleCellOpts sets options on the cells that contain the circle.
|
||||
// Cell options on a braille canvas can only be set on the entire cell, not per
|
||||
// pixel.
|
||||
func BrailleCircleCellOpts(cOpts ...cell.Option) BrailleCircleOption {
|
||||
@ -120,12 +110,12 @@ func BrailleCircleClearPixels() BrailleCircleOption {
|
||||
// BrailleCircle draws an approximated circle with the specified mid point and radius.
|
||||
// The mid point must be a valid pixel within the canvas.
|
||||
// All the points that form the circle must fit into the canvas.
|
||||
// The smallest valid radius is one.
|
||||
// The smallest valid radius is two.
|
||||
func BrailleCircle(bc *braille.Canvas, mid image.Point, radius int, opts ...BrailleCircleOption) error {
|
||||
if ar := bc.Area(); !mid.In(ar) {
|
||||
return fmt.Errorf("unable to draw circle with mid point %v which is outside of the braille canvas area %v", mid, ar)
|
||||
}
|
||||
if min := 1; radius < min {
|
||||
if min := 2; radius < min {
|
||||
return fmt.Errorf("unable to draw circle with radius %d, must be in range %d <= radius", radius, min)
|
||||
}
|
||||
|
||||
@ -140,34 +130,35 @@ func BrailleCircle(bc *braille.Canvas, mid image.Point, radius int, opts ...Brai
|
||||
|
||||
points := circlePoints(mid, radius)
|
||||
if opt.arcOnly {
|
||||
points = arcPoints(points, mid, radius, opt)
|
||||
f, err := trig.FilterByAngle(points, mid, opt.startDegree, opt.endDegree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
points = f
|
||||
if opt.filled && (opt.startDegree != 0 || opt.endDegree != 360) {
|
||||
points = append(points, openingPoints(mid, radius, opt)...)
|
||||
}
|
||||
}
|
||||
if err := drawPoints(bc, points, opt); err != nil {
|
||||
return fmt.Errorf("failed to draw circle with mid:%v, radius:%d, start:%d degrees, end:%d degrees: %v", mid, radius, opt.startDegree, opt.endDegree, err)
|
||||
}
|
||||
|
||||
if opt.filled {
|
||||
lineOpts := []BrailleLineOption{
|
||||
BrailleLineCellOpts(opt.cellOpts...),
|
||||
}
|
||||
if opt.pixelChange == braillePixelChangeClear {
|
||||
lineOpts = append(lineOpts, BrailleLineClearPixels())
|
||||
}
|
||||
|
||||
for _, pts := range groupByY(points) {
|
||||
if err := BrailleLine(bc, pts[0], pts[1], lineOpts...); err != nil {
|
||||
return fmt.Errorf("failed to fill circle with mid:%v, start:%d degrees end:%d degrees, BrailleLine => %v", mid, opt.startDegree, opt.endDegree, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return fillCircle(bc, points, mid, radius, opt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// drawPoints draws the points onto the canvas.
|
||||
func drawPoints(bc *braille.Canvas, points []image.Point, opt *brailleCircleOptions) error {
|
||||
for _, p := range points {
|
||||
switch opt.pixelChange {
|
||||
case braillePixelChangeSet:
|
||||
if err := bc.SetPixel(p, opt.cellOpts...); err != nil {
|
||||
return fmt.Errorf("failed to draw circle with mid:%v, start:%d degrees end:%d degrees, SetPixel => %v", mid, opt.startDegree, opt.endDegree, err)
|
||||
return fmt.Errorf("SetPixel => %v", err)
|
||||
}
|
||||
case braillePixelChangeClear:
|
||||
if err := bc.ClearPixel(p, opt.cellOpts...); err != nil {
|
||||
return fmt.Errorf("failed to erase circle with mid:%v, start:%d degrees end:%d degrees, ClearPixel => %v", mid, opt.startDegree, opt.endDegree, err)
|
||||
return fmt.Errorf("ClearPixel => %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
@ -175,96 +166,57 @@ func BrailleCircle(bc *braille.Canvas, mid image.Point, radius int, opts ...Brai
|
||||
return nil
|
||||
}
|
||||
|
||||
// groupByY groups the points by their Y coordinate.
|
||||
// Creates a map of Y coordinates to two points on that Y row.
|
||||
// The points are the point with the smallest and the largest X coordinate.
|
||||
// This is used to fill a circle or an arc - by drawing lines between these
|
||||
// points.
|
||||
func groupByY(points []image.Point) map[int][]image.Point {
|
||||
groupped := map[int][]int{} // maps y -> x
|
||||
for _, p := range points {
|
||||
groupped[p.Y] = append(groupped[p.Y], p.X)
|
||||
// fillCircle fills a circle that consists of the provided point and has the
|
||||
// mid point and radius.
|
||||
func fillCircle(bc *braille.Canvas, points []image.Point, mid image.Point, radius int, opt *brailleCircleOptions) error {
|
||||
lineOpts := []BrailleLineOption{
|
||||
BrailleLineCellOpts(opt.cellOpts...),
|
||||
}
|
||||
fillOpts := []BrailleFillOption{
|
||||
BrailleFillCellOpts(opt.cellOpts...),
|
||||
}
|
||||
if opt.pixelChange == braillePixelChangeClear {
|
||||
lineOpts = append(lineOpts, BrailleLineClearPixels())
|
||||
fillOpts = append(fillOpts, BrailleFillClearPixels())
|
||||
}
|
||||
|
||||
res := map[int][]image.Point{}
|
||||
for y, pts := range groupped {
|
||||
min, max := numbers.MinMaxInts(pts)
|
||||
res[y] = []image.Point{
|
||||
{min, y},
|
||||
{max, y},
|
||||
// Determine a fill point that should be inside of the circle sector.
|
||||
midA, err := trig.RangeMid(opt.startDegree, opt.endDegree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fp := trig.CirclePointAtAngle(midA, mid, radius-1)
|
||||
|
||||
// Ensure the fill point falls inside the circle.
|
||||
// If drawing a partial circle, it must also fall within points belonging
|
||||
// to the opening.
|
||||
// This might not be true if drawing a partial circle and the arc is very
|
||||
// small.
|
||||
shape := points
|
||||
if opt.arcOnly {
|
||||
startP := trig.CirclePointAtAngle(opt.startDegree, mid, radius-1)
|
||||
endP := trig.CirclePointAtAngle(opt.endDegree, mid, radius-1)
|
||||
shape = append(shape, startP, endP)
|
||||
}
|
||||
if trig.PointIsIn(fp, shape) {
|
||||
if err := BrailleFill(bc, fp, points, fillOpts...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := BrailleLine(bc, mid, fp, lineOpts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return res
|
||||
return nil
|
||||
}
|
||||
|
||||
// filterByAngle filters the provided points, returning only those that fall
|
||||
// within the starting and the ending angle.
|
||||
func filterByAngle(points []image.Point, mid image.Point, start, end int) []image.Point {
|
||||
var res []image.Point
|
||||
for _, p := range points {
|
||||
angle := numbers.CircleAngleAtPoint(p, mid)
|
||||
|
||||
// Edge case, this might mean 0 or 360.
|
||||
// Decide based on where we are starting.
|
||||
if angle == 0 && start > 0 {
|
||||
angle = 360
|
||||
}
|
||||
|
||||
ranges := toDegreeRanges(start, end)
|
||||
for _, r := range ranges {
|
||||
if r.in(angle) {
|
||||
res = append(res, p)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// intRange represents a range of integers.
|
||||
type intRange struct {
|
||||
start int
|
||||
end int
|
||||
}
|
||||
|
||||
// in asserts whether the integer is in the range.
|
||||
func (ir *intRange) in(i int) bool {
|
||||
return i >= ir.start && i <= ir.end
|
||||
}
|
||||
|
||||
// toDegreeRanges converts the start and end angles in degrees into ranges of
|
||||
// angles. Solves cases where the 0/360 point falls within the range.
|
||||
func toDegreeRanges(start, end int) []*intRange {
|
||||
if start == 360 && end == 0 {
|
||||
start, end = end, start
|
||||
}
|
||||
|
||||
if start < end {
|
||||
return []*intRange{
|
||||
{start, end},
|
||||
}
|
||||
}
|
||||
|
||||
// The range is crossing the 0/360 degree point.
|
||||
// Break it into multiple ranges.
|
||||
return []*intRange{
|
||||
{start, 360},
|
||||
{0, end},
|
||||
}
|
||||
}
|
||||
|
||||
// arcPoints returns only those points that belong to an incomplete circle.
|
||||
func arcPoints(points []image.Point, mid image.Point, radius int, opt *brailleCircleOptions) []image.Point {
|
||||
points = filterByAngle(points, mid, opt.startDegree, opt.endDegree)
|
||||
|
||||
if opt.filled {
|
||||
// If we are filling the angle - add points representing the lines from
|
||||
// the mid point to the start and end point of the arc.
|
||||
startP := numbers.CirclePointAtAngle(opt.startDegree, mid, radius)
|
||||
endP := numbers.CirclePointAtAngle(opt.endDegree, mid, radius)
|
||||
points = append(points, brailleLinePoints(mid, startP)...)
|
||||
points = append(points, brailleLinePoints(mid, endP)...)
|
||||
}
|
||||
// openingPoints returns points on the lines from the mid point to the circle
|
||||
// opening when drawing an incomplete circle.
|
||||
func openingPoints(mid image.Point, radius int, opt *brailleCircleOptions) []image.Point {
|
||||
var points []image.Point
|
||||
startP := trig.CirclePointAtAngle(opt.startDegree, mid, radius)
|
||||
endP := trig.CirclePointAtAngle(opt.endDegree, mid, radius)
|
||||
points = append(points, brailleLinePoints(mid, startP)...)
|
||||
points = append(points, brailleLinePoints(mid, endP)...)
|
||||
return points
|
||||
}
|
||||
|
||||
|
@ -137,61 +137,6 @@ func TestBrailleCircle(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
desc: "draws circle with radius of one",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
mid: image.Point{1, 1},
|
||||
radius: 1,
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 0})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 1})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 1})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 2})
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 2})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 2})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "sets cell options",
|
||||
canvas: image.Rect(0, 0, 2, 2),
|
||||
mid: image.Point{1, 1},
|
||||
radius: 1,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleCellOpts(cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorGreen)),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
opts := []cell.Option{
|
||||
cell.FgColor(cell.ColorRed),
|
||||
cell.BgColor(cell.ColorGreen),
|
||||
}
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 0}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 0}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 0}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 1}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 1}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 2}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 2}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 2}, opts...)
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "empty circle with radius of two",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
@ -222,6 +167,43 @@ func TestBrailleCircle(t *testing.T) {
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "sets cell options",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
mid: image.Point{2, 2},
|
||||
radius: 2,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleCellOpts(cell.FgColor(cell.ColorRed), cell.BgColor(cell.ColorGreen)),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
opts := []cell.Option{
|
||||
cell.FgColor(cell.ColorRed),
|
||||
cell.BgColor(cell.ColorGreen),
|
||||
}
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 0}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 0}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 0}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 1}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 1}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 2}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 2}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 3}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 3}, opts...)
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 4}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 4}, opts...)
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 4}, opts...)
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "empty circle with radius of two, specified as arc",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
@ -344,13 +326,13 @@ func TestBrailleCircle(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "clears pixels by drawing a smaller filled on circle",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
mid: image.Point{2, 2},
|
||||
radius: 1,
|
||||
desc: "clears pixels by drawing a smaller filled circle",
|
||||
canvas: image.Rect(0, 0, 4, 4),
|
||||
mid: image.Point{3, 3},
|
||||
radius: 2,
|
||||
prepare: func(bc *braille.Canvas) error {
|
||||
// Draw a filled circle so we can erase part of it.
|
||||
return BrailleCircle(bc, image.Point{2, 2}, 2, BrailleCircleFilled())
|
||||
return BrailleCircle(bc, image.Point{3, 3}, 3, BrailleCircleFilled())
|
||||
},
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleClearPixels(),
|
||||
@ -360,62 +342,22 @@ func TestBrailleCircle(t *testing.T) {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 0})
|
||||
mustBrailleLine(bc, image.Point{1, 0}, image.Point{5, 0})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 1})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 1})
|
||||
mustBrailleLine(bc, image.Point{0, 1}, image.Point{1, 1})
|
||||
mustBrailleLine(bc, image.Point{5, 1}, image.Point{6, 1})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 2})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 2})
|
||||
mustBrailleLine(bc, image.Point{0, 2}, image.Point{0, 2})
|
||||
mustBrailleLine(bc, image.Point{6, 2}, image.Point{6, 2})
|
||||
mustBrailleLine(bc, image.Point{0, 3}, image.Point{0, 3})
|
||||
mustBrailleLine(bc, image.Point{6, 3}, image.Point{6, 3})
|
||||
mustBrailleLine(bc, image.Point{0, 4}, image.Point{0, 4})
|
||||
mustBrailleLine(bc, image.Point{6, 4}, image.Point{6, 4})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 3})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 3})
|
||||
mustBrailleLine(bc, image.Point{0, 5}, image.Point{1, 5})
|
||||
mustBrailleLine(bc, image.Point{5, 5}, image.Point{6, 5})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 4})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "clears pixels by drawing a smaller empty on circle",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
mid: image.Point{2, 2},
|
||||
radius: 1,
|
||||
prepare: func(bc *braille.Canvas) error {
|
||||
// Draw a filled circle so we can erase part of it.
|
||||
return BrailleCircle(bc, image.Point{2, 2}, 2, BrailleCircleFilled())
|
||||
},
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleClearPixels(),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
// The middle remains.
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 2})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 0})
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 0})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 1})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 1})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 2})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 2})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{0, 3})
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 3})
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{1, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 4})
|
||||
mustBrailleLine(bc, image.Point{1, 6}, image.Point{5, 6})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
@ -444,6 +386,146 @@ func TestBrailleCircle(t *testing.T) {
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle that is almost full",
|
||||
canvas: image.Rect(0, 0, 5, 5),
|
||||
mid: image.Point{4, 4},
|
||||
radius: 4,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(150, 90),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
mustBrailleLine(bc, image.Point{4, 0}, image.Point{6, 0})
|
||||
mustBrailleLine(bc, image.Point{4, 1}, image.Point{7, 1})
|
||||
|
||||
mustBrailleLine(bc, image.Point{0, 2}, image.Point{1, 2})
|
||||
mustBrailleLine(bc, image.Point{4, 2}, image.Point{8, 2})
|
||||
|
||||
mustBrailleLine(bc, image.Point{0, 3}, image.Point{8, 3})
|
||||
mustBrailleLine(bc, image.Point{0, 4}, image.Point{8, 4})
|
||||
mustBrailleLine(bc, image.Point{0, 5}, image.Point{8, 5})
|
||||
mustBrailleLine(bc, image.Point{0, 6}, image.Point{8, 6})
|
||||
|
||||
mustBrailleLine(bc, image.Point{1, 7}, image.Point{7, 7})
|
||||
mustBrailleLine(bc, image.Point{2, 8}, image.Point{6, 8})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle in the first quadrant that is very small",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
mid: image.Point{2, 2},
|
||||
radius: 2,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(30, 90),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
mustBrailleLine(bc, image.Point{2, 0}, image.Point{3, 0})
|
||||
mustBrailleLine(bc, image.Point{2, 1}, image.Point{4, 1})
|
||||
mustBrailleLine(bc, image.Point{2, 2}, image.Point{3, 2})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle in the third quadrant, 36 degree arc",
|
||||
canvas: image.Rect(0, 0, 4, 4),
|
||||
mid: image.Point{4, 4},
|
||||
radius: 3,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(194, 230),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
mustBrailleLine(bc, image.Point{3, 4}, image.Point{4, 4})
|
||||
mustBrailleLine(bc, image.Point{1, 5}, image.Point{3, 5})
|
||||
mustBrailleLine(bc, image.Point{1, 6}, image.Point{2, 6})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle in the third quadrant, four degree arc",
|
||||
canvas: image.Rect(0, 0, 4, 4),
|
||||
mid: image.Point{4, 4},
|
||||
radius: 3,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(226, 230),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{4, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{3, 5})
|
||||
testbraille.MustSetPixel(bc, image.Point{2, 6})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle in the first quadrant, four degree arc",
|
||||
canvas: image.Rect(0, 0, 6, 6),
|
||||
mid: image.Point{6, 6},
|
||||
radius: 5,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(66, 70),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
testbraille.MustSetPixel(bc, image.Point{8, 1})
|
||||
testbraille.MustSetPixel(bc, image.Point{8, 2})
|
||||
testbraille.MustSetPixel(bc, image.Point{7, 3})
|
||||
testbraille.MustSetPixel(bc, image.Point{7, 4})
|
||||
testbraille.MustSetPixel(bc, image.Point{6, 5})
|
||||
testbraille.MustSetPixel(bc, image.Point{6, 6})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled partial circle in the third quadrant, 72 degree arc",
|
||||
canvas: image.Rect(0, 0, 4, 4),
|
||||
mid: image.Point{4, 4},
|
||||
radius: 3,
|
||||
opts: []BrailleCircleOption{
|
||||
BrailleCircleFilled(),
|
||||
BrailleCircleArcOnly(158, 230),
|
||||
},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
bc := testbraille.MustNew(ft.Area())
|
||||
|
||||
mustBrailleLine(bc, image.Point{1, 3}, image.Point{2, 3})
|
||||
mustBrailleLine(bc, image.Point{1, 4}, image.Point{4, 4})
|
||||
mustBrailleLine(bc, image.Point{1, 5}, image.Point{3, 5})
|
||||
mustBrailleLine(bc, image.Point{1, 6}, image.Point{2, 6})
|
||||
|
||||
testbraille.MustApply(bc, ft)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "filled circle with radius of two and cell options",
|
||||
canvas: image.Rect(0, 0, 3, 3),
|
||||
|
Loading…
x
Reference in New Issue
Block a user