Очистка
This commit is contained in:
@@ -4,7 +4,6 @@ const Property = @import("../Property.zig").Property;
|
|||||||
const PropertyData = @import("../Property.zig").Data;
|
const PropertyData = @import("../Property.zig").Data;
|
||||||
const Point2_f = @import("../basic_models.zig").Point2_f;
|
const Point2_f = @import("../basic_models.zig").Point2_f;
|
||||||
const Rect_f = @import("../basic_models.zig").Rect_f;
|
const Rect_f = @import("../basic_models.zig").Rect_f;
|
||||||
const common = @import("common.zig");
|
|
||||||
const shape_mod = @import("shape.zig");
|
const shape_mod = @import("shape.zig");
|
||||||
|
|
||||||
/// Свойства фигуры по умолчанию (добавляются к общим). points — слайс на статический массив.
|
/// Свойства фигуры по умолчанию (добавляются к общим). points — слайс на статический массив.
|
||||||
@@ -19,29 +18,3 @@ pub const default_shape_properties = [_]Property{
|
|||||||
.{ .data = .{ .filled = true } },
|
.{ .data = .{ .filled = true } },
|
||||||
.{ .data = .{ .fill_rgba = 0x000000FF } },
|
.{ .data = .{ .fill_rgba = 0x000000FF } },
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Теги обязательных свойств = теги из default_shape_properties.
|
|
||||||
pub const required_tags = common.tagsFromProperties(&default_shape_properties);
|
|
||||||
|
|
||||||
/// Локальные границы: AABB по точкам.
|
|
||||||
pub fn getLocalBounds(obj: *const Object) !Rect_f {
|
|
||||||
try shape_mod.ensure(obj, .broken);
|
|
||||||
const p = obj.getProperty(.points).?;
|
|
||||||
if (p.points.len == 0) return error.EmptyPoints;
|
|
||||||
var min_x: f32 = p.points[0].x;
|
|
||||||
var max_x: f32 = min_x;
|
|
||||||
var min_y: f32 = p.points[0].y;
|
|
||||||
var max_y: f32 = min_y;
|
|
||||||
for (p.points[1..]) |pt| {
|
|
||||||
min_x = @min(min_x, pt.x);
|
|
||||||
max_x = @max(max_x, pt.x);
|
|
||||||
min_y = @min(min_y, pt.y);
|
|
||||||
max_y = @max(max_y, pt.y);
|
|
||||||
}
|
|
||||||
return .{
|
|
||||||
.x = min_x,
|
|
||||||
.y = min_y,
|
|
||||||
.w = max_x - min_x,
|
|
||||||
.h = max_y - min_y,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Property = @import("../Property.zig").Property;
|
|
||||||
const PropertyData = @import("../Property.zig").Data;
|
|
||||||
|
|
||||||
/// Теги свойств — те же, что фигура добавляет к стандартным (из default_shape_properties).
|
|
||||||
pub fn tagsFromProperties(comptime props: []const Property) [props.len]std.meta.Tag(PropertyData) {
|
|
||||||
var result: [props.len]std.meta.Tag(PropertyData) = undefined;
|
|
||||||
for (props, &result) |p, *r| r.* = std.meta.activeTag(p.data);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ const std = @import("std");
|
|||||||
const Object = @import("../Object.zig");
|
const Object = @import("../Object.zig");
|
||||||
const Property = @import("../Property.zig").Property;
|
const Property = @import("../Property.zig").Property;
|
||||||
const Rect_f = @import("../basic_models.zig").Rect_f;
|
const Rect_f = @import("../basic_models.zig").Rect_f;
|
||||||
const common = @import("common.zig");
|
|
||||||
const shape_mod = @import("shape.zig");
|
const shape_mod = @import("shape.zig");
|
||||||
|
|
||||||
/// Свойства фигуры по умолчанию (добавляются к общим).
|
/// Свойства фигуры по умолчанию (добавляются к общим).
|
||||||
@@ -13,18 +12,3 @@ pub const default_shape_properties = [_]Property{
|
|||||||
.{ .data = .{ .filled = false } },
|
.{ .data = .{ .filled = false } },
|
||||||
.{ .data = .{ .fill_rgba = 0x000000FF } },
|
.{ .data = .{ .fill_rgba = 0x000000FF } },
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Теги обязательных свойств = теги из default_shape_properties.
|
|
||||||
pub const required_tags = common.tagsFromProperties(&default_shape_properties);
|
|
||||||
|
|
||||||
/// Локальные границы эллипса: [-radii.x, -radii.y] .. [radii.x, radii.y].
|
|
||||||
pub fn getLocalBounds(obj: *const Object) !Rect_f {
|
|
||||||
try shape_mod.ensure(obj, .ellipse);
|
|
||||||
const r = obj.getProperty(.radii).?;
|
|
||||||
return .{
|
|
||||||
.x = -r.radii.x,
|
|
||||||
.y = -r.radii.y,
|
|
||||||
.w = 2 * r.radii.x,
|
|
||||||
.h = 2 * r.radii.y,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,29 +2,9 @@ const std = @import("std");
|
|||||||
const Object = @import("../Object.zig");
|
const Object = @import("../Object.zig");
|
||||||
const Property = @import("../Property.zig").Property;
|
const Property = @import("../Property.zig").Property;
|
||||||
const Rect_f = @import("../basic_models.zig").Rect_f;
|
const Rect_f = @import("../basic_models.zig").Rect_f;
|
||||||
const common = @import("common.zig");
|
|
||||||
const shape_mod = @import("shape.zig");
|
const shape_mod = @import("shape.zig");
|
||||||
|
|
||||||
/// Свойства фигуры по умолчанию (добавляются к общим).
|
/// Свойства фигуры по умолчанию (добавляются к общим).
|
||||||
pub const default_shape_properties = [_]Property{
|
pub const default_shape_properties = [_]Property{
|
||||||
.{ .data = .{ .end_point = .{ .x = 100, .y = 200 } } },
|
.{ .data = .{ .end_point = .{ .x = 100, .y = 200 } } },
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Теги обязательных свойств = теги из default_shape_properties.
|
|
||||||
pub const required_tags = common.tagsFromProperties(&default_shape_properties);
|
|
||||||
|
|
||||||
/// Локальные границы: от (0,0) до end_point.
|
|
||||||
pub fn getLocalBounds(obj: *const Object) !Rect_f {
|
|
||||||
try shape_mod.ensure(obj, .line);
|
|
||||||
const ep = obj.getProperty(.end_point).?;
|
|
||||||
const min_x = @min(0, ep.end_point.x);
|
|
||||||
const max_x = @max(0, ep.end_point.x);
|
|
||||||
const min_y = @min(0, ep.end_point.y);
|
|
||||||
const max_y = @max(0, ep.end_point.y);
|
|
||||||
return .{
|
|
||||||
.x = min_x,
|
|
||||||
.y = min_y,
|
|
||||||
.w = max_x - min_x,
|
|
||||||
.h = max_y - min_y,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,61 +50,3 @@ fn createWithCommonProperties(allocator: std.mem.Allocator, shape_kind: Object.S
|
|||||||
.children = std.ArrayList(Object).empty,
|
.children = std.ArrayList(Object).empty,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Проверяет тип объекта и наличие обязательных свойств.
|
|
||||||
pub fn ensure(obj: *const Object, expected_kind: Object.ShapeKind) !void {
|
|
||||||
if (obj.shape != expected_kind) return error.WrongShapeKind;
|
|
||||||
const tags = requiredTagsFor(expected_kind);
|
|
||||||
for (tags) |tag| {
|
|
||||||
if (obj.getProperty(tag) == null) return error.MissingRequiredProperty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Обязательные теги = те свойства, которые фигура добавляет к общим (из default_shape_properties).
|
|
||||||
fn requiredTagsFor(kind: Object.ShapeKind) []const std.meta.Tag(PropertyData) {
|
|
||||||
return switch (kind) {
|
|
||||||
.line => &line.required_tags,
|
|
||||||
.ellipse => &ellipse.required_tags,
|
|
||||||
.broken => &broken.required_tags,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Локальные границы (AABB).
|
|
||||||
pub fn getLocalBounds(obj: *const Object) !Rect {
|
|
||||||
return switch (obj.shape) {
|
|
||||||
.line => line.getLocalBounds(obj),
|
|
||||||
.ellipse => ellipse.getLocalBounds(obj),
|
|
||||||
.broken => broken.getLocalBounds(obj),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test "getLocalBounds" {
|
|
||||||
const shape = @This();
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
||||||
defer _ = gpa.deinit();
|
|
||||||
const allocator = gpa.allocator();
|
|
||||||
|
|
||||||
var line_obj = try shape.createObject(allocator, .line);
|
|
||||||
defer line_obj.deinit(allocator);
|
|
||||||
const line_bounds = try getLocalBounds(&line_obj);
|
|
||||||
try std.testing.expect(line_bounds.x == 0);
|
|
||||||
try std.testing.expect(line_bounds.y == 0);
|
|
||||||
try std.testing.expect(line_bounds.w == 100);
|
|
||||||
try std.testing.expect(line_bounds.h == 200);
|
|
||||||
|
|
||||||
var ellipse_obj = try shape.createObject(allocator, .ellipse);
|
|
||||||
defer ellipse_obj.deinit(allocator);
|
|
||||||
const ellipse_bounds = try getLocalBounds(&ellipse_obj);
|
|
||||||
try std.testing.expect(ellipse_bounds.x == -50);
|
|
||||||
try std.testing.expect(ellipse_bounds.y == -50);
|
|
||||||
try std.testing.expect(ellipse_bounds.w == 100);
|
|
||||||
try std.testing.expect(ellipse_bounds.h == 100);
|
|
||||||
|
|
||||||
var broken_obj = try shape.createObject(allocator, .broken);
|
|
||||||
defer broken_obj.deinit(allocator);
|
|
||||||
const broken_bounds = try getLocalBounds(&broken_obj);
|
|
||||||
try std.testing.expect(broken_bounds.x == 0);
|
|
||||||
try std.testing.expect(broken_bounds.y == 0);
|
|
||||||
try std.testing.expect(broken_bounds.w == 80);
|
|
||||||
try std.testing.expect(broken_bounds.h == 60);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user