SilverLight绘图(求高手解答)

heren5201314 2011-04-01 08:20:28
我想画一个拥有很多条数据的波形图,但是要在屏幕中全部展示出来,各位有什么好的方法没?我个人想法是像素减小,画倒是能画,就是太卡了。页面根本运行不了,一运行就假死! 线条可能要画几万条!
如图:
各位如果有什么更好更有效率的方法请指教。先谢谢了,然后送分!
...全文
231 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
海涵德 2011-04-05
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 heren5201314 的回复:]
SilvLight绘图方面除了用GPU加速还有么有其他的方法可以提高绘图的性能,向各位老大求教!希望各位大大们多帮帮忙!
[/Quote]没有那么复杂,按照6楼的方法做就可以了,直接使用line也可以,我试过,silverlight画10万条线没有问题,不会卡的,6楼画2万条线仅仅使用50毫秒是正常的。
写了一段代码送给你,画1000条线,可以看得出来,画10000条线就是一片了,你可以自己调整线数。

<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White" >
<Button x:Name="button_draw_line" Content="画线" Height="20" Width="100" VerticalAlignment="Top" Click="button_draw_line_Click" ></Button>

</Grid>
</UserControl>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
private Random r=new Random();
private SolidColorBrush s = new SolidColorBrush(Colors.Blue);
private void draw_random_line(int line_count)
{
Line l;
for (int i = 0; i < line_count; i++)
{
l = new Line();
l.X1 = r.NextDouble() * LayoutRoot.ActualWidth ;
l.Y1 = r.NextDouble() * LayoutRoot.ActualHeight;
l.X2 = r.NextDouble() * LayoutRoot.ActualWidth;
l.Y2 = r.NextDouble() * LayoutRoot.ActualHeight;
l.Stroke = s;
l.StrokeThickness = 1;
LayoutRoot.Children.Add(l);
}
}

public MainPage()
{
InitializeComponent();
}

private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{

}

private void button_draw_line_Click(object sender, RoutedEventArgs e)
{
draw_random_line(1000);
}
}
}
assky124 2011-04-03
  • 打赏
  • 举报
回复
不知道先绘制到内存中,然后再绘制图像可不可行
hhddzz 2011-04-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 heren5201314 的回复:]
有没有Silverlight的高性能绘图,我对WPF不是很懂。哎~~~
[/Quote]
大部分WPF和SL代码是通用的
我想SL应该是支持StreamGeometry的
heren5201314 2011-04-02
  • 打赏
  • 举报
回复
有没有Silverlight的高性能绘图,我对WPF不是很懂。哎~~~
heren5201314 2011-04-02
  • 打赏
  • 举报
回复
SilvLight绘图方面除了用GPU加速还有么有其他的方法可以提高绘图的性能,向各位老大求教!希望各位大大们多帮帮忙!
无趣 2011-04-01
  • 打赏
  • 举报
回复
根据绘图区域大小,适当对数据进行采样,没必要绘制那么多。

比如 图宽为100,数据为20000点,你只需从中取出200点进行绘制就可以了。

采样方式可使用等间隔采样等算法。
heren5201314 2011-04-01
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lujunql 的回复:]
使用路径方式绘图,Path ,Geometry ,绘制完成后再显示
类似以下方式(LineGeometry 对象都添加到Path 中,最后在将Path对象添加到Canvas )试试吧!

<Canvas Width="200" Height="200">
<Path Stroke="Black" StrokeThickness="1" >
<Path.Data>
<Line……
[/Quote]
我是按照你的方法来做的,图是画出来了,但是实在太卡,有时候运行都直接假死。因为数据太多。UI无法呈现~
lujunql 2011-04-01
  • 打赏
  • 举报
回复
使用路径方式绘图,Path ,Geometry ,绘制完成后再显示
类似以下方式(LineGeometry 对象都添加到Path 中,最后在将Path对象添加到Canvas )试试吧!

<Canvas Width="200" Height="200">
<Path Stroke="Black" StrokeThickness="1" >
<Path.Data>
<LineGeometry StartPoint="10,20" EndPoint="100,130" />
</Path.Data>
</Path>
</Canvas>

heren5201314 2011-04-01
  • 打赏
  • 举报
回复
来人解答啊!
hhddzz 2011-04-01
  • 打赏
  • 举报
回复
我觉得我越来越搞不懂WPF的绘图系统了
上面的代码,如果直接用
drawingContext.DrawLine(pen,p1,p2)
来画卡得要死

书上不是说这样就可以省去Drawing对象的开销更快吗

还有,如果用DrawingVisual来画,重写GetVisualChild和VisualChildCount的话
一样卡
Imports System.Diagnostics
Public Class Lines : Inherits FrameworkElement
Dim gVisual As New DrawingVisual
Public Sub Refresh()
'MyBase.OnRender(drawingContext)
Dim r As New Random
Const LineCount As Integer = 20000
Dim MidlLine As Integer = ActualHeight / 2
Dim p As New Pen(Brushes.Green, 1)
Dim watcher As New Stopwatch
Dim p1 As New Point, p2 As New Point
watcher.Start()
Dim g As Windows.Media.DrawingContext = gVisual.RenderOpen
For i As Single = 0 To LineCount
Dim Lenght As Integer = r.Next(0, ActualHeight)
p1.X = i : p1.Y = MidlLine - Lenght / 2
p2.X = i : p2.Y = MidlLine + Lenght / 2
g.DrawLine(p, p1, p2)
Next

g.Close()
Me.InvalidateVisual()
watcher.Stop()
MsgBox(watcher.ElapsedMilliseconds)
End Sub
Protected Overrides Function GetVisualChild(index As Integer) As System.Windows.Media.Visual
If index = 0 Then Return gVisual
Throw New ArgumentOutOfRangeException
End Function
Protected Overrides ReadOnly Property VisualChildrenCount As Integer
Get
Return 1
End Get
End Property

Public Sub New()
AddVisualChild(gVisual)
AddLogicalChild(gVisual)
End Sub
hhddzz 2011-04-01
  • 打赏
  • 举报
回复
LZ你试试这个
WPF的代码,我这里只要50ms左右
Imports System.Diagnostics
Public Class Lines_Geometry : Inherits FrameworkElement
Protected Overrides Sub OnRender(drawingContext As System.Windows.Media.DrawingContext)
'# 一些测试用数据
Dim r As New Random
Const LineCount As Integer = 20000
Dim watcher As New Stopwatch

'# 绘图相关对象
Dim MidlLine As Integer = ActualHeight / 2
Dim p As New Pen(Brushes.Green, 1)
Dim p1 As New Point, p2 As New Point
Dim gStream As New StreamGeometry

'# 绘制到StreamGeometry
watcher.Start()
Dim g As Windows.Media.StreamGeometryContext = gStream.Open
For i As Integer = 0 To LineCount
Dim Lenght As Integer = r.Next(0, ActualHeight)
p1.X = i : p1.Y = MidlLine - Lenght / 2
p2.X = i : p2.Y = MidlLine + Lenght / 2
g.BeginFigure(p1, True, False)
g.LineTo(p2, True, False)
Next
g.Close()

'# 绘制到FrameWorkElement
drawingContext.DrawDrawing(New GeometryDrawing(Brushes.Green, New Pen(Brushes.Green, 1), gStream))

'# 显示消耗时间
watcher.Stop()
MainForm.Title = watcher.ElapsedMilliseconds
End Sub
End Class

我这里数据是随机产生,如果你的数据事先就已经准备好了,应该还要快一些
heren5201314 2011-04-01
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 funniest 的回复:]
根据绘图区域大小,适当对数据进行采样,没必要绘制那么多。

比如 图宽为100,数据为20000点,你只需从中取出200点进行绘制就可以了。

采样方式可使用等间隔采样等算法。
[/Quote]
那样数据就不准确了啊,图就起伏,菱角度就看不太出来了!

8,735

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧