Refactor: Переместил модуль shape
Я переместил модуль shape в подкаталог shape/ для лучшей организации кода. Изменил пути импорта в связанных файлах, чтобы соответствовать новому местоположению модуля. Удалил возвраты null из `getLocalBounds` и заменил их на обработку ошибок для улучшения надежности.
This commit is contained in:
95
src/models/shape/shape.zig
Normal file
95
src/models/shape/shape.zig
Normal file
@@ -0,0 +1,95 @@
|
||||
const std = @import("std");
|
||||
const Object = @import("../Object.zig");
|
||||
const Property = @import("../Property.zig").Property;
|
||||
const PropertyData = @import("../Property.zig").Data;
|
||||
const defaultCommonProperties = @import("../Property.zig").defaultCommonProperties;
|
||||
const basic_models = @import("../basic_models.zig");
|
||||
const line = @import("line.zig");
|
||||
const ellipse = @import("ellipse.zig");
|
||||
const broken = @import("broken.zig");
|
||||
const arc = @import("arc.zig");
|
||||
|
||||
pub const Rect = basic_models.Rect;
|
||||
|
||||
/// Создаёт объект с общими свойствами по умолчанию и специфичными для типа фигуры.
|
||||
pub fn createObject(allocator: std.mem.Allocator, shape_kind: Object.ShapeKind) !Object {
|
||||
var obj = try createWithCommonProperties(allocator, shape_kind);
|
||||
errdefer obj.deinit(allocator);
|
||||
switch (shape_kind) {
|
||||
.line => try line.appendDefaultShapeProperties(allocator, &obj),
|
||||
.ellipse => try ellipse.appendDefaultShapeProperties(allocator, &obj),
|
||||
.broken => try broken.appendDefaultShapeProperties(allocator, &obj),
|
||||
.arc => try arc.appendDefaultShapeProperties(allocator, &obj),
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
fn createWithCommonProperties(allocator: std.mem.Allocator, shape_kind: Object.ShapeKind) !Object {
|
||||
var properties_list = std.ArrayList(Property).empty;
|
||||
errdefer properties_list.deinit(allocator);
|
||||
for (defaultCommonProperties) |prop| try properties_list.append(allocator, prop);
|
||||
return .{
|
||||
.shape = shape_kind,
|
||||
.properties = properties_list,
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
fn requiredTagsFor(kind: Object.ShapeKind) []const std.meta.Tag(PropertyData) {
|
||||
return switch (kind) {
|
||||
.line => line.getRequiredTags(),
|
||||
.ellipse => ellipse.getRequiredTags(),
|
||||
.broken => broken.getRequiredTags(),
|
||||
.arc => arc.getRequiredTags(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Локальные границы объекта (AABB в своих координатах).
|
||||
pub fn getLocalBounds(obj: *const Object) !Rect {
|
||||
return switch (obj.shape) {
|
||||
.line => line.getLocalBounds(obj),
|
||||
.ellipse => ellipse.getLocalBounds(obj),
|
||||
.broken => broken.getLocalBounds(obj),
|
||||
.arc => arc.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 == 0);
|
||||
|
||||
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