Случайное дерево объектов
This commit is contained in:
@@ -40,3 +40,43 @@ pub fn addShape(self: *Document, parent: ?*Object, shape: Object.ShapeKind) !voi
|
||||
try self.addObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
fn randomShapeKind(rng: std.Random) Object.ShapeKind {
|
||||
const shapes_implemented = [_]Object.ShapeKind{ .line, .ellipse, .broken };
|
||||
return shapes_implemented[rng.intRangeLessThan(usize, 0, shapes_implemented.len)];
|
||||
}
|
||||
|
||||
/// Создаёт случайное количество фигур в документе (в т.ч. вложенных).
|
||||
/// Используются только реализованные типы: line, ellipse, broken.
|
||||
/// Ограничение max_total предотвращает экспоненциальный рост и переполнение.
|
||||
pub fn addRandomShapes(self: *Document, rng: std.Random) !void {
|
||||
const max_total: usize = 80;
|
||||
var total_count: usize = 0;
|
||||
|
||||
const n_root = rng.intRangeLessThan(usize, 1, 5);
|
||||
for (0..n_root) |_| {
|
||||
if (total_count >= max_total) break;
|
||||
try self.addShape(null, randomShapeKind(rng));
|
||||
total_count += 1;
|
||||
}
|
||||
|
||||
var stack = std.ArrayList(*Object).empty;
|
||||
defer stack.deinit(self.allocator);
|
||||
for (self.objects.items) |*obj| {
|
||||
try stack.append(self.allocator, obj);
|
||||
}
|
||||
while (stack.pop()) |obj| {
|
||||
if (total_count >= max_total) continue;
|
||||
const n_children = rng.intRangeLessThan(usize, 0, 2);
|
||||
const base_len = obj.children.items.len;
|
||||
for (0..n_children) |_| {
|
||||
if (total_count >= max_total) break;
|
||||
try self.addShape(obj, randomShapeKind(rng));
|
||||
total_count += 1;
|
||||
}
|
||||
// Пушим в стек только после всех append, чтобы не держать указатели при реаллокации obj.children
|
||||
for (obj.children.items[base_len..]) |*child| {
|
||||
try stack.append(self.allocator, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ pub fn createLine(allocator: std.mem.Allocator) !Object {
|
||||
pub fn createBrokenLine(allocator: std.mem.Allocator) !Object {
|
||||
var obj = try createWithCommonProperties(allocator, .broken);
|
||||
errdefer obj.deinit(allocator);
|
||||
var points = std.ArrayList(Point2).init(allocator);
|
||||
var points = std.ArrayList(Point2).empty;
|
||||
try points.appendSlice(allocator, &.{
|
||||
.{ .x = 0, .y = 0 },
|
||||
.{ .x = 80, .y = 0 },
|
||||
|
||||
Reference in New Issue
Block a user