老师给的一个课题:
用 C# 实现一个路况图,不需要 GIS 那样的,会给出道路的信息(横竖或者 45°这种简单的直线)和红绿灯,还有车辆的实时位置,车最多给十辆吧。要有缩放和拖动功能,1 秒刷一次
各位大佬有什么好的方案吗...
我现在是用 Graphics 来做的,Bitmap 手动做的二级缓存,缩放试过了 graphics 的 ScaleTransform,试过了构造函数直接给个新 size 再 new 一个 bitmap 来,试过了 drawimage 来缩放,但是效率都太低了,太卡了。调了 BitBlt 也还是太慢。
请问各位大佬有好的方案吗?
1
GM 2020-11-06 14:36:56 +08:00
这问题,看得头皮发麻。。。。。
“GIS 那样的”是怎样? “不需要 GIS 那样的”是什么意思? “效率太低”指的是缩放的时候效率低,还是所有时候效率都低? 最后: 缩放为什么会需要 ScaleTransform 、new Bitmap 、drawimage ?计算好比例,直接用 g.drawXxx 画到 buffer 里,然后 BitBlt 出来不就好了吗? |
2
shaderlab 2020-11-06 14:42:04 +08:00
用 Unity3D 呀,也算 C# 开发吧,实现你这个功能太容易了
|
3
iSNN OP @GM GIS 那样就是要和真实地理信息结合,有海拔那些什么乱七八糟的,曲折的。不要那么具体的,地图只是简单的横竖 45°组成。效率低缩放是最严重的,其余也不高,明显感觉卡顿。
缩放直接用 DrawXxx 不是 drawimage 吗? |
4
across 2020-11-06 14:54:13 +08:00
嵌入 OpenGL/DirectX
|
5
xxiu 2020-11-06 14:55:52 +08:00
需要将变化的和不变的独立出来,每次只在不变的上面画变化的,双缓冲,也就是 bitmap 变化异步刷新到界面。
|
6
kanezeng 2020-11-06 14:56:23 +08:00
Unity 吧,2D/3D 都简单。
|
7
MinQ 2020-11-06 14:58:35 +08:00
这是 AGV 的实时监控吧,网上有个开源的 DragCanvas
|
9
MinQ 2020-11-06 15:02:48 +08:00
|
11
GM 2020-11-06 15:24:15 +08:00
你对二级缓存理解错误了,Bitmap 做二级缓存不是这样做的。
感觉你是做成了先画一张大图到 Bitmap 里,然后想通过缩放图片的方式来做缩放,这样当然慢了,奇慢无比。 Bitmap 做二级缓存,是在需要更新画面的时候,不直接往屏幕上 DrawXxx,而是先往缓存 Bitmap 里 DrawXxx,所有东西都 Draw 完后,一句 BitBlt 直接输出到显示屏上,避免了直接在屏幕上各种 Draw 导致的闪烁。 |
12
xdtr 2020-11-06 15:40:44 +08:00
使用 BufferedGraphicsContext 和 BufferedGraphics
|
13
MinQ 2020-11-06 15:42:22 +08:00
@GM 话说这个不需要二级缓冲吧,就建个 WPF 的工程,搞个 Canvas 把车辆和地图上的标识当成组件扔进去,然后建个定时器,更新一下车辆组建的位置就完事了。画界面的破事都让 WPF 后面的 DirectX 处理去,这种量级的界面重绘根本就不需要二级缓冲
|
16
rocbomb 2020-11-06 16:00:08 +08:00
或者 monogame
这个需求用游戏引擎来解决,会非常舒服 |
17
MinQ 2020-11-06 16:11:21 +08:00
@rocbomb 本来用控件就不会有性能问题,这种项目我是做过的,用 Unity 的话还要学一堆 Unity2D 的东西,我个人觉得是犯不着。
|
18
GM 2020-11-06 16:33:52 +08:00
@iSNN
大概是这样: 假设你显示区域大小为 W 、H,缩放系数为 x 需要 new 一个和你目标显示区域一样大小的 bitmap, 然后根据当前缩放比例,往 bitmap 上 draw 各种元素,也就是你说的横竖、斜 45 度的线条。 draw 完后,BitBlt 到显示区域对应的 Graphics 对象中。 完事。 |
19
iSNN OP @GM 您的意思是,重新绘图,比缩放图片要快?我确实没有缩放后再画线,我是一个原图,然后路线啊,红绿灯位置这些固定的画好,然后缩放后再画动态的东西,再 BitBlt
|
20
zhujinliang 2020-11-06 16:43:40 +08:00 via iPhone
肯定先画大图然后缩放效率不行,而且图像会模糊
,应建立跟显示界面大小一样的缓冲区,使用数学计算进行坐标的缩放,根据缩放后的坐标绘制到缓冲区,最后 bitblt 到前台 再不行就看看 SVG 方面有没有现成的东西 |
21
kokutou 2020-11-06 16:51:24 +08:00 via Android
套个 cef 用网页画。。。
其他的手画遇到 hidpi 缩放就跪了啊。。。 |
23
binsys 2020-11-07 09:45:35 +08:00
CefSharp(或 CefGlue) 壳,跑 HTML 版本的 Leaflet openlayers d3 等,在 Leaflet openlayers 上做。
|
24
iSNN OP @MinQ 谢谢大佬的指点...这几天学了 WPF 的东西,图基本上是画出来了。但是遇到了个问题,我是用 Shapes 里面的图形去画的,道路就是 Line,信号灯就是 Ellipse......不过这些东西都会有一些其他属性,但是这些类都是 sealed 密封类不能继承。我现在就是把这些无法用 Shapes 表示的属性写个类来存储放在一个数组里,然后把道路啊信号编上 Name,然后根据 Name 去数组匹配.......比如一个事件的监听,从 sender 得到 Name,然后 for 数组找匹配的对象,在根据对象里的属性显示不同的东西。请问大佬有好的解决方案吗
|
27
iSNN OP @MinQ 我也这样想过...但是那些图形的实现我也是不明白,去 referencesource.microsoft.com 找的代码,发现掉了很多 internal 的东西。那就算了吧,找了下 Dictionary 的效率挺不错的,不用数组了,这样效率应该不慢
|