- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在使用标记时,我很难等待 D3 中的 ChartPlotter 显示自己。当然,我正在尝试绘制 Gazillion 记录(好吧,700,000 条记录)。当只使用一条线时,一切都很好(20 秒左右)。使用标记时,我们说的是 5 分钟。这是 Not Acceptable 。
有什么想法吗?
这是我所做的,下面有解释。
public static string MakeSimplePlot(double[][] xData, double[][] yData, string[] legend, string xAxisTitle, string yAxisTitle, bool[] showLines, bool[] showMarkers)
{
ChartPlotter plotter = new ChartPlotter();
plotter.MainHorizontalAxis = new HorizontalAxis();
plotter.MainVerticalAxis = new VerticalAxis();
HorizontalAxisTitle horizontalAxisTitle = new HorizontalAxisTitle();
horizontalAxisTitle.Content = xAxisTitle;
plotter.AddChild(horizontalAxisTitle);
VerticalAxisTitle verticalAxisTitle = new VerticalAxisTitle();
verticalAxisTitle.Content = yAxisTitle;
plotter.AddChild(verticalAxisTitle);
Color[] plotColors = new Color[13] { Colors.Blue, Colors.Red, Colors.Green, Colors.Chartreuse, Colors.Yellow, Colors.Violet, Colors.Tan, Colors.Silver, Colors.Salmon, Colors.Lime, Colors.Brown, Colors.Chartreuse, Colors.DarkGray };
for (int seriesCounter = 0; seriesCounter < legend.Count(); seriesCounter++)
{
DataFile clearedInputs = ClearExcess(new DataFile(xData[seriesCounter], yData[seriesCounter]));
xData[seriesCounter] = clearedInputs.time;
yData[seriesCounter] = clearedInputs.data;
var xDataSource = new EnumerableDataSource<double>(xData[seriesCounter]);
xDataSource.SetXMapping(x => x);
var yDataSource = new EnumerableDataSource<double>(yData[seriesCounter]);
yDataSource.SetYMapping(x => x);
CompositeDataSource plotSeries = new CompositeDataSource(xDataSource, yDataSource);
CirclePointMarker circlePointMarker = new CirclePointMarker();
circlePointMarker.Fill = new SolidColorBrush(plotColors[seriesCounter]);
circlePointMarker.Pen = new Pen(circlePointMarker.Fill, 0);
circlePointMarker.Size = (showMarkers[seriesCounter] == false) ? 0 : 8;
int lineWidth = (showLines[seriesCounter] == false) ? 0 : 2;
if (showMarkers[seriesCounter] == false)
{
plotter.AddLineGraph(plotSeries, new Pen(circlePointMarker.Fill, lineWidth), new PenDescription("Dummy"));
}
else
{
plotter.AddLineGraph(plotSeries, new Pen(circlePointMarker.Fill, lineWidth), circlePointMarker, new PenDescription("Dummy"));
}
}
UIParameters.plotWindow.mainGrid.Children.Clear();
UIParameters.plotWindow.mainGrid.RowDefinitions.Clear();
UIParameters.plotWindow.mainGrid.Children.Add(plotter);
plotter.Viewport.FitToView();
plotter.LegendVisible = false;
plotter.NewLegendVisible = false;
if (legend.Count() > 1)
{
ShowLegend(legend, plotColors);
}
UIParameters.plotWindow.WindowState = WindowState.Minimized;
UIParameters.plotWindow.WindowState = WindowState.Normal;
string filename = Path.ChangeExtension(Path.GetTempFileName(), "png");
RenderTargetBitmap targetBitmap = new RenderTargetBitmap((int)UIParameters.plotWindow.mainGrid.ActualWidth, (int)UIParameters.plotWindow.mainGrid.ActualHeight, 96d, 96d, PixelFormats.Default);
targetBitmap.Render(UIParameters.plotWindow.mainGrid);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(targetBitmap));
using (var fileStream = File.Open(filename, FileMode.OpenOrCreate))
{
encoder.Save(fileStream);
UIParameters.plotWindow.mainGrid.Clip = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
targetBitmap.Freeze();
if (targetBitmap != null) targetBitmap.Clear();
targetBitmap = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
return filename;
}
解释:
谢谢!
最佳答案
我编写了自己的类来隐藏屏幕外的标记。当屏幕上没有大量标记时,这是一种虚拟化技术,可以将性能提高十倍。它看起来像这样:
using System;
using System.Windows;
using System.Windows.Media;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using Microsoft.Research.DynamicDataDisplay.Common;
namespace Microsoft.Research.DynamicDataDisplay.Charts {
public class FilteredMarkerPointsGraph : MarkerPointsGraph {
public FilteredMarkerPointsGraph()
: base() {
;
}
public FilteredMarkerPointsGraph(IPointDataSource dataSource)
: base(dataSource) {
;
}
protected override void OnRenderCore(DrawingContext dc, RenderState state) {
// base.OnRenderCore
if (DataSource == null) return;
if (Marker == null) return;
var left = Viewport.Visible.Location.X;
var right = Viewport.Visible.Location.X + Viewport.Visible.Size.Width;
var top = Viewport.Visible.Location.Y;
var bottom = Viewport.Visible.Location.Y + Viewport.Visible.Size.Height;
var transform = Plotter2D.Viewport.Transform;
DataRect bounds = DataRect.Empty;
using (IPointEnumerator enumerator = DataSource.GetEnumerator(GetContext())) {
Point point = new Point();
while (enumerator.MoveNext()) {
enumerator.GetCurrent(ref point);
if (point.X >= left && point.X <= right && point.Y >= top && point.Y <= bottom)
{
enumerator.ApplyMappings(Marker);
Point screenPoint = point.DataToScreen(transform);
bounds = DataRect.Union(bounds, point);
Marker.Render(dc, screenPoint);
}
}
}
Viewport2D.SetContentBounds(this, bounds);
}
}
确保在 XAML 中调用 FilteredMarkerPointsGraph 而不是 MarkerPointsGraph!
编辑
我不确定您需要什么带标记的图例,我实际上没有在我的任何图表中使用过图例,但您的解决方案似乎没问题。
重绘剧情其实很容易。
我发现执行此操作的最佳方法是在您的代码后面有一个表示数据源的属性,并将图表的数据源绑定(bind)到该属性。每次更新或重新分配数据源时,让您的代码实现 INotifyPropertyChanged 并调用 OnPropertyChanged。这将强制绘图仪观察绑定(bind)并重新绘制图形。
例子:
EnumerableDataSource<Point> m_d3DataSource;
public EnumerableDataSource<Point> D3DataSource {
get {
return m_d3DataSource;
}
set {
//you can set your mapping inside the set block as well
m_d3DataSource = value;
OnPropertyChanged("D3DataSource");
}
}
protected void OnPropertyChanged(PropertyChangedEventArgs e) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, e);
}
}
protected void OnPropertyChanged(string propertyName) {
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
关于您使用标记的表现。很难准确指出是什么导致了您的表现问题,但我的建议是尝试使用不同的数据源。我一直在使用 EnumerableDataSource 并且它总是非常有效。尝试将您的数据引入单个对象并在您的 set block 中设置映射,如上所示使用:
value.SetYMapping(k => Convert.ToDouble(k.yData));
value.SetXMapping(k => Convert.ToDouble(k.xData));
您唯一需要担心的是 Enumerable 数据源中的映射,D3 应该会为您处理剩下的事情。
关于c# - WPF DynamicDataDisplay - 使用标记缓慢绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13378180/
在搜索 WPF 的开放图表库时,我找到了 DynamicDataDisplay图书馆。 但是我找不到一种方法(可能是由于文档不完善)来格式化轴标签,它们包含基于值的图像。 为什么我需要这个? 我目前正
在使用标记时,我很难等待 D3 中的 ChartPlotter 显示自己。当然,我正在尝试绘制 Gazillion 记录(好吧,700,000 条记录)。当只使用一条线时,一切都很好(20 秒左右)。
在我的 WPF 应用程序中,我有一个 D3 ChartPlotter,我可以在其中绘制 4 个线图。这是 XAML 代码:
使用 WPF(不是 Silverlight)D3,是否可以将字符串放在 Y 轴上?我具体说的是这样一种情况,在这种情况下,我有一个带有状态值的时间线图(假设“高”、“中”和“低”映射为 1、0 和 -
这个问题是关于可用的 DynamicDataDisplay 库的 codeplex . 有没有办法获取当前ViewPort中当前可见的数据。 即我想获取当用户执行 ctrl+鼠标缩放时当前可见的数据。
我想知道如何更改我的 d3 海图仪的日期时间轴的颜色。 我要更改的颜色是两个条形之间的棕色和白色背景色。 如果我这样做: 它只会更改第一个棕色条上方的内容。 是否可以更改这两个条的颜色? 最佳答案 奇
我是一名优秀的程序员,十分优秀!