Files
DTrierFlood_New/Assets/FloodSWE/Scripts/Preprocess/TileStaticData.cs

143 lines
4.3 KiB
C#

using System;
using UnityEngine;
namespace FloodSWE.Preprocess
{
public sealed class TileStaticData
{
public int GridRes { get; }
public float TileSizeMeters { get; }
public float MinHeight { get; }
public float MaxHeight { get; }
public float[] Heights { get; }
public float[] BuildingHeights { get; }
public byte[] Porosity { get; }
public TileStaticData(
int gridRes,
float tileSizeMeters,
float[] heights,
float minHeight,
float maxHeight,
float[] buildingHeights = null,
byte[] porosity = null)
{
if (gridRes <= 0)
{
throw new ArgumentOutOfRangeException(nameof(gridRes));
}
if (tileSizeMeters <= 0.0f)
{
throw new ArgumentOutOfRangeException(nameof(tileSizeMeters));
}
if (heights == null)
{
throw new ArgumentNullException(nameof(heights));
}
int expectedLength = gridRes * gridRes;
if (heights.Length != expectedLength)
{
throw new ArgumentException("Heights length does not match grid resolution.", nameof(heights));
}
if (buildingHeights != null && buildingHeights.Length != expectedLength)
{
throw new ArgumentException("Building heights length does not match grid resolution.", nameof(buildingHeights));
}
if (porosity != null && porosity.Length != expectedLength)
{
throw new ArgumentException("Porosity length does not match grid resolution.", nameof(porosity));
}
GridRes = gridRes;
TileSizeMeters = tileSizeMeters;
MinHeight = minHeight;
MaxHeight = maxHeight;
Heights = heights;
BuildingHeights = buildingHeights;
Porosity = porosity;
}
public static TileStaticData CreateFlat(
int gridRes,
float tileSizeMeters,
float heightMeters,
byte porosityValue = 255)
{
int length = gridRes * gridRes;
float[] heights = new float[length];
byte[] porosity = new byte[length];
for (int i = 0; i < length; i++)
{
heights[i] = heightMeters;
porosity[i] = porosityValue;
}
return new TileStaticData(gridRes, tileSizeMeters, heights, heightMeters, heightMeters, null, porosity);
}
public bool ValidateMinMax(float toleranceMeters, out float resampledMin, out float resampledMax)
{
ComputeMinMax(Heights, out resampledMin, out resampledMax);
if (toleranceMeters < 0.0f)
{
toleranceMeters = 0.0f;
}
return Mathf.Abs(resampledMin - MinHeight) <= toleranceMeters
&& Mathf.Abs(resampledMax - MaxHeight) <= toleranceMeters;
}
public ushort[] EncodeHeightsToUInt16Mm()
{
int length = Heights.Length;
ushort[] packed = new ushort[length];
for (int i = 0; i < length; i++)
{
float mm = (Heights[i] - MinHeight) * 1000.0f;
if (mm < 0.0f)
{
mm = 0.0f;
}
else if (mm > ushort.MaxValue)
{
mm = ushort.MaxValue;
}
packed[i] = (ushort)Mathf.RoundToInt(mm);
}
return packed;
}
private static void ComputeMinMax(float[] data, out float min, out float max)
{
min = float.PositiveInfinity;
max = float.NegativeInfinity;
for (int i = 0; i < data.Length; i++)
{
float value = data[i];
if (value < min)
{
min = value;
}
if (value > max)
{
max = value;
}
}
if (float.IsInfinity(min))
{
min = 0.0f;
max = 0.0f;
}
}
}
}