I am using a 3D Voronoi library called MIConvexHull, which calculates a 3D Voronoi diagram for a series of points in 3D space. However, it does not provide high-level information about the structure of the Voronoi diagram; the reported edges are simply a list of coordinate pairs which then have to have the circumcentre calculated.
Now the library provides an implementation of the circumcentre calculation for a series of 2D points. As you can see here, the coordinate pairs for the start (orange) and end (green) are shown:
You can visually see that if you take the vertexes listed in each of the edges and you make a circle such that the circumference of that circle touches all of the edges, the centre is where the edge starts.
The problem that I have is that my points are 3D and thus it won't be the centre of a circle that's returned, but the centre of a sphere. Unfortunately, advanced mathematics is not something that my head can really handle that well, so I have no idea how to approach this problem.
How, given 4 points in 3D space, can I get the centre of a sphere such that all of the points lie on the surface of the sphere?
EDIT: In 3D, there will be 4 points provided, not 3.
I converted the Javascript implementation that was linked above into C#. Here it is:
/// <summary>
/// Given four points in 3D space, solves for a sphere such that all four points
/// lie on the sphere's surface.
/// </summary>
/// <remarks>
/// Translated from Javascript on http://www.convertalot.com/sphere_solver.html, originally
/// linked to by http://stackoverflow.com/questions/13600739/calculate-centre-of-sphere-whose-surface-contains-4-points-c.
/// </remarks>
public class CircumcentreSolver
{
private const float ZERO = 0;
private double m_X0, m_Y0, m_Z0;
private double m_Radius;
private double[,] P =
{
{ ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO }
};
/// <summary>
/// The centre of the resulting sphere.
/// </summary>
public double[] Centre
{
get { return new double[] { this.m_X0, this.m_Y0, this.m_Z0 }; }
}
/// <summary>
/// The radius of the resulting sphere.
/// </summary>
public double Radius
{
get { return this.m_Radius; }
}
/// <summary>
/// Whether the result was a valid sphere.
/// </summary>
public bool Valid
{
get { return this.m_Radius != 0; }
}
/// <summary>
/// Computes the centre of a sphere such that all four specified points in
/// 3D space lie on the sphere's surface.
/// </summary>
/// <param name="a">The first point (array of 3 doubles for X, Y, Z).</param>
/// <param name="b">The second point (array of 3 doubles for X, Y, Z).</param>
/// <param name="c">The third point (array of 3 doubles for X, Y, Z).</param>
/// <param name="d">The fourth point (array of 3 doubles for X, Y, Z).</param>
public CircumcentreSolver(double[] a, double[] b, double[] c, double[] d)
{
this.Compute(a, b, c, d);
}
/// <summary>
/// Evaluate the determinant.
/// </summary>
private void Compute(double[] a, double[] b, double[] c, double[] d)
{
P[0, 0] = a[0];
P[0, 1] = a[1];
P[0, 2] = a[2];
P[1, 0] = b[0];
P[1, 1] = b[1];
P[1, 2] = b[2];
P[2, 0] = c[0];
P[2, 1] = c[1];
P[2, 2] = c[2];
P[3, 0] = d[0];
P[3, 1] = d[1];
P[3, 2] = d[2];
// Compute result sphere.
this.Sphere();
}
private void Sphere()
{
double r, m11, m12, m13, m14, m15;
double[,] a =
{
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO }
};
// Find minor 1, 1.
for (int i = 0; i < 4; i++)
{
a[i, 0] = P[i, 0];
a[i, 1] = P[i, 1];
a[i, 2] = P[i, 2];
a[i, 3] = 1;
}
m11 = this.Determinant(a, 4);
// Find minor 1, 2.
for (int i = 0; i < 4; i++)
{
a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
a[i, 1] = P[i, 1];
a[i, 2] = P[i, 2];
a[i, 3] = 1;
}
m12 = this.Determinant(a, 4);
// Find minor 1, 3.
for (int i = 0; i < 4; i++)
{
a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
a[i, 1] = P[i, 0];
a[i, 2] = P[i, 2];
a[i, 3] = 1;
}
m13 = this.Determinant(a, 4);
// Find minor 1, 4.
for (int i = 0; i < 4; i++)
{
a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
a[i, 1] = P[i, 0];
a[i, 2] = P[i, 1];
a[i, 3] = 1;
}
m14 = this.Determinant(a, 4);
// Find minor 1, 5.
for (int i = 0; i < 4; i++)
{
a[i, 0] = P[i, 0] * P[i, 0] + P[i, 1] * P[i, 1] + P[i, 2] * P[i, 2];
a[i, 1] = P[i, 0];
a[i, 2] = P[i, 1];
a[i, 3] = P[i, 2];
}
m15 = this.Determinant(a, 4);
// Calculate result.
if (m11 == 0)
{
this.m_X0 = 0;
this.m_Y0 = 0;
this.m_Z0 = 0;
this.m_Radius = 0;
}
else
{
this.m_X0 = 0.5 * m12 / m11;
this.m_Y0 = -0.5 * m13 / m11;
this.m_Z0 = 0.5 * m14 / m11;
this.m_Radius = System.Math.Sqrt(this.m_X0 * this.m_X0 + this.m_Y0 * this.m_Y0 + this.m_Z0 * this.m_Z0 - m15 / m11);
}
}
/// <summary>
/// Recursive definition of determinate using expansion by minors.
/// </summary>
private double Determinant(double[,] a, int n)
{
int i, j, j1, j2;
double d = 0;
double[,] m =
{
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO },
{ ZERO, ZERO, ZERO, ZERO }
};
if (n == 2)
{
// Terminate recursion.
d = a[0, 0] * a[1, 1] - a[1, 0] * a[0, 1];
}
else
{
d = 0;
for (j1 = 0; j1 < n; j1++) // Do each column.
{
for (i = 1; i < n; i++) // Create minor.
{
j2 = 0;
for (j = 0; j < n; j++)
{
if (j == j1) continue;
m[i - 1, j2] = a[i, j];
j2++;
}
}
// Sum (+/-)cofactor * minor.
d = d + System.Math.Pow(-1.0, j1) * a[0, j1] * this.Determinant(m, n - 1);
}
}
return d;
}
}
Here's a Javascript implementation:
http://www.convertalot.com/sphere_solver.html
And some mathematical explanations:
http://steve.hollasch.net/cgindex/geometry/sphere4pts.html
The equation of the sphere ... is given by setting the following determinant to zero:
| x^2 + y^2 + z^2 x y z 1 |
| x1^2 + y1^2 + z1^2 x1 y1 z1 1 |
| x2^2 + y2^2 + z2^2 x2 y2 z2 1 | = 0.
| x3^2 + y3^2 + z3^2 x3 y3 z3 1 |
| x4^2 + y4^2 + z4^2 x4 y4 z4 1 |
Related
I draw a bunch of line graphs using LiveCharts and WPF, where the contents and the number of line charts are determined at run time. So I don't know in advance how many LineSeries will be there, and what their values will be. However, I know the good range for each LineSeries. For example, one series, let's call it S1 has a good range of 2+/-1. So anything between 1 and 3 are considered to be good. Similarly there can be another, say S2 where range is 30+/-2, so anything between 28 and 32 is good.
I would like to draw the line graph so that sections that are within range are drawn as a solid line, but if a section is outside the range, it would be a dotted/dash line. Since I have multiple LineSeries in one, I have plotted each in its own Y-axis. My XAML and code looks like this:
<Grid>
<lvc:CartesianChart Name="MyChart" Margin="4"
Series="{Binding SeriesCollection}"/>
</Grid>
Code behind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public SeriesCollection SeriesCollection { get; set; }
public MainWindow()
{
InitializeComponent();
PlotGraph();
}
private void PlotGraph()
{
SeriesCollection = new SeriesCollection();
var lineSeries1 = new LineSeries
{
Title = "S1",
Values = new ChartValues<double>() { 2.3, 2.0, 3.1, 1.3, 0.5, 3.8, 7.3, 2.4, 1.2, 0.1 },
DataLabels = true,
Stroke = Brushes.Green,
Fill = Brushes.Transparent,
ScalesYAt = 0
};
var lineSeries2 = new LineSeries
{
Title = "S2",
Values = new ChartValues<double>() { 32.5, 34.5, 29.5, 26.0, 25.8, 30.5, 32.1, 36.5, 32.4, 24.5 },
DataLabels = true,
Stroke = Brushes.HotPink,
Fill = Brushes.Transparent,
ScalesYAt = 1
};
SeriesCollection.Add(lineSeries1);
SeriesCollection.Add(lineSeries2);
MyChart.AxisY.Add(new Axis());
MyChart.AxisY.Add(new Axis());
DataContext = this;
}
}
I found an example here that the PointState is colored based on values, but it doesn't work for me because I draw multiple series in one. Also, my graph has thousands of points so I have disabled PointGeometry since if I enable them they will be very hard to see anyway.
Is what I want possible at all?
i have found a solution, in fact 2: either you customize livechart to your problem or you recalculate the differents points like i do below:
its just a way, an idea to answer to your question, all things are possible, but need some line of codes....
the plotgraph method
private void PlotGraph()
{
var points = new List<Point>() { new Point(0, 2.3), new Point(1, 2.0),
new Point(2, 3.1), new Point(3, 1.3),
new Point(4, 0.5), new Point(5, 3.8),
new Point(6, 7.3), new Point(7, 2.4),
new Point(8, 1.2), new Point(9, 0.1)};
var range1 = new double[] { 1d, 3d };
var otherpoints = CurvesMath.GetInterpolatedCubicSplinedCurve(points);
var pointscurve = otherpoints.Select(p => p.Y).ToArray();
SeriesCollection = new SeriesCollection();
var lineSeries1 = new LineSeries
{
Title = "S1",
Values = new ChartValues<double>(pointscurve),
DataLabels = false,
Stroke = Brushes.Transparent,
Fill = Brushes.Transparent,
ScalesYAt = 0,
PointGeometrySize = 2,
Configuration = Mappers.Xy<double>()
.X((value, index) => index)
.Y((value, index) => value)
.Stroke((value, index) => value <= range1[0] || value >= range1[1] ? Brushes.Red : Brushes.Blue)
.Fill((value, index) => value <= range1[0] || value >= range1[1] ? Brushes.Red : Brushes.Blue)
};
points = new List<Point>() { new Point(0, 32.5), new Point(1, 34.5),
new Point(2, 29.5), new Point(3, 26.0),
new Point(4, 25.8), new Point(5, 30.5),
new Point(6, 32.1), new Point(7, 36.5),
new Point(8, 32.4), new Point(9, 24.5)};
var range2 = new double[] { 28d, 32d };
otherpoints = CurvesMath.GetInterpolatedCubicSplinedCurve(points);
pointscurve = otherpoints.Select(p => p.Y).ToArray();
var lineSeries2 = new LineSeries
{
Title = "S2",
Values = new ChartValues<double>(pointscurve),
DataLabels = false,
Stroke = Brushes.Transparent,
Fill = Brushes.Transparent,
ScalesYAt = 1,
PointGeometrySize = 2,
Configuration = Mappers.Xy<double>()
.X((value, index) => index)
.Y((value, index) => value)
.Stroke((value, index) => value <= range2[0] || value >= range2[1] ? Brushes.Red : Brushes.Green)
.Fill((value, index) => value <= range2[0] || value >= range2[1] ? Brushes.Red : Brushes.Green)
};
SeriesCollection.Add(lineSeries1);
SeriesCollection.Add(lineSeries2);
MyChart.AxisY.Add(new Axis());
MyChart.AxisY.Add(new Axis());
DataContext = this;
}
the xaml file:
<Grid>
<lvc:CartesianChart Name="MyChart" Margin="4"
Series="{Binding SeriesCollection}" >
</lvc:CartesianChart>
</Grid>
the interpolation cubic spline (or bezier)
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace WpfApp2
{
public static class CurvesMath
{
private const int precision = 80;
public static List<Point> GetInterpolatedCubicSplinedCurve(IList<Point> points)
{
var output = new List<Point>();
int np = points.Count; // number of points
double[] yCoords = new double[np]; // Newton form coefficients
double[] xCoords = new double[np]; // x-coordinates of nodes
double y;
double x;
if (np > 0)
{
for (int i = 0; i < np; i++)
{
var p = points[i];
xCoords[i] = p.X;
yCoords[i] = p.Y;
}
if (np > 1)
{
double[] a = new double[np];
double x1;
double x2;
double[] h = new double[np];
for (int i = 1; i <= np - 1; i++)
{
h[i] = xCoords[i] - xCoords[i - 1];
}
if (np > 2)
{
double[] sub = new double[np - 1];
double[] diag = new double[np - 1];
double[] sup = new double[np - 1];
for (int i = 1; i <= np - 2; i++)
{
diag[i] = (h[i] + h[i + 1]) / 3;
sup[i] = h[i + 1] / 6;
sub[i] = h[i] / 6;
a[i] = (yCoords[i + 1] - yCoords[i]) / h[i + 1] - (yCoords[i] - yCoords[i - 1]) / h[i];
}
SolveTridiag(sub, diag, sup, ref a, np - 2);
}
output.Add(points.First());
for (int i = 1; i <= np - 1; i++)
{
// loop over intervals between nodes
for (int j = 1; j <= precision; j++)
{
x1 = (h[i] * j) / precision;
x2 = h[i] - x1;
y = ((-a[i - 1] / 6 * (x2 + h[i]) * x1 + yCoords[i - 1]) * x2 +
(-a[i] / 6 * (x1 + h[i]) * x2 + yCoords[i]) * x1) / h[i];
x = xCoords[i - 1] + x1;
output.Add(new Point(x, y));
}
}
}
}
return output;
}
public static double SolveCubicSpline(IList<Point> knownSamples, double z)
{
int np = knownSamples.Count;
if (np > 1)
{
if (knownSamples[0].X == z) return knownSamples[0].Y;
double[] a = new double[np];
double x1;
double x2;
double y;
double[] h = new double[np];
for (int i = 1; i <= np - 1; i++)
{
h[i] = knownSamples[i].X - knownSamples[i - 1].X;
}
if (np > 2)
{
double[] sub = new double[np - 1];
double[] diag = new double[np - 1];
double[] sup = new double[np - 1];
for (int i = 1; i <= np - 2; i++)
{
diag[i] = (h[i] + h[i + 1]) / 3;
sup[i] = h[i + 1] / 6;
sub[i] = h[i] / 6;
a[i] = (knownSamples[i + 1].Y - knownSamples[i].Y) / h[i + 1] -
(knownSamples[i].Y - knownSamples[i - 1].Y) / h[i];
}
// SolveTridiag is a support function, see Marco Roello's original code
// for more information at
// http://www.codeproject.com/useritems/SplineInterpolation.asp
SolveTridiag(sub, diag, sup, ref a, np - 2);
}
int gap = 0;
double previous = double.MinValue;
// At the end of this iteration, "gap" will contain the index of the interval
// between two known values, which contains the unknown z, and "previous" will
// contain the biggest z value among the known samples, left of the unknown z
for (int i = 0; i < knownSamples.Count; i++)
{
if (knownSamples[i].X < z && knownSamples[i].X > previous)
{
previous = knownSamples[i].X;
gap = i + 1;
}
}
x1 = z - previous;
if (gap > h.Length - 1)
return z;
x2 = h[gap] - x1;
if (gap == 0)
return 0.0;
y = ((-a[gap - 1] / 6 * (x2 + h[gap]) * x1 + knownSamples[gap - 1].Y) * x2 +
(-a[gap] / 6 * (x1 + h[gap]) * x2 + knownSamples[gap].Y) * x1) / h[gap];
return y;
}
return 0;
}
private static void SolveTridiag(double[] sub, double[] diag, double[] sup, ref double[] b, int n)
{
/* solve linear system with tridiagonal n by n matrix a
using Gaussian elimination *without* pivoting
where a(i,i-1) = sub[i] for 2<=i<=n
a(i,i) = diag[i] for 1<=i<=n
a(i,i+1) = sup[i] for 1<=i<=n-1
(the values sub[1], sup[n] are ignored)
right hand side vector b[1:n] is overwritten with solution
NOTE: 1...n is used in all arrays, 0 is unused */
int i;
/* factorization and forward substitution */
for (i = 2; i <= n; i++)
{
sub[i] = sub[i] / diag[i - 1];
diag[i] = diag[i] - sub[i] * sup[i - 1];
b[i] = b[i] - sub[i] * b[i - 1];
}
b[n] = b[n] / diag[n];
for (i = n - 1; i >= 1; i--)
{
b[i] = (b[i] - sup[i] * b[i + 1]) / diag[i];
}
}
}
}
in the result you see all bad parts with the color RED
I am attempting to implement the Levenshtein Distance algorithm in C# (for practice and because it'd be handy to have). I used an implementation from the Wikipedia page but for some reason I'm getting the wrong distance on one set of words. Here's the code (from LinqPad):
void Main()
{
var ld = new LevenshteinDistance();
int dist = ld.LevenshteinDistanceCalc("sitting","kitten");
dist.Dump();
}
// Define other methods and classes here
public class LevenshteinDistance
{
private int[,] distance;
public int LevenshteinDistanceCalc(string source, string target)
{
int sourceSize = source.Length, targetSize = target.Length;
distance = new int[sourceSize, targetSize];
for (int sIndex = 0; sIndex < sourceSize; sIndex++)
{
distance[sIndex, 0] = sIndex;
}
for (int tIndex = 0; tIndex < targetSize; tIndex++)
{
distance[0,tIndex] = tIndex;
}
// for j from 1 to n:
// for i from 1 to m:
// if s[i] = t[j]:
// substitutionCost:= 0
// else:
// substitutionCost:= 1
// d[i, j] := minimum(d[i - 1, j] + 1, // deletion
// d[i, j - 1] + 1, // insertion
// d[i - 1, j - 1] + substitutionCost) // substitution
//
//
// return d[m, n]
for (int tIndex = 1; tIndex < targetSize; tIndex++)
{
for (int sIndex = 1; sIndex < sourceSize; sIndex++)
{
int substitutionCost = source[sIndex] == target[tIndex] ? 0 : 1;
int deletion = distance[sIndex-1, tIndex]+1;
int insertion = distance[sIndex,tIndex-1]+1;
int substitution = distance[sIndex-1, tIndex-1] + substitutionCost;
distance[sIndex, tIndex] = leastOfThree(deletion, insertion, substitution);
}
}
return distance[sourceSize-1,targetSize-1];
}
private int leastOfThree(int a, int b, int c)
{
return Math.Min(a,(Math.Min(b,c)));
}
}
When I try "sitting" and "kitten" I get an LD of 2 (should be 3). Yet when I try "Saturday" and "Sunday" I get an LD of 3 (which is correct). I know something's wrong but I can't figure out what I'm missing.
The example on wikipedia uses 1-based strings. In C# we use 0-based strings.
In their matrix the 0-row and 0-column does exist. So the size of their matrix is [source.Length + 1, source.Length + 1] In your code it doesn't exist.
public int LevenshteinDistanceCalc(string source, string target)
{
int sourceSize = source.Length, targetSize = target.Length;
distance = new int[sourceSize + 1, targetSize + 1];
for (int sIndex = 1; sIndex <= sourceSize; sIndex++)
distance[sIndex, 0] = sIndex;
for (int tIndex = 1; tIndex <= targetSize; tIndex++)
distance[0, tIndex] = tIndex;
for (int tIndex = 1; tIndex <= targetSize; tIndex++)
{
for (int sIndex = 1; sIndex <= sourceSize; sIndex++)
{
int substitutionCost = source[sIndex-1] == target[tIndex-1] ? 0 : 1;
int deletion = distance[sIndex - 1, tIndex] + 1;
int insertion = distance[sIndex, tIndex - 1] + 1;
int substitution = distance[sIndex - 1, tIndex - 1] + substitutionCost;
distance[sIndex, tIndex] = leastOfThree(deletion, insertion, substitution);
}
}
return distance[sourceSize, targetSize];
}
Your matrix isn't big enough.
In the pseudo-code, s and t have lengths m and n respectively (char s[1..m], char t[1..n]). The matrix however has dimentions [0..m, 0..n] - i.e. one more than the length of the strings in each direction. You can see this in the tables below the pseudo-code.
So the matrix for "sitting" and "kitten" is 7x8, but your matrix is only 6x7.
You're also indexing into the strings incorrectly, because the strings in the pseudo-code are 1-indexed, but C#'s strings are 0-indexed.
After fixing these, you get this code, which works with "sitting" and "kitten":
public static class LevenshteinDistance
{
public static int LevenshteinDistanceCalc(string source, string target)
{
int sourceSize = source.Length + 1, targetSize = target.Length + 1;
int[,] distance = new int[sourceSize, targetSize];
for (int sIndex = 0; sIndex < sourceSize; sIndex++)
{
distance[sIndex, 0] = sIndex;
}
for (int tIndex = 0; tIndex < targetSize; tIndex++)
{
distance[0, tIndex] = tIndex;
}
// for j from 1 to n:
// for i from 1 to m:
// if s[i] = t[j]:
// substitutionCost:= 0
// else:
// substitutionCost:= 1
// d[i, j] := minimum(d[i - 1, j] + 1, // deletion
// d[i, j - 1] + 1, // insertion
// d[i - 1, j - 1] + substitutionCost) // substitution
//
//
// return d[m, n]
for (int tIndex = 1; tIndex < targetSize; tIndex++)
{
for (int sIndex = 1; sIndex < sourceSize; sIndex++)
{
int substitutionCost = source[sIndex - 1] == target[tIndex - 1] ? 0 : 1;
int deletion = distance[sIndex - 1, tIndex] + 1;
int insertion = distance[sIndex, tIndex - 1] + 1;
int substitution = distance[sIndex - 1, tIndex - 1] + substitutionCost;
distance[sIndex, tIndex] = leastOfThree(deletion, insertion, substitution);
}
}
return distance[sourceSize - 1, targetSize - 1];
}
private static int leastOfThree(int a, int b, int c)
{
return Math.Min(a, (Math.Min(b, c)));
}
}
(I also took the liberty of making distance a local variable since there's no need for it to be a field (it only makes your class non-threadsafe), and also making it static to avoid the unnecessary instantiation).
To debug this, I put a breakpoint on return distance[sourceSize - 1, targetSize - 1] and compared distance to the table on Wikipedia. It was very obvious that it was too small.
Well, this is giving me a real headache. I'm building a matrix determinant function to compute NxN determinant, and I'm using recursion.
The logic is working right but I'm not able to get the final value computed correctly.
Here is my code for Matrix Determinant:
public static double determinant(double[,]array){
double det=0;
double total = 0;
double[,] tempArr = new double[array.GetLength(0) - 1, array.GetLength(1) - 1];
if(array.GetLength(0)==2)
{
det = array[0, 0] * array[1, 1] - array[0, 1] * array[1, 0];
}
else {
for (int i = 0; i <1; i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
if (j % 2 != 0) array[i, j] = array[i, j] * -1;
tempArr= fillNewArr(array, i, j);
det+=determinant(tempArr);
total =total + (det * array[i, j]);
}
}
}
return det;
}
and about fillNewArr method it's just a method to trim the array, method is as follow:
p
ublic static double[,] fillNewArr(double[,] originalArr, int row, int col)
{
double[,] tempArray = new double[originalArr.GetLength(0) - 1, originalArr.GetLength(1) - 1];
for (int i = 0, newRow = 0; i < originalArr.GetLength(0); i++)
{
if (i == row)
continue;
for (int j = 0, newCol=0; j < originalArr.GetLength(1); j++)
{
if ( j == col) continue;
tempArray[newRow, newCol] = originalArr[i, j];
newCol++;
}
newRow++;
}
return tempArray;
}
The method is working as it supposed to "I assume" but the final result is not computed in the right way, why would that be?!
4x4 Array Example:
{2 6 6 2}
{2 7 3 6}
{1 5 0 1}
{3 7 0 7}
Final result should be -168, while mine is 104!
This bit
if (j % 2 != 0) array[i, j] = array[i, j] * -1;
tempArr= fillNewArr(array, i, j);
det+=determinant(tempArr);
total =total + (det * array[i, j]);
uses a variable total that is never used again. It should probably be something like
double subdet = determinant(fillNewArr(array, i, j));
if (j % 2 != 0) subdet *= -1;
det += array[i, j] * subdet;
Hi i'm using the levenshtein algorithm to calculate the difference between two strings, using the below code. It currently provides the total number of changes which need to be made to get from 'answer' to 'target', but i'd like to split these up into the types of errors being made. So classifying an error as a deletion, substitution or insertion.
I've tried adding a simple count but i'm new at this and don't really understand how the code works so not sure how to go about it.
static class LevenshteinDistance
{
/// <summary>
/// Compute the distance between two strings.
/// </summary>
public static int Compute(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// Step 1
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
// Step 2
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
// Step 3
for (int i = 1; i <= n; i++)
{
//Step 4
for (int j = 1; j <= m; j++)
{
// Step 5
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
// Step 6
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
// Step 7
return d[n, m];
}
}
Thanks in advance.
as a Practice I tried flipping a bitmap with unsafe code and pointers in C#
but the problem is I get the original bitmap as the result instead of flipped bitmap , it seems that the function does nothing at all , so I'm wondering what's wrong in my code !
please keep in mind that I want to flip pictureBox1.Image and set it as pictureBox2.Image
private bool Flip_H()
{
try
{
b = new Bitmap(pictureBox1.Image);
bmdata = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int offset = bmdata.Stride - b.Width * 3;
byte back_up;
int BGRwidth = b.Width * 3;
unsafe
{
byte* p = (byte*)bmdata.Scan0;
for (int y = 0; y < b.Height; y++)
{
for (int x = 0; x < BGRwidth / 2; x += 3)
{
back_up = p[x];
p[x] = p[BGRwidth - x - 3];
p[BGRwidth - x - 1] = back_up;
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
}
p += offset;
}
}
b.UnlockBits(bmdata);
pictureBox2.Image = b;
return true;
}
catch
{
return false;
}
}
I have already done this with GetPixel() and SetPixel() functions , but as you know they are too slow , so I'm trying to Improve my code with pointers !
the Problem was Offset Parameter ! thanks everyone who helped
Your problem is that you never advanced in the Y direction. You always change the pixels only on the first scanline and therefore the rest does not change. This happens because you do p += offset but you defined offset as:
int offset = bmdata.Stride - b.Width * 3;
You should instead define offset as:
int offset = bmdata.Stride;
Since you want to add the stride width, in bytes, to get to the next scan line.
Also there is a bug in your swapping code. You have:
back_up = p[x + 0];
p[x + 0] = p[BGRwidth - x - 3];
p[BGRwidth - x - 1] = back_up; // Error!
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
// Missing!
You should have:
back_up = p[x + 0];
p[x + 0] = p[BGRwidth - x - 3];
p[BGRwidth - x - 3] = back_up;
back_up = p[x + 1];
p[x + 1] = p[BGRwidth - x - 2];
p[BGRwidth - x - 2] = back_up;
back_up = p[x + 2];
p[x + 2] = p[BGRwidth - x - 1];
p[BGRwidth - x - 1] = back_up;