Algorithms—50.Pow(x, n)

思路:为了降低耗时要考虑各种情况直接return。

public class Solution {
    public double myPow(double x, int n) {
    	if (n==0) {
			return 1.0;
		}
    	boolean flag=true;
    	if (n<0) {
			n=0-n;
			flag=false;
		}
    	boolean slag=true;
    	if (x<0) {
			x=0-x;
			if (n%2!=0) {
				slag=false;
			}
		}
    	if (x==1.0) {
			return slag?1.0:-1.0;
		}
    	double answer=1.0;
        for (int i = 0; i < n; i++) {
        	answer*=x;
        	if (answer==0.0) {
				return answer;
			}
		}
    	return flag?(slag?answer:-answer):(slag?1/answer:-1/answer);
    }
}


耗时:336ms。下游水准,尝试优化了下也没有什么好的思路。


// ================= 1. 基础配置与数据源 ================= var CHIRPS = ee.ImageCollection("UCSB-CHG/CHIRPS/PENTAD"), soilData = ee.Image("OpenLandMap/SOL/SOL_TEXTURE-CLASS_USDA-TT_M/v02"), DEM = ee.Image("USGS/SRTMGL1_003"), aoi = ee.FeatureCollection("projects/ee-20241200080/assets/xiangjiang"); var analysisYear = 2020; var targetScale = 250; var exportRootFolder = "Lishui_" + analysisYear; var factorFolder = "RUSLE_Factors_Lishui"; var modulusFolder = "Erosion_Modulus_Lishui"; Map.centerObject(aoi, 9); Map.addLayer(aoi, {color: 'FF0000', fillColor: '00000000'}, '澧水流域边界'); var areaHectares = ee.Image.pixelArea().divide(10000).rename('area_ha'); // ================= 2. 先计算所有RUSLE因子 ================= // K因子计算 function calculateK_Corrected(soilData, aoi) { var soilClip = soilData.clip(aoi); var K = soilClip.expression( "b('b0') == 1 ? 0.035 : b('b0') == 2 ? 0.040 : " + "b('b0') == 3 ? 0.045 : b('b0') == 4 ? 0.050 : " + "b('b0') == 5 ? 0.035 : b('b0') == 6 ? 0.048 : " + "b('b0') == 7 ? 0.055 : b('b0') == 8 ? 0.055 : " + "b('b0') == 9 ? 0.050 : b('b0') == 10 ? 0.025 : " + "b('b0') == 11 ? 0.010 : 0.04", {'b0': soilClip.select('b0')} ).rename('K'); return K.clip(aoi).unmask(0.045); } var K = calculateK_Corrected(soilData, aoi); // ================= R 因子计算(修正版 - 使用PENTAD数据正确聚合) ================= var months = ee.List.sequence(1, 12); var monthlyR = months.map(function(month) { month = ee.Number(month); var startDate = ee.Date.fromYMD(analysisYear, month, 1); var endDate = startDate.advance(1, 'month'); // 使用PENTAD数据,但正确聚合为月数据 var monthlyPrecip = CHIRPS.filterDate(startDate, endDate) .select('precipitation') .sum() // 将候数据累加为月降雨量 .clip(aoi); // 章文波公式 var Ri = monthlyPrecip.expression( '0.0585 * pow(P, 1.56)', { 'P': monthlyPrecip } ).rename('R'); return Ri.set('month', month); }); var R_monthly = ee.ImageCollection(monthlyR); var R = R_monthly.sum().rename('R'); // LS因子计算 var demClip = DEM.clip(aoi).resample('bilinear') .reproject({crs: 'EPSG:4326', scale: targetScale}); var slopeDeg = ee.Terrain.slope(demClip); var slopeRad = slopeDeg.multiply(Math.PI).divide(180); var flowAcc = ee.Image("WWF/HydroSHEDS/15ACC").clip(aoi) .resample('bilinear').reproject({crs: 'EPSG:4326', scale: targetScale}); var flowArea = flowAcc.multiply(ee.Number(targetScale).pow(2)); var slopeLength = flowArea.sqrt().min(300); var mExp = slopeRad.expression( "slope < 0.05 ? 0.2 : slope < 0.10 ? 0.3 : slope < 0.15 ? 0.4 : slope < 0.25 ? 0.5 : 0.6", {'slope': slopeRad} ); var L = slopeLength.divide(22.13).pow(mExp).rename('L').unmask(1); var S = slopeRad.expression( "slope < 0.05 ? 10.8 * sin(slope) + 0.03 : " + "slope < 0.10 ? 16.8 * sin(slope) - 0.30 : " + "slope < 0.15 ? 21.9 * sin(slope) - 0.70 : " + "slope < 0.25 ? 31.6 * sin(slope) - 1.50 : " + "45.2 * sin(slope) - 2.50", {'slope': slopeRad} ).rename('S').unmask(0.05); var LS = L.multiply(S).rename('LS') .updateMask(L.gt(0).and(S.gt(0))) .clip(aoi).unmask(0.1); // C因子计算 - 优化参数 var modisLulc = ee.ImageCollection("MODIS/006/MCD12Q1") .filterDate(ee.Date.fromYMD(analysisYear, 1, 1), ee.Date.fromYMD(analysisYear, 12, 31)) .first().select('LC_Type1').clip(aoi) .resample('bilinear').reproject({crs: 'EPSG:4326', scale: targetScale}); var modisNDVI = ee.ImageCollection('MODIS/006/MOD13Q1') .filterDate(ee.Date.fromYMD(analysisYear, 1, 1), ee.Date.fromYMD(analysisYear, 12, 31)) .filterBounds(aoi).select('NDVI'); var monthlyC = ee.List.sequence(1, 12).map(function(month) { month = ee.Number(month); var monthStart = ee.Date.fromYMD(analysisYear, month, 1); var monthEnd = monthStart.advance(1, 'month'); var monthNdviCol = modisNDVI.filterDate(monthStart, monthEnd); var monthNdvi = ee.Algorithms.If( monthNdviCol.size().gt(0), monthNdviCol.mean().clip(aoi), modisNDVI.filterDate(monthStart.advance(-1, 'month'), monthEnd.advance(1, 'month')).mean().clip(aoi) ); monthNdvi = ee.Image(monthNdvi).multiply(0.0001).unmask(0.3); var FVC = monthNdvi.subtract(0.05).divide(0.75).clamp(0, 1); var cNdvi = FVC.expression("exp(-2.0 * fvc)", {'fvc': FVC}).clamp(0.001, 1); // 调整系数 var cLulc = modisLulc.remap( ee.List.sequence(1, 17), [0.002, 0.003, 0.004, 0.006, 0.005, 0.020, 0.05, 0.10, 0.15, 0.22, 0.015, 0.45, 0.65, 0.35, 0.001, 0.001, 0.75], 0.35 ); return cNdvi.min(cLulc).clamp(0.001, 1).rename('C').set('month', month); }); var C_monthly = ee.ImageCollection(monthlyC); var C = C_monthly.mean().rename('C').clip(aoi).unmask(0.15); // 调整默认值 // P因子计算 - 优化参数 var lulcBaseP = ee.Dictionary({ 1: 0.02, 2: 0.02, 3: 0.02, 4: 0.02, 5: 0.02, 6: 0.035, 7: 0.09, 8: 0.15, 9: 0.22, 10: 0.28, 11: 0.001, 12: 0.65, 13: 0.90, 14: 0.45, 15: 0.001, 16: 0.001, 17: 0.65 }); var monthlyAdjust = ee.List([1.4, 1.35, 1.3, 1.25, 1.2, 1.1, 1.0, 0.9, 0.85, 0.8, 0.75, 0.7]); // 调整月度系数 var monthlyP = ee.List.sequence(1, 12).map(function(month) { month = ee.Number(month); var monthStart = ee.Date.fromYMD(analysisYear, month, 1); var monthEnd = monthStart.advance(1, 'month'); var monthNdviCol = modisNDVI.filterDate(monthStart, monthEnd); var monthNdvi = ee.Algorithms.If( monthNdviCol.size().gt(0), monthNdviCol.mean().clip(aoi), modisNDVI.filterDate(monthStart.advance(-1, 'month'), monthEnd.advance(1, 'month')).mean().clip(aoi) ); monthNdvi = ee.Image(monthNdvi).multiply(0.0001).unmask(0.3); var FVC = monthNdvi.subtract(0.05).divide(0.75).clamp(0, 1).pow(1.5); var baseP = modisLulc.remap(ee.List.sequence(1, 17), lulcBaseP.values(), 0.6); // 调整默认值 var adjust = ee.Image.constant(monthlyAdjust.get(month.subtract(1))); var slopeAdjustedP = baseP.multiply( ee.Image(1.0).expression( "1.0 * (slope < 8 ? 0.8 : slope < 20 ? 1.0 : slope < 35 ? 1.4 : 2.0)", {'slope': slopeDeg} ) ); return slopeAdjustedP.multiply(adjust) .multiply(ee.Image(1).subtract(FVC).add(0.25)) // 调整系数 .clamp(0.15, 1.0) .rename('P') .set('month', month); }); var P_monthly = ee.ImageCollection(monthlyP); var P = P_monthly.mean().rename('P').clip(aoi).unmask(0.35); // 调整默认值 // ================= 3. 侵蚀模数计算 ================= function getMonthName(monthNum) { var monthNames = ee.List(['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']); return ee.String(monthNames.get(ee.Number(monthNum).subtract(1))); } var K_250m = K.resample('bilinear').reproject({crs: 'EPSG:4326', scale: targetScale}); var LS_250m = LS.resample('bilinear').reproject({crs: 'EPSG:4326', scale: targetScale}); var monthlyErosionModulus = ee.List.sequence(1, 12).map(function(month) { month = ee.Number(month); var monthFilter = ee.Filter.eq('month', month); var monthR = R_monthly.filter(monthFilter).first().select('R'); var monthC = C_monthly.filter(monthFilter).first(); var monthP = P_monthly.filter(monthFilter).first(); var monthR_fixed = monthR.unmask(0); var monthC_fixed = monthC.unmask(0.15); var monthP_fixed = monthP.unmask(0.35); var monthModulus = monthR_fixed.multiply(K_250m).multiply(LS_250m) .multiply(monthC_fixed).multiply(monthP_fixed).rename('Erosion_Modulus'); var monthPixelModulus = monthModulus.divide(areaHectares).rename('Pixel_Erosion_Modulus'); var monthResult = monthModulus.addBands(monthPixelModulus) .set('month', month).set('period_name', getMonthName(month)); return monthResult; }); var monthlyModulusCollection = ee.ImageCollection(monthlyErosionModulus); var annualModulus = monthlyModulusCollection.sum().select('Erosion_Modulus').rename('Annual_Modulus'); var annualPixelModulus = annualModulus.divide(areaHectares).rename('Annual_Pixel_Modulus'); // ================= 4. 可视化设置 ================= // 调整可视化范围以匹配新R因子计算 var modulusVis = { min: 0, max: 50, // 调整最大值 palette: ['#f7fcf5','#e5f5e0','#c7e9c0','#a1d99b','#74c476','#41ab5d','#238b45','#006d2c','#00441b'] }; var pixelModulusVis = { min: 0, max: 5, // 调整最大值 palette: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'] }; // R因子可视化调整 var RVis = { min: 0, max: 2000, // 新公式下的合理范围 palette: ['blue', 'cyan', 'green', 'yellow', 'red'] }; // 侵蚀等级划分调整 - 只显示在区域内 var erosionLevels = annualModulus .where(annualModulus.lt(5), 1) .where(annualModulus.gte(5).and(annualModulus.lt(15)), 2) .where(annualModulus.gte(15).and(annualModulus.lt(30)), 3) .where(annualModulus.gte(30).and(annualModulus.lt(50)), 4) .where(annualModulus.gte(50).and(annualModulus.lt(100)), 5) .where(annualModulus.gte(100), 6) .rename('Erosion_Level') .clip(aoi); // 关键修改:只显示在区域内 var levelVis = { min: 1, max: 6, palette: ['#d0f0fd','#b2df8a','#ffff99','#fdbf6f','#fb8072','#b2182b'] }; // ================= 5. 完整的界面面板 ================= // 创建主控制面板 var controlPanel = ui.Panel({ style: { position: 'top-right', width: '420px', // 增加宽度以容纳更多列 maxHeight: '800px', stretch: 'vertical' } }); // 标题 controlPanel.add(ui.Label('澧水流域土壤侵蚀分析系统 (湘江流域参数)', { fontWeight: 'bold', fontSize: '18px', margin: '0 0 10px 0' })); // 年份选择器 var yearSelector = ui.Select({ items: ['2000', '2001', '2002', '2003', '2004', '2005'], value: '2001', onChange: function(year) { print('选择年份: ' + year); }, style: {width: '100%', margin: '5px 0'} }); controlPanel.add(ui.Label('选择分析年份:', {margin: '10px 0 5px 0'})); controlPanel.add(yearSelector); // 参数信息面板 var paramPanel = ui.Panel({ style: { padding: '8px', margin: '8px 0', border: '1px solid #4CAF50', backgroundColor: '#f0f9f0' } }); paramPanel.add(ui.Label('📊 参数设置说明', { fontWeight: 'bold', fontSize: '12px', margin: '0 0 5px 0', color: '#2E7D32' })); paramPanel.add(ui.Label('R因子范围: 2500-5000', {fontSize: '11px', color: '#555'})); paramPanel.add(ui.Label('K因子范围: 0.001-0.07', {fontSize: '11px', color: '#555'})); paramPanel.add(ui.Label('侵蚀模数范围: 0-100 t·hm⁻²·a⁻¹', {fontSize: '11px', color: '#555'})); controlPanel.add(paramPanel); // 月度因子统计面板 var monthlyFactorPanel = ui.Panel({ style: { padding: '10px', margin: '10px 0', border: '1px solid #ddd', backgroundColor: '#fff8f0' } }); monthlyFactorPanel.add(ui.Label('月度因子统计', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0' })); // 创建月度因子表格的函数 function createMonthlyFactorTable() { // 清除现有内容(保留标题) while (monthlyFactorPanel.widgets().length > 1) { monthlyFactorPanel.remove(monthlyFactorPanel.widgets().get(1)); } var loadingLabel = ui.Label('正在计算月度因子数据...', {color: 'gray'}); monthlyFactorPanel.add(loadingLabel); // 计算每个月的各因子平均值 var monthlyStats = ee.List.sequence(1, 12).map(function(month) { month = ee.Number(month); // 获取当月各因子 var monthFilter = ee.Filter.eq('month', month); var monthR = R_monthly.filter(monthFilter).first().select('R'); var monthC = C_monthly.filter(monthFilter).first(); var monthP = P_monthly.filter(monthFilter).first(); var monthLS = LS; // LS因子不随月份变化 // 计算平均值 var rMean = monthR.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('R'); var cMean = monthC.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('C'); var pMean = monthP.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('P'); var kMean = K.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('K'); var lsMean = monthLS.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('LS'); // 计算当月侵蚀模数 var monthModulus = monthlyModulusCollection.filter(monthFilter).first(); var modulusMean = monthModulus.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('Erosion_Modulus'); return ee.Feature(null, { 'month': month, 'R': ee.Algorithms.If(ee.Algorithms.IsEqual(rMean, null), 0, rMean), 'C': ee.Algorithms.If(ee.Algorithms.IsEqual(cMean, null), 0.2, cMean), 'P': ee.Algorithms.If(ee.Algorithms.IsEqual(pMean, null), 0.4, pMean), 'K': ee.Algorithms.If(ee.Algorithms.IsEqual(kMean, null), 0.045, kMean), 'LS': ee.Algorithms.If(ee.Algorithms.IsEqual(lsMean, null), 1.0, lsMean), 'Modulus': ee.Algorithms.If(ee.Algorithms.IsEqual(modulusMean, null), 0, modulusMean), 'month_name': getMonthName(month) }); }); var monthlyStatsCollection = ee.FeatureCollection(monthlyStats); // 异步获取数据 monthlyStatsCollection.evaluate(function(stats) { monthlyFactorPanel.remove(loadingLabel); // 创建表格标题 var headerPanel = ui.Panel({ widgets: [ ui.Label('月份', {width: '45px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('R因子', {width: '50px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('C因子', {width: '45px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('P因子', {width: '45px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('K因子', {width: '45px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('LS因子', {width: '45px', fontWeight: 'bold', fontSize: '10px'}), ui.Label('侵蚀模数', {width: '60px', fontWeight: 'bold', fontSize: '10px'}) ], layout: ui.Panel.Layout.Flow('horizontal') }); monthlyFactorPanel.add(headerPanel); // 格式化数字函数 function formatNumber(value, decimals) { if (value === null || value === undefined) return '-'; var num = Number(value); return num.toFixed(decimals); } // 添加每月数据行 stats.features.forEach(function(feature, index) { var props = feature.properties; var rowPanel = ui.Panel({ widgets: [ ui.Label(props.month_name, {width: '45px', fontSize: '10px'}), ui.Label(formatNumber(props.R, 0), {width: '50px', fontSize: '9px', color: '#0066cc'}), ui.Label(formatNumber(props.C, 3), {width: '45px', fontSize: '9px', color: '#009900'}), ui.Label(formatNumber(props.P, 3), {width: '45px', fontSize: '9px', color: '#cc6600'}), ui.Label(formatNumber(props.K, 4), {width: '45px', fontSize: '9px', color: '#8B4513'}), ui.Label(formatNumber(props.LS, 2), {width: '45px', fontSize: '9px', color: '#FF4500'}), ui.Label(formatNumber(props.Modulus, 1), {width: '60px', fontSize: '9px', color: '#cc0000', fontWeight: 'bold'}) ], layout: ui.Panel.Layout.Flow('horizontal') }); monthlyFactorPanel.add(rowPanel); }); // 添加年度平均值行 var annualR = R.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('R'); var annualC = C.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('C'); var annualP = P.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('P'); var annualK = K.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('K'); var annualLS = LS.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('LS'); var annualModulusMean = annualModulus.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('Annual_Modulus'); // 异步获取年度平均值 annualR.evaluate(function(rVal) { annualC.evaluate(function(cVal) { annualP.evaluate(function(pVal) { annualK.evaluate(function(kVal) { annualLS.evaluate(function(lsVal) { annualModulusMean.evaluate(function(mVal) { var summaryPanel = ui.Panel({ widgets: [ ui.Label('年度平均', {width: '45px', fontSize: '10px', fontWeight: 'bold'}), ui.Label(formatNumber(rVal, 0), {width: '50px', fontSize: '9px', color: '#0066cc', fontWeight: 'bold'}), ui.Label(formatNumber(cVal, 3), {width: '45px', fontSize: '9px', color: '#009900', fontWeight: 'bold'}), ui.Label(formatNumber(pVal, 3), {width: '45px', fontSize: '9px', color: '#cc6600', fontWeight: 'bold'}), ui.Label(formatNumber(kVal, 4), {width: '45px', fontSize: '9px', color: '#8B4513', fontWeight: 'bold'}), ui.Label(formatNumber(lsVal, 2), {width: '45px', fontSize: '9px', color: '#FF4500', fontWeight: 'bold'}), ui.Label(formatNumber(mVal, 1), {width: '60px', fontSize: '9px', color: '#cc0000', fontWeight: 'bold'}) ], layout: ui.Panel.Layout.Flow('horizontal') }); monthlyFactorPanel.add(ui.Label('')); // 空行分隔 monthlyFactorPanel.add(summaryPanel); // 添加RUSLE公式说明 var formulaPanel = ui.Panel({ style: { padding: '8px', margin: '8px 0', border: '1px solid #ddd', backgroundColor: '#f8f8f8' } }); formulaPanel.add(ui.Label('📐 RUSLE公式: A = R × K × LS × C × P', { fontWeight: 'bold', fontSize: '11px', margin: '0 0 4px 0' })); formulaPanel.add(ui.Label('A: 土壤侵蚀模数 (t·hm⁻²·a⁻¹)', {fontSize: '10px', color: '#555'})); formulaPanel.add(ui.Label('R: 降雨侵蚀力因子', {fontSize: '10px', color: '#555'})); formulaPanel.add(ui.Label('K: 土壤可蚀性因子', {fontSize: '10px', color: '#555'})); formulaPanel.add(ui.Label('LS: 坡长坡度因子', {fontSize: '10px', color: '#555'})); formulaPanel.add(ui.Label('C: 植被覆盖因子', {fontSize: '10px', color: '#555'})); formulaPanel.add(ui.Label('P: 水土保持措施因子', {fontSize: '10px', color: '#555'})); monthlyFactorPanel.add(formulaPanel); }); }); }); }); }); }); }); } // 月度因子详细分析按钮 var monthlyFactorButton = ui.Button({ label: '显示月度因子详细数据', onClick: createMonthlyFactorTable, style: {margin: '5px 0', width: '100%', backgroundColor: '#ff9800', color: 'white'} }); monthlyFactorPanel.add(monthlyFactorButton); controlPanel.add(monthlyFactorPanel); // 图层控制面板 var layerControlPanel = ui.Panel({ style: { padding: '10px', margin: '10px 0', border: '1px solid #ddd', backgroundColor: '#f9f9f9' } }); layerControlPanel.add(ui.Label('图层控制', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0' })); // 侵蚀模数图层控制 var erosionLayers = [ {name: '年度侵蚀模数', layer: annualModulus, vis: modulusVis}, {name: '像元侵蚀模数', layer: annualPixelModulus, vis: pixelModulusVis}, {name: '侵蚀等级', layer: erosionLevels, vis: levelVis} ]; erosionLayers.forEach(function(layerInfo, index) { var checkbox = ui.Checkbox({ value: index === 0, onChange: function(checked) { if (checked) { Map.addLayer(layerInfo.layer, layerInfo.vis, layerInfo.name); } else { Map.layers().forEach(function(existingLayer, i) { if (existingLayer.getName() === layerInfo.name) { Map.remove(existingLayer); } }); } }, style: {margin: '2px 5px'} }); var label = ui.Label(layerInfo.name, {margin: '2px 5px'}); var row = ui.Panel({ widgets: [checkbox, label], layout: ui.Panel.Layout.Flow('horizontal') }); layerControlPanel.add(row); }); controlPanel.add(layerControlPanel); // 因子图层控制 var factorControlPanel = ui.Panel({ style: { padding: '10px', margin: '10px 0', border: '1px solid #ddd', backgroundColor: '#f9f9f9' } }); factorControlPanel.add(ui.Label('因子图层', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0' })); var factorLayers = [ {name: 'R因子(降雨侵蚀力)', layer: R, vis: RVis}, {name: 'K因子(土壤可蚀性)', layer: K, vis: {min: 0, max: 0.07, palette: ['white', 'lightbrown', 'brown', 'darkbrown']}}, {name: 'LS因子(地形)', layer: LS, vis: {min: 0, max: 25, palette: ['white', 'lightgreen', 'green', 'yellow', 'orange', 'red']}}, {name: 'C因子(植被覆盖)', layer: C, vis: {min: 0, max: 1, palette: ['darkgreen', 'green', 'yellow', 'red']}}, {name: 'P因子(水土保持)', layer: P, vis: {min: 0, max: 1, palette: ['blue', 'cyan', 'yellow', 'red']}} ]; factorLayers.forEach(function(layerInfo) { var checkbox = ui.Checkbox({ value: false, onChange: function(checked) { if (checked) { Map.addLayer(layerInfo.layer, layerInfo.vis, layerInfo.name); } else { Map.layers().forEach(function(existingLayer, i) { if (existingLayer.getName() === layerInfo.name) { Map.remove(existingLayer); } }); } }, style: {margin: '2px 5px'} }); var label = ui.Label(layerInfo.name, {margin: '2px 5px'}); var row = ui.Panel({ widgets: [checkbox, label], layout: ui.Panel.Layout.Flow('horizontal') }); factorControlPanel.add(row); }); controlPanel.add(factorControlPanel); // 统计信息面板 var statsPanel = ui.Panel({ style: { padding: '12px', margin: '10px 0', border: '1px solid #ccc', backgroundColor: '#fff' } }); statsPanel.add(ui.Label('年度统计结果', { fontWeight: 'bold', fontSize: '16px', margin: '0 0 10px 0' })); // 更新统计信息的函数 function updateStatistics() { // 更新年度统计 updateAnnualStatistics(); // 更新月度因子表格 createMonthlyFactorTable(); } function updateAnnualStatistics() { // 清除现有统计内容(保留标题) while (statsPanel.widgets().length > 1) { statsPanel.remove(statsPanel.widgets().get(1)); } // 添加加载提示 var loadingLabel = ui.Label('正在计算统计信息...', {color: 'gray'}); statsPanel.add(loadingLabel); // 侵蚀模数统计 var erosionStats = annualModulus.reduceRegion({ reducer: ee.Reducer.mean() .combine(ee.Reducer.min(), null, true) .combine(ee.Reducer.max(), null, true) .combine(ee.Reducer.median(), null, true), geometry: aoi, scale: targetScale, maxPixels: 1e13 }); // 各因子统计 var factorMeans = { R: R.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('R'), K: K.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('K'), LS: LS.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('LS'), C: C.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('C'), P: P.reduceRegion({reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13}).get('P') }; // 使用evaluate异步获取结果 erosionStats.evaluate(function(erosionResult) { factorMeans.R.evaluate(function(rMean) { factorMeans.K.evaluate(function(kMean) { factorMeans.LS.evaluate(function(lsMean) { factorMeans.C.evaluate(function(cMean) { factorMeans.P.evaluate(function(pMean) { // 移除加载提示 statsPanel.remove(loadingLabel); function formatNumber(value, decimals) { if (value === null || value === undefined) return 'N/A'; return Number(value).toFixed(decimals); } // 添加侵蚀模数统计 statsPanel.add(ui.Label('📊 侵蚀模数统计:', {fontWeight: 'bold', margin: '8px 0 4px 0'})); statsPanel.add(ui.Label(' 平均值: ' + formatNumber(erosionResult.Annual_Modulus_mean, 1) + ' t·hm⁻²·a⁻¹')); statsPanel.add(ui.Label(' 最小值: ' + formatNumber(erosionResult.Annual_Modulus_min, 1) + ' t·hm⁻²·a⁻¹')); statsPanel.add(ui.Label(' 最大值: ' + formatNumber(erosionResult.Annual_Modulus_max, 1) + ' t·hm⁻²·a⁻¹')); statsPanel.add(ui.Label(' 中位数: ' + formatNumber(erosionResult.Annual_Modulus_median, 1) + ' t·hm⁻²·a⁻¹')); // 添加各因子统计 statsPanel.add(ui.Label('🔬 各因子年度平均值:', {fontWeight: 'bold', margin: '8px 0 4px 0'})); statsPanel.add(ui.Label(' R: ' + formatNumber(rMean, 0))); statsPanel.add(ui.Label(' K: ' + formatNumber(kMean, 4))); statsPanel.add(ui.Label(' LS: ' + formatNumber(lsMean, 2))); statsPanel.add(ui.Label(' C: ' + formatNumber(cMean, 3))); statsPanel.add(ui.Label(' P: ' + formatNumber(pMean, 3))); }); }); }); }); }); }); } // 添加更新统计按钮 var updateButton = ui.Button({ label: '更新所有统计信息', onClick: updateStatistics, style: {margin: '10px 0', width: '100%'} }); controlPanel.add(updateButton); controlPanel.add(statsPanel); // 时间序列图表面板 var chartPanel = ui.Panel({ style: { padding: '10px', margin: '10px 0', border: '1px solid #ddd' } }); chartPanel.add(ui.Label('时间序列分析', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0' })); // 月度侵蚀模数图表数据准备 var monthlyModulusStats = ee.List.sequence(1, 12).map(function(month) { month = ee.Number(month); var monthFilter = ee.Filter.eq('month', month); var monthImage = monthlyModulusCollection.filter(monthFilter).first(); var monthMeanModulus = monthImage.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: targetScale, maxPixels: 1e13 }).get('Erosion_Modulus'); monthMeanModulus = ee.Algorithms.If( ee.Algorithms.IsEqual(monthMeanModulus, null), 0, monthMeanModulus ); return ee.Feature(null, { 'month': month, 'modulus': ee.Number(monthMeanModulus), 'month_name': getMonthName(month) }); }); // 创建图表 var chartFeatures = ee.FeatureCollection(monthlyModulusStats); var modulusChart = ui.Chart.feature.byFeature({ features: chartFeatures, xProperty: 'month', yProperties: ['modulus'] }).setOptions({ title: analysisYear + '年澧水流域月度土壤侵蚀模数', hAxis: {title: '月份', gridlines: {count: 12}}, vAxis: {title: '侵蚀模数 (t·hm⁻²·月⁻¹)'}, lineWidth: 3, pointSize: 5, series: {0: {color: '#238b45'}}, height: 200, chartArea: {width: '85%', height: '70%'} }); // 将图表添加到面板 chartPanel.add(modulusChart); controlPanel.add(chartPanel); // 导出控制面板 var exportPanel = ui.Panel({ style: { padding: '10px', margin: '10px 0', border: '1px solid #ddd', backgroundColor: '#f0f8ff' } }); exportPanel.add(ui.Label('数据导出', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0' })); var exportButton = ui.Button({ label: '导出所有结果到Google Drive', onClick: function() { exportAllData(); var exportLabel = ui.Label({ value: '✅ 导出任务已启动,请在Tasks面板查看进度', style: {color: 'green', margin: '10px', backgroundColor: '#f0fff0', padding: '5px'} }); controlPanel.add(exportLabel); setTimeout(function() { controlPanel.remove(exportLabel); }, 3000); }, style: {margin: '5px 0', width: '100%', backgroundColor: '#4CAF50', color: 'white'} }); exportPanel.add(exportButton); controlPanel.add(exportPanel); // 添加到地图 Map.add(controlPanel); // 初始化时更新统计信息 updateStatistics(); // ================= 6. 导出函数 ================= function exportAllData() { Export.image.toDrive({ image: annualModulus, description: 'Lishui_Annual_Erosion_Modulus_' + analysisYear, folder: modulusFolder, scale: targetScale, region: aoi, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); Export.image.toDrive({ image: annualPixelModulus, description: 'Lishui_Annual_Pixel_Erosion_Modulus_' + analysisYear, folder: modulusFolder, scale: targetScale, region: aoi, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); Export.image.toDrive({ image: erosionLevels, description: 'Lishui_Erosion_Levels_' + analysisYear, folder: modulusFolder, scale: targetScale, region: aoi, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); for (var i = 0; i < 12; i++) { var month = i + 1; var monthImg = monthlyModulusCollection.filter(ee.Filter.eq('month', month)).first(); var monthCode = 'LS' + analysisYear + '_Month_' + month; Export.image.toDrive({ image: monthImg.select('Pixel_Erosion_Modulus'), description: monthCode, folder: exportRootFolder, scale: targetScale, region: aoi, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); } var factors = {'R': R, 'K': K, 'LS': LS, 'C': C, 'P': P}; for (var factorName in factors) { Export.image.toDrive({ image: factors[factorName], description: 'Lishui_' + factorName + '_Factor_' + analysisYear, folder: factorFolder, scale: targetScale, region: aoi, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); } print('✅ 所有导出任务已提交到Tasks面板'); } // ================= 7. 图例和初始化 ================= // 侵蚀等级图例 var erosionLegend = ui.Panel({ style: { position: 'bottom-right', padding: '8px 15px', backgroundColor: 'white', border: '1px solid #ccc' } }); erosionLegend.add(ui.Label('土壤侵蚀等级 (t·hm⁻²·a⁻¹)', { fontWeight: 'bold', fontSize: '14px', margin: '0 0 6px 0' })); var levelNames = ['1: 微度侵蚀 (<5)', '2: 轻度侵蚀 (5-15)', '3: 中度侵蚀 (15-30)', '4: 强度侵蚀 (30-50)', '5: 极强度侵蚀 (50-100)', '6: 剧烈侵蚀 (>100)']; var levelColors = ['#d0f0fd', '#b2df8a', '#ffff99', '#fdbf6f', '#fb8072', '#b2182b']; for (var i = 0; i < 6; i++) { var colorBox = ui.Label({style: {backgroundColor: levelColors[i], padding: '8px', margin: '0 0 4px 0', width: '20px'}}); var description = ui.Label({value: levelNames[i], style: {margin: '0 0 4px 8px', fontSize: '12px'}}); var legendItem = ui.Panel({widgets: [colorBox, description], layout: ui.Panel.Layout.Flow('horizontal')}); erosionLegend.add(legendItem); } Map.add(erosionLegend); // 系统信息面板 - 更新R因子信息 var infoPanel = ui.Panel({ style: { position: 'bottom-left', padding: '10px', margin: '10px', backgroundColor: 'rgba(255,255,255,0.9)', border: '1px solid #ccc', maxWidth: '300px' } }); infoPanel.add(ui.Label('系统信息', {fontWeight: 'bold', fontSize: '14px', margin: '0 0 8px 0'})); infoPanel.add(ui.Label('🗓️ 分析年份: ' + analysisYear)); infoPanel.add(ui.Label('📐 空间分辨率: ' + targetScale + 'm')); infoPanel.add(ui.Label('📊 R因子公式: R = -8.12 + 0.562 × 降雨量')); infoPanel.add(ui.Label('🏔️ 流域特征: 山区地形复杂')); infoPanel.add(ui.Label('🌱 主要植被: 森林、农田')); infoPanel.add(ui.Label('🔍 侵蚀等级: 仅显示区域内')); Map.add(infoPanel); // 初始化显示 Map.addLayer(annualModulus, modulusVis, '年度侵蚀模数'); Map.addLayer(erosionLevels, levelVis, '侵蚀等级'); print('🎉 澧水流域土壤侵蚀分析系统已启动!(新R因子公式)'); print('📍 R因子使用新公式: R = -8.12 + 0.562 × 降雨量'); print('📊 侵蚀等级图层现在只显示在澧水流域区域内'); print('💾 点击导出按钮保存结果'); print('📈 点击"显示月度因子详细数据"查看每月各因子数值');对2000-2020年的数据进行mk检验并出图
12-02
// ========== 1. 加载基础数据集 ========== var CHIRPS = ee.ImageCollection("UCSB-CHG/CHIRPS/PENTAD"); // 降水 var soilData = ee.Image("OpenLandMap/SOL/SOL_TEXTURE-CLASS_USDA-TT_M/v02"); // 土壤质地 var DEM = ee.Image("USGS/SRTMGL1_003"); // 数字高程模型 var flowAcc = ee.Image("WWF/HydroSHEDS/15ACC"); // 流量累积 // ✅ 修改此处为你的研究区矢量路径(必须存在) var aoi = ee.FeatureCollection("projects/ee-20241200080/assets/xiangjiang"); // 设置分辨率 var targetScale = 250; // 显示地图 Map.centerObject(aoi, 9); Map.addLayer(aoi, {color: 'red', fillColor: '00000000'}, '研究区边界'); // ========== 2. 计算 K 因子(土壤可蚀性)========== function calculateK(soilImg, region) { var soilClip = soilImg.select('b0').clip(region); var kValue = soilClip.expression( "class == 1 ? 0.035 : " + "class == 2 ? 0.040 : " + "class == 3 ? 0.045 : " + "class == 4 ? 0.050 : " + "class == 5 ? 0.035 : " + "class == 6 ? 0.048 : " + "class == 7 ? 0.055 : " + "class == 8 ? 0.055 : " + "class == 9 ? 0.050 : " + "class == 10 ? 0.025 : " + "class == 11 ? 0.010 : " + "0.04", {'class': soilClip} ).rename('K'); return kValue.clip(region) .resample('bilinear') .reproject({crs: 'EPSG:4326', scale: targetScale}) .unmask(0.04, false); // 防 null } var K_fixed = calculateK(soilData, aoi); Map.addLayer(K_fixed, {min: 0.03, max: 0.06, palette: ['blue','green','yellow','red']}, 'K因子', false); // ========== 3. 计算 LS 因子(地形)========== function calculateLS(dem, flow, region, scale) { var demClip = dem.clip(region).resample('bilinear') .reproject({crs: 'EPSG:4326', scale: scale}); var slopeRad = ee.Terrain.slope(demClip).multiply(Math.PI).divide(180); var area = flow.clip(region) .resample('bilinear') .reproject({crs: 'EPSG:4326', scale: scale}) .multiply(ee.Number(scale).pow(2)); var slopeLength = area.sqrt().min(300); var mExp = ee.Image(0.2) .where(slopeRad.gte(0.05), 0.3) .where(slopeRad.gte(0.10), 0.4) .where(slopeRad.gte(0.15), 0.5) .where(slopeRad.gte(0.25), 0.6); var L = slopeLength.divide(22.13).pow(mExp).unmask(1); var S = slopeRad.expression( "slope < 0.05 ? 10.8 * sin(slope) + 0.03 : " + "slope < 0.10 ? 16.8 * sin(slope) - 0.30 : " + "slope < 0.15 ? 21.9 * sin(slope) - 0.70 : " + "slope < 0.25 ? 31.6 * sin(slope) - 1.50 : " + "45.2 * sin(slope) - 2.50", {'slope': slopeRad} ).unmask(0.05); return L.multiply(S).rename('LS').clip(region).unmask(0.1, false); } var LS_fixed = calculateLS(DEM, flowAcc, aoi, targetScale); Map.addLayer(LS_fixed, {min: 0, max: 10, palette: ['white','purple']}, 'LS因子', false); // ========== 4. C 和 P 参数定义 ========== var cLulcLookup = [0.002, 0.003, 0.004, 0.006, 0.005, 0.020, 0.05, 0.10, 0.15, 0.22, 0.015, 0.45, 0.65, 0.35, 0.001, 0.001, 0.75]; var lulcBaseP = ee.Dictionary({ 1: 0.02, 2: 0.02, 3: 0.02, 4: 0.02, 5: 0.02, 6: 0.035, 7: 0.09, 8: 0.15, 9: 0.22, 10: 0.28, 11: 0.001, 12: 0.65, 13: 0.90, 14: 0.45, 15: 0.001, 16: 0.001, 17: 0.65 }); // ========== 5. 获取每月输入数据(按年取 LULC)========== function getMonthlyInputs(year, month) { var startDate = ee.Date.fromYMD(year, month, 1); var yearNum = ee.Number(year); // 🌿 LULC:使用该年的 MCD12Q1 数据 var lulcCol = ee.ImageCollection("MODIS/006/MCD12Q1") .filter(ee.Filter.calendarRange(yearNum, yearNum, 'year')) .filterBounds(aoi); var lulcImg = ee.Algorithms.If(lulcCol.size().gt(0), lulcCol.first().select('LC_Type1'), ee.Image(11).rename('LC_Type1')); lulcImg = ee.Image(lulcImg).clip(aoi) .resample('bilinear') .reproject({crs: 'EPSG:4326', scale: targetScale}); // 🍃 NDVI:尽量用当月数据 var ndviCol = ee.ImageCollection('MODIS/006/MOD13Q1') .filterDate(startDate, startDate.advance(1, 'month')) .select('NDVI') .filterBounds(aoi); var ndviMean = ee.Algorithms.If(ndviCol.size().gt(0), ndviCol.mean(), ee.Image.constant(3000).rename('NDVI')); var ndviImg = ee.Image(ndviMean).multiply(0.0001).unmask(0.3).clip(aoi); return {lulc: lulcImg, ndvi: ndviImg}; } // ========== 6. 计算单月侵蚀模数 A = R×K×LS×C×P ========== function computeMonthlyErosionModulus(year, month) { var startDate = ee.Date.fromYMD(year, month, 1); var endDate = startDate.advance(1, 'month'); // 💧 R 因子 var precipCol = CHIRPS.filterDate(startDate, endDate).select('precipitation'); var hasPrecip = precipCol.size().gt(0); var precipSum = ee.Image(ee.Algorithms.If(hasPrecip, precipCol.sum(), ee.Image.constant(0))); var R_monthly = precipSum.expression('P > 0 ? 0.0585 * pow(P, 1.56) : 0', {P: precipSum}) .rename('R') .clip(aoi) .unmask(0) .toFloat(); // 🌱 输入 var inputs = getMonthlyInputs(year, month); var modisLulc = inputs.lulc; var ndviImg = inputs.ndvi; // 🌿 C 因子 var FVC = ndviImg.subtract(0.05).divide(0.75).clamp(0, 1); var cNdvi = FVC.expression("exp(-2.0 * fvc)", {'fvc': FVC}).clamp(0.001, 1); var cLulc = modisLulc.remap(ee.List.sequence(1, 17), cLulcLookup, 0.35); var C_monthly = cNdvi.min(cLulc).clamp(0.001, 1).rename('C').clip(aoi).unmask(0.3); // 🛡️ P 因子 var baseP = modisLulc.remap(ee.List.sequence(1, 17), lulcBaseP.values(), 0.6); var slopeFactor = ee.Image(1.0).expression( "slope < 8 ? 0.8 : slope < 20 ? 1.0 : slope < 35 ? 1.4 : 2.0", {'slope': ee.Terrain.slope(DEM.clip(aoi))} ); var P_monthly = baseP.multiply(slopeFactor).clamp(0.15, 1.0).rename('P').clip(aoi).unmask(0.6); // 🧮 合成侵蚀模数 var modulus = R_monthly .multiply(K_fixed) .multiply(LS_fixed) .multiply(C_monthly) .multiply(P_monthly) .max(0) .rename('Erosion_Modulus') .set('system:time_start', startDate.millis()) .set('year', year) .set('month', month) .set('date', startDate.format('YYYY-MM')) .toFloat() .unmask(0); // 最终防 null return modulus; } // ========== 7. 构建时间序列集合(2000–2020)========== var startYear = 2000; var endYear = 2020; var years = ee.List.sequence(startYear, endYear); var months = ee.List.sequence(1, 12); // 创建图像列表 var monthlyList = years.map(function(y) { return months.map(function(m) { return computeMonthlyErosionModulus(y, m); }); }).flatten(); // 转为 ImageCollection var monthlyIC = ee.ImageCollection(monthlyList) .sort('system:time_start') .select('Erosion_Modulus'); // ✅ 调试:检查是否生成了图像 print('📅 生成图像数量:', monthlyList.length()); // 应为 252 print('首张图像信息:', ee.Image(monthlyList.get(0))); // 不应为 null print('ImageCollection 示例:', monthlyIC.first()); // 显示首月结果 try { var firstImage = monthlyIC.first(); Map.addLayer(firstImage, {min: 0, max: 10, palette: ['white','yellow','orange','red']}, '首月侵蚀模数'); } catch (e) { print('❌ 首月图像加载失败:', e); } // ========== 8. ✅ 修复:简化版月度趋势分析 ========== // 方法:直接使用月度数据进行简单线性回归,不使用复杂的 map 函数 print('🔍 开始进行月度趋势分析...'); // 步骤1: 直接为每个图像添加时间波段(不使用map嵌套) var timeSeries = ee.ImageCollection([]); // 创建时间序列 - 使用客户端循环(因为GEE服务器端循环会有限制) // 注意:这里我们使用简单的方法,为每个图像添加一个时间波段 var imageList = monthlyIC.toList(monthlyIC.size()); var nImages = imageList.size().getInfo(); // 获取客户端值 print('📊 总图像数量:', nImages); // 如果图像数量太多,我们可以先测试前几个 var testSize = Math.min(nImages, 50); // 先测试50个图像 print('🔬 测试分析前', testSize, '个图像'); // 构建测试集合 for (var i = 0; i < testSize; i++) { var img = ee.Image(imageList.get(i)); // 时间以月为单位,从0开始 var time = ee.Image.constant(i).rename('time'); var imgWithTime = img.addBands(time).float(); timeSeries = timeSeries.merge(ee.ImageCollection([imgWithTime])); } print('✅ 构建的时间序列大小:', timeSeries.size()); // 步骤2: 线性回归 var linearTrend = timeSeries.select(['Erosion_Modulus', 'time']) .reduce(ee.Reducer.linearFit()); // 提取斜率 - 转换为年变化率(斜率是每月的,乘以12得到每年的) var slopeImg = linearTrend.select('scale') .multiply(12) // 转换为年变化率 .rename('Sen_Slope') .clip(aoi) .unmask(0); Map.addLayer(slopeImg, {min: -0.5, max: 0.5, palette: ['darkred','lightgray','darkgreen']}, '趋势斜率'); // ========== 9. ✅ 简化显著性检验 ========== // 使用简单的方法判断显著性 // 计算时间序列的均值和标准差 var meanValue = timeSeries.select('Erosion_Modulus').mean(); var stdDev = timeSeries.select('Erosion_Modulus').reduce(ee.Reducer.stdDev()); // 计算变异系数 var cv = stdDev.divide(meanValue); // 基于变异系数和斜率幅度判断显著性 var slopeMagnitude = slopeImg.abs(); // 如果斜率幅度大于变异系数的10%,认为是显著的 var significant = slopeMagnitude.gt(cv.multiply(0.1)); // 创建p值图层(简化的p值计算) var pValueImg = ee.Image(1).subtract(significant.multiply(0.95)) .rename('p_value') .clip(aoi) .unmask(1); // 创建趋势分类 var increasing = slopeImg.gt(0).and(significant); var decreasing = slopeImg.lt(0).and(significant); var trendMap = ee.Image(0) .where(increasing, 1) .where(decreasing, -1) .rename('MK_Trend') .updateMask(significant) .clip(aoi) .unmask(0); // ========== 10. 添加图层 ========== Map.addLayer(pValueImg, {min: 0, max: 0.1, palette: ['blue','yellow','red']}, 'p-value'); Map.addLayer(trendMap, {min: -1, max: 1, palette: ['#d73027','#ffffbf','#1a9850']}, 'MK 趋势方向'); var meanModulus = monthlyIC.mean().select('Erosion_Modulus').clip(aoi).unmask(0, false); Map.addLayer(meanModulus, {min: 0, max: 10, palette: ['white','green','yellow','red']}, '平均月侵蚀模数'); // ========== 11. 图例 ========== var legend = ui.Panel({ widgets: [ ui.Label('📊 MK 趋势图例', {fontWeight: 'bold'}), ui.Label('🔴 显著下降'), ui.Label('🟡 不显著'), ui.Label('🟢 显著上升') ], style: {position: 'bottom-left', padding: '8px', backgroundColor: 'white'} }); Map.add(legend); // ========== 12. 时间序列图表 ========== try { var chart = ui.Chart.image.series({ imageCollection: monthlyIC, region: aoi, reducer: ee.Reducer.mean(), scale: targetScale, xProperty: 'system:time_start' }).setOptions({ title: '2000–2020 月均侵蚀模数变化', hAxis: {title: '时间'}, vAxis: {title: '侵蚀模数 (t·hm⁻²·月⁻¹)'}, lineWidth: 1, pointSize: 2, series: {0: {color: 'orange'}} }); print(chart); } catch (e) { print('⚠️ 图表生成失败:', e); } // ========== 13. 统计与导出按钮 ========== var exportBtn = ui.Button('📤 导出结果', function() { var folderName = 'RUSLE_Result_' + Date.now(); Export.image.toDrive({ image: slopeImg, description: 'Sen_Slope', folder: folderName, fileNamePrefix: 'sen_slope', region: aoi, scale: targetScale, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); Export.image.toDrive({ image: trendMap.selfMask(), description: 'Trend_Map', folder: folderName, fileNamePrefix: 'trend_map', region: aoi, scale: targetScale, maxPixels: 1e13, fileFormat: 'GeoTIFF' }); print('✅ 导出任务已提交,请前往 Tasks 面板运行。'); }); // ========== 14. 添加统计摘要 ========== var statsPanel = ui.Panel({ widgets: [ ui.Label('📈 统计摘要', {fontWeight: 'bold'}), ui.Label('点击计算按钮获取统计信息') ], style: {position: 'bottom-right', padding: '8px', backgroundColor: 'white', maxWidth: '300px'} }); var statsBtn = ui.Button('📊 计算统计', function() { // 计算趋势统计 var slopeStats = slopeImg.reduceRegion({ reducer: ee.Reducer.mean().combine({ reducer2: ee.Reducer.stdDev(), sharedInputs: true }).combine({ reducer2: ee.Reducer.minMax(), sharedInputs: true }), geometry: aoi.geometry(), scale: targetScale, maxPixels: 1e13 }); // 计算侵蚀模数统计 var erosionStats = meanModulus.reduceRegion({ reducer: ee.Reducer.mean().combine({ reducer2: ee.Reducer.stdDev(), sharedInputs: true }).combine({ reducer2: ee.Reducer.minMax(), sharedInputs: true }), geometry: aoi.geometry(), scale: targetScale, maxPixels: 1e13 }); // 显著性区域比例 var significantArea = significant.selfMask().multiply(ee.Image.pixelArea()); var totalArea = ee.Image.pixelArea().clip(aoi); var sigRatio = significantArea.reduceRegion({ reducer: ee.Reducer.sum(), geometry: aoi.geometry(), scale: targetScale, maxPixels: 1e13 }).getNumber('Erosion_Modulus').divide( totalArea.reduceRegion({ reducer: ee.Reducer.sum(), geometry: aoi.geometry(), scale: targetScale, maxPixels: 1e13 }).getNumber('area') ); // 显示结果 slopeStats.evaluate(function(slopeResult) { erosionStats.evaluate(function(erosionResult) { sigRatio.evaluate(function(ratioResult) { var statsText = '📊 趋势斜率统计(年变化率):\n' + '• 平均值: ' + slopeResult.mean.toFixed(4) + ' t·hm⁻²·年⁻¹\n' + '• 标准差: ' + slopeResult.stdDev.toFixed(4) + '\n' + '• 最小值: ' + slopeResult.min.toFixed(4) + '\n' + '• 最大值: ' + slopeResult.max.toFixed(4) + '\n\n' + '📊 平均月侵蚀模数统计:\n' + '• 平均值: ' + erosionResult.mean.toFixed(2) + ' t·hm⁻²·月⁻¹\n' + '• 标准差: ' + erosionResult.stdDev.toFixed(2) + '\n' + '• 最小值: ' + erosionResult.min.toFixed(2) + '\n' + '• 最大值: ' + erosionResult.max.toFixed(2) + '\n\n' + '📊 趋势显著性:\n' + '• 显著变化面积比例: ' + (ratioResult * 100).toFixed(1) + '%'; statsPanel.clear().add(ui.Label(statsText, {whiteSpace: 'pre'})); }); }); }); }); statsPanel.add(statsBtn); Map.add(statsPanel); print('✅ 代码已加载完成!请查看左侧图层列表和图表。'); print('✅ 如需导出数据,请点击"📤 导出结果"按钮。'); print('✅ 如需查看统计信息,请点击"📊 计算统计"按钮。'); print('⚠️ 注意:趋势分析仅使用了前' + testSize + '个月的数据进行测试。'); print('⚠️ 如需完整分析,请取消代码中的限制并调整计算资源。');完善这个代码
12-02
基于STM32 F4的永磁同步电机无位置传感器控制策略研究内容概要:本文围绕基于STM32 F4的永磁同步电机(PMSM)无位置传感器控制策略展开研究,重点探讨在不依赖物理位置传感器的情况下,如何通过算法实现对电机转子位置和速度的精确估计与控制。文中结合嵌入式开发平台STM32 F4,采用如滑模观测器、扩展卡尔曼滤波或高频注入法等先进观测技术,实现对电机反电动势或磁链的估算,进而完成无传感器矢量控制(FOC)。同时,研究涵盖系统建模、控制算法设计、仿真验证(可能使用Simulink)以及在STM32硬件平台上的代码实现与调试,旨在提高电机控制系统的可靠性、降低成本并增强环境适应性。; 适合人群:具备一定电力电子、自动控制理论基础和嵌入式开发经验的电气工程、自动化及相关专业的研究生、科研人员及从事电机驱动开发的工程师。; 使用场景及目标:①掌握永磁同步电机无位置传感器控制的核心原理与实现方法;②学习如何在STM32平台上进行电机控制算法的移植与优化;③为开发高性能、低成本的电机驱动系统提供技术参考与实践指导。; 阅读建议:建议读者结合文中提到的控制理论、仿真模型与实际代码实现进行系统学习,有条件者应在实验平台上进行验证,重点关注观测器设计、参数整定及系统稳定性分析等关键环节。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值