6.97
This commit is contained in:
@ -10,7 +10,7 @@
|
||||
|
||||
"package": {
|
||||
"productName": "SpectralPlot",
|
||||
"version": "0.6.95"
|
||||
"version": "0.6.97"
|
||||
},
|
||||
"tauri": {
|
||||
|
||||
|
||||
693
src/components/menubox/ReflectanceToIris.vue
Normal file
693
src/components/menubox/ReflectanceToIris.vue
Normal file
@ -0,0 +1,693 @@
|
||||
<script>
|
||||
import SensorMethod from "../SerialPort/SerialportMethod.js";
|
||||
import * as echarts from "echarts";
|
||||
import { dialog, fs } from "@tauri-apps/api";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
|
||||
export default {
|
||||
name: "ReflectanceToIris",
|
||||
data() {
|
||||
return {
|
||||
mydev:{sensor_id:"",name:"",serialnumber:""},
|
||||
option: {},
|
||||
Devinfo: {
|
||||
work_mode: 0,
|
||||
bochangxishu: {
|
||||
a0: 0,
|
||||
a1: 0,
|
||||
a2: 0,
|
||||
a3: 0
|
||||
},
|
||||
bandsum: 0
|
||||
},
|
||||
wavelengthSource: "device", // "device", "file"
|
||||
currentCoeffs: {
|
||||
a0: 0,
|
||||
a1: 0,
|
||||
a2: 0,
|
||||
a3: 0
|
||||
},
|
||||
irisFileWavelengths: [], // 从iris文件导入的波长选项列表
|
||||
selectedIrisWavelength: null, // 选中的波长数据索引
|
||||
irisFilePath: "", // iris文件路径
|
||||
reflectanceData: {
|
||||
wavelengths: [],
|
||||
values: [],
|
||||
fileName: ""
|
||||
},
|
||||
resampledData: {
|
||||
wavelengths: [],
|
||||
values: []
|
||||
},
|
||||
reflectanceFilePath: ""
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 只初始化图表,不自动加载设备信息
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.initChart();
|
||||
setTimeout(() => {
|
||||
this.echartresize();
|
||||
// 添加窗口resize监听
|
||||
window.addEventListener('resize', this.echartresize);
|
||||
}, 100);
|
||||
}, 200);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
async initDeviceInfo() {
|
||||
var isdevopen= this.$globalState.isDevOpen;
|
||||
if(isdevopen==false)
|
||||
{
|
||||
alert("设备未打开,请先连接并打开设备");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.Devinfo = await SensorMethod.Get_Device_Info();
|
||||
|
||||
// 检查设备是否打开
|
||||
if (this.Devinfo.error || !this.Devinfo || !this.Devinfo.name || this.Devinfo.name === "暂无") {
|
||||
alert("设备未打开,请先连接并打开设备");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.Devinfo.bochangxishu) {
|
||||
this.currentCoeffs.a0 = this.Devinfo.bochangxishu.a0 || 0;
|
||||
this.currentCoeffs.a1 = this.Devinfo.bochangxishu.a1 || 0;
|
||||
this.currentCoeffs.a2 = this.Devinfo.bochangxishu.a2 || 0;
|
||||
this.currentCoeffs.a3 = this.Devinfo.bochangxishu.a3 || 0;
|
||||
}
|
||||
this.wavelengthSource = 'device';
|
||||
} catch (err) {
|
||||
console.error('获取设备信息失败:', err);
|
||||
alert("获取设备信息失败,请确保设备已连接并打开");
|
||||
}
|
||||
},
|
||||
async importReflectanceFile() {
|
||||
var options = {
|
||||
defaultPath: "../",
|
||||
directory: false,
|
||||
title: "请选择反射率文件",
|
||||
filters: [
|
||||
{ name: "文本文件", extensions: ["txt", "mn"] },
|
||||
{ name: "所有文件", extensions: ["*"] }
|
||||
]
|
||||
}
|
||||
var pathofdir = await dialog.open(options);
|
||||
if (!pathofdir) {
|
||||
return;
|
||||
}
|
||||
this.reflectanceFilePath = pathofdir;
|
||||
try {
|
||||
const data = await fs.readTextFile(pathofdir);
|
||||
const lines = data.split('\n');
|
||||
|
||||
// 解析第一行获取文件名
|
||||
const firstLine = lines[0].trim();
|
||||
let fileName = "";
|
||||
if (firstLine.startsWith("Wavelength")) {
|
||||
const parts = firstLine.split('\t');
|
||||
if (parts.length > 1) {
|
||||
fileName = parts[1].trim();
|
||||
}
|
||||
}
|
||||
|
||||
const wavelengths = [];
|
||||
const values = [];
|
||||
|
||||
// 解析数据行(跳过第一行)
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
if (line !== '') {
|
||||
const parts = line.split(/\s+/);
|
||||
if (parts.length >= 2) {
|
||||
const wavelength = parseFloat(parts[0]);
|
||||
const value = parseFloat(parts[1]);
|
||||
if (!isNaN(wavelength) && !isNaN(value)) {
|
||||
wavelengths.push(wavelength); // 直接使用文件中的波长值
|
||||
values.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.reflectanceData = {
|
||||
wavelengths: wavelengths,
|
||||
values: values,
|
||||
fileName: fileName || this.getFileNameFromPath(pathofdir)
|
||||
};
|
||||
|
||||
this.updateChart();
|
||||
//alert(`成功导入反射率文件,共 ${wavelengths.length} 个数据点`);
|
||||
} catch (err) {
|
||||
console.error('读取文件失败:', err);
|
||||
//alert('读取文件失败: ' + err);
|
||||
}
|
||||
},
|
||||
getFileNameFromPath(path) {
|
||||
const parts = path.split(/[\\\/]/);
|
||||
return parts[parts.length - 1].replace(/\.[^/.]+$/, "");
|
||||
},
|
||||
async importWavelengthFromIris() {
|
||||
var options = {
|
||||
defaultPath: "../",
|
||||
directory: false,
|
||||
title: "请选择iris文件",
|
||||
filters: [
|
||||
{ name: "IRIS文件", extensions: ["iris"] },
|
||||
{ name: "所有文件", extensions: ["*"] }
|
||||
]
|
||||
}
|
||||
var pathofdir = await dialog.open(options);
|
||||
if (!pathofdir) {
|
||||
return;
|
||||
}
|
||||
this.irisFilePath = pathofdir;
|
||||
try {
|
||||
// 调用 Rust 函数读取 iris 文件
|
||||
const irisData = await invoke("getoneirisfile", { path: pathofdir });
|
||||
|
||||
// 解析波长信息
|
||||
const wavelengths = [];
|
||||
|
||||
// 从 spectral_info_section 中提取波长系数
|
||||
if (irisData.spectral_info_section && irisData.spectral_info_section.length > 0) {
|
||||
for (let i = 0; i < irisData.spectral_info_section.length; i++) {
|
||||
const info = irisData.spectral_info_section[i];
|
||||
if (info.info_type === "devinfo" && info.wave_coeff) {
|
||||
const coeffs = info.wave_coeff;
|
||||
// 从 spectral_data_section 中查找对应的数据以获取波段数
|
||||
let bands = 2048; // 默认值
|
||||
let name = info.sensor_id || `波长数据${i + 1}`;
|
||||
|
||||
// 尝试从 spectral_data_section 中找到匹配的数据
|
||||
if (irisData.spectral_data_section && irisData.spectral_data_section.length > 0) {
|
||||
for (const spectralData of irisData.spectral_data_section) {
|
||||
if (spectralData.sensor_id === info.sensor_id) {
|
||||
bands = spectralData.bands || bands;
|
||||
name = spectralData.name || name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iris文件中的wave_coeff使用a1,a2,a3,a4,对应我们的a0,a1,a2,a3
|
||||
wavelengths.push({
|
||||
index: i,
|
||||
name: name,
|
||||
sensor_id: info.sensor_id || "",
|
||||
coeffs: {
|
||||
a0: coeffs.a1 !== undefined ? coeffs.a1 : (coeffs.a0 !== undefined ? coeffs.a0 : 0),
|
||||
a1: coeffs.a2 !== undefined ? coeffs.a2 : (coeffs.a1 !== undefined ? coeffs.a1 : 0),
|
||||
a2: coeffs.a3 !== undefined ? coeffs.a3 : (coeffs.a2 !== undefined ? coeffs.a2 : 0),
|
||||
a3: coeffs.a4 !== undefined ? coeffs.a4 : (coeffs.a3 !== undefined ? coeffs.a3 : 0)
|
||||
},
|
||||
bands: bands
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.mydev.sensor_id = irisData.spectral_info_section[0].sensor_id;
|
||||
this.mydev.name = irisData.spectral_info_section[0].name;
|
||||
this.mydev.serialnumber = irisData.spectral_info_section[0].serialnumber;
|
||||
// 如果没有从 spectral_info_section 找到,尝试从 spectral_data_section 计算
|
||||
if (wavelengths.length === 0 && irisData.spectral_data_section && irisData.spectral_data_section.length > 0) {
|
||||
// 如果 spectral_data_section 有数据但没有波长系数,我们需要提示用户
|
||||
alert("该iris文件中没有找到波长系数信息,请使用设备或手动输入");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wavelengths.length === 0) {
|
||||
alert("该iris文件中没有找到波长信息");
|
||||
return;
|
||||
}
|
||||
|
||||
this.irisFileWavelengths = wavelengths;
|
||||
this.wavelengthSource = 'file'; // 设置为文件导入模式
|
||||
|
||||
// 如果只有一个波长数据,自动选择并更新系数
|
||||
if (wavelengths.length === 1) {
|
||||
this.selectedIrisWavelength = 0;
|
||||
this.updateCoeffsFromFile(0);
|
||||
} else {
|
||||
// 多个波长数据,让用户选择(通过下拉框)
|
||||
this.selectedIrisWavelength = null;
|
||||
}
|
||||
|
||||
//alert(`成功从iris文件导入 ${wavelengths.length} 个波长数据`);
|
||||
} catch (err) {
|
||||
console.error('读取iris文件失败:', err);
|
||||
alert('读取iris文件失败: ' + err);
|
||||
}
|
||||
},
|
||||
updateCoeffsFromFile(index) {
|
||||
if (this.irisFileWavelengths.length > index) {
|
||||
const selectedWl = this.irisFileWavelengths[index];
|
||||
const coeffs = selectedWl.coeffs;
|
||||
this.currentCoeffs.a0 = coeffs.a0;
|
||||
this.currentCoeffs.a1 = coeffs.a1;
|
||||
this.currentCoeffs.a2 = coeffs.a2;
|
||||
this.currentCoeffs.a3 = coeffs.a3;
|
||||
|
||||
// 同步更新 Devinfo,从 iris 文件中提取设备信息
|
||||
// 从 name 或 sensor_id 中提取设备名称和序列号
|
||||
// name 格式可能是: "name_serialnumber_reflectance_filename" 或 "name_serialnumber"
|
||||
// sensor_id 格式可能是: "name_serialnumber" 或只有序列号
|
||||
let deviceName = "Unknown";
|
||||
let serialNumber = "Unknown";
|
||||
|
||||
const nameStr = selectedWl.name || "";
|
||||
const sensorId = selectedWl.sensor_id || "";
|
||||
|
||||
// 优先从 name 中解析(通常包含更多信息)
|
||||
if (nameStr) {
|
||||
// name 可能包含 "name_serialnumber_reflectance_filename" 格式
|
||||
// 或者 "name_serialnumber" 格式
|
||||
const nameParts = nameStr.split('_');
|
||||
if (nameParts.length >= 2) {
|
||||
deviceName = nameParts[0];
|
||||
// 查找序列号部分(通常在第二个位置,但可能后面还有 "reflectance" 等)
|
||||
// 假设序列号是第二个部分,或者从第二个到 "reflectance" 之前
|
||||
let serialIndex = 1;
|
||||
if (nameParts.length > 2 && nameParts[2].toLowerCase().includes('reflectance')) {
|
||||
serialNumber = nameParts[1];
|
||||
} else if (nameParts.length >= 2) {
|
||||
// 如果只有两部分,第二部分就是序列号
|
||||
serialNumber = nameParts[1];
|
||||
}
|
||||
} else {
|
||||
deviceName = nameStr;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果从 name 没有解析到序列号,尝试从 sensor_id 解析
|
||||
if (serialNumber === "Unknown" && sensorId) {
|
||||
const sensorParts = sensorId.split('_');
|
||||
if (sensorParts.length >= 2) {
|
||||
if (deviceName === "Unknown") {
|
||||
deviceName = sensorParts[0];
|
||||
}
|
||||
serialNumber = sensorParts.slice(1).join('_');
|
||||
} else {
|
||||
serialNumber = sensorId;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 Devinfo
|
||||
if (!this.Devinfo) {
|
||||
this.Devinfo = {};
|
||||
}
|
||||
this.Devinfo.name = deviceName;
|
||||
this.Devinfo.serialnumber = serialNumber;
|
||||
this.Devinfo.SerialNumber = serialNumber; // 兼容不同的字段名
|
||||
this.Devinfo.bandsum = selectedWl.bands || (this.resampledData.values.length > 0 ? this.resampledData.values.length : 2048);
|
||||
if (!this.Devinfo.bochangxishu) {
|
||||
this.Devinfo.bochangxishu = {};
|
||||
}
|
||||
this.Devinfo.bochangxishu.a0 = coeffs.a0;
|
||||
this.Devinfo.bochangxishu.a1 = coeffs.a1;
|
||||
this.Devinfo.bochangxishu.a2 = coeffs.a2;
|
||||
this.Devinfo.bochangxishu.a3 = coeffs.a3;
|
||||
}
|
||||
},
|
||||
async resampleReflectance() {
|
||||
if (this.reflectanceData.wavelengths.length === 0) {
|
||||
alert("请先导入反射率文件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用当前系数
|
||||
const coeffweave1 = this.currentCoeffs.a0;
|
||||
const coeffweave2 = this.currentCoeffs.a1;
|
||||
const coeffweave3 = this.currentCoeffs.a2;
|
||||
const coeffweave4 = this.currentCoeffs.a3;
|
||||
|
||||
// 获取波段数
|
||||
let lenthofdata = 2048; // 默认值
|
||||
if (this.wavelengthSource === "device") {
|
||||
lenthofdata = this.Devinfo.bandsum || 2048;
|
||||
} else if (this.wavelengthSource === "file") {
|
||||
if (this.selectedIrisWavelength !== null && this.irisFileWavelengths.length > 0) {
|
||||
lenthofdata = this.irisFileWavelengths[this.selectedIrisWavelength].bands || 2048;
|
||||
}
|
||||
} else {
|
||||
lenthofdata = this.Devinfo.bandsum || 2048;
|
||||
}
|
||||
|
||||
// 计算目标波长
|
||||
let weavetarget = [];
|
||||
for (var i = 0; i < lenthofdata; i++) {
|
||||
var weave = coeffweave1 * i * i * i + coeffweave2 * i * i + coeffweave3 * i + coeffweave4;
|
||||
weavetarget.push(weave);
|
||||
}
|
||||
|
||||
// 使用插值函数重采样
|
||||
try {
|
||||
let valuetarget = await invoke("interpolate_spline_at_points", {
|
||||
x: this.reflectanceData.wavelengths,
|
||||
y: this.reflectanceData.values,
|
||||
xTarget: weavetarget
|
||||
});
|
||||
|
||||
this.resampledData = {
|
||||
wavelengths: weavetarget,
|
||||
values: valuetarget
|
||||
};
|
||||
|
||||
this.updateChart();
|
||||
// alert(`重采样完成,共 ${valuetarget.length} 个数据点`);
|
||||
} catch (err) {
|
||||
console.error('重采样失败:', err);
|
||||
alert('重采样失败: ' + err);
|
||||
}
|
||||
},
|
||||
async saveToIris() {
|
||||
if (this.resampledData.values.length === 0) {
|
||||
alert("请先进行重采样");
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建默认文件名(包含原文件名)
|
||||
const defaultFileName = (this.reflectanceData.fileName || "reflectance") + ".iris";
|
||||
|
||||
// 选择保存路径
|
||||
var options = {
|
||||
defaultPath: defaultFileName,
|
||||
directory: false,
|
||||
title: "保存iris文件",
|
||||
filters: [
|
||||
{ name: "IRIS文件", extensions: ["iris"] }
|
||||
]
|
||||
}
|
||||
var savePath = await dialog.save(options);
|
||||
if (!savePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保文件扩展名为.iris
|
||||
if (!savePath.endsWith('.iris')) {
|
||||
savePath += '.iris';
|
||||
}
|
||||
|
||||
// 获取设备信息(如果可用),始终使用当前系数
|
||||
let devinfo = {};
|
||||
let deviceName = "Unknown";
|
||||
if (this.Devinfo && this.Devinfo.name && this.Devinfo.name !== "暂无") {
|
||||
deviceName = this.Devinfo.name;
|
||||
}
|
||||
|
||||
if (this.Devinfo && this.Devinfo.name && this.Devinfo.name !== "暂无") {
|
||||
// 使用设备信息,但使用当前系数
|
||||
devinfo = {
|
||||
name: "flat_ref",
|
||||
serialnumber: this.Devinfo.serialnumber || this.Devinfo.SerialNumber || "Unknown",
|
||||
sensor_id: this.mydev.sensor_id, // sensor_id 使用 name 的值
|
||||
bands: this.resampledData.values.length,
|
||||
bochangxishu: {
|
||||
a0: this.currentCoeffs.a0,
|
||||
a1: this.currentCoeffs.a1,
|
||||
a2: this.currentCoeffs.a2,
|
||||
a3: this.currentCoeffs.a3
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// 使用当前系数
|
||||
devinfo = {
|
||||
name: "flat_ref",
|
||||
serialnumber: "Unknown",
|
||||
sensor_id: this.mydev.sensor_id, // sensor_id 使用 name 的值
|
||||
bands: this.resampledData.values.length,
|
||||
bochangxishu: {
|
||||
a0: this.currentCoeffs.a0,
|
||||
a1: this.currentCoeffs.a1,
|
||||
a2: this.currentCoeffs.a2,
|
||||
a3: this.currentCoeffs.a3
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 构建反射率数据对象
|
||||
const reflectanceDataJson = {
|
||||
data: this.resampledData.values,
|
||||
wavelengths: this.resampledData.wavelengths,
|
||||
fileName: this.reflectanceData.fileName
|
||||
};
|
||||
|
||||
// 调用Rust函数保存
|
||||
try {
|
||||
const result = await invoke("save_reflectance_to_iris", {
|
||||
reflectanceData: reflectanceDataJson,
|
||||
devinfo: devinfo,
|
||||
filepath: savePath
|
||||
});
|
||||
|
||||
if (result === "ok") {
|
||||
alert("成功保存iris文件: " + savePath);
|
||||
} else {
|
||||
alert("保存失败: " + result);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('保存失败:', err);
|
||||
alert('保存失败: ' + err);
|
||||
}
|
||||
},
|
||||
initChart() {
|
||||
const chartDom = this.$refs.chart;
|
||||
if (!chartDom) {
|
||||
console.error('图表容器未找到');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果已经初始化过,先销毁
|
||||
const existingChart = echarts.getInstanceByDom(chartDom);
|
||||
if (existingChart) {
|
||||
existingChart.dispose();
|
||||
}
|
||||
|
||||
let chart = echarts.init(chartDom);
|
||||
|
||||
this.option = {
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: false,
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
start: 0,
|
||||
end: 100
|
||||
}
|
||||
]
|
||||
},
|
||||
animation: false,
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '5%',
|
||||
top: '5%'
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
xAxisIndex: [0],
|
||||
filterMode: 'none'
|
||||
},
|
||||
{
|
||||
type: 'inside',
|
||||
yAxisIndex: [0],
|
||||
filterMode: 'none'
|
||||
}
|
||||
],
|
||||
legend: {
|
||||
data: ['原始反射率', '重采样后'],
|
||||
show: true
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '原始反射率',
|
||||
type: 'line',
|
||||
data: [],
|
||||
symbol: 'none',
|
||||
smooth: false,
|
||||
step: 'start'
|
||||
},
|
||||
{
|
||||
name: '重采样后',
|
||||
type: 'line',
|
||||
data: [],
|
||||
symbol: 'none',
|
||||
smooth: false,
|
||||
step: 'start'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chart.setOption(this.option);
|
||||
chart.dispatchAction({
|
||||
type: 'resize'
|
||||
});
|
||||
chart.resize();
|
||||
},
|
||||
updateChart() {
|
||||
let chart = echarts.getInstanceByDom(this.$refs.chart);
|
||||
if (!chart) {
|
||||
this.initChart();
|
||||
chart = echarts.getInstanceByDom(this.$refs.chart);
|
||||
}
|
||||
|
||||
// 更新原始数据
|
||||
const originalData = [];
|
||||
for (let i = 0; i < this.reflectanceData.wavelengths.length; i++) {
|
||||
originalData.push([this.reflectanceData.wavelengths[i], this.reflectanceData.values[i]]);
|
||||
}
|
||||
this.option.series[0].data = originalData;
|
||||
|
||||
// 更新重采样数据
|
||||
const resampledData = [];
|
||||
for (let i = 0; i < this.resampledData.wavelengths.length; i++) {
|
||||
resampledData.push([this.resampledData.wavelengths[i], this.resampledData.values[i]]);
|
||||
}
|
||||
this.option.series[1].data = resampledData;
|
||||
|
||||
chart.setOption(this.option);
|
||||
},
|
||||
echartresize() {
|
||||
let chart = echarts.getInstanceByDom(this.$refs.chart);
|
||||
if (chart) {
|
||||
chart.resize();
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.echartresize);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container" style="width: 100%;height: 100%;max-width:100%;margin: 0px;padding: 0px; display: flex; flex-direction: column; overflow: hidden;">
|
||||
<div class="row" style="flex: 1; min-height: 0; margin: 0px; overflow: hidden;">
|
||||
<!-- 左侧控制面板 -->
|
||||
<div class="col-2">
|
||||
<!-- 标题 -->
|
||||
<div style="padding: 10px; border-bottom: 1px solid #d2dede; background-color: #e9ecef;">
|
||||
<h6 style="margin: 0; font-weight: bold; text-align: center;">波长系数</h6>
|
||||
</div>
|
||||
|
||||
<!-- 波长来源选择按钮 -->
|
||||
<div style="padding: 10px;">
|
||||
<b-button variant="secondary" @click="initDeviceInfo()"
|
||||
:variant="wavelengthSource === 'device' ? 'primary' : 'secondary'"
|
||||
style="width: 100%; margin-bottom: 10px;">
|
||||
设备导入
|
||||
</b-button>
|
||||
<b-button variant="secondary" @click="importWavelengthFromIris()"
|
||||
:variant="wavelengthSource === 'file' ? 'primary' : 'secondary'"
|
||||
style="width: 100%; margin-bottom: 10px;">
|
||||
文件导入
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<!-- 从文件导入时显示选择下拉框 -->
|
||||
<div v-if="wavelengthSource === 'file' && irisFileWavelengths.length > 0" style="padding: 10px;">
|
||||
<b-form-select
|
||||
v-model="selectedIrisWavelength"
|
||||
:options="irisFileWavelengths.map((wl, index) => ({ value: index, text: wl.name + ' (' + wl.bands + ')' }))"
|
||||
@change="updateCoeffsFromFile(selectedIrisWavelength)"
|
||||
style="width: 100%; margin-bottom: 10px;">
|
||||
<template #first>
|
||||
<b-form-select-option :value="null" disabled>请选择波长数据</b-form-select-option>
|
||||
</template>
|
||||
</b-form-select>
|
||||
</div>
|
||||
|
||||
<!-- 波长系数输入框 - 始终显示并可编辑 -->
|
||||
<div style="padding: 10px;">
|
||||
<b-input-group class="my-1">
|
||||
<BInputGroupPrepend is-text class="myinputprepend">a0</BInputGroupPrepend>
|
||||
<b-form-input
|
||||
type="number"
|
||||
step="0.00000000000001"
|
||||
v-model.number="currentCoeffs.a0"></b-form-input>
|
||||
</b-input-group>
|
||||
<b-input-group class="my-1">
|
||||
<BInputGroupPrepend is-text class="myinputprepend">a1</BInputGroupPrepend>
|
||||
<b-form-input
|
||||
type="number"
|
||||
step="0.00000000000001"
|
||||
v-model.number="currentCoeffs.a1"></b-form-input>
|
||||
</b-input-group>
|
||||
<b-input-group class="my-1">
|
||||
<BInputGroupPrepend is-text class="myinputprepend">a2</BInputGroupPrepend>
|
||||
<b-form-input
|
||||
type="number"
|
||||
step="0.00000000000001"
|
||||
v-model.number="currentCoeffs.a2"></b-form-input>
|
||||
</b-input-group>
|
||||
<b-input-group class="my-1">
|
||||
<BInputGroupPrepend is-text class="myinputprepend">a3</BInputGroupPrepend>
|
||||
<b-form-input
|
||||
type="number"
|
||||
step="0.00000000000001"
|
||||
v-model.number="currentCoeffs.a3"></b-form-input>
|
||||
</b-input-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧图表区域 -->
|
||||
<div class="col-10" style="position: relative; overflow: hidden;">
|
||||
<div class="chart-container" ref="chart" style="width: 100%; height: 100%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部操作按钮 - 横跨整个界面 -->
|
||||
<div style="flex-shrink: 0; height: 50px; border-top: 1px solid #d2dede; padding: 10px; display: flex; align-items: center; background-color: #f8f9fa;">
|
||||
<b-button @click="importReflectanceFile()" style="margin-right: 10px;">打开文件</b-button>
|
||||
<b-button @click="resampleReflectance()" style="margin-right: 10px;">重采样</b-button>
|
||||
<b-button variant="primary" @click="saveToIris()" style="margin-left: auto;">保存文件</b-button>
|
||||
<span v-if="reflectanceData.fileName" style="margin-left: 20px; line-height: 30px;">
|
||||
当前文件: {{ reflectanceData.fileName }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.col-2 {
|
||||
background-color: #f8f9fa;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding: 0px;
|
||||
border-right: 1px solid #d2dede;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.col-10 {
|
||||
padding: 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background-color: #f8f9fa;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
background-color: #f8f9fa;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.myinputprepend {
|
||||
min-width: 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -272,8 +272,18 @@ export default {
|
||||
},
|
||||
async findpeak(specindex) {
|
||||
if (specindex == 0) {
|
||||
let dataforpeak = this.Data.data;
|
||||
var peaks = await invoke("find_peek", { data: dataforpeak, minheigh: 3000 });
|
||||
let originalData = this.Data.data;
|
||||
// Step 1: 亚像素插值 (0.05像素间隔,20倍数据量)
|
||||
let resampled = await invoke("interpolate_spline", {
|
||||
x: Array.from({length: originalData.length}, (_, i) => i),
|
||||
y: originalData.map(v => Number(v)),
|
||||
step: 0.05
|
||||
});
|
||||
// Step 2: 在插值数据上寻峰
|
||||
let resampledY = resampled.map(p => p[1]);
|
||||
var peaks = await invoke("find_peek", { data: resampledY, minheigh: 3000 });
|
||||
// Step 3: 峰位置除以20映射回原始像素(亚像素精度)
|
||||
peaks = peaks.map(p => [p[0] / 20, p[1]]);
|
||||
console.log(peaks);
|
||||
let peaksforshow = [];
|
||||
let coeffweave1 = this.Devinfo.bochangxishu.a0;
|
||||
@ -295,7 +305,7 @@ export default {
|
||||
peaks.forEach(element => {
|
||||
var weave = coeffweave1 * element[0] * element[0] * element[0] + coeffweave2 * element[0] * element[0] + coeffweave3 * element[0] + coeffweave4;
|
||||
peaksforshow.push([weave, element[1], element[0]]);
|
||||
this.Peaks.push([weave, element[1], element[0], false, 0])
|
||||
if (!this.Peaks.some(p => p[2] === element[0])) { this.Peaks.push([weave, element[1], element[0], false, 0]); }
|
||||
peakformatch.push(element[0]);
|
||||
});
|
||||
peakformatch.sort(function (a, b) {
|
||||
@ -337,8 +347,18 @@ export default {
|
||||
}
|
||||
|
||||
else if (specindex == 1) {
|
||||
let dataforpeak = this.DataDown.data;
|
||||
var peaks = await invoke("find_peek", { data: dataforpeak, minheigh: 3000 });
|
||||
let originalDataDown = this.DataDown.data;
|
||||
// Step 1: 亚像素插值 (0.05像素间隔,20倍数据量)
|
||||
let resampledDown = await invoke("interpolate_spline", {
|
||||
x: Array.from({length: originalDataDown.length}, (_, i) => i),
|
||||
y: originalDataDown.map(v => Number(v)),
|
||||
step: 0.05
|
||||
});
|
||||
// Step 2: 在插值数据上寻峰
|
||||
let resampledYDown = resampledDown.map(p => p[1]);
|
||||
var peaks = await invoke("find_peek", { data: resampledYDown, minheigh: 3000 });
|
||||
// Step 3: 峰位置映射回原始像素(亚像素精度)
|
||||
peaks = peaks.map(p => [p[0] / 20, p[1]]);
|
||||
console.log(peaks);
|
||||
let peaksforshow = [];
|
||||
let coeffweave1 = this.Devinfo.bochangxishu2.a0;
|
||||
@ -356,7 +376,7 @@ export default {
|
||||
peaks.forEach(element => {
|
||||
var weave = coeffweave1 * element[0] * element[0] * element[0] + coeffweave2 * element[0] * element[0] + coeffweave3 * element[0] + coeffweave4;
|
||||
peaksforshow.push([weave, element[1], element[0]]);
|
||||
this.PeaksDown.push([weave, element[1], element[0], false, 0])
|
||||
if (!this.PeaksDown.some(p => p[2] === element[0])) { this.PeaksDown.push([weave, element[1], element[0], false, 0]); }
|
||||
});
|
||||
|
||||
|
||||
@ -395,11 +415,11 @@ export default {
|
||||
},
|
||||
async ClearArry(specindex){
|
||||
if (specindex == 0) {
|
||||
this.Peaks = [];
|
||||
this.Peaks = this.Peaks.filter(p => p[3] === true && p[4] !== 0);
|
||||
this.option.series[1].data = [];
|
||||
|
||||
} else if (specindex == 1) {
|
||||
this.PeaksDown = [];
|
||||
this.PeaksDown = this.PeaksDown.filter(p => p[3] === true && p[4] !== 0);
|
||||
this.optiondown.series[1].data = [];
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user