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);
            }
        }
Exemplo n.º 2
0
        public IVoronoiRegion AddNewPoint(object data, double[] newPoint)
        {
            if (newPoint == null || newPoint.Length != ProblemDimensionality)
            {
                throw new ArgumentException("point added null or has invalid dimensionality");
            }

            BowyerNuclei newNuclei = new BowyerNuclei(newPoint);

            newNuclei.Data = data;

            //SPECIAL CASE FOR FIRST ADD
            if (!voronoiVertexes.Any())
            {
                //no voronoiVertexes
                //no simplices
                //no regions

                BowyerNuclei[] nucleis = new BowyerNuclei[1];
                newNuclei      = nucleis[0] = new BowyerNuclei(newPoint);
                newNuclei.Data = data;

                //create a VoronoiVertex in the infinite
                var voronoiVertex = new BowyerVoronoiVertex(0, nucleis, new HyperSphereConstraint(newNuclei.Coordinates, double.PositiveInfinity));

                this.voronoiVertexes.Add(voronoiVertex);
                this.nucleis.Add(newNuclei);

                //create a not formed Simplice
                return(voronoiVertexes.First().Simplice.Nucleis.First().VoronoiHyperRegion);
            }
            else
            {
                //--------------- SITUATION ANALYSIS - READ ONLY--------------

#warning optimizable: not variable list without cast, external auxiliar attribute
                List <BowyerVoronoiVertex> affectedVertexes = new List <BowyerVoronoiVertex>();
#warning optimizable: not variable list without cast, external auxiliar attribute
                List <BowyerNuclei> affectedNucleis = new List <BowyerNuclei>();


                IEnumerable <INuclei> newpointSet = new INuclei[] { newNuclei };

#warning optimizable: cant be this an auxiliar attribute?
                var secondaryAffecteVertexes = new List <BowyerSimpliceFacet>();


                if (nucleisRank < ProblemDimensionality && Helpers.CalculatePointsRank(Simplices.First().Nucleis.Union(newpointSet)) > nucleisRank)
                {
                    affectedVertexes = this.voronoiVertexes;
                    nucleisRank++;
                    foreach (var v in affectedVertexes)
                    {
                        v.IsTrash = true;
                    }

#warning optimize, eliminate the cast and create a nuclei List
                    affectedNucleis.AddRange(this.Nucleis.Cast <BowyerNuclei>());
                }
                else
                {
                    IVoronoiRegion r = GetMatchingRegion(newPoint);
                    // and use r.Vertexes
                    foreach (BowyerVoronoiVertex v in r.Vertexes)
                    {
                        if (v.Simplice.CircumsphereContains(newPoint))
                        {
                            if (!affectedVertexes.Contains(v))
                            {
                                affectedVertexes.Add(v);
                                v.IsTrash = true;
                                foreach (var affectedNuclei in v.simplice.nucleis)
                                {
                                    if (!affectedNucleis.Contains(affectedNuclei))
                                    {
                                        affectedNucleis.Add(affectedNuclei);
                                    }
                                }
                            }

                            foreach (var vaffected in v.simplice.facets.Where(f => f.External.Infinity).Select(f => (BowyerVoronoiVertex)f.External))
                            {
                                if (!affectedVertexes.Contains(vaffected))
                                {
                                    affectedVertexes.Add(vaffected);
                                    vaffected.IsTrash = true;
                                }
                            }

                            foreach (var otherAffectedFace in v.simplice.facets.Where(f => !f.External.Infinity))
                            {
                                if (!affectedVertexes.Contains((BowyerVoronoiVertex)otherAffectedFace.External) && !secondaryAffecteVertexes.Contains(otherAffectedFace))
                                {
                                    secondaryAffecteVertexes.Add(otherAffectedFace);
                                }
                            }


                            //add also all the infinite vertexes if it or neighbours who contains it
                            //foreach (var vneigh2 in v.simplice.facets
                            //                                      .Where(f => !affectedVertexes.Contains((BowyerVoronoiVertex)f.External)
                            //                                                  && (f.External.Infinity
                            //                                                     || f.External.Simplice.CircumsphereContains(newPoint)))
                            //                                      .Select(f => (BowyerVoronoiVertex)f.External))
                            //{
                            //    vneigh2.IsTrash = true;
                            //    affectedVertexes.Add(vneigh2);

                            //}
                        }
                    }
                }



                //if (!affectedVertexes.Any())
                //{
                //    //if no normal simplices contains the new point
                //    //we will to try it in infinite vertexs of this region
                //    foreach (BowyerVoronoiVertex v in r.Vertexes.Where(v => v.Infinity))
                //        if (v.Simplice.CircumsphereContains(newPoint))
                //        {
                //            affectedVertexes.Add(v);
                //            v.IsTrash = true;
                //            affectedNucleis.AddRange(v.simplice.nucleis);

                //            //add to affected vertexes also the only neighbour vertex of
                //            //the current infinite vertex
                //            BowyerVoronoiVertex vnormal = (BowyerVoronoiVertex)v.simplice.facets.Single().External;
                //            secondaryAffecteVertexes.Add(vnormal);

                //            //vnormal.IsTrash = true;
                //            //affectedVertexes.Add(vnormal);
                //            ////add also all the infinite vertexes if it or neighbours who contains it
                //            //foreach (var vneigh2 in vnormal.simplice.facets.Select(f => (BowyerVoronoiVertex)f.External)
                //            //                                               .Where(v2 => v2 != v && !affectedVertexes.Contains(v2)
                //            //                                                   && (v2.Infinity || v2.simplice.CircumsphereContains(newPoint))))
                //            //{
                //            //    vneigh2.IsTrash = true;
                //            //    affectedVertexes.Add(vneigh2);
                //            //}

                //      }
                //  }

                // }

#if DEBUG
                Debug.Print(string.Format("{0} ||| adding new point. Affected vertexes: {1}. Secondary Affected vertexes: {2}", this.ToString(), affectedVertexes.Count, secondaryAffecteVertexes.Count));

                if (!affectedVertexes.Any())
                {
                    throw new ArgumentException("this case is not possible and has not been contemplated");
                }

                if (affectedVertexes.Distinct().Count() != affectedVertexes.Count)
                {
                    throw new ArgumentException("Incoherence in the algorithm");
                }

                if (affectedNucleis.Distinct().Count() != affectedNucleis.Count)
                {
                    throw new ArgumentException("Incoherence in the algorithm");
                }

                if (secondaryAffecteVertexes.Distinct().Count() != secondaryAffecteVertexes.Count)
                {
                    throw new ArgumentException("Incoherence in the algorithm");
                }
#endif


                //if any candidate vertex sismplice has the maxium dimensionality, the postgenerated tesellation will also have this maxium dimensionality

                //if (affectedVertexes.First().Simplice.Dimensionality == ProblemDimensionality)
                //    nucleisRank = ProblemDimensionality;
                //else
                //    nucleisRank = Helpers.CalculatePointsRank(affectedNucleisArray);



                //--------------------- CLEARING EXISTING DATA --------------------------------------

                foreach (var f in secondaryAffecteVertexes)
                {
                    ((BowyerVoronoiVertex)f.Owner).RemoveNeighbour(f);
                }


                //Removing affected voronoi vertexes
                //Removing affected voronoi facets in nucleis
                foreach (var v in affectedVertexes)
                {
                    v.Dispose();
                }


                //Removing affected simplices
                voronoiVertexes.RemoveAll(v => v.IsTrash);

#if DEBUG
                if (secondaryAffecteVertexes.Any(f => f.FullyInitialized))
                {
                    throw new NotSupportedException("Incoherence in the problem");
                }
#endif
                affectedNucleis.Add(newNuclei);

                //--------------------- BUILDING NEW MESH --------------------------------------
                //build tesellation and check some neighbourhood with secondary
                var generatedVertexes = BuildTesellation(affectedNucleis, secondaryAffecteVertexes, nucleisRank);

                this.nucleis.Add(newNuclei);
                return(newNuclei.VoronoiHyperRegion);
            }
        }
 public BowyerVoronoiVertex(int dimensionality, BowyerNuclei[] nucleis, HyperSphereConstraint hyperSphereConstraint)
 {
     simplice = new BowyerSimplice(hyperSphereConstraint, dimensionality, this, nucleis);
 }
        public IVoronoiRegion AddNewPoint(object data, double[] newPoint)
        {
            if (newPoint == null || newPoint.Length != ProblemDimensionality)
                throw new ArgumentException("point added null or has invalid dimensionality");

            BowyerNuclei newNuclei = new BowyerNuclei(newPoint);
            newNuclei.Data = data;

            //SPECIAL CASE FOR FIRST ADD
            if (!voronoiVertexes.Any())
            {
                //no voronoiVertexes
                //no simplices
                //no regions

                BowyerNuclei[] nucleis = new BowyerNuclei[1];
                newNuclei = nucleis[0] = new BowyerNuclei(newPoint);
                newNuclei.Data = data;

                //create a VoronoiVertex in the infinite
                var voronoiVertex = new BowyerVoronoiVertex(0, nucleis, new HyperSphereConstraint(newNuclei.Coordinates, double.PositiveInfinity));

                this.voronoiVertexes.Add(voronoiVertex);
                this.nucleis.Add(newNuclei);

                //create a not formed Simplice
                return voronoiVertexes.First().Simplice.Nucleis.First().VoronoiHyperRegion;
            }
            else
            {

                //--------------- SITUATION ANALYSIS - READ ONLY--------------

#warning optimizable: not variable list without cast, external auxiliar attribute
                List<BowyerVoronoiVertex> affectedVertexes = new List<BowyerVoronoiVertex>();
#warning optimizable: not variable list without cast, external auxiliar attribute
                List<BowyerNuclei> affectedNucleis = new List<BowyerNuclei>();


                IEnumerable<INuclei> newpointSet = new INuclei[] { newNuclei };

#warning optimizable: cant be this an auxiliar attribute?
                var secondaryAffecteVertexes = new List<BowyerSimpliceFacet>();


                if (nucleisRank < ProblemDimensionality && Helpers.CalculatePointsRank(Simplices.First().Nucleis.Union(newpointSet)) > nucleisRank)
                {
                    affectedVertexes = this.voronoiVertexes;
                    nucleisRank++;
                    foreach (var v in affectedVertexes)
                        v.IsTrash = true;

#warning optimize, eliminate the cast and create a nuclei List
                    affectedNucleis.AddRange(this.Nucleis.Cast<BowyerNuclei>());
                }
                else
                {
                    IVoronoiRegion r = GetMatchingRegion(newPoint);
                    // and use r.Vertexes
                    foreach (BowyerVoronoiVertex v in r.Vertexes)
                        if (v.Simplice.CircumsphereContains(newPoint))
                        {
                            if (!affectedVertexes.Contains(v))
                            {
                                affectedVertexes.Add(v);
                                v.IsTrash = true;
                                foreach (var affectedNuclei in v.simplice.nucleis)
                                    if (!affectedNucleis.Contains(affectedNuclei))
                                        affectedNucleis.Add(affectedNuclei);
                            }

                            foreach (var vaffected in v.simplice.facets.Where(f => f.External.Infinity).Select(f => (BowyerVoronoiVertex)f.External))
                            {
                                if (!affectedVertexes.Contains(vaffected))
                                {
                                    affectedVertexes.Add(vaffected);
                                    vaffected.IsTrash = true;
                                }

                            }

                            foreach (var otherAffectedFace in v.simplice.facets.Where(f => !f.External.Infinity))
                            {
                                if (!affectedVertexes.Contains((BowyerVoronoiVertex)otherAffectedFace.External) && !secondaryAffecteVertexes.Contains(otherAffectedFace))
                                    secondaryAffecteVertexes.Add(otherAffectedFace);
                            }


                            //add also all the infinite vertexes if it or neighbours who contains it
                            //foreach (var vneigh2 in v.simplice.facets
                            //                                      .Where(f => !affectedVertexes.Contains((BowyerVoronoiVertex)f.External)
                            //                                                  && (f.External.Infinity
                            //                                                     || f.External.Simplice.CircumsphereContains(newPoint)))
                            //                                      .Select(f => (BowyerVoronoiVertex)f.External))
                            //{
                            //    vneigh2.IsTrash = true;
                            //    affectedVertexes.Add(vneigh2);

                            //}
                        }
                }



                //if (!affectedVertexes.Any())
                //{
                //    //if no normal simplices contains the new point
                //    //we will to try it in infinite vertexs of this region
                //    foreach (BowyerVoronoiVertex v in r.Vertexes.Where(v => v.Infinity))
                //        if (v.Simplice.CircumsphereContains(newPoint))
                //        {
                //            affectedVertexes.Add(v);
                //            v.IsTrash = true;
                //            affectedNucleis.AddRange(v.simplice.nucleis);

                //            //add to affected vertexes also the only neighbour vertex of
                //            //the current infinite vertex
                //            BowyerVoronoiVertex vnormal = (BowyerVoronoiVertex)v.simplice.facets.Single().External;
                //            secondaryAffecteVertexes.Add(vnormal);

                //            //vnormal.IsTrash = true;
                //            //affectedVertexes.Add(vnormal);
                //            ////add also all the infinite vertexes if it or neighbours who contains it
                //            //foreach (var vneigh2 in vnormal.simplice.facets.Select(f => (BowyerVoronoiVertex)f.External)
                //            //                                               .Where(v2 => v2 != v && !affectedVertexes.Contains(v2)
                //            //                                                   && (v2.Infinity || v2.simplice.CircumsphereContains(newPoint))))
                //            //{
                //            //    vneigh2.IsTrash = true;
                //            //    affectedVertexes.Add(vneigh2);
                //            //}

                //      }
                //  }

                // }

#if DEBUG
                Debug.Print(string.Format("{0} ||| adding new point. Affected vertexes: {1}. Secondary Affected vertexes: {2}", this.ToString(), affectedVertexes.Count, secondaryAffecteVertexes.Count));

                if (!affectedVertexes.Any())
                    throw new ArgumentException("this case is not possible and has not been contemplated");

                if (affectedVertexes.Distinct().Count() != affectedVertexes.Count)
                    throw new ArgumentException("Incoherence in the algorithm");

                if (affectedNucleis.Distinct().Count() != affectedNucleis.Count)
                    throw new ArgumentException("Incoherence in the algorithm");

                if (secondaryAffecteVertexes.Distinct().Count() != secondaryAffecteVertexes.Count)
                    throw new ArgumentException("Incoherence in the algorithm");

#endif


                //if any candidate vertex sismplice has the maxium dimensionality, the postgenerated tesellation will also have this maxium dimensionality

                //if (affectedVertexes.First().Simplice.Dimensionality == ProblemDimensionality)
                //    nucleisRank = ProblemDimensionality;
                //else
                //    nucleisRank = Helpers.CalculatePointsRank(affectedNucleisArray);



                //--------------------- CLEARING EXISTING DATA -------------------------------------- 

                foreach (var f in secondaryAffecteVertexes)
                    ((BowyerVoronoiVertex)f.Owner).RemoveNeighbour(f);


                //Removing affected voronoi vertexes
                //Removing affected voronoi facets in nucleis
                foreach (var v in affectedVertexes)
                    v.Dispose();


                //Removing affected simplices
                voronoiVertexes.RemoveAll(v => v.IsTrash);

#if DEBUG
                if (secondaryAffecteVertexes.Any(f => f.FullyInitialized))
                    throw new NotSupportedException("Incoherence in the problem");
#endif
                affectedNucleis.Add(newNuclei);

                //--------------------- BUILDING NEW MESH -------------------------------------- 
                //build tesellation and check some neighbourhood with secondary
                var generatedVertexes = BuildTesellation(affectedNucleis, secondaryAffecteVertexes, nucleisRank);

                this.nucleis.Add(newNuclei);
                return newNuclei.VoronoiHyperRegion;

            }
        }