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 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; } }