Толщина круга

This commit is contained in:
2026-02-26 00:32:59 +03:00
parent f8731bde87
commit faf79367f6
2 changed files with 14 additions and 4 deletions

View File

@@ -6,14 +6,24 @@ const Color = @import("dvui").Color;
const Object = Document.Object; const Object = Document.Object;
const default_stroke: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 }; const default_stroke: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 };
const default_thickness: f32 = 2.0;
/// Эллипс с центром (0,0) и полуосями radii (обводка). /// Эллипс с центром (0,0) и полуосями radii (обводка с учётом thickness).
pub fn draw(ctx: *DrawContext, obj: *const Object) void { pub fn draw(ctx: *DrawContext, obj: *const Object) void {
const r_prop = obj.getProperty(.radii) orelse return; const r_prop = obj.getProperty(.radii) orelse return;
const rx = r_prop.radii.x; const rx = r_prop.radii.x;
const ry = r_prop.radii.y; const ry = r_prop.radii.y;
if (rx <= 0 or ry <= 0) return; if (rx <= 0 or ry <= 0) return;
const stroke = if (obj.getProperty(.stroke_rgba)) |s| pipeline.rgbaToPma(s.stroke_rgba) else default_stroke; const stroke = if (obj.getProperty(.stroke_rgba)) |s| pipeline.rgbaToPma(s.stroke_rgba) else default_stroke;
const thickness = if (obj.getProperty(.thickness)) |t| t.thickness else default_thickness;
// Полуширина обводки в нормализованных единицах (d = (x/rx)² + (y/ry)², граница при d=1).
const min_r = @min(rx, ry);
const half_norm = thickness / (2.0 * min_r);
const inner = @max(0.0, 1.0 - half_norm);
const outer = 1.0 + half_norm;
const d_inner_sq = inner * inner;
const d_outer_sq = outer * outer;
const corners = [_]struct { x: f32, y: f32 }{ const corners = [_]struct { x: f32, y: f32 }{
.{ .x = -rx, .y = -ry }, .{ .x = -rx, .y = -ry },
@@ -51,7 +61,7 @@ pub fn draw(ctx: *DrawContext, obj: *const Object) void {
const nx = loc.x / rx; const nx = loc.x / rx;
const ny = loc.y / ry; const ny = loc.y / ry;
const d = nx * nx + ny * ny; const d = nx * nx + ny * ny;
if (d >= 0.9 and d <= 1.1) { if (d >= d_inner_sq and d <= d_outer_sq) {
ctx.blendPixelAtBuffer(@intCast(bx), @intCast(by), stroke); ctx.blendPixelAtBuffer(@intCast(bx), @intCast(by), stroke);
} }
} }

View File

@@ -30,11 +30,11 @@ pub fn drawLine(ctx: *DrawContext, x0: f32, y0: f32, x1: f32, y1: f32, color: Co
drawLineInBuffer(ctx, b0.x, b0.y, b1.x, b1.y, color, thickness_px); drawLineInBuffer(ctx, b0.x, b0.y, b1.x, b1.y, color, thickness_px);
} }
/// Точка (px, py) лежит внутри/на круге с центром (cx, cy) и радиусом в квадрате r_sq. /// Точка (px, py) лежит строго внутри круга с центром (cx, cy) и радиусом в квадрате r_sq (граница не включается).
fn insideCircle(px: i32, py: i32, cx: i32, cy: i32, r_sq: i32) bool { fn insideCircle(px: i32, py: i32, cx: i32, cy: i32, r_sq: i32) bool {
const dx = px - cx; const dx = px - cx;
const dy = py - cy; const dy = py - cy;
return dx * dx + dy * dy <= r_sq; return dx * dx + dy * dy < r_sq;
} }
/// Заливает круг в буфере (для скруглённых концов отрезка). /// Заливает круг в буфере (для скруглённых концов отрезка).