012_图例

1. 图例是图表中对内容区元素的注释、用不同形状、颜色、文字等来标示不同数据列, 通过点击对应数据列的标记, 可以显示或隐藏该数据列。图例虽然不是图表中的主要信息、却是了解图表信息的钥匙。

2. 图例布局

2.1. 图例一般放在图表的右上角、也可以放在图表的底部、同一页面中的所有图例位置保持一致, 可以横排对齐也可以纵排对齐。还要综合考虑整体的图表空间是适合哪种摆放方式。

2.2. legend.type, 图例的类型。可选值: 'plain'普通图例, 缺省就是普通图例; 'scroll'可滚动翻页的图例, 当图例数量较多时可以使用。string类型。

2.3. legend.id , 组件ID。默认不指定。指定则可用于在option或者API中引用组件。string类型。

2.4. legend.show = true, 是否显示图例。boolean类型。

2.5. legend.left = 'auto', 图例组件离容器左侧的距离。left的值可以是像20这样的具体像素值, 可以是像'20%'这样相对于容器高宽的百分比, 也可以是'left', 'center', 'right'。string和number类型。

2.6. legend.top = 'auto', 图例组件离容器上侧的距离。top的值可以是像20这样的具体像素值, 可以是像'20%'这样相对于容器高宽的百分比, 也可以是'top', 'middle', 'bottom'。string和number类型。

2.7. legend.right = 'auto', 图例组件离容器右侧的距离。right的值可以是像20这样的具体像素值, 可以是像'20%'这样相对于容器高宽的百分比。默认自适应。string和number类型。

2.8. legend.bottom = 'auto', 图例组件离容器下侧的距离。bottom的值可以是像20这样的具体像素值, 可以是像'20%'这样相对于容器高宽的百分比。默认自适应。string和number类型。

2.9. legend.width = 'auto', 图例组件的宽度。默认自适应。string和number类型。

2.10. legend.height = 'auto', 图例组件的高度。默认自适应。string和number类型。

2.11. legend.orient = 'horizontal', 例列表的布局朝向。可选: 'horizontal'和'vertical'。string类型。

2.12. legend.borderColor = '#ccc', 图例的边框颜色。Color类型。

2.13. legend.borderWidth = 1, 图例的边框线宽。number类型。

2.14. legend.borderRadius, 圆角半径, 单位px, 支持传入数组分别指定4个圆角半径。number或Array类型。如:

borderRadius: 5, // 统一设置四个角的圆角大小
borderRadius: [5, 5, 0, 0] // (顺时针左上, 右上, 右下, 左下)

2.15. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>图例布局</title>
		<!-- 引入echarts.js -->
		<script type="text/javascript" src="echarts.js"></script>
	</head>
	<body>
		<!-- 为ECharts准备一个具备大小(宽高)的DOM -->
		<div id="top" style="width: 900px; height: 400px;"></div>
		<div id="right" style="width: 900px; height: 400px;"></div>
		<div id="bottom" style="width: 900px; height: 400px;"></div>
		<script type="text/javascript">
	    	// 基于准备好的dom, 初始化echarts实例
	      	var mytopChart = echarts.init(document.getElementById('top'));
	      	var myrightChart = echarts.init(document.getElementById('right'));
	      	var mybottomChart = echarts.init(document.getElementById('bottom'));

	      	// 指定图表的配置项和数据
	      	var option = {
	      		// 为图表配置标题
		        title: {
		          text: '图例布局'
		        },
		        // 配置提示信息
		        tooltip: {},
		        // 配置要在X轴显示的项
		        xAxis: {
    			  type: "category" // 类目
  				},
		        // 配置要在Y轴显示的项
		        yAxis: {},
		        // 数据集
		        dataset: {
		          source: [ // 原数据。
		            ['product', '2020', '2021', '2022'],
		        	['Matcha Latte', 89.3, 95.8, 97.7],
		        	['Milk Tea', 92.1, 89.4, 83.1],
		        	['Cheese Cocoa', 94.4, 91.2, 92.5],
		        	['Walnut Brownie', 85.4, 76.9, 78.1]
		          ]
		        },
		        // 系列列表
		        series: [ { type: 'bar' }, { type: 'bar' }, { type: 'bar' } ]
	      	};
	      	// 图例组件
		    var topLegend = {
	          	id: 'top',
	          	show: true,
	          	width: 300, // 宽高设置过大, 也还是包裹内容的大小
	          	height: 80,
	          	borderColor: 'red',
	          	borderWidth: 1,
	          	left: 'center',
	          	top: 'top',
	          	orient: 'horizontal'
	        };
	        option.legend = topLegend;
	        option.title.text = '图例布局在上方';
	      	// 使用刚指定的配置项和数据显示图表。
	      	mytopChart.setOption(option);


	      	// 图例组件
		    var rightLegend = {
	          	id: 'right',
	          	show: true,
	          	width: 80, // 宽高设置过大, 也还是包裹内容的大小
	          	height: 60,
	          	borderColor: 'red',
	          	borderWidth: 1,
	          	type: 'scroll',
	          	right: 10,
	          	top: 'middle',
	          	orient: 'vertical'
	        };
	        option.legend = rightLegend;
	        option.title.text = '图例布局在右边';
	        myrightChart.setOption(option);

	        // 图例组件
		    var bottomLegend = {
	          	id: 'bottom',
	          	show: true,
	          	width: 300, // 宽高设置过大, 也还是包裹内容的大小
	          	height: 80,
	          	borderColor: 'red',
	          	borderWidth: 1,
	          	left: 'center',
	          	bottom: 10,
	          	orient: 'horizontal'
	        };
	        option.legend = bottomLegend;
	        option.title.text = '图例布局在下方';
	        mybottomChart.setOption(option);
	    </script>
	</body>
</html>

2.16. 效果图

3. 图例样式

3.1. legend.formatter, 用来格式化图例文本, 支持字符串模板和回调函数两种形式。string或Function类型。示例:

// 使用字符串模板, 模板变量为图例名称{name}
formatter: 'Legend {name}'
// 使用回调函数
formatter: function (name) {
    return 'Legend ' + name;
}

3.2. legend.icon, 图例项的icon。string类型。ECharts提供的标记类型包括: 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'。可以通过'image://url'设置为图片, 其中URL为图片的链接, 或者dataURI。例如:

// URL为图片链接
'image://http://xxx.xxx.xxx/a/b.png'
// URL为dataURI
'image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'

3.3. legend.backgroundColor = 'transparent', 图例背景色, 默认透明。颜色可以使用RGB表示, 比如: 'rgb(128, 128, 128)', 如果想要加上alpha通道, 可以使用RGBA, 比如: 'rgba(128, 128, 128, 0.5)', 也可以使用十六进制格式, 比如: '#ccc'。Color类型。

3.4. legend.data, 图例的数据数组。数组项通常为一个字符串, 每一项代表一个系列的name。图例组件会自动根据对应系列的图形标记(symbol)来绘制自己的颜色和标记, 特殊字符串''(空字符串)或者'\n'(换行字符串)用于图例的换行。如果data没有被指定, 会自动从当前系列中获取。如果要设置单独一项的样式, 也可以把该项写成配置项对象。此时必须使用name属性对应表示系列的name。所有属性: { name , icon , itemStyle , lineStyle , symbolRotate , textStyle }。示例:

data: [{
    name: '系列1',
    // 强制设置图形为圆。
    icon: 'circle',
    // 设置文本为红色
    textStyle: {
        color: 'red'
    }
}]

3.5. legend.textStyle.color = #333, 文字的颜色。Color类型。

3.6. legend.textStyle.fontStyle = 'normal', 文字字体的风格。可选: 'normal'、'italic'和'oblique'。string类型。

3.7. legend.textStyle.fontWeight = 'normal', 文字字体的粗细。可选: 'normal'、'bold'、'bolder'、'lighter'和100 | 200 | 300 | 400...。string和number类型。

3.8. legend.textStyle.fontFamily = 'sans-serif', 文字的字体系列。还可以是'serif', 'monospace', 'Arial', 'Courier New', 'Microsoft YaHei', ...。string类型。

3.9. legend.textStyle.fontSize = 12, 文字的字体大小。number类型。

3.10. legend.textStyle.lineHeight, 行高。number类型。

3.11. legend.textStyle.backgroundColor = 'transparent', 文字块背景色。string和Object类型。可以使用颜色值, 例如:'#123234', 'red', 'rgba(0,23,11,0.3)'。也可以直接使用图片, 当使用图片的时候, 可以使用width或height指定高宽, 也可以不指定自适应。例如:

backgroundColor: {
    image: 'xxx/xxx.png'
    // 这里可以是图片的 URL,
    // 或者图片的 dataURI,
    // 或者 HTMLImageElement 对象,
    // 或者 HTMLCanvasElement 对象。
}

3.12. legend.textStyle.borderColor, 文字块边框颜色。Color类型。

3.13. legend.textStyle.borderWidth, 文字块边框宽度。number类型。

3.14. legend.textStyle.borderType = 'solid', 文字块边框描边类型。string、number和Array类型。可选: 'solid'、'dashed'和'dotted'。自v5.0.0开始, 也可以是number或者number数组, 用以指定线条的dash array, 配合borderDashOffset可实现更灵活的虚线效果。例如:

{
	borderType: [5, 10],

	borderDashOffset: 5
}

3.15. legend.textStyle.borderDashOffset, 用于设置虚线的偏移量, 可搭配borderType指定dash array实现灵活的虚线效果。number类型。

3.16. legend.textStyle.borderRadius, 文字块的圆角。number和Array类型。

3.17. legend.textStyle.padding, 文字块的内边距。number和Array类型。

  • padding: [3, 4, 5, 6], 表示[上, 右, 下, 左]的边距。
  • padding: 4, 表示padding: [4, 4, 4, 4]。
  • padding: [3, 4], 表示padding: [3, 4, 3, 4]。

3.18. legend.textStyle.shadowColor = 'transparent', 文字块的背景阴影颜色。Color类型。

3.19. legend.textStyle.shadowBlur, 文字块的背景阴影长度。number类型。

3.20. legend.textStyle.shadowOffsetX, 文字块的背景阴影X偏移。number类型。

3.21. legend.textStyle.shadowOffsetY, 文字块的背景阴影Y偏移。number类型。

3.22. legend.textStyle.width, 文本显示宽度。number类型。

3.23. legend.textStyle.height, 文本显示高度。number类型。

3.24. legend.textStyle.textBorderColor, 文字本身的描边颜色。Color类型。

3.25. legend.textStyle.textBorderWidth, 文字本身的描边宽度。number类型。

3.26. legend.textStyle.textBorderType = 'solid', 文字本身的描边类型。number、string和Array类型。可选: 'solid'、'dashed'和'dotted'。自v5.0.0开始, 也可以是number或者number数组, 用以指定线条的dash array, 配合textBorderDashOffset可实现更灵活的虚线效果。例如:

{
	textBorderType: [5, 10],

	textBorderDashOffset: 5
}

3.27. legend.textStyle.textBorderDashOffset, 用于设置虚线的偏移量, 可搭配textBorderType指定dash array实现灵活的虚线效果。number类型。

3.28. legend.textStyle.textShadowColor = 'transparent', 文字本身的阴影颜色。Color类型。

3.29. legend.textStyle.textShadowBlur, 文字本身的阴影长度。number类型。

3.30. legend.textStyle.textShadowOffsetX, 文字本身的阴影X偏移。number类型。

3.31. legend.textStyle.textShadowOffsetY, 文字本身的阴影Y偏移。number类型。

3.32. legend.textStyle.overflow = 'none', 文字超出宽度是否截断或者换行。配置width时有效。string类型。可选值:

  • 'truncate'截断, 并在末尾显示ellipsis配置的文本, 默认为...。
  • 'break'换行。
  • 'breakAll'换行, 跟'break'不同的是, 在英语等拉丁文中, 'breakAll'还会强制单词内换行。

3.33. legend.textStyle. ellipsis = '...',在overflow配置为'truncate'的时候, 可以通过该属性配置末尾显示的文本。string类型。

3.34. legend.textStyle. rich, 在rich里面, 可以自定义富文本样式。利用富文本样式, 可以在标签中做出非常丰富的效果。Object类型。

3.35. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>图例样式</title>
		<!-- 引入echarts.js -->
		<script type="text/javascript" src="echarts.js"></script>
	</head>
	<body>
		<!-- 为ECharts准备一个具备大小(宽高)的DOM -->
		<div id="main" style="width: 900px; height: 400px;"></div>
		<script type="text/javascript">
	    	// 基于准备好的dom, 初始化echarts实例
	      	var myChart = echarts.init(document.getElementById('main'));

	      	// 指定图表的配置项和数据
	      	var option = {
	      		// 为图表配置标题
		        title: {
		          text: '图例样式'
		        },
		        // 配置提示信息
		        tooltip: {},
		        // 图例组件
		        legend: {
		          formatter: function (name) {
    			    return name + '年';
				  },
		          backgroundColor: 'pink',
		          textStyle: {
	              	fontSize: 16,
	              	lineHeight: 32,
	              	backgroundColor: 'rgba(4, 4, 4, 1)',
	              	borderColor: '#F00',
	              	borderWidth: 3,
	              	borderType: [5, 10],
	              	borderDashOffset: 5,
	              	borderRadius: 5,
	              	padding: 8
	              },
		          data: [
		            {
		              name: '2020', 
		              icon: 'circle',
		              textStyle: {
		              	color: 'rgba(20, 231, 58, 1)',
		              	fontStyle: 'normal',
		              	fontWeight: 'normal',
		              	fontFamily: 'serif'
		              }
		            }, 
		            {
		              name: '2021', 
		              icon: 'rect',
		              textStyle: {
		              	color: 'rgba(20, 217, 231, 1)',
		              	fontStyle: 'italic',
		              	fontWeight: 'bold',
		              	fontFamily: 'monospace'
		              }
		            }, 
		            {
		              name: '2022', 
		              icon: 'triangle',
		              textStyle: {
		              	color: 'rgba(104, 20, 231, 1)',
		              	fontStyle: 'oblique',
		              	fontWeight: 'bolder',
		              	fontFamily: 'Courier New'
		              }
		            }
		          ]
		        },
		        // 配置要在X轴显示的项
		        xAxis: {
    			  type: "category" // 类目
  				},
		        // 配置要在Y轴显示的项
		        yAxis: {},
		        // 数据集
		        dataset: {
		          source: [ // 原数据。
		            ['product', '2020', '2021', '2022'],
		        	['Matcha Latte', 89.3, 95.8, 97.7],
		        	['Milk Tea', 92.1, 89.4, 83.1],
		        	['Cheese Cocoa', 94.4, 91.2, 92.5],
		        	['Walnut Brownie', 85.4, 76.9, 78.1]
		          ]
		        },
		        // 系列列表
		        series: [ { type: 'bar' }, { type: 'bar' }, { type: 'bar' } ]
	      	};

	      	// 使用刚指定的配置项和数据显示图表。
	      	myChart.setOption(option);
	    </script>
	</body>
</html>

3.36. 效果图

4. 图例交互

4.1. 根据场景需要, 图例可支持交互操作, 点击控制显示或隐藏对应的数据列。

4.2. legend.selected图例选中状态表。Object类型。示例:

selected: {
    // 选中'系列1'
    '系列1': true,
    // 不选中'系列2'
    '系列2': false
}

4.3. 代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>图例选中状态表</title>
		<!-- 引入echarts.js -->
		<script type="text/javascript" src="echarts.js"></script>
	</head>
	<body>
		<!-- 为ECharts准备一个具备大小(宽高)的DOM -->
		<div id="main" style="width: 900px; height: 400px;"></div>
		<script type="text/javascript">
	    	// 基于准备好的dom, 初始化echarts实例
	      	var myChart = echarts.init(document.getElementById('main'));

	      	// 指定图表的配置项和数据
	      	var option = {
	      		// 为图表配置标题
		        title: {
		          text: '图例选中状态表'
		        },
		        // 配置提示信息
		        tooltip: {},
		        // 图例组件
		        legend: {
		          selected: {
		          	'2020': true,
		          	'2021': true,
		          	'2022': false,
		          }
		        },
		        // 配置要在X轴显示的项
		        xAxis: {
    			  type: "category" // 类目
  				},
		        // 配置要在Y轴显示的项
		        yAxis: {},
		        // 数据集
		        dataset: {
		          source: [ // 原数据。
		            ['product', '2020', '2021', '2022'],
		        	['Matcha Latte', 89.3, 95.8, 97.7],
		        	['Milk Tea', 92.1, 89.4, 83.1],
		        	['Cheese Cocoa', 94.4, 91.2, 92.5],
		        	['Walnut Brownie', 85.4, 76.9, 78.1]
		          ]
		        },
		        // 系列列表
		        series: [ { type: 'bar' }, { type: 'bar' }, { type: 'bar' } ]
	      	};

	      	// 使用刚指定的配置项和数据显示图表。
	      	myChart.setOption(option);
	    </script>
	</body>
</html>

4.4. 效果图

% 清除工作区和命令窗口 clear; clc; close all; % 物料填充率范围 (0% 到 100%) filling_rate = 0:1:100; % 1. 磨机功率曲线 power = -0.012*(filling_rate - 40).^2 + 30; power(power < 0) = 0; % 确保功率值为正 % 计算关键点位 x5_idx = find(filling_rate == 5); % x=5处的索引 power_x5 = power(x5_idx); % x=5处的功率值 peak_idx = find(filling_rate == 40); % 峰值点索引(x=40) peak_power = power(peak_idx); % 峰值功率值 end_x = 75; end_idx = find(filling_rate == end_x);% 终点索引(x=75) % 2. 轴压曲线(直线) k_axial = (peak_power - power_x5) / (filling_rate(peak_idx) - filling_rate(x5_idx)); % 斜率 b_axial = power_x5 - k_axial * filling_rate(x5_idx); % 截距 axial_pressure = k_axial * filling_rate + b_axial; % 3. 磨机卫士曲线(分段曲线) guard = NaN(size(filling_rate)); % 前段:x=5到x=40 front_idx = filling_rate >= 5 & filling_rate <= 40; weights = 0.7 - 0.2*(filling_rate(front_idx) - 5)/35; guard(front_idx) = weights .* axial_pressure(front_idx) + (1-weights) .* power(front_idx); % 后段:x=40到x=75 back_idx = filling_rate > 40 & filling_rate <= 75; a = 0.05; guard(back_idx) = a * (filling_rate(back_idx) - 40).^2 + peak_power; guard(back_idx(filling_rate(back_idx)==41)) = guard(front_idx(end)); % 筛选绘制范围 plot_idx = filling_rate >= 5 & filling_rate <= 75; filling_plot = filling_rate(plot_idx); power_plot = power(plot_idx); axial_plot = axial_pressure(plot_idx); guard_plot = guard(plot_idx); % 创建形 figure('Name', '磨机特性曲线', 'Position', [100 100 900 600]); % 绘制三条曲线 h_power = plot(filling_plot, power_plot, 'b-', 'LineWidth', 2); hold on; h_axial = plot(filling_plot, axial_plot, 'r--', 'LineWidth', 2); h_guard = plot(filling_plot, guard_plot, 'g-.', 'LineWidth', 2); % ===== 新增功能 ===== % 1. 只绘制垂直网格线 grid on; ax = gca; ax.YGrid = 'off'; % 关闭水平网格线 ax.XGrid = 'on'; % 开启垂直网格线 % 2. 添加y=30的棕色虚线 yline(30, '--', 'Color', [0.6, 0.3, 0], 'LineWidth', 1.5); % 3. 添加x=30的棕色虚线 xline(30, '--', 'Color', [0.6, 0.3, 0], 'LineWidth', 1.5); % 4. 添加坐标轴标签(使用数据坐标) % 修改:使用文本函数添加标签 text(70, -1, '物料填充率 (%)', 'FontSize', 12, 'HorizontalAlignment', 'center'); text(-5, 50, '功率 (kW)', 'FontSize', 12, 'Rotation', 90); % ===== 标记点 ===== % 标记点A1 (30,40) plot(30, 30, 'ko', 'MarkerSize', 8, 'MarkerFaceColor', 'k'); text(30, 30, ' A1', 'FontSize', 12, 'VerticalAlignment', 'bottom'); % 标记点B1 (40,30) plot(40, 30, 'ko', 'MarkerSize', 8, 'MarkerFaceColor', 'k'); text(40, 30, ' B1', 'FontSize', 12, 'VerticalAlignment', 'bottom'); % =================== title('磨机功率、轴压和磨机卫士随物料填充率变化曲线', 'FontSize', 14); % 设置坐标轴范围 xlim([0 80]); ylim([10 max(power)*1.5]); % 添加图例 legend([h_power, h_axial, h_guard], ... {'磨机功率曲线', '轴压曲线', '磨机卫士曲线'}, ... 'Location', 'best', 'FontSize', 10); % 确保中文正常显示 set(gca, 'FontName', 'SimHei'); % 隐藏坐标轴线 ax.XAxis.Visible = 'off'; ax.YAxis.Visible = 'off'; % 获取坐标轴范围 xlims = ax.XLim; ylims = ax.YLim; % 绘制坐标轴箭头 ds2nfu = @(x,y) [ax.Position(1) + (x - xlims(1)) / (xlims(2)-xlims(1)) * ax.Position(3), ... ax.Position(2) + (y - ylims(1)) / (ylims(2)-ylims(1)) * ax.Position(4)]; origin = ds2nfu(xlims(1), ylims(1)); x_end = ds2nfu(xlims(2), ylims(1)); y_end = ds2nfu(xlims(1), ylims(2)); annotation('arrow', [origin(1), x_end(1)], [origin(2), x_end(2)], ... 'Color', 'k', 'LineWidth', 1.5, 'HeadWidth', 10, 'HeadLength', 10); annotation('arrow', [origin(1), y_end(1)], [origin(2), y_end(2)], ... 'Color', 'k', 'LineWidth', 1.5, 'HeadWidth', 10, 'HeadLength', 10); hold off; 将上述代码的xlabel和ylabel显示出来,其他不变
08-26
检查和修改以下代码:clc clear %% 参数定义 Time = 24; % 时间周期 NG = 6; % 常规机组数量 % 机组参数矩阵 G_mp = [1 150 50 0.0375 20 372.5 72 2; % [机组号, Pmax, Pmin, a, b, c, 固定成本, 爬坡率] 2 60 20 0.175 17.5 352.3 48 2; 3 60 15 0.625 10 316.5 30 2; 4 50 10 0.0834 32.5 329.2 30 2; 5 40 10 0.25 30 276.4 18 2; 6 45 12 0.25 30 232.2 24 2]; % 系统参数 kc = 2.5; % 弃风惩罚系数 soc_min = 0.1; soc_max = 0.9; % 储能SOC限制 P_ess_cha = -50; P_ess_dis = 50; % 储能充放电功率限制 Se = 200; Se_0 = 100; % 储能容量参数 P_ws_min = -50; P_ws_max = 50; % 水电功率限制 Vs_0 = 100; Vp_min = 0; Vp_max = 200; % 水电容量参数 % 负荷与可再生能源预测 p_load_e = [390 382 354 340 328 409 460 460 472 511 465 458 442 456 457 471 475 503 512 469 445 438 410 362]; p_wt_e = [61 60.5 70 63 64 102 131 165 167 182 153 179 182 121 99 293 272 245 210 182 145 105 96 85]; %% 网络参数初始化 case_Name = case30; % 30节点系统 base_MVA = 100; % 基准功率 % 节点负荷计算 p30 = sum(case_Name.bus(:,3)); pbl = p_load_e ./ p30; p_load_1 = repmat(pbl, 30, 1) .* repmat(case_Name.bus(:,3), 1, Time); P_GD_load = 0.85 .* p_load_1; % 固定负荷 % 网络拓扑矩阵 bus = case_Name.bus; brch = case_Name.branch; f = brch(:,1); t = brch(:,2); x = brch(:,4); n_bus = size(bus,1); n_brch = size(brch,1); % 导纳矩阵 C_ft = zeros(n_brch, n_bus); for ii = 1:n_brch C_ft(ii, f(ii)) = 1; C_ft(ii, t(ii)) = -1; end B_f = zeros(n_brch, n_bus); for ii = 1:n_brch B_f(ii, f(ii)) = 1./x(ii); B_f(ii, t(ii)) = -1./x(ii); end B_bus = C_ft' * B_f; % 节点-设备映射 i_dg = [1 2 5 8 11 13]; % 机组连接节点 iw = 2; % 风电节点 ie = 2; % 储能节点 is = 8; % 水电节点 % 假设getMbgMatrix和getMbdMatrix已正确定义 M_bg = getMbgMatrix(i_dg', bus); M_be = getMbdMatrix(ie, bus); M_bw = getMbdMatrix(iw, bus); M_bs = getMbdMatrix(is, bus); %% 优化变量定义 % 主变量 theta = sdpvar(30, Time, 'full'); % 电压相角 P_GT_e = sdpvar(NG, Time, 'full'); % 常规机组出力 P_WT_e = sdpvar(1, Time, 'full'); % 风电出力 B_upw = binvar(1, Time, 'full'); % 风电启停状态 P_WS_e = sdpvar(1, Time, 'full'); % 水电出力 Perss = sdpvar(1, Time, 'full'); % 储能出力 uerss = binvar(1, Time, 'full'); % 储能启停状态 ug = binvar(NG, Time, 'full'); % 机组启停状态 % === 新增:线性化储能成本 === P_erss_cha = sdpvar(1, Time, 'full'); % 储能充电功率 (≥0) P_erss_dis = sdpvar(1, Time, 'full'); % 储能放电功率 (≥0) % 成本线性化变量 gn = 5; % 分段线性化段数 x_pf = sdpvar(NG, Time, 'full'); % 二次项线性化变量 gw = cell(1, NG); % 分段权重 gz = cell(1, NG); % 分段选择变量 for i = 1:NG gw{i} = sdpvar(gn+1, Time, 'full'); gz{i} = binvar(gn, Time, 'full'); end % 启停成本变量 yy = binvar(NG, Time-1, 'full'); % 机组启停变化 yyw = binvar(1, Time-1, 'full'); % 风电启停变化 %% 约束定义 cons = []; % ===== 1. 机组约束 ===== % 出力限制 for i = 1:NG cons = [cons, G_mp(i,3) * ug(i,:) <= P_GT_e(i,:) <= G_mp(i,2) * ug(i,:)]; end % 爬坡约束 for i = 1:NG for t = 2:Time ramp_rate = G_mp(i,8); cons = [cons, -ramp_rate <= P_GT_e(i,t) - P_GT_e(i,t-1) <= ramp_rate]; end end % ===== 2. 可再生能源约束 ===== cons = [cons, 0 <= P_WT_e <= B_upw .* p_wt_e]; % 风电出力限制 % ===== 3. 储能约束 ===== % 充放电功率限制 cons = [cons, P_ess_cha * uerss <= Perss <= P_ess_dis * uerss]; % === 新增:充放电分解约束 === cons = [cons, Perss == P_erss_dis - P_erss_cha]; cons = [cons, 0 <= P_erss_cha <= -P_ess_cha * uerss]; cons = [cons, 0 <= P_erss_dis <= P_ess_dis * uerss]; % SOC约束(修复符号) soc = Se_0 - cumsum(Perss, 2); % 关键修复:负号 for t = 1:Time cons = [cons, soc_min * Se <= soc(t) <= soc_max * Se]; end % ===== 4. 水电约束 ===== % 功率限制 cons = [cons, P_ws_min <= P_WS_e <= P_ws_max]; % 容量约束(修复符号) water = Vs_0 - cumsum(P_WS_e, 2); % 关键修复:负号 for t = 1:Time cons = [cons, Vp_min <= water(t) <= Vp_max]; end % ===== 5. 网络约束 ===== % 潮流平衡约束 for t = 1:Time Pbus = M_bg * P_GT_e(:,t) + M_bs * P_WS_e(t) + M_be * Perss(t) + M_bw * P_WT_e(t) - P_GD_load(:,t); cons = [cons, Pbus == B_bus * theta(:,t) * base_MVA]; end % 线路潮流约束(修复索引) for t = 1:Time for ii = 1:length(f) d_theta = theta(f(ii),t) - theta(t(ii),t); pf(ii) = d_theta / x(ii) * base_MVA; end cons = [cons, -500 <= pf <= 500]; end cons = [cons, -pi <= theta <= pi]; % 相角约束 % ===== 6. 成本线性化约束 ===== for gen = 1:NG Pmax = G_mp(gen,2); Pmin = G_mp(gen,3); gl = (Pmax - Pmin) / gn; gl_points = Pmin:gl:Pmax; % 分段点 for t = 1:Time % 分段权重约束 cons = [cons, x_pf(gen,t) == (gl_points.^2) * gw{gen}(:,t)]; cons = [cons, gw{gen}(1,t) <= gz{gen}(1,t)]; for seg = 2:gn cons = [cons, gw{gen}(seg,t) <= gz{gen}(seg-1,t) + gz{gen}(seg,t)]; end cons = [cons, gw{gen}(gn+1,t) <= gz{gen}(gn,t)]; cons = [cons, sum(gz{gen}(:,t)) == 1]; cons = [cons, sum(gw{gen}(:,t)) == 1]; % 关键修复:权重归一化 % 出力与分段关系 cons = [cons, P_GT_e(gen,t) == gl_points * gw{gen}(:,t)]; cons = [cons, gw{gen}(:,t) >= 0]; end end % ===== 7. 启停状态约束 ===== % 机组启停状态变化 for gen = 1:NG for t = 1:Time-1 cons = [cons, yy(gen,t) <= ug(gen,t+1)]; % 启动标志 cons = [cons, yy(gen,t) <= 1 - ug(gen,t)]; % 停机标志 cons = [cons, yy(gen,t) >= ug(gen,t+1) - ug(gen,t)]; % 状态变化 end end % 风电启停状态变化 for t = 1:Time-1 cons = [cons, yyw(t) <= B_upw(t+1)]; % 启动标志 cons = [cons, yyw(t) <= 1 - B_upw(t)]; % 停机标志 cons = [cons, yyw(t) >= B_upw(t+1) - B_upw(t)]; % 状态变化 end %% 目标函数 % 1. 常规机组成本 gen_cost = 0; for gen = 1:NG a = G_mp(gen,4); b = G_mp(gen,5); c = G_mp(gen,6); for t = 1:Time gen_cost = gen_cost + a * x_pf(gen,t) + b * P_GT_e(gen,t) + c * ug(gen,t); end end % 2. 启停成本(修复索引) startup_cost = 0.9 * (sum(yy(:)) + sum(yyw)); % 关键修复 % 3. 储能成本(线性化) ess_cost = sum(0.53 * P_erss_dis + 0.12 * P_erss_cha) + 0.012 * sum(uerss); % 关键修复 % 4. 弃风成本 wind_curtail = kc * sum(p_wt_e - P_WT_e); % 总目标函数 total_cost = gen_cost + startup_cost + ess_cost + wind_curtail; %% 求解优化问题 ops = sdpsettings('solver', 'cplex', 'verbose', 1, 'usex0', 0); result = optimize(cons, total_cost, ops); %% 结果处理与可视化 if result.problem == 0 % 提取结果值 Pg_val = value(P_GT_e); Pw_val = value(P_WT_e); Ps_val = value(P_WS_e); Perss_val = value(Perss); % 充放电功率分解 Ps_charge = min(Ps_val, 0); Ps_discharge = max(Ps_val, 0); P_erss_cha = min(Perss_val, 0); P_erss_dis = max(Perss_val, 0); % 绘制调度结果 figure('Name', '系统调度结果', 'Position', [100, 100, 1000, 600]); hold on; % 负值部分(充电) bar([Ps_charge; P_erss_cha]', 'stacked'); % 正值部分(放电和发电) bar([Ps_discharge; P_erss_dis; sum(Pg_val,1); Pw_val]', 'stacked'); % 添加总负荷曲线 plot(sum(p_load_1), 'k--', 'LineWidth', 2); % 图例和标签 legend('水电充电', '电化学储能充电', '水电放电', '电化学储能放电', '传统机组', '风电', '总负荷'); xlabel('时间 (小时)'); ylabel('功率 (MW)'); title('电力系统调度结果'); grid on; hold off; % 显示总成本 disp(['总运行成本: ', num2str(value(total_cost)), ' 元']); % SOC可视化 figure; plot(value(soc)/Se, 'LineWidth', 2); hold on; yline(soc_min, 'r--', 'Min SOC'); yline(soc_max, 'r--', 'Max SOC'); title('储能SOC状态'); xlabel('时间 (小时)'); ylabel('SOC (%)'); grid on; else error('优化失败: %s', result.info); end
最新发布
11-20
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值