首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

画图有关问题,所用的点的坐标都挺大,求解决

2014-01-03 
画图问题,所用的点的坐标都挺大,求解决本帖最后由 wang1234587 于 2013-12-31 19:46:18 编辑我现在用的画

画图问题,所用的点的坐标都挺大,求解决
本帖最后由 wang1234587 于 2013-12-31 19:46:18 编辑 我现在用的画图方法就是,在form的paint事件中写代码
大致就是先做一个空的Bitmap,然后用这个bitmap来生成graphics,之后在graphics上画图。已经试验成功。

现在我遇到的问题就是,我要画的图形所用的点是我算出来的点,这些点的坐标都很大,例如
序号纵坐标X(m)横坐标Y(m)
14202295.84336385684.77
24202213.4236385385.36
34201804.84536385180.4
44201813.05636385192.95
54201919.65336385339.69
64202067.89836385543.94
...
这些点还有好多好多,然而bitmap宽和高的最大值也才不过2000吧。。。。

我应该怎么操作才能使:①由于坐标值太大,点数很多,生成的图形都能出现在画布上,(且出现在中央啊,因为点的坐标都很大,从很大才开始的)   ②图形应该涉及的范围很广,一次肯定不能较好的显示出来,最好可以使这个图形能够实现放大,缩小,移动
③默认的坐标原点在左上角,很不方便,怎么使用自己的坐标来画图
当然了,优先解决我第一个问题啊,急急急!
最好两个问题都能解答下。    由于本人小白,超级白,所以恳请解答的时候最好附带代码示例。。

[解决办法]
你是使用位图绘图,这可以获得“永久的输出”(你可以赋值给某个组件的image属性),但在你这个需求下不推荐使用(创建位图需要占用大量内存和操作时间),尤其是还需要缩放的情况(即便用位图,也不会是在Paint事件下)。
首先,你应该在Paint事件的e.graphics中绘图。这一过程不要通过创建位图实现。

例如:
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillEllipse(new SolidBrush(Color.Red), 100, 100, 3, 3);
        }
这相当于在Paint事件时将绘图绘制在了窗口画布上(而不是位图上)。当然,这并不“永久”。绘制在窗口上的图形随时会被擦除,但擦除时Paint事件会被再次触发,上面的代码会被再次执行,因此图像看上去像是永久的。

由于每次窗口被擦除时,并不是所有区域都需要重绘。这有个“脏矩形”的概念。每次Paint事件的触发都是因为出现了被擦除的矩形。e.ClipRectangle就是脏矩形。
画点事实上是画圆,它有一个矩形的区域。你可以将每个点的矩形区域与脏矩形比较,发现有相交的部分,再执行具体的画点操作。
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            Rectangle rect=new Rectangle(100,100,3,3);
            if (e.ClipRectangle.IntersectsWith(rect))
            {
                e.Graphics.FillEllipse(new SolidBrush(Color.Red), rect);
            }
使用上面的代码,无论你的点有多少,你都只会绘制窗口可见区域内无效矩形内的部分。这就解决了你第一个问题——范围和效率。

关于第二个问题:
显然,如果在Paint里编写绘图语句,那么它所使用的坐标和位置都可以是相对的。
你定义一个左上角坐标pointLT 
再定义一个缩放比k,使用逻辑控制这两个值,然后刷新(Refresh()方法。
绘图里添加对坐标和区域缩放和平移的代码。

下面的代码是相对完整的,满足你需求的代码:
 
        Point pointLT = new Point(0, -0);
        Double k = 1;
        private void Form1_Paint(object sender, PaintEventArgs e)
        {

            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            Point[] points = new Point[3] { new Point(100, 100), new Point(200, 100), new Point(30, 30) };
            int d = 3;
            foreach (Point point in points)
            {
                Rectangle rect = new Rectangle((int)((point.X + pointLT.X) * k - (d - d * k) / 2), (int)((point.Y + pointLT.Y) * k - (d - d * k) / 2), d, d);
                if (e.ClipRectangle.IntersectsWith(rect))
                {
                    e.Graphics.FillEllipse(new SolidBrush(Color.Red), rect);
                }
            }
        }

注意图形平移缩放的算法
(int)((point.X + pointLT.X) * k - (d - d * k) / 2)
1.先平移后缩放
2.不对点的直径进行缩放
3.减去因为点的直径未被缩放导致的点的中心点的偏移量(d - d * k) / 2

显然,向左移动就是
pointLT.X = pointLT.X - 10;


this.Refresh();
放大一倍就是
k=k*2;
this.Refresh();

你可以再补充向四个方向移动以及缩小的代码。

[解决办法]

引用:
Quote: 引用:

十分感谢你的耐心回答,我觉得有很大的帮助,然后我参照你的代码自己写了下,不知道为什么会错,图形显示不出来啊,你看看怎么回事
 PointF pointLT = new PointF(0, -0);
        Double k = 1;

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            int dd = 7;
            int ed = 2;
            int d = 3;
            double[] x1 = new double[9] {4202295.843,4202213.42,4201804.845,4201813.056,4201919.653,4202067.898,4202185.779,4202281.985,4202351.197};
            double[] y1 = new double[9] {36385684.77,36385385.36,36385180.4,36385192.95,36385339.69,36385543.94,36385706.21,36385838.51,36385934.29};
            PointF pointLT = new PointF((float)(y1.Min()-10), (float)(-(x1.Min()+10)));
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            PointF[] xPt = new PointF[dd + ed];
            PointF[] yPt = new PointF[dd + ed];
            PointF[] Pt = new PointF[dd + ed];
            Rectangle[] rect = new Rectangle[dd + ed];
            for (int i = 0; i < (dd + ed); i++)
            {
                Pt[i] = new PointF((float)y1[i], -(float)x1[i]);

                rect[i] = new Rectangle((int)((Pt[i].X + pointLT.X) * k - (d - d * k) / 2), (int)((Pt[i].Y + pointLT.Y) * k - (d - d * k) / 2), d, d);
                if (e.ClipRectangle.IntersectsWith(rect[i]))
                {
                    e.Graphics.FillEllipse(new SolidBrush(Color.Red), rect[i]);

                }
            }
            
        }

x1,y1数组里存放的就是我要显示的点,为什么显示不出来啊?谢谢了


k=1太大了。你屏幕也就1000左右的矩形。你的坐标都是千万级别的。
对于你的这个图,k=0.0001左右也许才能看到点。
另外,我不知道你的点有多密。
如果你要制作类似地图的效果,请注意,不是所有的点都会在某一尺度下全部显示。
你缩小k的值的时候,也许一些点就应该隐藏掉。让你的图在不同尺度下显示不同的内容。
一些点应该设计为在k足够大时显示。
[解决办法]
引用:
Quote: 引用:

类似于地图一样,往小了转换,或者平移转换

往小了转换不行啊,因为点与点之间有的才相差10+,怎么弄

那就平移转换吧,获取所有点中的x最小,y最小以及x最大和y最大值,然后将屏幕的坐标转换为你现在得到的这么坐标范围

热点排行