add line chart, fix renderable culling, (probably) fix run loop
This commit is contained in:
Родитель
5019baea9f
Коммит
5cbf35eefa
|
@ -6,6 +6,6 @@ namespace SomeChartsAvaloniaExamples;
|
|||
internal class Program {
|
||||
[STAThread]
|
||||
public static void Main(string[] args) {
|
||||
ElementsExamples.RunLabel();
|
||||
ElementsExamples.RunLineChart();
|
||||
}
|
||||
}
|
|
@ -149,28 +149,29 @@ public static class ElementsExamples {
|
|||
|
||||
public static void RunLineChart() {
|
||||
AvaloniaRunUtils.RunAfterStart(() => {
|
||||
AvaloniaChartsCanvas canvas = AvaloniaRunUtils.AddCanvas();
|
||||
AvaloniaGlChartsCanvas canvas = AvaloniaRunUtils.AddGlCanvas();
|
||||
const int rulerOffset = 1_000_000;
|
||||
|
||||
canvas.AddElement(new Ruler(canvas.canvas) {
|
||||
drawLabels = true,
|
||||
orientation = Orientation.horizontal,
|
||||
length = rulerOffset,
|
||||
names = new FuncChartManagedData<string>(i => i.ToString(), 1),
|
||||
stickRange = new(0, 0, 0, rulerOffset)
|
||||
});
|
||||
// canvas.AddElement(new Ruler(canvas.canvas) {
|
||||
// drawLabels = true,
|
||||
// orientation = Orientation.horizontal,
|
||||
// length = rulerOffset,
|
||||
// names = new FuncChartManagedData<string>(i => i.ToString(), 1),
|
||||
// stickRange = new(0, 0, 0, rulerOffset)
|
||||
// });
|
||||
//
|
||||
// canvas.AddElement(new Ruler(canvas.canvas) {
|
||||
// drawLabels = true,
|
||||
// orientation = Orientation.vertical,
|
||||
// length = rulerOffset,
|
||||
// names = new FuncChartManagedData<string>(i => (i * 100).ToString(), 1),
|
||||
// stickRange = new(0, 0, rulerOffset, 0)
|
||||
// });
|
||||
|
||||
canvas.AddElement(new Ruler(canvas.canvas) {
|
||||
drawLabels = true,
|
||||
orientation = Orientation.vertical,
|
||||
length = rulerOffset,
|
||||
names = new FuncChartManagedData<string>(i => (i * 100).ToString(), 1),
|
||||
stickRange = new(0, 0, rulerOffset, 0)
|
||||
});
|
||||
IChartData<float> data = new FuncChartData<float>(i => MathF.Sin(i * .1f) * 1000, 20480);
|
||||
IChartData<indexedColor> colors = new ConstChartData<indexedColor>(new(theme.bad_ind));
|
||||
|
||||
IChartData<float> data = new FuncChartData<float>(i => MathF.Sin(i * .1f) * 1000, 2048);
|
||||
IChartData<indexedColor> colors = new ConstChartData<indexedColor>(new(theme.good_ind));
|
||||
canvas.AddElement(new LineChart(data, colors, canvas.canvas));
|
||||
canvas.AddElement(new LineChart(data, colors, canvas.canvas) {isDynamic = true});
|
||||
});
|
||||
|
||||
AvaloniaRunUtils.RunAvalonia();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using MathStuff;
|
||||
using MathStuff.vectors;
|
||||
using SomeChartsUi.data;
|
||||
using SomeChartsUi.themes.colors;
|
||||
using SomeChartsUi.ui.canvas;
|
||||
|
@ -24,33 +26,33 @@ public class LineChart : RenderableBase, IDownsample {
|
|||
public float downsampleMultiplier { get; set; } = .5f;
|
||||
public float elementScale { get; set; } = 100;
|
||||
|
||||
protected override void GenerateMesh() { }
|
||||
// protected override unsafe void Render() {
|
||||
// int length = values.GetLength();
|
||||
// if (length < 1) return;
|
||||
//
|
||||
// int downsample = GetDownsample(orientation, downsampleMultiplier);
|
||||
// (float startPos, float endPos) culledPositions = GetStartEndPos(float2.zero, length * elementScale, orientation);
|
||||
// (float start, int count) = GetStartCountIndexes(culledPositions, elementScale * (1 << downsample));
|
||||
// int startIndex = (int)(start / elementScale);
|
||||
//
|
||||
// if (count <= 1) return;
|
||||
//
|
||||
// float2 vec = GetOrientationVector(orientation);
|
||||
//
|
||||
// // get line points
|
||||
// float2* linePoints = stackalloc float2[count];
|
||||
// float* pointHeightsStart = (float*)linePoints + (int) vec.x;
|
||||
// float* pointWidthStart = (float*)linePoints + (int) vec.y;
|
||||
// values.GetValuesWithStride(startIndex, count, downsample, pointHeightsStart, 2);
|
||||
// for (int i = 0; i < count; i++)
|
||||
// pointWidthStart[i << 1] = (startIndex + (i << downsample)) * elementScale;
|
||||
//
|
||||
// // get line colors
|
||||
// color* lineColors = stackalloc color[count];
|
||||
// colors.GetColors(startIndex, count, downsample, lineColors);
|
||||
//
|
||||
// DrawConnectedLines(linePoints, lineColors, lineThickness.Get(this), count - 1, lineAlphaMul.Get(this));
|
||||
// DrawPoints(linePoints, lineColors, pointThickness.Get(this), count - 1);
|
||||
// }
|
||||
protected override unsafe void GenerateMesh() {
|
||||
mesh!.Clear();
|
||||
|
||||
int length = values.GetLength();
|
||||
if (length < 1) return;
|
||||
int downsample = GetDownsample(orientation, downsampleMultiplier);
|
||||
(float startPos, float endPos) culledPositions = GetStartEndPos(float2.zero, length * elementScale, orientation);
|
||||
(float start, int count) = GetStartCountIndexes(culledPositions, elementScale * (1 << downsample));
|
||||
int startIndex = (int)(start / elementScale);
|
||||
if (count <= 1) return;
|
||||
float2 vec = GetOrientationVector(orientation);
|
||||
|
||||
// get line points
|
||||
float2* linePoints = stackalloc float2[count];
|
||||
float* pointHeightsStart = (float*)linePoints + (int) vec.x;
|
||||
float* pointWidthStart = (float*)linePoints + (int) vec.y;
|
||||
values.GetValuesWithStride(startIndex, count, downsample, pointHeightsStart, 2);
|
||||
for (int i = 0; i < count; i++)
|
||||
pointWidthStart[i << 1] = (startIndex + (i << downsample)) * elementScale;
|
||||
|
||||
// get line colors
|
||||
color* lineColors = stackalloc color[count];
|
||||
colors.GetColors(startIndex, count, downsample, lineColors);
|
||||
|
||||
AddPoints(mesh, linePoints, lineColors, pointThickness.Get(this), count - 1);
|
||||
AddConnectedLines(mesh!, linePoints, lineColors, lineThickness.Get(this), count - 1, lineAlphaMul.Get(this));
|
||||
|
||||
mesh.OnModified();
|
||||
}
|
||||
}
|
|
@ -27,8 +27,8 @@ public class ChartCanvasTransform {
|
|||
scale.OnUpdate(deltaTime);
|
||||
rotation.OnUpdate(deltaTime);
|
||||
|
||||
worldBounds = screenBounds.ToWorld(position, scale);
|
||||
|
||||
//worldBounds = screenBounds.ToWorld(-position.animatedValue, scale);
|
||||
worldBounds = new(screenBounds.left + position.animatedValue.x - screenBounds.width / 2 / scale.animatedValue.x, screenBounds.bottom + position.animatedValue.y, screenBounds.width / scale.animatedValue.x, screenBounds.height / scale.animatedValue.y);
|
||||
RecalculateMatrix();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,76 @@
|
|||
using MathStuff;
|
||||
using MathStuff.vectors;
|
||||
using SomeChartsUi.elements;
|
||||
using SomeChartsUi.utils.mesh;
|
||||
|
||||
namespace SomeChartsUi.ui.elements;
|
||||
|
||||
public abstract partial class RenderableBase {
|
||||
protected unsafe void AddConnectedLines(Mesh m, float2* linePoints, color* lineColors, float thickness, int len, float alphaMul = 1) {
|
||||
int vCount = len * 4;
|
||||
int iCount = len * 6;
|
||||
|
||||
m.vertices.EnsureFreeSpace(vCount);
|
||||
m.indexes.EnsureFreeSpace(iCount);
|
||||
|
||||
int curVIndex = m.vertices.count;
|
||||
for (int i = 0; i < len; i++) {
|
||||
float2 p0 = linePoints[i];
|
||||
float2 p1 = linePoints[i + 1];
|
||||
color c0 = lineColors[i];
|
||||
c0.aF *= alphaMul;
|
||||
|
||||
float2 offset = Rot90DegFastWithLen(p0 - p1, thickness);
|
||||
|
||||
m.AddVertex(new(new(p1.x - offset.x, p1.y - offset.y), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p1.x + offset.x, p1.y + offset.y), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p0.x + offset.x, p0.y + offset.y), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p0.x - offset.x, p0.y - offset.y), float3.front, float2.zero, c0));
|
||||
|
||||
m.AddIndex(curVIndex + 0);
|
||||
m.AddIndex(curVIndex + 1);
|
||||
m.AddIndex(curVIndex + 2);
|
||||
m.AddIndex(curVIndex + 0);
|
||||
m.AddIndex(curVIndex + 2);
|
||||
m.AddIndex(curVIndex + 3);
|
||||
|
||||
curVIndex += 4;
|
||||
}
|
||||
|
||||
//m.vertices.Add();
|
||||
//
|
||||
//DrawVertices(points, null, colors, indexes, vCount, iCount);
|
||||
}
|
||||
|
||||
protected unsafe void AddPoints(Mesh m, float2* elementPoints, color* elementColors, float size, int len) {
|
||||
int vCount = len * 4;
|
||||
int iCount = len * 6;
|
||||
|
||||
m.vertices.EnsureFreeSpace(vCount);
|
||||
m.indexes.EnsureFreeSpace(iCount);
|
||||
|
||||
int curVIndex = m.vertices.count;
|
||||
for (int i = 0; i < len; i++) {
|
||||
float2 p0 = elementPoints[i];
|
||||
color c0 = elementColors[i];
|
||||
|
||||
m.AddVertex(new(new(p0.x - size, p0.y - size), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p0.x - size, p0.y + size), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p0.x + size, p0.y + size), float3.front, float2.zero, c0));
|
||||
m.AddVertex(new(new(p0.x + size, p0.y - size), float3.front, float2.zero, c0));
|
||||
|
||||
m.AddIndex(curVIndex + 0);
|
||||
m.AddIndex(curVIndex + 1);
|
||||
m.AddIndex(curVIndex + 2);
|
||||
m.AddIndex(curVIndex + 0);
|
||||
m.AddIndex(curVIndex + 2);
|
||||
m.AddIndex(curVIndex + 3);
|
||||
|
||||
curVIndex += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* /// <summary>draws non-connected lines</summary>
|
||||
/// <param name="linePoints">first and second points of lines <br/>the length is 2 * lineCount</param>
|
||||
/// <param name="lineColors">first and second point colors of lines <br/>the length is 2 * lineCount</param>
|
||||
|
|
|
@ -61,6 +61,8 @@ public abstract partial class RenderableBase {
|
|||
protected (float start, float end) GetStartEndPos(float startLim, float endLim, Orientation orientation) {
|
||||
float2 s = 1 / canvasScale;
|
||||
Transform tr = transform;
|
||||
//Console.WriteLine(startLim + " " + endLim + " " + math.min(endLim, canvas.transform.worldBounds.right*10 - tr.position.x));
|
||||
//return (math.max(startLim, canvas.transform.worldBounds.left - tr.position.x), math.min(endLim, canvas.transform.worldBounds.right - tr.position.x));
|
||||
if ((orientation & Orientation.vertical) != 0)
|
||||
return (orientation & Orientation.reversed) != 0
|
||||
? (math.max(startLim, canvas.transform.worldBounds.top - tr.position.y), math.min(endLim, canvas.transform.worldBounds.bottom - tr.position.y))
|
||||
|
|
|
@ -53,6 +53,9 @@ public class Mesh : IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
public void AddVertex(Vertex v) => vertices.Add(v);
|
||||
public void AddIndex(int v) => indexes.Add((ushort) v);
|
||||
|
||||
public unsafe void RecalculateNormals() {
|
||||
int c = indexes.count;
|
||||
|
||||
|
|
|
@ -33,7 +33,10 @@ public class AvaloniaGlChartsCanvas : CustomGlControlBase {
|
|||
|
||||
public AvaloniaGlChartsCanvas() {
|
||||
_updateTimer = new(_ => {
|
||||
try { Dispatcher.UIThread?.RunJobs(); }
|
||||
try {
|
||||
if (Dispatcher.UIThread.CheckAccess())
|
||||
Dispatcher.UIThread?.RunJobs();
|
||||
}
|
||||
catch (Exception e) {// ignored
|
||||
}
|
||||
}, null, 0, 1000 / 50);
|
||||
|
|
|
@ -68,7 +68,7 @@ public class GlMesh : Mesh {
|
|||
else {
|
||||
List<Range> changes = vertices.GetChanges();
|
||||
foreach (Range r in changes)
|
||||
GlInfo.glExt!.BufferSubData(GL_ARRAY_BUFFER, r.Start.Value * vSize, (r.End.Value - r.Start.Value) * vSize, vertices.dataPtr);
|
||||
GlInfo.glExt!.BufferSubData(GL_ARRAY_BUFFER, r.Start.Value * vSize, (r.End.Value - r.Start.Value) * vSize, vertices.dataPtr + r.Start.Value);
|
||||
}
|
||||
|
||||
// indexes
|
||||
|
@ -82,7 +82,7 @@ public class GlMesh : Mesh {
|
|||
else {
|
||||
List<Range> changes = indexes.GetChanges();
|
||||
foreach (Range r in changes)
|
||||
GlInfo.glExt!.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, r.Start.Value * iSize, (r.End.Value - r.Start.Value) * iSize, indexes.dataPtr);
|
||||
GlInfo.glExt!.BufferSubData(GL_ELEMENT_ARRAY_BUFFER, r.Start.Value * iSize, (r.End.Value - r.Start.Value) * iSize, indexes.dataPtr + r.Start.Value);
|
||||
}
|
||||
|
||||
updateRequired = false;
|
||||
|
|
Загрузка…
Ссылка в новой задаче