161 lines
6.2 KiB
C#
161 lines
6.2 KiB
C#
using SFML.Graphics;
|
|
using SFML.System;
|
|
using FluidSim.Core;
|
|
using FluidSim.Components;
|
|
|
|
namespace FluidSim.Tests
|
|
{
|
|
public abstract class Scenario
|
|
{
|
|
protected const float AmbientPressure = 101325f;
|
|
protected const float AmbientTemperature = 300f;
|
|
public float Throttle { get; set; }
|
|
|
|
public abstract void Initialize(int sampleRate);
|
|
public abstract float Process();
|
|
public abstract void Draw(RenderWindow target);
|
|
|
|
protected Color PressureColor(float pressurePa)
|
|
{
|
|
float bar = pressurePa / 1e5f;
|
|
byte r, g, b;
|
|
if (bar < 1f)
|
|
{
|
|
float f = Math.Clamp(bar, 0f, 1f);
|
|
r = 0; g = (byte)(255 * f); b = (byte)(255 * (1 - f));
|
|
}
|
|
else
|
|
{
|
|
float f = Math.Min((bar - 1f) / 9f, 1f);
|
|
r = (byte)(255 * f); g = (byte)(255 * (1 - f)); b = 0;
|
|
}
|
|
return new Color(r, g, b);
|
|
}
|
|
|
|
protected Color TemperatureColor(float t)
|
|
{
|
|
t = Math.Clamp(t, 0f, 2000f);
|
|
byte r, g, b;
|
|
if (t < AmbientTemperature)
|
|
{
|
|
float f = t / AmbientTemperature;
|
|
r = 0; g = (byte)(255 * f); b = (byte)(255 * (1 - f));
|
|
}
|
|
else
|
|
{
|
|
float f = (t - AmbientTemperature) / (2000f - AmbientTemperature);
|
|
r = (byte)(255 * f); g = (byte)(255 * (1 - f)); b = 0;
|
|
}
|
|
return new Color(r, g, b);
|
|
}
|
|
|
|
protected void DrawVolume(RenderWindow target, Volume0D volume,
|
|
float centerX, float topY, float width, float height)
|
|
{
|
|
var rect = new RectangleShape(new Vector2f(width, height))
|
|
{
|
|
FillColor = PressureColor(volume.Pressure),
|
|
Position = new Vector2f(centerX - width / 2f, topY)
|
|
};
|
|
target.Draw(rect);
|
|
var border = new RectangleShape(new Vector2f(width, height))
|
|
{
|
|
FillColor = Color.Transparent,
|
|
OutlineColor = Color.White,
|
|
OutlineThickness = 1f,
|
|
Position = rect.Position
|
|
};
|
|
target.Draw(border);
|
|
}
|
|
|
|
protected void DrawCylinder(RenderWindow target, Cylinder cylinder,
|
|
float centerX, float topY, float width, float maxHeight)
|
|
{
|
|
float fraction = cylinder.PistonFraction;
|
|
float currentHeight = maxHeight * fraction;
|
|
var wall = new RectangleShape(new Vector2f(width, maxHeight))
|
|
{
|
|
FillColor = new Color(60, 60, 60),
|
|
Position = new Vector2f(centerX - width / 2f, topY)
|
|
};
|
|
target.Draw(wall);
|
|
var gas = new RectangleShape(new Vector2f(width, currentHeight))
|
|
{
|
|
FillColor = PressureColor(cylinder.Pressure),
|
|
Position = new Vector2f(centerX - width / 2f, topY)
|
|
};
|
|
target.Draw(gas);
|
|
var piston = new RectangleShape(new Vector2f(width, 4f))
|
|
{
|
|
FillColor = Color.White,
|
|
Position = new Vector2f(centerX - width / 2f, topY + currentHeight)
|
|
};
|
|
target.Draw(piston);
|
|
float valveW = 6f, valveH = 10f, valveY = topY + 4f;
|
|
var iv = new RectangleShape(new Vector2f(valveW, valveH))
|
|
{
|
|
FillColor = cylinder.IntakeValveArea > 0f ? Color.Green : Color.Red,
|
|
Position = new Vector2f(centerX - width / 2f - valveW - 2f, valveY)
|
|
};
|
|
target.Draw(iv);
|
|
var ev = new RectangleShape(new Vector2f(valveW, valveH))
|
|
{
|
|
FillColor = cylinder.ExhaustValveArea > 0f ? Color.Green : Color.Red,
|
|
Position = new Vector2f(centerX + width / 2f + 2f, valveY)
|
|
};
|
|
target.Draw(ev);
|
|
}
|
|
|
|
protected void DrawPipe(RenderWindow target, PipeSystem pipeSystem, int pipeIndex,
|
|
float pipeCenterY, float pipeStartX, float pipeEndX)
|
|
{
|
|
int start = pipeSystem.GetPipeStart(pipeIndex);
|
|
int end = pipeSystem.GetPipeEnd(pipeIndex);
|
|
int n = end - start;
|
|
if (n < 2) return;
|
|
|
|
float pipeLen = pipeEndX - pipeStartX;
|
|
float dx = pipeLen / (n - 1);
|
|
float baseRadius = 25f;
|
|
|
|
var centers = new float[n];
|
|
var radii = new float[n];
|
|
var temps = new float[n];
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
int cell = start + i;
|
|
float p = pipeSystem.GetCellPressure(cell);
|
|
float rho = pipeSystem.GetCellDensity(cell);
|
|
temps[i] = p / MathF.Max(rho * 287f, 1e-12f);
|
|
float dev = MathF.Tanh((p - AmbientPressure) / AmbientPressure * 0.5f);
|
|
radii[i] = baseRadius * (1f + dev * 2f);
|
|
if (radii[i] < 2f) radii[i] = 2f;
|
|
centers[i] = pipeStartX + i * dx;
|
|
}
|
|
|
|
int segments = 8;
|
|
var va = new VertexArray(PrimitiveType.TriangleStrip);
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
float x = centers[i], r = radii[i];
|
|
Color col = TemperatureColor(temps[i]);
|
|
va.Append(new Vertex(new Vector2f(x, pipeCenterY - r), col));
|
|
va.Append(new Vertex(new Vector2f(x, pipeCenterY + r), col));
|
|
if (i < n - 1)
|
|
{
|
|
for (int s = 1; s <= segments; s++)
|
|
{
|
|
float t = s / (float)segments;
|
|
float xi = centers[i] + (centers[i + 1] - centers[i]) * t;
|
|
float ri = radii[i] + (radii[i + 1] - radii[i]) * t;
|
|
float Ti = temps[i] + (temps[i + 1] - temps[i]) * t;
|
|
Color colS = TemperatureColor(Ti);
|
|
va.Append(new Vertex(new Vector2f(xi, pipeCenterY - ri), colS));
|
|
va.Append(new Vertex(new Vector2f(xi, pipeCenterY + ri), colS));
|
|
}
|
|
}
|
|
}
|
|
target.Draw(va);
|
|
}
|
|
}
|
|
} |