public static Image PartitionMask(Image mask, float3[] centroids) { float[] MaskData = mask.GetHostContinuousCopy(); int[] Partitions = new int[MaskData.Length]; int3 Dims = mask.Dims; Parallel.For(0, Dims.Z, z => { for (int y = 0; y < Dims.Y; y++) { for (int x = 0; x < Dims.X; x++) { if (MaskData[Dims.ElementFromPosition(x, y, z)] != 1) { Partitions[Dims.ElementFromPosition(x, y, z)] = -1; } else { float3 Pos = new float3(x, y, z); float BestDist = float.MaxValue; int BestCentroid = 0; for (int c = 0; c < centroids.Length; c++) { float Dist = (Pos - centroids[c]).LengthSq(); if (Dist < BestDist) { BestDist = Dist; BestCentroid = c; } } Partitions[Dims.ElementFromPosition(x, y, z)] = BestCentroid; } } } }); return(new Image(Partitions.Select(v => (float)v).ToArray(), Dims)); }
public static float3[] FillWithEquidistantPoints(Image mask, int n, out float R) { float3 MaskCenter = mask.AsCenterOfMass(); float[] MaskData = mask.GetHostContinuousCopy(); int3 Dims = mask.Dims; float3[] BestSolution = null; float a = 0, b = Dims.X / 2; R = (a + b) / 2; float3 Offset = new float3(0, 0, 0); for (int o = 0; o < 2; o++) { for (int i = 0; i < 10; i++) { R = (a + b) / 2; float Root3 = (float)Math.Sqrt(3); float ZTerm = (float)(2 * Math.Sqrt(6) / 3); float SpacingX = R * 2; float SpacingY = Root3 * R; float SpacingZ = ZTerm * R; int3 DimsSphere = new int3(Math.Min(512, (int)Math.Ceiling(Dims.X / SpacingX)), Math.Min(512, (int)Math.Ceiling(Dims.Y / SpacingX)), Math.Min(512, (int)Math.Ceiling(Dims.Z / SpacingX))); BestSolution = new float3[DimsSphere.Elements()]; for (int z = 0; z < DimsSphere.Z; z++) { for (int y = 0; y < DimsSphere.Y; y++) { for (int x = 0; x < DimsSphere.X; x++) { BestSolution[DimsSphere.ElementFromPosition(x, y, z)] = new float3(2 * x + (y + z) % 2, Root3 * (y + 1 / 3f * (z % 2)), ZTerm * z) * R + Offset; } } } List <float3> InsideMask = BestSolution.Where(p => { int3 ip = new int3(p); if (ip.X >= 0 && ip.X < Dims.X && ip.Y >= 0 && ip.Y < Dims.Y && ip.Z >= 0 && ip.Z < Dims.Z) { return(MaskData[Dims.ElementFromPosition(new int3(p))] == 1); } return(false); }).ToList(); BestSolution = InsideMask.ToArray(); if (BestSolution.Length == n) { break; } else if (BestSolution.Length < n) { b = R; } else { a = R; } } float3 CenterOfPoints = MathHelper.Mean(BestSolution); Offset = MaskCenter - CenterOfPoints; a = 0.8f * R; b = 1.2f * R; } BestSolution = BestSolution.Select(v => v + Offset).ToArray(); return(BestSolution); }