143 lines
4.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|