#冲刺创作新星#PIE-engine APP 教程城市生态宜居性评价系统 原创
这个系统是一个计算京津冀地区的生态宜居性评价的系统,而且是四季性的,整体上代码中,首先是加载数据和加载研究区,然后定义常量参数(定义图层和可视化参数以及图例变量),然后定义指定的研究区数据,这个系统中有一个小的差异加载的全国县级尺度、市级尺度和省级尺度因为研究区的面积大小不同,所用的统计的scale的统计是不同的分别是1000,2000,3000的,以此来提升运算速度同时嵌套了条件函数的与设定一次来返回给研究区,再预设过程中,还包括地表温度、MNDWI、植被覆盖度、NDBI、去云函数以及其它函数(NO2\O3\SO2\CO\),最终合成AQI空气质量的计算函数。接下来是主函数,用于整体流程的控制。最后一个部分是UI部分的设定和统计数据的结果,这里是指定年份通过循环函数计算出的季节性结果。
这个系统因为数据的限制所以只能再2018年至2020年,修改代码后的结果可以延伸到2022年
这里有一个链接函数:
ui.Cascader(placeholder,content,value,onChange,disabled,style)
级联选择组件。
方法参数:
- ui(ui)
调用者:ui对象。
- placeholder(String)
默认显示的文本。
- content(List)
级联菜单的内容。
- value(List)
当前选择值。
- onChange(Function)
选择不同值时触发的方法。
- disabled(Boolean)
组件是否可用。
- style(Object)
组件的样式。
返回值:ui.Cascader
ui.GeoCascader(init,placeholder,disabled,style,onChange)
行政区划级联选择组件。
方法参数:
- ui(ui)
调用者:ui对象。
- init(Object)
自定义配置显示数据对象:{list: 需要显示的行政区划级别列表,可选参数[province,city,county], province:要显示的省列表, city:要显示的市列表, county:要显示的县列表}
- placeholder(String)
默认显示的文本。
- disabled(Boolean)
组件是否可用。
- style(Object)
组件的样式。
- onChange(Function)
选择不同值时触发的方法。
返回值:ui.GeoCascader
ui.Radio(label,value,onChange,disabled,style)单项选择的一个按钮
单选按钮。
方法参数:
- ui(ui)
调用者:ui对象。
- label(List)
单选按钮的内容列表。
- value(String)
被选中的单选按钮。
- onChange(Function)
状态修改后触发事件。
- disabled(List)
不可用的单选按钮列表。
- style(Object)
组件样式
返回值:ui.Radio
removeLayer(key)
移除地图上指定的图层
方法参数:
- map(ui.Map)
调用者:ui.Map实例。
- key(String)
图层唯一key,由addLayer返回
返回值:Object
代码:
/**
* @Name : 基于PIE云平台的城市生态宜居性评价系统——以京津冀城市群为例
* @Time : 2021/8/21
* @Author : 中国石油大学(华东)牛转乾坤队
* @Version : 1.0
* @E-mail : genyunsun@163.com
* @Source
var libs = require("https://pie-engine-static-data.s3.cn-northwest-1.amazonaws.com.cn/engine-studio-data/demoData.js");
// 利用计算的结果 统计各个区域的各个指标变化情况:
var staticData = libs.data;
// print(staticData)
//划定研究区域
var Province = pie.FeatureCollection("user/pieadmin/JJJ_Provinces");
var Cities = pie.FeatureCollection("user/pieadmin/JJJ_Cities");
var Countries = pie.FeatureCollection("user/pieadmin/JJJ_County");
var all_region = pie.FeatureCollection("user/pieadmin/JingJinJi");
//定义常量参数
var layerKey = null; // 地图层 layerkery
var roilayerKey = null; // 矢量图层 key
var selectTag = "EI";
var selectSenson = "spring";
var seasonindex = 0; //季节的索引值 , 默认为0 ,春季
var environmetClass = 1; // 默认环境等级
var selectStartDate = "2020-3-1"; // 默认起始时间
var selectCode = "110101"; // 默认地区代码
var countyname = "北京市/东城区";
var selectYear = 2019; //通过滚动轴选择年份
var showLevel = 10; // 显示层级 , 区域越大层级越小
var reduceScale = 1000; // 局部统计使用的尺度 , 统计的区域越大, 尺度越大 ,防止内存不足
var staticType = "Season"; // 统计表的形式
var region_level = "District"; // 显示的区域级别 默认 Disrrict
var charttype = "bar";
var roi = null; // 显示的区域
Map.addLayer(
Cities,
{ color: "#044b4b", fillColor: "#00000000", width: 1.5 },
"Cities",
false
);
Map.addLayer(
Countries,
{ color: "#7b7b7b", fillColor: "#00000000", width: 1.0 },
"Countries",
false
);
var visAQI = {
min: 0,
max: 1,
palette: [
"#040274",
"#040281",
"#0502a3",
"#0502b8",
"#0502ce",
"#0502e6",
"#0602ff",
"#235cb1",
"#307ef3",
"#269db1",
"#30c8e2",
"#32d3ef",
"#3be285",
"#3ff38f",
"#86e26f",
"#3ae237",
"#b5e22e",
"#d6e21f",
"#fff705",
"#ffd611",
"#ffb613",
"#ff8b13",
"#ff6e08",
"#ff500d",
"#ff0000",
"#de0101",
"#c21301",
"#a71001",
"#911003",
],
};
var colors1 = [
"#0602ff",
"#235cb1",
"#307ef3",
"#269db1",
"#30c8e2",
"#32d3ef",
"#3be285",
"#3ff38f",
"#86e26f",
"#3ae237",
"#b5e22e",
"#d6e21f",
"#fff705",
"#ffd611",
"#ffb613",
"#ff8b13",
"#ff6e08",
"#ff500d",
"#ff0000",
"#de0101",
]; // 由绿到红
var colors2 = [
"#ff6e08",
"#ff8b13",
"#ff9613",
"#ffd611",
"#fff705",
"#d6e21f",
"#b5e22e",
"#3ae237",
"#86e26f",
"#3ff38f",
"#3be285",
"#32d3ef",
]; // 由红到绿
//获取指定的ROI数据
function getROI(code) {
print(code, parseInt(code));
if (region_level == "District") {
var fCol = pie.FeatureCollection("NGCC/CHINA_COUNTY_BOUNDARY");
showLevel = 10;
reduceScale = 1000;
} else if (region_level == "City") {
var fCol = pie.FeatureCollection("NGCC/CHINA_CITY_BOUNDARY");
showLevel = 7;
reduceScale = 2000;
} else if (region_level == "Province") {
var fCol = pie.FeatureCollection("NGCC/CHINA_PROVINCE_BOUNDARY");
showLevel = 6;
reduceScale = 3000;
}
if (region_level == "All") {
roi = all_region.first().geometry();
showLevel = 5;
reduceScale = 5000;
} else {
roi = fCol
.filter(pie.Filter.eq("code", parseInt(code)))
.first()
.geometry();
}
if (roilayerKey != null) {
Map.removeLayer(roilayerKey);
}
if (roi != null) {
roilayerKey = Map.addLayer(
roi,
{ color: "#ff0000", fillColor: "#00000000" },
"roi"
);
Map.centerObject(roi, showLevel);
}
return roi;
}
// 向地图中添加 图例 (颜色条)
function addMapLenged(INDEX) {
var colors = colors1;
switch (INDEX) {
case "FVC":
colors = colors2;
break;
case "MNDWI":
colors = colors2;
break;
case "EI":
colors = colors2;
break;
}
var data = {
title: INDEX,
colors: colors,
labels: ["0", "0.2", "0.4", "0.6", "0.8", "1.0"],
step: 30,
};
var style = {
right: "550px",
bottom: "70px",
height: "70px",
width: "300px",
};
var legend = ui.Legend(data, style);
Map.addUI(legend);
}
//地表温度反演
function LSTMap(image, roi) {
var ndvi = image
.expression("(B5-B4)/(B5+B4)", {
B4: image.select("B4"),
B5: image.select("B5"),
})
.rename("NDVI");
var normalNdvi = ndvi.subtract(-0.3).divide(pie.Number(0.81).subtract(-0.3));
var fv = normalNdvi.power(2.0).rename("fv");
var a = pie.Number(0.025);
var b = pie.Number(0.986);
var EM = fv
.multiply(a)
.add(pie.Image(1).subtract(fv).multiply(0.02).add(pie.Image(b)))
.rename("EMM");
var thermal = image.select("B10").multiply(0.1);
var EM_LOG = EM.log();
var FenMU = thermal.divide(1.438).multiply(0.00115);
var Fenmu2 = FenMU.multiply(EM_LOG).add(1.0);
var LST = thermal.divide(Fenmu2).subtract(273.15).rename("LST");
//计算最大值最小值
var LST_max = LST.reduceRegion(pie.Reducer.max(), roi, reduceScale).get(
"LST"
);
LST_max = pie.Number(LST_max);
var LST_min = LST.reduceRegion(pie.Reducer.min(), roi, reduceScale).get(
"LST"
);
LST_min = pie.Number(LST_min);
var nORLST = LST.subtract(LST_min).divide(LST_max.subtract(LST_min));
return nORLST;
}
//计算 MNDWI (水体分布)
function mNDWI(image, roi) {
var b3 = image.select("B3");
var b6 = image.select("B6");
var mNDWI = b3.subtract(b6).divide(b3.add(b6)).rename("mNDWI");
var mNDWI_max = mNDWI
.reduceRegion(pie.Reducer.max(), roi, reduceScale)
.get("mNDWI");
mNDWI_max = pie.Number(mNDWI_max);
var mNDWI_min = mNDWI
.reduceRegion(pie.Reducer.min(), roi, reduceScale)
.get("mNDWI");
mNDWI_min = pie.Number(mNDWI_min);
//归一化
var nORmNDWI = mNDWI
.subtract(mNDWI_min)
.divide(mNDWI_max.subtract(mNDWI_min));
return nORmNDWI;
}
// 植被覆盖度计算
function l8FVC(img, roi) {
var B4 = img.select("B4");
var B5 = img.select("B5");
var NDVI = B5.subtract(B4).divide(B5.add(B4)).rename("NDVI");
//4.计算京津冀范围FVC
//计算区域内NDVI最大值
var NDVI_max = NDVI.reduceRegion(pie.Reducer.max(), roi, reduceScale).get(
"NDVI"
);
NDVI_max = pie.Number(NDVI_max);
//计算区域内NDVI最小值
var NDVI_min = NDVI.reduceRegion(pie.Reducer.min(), roi, reduceScale).get(
"NDVI"
);
NDVI_min = pie.Number(NDVI_min);
//反演区域植被覆盖度并加载
var img_FVC = NDVI.subtract(NDVI_min).divide(NDVI_max.subtract(NDVI_min));
return img_FVC;
}
//计算 NDBI 建筑物密度
function l8NDBI(img, roi) {
var B5 = img.select("B5");
var B6 = img.select("B6");
var NDBI = B6.subtract(B5).divide(B6.add(B5)).rename("NDBI");
//计算最大值最小值
var NDBI_max = NDBI.reduceRegion(pie.Reducer.max(), roi, reduceScale).get(
"NDBI"
);
NDBI_max = pie.Number(NDBI_max);
var NDBI_min = NDBI.reduceRegion(pie.Reducer.min(), roi, reduceScale).get(
"NDBI"
);
NDBI_min = pie.Number(NDBI_min);
var nORNDBI = NDBI.subtract(NDBI_min).divide(NDBI_max.subtract(NDBI_min));
return nORNDBI;
}
// NO2 去云函数
function cloudMask(image) {
var k = image.updateMask(image.select("cloud_fraction").lt(0.2));
return k.select("tropospheric_NO2_column_number_density");
} //NO2 去云
function normalNO2(startDate, endDate, roi) {
//加载对二氧化氮进行监测的近实时数据流产品数据
var NO2cOLL = pie
.ImageCollection("S5P/OFFL_L3_NO2")
.filterBounds(roi)
.filterDate(startDate, endDate);
var NO2IMG = NO2cOLL.select([
"tropospheric_NO2_column_number_density",
"cloud_fraction",
]).map(cloudMask);
NO2IMG = NO2IMG.mean().clip(roi).rename("NO2");
var NO23_max = NO2IMG.reduceRegion(pie.Reducer.max(), roi, 7000).get("NO2");
NO23_max = pie.Number(NO23_max);
var NO23_min = NO2IMG.reduceRegion(pie.Reducer.min(), roi, 7000).get("NO2");
NO23_min = pie.Number(NO23_min);
var NORNO23 = NO2IMG.subtract(NO23_min).divide(NO23_max.subtract(NO23_min));
return NORNO23;
}
// O3 去云函数
function cloudMask_O3(image) {
var k = image.updateMask(image.select("cloud_fraction").lt(0.2));
return k.select("O3_column_number_density");
}
function normalO3(startDate, endDate, roi) {
var O3 = pie
.ImageCollection("S5P/OFFL_L3_O3")
.filterBounds(roi)
.filterDate(startDate, endDate);
var O33 = O3.select(["O3_column_number_density", "cloud_fraction"])
.map(cloudMask_O3)
.mean()
.clip(roi)
.rename("O3");
var O33_max = O33.reduceRegion(pie.Reducer.max(), roi, 7500).get("O3");
O33_max = pie.Number(O33_max);
var O33_min = O33.reduceRegion(pie.Reducer.min(), roi, 7500).get("O3");
O33_min = pie.Number(O33_min);
var NORO33 = O33.subtract(O33_min).divide(O33_max.subtract(O33_min));
return NORO33;
}
//SO2 去云
function cloudMask_SO2(image) {
var k = image.updateMask(image.select("cloud_fraction").lt(0.2));
return k.select("SO2_column_number_density");
}
function normalSO2(startDate, endDate, roi) {
var SO2 = pie
.ImageCollection("S5P/OFFL_L3_SO2")
.filterBounds(roi)
.filterDate(startDate, endDate);
var SO23 = SO2.select(["SO2_column_number_density", "cloud_fraction"])
.map(cloudMask_SO2)
.mean()
.clip(roi)
.rename("SO2");
var SO23_max = SO23.reduceRegion(pie.Reducer.max(), roi, 7500).get("SO2");
SO23_max = pie.Number(SO23_max);
var SO23_min = SO23.reduceRegion(pie.Reducer.min(), roi, 7500).get("SO2");
SO23_min = pie.Number(SO23_min);
//归一化
var NORSO23 = SO23.subtract(SO23_min).divide(SO23_max.subtract(SO23_min));
//加载春季SO2影像
return NORSO23;
}
//CO 指标归一化
function normalCO(startDate, endDate, roi) {
var CO3 = pie
.ImageCollection("S5P/OFFL_L3_CO")
.filterBounds(roi)
.filterDate(startDate, endDate)
.select("CO_column_number_density")
.mean()
.clip(roi)
.rename("CO");
var CO3_max = CO3.reduceRegion(pie.Reducer.max(), roi, 7500).get("CO");
CO3_max = pie.Number(CO3_max);
var CO3_min = CO3.reduceRegion(pie.Reducer.min(), roi, 7500).get("CO");
CO3_min = pie.Number(CO3_min);
var NORCO3 = CO3.subtract(CO3_min).divide(CO3_max.subtract(CO3_min));
return NORCO3;
}
//计算空气质量
function normalAQI(startDate, endDate, roi) {
var co = normalCO(startDate, endDate, roi);
var so2 = normalSO2(startDate, endDate, roi);
var o3 = normalO3(startDate, endDate, roi);
var no2 = normalNO2(startDate, endDate, roi);
var AQI5 = no2
.multiply(0.25)
.add(o3.multiply(0.25))
.add(so2.multiply(0.25))
.add(co.multiply(0.25))
.rename("AQI5");
//计算最大值最小值
var AQI5_max = AQI5.reduceRegion(pie.Reducer.max(), roi, 7500).get("AQI5");
AQI5_max = pie.Number(AQI5_max);
var AQI5_min = AQI5.reduceRegion(pie.Reducer.min(), roi, 7500).get("AQI5");
AQI5_min = pie.Number(AQI5_min);
//归一化
var NORAQI5 = AQI5.subtract(AQI5_min)
.divide(AQI5_max.subtract(AQI5_min))
.rename("NORAQI5");
//加载夏季AQI影像
return NORAQI5;
}
//计算生态环境质量
function cacluateEI(startDate, endDate, img, roi) {
var fvc = l8FVC(img, roi);
var lst = LSTMap(img, roi);
var ndbi = l8NDBI(img, roi);
var water = mNDWI(img, roi);
if (selectYear == "2020") {
var AQI = normalAQI(startDate, endDate, roi);
var eI = fvc
.multiply(0.2465)
.subtract(ndbi.multiply(0.1308))
.add(water.multiply(0.1863))
.subtract(AQI.multiply(0.3688))
.subtract(lst.multiply(0.0676))
.rename("EI");
} else {
// 绿地0.4094,建筑0.2047,水0.2895,LST0.0965
print("selectYear:", selectYear);
var eI = fvc
.multiply(0.4094)
.subtract(ndbi.multiply(0.2047))
.add(water.multiply(0.2895))
.subtract(lst.multiply(0.0965))
.rename("EI");
}
var eI_max = eI.reduceRegion(pie.Reducer.max(), roi, reduceScale).get("EI");
eI_max = pie.Number(eI_max);
var eI_min = eI.reduceRegion(pie.Reducer.min(), roi, reduceScale).get("EI");
eI_min = pie.Number(eI_min);
//归一化
var norEI = eI
.subtract(eI_min)
.divide(eI_max.subtract(eI_min))
.rename("norEI");
return norEI.clip(all_region.first().geometry());
}
// 主函数 , 控制整体流程
function cacluateVI(roi, startDate, tag) {
//影像集合
var endDate = pie.Date(startDate).advance(4, "month");
var l8Col = pie
.ImageCollection("LC08/01/T1_SR")
.filterBounds(roi)
.filterDate(startDate, endDate)
.filter(pie.Filter.lt("cloudCover", 30));
//通过日期过滤影像集合,并且计算指数
l8Col = l8Col
.select(["B2", "B3", "B4", "B5", "B6", "B7", "B10", "pixel_qa"])
.map(function (image) {
// Bits 3 and 5 are cloud shadow and cloud, respectively.
var cloudShadowBitMask = 1 << 3;
var cloudsBitMask = 1 << 5;
// Get the pixel QA band.
var qa = image.select("pixel_qa");
// Both flags should be set to zero, indicating clear conditions.
var mask = qa
.bitwiseAnd(cloudShadowBitMask)
.eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
return image.updateMask(mask);
});
l8Col = l8Col.select(["B2", "B3", "B4", "B5", "B6", "B7", "B10"]);
var l8image = l8Col.mean().clip(roi);
switch (tag) {
case "EI":
var eImap = cacluateEI(startDate, endDate, l8image, roi);
var viseImap = { min: 0, max: 0.85, palette: colors2 };
layerKey = Map.addLayer(eImap, viseImap, "EI", true);
addMapLenged("EI");
break;
case "FVC":
var imgFVC = l8FVC(l8image, roi);
layerKey = Map.addLayer(
imgFVC,
{ min: 0, max: 0.9, palette: colors2 },
"FVC",
true
);
addMapLenged("FVC");
break;
case "LST":
var imgLST = LSTMap(l8image, roi);
layerKey = Map.addLayer(
imgLST,
{ min: 0, max: 0.9, palette: colors },
"LST",
true
);
addMapLenged("LST");
break;
case "MNDWI":
var imgMNDWI = mNDWI(l8image, roi);
layerKey = Map.addLayer(
imgMNDWI,
{ min: 0, max: 0.9, palette: colors2 },
"MNDWI",
true
);
addMapLenged("MNDWI");
break;
case "NDBI":
var ndbiimg = l8NDBI(l8image, roi);
//设置NDBI影像预览参数与颜色组合
layerKey = Map.addLayer(
ndbiimg,
{ min: 0, max: 0.9, palette: colors1 },
"NDBI",
true
);
addMapLenged("NDBI");
break;
case "SO2":
var so2img = normalSO2(startDate, endDate, roi);
layerKey = Map.addLayer(so2img, visAQI, "SO2", true);
addMapLenged("SO2");
break;
case "NO2":
var no2img = normalNO2(startDate, endDate, roi);
layerKey = Map.addLayer(no2img, visAQI, "SO2", true);
addMapLenged("SO2");
break;
case "CO":
var coimg = normalCO(startDate, endDate, roi);
layerKey = Map.addLayer(coimg, visAQI, "CO", true);
addMapLenged("CO");
break;
case "O3":
var o3img = normalO3(startDate, endDate, roi);
layerKey = Map.addLayer(o3img, visAQI, "O3", true);
addMapLenged("O3");
break;
case "AQI":
var AQIimg = normalAQI(startDate, endDate, roi);
layerKey = Map.addLayer(AQIimg, visAQI, "AQI Quality", true);
addMapLenged("AQI");
break;
}
}
// 标题 Label
var label = ui.Label("生态宜居性评估系统-京津冀", {
"font-size": "20px",
color: "#00f",
textAlign: "center",
});
// select 选择要计算的指标
function funCascader(value, selectData) {
var index = parseInt(value.length);
selectTag = value[index - 1];
print("选择的指标为:", selectTag);
}
// 指标选择级联控件
var cascader = ui.Cascader({
placeholder: "请选择",
content: [
{
value: "FVC",
label: "植被覆盖度",
},
{
value: "MNDWI",
label: "水体分布",
},
{
value: "LST",
label: "地表温度",
},
{
value: "NDBI",
label: "建筑物密度",
},
{
value: "AQI",
label: "空气质量",
children: [
{
value: "SO2",
label: "二氧化硫",
},
{
value: "CO",
label: "一氧化碳",
},
{
value: "NO2",
label: "二氧化氮",
},
{
value: "O3",
label: "臭氧",
},
],
},
{
value: "EI",
label: "生态环境质量",
},
],
value: ["FVC"],
style: { width: "220px" },
onChange: funCascader,
});
var selectName = ui.Label("选择指标:");
var selectPanel = ui.Panel({
widgets: [selectName, cascader],
style: { left: "10px" },
layout: ui.Layout.flow("horizontal"),
});
// 地区选择回调函数
function inputArea(codeList, nameList) {
var index = nameList.length;
if (index <= 0) {
selectCode = "";
countyname = "";
} else {
selectCode = nameList[index - 1].value;
countyname = nameList[index - 1].label;
}
}
// 地区选择级联控件
var cascader_region = ui.GeoCascader({
// 可以通过init自定义显示内容
init: {
list: ["province", "city", "county"],
province: ["河北省", "北京市", "天津市"],
},
placeholder: "请选择",
onChange: inputArea,
});
var textboxName3 = ui.Label("行政区划:");
// 地区选择容器
var textboxPanel3 = ui.Panel({
widgets: [textboxName3, cascader_region],
style: { left: "10px", width: "400px" },
layout: ui.Layout.flow("horizontal"),
});
// 确定显示级别 回调函数
var showLevelLabel = ui.Label("显示级别:");
function funRadio(value) {
region_level = value;
}
// 计算区域 单选控件
var radio_region = ui.Radio({
label: ["All", "Province", "City", "District"],
value: "District",
onChange: funRadio,
disabled: false,
});
var show_level_Panel = ui.Panel({
widgets: [showLevelLabel, radio_region],
style: { left: "10px", width: "350px" },
layout: ui.Layout.flow("horizontal"),
});
// TextBox
function seanson2Date(senson) {
// 将季节转化为日期
print("选择的季节是", senson);
switch (senson) {
case "spring":
selectStartDate = selectYear + "-3-1";
seasonindex = 0;
break;
case "summer":
selectStartDate = selectYear + "-6-1";
seasonindex = 1;
break;
case "fall":
selectStartDate = selectYear + "-9-1";
seasonindex = 2;
break;
case "winter":
selectStartDate = selectYear + "-12-1";
seasonindex = 3;
break;
}
return selectStartDate;
}
//季节选择回调函数
function inputSDate(value) {
selectSeason = value;
}
//季节选择列表控件
var selectSeason = ui.Select({
items: ["spring", "summer", "fall", "winter"],
placeholder: "请选择季节",
value: selectSenson,
onChange: inputSDate,
disabled: false,
});
var textboxName1 = ui.Label("显示季节:");
var textboxPanel1 = ui.Panel({
widgets: [textboxName1, selectSeason],
style: { left: "10px", width: "300px" },
layout: ui.Layout.flow("horizontal"),
});
//年份滑块
function yearSlide(value) {
selectYear = value;
print("选择年份为:", value);
}
//年份选择滑块
var yearSlider = ui.Slider({
min: 2018,
max: 2020,
value: selectYear,
step: 1,
onChange: yearSlide,
style: { bottom: "0px", width: "500px" },
});
var sliderLabel = ui.Label("年份:", { bottom: "-10px" });
var sliderPanel = ui.Panel({
widgets: [sliderLabel, yearSlider],
style: { width: "580px", height: "55px", bottom: "10px", left: "450px" },
layout: ui.Layout.flow("horizontal"),
});
Map.addUI(sliderPanel);
// Button
function clickBtn() {
print(
"点击按钮,选择的参数是:",
selectCode + ":" + selectTag + ":" + selectSenson
);
if (layerKey != null) {
Map.removeLayer(layerKey);
print("layerKey", layerKey);
} //清空现有层
roi = getROI(selectCode);
var startdate = seanson2Date(selectSenson);
cacluateVI(roi, startdate, selectTag);
}
function cancelclickBtn() {
if (layerKey != null) {
Map.removeLayer(layerKey);
} //清空现有层
if (roilayerKey != null) {
Map.removeLayer(roilayerKey);
}
// DOM 操作:重启系统
var restbtn = document.getElementsByClassName("toolButton")[3];
restbtn.click();
var runbtn = document.getElementsByClassName("toolButton")[2];
runbtn.click();
}
var btn1 = ui.Button({
label: "清空",
style: { left: "40px" },
onClick: cancelclickBtn,
});
var btn2 = ui.Button({
label: "显示",
type: "success",
onClick: clickBtn,
style: { left: "70px", top: "0px" },
});
var btnPanel = ui.Panel({
widgets: [btn1, btn2],
style: { left: "0px", top: "20px" },
layout: ui.Layout.flow("horizontal"),
});
// 每个指标的逐季节平均值
var meanData = {
FVC: [0.5, 0.68, 0.57, 0.39],
LST: [0.71, 0.81, 0.64, 0.34],
MNDWI: [0.27, 0.23, 0.25, 0.38],
NDBI: [0.65, 0.43, 0.59, 0.65],
AQI: [0.43, 0.4, 0.45],
EI: [0.47, 0.55, 0.51, 0.49],
};
// seanson 转化为 索引
//统计部分
var staticIndes = ["MNDWI", "FVC", "NDBI"];
var staticLabel = ui.Label("统计指标:");
function staticIndex(value) {
staticIndes = value;
print("staticIndes", staticIndes);
}
var staticIndexcheckbox = ui.Checkbox({
label: ["EI", "MNDWI", "FVC", "NDBI", "LST", "AQI"],
value: staticIndes,
style: { width: "220px" },
onChange: staticIndex,
});
var staticIndexPanel = ui.Panel({
widgets: [staticLabel, staticIndexcheckbox],
style: { left: "10px" },
layout: ui.Layout.flow("horizontal"),
});
var showsStyleLabel = ui.Label("图表类型:");
function showStyleFunRadio(value) {
charttype = value;
print("图表类型为:", charttype);
}
var showStyleradio = ui.Radio({
label: ["bar", "column", "line"],
value: "bar",
onChange: showStyleFunRadio,
disabled: false,
});
var showStyle_Panel = ui.Panel({
widgets: [showsStyleLabel, showStyleradio],
style: { left: "10px", width: "350px" },
layout: ui.Layout.flow("horizontal"),
});
var timeSriesLabel = ui.Label("统计方式:");
function timeSriesFunRadio(value) {
staticType = value;
print("统计方式:", staticType);
}
var timeSriesradio = ui.Radio({
label: ["Season", "TimeSeries"],
value: "Season",
onChange: timeSriesFunRadio,
disabled: false,
});
var timeSries_Panel = ui.Panel({
widgets: [timeSriesLabel, timeSriesradio],
style: { left: "10px", width: "350px" },
layout: ui.Layout.flow("horizontal"),
});
function btn_staticClearBtn() {
var restbtn = document.getElementsByClassName("toolButton")[3];
restbtn.click();
var runbtn = document.getElementsByClassName("toolButton")[2];
print(runbtn);
runbtn.click();
}
var btn_static_clear = ui.Button({
label: "清空",
style: { left: "40px" },
onClick: btn_staticClearBtn,
});
// 数据统计 按照季节进行柱状图统计:
// 调用绘制方法,输出图表显示在结果面板中
// 柱状图统计: 指定年份的季节性
function colum_static() {
var col_data = [];
for (var i = 0; i < staticIndes.length; i++) {
col_data.push(
staticData[String(selectCode)][String(selectYear)][staticIndes[i]]
);
}
var chart_options = {};
if (charttype == "bar") {
chart_options = {
title: countyname + " " + selectYear + "年" + "环境指标逐季节变化情况",
legend: staticIndes,
yAxis: ["spring", "summer", "fall", "winter"],
xAxisName: "value",
yAxisName: "季节",
series: col_data,
chartType: charttype,
};
} else if (charttype == "column" || charttype == "line") {
chart_options = {
title: countyname + " " + selectYear + "年" + "环境指标逐季节变化情况",
legend: staticIndes,
xAxis: ["spring", "summer", "fall", "winter"],
xAxisName: "季节",
yAxisName: "value",
series: col_data,
chartType: charttype,
};
}
print(chart_options);
var chart = ui.Chart.array(chart_options);
chart.setStyle({
width: "500px",
height: "300px",
top: "50px",
right: "1px",
});
Map.addUI(chart);
}
// 时间序列统计
function time_static() {
var years = ["2018", "2019", "2020"];
var multiIndesData = [];
for (var i = 0; i < staticIndes.length; i++) {
var timeSeriesData = [];
for (var j = 0; j < years.length; j++) {
teamData = staticData[selectCode][years[j]][staticIndes[i]];
timeSeriesData = timeSeriesData.concat(teamData);
}
multiIndesData.push(timeSeriesData);
}
var chart_options = {
title: countyname + " " + "全时间序列" + "生态环境指标变化情况",
legend: staticIndes,
xAxis: [
"2018春",
"2018夏",
"2018秋",
"2018冬",
"2019春",
"2019夏",
"2019秋",
"2019冬",
"2020春",
"2020夏",
"2020秋",
],
xAxisName: "Time",
yAxisName: "各个指标",
series: multiIndesData,
chartType: "line",
smooth: true,
};
var chart = ui.Chart.array(chart_options);
chart.setStyle({ width: "500px", top: "50px", right: "1px" });
Map.addUI(chart);
}
// 根据EI 值对地区进行评级:
function classEI() {
// 实际值减去平均值
var subvalueEI =
staticData[selectCode][selectYear]["EI"][seasonindex] -
meanData["EI"][seasonindex];
var sublist = [];
if (parseFloat(subvalueEI) > 0.045) {
// 大于一倍标准差
environmetClass = 1;
} else if (parseFloat(subvalueEI) > 0) {
//大于均值
environmetClass = 2;
} else if (parseFloat(subvalueEI) > -0.045) {
//小于均值
environmetClass = 3;
} else {
environmetClass = 4;
}
//
var subFVC =
staticData[selectCode][selectYear]["FVC"][seasonindex] -
meanData["FVC"][seasonindex];
if (subFVC < -0.09) {
sublist.push(["FVC", subFVC]);
}
var subLST =
staticData[selectCode][selectYear]["LST"][seasonindex] -
meanData["LST"][seasonindex];
if (subLST > 0.08) {
sublist.push(["LST", subLST]);
}
var subNDBI =
staticData[selectCode][selectYear]["NDBI"][seasonindex] -
meanData["NDBI"][seasonindex];
if (subNDBI > 0.12) {
sublist.push(["NDBI", subNDBI]);
}
var subMNDWI =
staticData[selectCode][selectYear]["MNDWI"][seasonindex] -
meanData["MNDWI"][seasonindex];
if (subMNDWI < -0.1) {
sublist.push(["MNDWI", subMNDWI]);
}
if (selectYear == "2020") {
var subAQI =
staticData[selectCode][selectYear]["AQI"][seasonindex] -
meanData["AQI"][seasonindex];
if (subAQI > 0.1) {
sublist.push(["AQI", subAQI]);
}
}
return sublist;
}
// 统计各个指标数据并给出建议
function suggestPart() {
var index2char = {
FVC: "植被密度, ",
NDBI: "建筑物/裸地密度, ",
MNDWI: "水体数量, ",
LST: "地表温度, ",
AQI: "空气质量, ",
};
var indesQuality = classEI();
// var classENV = indesQuality[indesQuality.length-1] // 环境等级
var sign = "";
var strindes = "";
for (var k = 0; k < indesQuality.length; k++) {
var index = indesQuality[k][0]; // 每种标识
charindex = index2char[index];
strindes += charindex;
var indexsubvalue = indesQuality[k][1];
if (indexsubvalue > 0) {
sign = sign + index + "高于预警值,";
} else {
sign = sign + index + "低于预警值,";
}
}
environmetClasstoChart = ["优", "良", "中(预警)", "差"];
var signChart = "目前该地区:" + sign + "建议加强对" + strindes + "的管理";
if (parseInt(indesQuality.length) < 1) {
signChart = "目前该地区各生态环境指标正常";
}
var suggestTable = ui.Table({
items: [
{
name: countyname,
time: selectYear + " " + selectSenson,
result: "生态宜居性为: " + environmetClasstoChart[environmetClass - 1],
info: signChart,
},
],
columns: [
{
title: "地区",
key: "name",
width: "100px",
align: "center",
},
{
title: "时间",
key: "time",
width: "100px",
align: "center",
},
{
title: "评估结果",
key: "result",
width: "100px",
align: "center",
},
{
title: "建议",
key: "info",
width: "200px",
align: "center",
},
],
});
return suggestTable;
}
// 宜居性评估结果 表
function btn_staticclickBtn() {
if (staticType == "Season") {
colum_static();
} else if (staticType == "TimeSeries") {
time_static();
}
var suggestTable = suggestPart();
var suggestPanel = ui.Panel({
widgets: [suggestTable],
style: {
width: "500px",
right: "5px",
top: "380px",
border: "4px double #0bcbfb",
},
});
Map.addUI(suggestPanel);
}
// 统计按钮
var btn_static_success = ui.Button({
label: "统计",
type: "success",
onClick: btn_staticclickBtn,
style: { left: "70px", top: "0px" },
});
var btnPanel_s = ui.Panel({
widgets: [btn_static_clear, btn_static_success],
style: { left: "0px", top: "10px" },
layout: ui.Layout.flow("horizontal"),
});
//统计部分控件容器
var staticPanel = ui.Panel({
widgets: [staticIndexPanel, showStyle_Panel, timeSries_Panel, btnPanel_s],
style: {
left: "3px",
width: "350px",
height: "250px",
top: "5px",
border: "1px double #ababab",
},
layout: ui.Layout.flow("vertical"),
});
var mapPanel = ui.Panel({
widgets: [
selectPanel,
textboxPanel3,
show_level_Panel,
textboxPanel1,
btnPanel,
],
style: {
left: "3px",
width: "350px",
height: "300px",
top: "10px",
border: "1px double #ababab",
},
layout: ui.Layout.flow("vertical"),
});
// 整体的控件容器
var panel_control = ui.Panel({
widgets: [label, mapPanel, staticPanel],
style: {
width: "370px",
height: "350px",
left: "40px",
top: "50px",
backgroundColor: "#fff",
border: "3px solid #00afaf",
},
});
Map.addUI(panel_control);