commit 03db246d88f11b5ee20bd1f3f3497240603a40bf Author: dm1sh Date: Fri Apr 4 12:38:48 2025 +0300 does not work diff --git a/Calculator.cs b/Calculator.cs new file mode 100644 index 0000000..a8e3560 --- /dev/null +++ b/Calculator.cs @@ -0,0 +1,80 @@ +namespace omp +{ + public class OverlappingPoints : Exception { } + + public static class Calculator + { + public const double StationPDOP = -1000; + + public static double[,] Jacobian1T(List stations, Point position) + { + int n = stations.Count; + double[,] J = new double[4, n]; + + for (int i = 0; i < n; ++i) + { + double distance = position.Distance(stations[i]); + + if (distance == 0) + { + throw new OverlappingPoints(); + } + + J[0, i] = -(stations[i].x - position.x) / distance; + J[1, i] = -(stations[i].y - position.y) / distance; + J[2, i] = -(stations[i].z - position.z) / distance; + J[3, i] = 1; // Clock bias + } + + return J; + } + + public static double PDOP(List stations, Point position) + { + double[,] JR = Jacobian1T(stations, position); + + double[,] mult = MatrixOps.MultTrans(JR); + + double det = MatrixOps.Det(mult); + + double sx2 = MatrixOps.Adj(mult, 0, 0) / det; + double sy2 = MatrixOps.Adj(mult, 1, 1) / det; + double sz2 = MatrixOps.Adj(mult, 2, 2) / det; + + return Math.Sqrt(sx2 + sy2 + sz2); + } + + public static void PDOPs(double[,] pdops, Configurator conf, out double min, out double max) + { + min = double.MaxValue; + max = double.MinValue; + + for (int i = 0; i < pdops.GetLength(0); ++i) + { + for (int j = 0; j < pdops.GetLength(1); ++j) + { + try + { + pdops[i, j] = PDOP(conf.stations, new Point(i, j, conf.zCoordinate)); + + if (pdops[i, j] > max) + { + max = pdops[i, j]; + } + + if (pdops[i, j] < min) + { + min = pdops[i, j]; + } + } + catch (OverlappingPoints) + { + pdops[i, j] = StationPDOP; + } + } + } + + Console.WriteLine("{0}...{1}", min, max); + } + } +} \ No newline at end of file diff --git a/Configurator.cs b/Configurator.cs new file mode 100644 index 0000000..fefeea0 --- /dev/null +++ b/Configurator.cs @@ -0,0 +1,96 @@ +namespace omp +{ + public class Configurator + { + public int xsize; + public int ysize; + public int zCoordinate; + public List stations = []; + + public Configurator(string[] args) + { + List lines; + + if (args.Length == 0) + { + Console.WriteLine("Input parameters:"); + + lines = []; + + string? line; + while ((line = Console.ReadLine()) != null && line != "") + { + lines.Add(line); + } + } + else if (args.Length == 1) + { + lines = new(File.ReadAllLines(args[0])); + } + else + { + throw new ArgumentException("You must either provide path to parameters file as an only cli argument, or insert it into STDIN"); + } + + ParseParameters(lines); + } + + private void ParseParameters(IReadOnlyList lines) + { + bool hasZ = CheckHasZ(lines[1]); + + ParseSize(lines[0]); + ParseZCoord(lines[1], hasZ); + ParseStations(lines, hasZ); + } + + private static bool CheckHasZ(string line) + { + return line.Split(' ').Length == 1; // line contains a single number, z coordinate + } + + private void ParseSize(string line) + { + string[] size_parts = line.Split(' ', 2); + xsize = int.Parse(size_parts[0]); + ysize = int.Parse(size_parts[1]); + } + + private void ParseZCoord(string line, bool hasZ) + { + if (hasZ) + { + zCoordinate = int.Parse(line); + } + else + { + zCoordinate = 0; + } + } + + private void ParseStations(IReadOnlyList lines, bool hasZ) + { + int firstIndex = 1 + (hasZ ? 1 : 0); + for (int i = firstIndex; i < lines.Count; ++i) + { + string[] point_parts = lines[i].Split(' ', 2 + (hasZ ? 1 : 0)); + + int x, y, z; + + x = int.Parse(point_parts[0]) - 1; + y = int.Parse(point_parts[1]) - 1; + + if (hasZ) + { + z = int.Parse(point_parts[2]); + } + else + { + z = 0; + } + + stations.Add(new Point(x, y, z)); + } + } + } +} \ No newline at end of file diff --git a/Drawer.cs b/Drawer.cs new file mode 100644 index 0000000..c45d8ed --- /dev/null +++ b/Drawer.cs @@ -0,0 +1,67 @@ +using SkiaSharp; + +namespace omp +{ + class Drawer + { + public static void Draw(Configurator conf, double[,] pdops, double min, double max) + { + var bitmap = new SKBitmap(conf.xsize, conf.ysize); + + for (int i = 0; i < conf.xsize; ++i) + { + for (int j = 0; j < conf.ysize; ++j) + { + SKColor color; + + if (pdops[i, j] == Calculator.StationPDOP) + { + color = SKColors.White; + } + else + { + double t = (pdops[i, j] - min) / (max - min); + color = Map2Color(t); + } + + bitmap.SetPixel(i, j, color); + } + } + + using (var image = SKImage.FromBitmap(bitmap)) + using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) + using (var stream = File.OpenWrite("out.png")) + { + data.SaveTo(stream); + } + } + + public static SKColor Map2Color(double t) + { + if (t < 0.25) + { + // Blue to cyan + double localT = t / 0.25; + return new SKColor(0, (byte)(255 * localT), 255); + } + else if (t < 0.5) + { + // Cyan to green + double localT = (t - 0.25) / 0.25; + return new SKColor(0, 255, (byte)(255 * (1 - localT))); + } + else if (t < 0.75) + { + // Green to yellow + double localT = (t - 0.5) / 0.25; + return new SKColor((byte)(255 * localT), 255, 0); + } + else + { + // Yellow to red + double localT = (t - 0.75) / 0.25; + return new SKColor(255, (byte)(255 * (1 - localT)), 0); + } + } + } +} \ No newline at end of file diff --git a/MatrixOps.cs b/MatrixOps.cs new file mode 100644 index 0000000..338e381 --- /dev/null +++ b/MatrixOps.cs @@ -0,0 +1,129 @@ +namespace omp +{ + public static class MatrixOps + { + public static void Print(double[,] a) + { + int rows = a.GetLength(0); + int columns = a.GetLength(1); + + Console.WriteLine("Matrix of size {0}x{1}:", rows, columns); + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + Console.Write("\t{0}", a[i, j]); + } + Console.WriteLine(""); + } + } + + public static double Adj(double[,] a, int i, int j) + { + double sgn = ((i + j) % 2 == 0) ? 1 : -1; + + return sgn * Det(Minor(a, j, i)); + } + + public static double[,] Minor(double[,] a, int i, int j) + { + int rows = a.GetLength(0); + int columns = a.GetLength(1); + + double[,] minor = new double[rows - 1, columns - 1]; + + int k = 0; + int l; + + for (int r = 0; r < rows; ++r) + { + if (r == i) + { + continue; + } + + l = 0; + + for (int c = 0; c < columns; ++c) + { + if (c == j) + { + continue; + } + + minor[k, l] = a[r, c]; + + l++; + } + + k++; + } + + return minor; + } + + public static double Det(double[,] a) + { + int n = a.GetLength(0); + + switch (n) + { + case 2: + return Det2(a); + case 3: + return Det3(a); + default: + double det = 0; + + double sgn; + for (int j = 0; j < n; ++j) + { + sgn = (j % 2 == 0) ? 1 : -1; + det += sgn * a[0, j] * Det(Minor(a, 0, j)); + } + + return det; + } + } + + public static double Det2(double[,] a) + { + return a[0, 0] * a[1, 1] - a[0, 1] * a[1, 0]; + } + + public static double Det3(double[,] a) + { + if (a.GetLength(0) != 3 || a.GetLength(1) != 3) + throw new ArgumentException("Matrix must be 3x3"); + + return + a[0, 0] * a[1, 1] * a[2, 2] + + a[0, 1] * a[1, 2] * a[2, 0] + + a[0, 2] * a[1, 0] * a[2, 1] + - a[0, 2] * a[1, 1] * a[2, 0] + - a[0, 0] * a[1, 2] * a[2, 1] + - a[2, 2] * a[0, 1] * a[1, 0]; + } + + public static double[,] MultTrans(double[,] a) + { + int rows = a.GetLength(0); + int columns = a.GetLength(1); + + double[,] r = new double[rows, rows]; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < rows; j++) + { + for (int k = 0; k < columns; k++) + { + r[i, j] += a[i, k] * a[j, k]; + } + } + } + + return r; + } + } +} \ No newline at end of file diff --git a/Point.cs b/Point.cs new file mode 100644 index 0000000..673ce69 --- /dev/null +++ b/Point.cs @@ -0,0 +1,21 @@ +namespace omp +{ + public class Point(int x, int y, int z) + { + public int x = x, y = y, z = z; + + public double Distance(Point a) + { + double dx = x - a.x; + double dy = y - a.y; + double dz = z - a.z; + + return Math.Sqrt(dx * dx + dy * dy + dz * dz); + } + + public bool Equals(Point a) + { + return (x == a.x) && (y == a.y) && (z == a.z); + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..e91fc30 --- /dev/null +++ b/Program.cs @@ -0,0 +1,17 @@ +namespace omp +{ + public class DOPCalculator + { + public static void Main(string[] args) + { + Configurator conf = new(args); + + double[,] pdops = new double[conf.xsize, conf.ysize]; + double min, max; + + Calculator.PDOPs(pdops, conf, out min, out max); + + Drawer.Draw(conf, pdops, min, max); + } + } +} diff --git a/omp.csproj b/omp.csproj new file mode 100644 index 0000000..35edc10 --- /dev/null +++ b/omp.csproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + + + + + diff --git a/test2.txt b/test2.txt new file mode 100644 index 0000000..d2d31a6 --- /dev/null +++ b/test2.txt @@ -0,0 +1,4 @@ +500 500 +1 +100 499 0 +400 499 0 \ No newline at end of file diff --git a/test3.txt b/test3.txt new file mode 100644 index 0000000..cc9e64c --- /dev/null +++ b/test3.txt @@ -0,0 +1,5 @@ +1000 1000 +0 +236 134 0 +147 863 0 +915 591 0 \ No newline at end of file diff --git a/Задание для домашней работы 2025.docx b/Задание для домашней работы 2025.docx new file mode 100644 index 0000000..f39ae13 Binary files /dev/null and b/Задание для домашней работы 2025.docx differ