public InverseDefaultVoronoiFacet(IVoronoiFacet constraint) { if (constraint == null || !(constraint is DefaultVoronoiFacet)) { throw new ArgumentException("invalid constraint."); } decorated = constraint as DefaultVoronoiFacet; }
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; } } }
public InverseDefaultVoronoiFacet(IVoronoiFacet constraint) { if (constraint == null || !(constraint is DefaultVoronoiFacet)) throw new ArgumentException ("invalid constraint."); decorated = constraint as DefaultVoronoiFacet; }