Скачиваний:
0
Добавлен:
12.02.2026
Размер:
13.69 Кб
Скачать
%% Инициализация параметров
clear; clc; close all;

% Параметры алгоритма
numBoids = 10; % Количество боидов
cohesionWeight = 1.0; % Вес сцепления
cohesionDist = 2.0; % Расстояние сцепления
separationWeight = 1.5; % Вес разделения
separationDist = 1.0; % Расстояние разделения
alignmentWeight = 1.0; % Вес выравнивания
alignmentDist = 1.5; % Расстояние выравнивания
minSpeed = 0.5; % Минимальная скорость
maxSpeed = 3; % Максимальная скорость

% Параметры симуляции
numIterations = 200; % Количество итераций
fieldSize = 10; % Размер поля
dt = 0.1; % Шаг времени

% Цвета для разных боидов
colors = lines(numBoids);

%% Инициализация боидов
% Начальные позиции (случайные в пределах поля)
positions = (rand(numBoids, 2) - 0.5) * fieldSize;

% Начальные скорости (случайные направления с фиксированной скоростью)
initialSpeed = (minSpeed + maxSpeed) / 2;
angles = 2 * pi * rand(numBoids, 1);
velocities = initialSpeed * [cos(angles), sin(angles)];

% Массивы для хранения траекторий
trajectories = cell(numBoids, 1);
for i = 1:numBoids
trajectories{i} = positions(i, :);
end

%% Создание графического окна
figure('Position', [100, 100, 1200, 500]);

% Подграфик 1: Анимация движения
subplot(1, 2, 1);
hAx1 = gca;
hold on;
axis equal;
xlim([-fieldSize, fieldSize]);
ylim([-fieldSize, fieldSize]);
grid on;
xlabel('X');
ylabel('Y');
title('Анимация движения боидов');

% Создание графических объектов для боидов
boidPlots = gobjects(numBoids, 1);
trajectoryPlots = gobjects(numBoids, 1);
velocityQuivers = gobjects(numBoids, 1);

for i = 1:numBoids
% Траектории
trajectoryPlots(i) = plot(NaN, NaN, '-', 'Color', colors(i, :), ...
'LineWidth', 0.5, 'DisplayName', sprintf('Боид %d', i));

% Векторы скорости
velocityQuivers(i) = quiver(positions(i,1), positions(i,2), ...
velocities(i,1), velocities(i,2), 'Color', colors(i, :), ...
'LineWidth', 2, 'MaxHeadSize', 2, 'AutoScale', 'off');

% Маркеры боидов
boidPlots(i) = plot(positions(i,1), positions(i,2), 'o', ...
'MarkerSize', 10, 'MarkerFaceColor', colors(i, :), ...
'MarkerEdgeColor', 'k', 'LineWidth', 1);
end

legend(trajectoryPlots, 'Location', 'bestoutside');
hold off;

% Подграфик 2: Визуализация влияния правил
subplot(1, 2, 2);
hAx2 = gca;
hold on;
axis equal;
xlim([-fieldSize, fieldSize]);
ylim([-fieldSize, fieldSize]);
grid on;
xlabel('X');
ylabel('Y');
title('Визуализация влияния правил');
hold off;

%% Главный цикл симуляции
for iteration = 1:numIterations
% Буферы для новых скоростей и позиций
newVelocities = zeros(size(velocities));

for i = 1:numBoids
% Поиск соседей в пределах максимального радиуса взаимодействия
maxInteractionDist = max([cohesionDist, separationDist, alignmentDist]);
dists = sqrt(sum((positions - positions(i, :)).^2, 2));
neighbors = find(dists > 0 & dists < maxInteractionDist);

% Инициализация векторов правил
separationVec = [0, 0];
cohesionVec = [0, 0];
alignmentVec = [0, 0];
numNeighbors = length(neighbors);

if numNeighbors > 0
% Вычисление разделения (отталкивание от близких соседей)
closeNeighbors = neighbors(dists(neighbors) < separationDist);
if ~isempty(closeNeighbors)
for j = 1:length(closeNeighbors)
neighborIdx = closeNeighbors(j);
diff = positions(i, :) - positions(neighborIdx, :);
dist = dists(neighborIdx);
if dist > 0
separationVec = separationVec + (diff / dist^2);
end
end
separationVec = separationVec / length(closeNeighbors);
end

% Вычисление сцепления (движение к центру масс соседей)
cohesionNeighbors = neighbors(dists(neighbors) < cohesionDist);
if ~isempty(cohesionNeighbors)
centerOfMass = mean(positions(cohesionNeighbors, :), 1);
cohesionVec = (centerOfMass - positions(i, :));
distToCenter = norm(cohesionVec);
if distToCenter > 0
cohesionVec = cohesionVec / distToCenter;
end
end

% Вычисление выравнивания (совпадение со средней скоростью соседей)
alignmentNeighbors = neighbors(dists(neighbors) < alignmentDist);
if ~isempty(alignmentNeighbors)
avgVelocity = mean(velocities(alignmentNeighbors, :), 1);
alignmentVec = avgVelocity - velocities(i, :);
alignMag = norm(alignmentVec);
if alignMag > 0
alignmentVec = alignmentVec / alignMag;
end
end
end

% Применение весов к правилам
separationVec = separationWeight * separationVec;
cohesionVec = cohesionWeight * cohesionVec;
alignmentVec = alignmentWeight * alignmentVec;

% Вычисление новой скорости
acceleration = separationVec + cohesionVec + alignmentVec;

% Нормализация ускорения
accelMag = norm(acceleration);
if accelMag > 0
acceleration = acceleration / accelMag;
end

% Обновление скорости
newVelocities(i, :) = velocities(i, :) + acceleration * dt;

% Ограничение скорости
speed = norm(newVelocities(i, :));
if speed > maxSpeed
newVelocities(i, :) = (newVelocities(i, :) / speed) * maxSpeed;
elseif speed < minSpeed
newVelocities(i, :) = (newVelocities(i, :) / max(speed, 0.001)) * minSpeed;
end

% Обновление траектории
trajectories{i} = [trajectories{i}; positions(i, :)];
end

% Обновление позиций
velocities = newVelocities;
positions = positions + velocities * dt;

% Обработка границ поля (отражение от стен)
for i = 1:numBoids
if abs(positions(i, 1)) > fieldSize
velocities(i, 1) = -velocities(i, 1);
positions(i, 1) = sign(positions(i, 1)) * fieldSize * 0.99;
end
if abs(positions(i, 2)) > fieldSize
velocities(i, 2) = -velocities(i, 2);
positions(i, 2) = sign(positions(i, 2)) * fieldSize * 0.99;
end
end

%% Обновление графики
% Обновление анимации
subplot(1, 2, 1);
for i = 1:numBoids
% Обновление маркера боида
set(boidPlots(i), 'XData', positions(i, 1), 'YData', positions(i, 2));

% Обновление траектории
set(trajectoryPlots(i), 'XData', trajectories{i}(:,1), ...
'YData', trajectories{i}(:,2));

% Обновление вектора скорости
set(velocityQuivers(i), 'XData', positions(i, 1), ...
'YData', positions(i, 2), ...
'UData', velocities(i, 1), 'VData', velocities(i, 2));
end

% Обновление визуализации влияния правил
subplot(1, 2, 2);
cla;
hold on;
axis equal;
xlim([-fieldSize, fieldSize]);
ylim([-fieldSize, fieldSize]);
grid on;
title(sprintf('Визуализация влияния правил (Итерация: %d)', iteration));

% Отображение зон влияния для первого боида
i = 1; % Анализируем первого боида

% Рисуем круги зон влияния
theta = linspace(0, 2*pi, 100);

% Зона разделения (красная)
xSep = separationDist * cos(theta) + positions(i, 1);
ySep = separationDist * sin(theta) + positions(i, 2);
fill(xSep, ySep, [1, 0.8, 0.8], 'EdgeColor', [1, 0.5, 0.5], ...
'LineWidth', 1, 'FaceAlpha', 0.3);
text(positions(i,1), positions(i,2)+separationDist*1.1, ...
'Разделение', 'Color', [1, 0, 0], 'HorizontalAlignment', 'center');

% Зона выравнивания (синяя)
xAlign = alignmentDist * cos(theta) + positions(i, 1);
yAlign = alignmentDist * sin(theta) + positions(i, 2);
plot(xAlign, yAlign, 'b--', 'LineWidth', 1);
text(positions(i,1), positions(i,2)+alignmentDist*1.1, ...
'Выравнивание', 'Color', [0, 0, 1], 'HorizontalAlignment', 'center');

% Зона сцепления (зелёная)
xCoh = cohesionDist * cos(theta) + positions(i, 1);
yCoh = cohesionDist * sin(theta) + positions(i, 2);
plot(xCoh, yCoh, 'g--', 'LineWidth', 1);
text(positions(i,1), positions(i,2)+cohesionDist*1.1, ...
'Сцепление', 'Color', [0, 0.7, 0], 'HorizontalAlignment', 'center');

% Поиск соседей в разных зонах
dists = sqrt(sum((positions - positions(i, :)).^2, 2));
separationNeighbors = find(dists > 0 & dists < separationDist);
alignmentNeighbors = find(dists > 0 & dists < alignmentDist);
cohesionNeighbors = find(dists > 0 & dists < cohesionDist);

% Отображение боидов
for b = 1:numBoids
color = colors(b, :);
markerSize = 8;

if b == i
color = 'k'; % Выделяем анализируемого боида
markerSize = 12;
elseif ismember(b, separationNeighbors)
color = [1, 0, 0]; % Красный для соседей в зоне разделения
elseif ismember(b, alignmentNeighbors)
color = [0, 0, 1]; % Синий для соседей в зоне выравнивания
elseif ismember(b, cohesionNeighbors)
color = [0, 0.7, 0]; % Зелёный для соседей в зоне сцепления
end

plot(positions(b, 1), positions(b, 2), 'o', ...
'MarkerSize', markerSize, 'MarkerFaceColor', color, ...
'MarkerEdgeColor', 'k', 'LineWidth', 1);

% Векторы скорости
quiver(positions(b,1), positions(b,2), ...
velocities(b,1), velocities(b,2), 0.5, ...
'Color', colors(b, :), 'LineWidth', 1.5, 'MaxHeadSize', 1);
end

% Отображение центра масс для зоны сцепления
if ~isempty(cohesionNeighbors)
centerOfMass = mean(positions(cohesionNeighbors, :), 1);
plot(centerOfMass(1), centerOfMass(2), 'gx', ...
'MarkerSize', 15, 'LineWidth', 2);
plot([positions(i,1), centerOfMass(1)], ...
[positions(i,2), centerOfMass(2)], 'g-', 'LineWidth', 2);
end

hold off;

% Пауза для анимации
pause(0.05);

% Обновление заголовка первого графика
subplot(1, 2, 1);
title(sprintf('Движение боидов (Итерация: %d/%d)', iteration, numIterations));
end

%% Отображение итоговой статистики
fprintf('=== СТАТИСТИКА СИМУЛЯЦИИ ===\n');
fprintf('Количество боидов: %d\n', numBoids);
fprintf('Количество итераций: %d\n', numIterations);
fprintf('Параметры алгоритма:\n');
fprintf(' Вес сцепления: %.2f\n', cohesionWeight);
fprintf(' Вес разделения: %.2f\n', separationWeight);
fprintf(' Вес выравнивания: %.2f\n', alignmentWeight);
fprintf(' Скорости: min=%.2f, max=%.2f\n', minSpeed, maxSpeed);

% Вычисление средней скорости
avgSpeed = mean(sqrt(sum(velocities.^2, 2)));
fprintf('Средняя конечная скорость: %.3f\n', avgSpeed);

% Вычисление степени когерентности движения
if numBoids > 1
normalizedVelocities = velocities ./ sqrt(sum(velocities.^2, 2));
coherence = abs(sum(normalizedVelocities(:,1)) + 1i*sum(normalizedVelocities(:,2))) / numBoids;
fprintf('Степень когерентности движения: %.3f (1 = идеально согласовано)\n', coherence);
end
Соседние файлы в папке Движение стай (Boids)