/// <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 != ProblemDimensionality) { throw new ArgumentException("point added null or has invalid dimensionality"); } /*This will be a very first approach as a not very efficent algorithm */ if (!VoronoiRegions.Any()) { return(null); } else { /*candidate region */ IVoronoiRegion r = VoronoiRegions.First(); bool matchAllConstraints = false; while (!matchAllConstraints) { matchAllConstraints = true; foreach (var regionFacet in r.Facets) { if (!regionFacet.semiHyperSpaceMatch(point)) { r = regionFacet.External.VoronoiHyperRegion; matchAllConstraints = false; break; } } } return(r); } }
public void BasicVoronoiAddOne_RegionBasicFunctionality() { IVoronoiDelunayGraph gdv = createNewVoronoiDiagram(4); IVoronoiRegion reg = gdv.AddNewPoint(new double[] { 10, 3, 45, 2 }); Assert.IsTrue(reg.ContainsPoint(new double[] { 1, 2, 3, 4 })); CheckGeneralDiagramCoherence(gdv); }
public void BasicVoronoiAddTwo_BasicFunctionality() { IVoronoiDelunayGraph gdv = createNewVoronoiDiagram(4); IVoronoiRegion reg = gdv.AddNewPoint(new double[] { 10, 3, 45, 2 }); IVoronoiRegion regB = gdv.AddNewPoint(new double[] { 10, 50, 45, 50 }); double[] testingPoint = new double[] { 10, 4, 43, 0 }; Assert.IsTrue(reg.ContainsPoint(testingPoint)); Assert.IsFalse(regB.ContainsPoint(testingPoint)); Assert.AreEqual(gdv.GetMatchingRegion(testingPoint), reg); CheckGeneralDiagramCoherence(gdv); }
public void BasicVoronoiAddOne() { IVoronoiDelunayGraph gdv = createNewVoronoiDiagram(4); IVoronoiRegion reg = gdv.AddNewPoint(new double[] { 10, 3, 45, 2 }); Assert.AreEqual(gdv.VoronoiRegions.Count(), 1); Assert.AreEqual(gdv.VoronoiRegions.Single(), reg); Assert.IsFalse(reg.NeighbourgRegions.Any()); Assert.IsTrue(reg.Nuclei.BelongConvexHull); CheckGeneralDiagramCoherence(gdv); }
public void BasicVoronoiAddThree() { IVoronoiDelunayGraph gdv = createNewVoronoiDiagram(4); IVoronoiRegion reg = gdv.AddNewPoint(new double[] { 10, 3, 45, 2 }); IVoronoiRegion regB = gdv.AddNewPoint(new double[] { 10, 50, 45, 50 }); IVoronoiRegion regC = gdv.AddNewPoint(new double[] { 10, 50, -45, -1 }); Assert.AreEqual(gdv.VoronoiRegions.Count(), 3); Assert.AreEqual(gdv.Simplices.Count(s => s.Rank == 2), 1); Assert.IsTrue(gdv.Simplices.Single().Facets.All(f => f.semiHyperSpaceMatch(gdv.Simplices.Single().VoronoiVertex.Coordinates))); Assert.IsTrue(!gdv.Simplices.Any(s => s.Rank > 2)); Assert.IsTrue(gdv.VoronoiRegions.Contains(reg)); Assert.IsTrue(gdv.VoronoiRegions.Contains(regB)); Assert.IsTrue(gdv.VoronoiRegions.Contains(regC)); Assert.AreEqual(reg.NeighbourgRegions.Count(), 2); Assert.IsTrue(reg.IsInfiniteRegion); Assert.AreEqual(reg.Vertexes.Count(), 3); Assert.AreEqual(reg.Vertexes.Count(v => v.Infinity), 2); Assert.AreEqual(reg.Facets.Count(), 2); Assert.IsTrue(reg.Facets.All(f => f.semiHyperSpaceMatch(reg.Nuclei.Coordinates))); Assert.AreEqual(regB.NeighbourgRegions.Count(), 2); Assert.IsTrue(regB.IsInfiniteRegion); Assert.AreEqual(regB.Vertexes.Count(), 3); Assert.AreEqual(regB.Vertexes.Count(v => v.Infinity), 2); Assert.AreEqual(regB.Facets.Count(), 2); Assert.IsTrue(regB.Facets.All(f => f.semiHyperSpaceMatch(regB.Nuclei.Coordinates))); Assert.AreEqual(regC.NeighbourgRegions.Count(), 2); Assert.IsTrue(regC.IsInfiniteRegion); Assert.AreEqual(regC.Vertexes.Count(), 3); Assert.AreEqual(regC.Vertexes.Count(v => v.Infinity), 2); Assert.AreEqual(regC.Facets.Count(), 2); Assert.IsTrue(regC.Facets.All(f => f.semiHyperSpaceMatch(regC.Nuclei.Coordinates))); CheckGeneralDiagramCoherence(gdv); }
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); } }