|
@@ -1,6 +1,5 @@
|
|
using PixiEditor.ChangeableDocument.Rendering;
|
|
using PixiEditor.ChangeableDocument.Rendering;
|
|
using PixiEditor.DrawingApi.Core;
|
|
using PixiEditor.DrawingApi.Core;
|
|
-using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
|
|
|
|
using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
|
|
using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
|
|
using PixiEditor.Numerics;
|
|
using PixiEditor.Numerics;
|
|
|
|
|
|
@@ -9,17 +8,10 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Points;
|
|
[NodeInfo("DistributePoints")]
|
|
[NodeInfo("DistributePoints")]
|
|
public class DistributePointsNode : Node
|
|
public class DistributePointsNode : Node
|
|
{
|
|
{
|
|
- private readonly Paint averageGrayscalePaint = new()
|
|
|
|
- {
|
|
|
|
- ColorFilter = Filters.AverageGrayscaleFilter
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
public override string DisplayName { get; set; } = "DISTRIBUTE_POINTS";
|
|
public override string DisplayName { get; set; } = "DISTRIBUTE_POINTS";
|
|
|
|
|
|
public OutputProperty<PointList> Points { get; }
|
|
public OutputProperty<PointList> Points { get; }
|
|
|
|
|
|
- public InputProperty<Surface> Probability { get; }
|
|
|
|
-
|
|
|
|
public InputProperty<int> MaxPointCount { get; }
|
|
public InputProperty<int> MaxPointCount { get; }
|
|
|
|
|
|
public InputProperty<int> Seed { get; }
|
|
public InputProperty<int> Seed { get; }
|
|
@@ -28,18 +20,13 @@ public class DistributePointsNode : Node
|
|
{
|
|
{
|
|
Points = CreateOutput(nameof(Points), "POINTS", PointList.Empty);
|
|
Points = CreateOutput(nameof(Points), "POINTS", PointList.Empty);
|
|
|
|
|
|
- Probability = CreateInput<Surface>("Probability", "PROBABILITY", null);
|
|
|
|
MaxPointCount = CreateInput("MaxPointCount", "MAX_POINTS", 10);
|
|
MaxPointCount = CreateInput("MaxPointCount", "MAX_POINTS", 10);
|
|
Seed = CreateInput("Seed", "SEED", 0);
|
|
Seed = CreateInput("Seed", "SEED", 0);
|
|
}
|
|
}
|
|
|
|
|
|
protected override Surface? OnExecute(RenderingContext context)
|
|
protected override Surface? OnExecute(RenderingContext context)
|
|
{
|
|
{
|
|
- Points.Value = Probability.Value switch
|
|
|
|
- {
|
|
|
|
- { } prop => GetPointsByProbability(prop),
|
|
|
|
- _ => GetPointsRandomly()
|
|
|
|
- };
|
|
|
|
|
|
+ Points.Value = GetPointsRandomly();
|
|
|
|
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
@@ -51,7 +38,7 @@ public class DistributePointsNode : Node
|
|
var pointCount = MaxPointCount.Value;
|
|
var pointCount = MaxPointCount.Value;
|
|
var finalPoints = new PointList(pointCount)
|
|
var finalPoints = new PointList(pointCount)
|
|
{
|
|
{
|
|
- HashValue = HashCode.Combine(Probability.Value, pointCount, seed)
|
|
|
|
|
|
+ HashValue = HashCode.Combine(pointCount, seed)
|
|
};
|
|
};
|
|
|
|
|
|
for (int i = 0; i < pointCount; i++)
|
|
for (int i = 0; i < pointCount; i++)
|
|
@@ -62,107 +49,5 @@ public class DistributePointsNode : Node
|
|
return finalPoints;
|
|
return finalPoints;
|
|
}
|
|
}
|
|
|
|
|
|
- private PointList GetPointsByProbability(Surface probability)
|
|
|
|
- {
|
|
|
|
- var size = probability.Size;
|
|
|
|
- using var probabilityImage = Surface.UsingColorType(size, ColorType.Gray8);
|
|
|
|
- probabilityImage.DrawingSurface.Canvas.DrawSurface(probability.DrawingSurface, 0, 0, averageGrayscalePaint);
|
|
|
|
-
|
|
|
|
- using var pixmap = probabilityImage.PeekPixels();
|
|
|
|
-
|
|
|
|
- var random = new Random(Seed.Value);
|
|
|
|
- var pixels = pixmap.GetPixelSpan<byte>();
|
|
|
|
-
|
|
|
|
- var rowSumCache = new int[size.Y];
|
|
|
|
- var rowColCache = new int[size.X];
|
|
|
|
- Array.Fill(rowSumCache, -1);
|
|
|
|
-
|
|
|
|
- var pointCount = MaxPointCount.Value;
|
|
|
|
- var finalPoints = new PointList(pointCount) { HashValue = 0 };
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < pointCount; i++)
|
|
|
|
- {
|
|
|
|
- var xColRandom = random.Next(size.Y);
|
|
|
|
- var columnSum = GetColumnSum(xColRandom, size, pixels, rowColCache);
|
|
|
|
-
|
|
|
|
- var yRowRandom = random.Next(size.Y);
|
|
|
|
- var row = pixels.Slice(yRowRandom * size.X, size.X);
|
|
|
|
- var rowSum = GetRowSum(yRowRandom, row, rowSumCache);
|
|
|
|
-
|
|
|
|
- var xRandom = random.Next(rowSum);
|
|
|
|
- var yRandom = random.Next(columnSum);
|
|
|
|
-
|
|
|
|
- int counted = 0;
|
|
|
|
- int finalX = GetFinalPosition(row.Length, xRandom, row, (s, j) => s[j]);
|
|
|
|
- int finalY = GetFinalPosition(size.Y, yRandom, pixels, (s, j) => s[j * size.X + xColRandom]);
|
|
|
|
-
|
|
|
|
- if (finalX == -1 || finalY == -1)
|
|
|
|
- {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- finalPoints.Add(new VecD((double)finalX / size.X, (double)finalY / size.Y));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return finalPoints;
|
|
|
|
-
|
|
|
|
- static int GetFinalPosition(int size, int random, Span<byte> pixels, SpanAccessor accessor)
|
|
|
|
- {
|
|
|
|
- int counted = 0;
|
|
|
|
- int final;
|
|
|
|
- for (final = 0; final < size; final++)
|
|
|
|
- {
|
|
|
|
- counted += accessor(pixels, final);
|
|
|
|
-
|
|
|
|
- if (counted > random)
|
|
|
|
- {
|
|
|
|
- //finalPoints.Add(new VecD((double)j / size.X, (double)yRowRandom / size.Y));
|
|
|
|
- return final;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- delegate byte SpanAccessor(Span<byte> span, int index);
|
|
|
|
-
|
|
|
|
- private static int GetColumnSum(int x, VecI size, Span<byte> pixels, int[] sumCache)
|
|
|
|
- {
|
|
|
|
- int sum = sumCache[x];
|
|
|
|
-
|
|
|
|
- if (sum == -1)
|
|
|
|
- {
|
|
|
|
- sum = 0;
|
|
|
|
- for (int y = 0; y < size.Y; y++)
|
|
|
|
- {
|
|
|
|
- sum += pixels[size.X * y];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sumCache[x] = sum;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return sum;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static int GetRowSum(int y, ReadOnlySpan<byte> row, int[] sumCache)
|
|
|
|
- {
|
|
|
|
- var sum = sumCache[y];
|
|
|
|
-
|
|
|
|
- if (sum == -1)
|
|
|
|
- {
|
|
|
|
- sum = 0;
|
|
|
|
- foreach (var value in row)
|
|
|
|
- {
|
|
|
|
- sum += value;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sumCache[y] = sum;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return sum;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
public override Node CreateCopy() => new DistributePointsNode();
|
|
public override Node CreateCopy() => new DistributePointsNode();
|
|
}
|
|
}
|