gg: improve small circle (r<20) looks

pull/13285/head
Delyan Angelov 2022-01-26 10:32:14 +02:00
parent 469282b20d
commit 0979723636
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 81 additions and 20 deletions

View File

@ -1,6 +1,5 @@
// 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.
module gg
import gx
@ -374,21 +373,35 @@ pub fn (ctx &Context) draw_square_filled(x f32, y f32, s f32, c gx.Color) {
//---- 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
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 {
sgl.load_pipeline(ctx.timage_pip)
}
nx := x * ctx.scale
ny := y * ctx.scale
nr := r * ctx.scale
nr := radius * ctx.scale
mut theta := f32(0)
mut xx := 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.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
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, r f32, c gx.Color) {
segments := int(math.ceil(2 * math.pi * r / gg.circle_segment_size))
ctx.draw_circle_with_segments(x, y, r, segments, c)
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, radius f32, c gx.Color) {
ctx.draw_circle_with_segments(x, y, radius, radius_to_segments(radius), c)
}
// 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 {
sgl.load_pipeline(ctx.timage_pip)
}
sgl.c4b(c.r, c.g, c.b, c.a)
nx := x * ctx.scale
ny := y * ctx.scale
nr := r * ctx.scale
nr := radius * ctx.scale
mut theta := f32(0)
mut xx := 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) {
$if macos {
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
}
}
@ -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
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 {
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))
tan_factor := math.tanf(theta)
rad_factor := math.cosf(theta)
mut xx := r * math.cosf(start_angle)
mut yy := r * math.sinf(start_angle)
mut xx := radius * math.cosf(start_angle)
mut yy := radius * math.sinf(start_angle)
sgl.begin_triangle_strip()
for i := 0; i < segments + 1; i++ {
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']
pub fn (ctx &Context) draw_circle(x f32, y f32, r f32, c gx.Color) {
ctx.draw_circle_filled(x, y, r, c)
pub fn (ctx &Context) draw_circle(x f32, y f32, radius f32, c gx.Color) {
ctx.draw_circle_filled(x, y, radius, c)
}
[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) {
ctx.draw_slice_empty(x, y, r, start_angle, end_angle, segments, c)
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, radius, start_angle, end_angle, segments, c)
}
[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) {
ctx.draw_slice_filled(x, y, r, start_angle, end_angle, segments, c)
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, radius, start_angle, end_angle, segments, c)
}
[deprecated: 'use draw_arc_empty() instead']

View File

@ -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()
}