gg: improve small circle (r<20) looks
parent
469282b20d
commit
0979723636
|
@ -1,6 +1,5 @@
|
||||||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
||||||
|
|
||||||
module gg
|
module gg
|
||||||
|
|
||||||
import gx
|
import gx
|
||||||
|
@ -374,21 +373,35 @@ pub fn (ctx &Context) draw_square_filled(x f32, y f32, s f32, c gx.Color) {
|
||||||
|
|
||||||
//---- circle
|
//---- circle
|
||||||
|
|
||||||
const circle_segment_size = 8.35
|
// The table here is derived by looking at the result of vlib/gg/testdata/tweak_circles.vv
|
||||||
|
// and then choosing the most circle-ish drawing with the minimum number of segments.
|
||||||
|
const small_circle_segments = [0, 2, 4, 6, 6, 8, 8, 13, 10, 18, 12, 12, 10, 13, 16, 15, 16]!
|
||||||
|
|
||||||
|
[direct_array_access]
|
||||||
|
fn radius_to_segments(r f32) int {
|
||||||
|
if r < 30.0 {
|
||||||
|
ir := int(math.ceil(r))
|
||||||
|
if ir > 0 && ir < gg.small_circle_segments.len {
|
||||||
|
return gg.small_circle_segments[ir]
|
||||||
|
}
|
||||||
|
return ir
|
||||||
|
}
|
||||||
|
return int(math.ceil(2 * math.pi * r / 8))
|
||||||
|
}
|
||||||
|
|
||||||
// draw_circle_empty draws an empty circle
|
// draw_circle_empty draws an empty circle
|
||||||
pub fn (ctx &Context) draw_circle_empty(x f32, y f32, r f32, c gx.Color) {
|
pub fn (ctx &Context) draw_circle_empty(x f32, y f32, radius f32, c gx.Color) {
|
||||||
if c.a != 255 {
|
if c.a != 255 {
|
||||||
sgl.load_pipeline(ctx.timage_pip)
|
sgl.load_pipeline(ctx.timage_pip)
|
||||||
}
|
}
|
||||||
nx := x * ctx.scale
|
nx := x * ctx.scale
|
||||||
ny := y * ctx.scale
|
ny := y * ctx.scale
|
||||||
nr := r * ctx.scale
|
nr := radius * ctx.scale
|
||||||
mut theta := f32(0)
|
mut theta := f32(0)
|
||||||
mut xx := f32(0)
|
mut xx := f32(0)
|
||||||
mut yy := f32(0)
|
mut yy := f32(0)
|
||||||
|
|
||||||
segments := math.ceil(2 * math.pi * r / gg.circle_segment_size)
|
segments := radius_to_segments(radius)
|
||||||
|
|
||||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||||
sgl.begin_line_strip()
|
sgl.begin_line_strip()
|
||||||
|
@ -402,20 +415,19 @@ pub fn (ctx &Context) draw_circle_empty(x f32, y f32, r f32, c gx.Color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw_circle_filled draws a filled circle
|
// draw_circle_filled draws a filled circle
|
||||||
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, r f32, c gx.Color) {
|
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, radius f32, c gx.Color) {
|
||||||
segments := int(math.ceil(2 * math.pi * r / gg.circle_segment_size))
|
ctx.draw_circle_with_segments(x, y, radius, radius_to_segments(radius), c)
|
||||||
ctx.draw_circle_with_segments(x, y, r, segments, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw_circle_with_segments draws a circle with a specific number of segments (affects how smooth/round the circle is)
|
// draw_circle_with_segments draws a circle with a specific number of segments (affects how smooth/round the circle is)
|
||||||
pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, r f32, segments int, c gx.Color) {
|
pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, radius f32, segments int, c gx.Color) {
|
||||||
if c.a != 255 {
|
if c.a != 255 {
|
||||||
sgl.load_pipeline(ctx.timage_pip)
|
sgl.load_pipeline(ctx.timage_pip)
|
||||||
}
|
}
|
||||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||||
nx := x * ctx.scale
|
nx := x * ctx.scale
|
||||||
ny := y * ctx.scale
|
ny := y * ctx.scale
|
||||||
nr := r * ctx.scale
|
nr := radius * ctx.scale
|
||||||
mut theta := f32(0)
|
mut theta := f32(0)
|
||||||
mut xx := f32(0)
|
mut xx := f32(0)
|
||||||
mut yy := f32(0)
|
mut yy := f32(0)
|
||||||
|
@ -433,7 +445,7 @@ pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, r f32, segments in
|
||||||
pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) {
|
pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) {
|
||||||
$if macos {
|
$if macos {
|
||||||
if ctx.native_rendering {
|
if ctx.native_rendering {
|
||||||
C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), r, c)
|
C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), radius, c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,7 +500,7 @@ pub fn (ctx &Context) draw_slice_empty(x f32, y f32, outer_radius f32, start_ang
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw_slice_filled draws a filled circle slice/pie
|
// draw_slice_filled draws a filled circle slice/pie
|
||||||
pub fn (ctx &Context) draw_slice_filled(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
pub fn (ctx &Context) draw_slice_filled(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||||
if c.a != 255 {
|
if c.a != 255 {
|
||||||
sgl.load_pipeline(ctx.timage_pip)
|
sgl.load_pipeline(ctx.timage_pip)
|
||||||
}
|
}
|
||||||
|
@ -498,8 +510,8 @@ pub fn (ctx &Context) draw_slice_filled(x f32, y f32, r f32, start_angle f32, en
|
||||||
theta := f32(end_angle / f32(segments))
|
theta := f32(end_angle / f32(segments))
|
||||||
tan_factor := math.tanf(theta)
|
tan_factor := math.tanf(theta)
|
||||||
rad_factor := math.cosf(theta)
|
rad_factor := math.cosf(theta)
|
||||||
mut xx := r * math.cosf(start_angle)
|
mut xx := radius * math.cosf(start_angle)
|
||||||
mut yy := r * math.sinf(start_angle)
|
mut yy := radius * math.sinf(start_angle)
|
||||||
sgl.begin_triangle_strip()
|
sgl.begin_triangle_strip()
|
||||||
for i := 0; i < segments + 1; i++ {
|
for i := 0; i < segments + 1; i++ {
|
||||||
sgl.v2f(xx + nx, yy + ny)
|
sgl.v2f(xx + nx, yy + ny)
|
||||||
|
@ -764,18 +776,18 @@ pub fn (ctx &Context) draw_square(x f32, y f32, s f32, c gx.Color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
[deprecated: 'use draw_circle_filled() instead']
|
[deprecated: 'use draw_circle_filled() instead']
|
||||||
pub fn (ctx &Context) draw_circle(x f32, y f32, r f32, c gx.Color) {
|
pub fn (ctx &Context) draw_circle(x f32, y f32, radius f32, c gx.Color) {
|
||||||
ctx.draw_circle_filled(x, y, r, c)
|
ctx.draw_circle_filled(x, y, radius, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
[deprecated: 'use draw_slice_empty() instead']
|
[deprecated: 'use draw_slice_empty() instead']
|
||||||
pub fn (ctx &Context) draw_empty_slice(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
pub fn (ctx &Context) draw_empty_slice(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||||
ctx.draw_slice_empty(x, y, r, start_angle, end_angle, segments, c)
|
ctx.draw_slice_empty(x, y, radius, start_angle, end_angle, segments, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
[deprecated: 'use draw_slice_filled() instead']
|
[deprecated: 'use draw_slice_filled() instead']
|
||||||
pub fn (ctx &Context) draw_slice(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
pub fn (ctx &Context) draw_slice(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||||
ctx.draw_slice_filled(x, y, r, start_angle, end_angle, segments, c)
|
ctx.draw_slice_filled(x, y, radius, start_angle, end_angle, segments, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
[deprecated: 'use draw_arc_empty() instead']
|
[deprecated: 'use draw_arc_empty() instead']
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
import gg
|
||||||
|
import gx
|
||||||
|
|
||||||
|
struct App {
|
||||||
|
mut:
|
||||||
|
gg &gg.Context = 0
|
||||||
|
radius f64 = 10.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut app := &App{}
|
||||||
|
app.gg = gg.new_context(
|
||||||
|
bg_color: gx.white
|
||||||
|
width: 300
|
||||||
|
height: 300
|
||||||
|
window_title: 'Circles'
|
||||||
|
frame_fn: frame
|
||||||
|
event_fn: on_event
|
||||||
|
user_data: app
|
||||||
|
)
|
||||||
|
app.gg.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_event(e &gg.Event, mut app App) {
|
||||||
|
match e.typ {
|
||||||
|
.key_down {
|
||||||
|
match e.key_code {
|
||||||
|
.up {
|
||||||
|
app.radius += 1
|
||||||
|
}
|
||||||
|
.down {
|
||||||
|
app.radius -= 1
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame(mut app App) {
|
||||||
|
app.gg.begin()
|
||||||
|
app.gg.draw_circle_empty(150, 150, f32(app.radius), gx.blue)
|
||||||
|
app.gg.draw_text(20, 20, 'radius: $app.radius')
|
||||||
|
// app.gg.draw_text(20, 50, 'circle_segment_size: $circle_segment_size')
|
||||||
|
app.gg.end()
|
||||||
|
}
|
Loading…
Reference in New Issue