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; }
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; }
/*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; }
/// <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); }