public IEnumerable <ISimpliceFacet> GetFacetOrNull(INuclei n1, INuclei n2) { IEnumerable <BowyerSimplice> intersectionSimplices = ((BowyerNuclei)n1).simplices.Where(s => s.nucleis.Contains(n2)); var facetsA = intersectionSimplices.Select(s => s.Facets.SingleOrDefault(f => f.Nucleis.Contains(n2) && f.Nucleis.Contains(n1))) .Where(f => f != null); return(facetsA); }
internal void Calculate(IEnumerable <INuclei> Nucleis, int problemDimensionality, int nucleisCount) { Helpers.CalculateSimpliceCentroidFromFacets(Nucleis, nucleisCount - 1, ref Center); INuclei nuclei = Nucleis.First(); //now calculate the radious and store it. Vector v = new Vector(problemDimensionality); for (int i = 0; i < problemDimensionality; i++) { v[i] = Center[i] - nuclei.Coordinates[i]; } this.Radious = v.Norm(); }
/// <summary> /// Constraint is created as a bound between these two points. A line-bound in 2D case, a Plane in the 3D case and a hyperplane in ND case. /// It represents a single inequality that checks if a sample point belong to the positive or negative subspaces. /// </summary> /// </param> public DefaultVoronoiFacet(INuclei ownerNuclei, INuclei foreignNuclei) { this.Owner = ownerNuclei; this.External = foreignNuclei; double[] ownerPoint = Owner.Coordinates; double[] foreignPoint = External.Coordinates; double[] coefficents = new Vector(ownerPoint.Length + 1) ; coefficents[coefficents.Length - 1] = 0; //calculating coefficents except the independent coefficent for (int i = 0; i < ownerPoint.Length; i++) { coefficents[i] = ownerPoint[i] - foreignPoint[i]; //calculating the independent coefficent coefficents[coefficents.Length - 1] -= coefficents[i] * ((foreignPoint[i] + ownerPoint[i]) / 2f); } this.constraint = new HyperPlaneConstraint(coefficents); }
internal static int CalculatePointsRank(IEnumerable <INuclei> points) { INuclei first = points.First(); int pointsCount = first.Simplices.First().Rank + 2; Matrix vectors = new Matrix(pointsCount - 1, first.Coordinates.Length); IEnumerator <INuclei> currPoint = points.GetEnumerator(); currPoint.MoveNext(); for (int i = 0; i < vectors.RowCount && currPoint.MoveNext(); i++) { for (int j = 0; j < vectors.ColumnCount; j++) { vectors[i, j] = first.Coordinates[j] - currPoint.Current.Coordinates[j]; } } return(vectors.Rank()); }
/// <summary> /// Constraint is created as a bound between these two points. A line-bound in 2D case, a Plane in the 3D case and a hyperplane in ND case. /// It represents a single inequality that checks if a sample point belong to the positive or negative subspaces. /// </summary> /// </param> public DefaultVoronoiFacet(INuclei ownerNuclei, INuclei foreignNuclei) { this.Owner = ownerNuclei; this.External = foreignNuclei; double[] ownerPoint = Owner.Coordinates; double[] foreignPoint = External.Coordinates; double[] coefficents = new Vector(ownerPoint.Length + 1); coefficents[coefficents.Length - 1] = 0; //calculating coefficents except the independent coefficent for (int i = 0; i < ownerPoint.Length; i++) { coefficents[i] = ownerPoint[i] - foreignPoint[i]; //calculating the independent coefficent coefficents[coefficents.Length - 1] -= coefficents[i] * ((foreignPoint[i] + ownerPoint[i]) / 2f); } this.constraint = new HyperPlaneConstraint(coefficents); }
internal static Vector[] VectorsFromPoints(IEnumerable <INuclei> points, int pointsCount) { Vector[] vectors = new Vector[pointsCount - 1]; IEnumerator <INuclei> currentPoint = points.GetEnumerator(); currentPoint.MoveNext(); INuclei first = currentPoint.Current; int dimensionality = first.Coordinates.Length; for (int i = 0; currentPoint.MoveNext(); i++) { vectors[i] = new Vector(dimensionality); for (int j = 0; j < first.Coordinates.Length; j++) { vectors[i][j] = currentPoint.Current.Coordinates[j] - first.Coordinates[j]; } } return(vectors); }
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); } }
/// <summary> /// This function checks all requirements to build a tessellation, basically the number of independent nodes. /// If they are enough this method call to the buildTesellation method. /// </summary> private bool TryBuildTesellation(INuclei[] PointsToRemake, List<ISimplice> oldSimplices) { //check enough points if (PointsToRemake.Length >= dimensions + 1) { //Candidate simplices will contain some old simplices //and some new maked up simplices IEnumerable<IEnumerable<INuclei>> candidateSimplicesNucleis = Helpers.Combinations(PointsToRemake, dimensions + 1); //the only thing we need is a combinatory function about the exploited points //generateCombinatorySimplicies(0,0, dimensions + 1, PointsToRemake, null, oldSimplices, candidateSimplices); List<ISimplice> candidateSimplices = new List<ISimplice>(); foreach (var nucSet in candidateSimplicesNucleis) { ISimplice existingSimplice = oldSimplices.FirstOrDefault(s => nucSet.All(n => s.Nucleis.Contains(n))); if (existingSimplice != null) candidateSimplices.Add(existingSimplice); else { INuclei[] nucs = nucSet.ToArray(); if (Nuclei.AssertRank(nucs, dimensions)) candidateSimplices.Add(new Simplice(nucs)); } } //check enough independent points if (candidateSimplices.Any()) { BuildTesellationAndSetNeiborghood(candidateSimplices, PointsToRemake, oldSimplices); return true; } else return false; //not enough indepndent poitns to build a tessellation in this n-dimensional world } else return false; //not enough points to build a teselation in this n-dimensional world }
private void BuildTesellationAndSetNeiborghood(List<ISimplice> candidateSimplices, INuclei[] pointsToRemake, List<ISimplice> oldSimplices) { List<Simplice> newTesellation = new List<Simplice>(); foreach (Simplice s in candidateSimplices) { bool hyperSphereCoversPoint = false; foreach (var p in pointsToRemake.Except(s.Nucleis)) { if (s.CheckIsInsideCircumSphere(p.Coordinates)) { hyperSphereCoversPoint = true; break; } } if (!hyperSphereCoversPoint) { //if finally some new simplice existed previously //they have not been exploited so don't mark them as new (recreate them) //neither mark them to remove(oldSimplice) them because are stable and usefull simplices. if (oldSimplices.Contains(s)) oldSimplices.Remove(s); else newTesellation.Add(s); } } /*var oldSimplices = newTesellation.Select(s => s.Nucleis as IEnumerable<Nuclei>) .Aggregate((acc, ns) => acc.Union(ns)) .Distinct() .Select(n => n.simplices as IEnumerable<Simplice>) .Aggregate((acc, sim) => acc.Union(sim) ) .Distinct() .Except(newTesellation) .ToArray();*/ foreach (Simplice s in newTesellation) { foreach (Nuclei n in s.Nucleis) { //Deleting refactored nuclei neighbourg for each nuclei. //Assert that we do not remove any neighbour that is connected //thorugh another simplice that won't be removed foreach (Simplice os in oldSimplices.Where(x => x.Nucleis.Contains(n))) { n.simplices.Remove(os); //remove neighbour not contained in other neighbourgs var neighToRemove = os.Nucleis .Where(nuc => nuc != n && !n.simplices .Any(sim => sim.Nucleis.Contains(nuc))); foreach (var neighRm in neighToRemove) n.nucleiNeigbourgs.Remove(neighRm); } if (n.simplices.Contains(s)) throw new Exception(); n.simplices.Add(s); foreach (Nuclei newNeigbourg in s.Nucleis) if (newNeigbourg != n && !n.nucleiNeigbourgs.Contains(newNeigbourg)) { n.nucleiNeigbourgs.Add(newNeigbourg); } } s.RaiseRefreshNeighbours(); } foreach (Simplice s in oldSimplices) { s.RaiseRefreshNeighbours(); } }
private void CalculateConstraint() { //three possible cases, both finites, owner finite/external infnite and viceversa if (!Owner.Infinity && !external.Infinity) { double[] ownerPoint = Owner.Coordinates; double[] foreignPoint = external.Coordinates; double[] coefficents = new Vector(ownerPoint.Length + 1); coefficents[coefficents.Length - 1] = 0; //calculating coefficents except the independent coefficent for (int i = 0; i < ownerPoint.Length; i++) { coefficents[i] = ownerPoint[i] - foreignPoint[i]; //calculating the independent coefficent coefficents[coefficents.Length - 1] -= coefficents[i] * ((foreignPoint[i] + ownerPoint[i]) / 2f); } this.constraint = new HyperPlaneConstraint(coefficents); } else if (External.Infinity && Owner.Infinity) { INuclei[] n = External.Simplice.Nucleis.Intersect(Owner.Simplice.Nucleis).ToArray(); if (n.Length != 2) { throw new NotSupportedException(); } IVoronoiFacet vf = n[0].VoronoiHyperRegion.Facets.Single(f => f.External == n[1]); double[] coefficents = new Vector(Owner.Coordinates.Length + 1); for (int i = 0; i < Owner.Coordinates.Length; i++) { coefficents[i] = vf[i]; } this.constraint = new HyperPlaneConstraint(coefficents); } else if (External.Infinity) { if (Owner.Simplice.Nucleis.Length > 2) { double[] middlePoint = new double[Nucleis[0].Coordinates.Length]; Helpers.CalculateSimpliceCentroidFromFacets(this.Nucleis, this.Rank, ref middlePoint); Vector normal = new Vector(Nucleis[0].Coordinates.Length + 1); double independentTerm = 0; for (int i = 0; i < Nucleis[0].Coordinates.Length; i++) { normal[i] = Owner.Coordinates[i] - middlePoint[i]; independentTerm -= normal[i] * middlePoint[i]; } normal[normal.Length - 1] = independentTerm; this.constraint = new HyperPlaneConstraint(normal.ToArray()); } else { //only two nucleis...is this enough general for n-dimensions? //hope this is only the case base, where a voronoiVertex overlaps a voronoiFacet INuclei n = External.Simplice.Nucleis.Intersect(Owner.Simplice.Nucleis).Single(); Vector normal = new Vector(Nucleis[0].Coordinates.Length + 1); double independentTerm = 0; for (int i = 0; i < Nucleis[0].Coordinates.Length; i++) { normal[i] = Owner.Coordinates[i] - n.Coordinates[i]; independentTerm -= normal[i] * n.Coordinates[i]; } normal[normal.Length - 1] = independentTerm; this.constraint = new HyperPlaneConstraint(normal.ToArray()); } } else if (Owner.Infinity) { if (External.Simplice.Nucleis.Length > 2) { double[] middlePoint = new double[Nucleis[0].Coordinates.Length]; Helpers.CalculateSimpliceCentroidFromFacets(Nucleis, this.Rank, ref middlePoint); Vector normal = new Vector(Nucleis[0].Coordinates.Length + 1); double independentTerm = 0; for (int i = 0; i < Nucleis[0].Coordinates.Length; i++) { normal[i] = middlePoint[i] - External.Coordinates[i]; independentTerm -= normal[i] * middlePoint[i]; } normal[normal.Length - 1] = independentTerm; this.constraint = new HyperPlaneConstraint(normal.ToArray()); } else { //only two nucleis...is this enough general for n-dimensions? //hope this is only the case base, where a voronoiVertex overlaps a voronoiFacet INuclei n = External.Simplice.Nucleis.Intersect(Owner.Simplice.Nucleis).Single(); Vector normal = new Vector(Nucleis[0].Coordinates.Length + 1); double independentTerm = 0; for (int i = 0; i < Nucleis[0].Coordinates.Length; i++) { normal[i] = n.Coordinates[i] - External.Coordinates[i]; independentTerm -= normal[i] * n.Coordinates[i]; } normal[normal.Length - 1] = independentTerm; this.constraint = new HyperPlaneConstraint(normal.ToArray()); } } else //both infinities { throw new NotFiniteNumberException(); } }
/// <summary> /// This is a lazy calculation of the voronoi Vertex, its not calculated if it isn't required. /// </summary> internal static void CalculateSimpliceCentroidFromFacets(IEnumerable <INuclei> Nucleis, int simpliceDimensions, ref double[] vectorOut) { INuclei firstNuclei = Nucleis.First(); int problemDimensionality = Nucleis.First().Coordinates.Length; IVoronoiFacet[] voronoiFacets = firstNuclei.VoronoiHyperRegion.Facets.Where(f => Nucleis.Contains(f.External)).ToArray(); int Dof = problemDimensionality - simpliceDimensions; //we have facets.Length restrictions, and we have to create Dof new restrictions. if (simpliceDimensions == problemDimensionality) { CalculateSimpliceCentroid(Nucleis.Select(n => n.Coordinates), ref vectorOut); } else //we have to solve a facets.Length problem, to get the parameters of the problem. //ie: two facets, two ecuations. constraint with the current space formed by nucleiVectors with 2 parameters (unknowns) //this is a two ecuations/two unknowns problem. if (simpliceDimensions == 1) { IVoronoiFacet hpConstraint = voronoiFacets[0]; double tCoeff = 0; double independentTerm = hpConstraint[problemDimensionality]; Vector[] vectors = VectorsFromPoints(Nucleis, simpliceDimensions + 1); for (int i = 0; i < problemDimensionality; i++) { tCoeff += hpConstraint[i] * vectors[0][i]; independentTerm += hpConstraint[i] * firstNuclei.Coordinates[i]; } double t = (-independentTerm) / tCoeff; //solve the system for (int i = 0; i < problemDimensionality; i++) { vectorOut[i] = firstNuclei.Coordinates[i] + t * vectors[0][i]; } } else { //parameters matrix Matrix mA = new Matrix(voronoiFacets.Length, voronoiFacets.Length); Vector[] vectors = VectorsFromPoints(Nucleis, simpliceDimensions + 1); Matrix mb = new Matrix(voronoiFacets.Length, 1); //mounting parameters matrix for (int row = 0; row < voronoiFacets.Length; row++) { IVoronoiFacet hpConstraint = voronoiFacets[row]; double independentTerm = hpConstraint[problemDimensionality]; for (int col = 0; col < voronoiFacets.Length; col++) { double tCoeff_col = 0; for (int j = 0; j < problemDimensionality; j++) { tCoeff_col += hpConstraint[j] * vectors[col][j]; independentTerm += hpConstraint[j] * firstNuclei.Coordinates[j]; } mA[row, col] = tCoeff_col; } mb[row, 0] = independentTerm; } //solving parameters matrix Matrix parametersRes = mA.Solve(mb); for (int i = 0; i < vectorOut.Length; i++) { double increment = 0; for (int j = 0; j < voronoiFacets.Length; j++) { increment = parametersRes[j, 0] * vectors[j][i]; } vectorOut[i] = firstNuclei.Coordinates[i] + increment; } } }
/// <summary> /// The number of nodes must be n+1 dimensional where n is the dimensions of the problem /// </summary> /// <param name="nucleis"></param> public Simplice(INuclei[] nucleis) { this.Nucleis = nucleis; }
internal static bool AssertRank(INuclei[] nucleis, int desiredRank) { if (nucleis.Length < desiredRank) return false; int workingSpaceDim=nucleis.First().Coordinates.Length; Matrix m = new Matrix(nucleis.Length,workingSpaceDim ); for(int i=0;i<nucleis.Length;i++) { for(int j=0;j<workingSpaceDim;j++) m[i,j]=nucleis[i].Coordinates[j]; } return m.Rank()==desiredRank; }
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 IEnumerable<ISimpliceFacet> GetFacetOrNull(INuclei n1, INuclei n2) { IEnumerable<BowyerSimplice> intersectionSimplices=((BowyerNuclei)n1).simplices.Where(s => s.nucleis.Contains(n2)); var facetsA=intersectionSimplices.Select(s => s.Facets.SingleOrDefault(f => f.Nucleis.Contains(n2) && f.Nucleis.Contains(n1))) .Where(f=>f!=null); return facetsA; }