求教 C# 绘图问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
iSNN
V2EX    程序员

求教 C# 绘图问题

  •  
  • /li>
  •   iSNN 2020-11-06 14:28:16 +08:00 2480 次点击
    这是一个创建于 1867 天前的主题,其中的信息可能已经有所发展或是发生改变。

    老师给的一个课题:

    用 C# 实现一个路况图,不需要 GIS 那样的,会给出道路的信息(横竖或者 45°这种简单的直线)和红绿灯,还有车辆的实时位置,车最多给十辆吧。要有缩放和拖动功能,1 秒刷一次

    各位大佬有什么好的方案吗...

    我现在是用 Graphics 来做的,Bitmap 手动做的二级缓存,缩放试过了 graphics 的 ScaleTransform,试过了构造函数直接给个新 size 再 new 一个 bitmap 来,试过了 drawimage 来缩放,但是效率都太低了,太卡了。调了 BitBlt 也还是太慢。

    请问各位大佬有好的方案吗?

    29 条回复    2020-11-13 13:59:34 +08:00
    GM
        1
    GM  
       2020-11-06 14:36:56 +08:00
    这问题,看得头皮发麻。。。。。


    “GIS 那样的”是怎样?

    “不需要 GIS 那样的”是什么意思?

    “效率太低”指的是缩放的时候效率低,还是所有时候效率都低?


    最后:
    缩放为什么会需要 ScaleTransform 、new Bitmap 、drawimage ?计算好比例,直接用 g.drawXxx 画到 buffer 里,然后 BitBlt 出来不就好了吗?
    shaderlab
        2
    shaderlab  
       2020-11-06 14:42:04 +08:00
    用 Unity3D 呀,也算 C# 开发吧,实现你这个功能太容易了
    iSNN
        3
    iSNN  
    OP
       2020-11-06 14:50:07 +08:00
    @GM GIS 那样就是要和真实地理信息结合,有海拔那些什么乱七八糟的,曲折的。不要那么具体的,地图只是简单的横竖 45°组成。效率低缩放是最严重的,其余也不高,明显感觉卡顿。
    缩放直接用 DrawXxx 不是 drawimage 吗?
    across
        4
    across  
       2020-11-06 14:54:13 +08:00
    嵌入 OpenGL/DirectX
    xxiu
        5
    xxiu  
       2020-11-06 14:55:52 +08:00
    需要将变化的和不变的独立出来,每次只在不变的上面画变化的,双缓冲,也就是 bitmap 变化异步刷新到界面。
    kanezeng
        6
    kanezeng  
       2020-11-06 14:56:23 +08:00
    Unity 吧,2D/3D 都简单。
    MinQ
        7
    MinQ  
       2020-11-06 14:58:35 +08:00
    这是 AGV 的实时监控吧,网上有个开源的 DragCanvas
    MinQ
        8
    MinQ  
       2020-11-06 14:58:56 +08:00
    @kanezeng 用 Unity 就整复杂了
    iSNN
        10
    iSNN  
    OP
       2020-11-06 15:17:52 +08:00
    @MinQ 感谢,我去看看这个。你这么一说 AGV 实时监控我开始怀疑是一个商业课题,被迫免费劳动力 2333
    GM
        11
    GM  
       2020-11-06 15:24:15 +08:00
    你对二级缓存理解错误了,Bitmap 做二级缓存不是这样做的。

    感觉你是做成了先画一张大图到 Bitmap 里,然后想通过缩放图片的方式来做缩放,这样当然慢了,奇慢无比。

    Bitmap 做二级缓存,是在需要更新画面的时候,不直接往屏幕上 DrawXxx,而是先往缓存 Bitmap 里 DrawXxx,所有东西都 Draw 完后,一句 BitBlt 直接输出到显示屏上,避免了直接在屏幕上各种 Draw 导致的闪烁。
    xdtr
        12
    xdtr  
       2020-11-06 15:40:44 +08:00
    使用 BufferedGraphicsContext 和 BufferedGraphics
    MinQ
        13
    MinQ  
       2020-11-06 15:42:22 +08:00
    @GM 话说这个不需要二级缓冲吧,就建个 WPF 的工程,搞个 Canvas 把车辆和地图上的标识当成组件扔进去,然后建个定时器,更新一下车辆组建的位置就完事了。画界面的破事都让 WPF 后面的 DirectX 处理去,这种量级的界面重绘根本就不需要二级缓冲
    iSNN
        14
    iSNN  
    OP
       2020-11-06 15:53:03 +08:00
    @GM 那请问怎么缩放呢?都 BitBlt 我不会直接往屏幕上 Draw 的......
    rocbomb
        15
    rocbomb  
       2020-11-06 15:57:16 +08:00
    @MinQ 我觉得反倒简单了
    这种需求,用 Unity 的 2d 一下午就撸出来了,而且绝对不会有性能问题
    rocbomb
        16
    rocbomb  
       2020-11-06 16:00:08 +08:00
    或者 monogame
    这个需求用游戏引擎来解决,会非常舒服
    MinQ
        17
    MinQ  
       2020-11-06 16:11:21 +08:00
    @rocbomb 本来用控件就不会有性能问题,这种项目我是做过的,用 Unity 的话还要学一堆 Unity2D 的东西,我个人觉得是犯不着。
    GM
        18
    GM  
       2020-11-06 16:33:52 +08:00
    @iSNN
    大概是这样:
    假设你显示区域大小为 W 、H,缩放系数为 x
    需要 new 一个和你目标显示区域一样大小的 bitmap,
    然后根据当前缩放比例,往 bitmap 上 draw 各种元素,也就是你说的横竖、斜 45 度的线条。
    draw 完后,BitBlt 到显示区域对应的 Graphics 对象中。
    完事。
    iSNN
        19
    iSNN  
    OP
       2020-11-06 16:37:13 +08:00
    @GM 您的意思是,重新绘图,比缩放图片要快?我确实没有缩放后再画线,我是一个原图,然后路线啊,红绿灯位置这些固定的画好,然后缩放后再画动态的东西,再 BitBlt
    zhujinliang
        20
    zhujinliang  
       2020-11-06 16:43:40 +08:00 via iPhone
    肯定先画大图然后缩放效率不行,而且图像会模糊
    ,应建立跟显示界面大小一样的缓冲区,使用数学计算进行坐标的缩放,根据缩放后的坐标绘制到缓冲区,最后 bitblt 到前台
    再不行就看看 SVG 方面有没有现成的东西
    kokutou
        21
    kokutou  
       2020-11-06 16:51:24 +08:00 via Android
    套个 cef 用网页画。。。

    其他的手画遇到 hidpi 缩放就跪了啊。。。
    GM
        22
    GM  
       2020-11-06 17:09:07 +08:00
    @iSNN 那当然了,图片缩放很慢的,慢得惨无人寰。想要快,事先准备好各种比例的图片,直接 draw 上去,别缩放。
    binsys
        23
    binsys  
       2020-11-07 09:45:35 +08:00
    CefSharp(或 CefGlue) 壳,跑 HTML 版本的 Leaflet openlayers d3 等,在 Leaflet openlayers 上做。
    iSNN
        24
    iSNN  
    OP
       2020-11-13 09:48:34 +08:00
    @MinQ 谢谢大佬的指点...这几天学了 WPF 的东西,图基本上是画出来了。但是遇到了个问题,我是用 Shapes 里面的图形去画的,道路就是 Line,信号灯就是 Ellipse......不过这些东西都会有一些其他属性,但是这些类都是 sealed 密封类不能继承。我现在就是把这些无法用 Shapes 表示的属性写个类来存储放在一个数组里,然后把道路啊信号编上 Name,然后根据 Name 去数组匹配.......比如一个事件的监听,从 sender 得到 Name,然后 for 数组找匹配的对象,在根据对象里的属性显示不同的东西。请问大佬有好的解决方案吗
    MinQ
        25
    MinQ  
       2020-11-13 12:15:32 +08:00 via Android
    @iSNN 写个新类继承 shape 呗,把想要的属性加上
    MinQ
        26
    MinQ  
       2020-11-13 12:15:47 +08:00 via Android
    @iSNN 控件同理
    iSNN
        27
    iSNN  
    OP
       2020-11-13 13:36:29 +08:00
    @MinQ 我也这样想过...但是那些图形的实现我也是不明白,去 referencesource.microsoft.com 找的代码,发现掉了很多 internal 的东西。那就算了吧,找了下 Dictionary 的效率挺不错的,不用数组了,这样效率应该不慢
    MinQ
        28
    MinQ  
       2020-11-13 13:58:47 +08:00 via Android
    @iSNN extends 下来以后会直接把父类的方法都继承了啊,根本不需要再写一遍
    MinQ
        29
    MinQ  
       2020-11-13 13:59:34 +08:00 via Android
    @MinQ 我 github 上有个 AGVMonitor,你参考一下吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     906 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 22:03 PVG 06:03 LAX 14:03 JFK 17:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86