泰森多边形图(`voronoi`)
泰森多边形图(voronoi)
04_三维与几何 5 张 MATLAB R2023b 100 mm 宽 @ 300 dpi
这个方法适合什么
按最近距离划分区域,每个多边形是一个点的服务范围。适合:充电站服务区划分、变电站供电分区、通信基站覆盖。
电气场景
1 充电站服务区划分

2 变电站供电分区

3 分布式光伏集群划分

4 配电终端覆盖分区

5 抢修驻点覆盖分区

代码
脚本 p4_3d_geom.m 中对应 voronoi 的一段,SEL 用于选择只跑某几个方法。
if any(SEL==10)
% ---- 10.1 充电站服务区划分 ----
try
rng(1001);
x = 1.5 + 17.0*rand(12,1); y = 1.2 + 11.0*rand(12,1);
pw = 60 + 200*rand(12,1); % 单站功率 / kW
f = ml_fig(PP,100,95);
ax = axes('Parent',f,'Position',[0.155 0.180 0.760 0.760]);
axes(ax);
vor2(x,y,C(1,:)); hold(ax,'on');
h1 = plot(ax,NaN,NaN,'-','Color',C(1,:),'LineWidth',0.55); % 图例代理:voronoi 句柄不能进 legend
h2 = scatter(ax,x,y,18+pw/14,pw,'filled','MarkerEdgeColor','w','LineWidth',0.4);
colormap(ax,parula);
xlabel(ax,ml_tx('东西向 <i>x</i> / km'));
ylabel(ml_tx('南北向 <i>y</i> / km'));
xlim(ax,[0 20]); ylim(ax,[0 16]);
lg = legend(ax,[h1 h2],ml_tx({'服务区边界','充电站(大小表示功率)'}),'Location','northeast');
ml_style_legend(lg,PP);
save_png(f,FIGD,'充电站服务区划分');
catch ME
fprintf('[FAIL] 10-1 %s\n', ME.message); close all
end
% ---- 10.2 变电站供电分区 ----
try
rng(1002);
x = 2 + 22*rand(9,1); y = 2 + 14*rand(9,1);
cap = [50 63 80 40 100 63 31 50 80];
f = ml_fig(PP,100,95);
ax = axes('Parent',f,'Position',[0.155 0.180 0.760 0.760]);
axes(ax);
vor2(x,y,C(4,:)); hold(ax,'on');
h1 = plot(ax,NaN,NaN,'-','Color',C(4,:),'LineWidth',0.55);
h2 = plot(ax,x,y,'s','MarkerSize',8,'MarkerFaceColor',C(1,:), ...
'MarkerEdgeColor','w','LineWidth',0.6);
for i = 1:numel(x)
text(ax,x(i)+0.6,y(i)+0.5,ml_tx(sprintf('%d MVA',cap(i))),'FontSize',7);
end
xlabel(ax,ml_tx('东西向 <i>x</i> / km'));
ylabel(ml_tx('南北向 <i>y</i> / km'));
xlim(ax,[0 26]); ylim(ax,[0 20.5]);
lg = legend(ax,[h1 h2],ml_tx({'供电分区边界','变电站'}),'Location','northeast');
ml_style_legend(lg,PP);
save_png(f,FIGD,'变电站供电分区');
catch ME
fprintf('[FAIL] 10-2 %s\n', ME.message); close all
end
% ---- 10.3 分布式光伏集群划分 ----
try
rng(1003);
x = 1 + 20*rand(14,1); y = 1 + 13*rand(14,1);
pv = 200 + 900*rand(14,1); % 装机 / kW
f = ml_fig(PP,100,95);
ax = axes('Parent',f,'Position',[0.155 0.180 0.760 0.760]);
axes(ax);
vor2(x,y,C(6,:)); hold(ax,'on');
h1 = plot(ax,NaN,NaN,'-','Color',C(6,:),'LineWidth',0.55);
h2 = scatter(ax,x,y,20+pv/30,pv,'filled','MarkerEdgeColor','w','LineWidth',0.4);
colormap(ax,parula);
xlabel(ax,ml_tx('东西向 <i>x</i> / km'));
ylabel(ml_tx('南北向 <i>y</i> / km'));
xlim(ax,[0 22]); ylim(ax,[0 17.5]);
lg = legend(ax,[h1 h2],ml_tx({'集群边界','分布式光伏(大小表示装机)'}),'Location','northeast');
ml_style_legend(lg,PP);
save_png(f,FIGD,'分布式光伏集群划分');
catch ME
fprintf('[FAIL] 10-3 %s\n', ME.message); close all
end
% ---- 10.4 配电终端覆盖分区 ----
try
rng(1004);
x = 1 + 21*rand(16,1); y = 1 + 12*rand(16,1);
f = ml_fig(PP,100,95);
ax = axes('Parent',f,'Position',[0.155 0.180 0.760 0.760]);
axes(ax);
vor2(x,y,C(5,:)); hold(ax,'on');
h1 = plot(ax,NaN,NaN,'-','Color',C(5,:),'LineWidth',0.55);
h2 = plot(ax,x,y,'o','MarkerSize',5.5,'MarkerFaceColor',C(2,:), ...
'MarkerEdgeColor','w','LineWidth',0.5);
xlabel(ax,ml_tx('东西向 <i>x</i> / km'));
ylabel(ml_tx('南北向 <i>y</i> / km'));
xlim(ax,[0 23]); ylim(ax,[0 16.5]);
lg = legend(ax,[h1 h2],ml_tx({'通信覆盖分区','配电终端'}),'Location','northeast');
ml_style_legend(lg,PP);
save_png(f,FIGD,'配电终端覆盖分区');
catch ME
fprintf('[FAIL] 10-4 %s\n', ME.message); close all
end
% ---- 10.5 抢修驻点覆盖分区 ----
try
rng(1005);
x = 2 + 19*rand(10,1); y = 1.5 + 11*rand(10,1);
tm = 12 + 22*rand(10,1); % 平均到达时间 / min
f = ml_fig(PP,100,95);
ax = axes('Parent',f,'Position',[0.155 0.180 0.760 0.760]);
axes(ax);
vor2(x,y,C(4,:)); hold(ax,'on');
h1 = plot(ax,NaN,NaN,'-','Color',C(4,:),'LineWidth',0.55);
h2 = scatter(ax,x,y,26+tm/1.4,tm,'filled','MarkerEdgeColor','w','LineWidth',0.4);
colormap(ax,parula);
xlabel(ax,ml_tx('东西向 <i>x</i> / km'));
ylabel(ml_tx('南北向 <i>y</i> / km'));
xlim(ax,[0 23]); ylim(ax,[0 17]);
lg = legend(ax,[h1 h2],ml_tx({'责任分区','抢修驻点(大小表示到达时间)'}),'Location','northeast');
ml_style_legend(lg,PP);
save_png(f,FIGD,'抢修驻点覆盖分区');
catch ME
fprintf('[FAIL] 10-5 %s\n', ME.message); close all
end
end
fprintf('\n=========== 04 三维与几何:全部完成 ===========\n');
%% ===================== 局部函数 =====================
function ax = ax3(f, withcb)
%AX3 三维坐标区:三维盒子的刻度与 zlabel 会溢出 Position 之外,
% 故左侧留到 0.205;带色条时再收窄,给色条刻度让位
if nargin < 2, withcb = false; end
if withcb
ax = axes('Parent',f,'Position',[0.205 0.180 0.590 0.760]);
else
ax = axes('Parent',f,'Position',[0.205 0.180 0.700 0.760]);
end
view(ax,[-37.5 30]);
box(ax,'on');
grid(ax,'off');
set(ax,'LineWidth',0.5,'Layer','top');
end
function cb = cb3(ax, PP)
%CB3 色条:手工定位,避免右缘刻度被裁、也不压住 x 轴末位刻度
cb = colorbar(ax);
cb.Position = [0.815 0.180 0.016 0.760];
cb.FontName = PP.FontEN;
cb.FontSize = 8;
cb.LineWidth = 0.5;
cb.TickDirection = 'in';
end
function h = box3(ax, x0,x1, y0,y1, z0,z1, col, fa)
%BOX3 由 6 个四边形构成的长方体
V = [x0 y0 z0; x1 y0 z0; x1 y1 z0; x0 y1 z0
x0 y0 z1; x1 y0 z1; x1 y1 z1; x0 y1 z1];
F = [1 2 3 4; 5 6 7 8; 1 2 6 5; 2 3 7 6; 3 4 8 7; 4 1 5 8];
h = patch(ax,'Vertices',V,'Faces',F,'FaceColor',col,'FaceAlpha',fa, ...
'EdgeColor',[0.25 0.25 0.25],'LineWidth',0.5);
end
function h = tri2(TRI, x, y, col)
%TRI2 triplot 包装:统一线色与线宽
h = triplot(TRI,x,y);
try
set(h,'Color',col,'LineWidth',0.55);
catch
end
end
function h = vor2(x, y, col)
%VOR2 voronoi 包装:统一线色与线宽
h = voronoi(x,y);
try
set(h,'Color',col,'LineWidth',0.55);
catch
end
end
function cm = cmap_blue()
%CMAP_BLUE 深蓝单色渐变
c1 = [0.60 0.74 0.88]; c2 = [0.180 0.373 0.639];
t = linspace(0,1,128)';
cm = [c1(1)+t*(c2(1)-c1(1)), c1(2)+t*(c2(2)-c1(2)), c1(3)+t*(c2(3)-c1(3))];
end
function p = save_png(f, FIGD, nm)
%SAVE_PNG 关网格 + 导出 300dpi PNG + 边距自检 + 关图
% ★ surf/mesh/trisurf 会在绘图时把网格重新打开,故必须在此处再关一次
ha = findall(f,'Type','axes');
for k = 1:numel(ha)
set(ha(k),'XGrid','off','YGrid','off','ZGrid','off');
end
p = fullfile(FIGD, ['04_三维与几何_' nm '261107.png']);
print(f, p, '-dpng', '-r300');
ml_chkpng(p, 8);
close(f);
end

浙公网安备 33010602011771号