Пример #1
0
 internal Nuclei(double[] coordinates, HyperRegion thisRegion, object data)
 {
     this.coordinates        = coordinates;
     this.VoronoiHyperRegion = thisRegion;
     this.simplices          = new List <Simplice>();
     this.nucleiNeigbourgs   = new List <INuclei>();
     this.Data = data;
 }
Пример #2
0
 internal Nuclei(double[] coordinates,HyperRegion thisRegion,object data)
 {
     this.coordinates = coordinates;
     this.VoronoiHyperRegion = thisRegion;
     this.simplices = new List<Simplice>();
     this.nucleiNeigbourgs = new List<INuclei>();
     this.Data = data;
 }
Пример #3
0
        /*private void generateCombinatorySimplicies(int auxStartIndex, int workingIndex, int combinationSize, Nuclei[] originalBag, Nuclei[] CurrentNucleiCombination, IEnumerable<Simplice> containersSimplices, List<Simplice> resultingSimplices)
         * {
         *
         *  //first time
         *  if (CurrentNucleiCombination == null)
         *      //to get a vertex we need n constraints where n==dimensionality of the problem
         *      CurrentNucleiCombination = new Nuclei[combinationSize];
         *
         *
         *  //recursive case
         *  if (workingIndex<CurrentNucleiCombination.Length)
         *  {
         *      //generateCombinatorySimplicies(auxStartIndex + 1, combinationSize - 1, originalBag, CurrentNucleiCombination, containersSimplices, resultingSimplices);
         *      for (int i = auxStartIndex; i < originalBag.Length && originalBag.Length- i >= combinationSize; i++)
         *      {
         *          CurrentNucleiCombination[workingIndex] = originalBag[i];
         *          generateCombinatorySimplicies(i+1,workingIndex+1,combinationSize - 1, originalBag, CurrentNucleiCombination, containersSimplices, resultingSimplices);
         *      }
         *  }
         *
         *  //base case
         *  else
         *  {
         *      var alreadyExistingSimplice = containersSimplices.SingleOrDefault(s => s.Nucleis.All(n => CurrentNucleiCombination.Contains(n)));
         *
         *      //trying to reuse existing simplices that will be removed
         *      if (alreadyExistingSimplice != null)
         *      {
         *          resultingSimplices.Add(alreadyExistingSimplice);
         *          Debug.Print("Simplice saved: {0}", alreadyExistingSimplice);
         *      }
         *      else
         *          //creating a very new simplice
         *          resultingSimplices.Add(new Simplice(CurrentNucleiCombination.ToArray()));
         *  }
         * }*/


        /// <summary>
        /// Look up the region that match point. It uses the Gradient Descendent Method.
        /// </summary>
        /// <param name="point">
        /// point that will be checked
        /// A <see cref="System.Double[]"/>
        /// </param>
        /// <returns>
        /// Region that contains point.
        /// A <see cref="Region"/>
        /// </returns>
        public IVoronoiRegion GetMatchingRegion(double[] point)
        {
            if (point == null || point.Length != dimensions)
            {
                throw new ArgumentException("point added null or has invalid dimensionality");
            }

            /*This will be a very first approach as a not very efficent algorithm */
            if (!regions.Any())
            {
                return(null);
            }
            else if (regions.Count() == 1)
            {
                return(regions.Single());
            }
            else
            {
                /*candidate region */
                HyperRegion r = (HyperRegion)regions.First();

                bool matchAllConstraints = false;
                while (!matchAllConstraints)
                {
                    matchAllConstraints = true;
                    foreach (var constraintInfo in r.lazyConstraintsMap)
                    {
                        var constraint    = constraintInfo.Value;
                        var foreingRegion = constraintInfo.Key;

                        if (!constraint.semiHyperSpaceMatch(point))
                        {
                            r = (HyperRegion)foreingRegion;
                            matchAllConstraints = false;
                            break;
                        }
                    }
                }

                return(r);
            }
        }
        /// <summary>
        /// Adds a new point to the diagram and returns the generated region.
        /// </summary>
        /// <param name="newPoint">
        /// point coordinates. Dimensions must match.
        /// A <see cref="System.Double[]"/>
        /// </param>
        /// <returns>
        /// generated region that represent the set of pooints that has newPoint as the nearest neigbourgh.
        /// A <see cref="Region"/>
        /// </returns>
        public IVoronoiRegion AddNewPoint(object data, double[] newPoint)
        {
            if (newPoint == null || newPoint.Length != dimensions)
                throw new ArgumentException("point added null or has invalid dimensionality");

            HyperRegion containerRegion = (HyperRegion)this.GetMatchingRegion(newPoint);
            HyperRegion newRegion = new HyperRegion(newPoint, data);
            this.regions.Add(newRegion);

            //the very first one region
            if (containerRegion == null)
            {
                ((Nuclei)newRegion.Nuclei).BelongConvexHull = true;
            }
            //the standard case
            else
            {
                //Get all the simplices of this region and neighbourgs
                //they are candidates to contains this new point
                //after this checks and select the simplicitis of these regions
                //that contains the new point
                //this simplicitis are selected, and latter will be removed since
                //their tesellation will be refactored
                List<ISimplice> affectedSimplicies = containerRegion.NeighbourgRegions
                                        .Union(new IVoronoiRegion[] { containerRegion })
                                                .SelectMany(r => r.Nuclei.Simplices as IEnumerable<ISimplice>)
                                                .Distinct()
                                                .Where(s => ((Simplice)s).CheckIsInsideCircumSphere(newPoint))
                                                .ToList();

                //standard case
                if (affectedSimplicies.Any())
                {

                    //we have to regenerate a chunk of the delunai map. All the points to remake belongs
                    //to a simplice that match in his hyperSphere the new point.
                    INuclei[] PointsToRemake = affectedSimplicies.Select(s => s.Nucleis as IEnumerable<INuclei>)
                                                         .Aggregate((acc, nucs) => acc.Union(nucs))
                                                         .Union(new INuclei[] { newRegion.Nuclei })
                                                         .Distinct()
                                                         .ToArray();

                    if (!TryBuildTesellation(PointsToRemake, affectedSimplicies))
                    {
                        //theoretically if it's inside of a hypersphere, at least a set of points are rank==dimensions
                        //so this never should happen
                        throw new NotImplementedException("Unexpected Derivation");
                    }
                }
                //THIRD NOT USUAL CASE:
                //
                //It should be    1- an external point of the delunai convex tesellation.
                //                2- a new point in the beginnings and the number of points are not enough to build
                //                   a simplice
                //                      2.1 Enough point to build the very first simplice but they have not enough rank
                //                     rank(existingpoints)<dims
                //                      2.2 Otherwise everyvody is neighbour and bound

                else
                {
                    //CASE 1 - External point
                    //Then try to build a tesellation with bruteForce. This point, is owner region and all his the neighbourg.
                    /*var affectedPoints = containerRegion.NeighbourgRegions
                                        .Union(new HyperRegion[] { containerRegion, newRegion })
                                        .Select(r => r.Nuclei);*/

                    var affectedPoints=this.Simplices.SelectMany(s => s.Facets.Where(f => f.IsConvexHullFacet>0))
                                        .SelectMany(f => f.Vertexes)
                                        .Union(containerRegion.NeighbourgRegions.Select(neigh=>neigh.Nuclei))
                                        .Union(new INuclei[]{containerRegion.Nuclei, newRegion.Nuclei})
                                        .Distinct();

                    INuclei[] pointsToRemake;

                        //select all the simplices related with all nucleis of the current hyperregion
                        affectedSimplicies = affectedPoints
                                                    .Select(n => n.Simplices as IEnumerable<ISimplice>)
                                                    .Aggregate((acc, simps) => acc.Union(simps))
                                                    .Distinct()
                                                    .ToList();
                        pointsToRemake = affectedSimplicies.SelectMany(s => s.Nucleis)
                                                .Union(affectedPoints).Distinct().ToArray();

                    bool achievedTesellation = TryBuildTesellation(pointsToRemake, affectedSimplicies);
                    if (achievedTesellation)
                        Debug.Print("CASE STRANGE 1");

                //THEN CASE 2 - Beginigs and noth enough to build a simplice
                    else
                    {
                        Debug.Print("CASE STRANGE 2");
                        //this case is only usefull for firsts points when no simplicie exists
                        //and all points can't build a simplicie

                        Debug.Print("We don't like this region. Maybe super-computer requirements?");

                        foreach (var n in containerRegion.NeighbourgRegions.Select(r => r.Nuclei))
                        {
                            if (!Nuclei.AssertCoLinear(new INuclei[] { n, newRegion.Nuclei, containerRegion.Nuclei }))
                            {
                                ((Nuclei)newRegion.Nuclei).nucleiNeigbourgs.Add(n);
                                ((Nuclei)n).nucleiNeigbourgs.Add(newRegion.Nuclei);
                            }
                        }

                        //of course the new point is neigbhour of the region where it fell
                        ((Nuclei)containerRegion.Nuclei).nucleiNeigbourgs.Add(newRegion.Nuclei);
                        ((Nuclei)newRegion.Nuclei).nucleiNeigbourgs.Add(containerRegion.Nuclei);
                        ((Nuclei)newRegion.Nuclei).BelongConvexHull = true;
                    }

                }
            }
            return newRegion;
        }
Пример #5
0
        /// <summary>
        /// Adds a new point to the diagram and returns the generated region.
        /// </summary>
        /// <param name="newPoint">
        /// point coordinates. Dimensions must match.
        /// A <see cref="System.Double[]"/>
        /// </param>
        /// <returns>
        /// generated region that represent the set of pooints that has newPoint as the nearest neigbourgh.
        /// A <see cref="Region"/>
        /// </returns>
        public IVoronoiRegion AddNewPoint(object data, double[] newPoint)
        {
            if (newPoint == null || newPoint.Length != dimensions)
            {
                throw new ArgumentException("point added null or has invalid dimensionality");
            }

            HyperRegion containerRegion = (HyperRegion)this.GetMatchingRegion(newPoint);
            HyperRegion newRegion       = new HyperRegion(newPoint, data);

            this.regions.Add(newRegion);

            //the very first one region
            if (containerRegion == null)
            {
                ((Nuclei)newRegion.Nuclei).BelongConvexHull = true;
            }
            //the standard case
            else
            {
                //Get all the simplices of this region and neighbourgs
                //they are candidates to contains this new point
                //after this checks and select the simplicitis of these regions
                //that contains the new point
                //this simplicitis are selected, and latter will be removed since
                //their tesellation will be refactored
                List <ISimplice> affectedSimplicies = containerRegion.NeighbourgRegions
                                                      .Union(new IVoronoiRegion[] { containerRegion })
                                                      .SelectMany(r => r.Nuclei.Simplices as IEnumerable <ISimplice>)
                                                      .Distinct()
                                                      .Where(s => ((Simplice)s).CheckIsInsideCircumSphere(newPoint))
                                                      .ToList();



                //standard case
                if (affectedSimplicies.Any())
                {
                    //we have to regenerate a chunk of the delunai map. All the points to remake belongs
                    //to a simplice that match in his hyperSphere the new point.
                    INuclei[] PointsToRemake = affectedSimplicies.Select(s => s.Nucleis as IEnumerable <INuclei>)
                                               .Aggregate((acc, nucs) => acc.Union(nucs))
                                               .Union(new INuclei[] { newRegion.Nuclei })
                                               .Distinct()
                                               .ToArray();

                    if (!TryBuildTesellation(PointsToRemake, affectedSimplicies))
                    {
                        //theoretically if it's inside of a hypersphere, at least a set of points are rank==dimensions
                        //so this never should happen
                        throw new NotImplementedException("Unexpected Derivation");
                    }
                }
                //THIRD NOT USUAL CASE:
                //
                //It should be    1- an external point of the delunai convex tesellation.
                //                2- a new point in the beginnings and the number of points are not enough to build
                //                   a simplice
                //                      2.1 Enough point to build the very first simplice but they have not enough rank
                //                     rank(existingpoints)<dims
                //                      2.2 Otherwise everyvody is neighbour and bound

                else
                {
                    //CASE 1 - External point
                    //Then try to build a tesellation with bruteForce. This point, is owner region and all his the neighbourg.

                    /*var affectedPoints = containerRegion.NeighbourgRegions
                     *                  .Union(new HyperRegion[] { containerRegion, newRegion })
                     *                  .Select(r => r.Nuclei);*/

                    var affectedPoints = this.Simplices.SelectMany(s => s.Facets.Where(f => f.IsConvexHullFacet > 0))
                                         .SelectMany(f => f.Vertexes)
                                         .Union(containerRegion.NeighbourgRegions.Select(neigh => neigh.Nuclei))
                                         .Union(new INuclei[] { containerRegion.Nuclei, newRegion.Nuclei })
                                         .Distinct();



                    INuclei[] pointsToRemake;


                    //select all the simplices related with all nucleis of the current hyperregion
                    affectedSimplicies = affectedPoints
                                         .Select(n => n.Simplices as IEnumerable <ISimplice>)
                                         .Aggregate((acc, simps) => acc.Union(simps))
                                         .Distinct()
                                         .ToList();
                    pointsToRemake = affectedSimplicies.SelectMany(s => s.Nucleis)
                                     .Union(affectedPoints).Distinct().ToArray();



                    bool achievedTesellation = TryBuildTesellation(pointsToRemake, affectedSimplicies);
                    if (achievedTesellation)
                    {
                        Debug.Print("CASE STRANGE 1");
                    }

                    //THEN CASE 2 - Beginigs and noth enough to build a simplice
                    else
                    {
                        Debug.Print("CASE STRANGE 2");
                        //this case is only usefull for firsts points when no simplicie exists
                        //and all points can't build a simplicie

                        Debug.Print("We don't like this region. Maybe super-computer requirements?");

                        foreach (var n in containerRegion.NeighbourgRegions.Select(r => r.Nuclei))
                        {
                            if (!Nuclei.AssertCoLinear(new INuclei[] { n, newRegion.Nuclei, containerRegion.Nuclei }))
                            {
                                ((Nuclei)newRegion.Nuclei).nucleiNeigbourgs.Add(n);
                                ((Nuclei)n).nucleiNeigbourgs.Add(newRegion.Nuclei);
                            }
                        }

                        //of course the new point is neigbhour of the region where it fell
                        ((Nuclei)containerRegion.Nuclei).nucleiNeigbourgs.Add(newRegion.Nuclei);
                        ((Nuclei)newRegion.Nuclei).nucleiNeigbourgs.Add(containerRegion.Nuclei);
                        ((Nuclei)newRegion.Nuclei).BelongConvexHull = true;
                    }
                }
            }
            return(newRegion);
        }