Скачиваний:
0
Добавлен:
12.02.2026
Размер:
14 Кб
Скачать
%% Инициализация параметров
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)