制作曲线图数据
This commit is contained in:
parent
df1ba524d1
commit
94fcb4feac
|
|
@ -11042,7 +11042,7 @@ MonoBehaviour:
|
|||
objectValue: {fileID: 5627652597274816387}
|
||||
dataValue:
|
||||
variableType: 10
|
||||
- name: "\u65F6\u957F\u8F93\u5165\u6846"
|
||||
- name: "\u8FD0\u884C\u65F6\u957F\u8F93\u5165\u6846"
|
||||
objectValue: {fileID: 5627652595602229817}
|
||||
dataValue:
|
||||
variableType: 10
|
||||
|
|
@ -15539,8 +15539,8 @@ MonoBehaviour:
|
|||
allowNegative: 0
|
||||
allowEmpty: 0
|
||||
maxDecimalPlaces: 1
|
||||
minValue: -15
|
||||
maxValue: 55
|
||||
minValue: 16
|
||||
maxValue: 32
|
||||
--- !u!1 &5627652596662180239
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -17828,7 +17828,7 @@ MonoBehaviour:
|
|||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: "\u6E29\u5EA6\u8303\u56F4(-15\u2103~55\u2103)"
|
||||
m_Text: "\u6E29\u5EA6\u8303\u56F4(16\u2103~32\u2103)"
|
||||
--- !u!1 &5627652596936877788
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -23919,7 +23919,7 @@ GameObject:
|
|||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2218283927450267575
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -23957,7 +23957,7 @@ RectTransform:
|
|||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 448, y: -11}
|
||||
m_AnchoredPosition: {x: -650, y: -359.76}
|
||||
m_SizeDelta: {x: 580, y: 300}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3579183680715366806
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ public class NumberInputField : MonoBehaviour
|
|||
[Header("输入规则")]
|
||||
[Tooltip("是否允许输入小数(小数点)")]
|
||||
public bool allowDecimal = true;
|
||||
|
||||
|
||||
[Tooltip("是否允许输入负数")]
|
||||
public bool allowNegative = false;
|
||||
|
||||
|
||||
[Tooltip("是否允许为空")]
|
||||
public bool allowEmpty = true;
|
||||
|
||||
|
||||
[Tooltip("小数点后最多几位(0表示不限制)")]
|
||||
[Range(0, 10)]
|
||||
public int maxDecimalPlaces = 2;
|
||||
|
|
@ -38,11 +38,12 @@ public class NumberInputField : MonoBehaviour
|
|||
|
||||
private string previousValidText = "";
|
||||
private InputField legacyInputField;
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
private TMP_InputField tmpInputField;
|
||||
#endif
|
||||
#endif
|
||||
private bool isInitialized = false;
|
||||
|
||||
|
||||
void Start()
|
||||
{
|
||||
InitializeInputField();
|
||||
|
|
@ -68,7 +69,7 @@ public class NumberInputField : MonoBehaviour
|
|||
{
|
||||
targetInputField = legacyInputField;
|
||||
}
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
else
|
||||
{
|
||||
tmpInputField = GetComponent<TMP_InputField>();
|
||||
|
|
@ -77,17 +78,17 @@ public class NumberInputField : MonoBehaviour
|
|||
targetInputField = tmpInputField;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
legacyInputField = targetInputField as InputField;
|
||||
#if TMP_PRESENT
|
||||
legacyInputField = targetInputField.GetComponent<InputField>();
|
||||
#if TMP_PRESENT
|
||||
if (legacyInputField == null)
|
||||
{
|
||||
tmpInputField = targetInputField as TMP_InputField;
|
||||
tmpInputField = targetInputField.GetComponent<TMP_InputField>();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (targetInputField == null)
|
||||
|
|
@ -100,15 +101,15 @@ public class NumberInputField : MonoBehaviour
|
|||
if (legacyInputField != null)
|
||||
{
|
||||
previousValidText = legacyInputField.text;
|
||||
legacyInputField.onValueChanged.AddListener(OnInputValueChanged);
|
||||
legacyInputField.onEndEdit.AddListener(OnInputValueChanged);
|
||||
}
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
else if (tmpInputField != null)
|
||||
{
|
||||
previousValidText = tmpInputField.text;
|
||||
tmpInputField.onValueChanged.AddListener(OnInputValueChanged);
|
||||
tmpInputField.onEndEdit.AddListener(OnInputValueChanged);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
|
@ -200,7 +201,7 @@ public class NumberInputField : MonoBehaviour
|
|||
// 3. 检查小数点和数字
|
||||
bool hasDecimalPoint = false;
|
||||
int decimalPlaces = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < str.Length; i++)
|
||||
{
|
||||
char c = str[i];
|
||||
|
|
@ -213,7 +214,7 @@ public class NumberInputField : MonoBehaviour
|
|||
if (!allowDecimal) return false; // 不允许小数
|
||||
if (hasDecimalPoint) return false; // 已经有一个小数点了
|
||||
hasDecimalPoint = true;
|
||||
|
||||
|
||||
// 小数点不能是唯一字符(除非前面有符号)
|
||||
if (i == 0 || (i == 1 && (str[0] == '-' || str[0] == '+')))
|
||||
{
|
||||
|
|
@ -248,10 +249,10 @@ public class NumberInputField : MonoBehaviour
|
|||
private bool HasTooManyDecimalPlaces(string str)
|
||||
{
|
||||
if (maxDecimalPlaces <= 0 || !allowDecimal) return false;
|
||||
|
||||
|
||||
int decimalIndex = str.IndexOf('.');
|
||||
if (decimalIndex == -1) return false;
|
||||
|
||||
|
||||
int decimalPlaces = str.Length - decimalIndex - 1;
|
||||
return decimalPlaces > maxDecimalPlaces;
|
||||
}
|
||||
|
|
@ -262,15 +263,15 @@ public class NumberInputField : MonoBehaviour
|
|||
private string TruncateDecimalPlaces(string str)
|
||||
{
|
||||
if (maxDecimalPlaces <= 0) return str;
|
||||
|
||||
|
||||
int decimalIndex = str.IndexOf('.');
|
||||
if (decimalIndex == -1) return str;
|
||||
|
||||
|
||||
if (decimalIndex + 1 + maxDecimalPlaces < str.Length)
|
||||
{
|
||||
return str.Substring(0, decimalIndex + 1 + maxDecimalPlaces);
|
||||
}
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
@ -292,12 +293,12 @@ public class NumberInputField : MonoBehaviour
|
|||
{
|
||||
legacyInputField.text = text;
|
||||
}
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
else if (tmpInputField != null)
|
||||
{
|
||||
tmpInputField.text = text;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -318,12 +319,12 @@ public class NumberInputField : MonoBehaviour
|
|||
{
|
||||
text = legacyInputField.text;
|
||||
}
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
else if (tmpInputField != null)
|
||||
{
|
||||
text = tmpInputField.text;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (string.IsNullOrEmpty(text) || text == "-" || text == "+" || text == ".")
|
||||
{
|
||||
|
|
@ -363,7 +364,7 @@ public class NumberInputField : MonoBehaviour
|
|||
{
|
||||
text = clampedValue.ToString("F" + maxDecimalPlaces);
|
||||
}
|
||||
|
||||
|
||||
SetInputFieldText(text);
|
||||
previousValidText = text;
|
||||
}
|
||||
|
|
@ -399,11 +400,11 @@ public class NumberInputField : MonoBehaviour
|
|||
{
|
||||
legacyInputField.onValueChanged.RemoveListener(OnInputValueChanged);
|
||||
}
|
||||
#if TMP_PRESENT
|
||||
#if TMP_PRESENT
|
||||
if (tmpInputField != null)
|
||||
{
|
||||
tmpInputField.onValueChanged.RemoveListener(OnInputValueChanged);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ public class EquipmentSimulationView : UIView
|
|||
|
||||
#region 切换设备
|
||||
|
||||
void InitLeftBtns()
|
||||
void InitLeftBtns()
|
||||
{
|
||||
|
||||
// 初始化字典
|
||||
|
|
@ -235,7 +235,7 @@ public class EquipmentSimulationView : UIView
|
|||
{
|
||||
SetSelectedButton(deviceBtns[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnButtonSelected(Button selectedButton, int index)
|
||||
{
|
||||
|
|
@ -352,7 +352,7 @@ public class EquipmentSimulationView : UIView
|
|||
/**/
|
||||
variables.Get<Button>("运行工况模拟").onClick.AddListener(delegate
|
||||
{
|
||||
SetHightlight(variables.Get<Button>("运行工况模拟"),modeData[0]);
|
||||
SetHightlight(variables.Get<Button>("运行工况模拟"), modeData[0]);
|
||||
SetNormal(variables.Get<Button>("高耗能场景模拟"), modeData[1]);
|
||||
SetNormal(variables.Get<Button>("节能改造实操"), modeData[2]);
|
||||
|
||||
|
|
@ -424,6 +424,11 @@ public class EquipmentSimulationView : UIView
|
|||
ShowWarming("请输入温度值!");
|
||||
return;
|
||||
}
|
||||
else if (!(string.IsNullOrEmpty(variables.Get<InputField>("运行时长输入框").text.Trim())))
|
||||
{
|
||||
InitializeChart("运行工况", "时间", 5, "温度");
|
||||
GenerateTemperatureChart(float.Parse(variables.Get<InputField>("运行时长输入框").text), float.Parse(variables.Get<InputField>("温度输入框").text));
|
||||
}
|
||||
}
|
||||
if (variables.Get<InputField>("风速输入框").gameObject.activeSelf)
|
||||
{
|
||||
|
|
@ -433,6 +438,11 @@ public class EquipmentSimulationView : UIView
|
|||
ShowWarming("请输入风速值!");
|
||||
return;
|
||||
}
|
||||
else if (!(string.IsNullOrEmpty(variables.Get<InputField>("运行时长输入框").text.Trim())))
|
||||
{
|
||||
InitializeChart("运行工况", "时间", 5, "风速");
|
||||
GenerateTemperatureChart(float.Parse(variables.Get<InputField>("运行时长输入框").text), float.Parse(variables.Get<InputField>("风速输入框").text));
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(variables.Get<InputField>("运行时长输入框").text.Trim()))
|
||||
{
|
||||
|
|
@ -459,6 +469,8 @@ public class EquipmentSimulationView : UIView
|
|||
{
|
||||
Debug.Log($"{field.text}");
|
||||
isEnterValue = true;
|
||||
InitializeChart("能耗变化", "异常参数", 10, "能耗");
|
||||
HighenErgyConsumptionChart(float.Parse(field.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -511,9 +523,9 @@ public class EquipmentSimulationView : UIView
|
|||
/// <summary>
|
||||
/// 折线设置
|
||||
/// </summary>
|
||||
private void InitializeChart(string title,string xAxisName,double yAxisMaxValue, string yAxisName)
|
||||
private void InitializeChart(string title, string xAxisName, double yAxisMaxValue, string yAxisName)
|
||||
{
|
||||
|
||||
|
||||
lineChart.RemoveData();
|
||||
|
||||
lineChart.EnsureChartComponent<Title>().text = title;
|
||||
|
|
@ -563,13 +575,13 @@ public class EquipmentSimulationView : UIView
|
|||
}
|
||||
|
||||
// 生成图表主方法
|
||||
public void GenerateTemperatureChart(float durationHours,float initialTemp)
|
||||
public void GenerateTemperatureChart(float durationHours, float initialTemp)
|
||||
{
|
||||
// 生成温度数据
|
||||
List<Vector2> temperatureData = GenerateTemperatureData(durationHours, initialTemp);
|
||||
|
||||
// 更新图表
|
||||
UpdateChartWithData(temperatureData, durationHours);
|
||||
UpdateChartWithData(temperatureData, 5);
|
||||
}
|
||||
|
||||
// 生成温度数据
|
||||
|
|
@ -582,13 +594,45 @@ public class EquipmentSimulationView : UIView
|
|||
{
|
||||
// 可以根据需要调整时间间隔
|
||||
float time = hour;
|
||||
float temperature = CalculateTemperatureAtHour(hour, initialTemp, durationHours);
|
||||
float temperature = CalculateTemperatureAtHour_(hour, initialTemp, durationHours);
|
||||
dataPoints.Add(new Vector2(time, temperature));
|
||||
}
|
||||
|
||||
return dataPoints;
|
||||
}
|
||||
// 生成高耗能场景图表
|
||||
public void HighenErgyConsumptionChart(float parameter)
|
||||
{
|
||||
// 生成温度数据
|
||||
List<Vector2> temperatureData = GetDynamicChartPoints(parameter);
|
||||
|
||||
// 更新图表
|
||||
UpdateChartWithData(temperatureData, 5);
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据当前故障程度,动态生成 X 轴和 Y 轴坐标点
|
||||
/// </summary>
|
||||
/// <param name="currentFault">当前的故障百分比数字 (如:输入 10 代表 10%)</param>
|
||||
/// <returns>返回 3 个动态坐标点</returns>
|
||||
public List<Vector2> GetDynamicChartPoints(float currentFault)
|
||||
{
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
// 1. 起点:永远是 (0, 基础能耗)
|
||||
points.Add(new Vector2(0f, 100));
|
||||
|
||||
// 2. 中点:X 轴是当前故障的一半,Y 轴能耗也相应增加一半
|
||||
float xMid = currentFault / 2f;
|
||||
float yMid = 100 + (100 * (xMid / 100f)); // 按比例增加能耗
|
||||
points.Add(new Vector2(xMid, yMid));
|
||||
|
||||
// 3. 终点:X 轴达到当前故障值,Y 轴达到目标能耗
|
||||
float xEnd = currentFault;
|
||||
float yEnd = 100 + (100 * (xEnd / 100f));
|
||||
points.Add(new Vector2(xEnd, yEnd));
|
||||
|
||||
return points;
|
||||
}
|
||||
// 计算每小时温度 - 可自定义算法
|
||||
private float CalculateTemperatureAtHour(int hour, float initialTemp, float totalDuration)
|
||||
{
|
||||
|
|
@ -607,7 +651,42 @@ public class EquipmentSimulationView : UIView
|
|||
return maxTemp;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 平滑显示温度曲线,从0-initialTemp
|
||||
/// </summary>
|
||||
/// <param name="hour"></param>
|
||||
/// <param name="initialTemp"></param>
|
||||
/// <param name="totalDuration"></param>
|
||||
/// <returns></returns>
|
||||
private float CalculateTemperatureAtHour_(int hour, float initialTemp, float totalDuration)
|
||||
{
|
||||
// 固定从 0 度开始
|
||||
float startTemp = 0f;
|
||||
|
||||
// 计算总体时间进度 (0.0 到 1.0)
|
||||
float timeFactor = Mathf.Clamp01((float)hour / totalDuration);
|
||||
|
||||
float currentTemp;
|
||||
|
||||
if (timeFactor < 0.7f)
|
||||
{
|
||||
// 前 70% 时间:从 0 指数升温
|
||||
// 为了让升温在 70% 的节点刚好平滑到达终点,我们将 0~0.7 的进度重新映射为 0~1
|
||||
float normalizedTime = timeFactor / 0.7f;
|
||||
|
||||
// 使用指数公式:当 normalizedTime 接近 1 时,1 - Exp(-5) 非常接近 1 (约0.993)
|
||||
// 这样温度就会从 0 平滑地上升到 initialTemp
|
||||
currentTemp = startTemp + (initialTemp - startTemp) * (1 - Mathf.Exp(-5f * normalizedTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 后 30% 时间:保持稳定在最高温
|
||||
currentTemp = initialTemp;
|
||||
}
|
||||
|
||||
// 最终安全限制:确保返回值被严格卡在 0 到 initialTemp 之间
|
||||
return Mathf.Clamp(currentTemp, 0f, initialTemp);
|
||||
}
|
||||
// 更新图表数据
|
||||
private void UpdateChartWithData(List<Vector2> dataPoints, float maxDuration)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue