Example #1
0
        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));
        }
Example #2
0
        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);
        }