📜 ⬆️ ⬇️

Cell painter

It is known that a set of regular hexagons can be used to describe almost any contour and thereby create a figure of arbitrary shape. Such a principle can be applied when constructing topographic maps similar to how it is implemented in Sid Meier's Civilization V , or used in systems based on the same hexagons (cellular operators). To make the information more informative, each cell of the map can be assigned a control value, whether it be the signal level of the network, height, depth, the presence of a certain type of resources, etc., which characterizes a section of the map - a cell. It might look something like this . However, for the eyes, this view is not quite presentable, and it can be visualized by adding a corresponding color to each cell.

Design work

First you need to build a frame card - a cellular structure. There are some solutions to this problem, for example, on the codeproject , but the end goal is slightly different there. So, we will construct a grid in the horizontal projection, the essence is in the calculation of the new coordinate according to the mathematical control, with a shift by a constant value for every odd row, depending on the length of the side of the hexagon:
private void DrawHexangleHorizon(Graphics gr, int i, int j) { int shft; int shft2; GraphicsPath gp; if (i % 2 != 0) { shft = (int)(Side * Math.Sqrt(3) / 2); shft2 = (int)((i - 1) * 1.5 * Side); gp = new GraphicsPath(new PointF[7] { new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2), //init 1-1 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))+(int)(Side * Math.Sqrt(3)/2),20+shft2+Side/2), //1->2 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))+(int)(Side * Math.Sqrt(3)/2), 20+shft2 +Side+ Side/2), //2->3 new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2 + 2*Side), //3->4 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))-(int)(Side * Math.Sqrt(3)/2), 20+shft2 +Side+ Side/2), //4->5 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))-(int)(Side * Math.Sqrt(3)/2), 20+shft2 + Side/2), //5->6 new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2) //finish 6->1 }, new byte[7] { (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, } ); } else { shft2 = (int)((i - 1) * 1.5 * Side); shft = 0; gp = new GraphicsPath(new PointF[7] { new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2), //init 1-1 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))+(int)(Side * Math.Sqrt(3)/2),20+shft2+Side/2), //1->2 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))+(int)(Side * Math.Sqrt(3)/2), 20+shft2 +Side+ Side/2), //2->3 new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2 + 2*Side), //3->4 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))-(int)(Side * Math.Sqrt(3)/2), 20+shft2 +Side+ Side/2), //4->5 new Point(20+shft+j*(int)(Side * Math.Sqrt(3))-(int)(Side * Math.Sqrt(3)/2), 20+shft2 + Side/2), //5->6 new Point(20+shft+j*(int)(Side * Math.Sqrt(3)), 20+shft2) //finish 6->1 }, new byte[7] { (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line, } ); } gr.DrawPath(Pens.Black, gp); gr.FillPath(Sbr, gp); } 

After doing something like this:
image
If this framework is superimposed on a real flat object and “subtract”, only those cells will remain, which are the boundaries of the object.
Painting works

When the frame construction apparatus is ready, i.e. borders of the map and cells, you can paint them in the appropriate color. Rules for coloring can be thought up as you like. In my case, the cell with a large value was painted red, with a smaller color in blue. To solve the visualization problem, we apply a linear gradient of the RGB standard. Decorate:
 private void ColoredGrig(Graphics gr, double[,] mas) { double max = double.MinValue; double min = double.MaxValue; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (mas[i, j] > max) { max = mas[i, j]; } if (mas[i, j] < min) { min = mas[i, j]; } } } double average = (max + min) / 2.0; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { var c = new Color(); var red = new double(); var green = new double(); var blue = new double(); if (mas[i, j] == max) { red = 255; blue = 0; green = 0; } if (mas[i, j] == min) { red = 0; blue = 255; green = 0; } if (mas[i, j] == average) { red = 0; blue = 0; green = 255; } //warm colors if ((mas[i, j] < max) && (mas[i, j] >= ((average + max) / 2))) { red = 255; green = 255 - ((mas[i, j] - ((average + max) / 2)) * 255) / (max - ((max + average) / 2)); } if ((mas[i, j] > average) && (mas[i, j] < ((average + max) / 2))) { red = ((mas[i, j] - average) * 255) / (((max + average) / 2) - average); green = 255; } //cold colors if ((mas[i, j] < average) && (mas[i, j] > ((average + min) / 2))) { blue = 255 - ((mas[i, j] - ((average + min) / 2)) * 255) / (average - ((average + min) / 2)); green = 255; } if ((mas[i, j] > min) && (mas[i, j] <= ((average + min) / 2))) { blue = 255; green = ((mas[i, j] - min) * 255) / (((average + min) / 2) - min); } c = Color.FromArgb((int)red, (int)green, (int)blue); Sbr = new SolidBrush(c); DrawHexangleHorizon(gr, i, j); } } } 

If you paint randomly generated values, the map will resemble something like a stained glass window, and does not carry much meaning:
image
But if the data contain certain linear dependencies, then they are observed quite clearly on the maps:
image

Other side

And further. The obtained functions can be applied when using Kohonen self-organization maps for analyzing multidimensional data and clustering features in areas for which large amounts of related information need to be analyzed, for example, for analyzing network traffic in order to identify patterns, deviations or anomalies, both in the main communication channels and in local networks. This type of neural networks is based on competitive learning, the organization of which uses lateral connections between neurons. When training a network, the method of training without a teacher is used, that is, the result of training depends only on the structure of the input data. This line of analysis is not signature-based, which in theory can create a new branch of network security products.

')

Source: https://habr.com/ru/post/167685/


All Articles