Толщина круга
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Заливает круг в буфере (для скруглённых концов отрезка).
|
/// Заливает круг в буфере (для скруглённых концов отрезка).
|
||||||
|
|||||||
Reference in New Issue
Block a user