我试图用每个点的点和幅度的给定输入绘制热图。正常输入大小约为400,000点,但代码每15个 th 点。地图绘制在Canvas
。
在XAML中:
<Grid x:Name="MainPanel" Width="800" Height="600">
<Textbox Name="textbox" Grid.Column="0"/>
<Canvas Name="canvas" Grid.Column="1" HorizontalAlignment="Left" Height="450" Margin="70,75,0,0" VerticalAlignment="Top" Width="706"/>
</Grid>
渲染代码:
public static void DrawPoints(Parser parser, Canvas canvas, double radiusX, double radiusY, double thickness, double minAmplitude, double maxAmplitude)
{
double cellWidth = canvas.ActualWidth;
double cellHeight = canvas.ActualHeight;
var list = parser.Data;
// Draws every 15th point
int res = 15;
for (int i = 0; i < list.Count; i += res)
{
var location = list[i].Point;
var amplitude = list[i].Amplitude;
// Converts rgb to hsv values for representation
var color= ColorConverter.hsv2rgb(
COLOR_START_H * (1.0 - ((amplitude - minAmplitude) / (maxAmplitude - minAmplitude))),
COLOR_START_S, COLOR_START_V);
Point center = new Point(location.X, location.Y);
DrawEllipse(canvas, center, radiusX, radiusY,
new SolidColorBrush(color), new SolidColorBrush(color), thickness);
}
return;
}
在DrawEllipse
函数中:
public static void DrawEllipse(Canvas canvas, Point center, double radiusX, double radiusY, Brush fill, Brush stroke, double thickness)
{
var ellipse = new Ellipse();
ellipse.Width = radiusX * 2;
ellipse.Height = radiusY * 2;
ellipse.Fill = fill;
ellipse.Stroke = stroke;
ellipse.StrokeThickness = thickness;
Canvas.SetLeft(ellipse, center.X - radiusX);
Canvas.SetBottom(ellipse, center.Y - radiusY);
canvas.Children.Add(ellipse);
return;
}
在主要代码中:
private void btnDraw_Click(object sender, RoutedEventArgs e)
{
Painter.DrawPoints(parser, canvas, 3, 3, 1, 0, 100);
}
问题在于,在将所有点渲染到Canvas
之后,当我尝试在同一网格中的textbox
中输入一些文本时,存在显着的滞后。我该怎么做才能减少滞后?
答案 0 :(得分:1)
您可以做的是将所有数据绘制到Visual
并使用RenderTargetBitmap
进行渲染。这需要一段时间,但会解决您的性能问题。
private List<Point> _points;
private Size _targetarea;
private void btnGenerate_Click(object sender, RoutedEventArgs e)
{
_targetarea = new Size(500, 500);
_points = GeneratePoints(10000, _targetarea);
TheImage.Source = DrawPoints(_points, _targetarea, 5, 5, 1);
}
private List<Point> GeneratePoints(int count, Size size)
{
Random r = new Random();
return Enumerable.Range(0, count)
.Select(j => new Point(r.NextDouble() * size.Width, r.NextDouble() * size.Height))
.ToList();
}
private static ImageSource DrawPoints(IEnumerable<Point> points, Size size, double radiusX, double radiusY, double thickness)
{
DrawingVisual visual = new DrawingVisual();
using (DrawingContext context = visual.RenderOpen())
{
var fill = new SolidColorBrush(Colors.Yellow);
var stroke = new SolidColorBrush(Colors.Red);
foreach(var center in points)
{
context.DrawEllipse(fill, new Pen(stroke, thickness), center, radiusX, radiusY);
}
}
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
bitmap.Freeze();
return bitmap;
}
要在单击图像时确定最近的数据点,只需使用您用于生成图像的原始数据。
private void TheImage_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point clickPoint = GetCoordinates(e.GetPosition((IInputElement) sender));
Point closestPoint = new Point();
double minSquareDistance = double.MaxValue;
foreach (Point point in _points)
{
double dX = point.X - clickPoint.X;
double dY = point.Y - clickPoint.Y;
double squareDistance = dX * dX * dY * dY;
if (squareDistance < minSquareDistance)
{
minSquareDistance = squareDistance;
closestPoint = point;
}
}
MessageBox.Show($"Clicked near {closestPoint.X:f0}/{closestPoint.Y:f0}");
}
private Point GetCoordinates(Point position)
{
// Here you need to translate Screen-Coordinates to your internal coordinate system
return position;
}
要加快整个过程,请安装WriteableBitmapEx
(NuGet可用)并改为使用此代码:
private static ImageSource DrawPoints(IEnumerable<Point> points, Size size, double radiusX, double radiusY, double thickness)
{
WriteableBitmap bitmap = new WriteableBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32, null);
foreach(var center in points)
{
bitmap.FillEllipse((int)(center.X - radiusX), (int)(center.Y - radiusY), (int)(center.X + radiusX), (int)(center.Y + radiusY), Colors.Yellow);
bitmap.DrawEllipse((int) (center.X - radiusX), (int) (center.Y - radiusY), (int) (center.X + radiusX), (int) (center.Y + radiusY), Colors.Red);
}
bitmap.Freeze();
return bitmap;
}
我无权访问您的其余代码,因此以下代码使用了大量简化和随机数据,例如:我使用的是Image
而不是Canvas
和简单的Point
,而不是您的解析器返回的任何内容。