public BowyerSimplice(HyperSphereConstraint containConstraint, int rank, BowyerVoronoiVertex voronoiVertex, BowyerNuclei[] nucleis)
        {
            this.Rank = rank;
            this.nucleis = nucleis;
            this.voronoiVertex = voronoiVertex;
            this.containConstraint = containConstraint;
            infiniteSimplice = this.Rank == nucleis.Length;

            //if(!this.InfiniteSimplice)
            foreach (var n in nucleis)
                n.AddSimplice(this);

            if (InfiniteSimplice || rank == 0)
            {
                facets = new BowyerSimpliceFacet[] { new BowyerSimpliceFacet(this.voronoiVertex, null, nucleis) };
            }
            else
            {
                facets = new BowyerSimpliceFacet[Rank + 1];
                IEnumerable<IEnumerable<BowyerNuclei>> fs = Helpers.Combinations(nucleis, rank);
                int i = 0;

                foreach (var f in fs)
                    facets[i++] = new BowyerSimpliceFacet(this.voronoiVertex, null, f);
            }
        }
 public BowyerVoronoiVertex(int dimensionality, BowyerNuclei[] nucleis, HyperSphereConstraint hyperSphereConstraint)
 {
     simplice = new BowyerSimplice(hyperSphereConstraint, dimensionality, this, nucleis);
 }
        private IEnumerable<BowyerVoronoiVertex> BuildTesellation(IEnumerable<BowyerNuclei> affectedNucleis, IEnumerable<BowyerSimpliceFacet> aloneOldFacets, int groupRank)
        {
            int previousVoronoiVertexSize = voronoiVertexes.Count;
            var newVoronoiVertexes = Helpers.Combinations(affectedNucleis, groupRank + 1);

#warning optimizable: cant this be an reusable attribute?
            foreach (var nucleiGroup in newVoronoiVertexes)
            {
                BowyerNuclei[] nucleiGroupArray = nucleiGroup.ToArray();

                bool validSimplice = false;

                BowyerVoronoiVertex v = null;
                //if (groupRank == ProblemDimensionality)
                //{ //this is the usual case
                //    HyperSphereConstraint hyperSphereConstraint = new HyperSphereConstraint(this.ProblemDimensionality);
                //    hyperSphereConstraint.Calculate(nucleiGroupArray, ProblemDimensionality, groupRank+1);
                //    if (affectedNucleis.Except(nucleiGroupArray)
                //    .All(nuc => !hyperSphereConstraint.CircumsphereContains(nuc.Coordinates)))
                //    {
                //        validSimplice = true;
                //        v = new BowyerVoronoiVertex(groupRank, nucleiGroupArray, hyperSphereConstraint);

                //    }
                //}
                //else
                //{
                HyperSphereConstraint hyperSphereConstraint = new HyperSphereConstraint(this.ProblemDimensionality);
                v = new BowyerVoronoiVertex(groupRank, nucleiGroupArray, hyperSphereConstraint);
                hyperSphereConstraint.Calculate(nucleiGroupArray, ProblemDimensionality, groupRank + 1);

#warning this is very little optime!!!
                if (//nucleis.Except(nucleiGroupArray)
                    affectedNucleis.Except(nucleiGroupArray)
                    .All(nuc => !v.simplice.CircumsphereContains(nuc.Coordinates)))
                {
                    validSimplice = true;

                }
                else
                    v.Dispose();
                //}

                if (validSimplice)
                {
                    this.voronoiVertexes.Add(v);

                    //select those who share a face with the new voronoiVertex



                    //foreach (var s in stableNeighbours)
                    //{
                    //    foreach (var f in s.simplice.facets.Where(f => !f.FullyInitialized))
                    //    {
                    //        if (v.simplice.nucleis.All(n => f.nucleis.Contains(n)))
                    //        {
                    //            v.AddNeighbour(s);
                    //            s.AddNeighbour(v);
                    //        }
                    //    }
                    //}


                }
            }


            //all generated vertexes are neighbour
            IEnumerable<BowyerVoronoiVertex> generatedVertexes = voronoiVertexes.Skip(previousVoronoiVertexSize);

            IEnumerable<BowyerVoronoiVertex> createdInfiniteVoronoiVertexes = Enumerable.Empty<BowyerVoronoiVertex>();
           

            foreach (BowyerVoronoiVertex v in generatedVertexes)
            {
                foreach (var v2 in generatedVertexes)
                    if (v != v2)
                    {
#warning 3level loop ... this shouldn't be to optime
                        foreach (var externalFacet in v2.simplice.facets.Where(f => !f.FullyInitialized))
                        {
                            BowyerSimpliceFacet thisFacet = v.simplice.facets.SingleOrDefault(f => externalFacet.nucleis.All(n => f.nucleis.Contains(n)));
                            if (thisFacet != null)
                            {
                                externalFacet.External = v;
                                v.AddNeighbour(thisFacet);
                            }
                        }
                    }

                foreach (BowyerSimpliceFacet externalFacet in aloneOldFacets.Where(f => !f.FullyInitialized))
                {
                    BowyerSimpliceFacet thisFacet = v.simplice.facets.SingleOrDefault(f => externalFacet.nucleis.All(n => f.nucleis.Contains(n)));
                    if (thisFacet != null)
                    {
                        externalFacet.External = v;
                        v.AddNeighbour(thisFacet);
                    }
                }

                //this vertex need nucleisRank+1 neighbours
                if (v.simplice.facets.Count(f => f.FullyInitialized) <= groupRank)
                {
                    v.GenerateInfiniteNeighbousr();
                    //add the new created voronoi vertex neighbours
                    createdInfiniteVoronoiVertexes = createdInfiniteVoronoiVertexes.Union(v.simplice.facets.Where(f => f.External.Infinity).Select(f => (BowyerVoronoiVertex)f.External));
                }

#if DEBUG
                else if (v.simplice.facets.Any(f => !f.FullyInitialized))
                    throw new NotSupportedException("This case has not been contemplated");
#endif
            }

#if DEBUG
            if (aloneOldFacets.Any(f => !f.FullyInitialized))
                throw new NotSupportedException("Incoherence in the problem. All old facets should be filled.");
#endif

            voronoiVertexes.AddRange(createdInfiniteVoronoiVertexes);

            return generatedVertexes;
        }