Home > Study > てけとーにマウスで引いたギザギザな線を微妙にきれいな曲線で描画したい

てけとーにマウスで引いたギザギザな線を微妙にきれいな曲線で描画したい

image

経済学で使う無差別曲線をてきとーに書けるソフトがほしいけど、そんな都合のいいものはないらしい。んだらば自分で作るしかないんだけど、てけとーにマウスで引いたギザギザな線が微妙にきれいなるようにするのってどうすりゃいいんだろうか。さっぱり訳わかめ。

image image

とりあえず、サンプルを作ってみた。左みたいに適当に書くと、右のようにちょっときれいになる。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Drawing.Drawing2D;

namespace SampleBezierDraw
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool isDragging = false;

        List<Point> bezierPoints = new List<Point>();

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDragging = true;

                bezierPoints.Clear();
                bezierPoints.Add(e.Location);
            }
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                bezierPoints.Add(e.Location);

                using (Pen pen = new Pen(Color.Black, 3.0f))
                using (Bitmap b = new Bitmap(ClientRectangle.Width, ClientRectangle.Height))
                using (Graphics g1 = Graphics.FromImage(b))
                using (Graphics g2 = Graphics.FromHwnd(Handle))
                {
                    g1.FillRectangle(SystemBrushes.Window, ClientRectangle);
                    g1.DrawLines(pen, bezierPoints.ToArray());

                    g2.DrawImage(b, 0, 0);
                }
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (isDragging && e.Button == MouseButtons.Left)
            {
                bezierPoints.Add(e.Location);

                using (Graphics g = Graphics.FromHwnd(Handle))
                using (Pen pen = new Pen(Color.Black, 3.0f))
                {
                    g.FillRectangle(SystemBrushes.Window, ClientRectangle);

                    if (bezierPoints.Count <= 0)
                    {
                        /* Do nothing */
                    }
                    else if (bezierPoints.Count <= 3)
                    {
                        g.DrawLines(pen, bezierPoints.ToArray());
                    }
                    else
                    {
                        /* 全体の20%(または20個)まで点を間引く */
                        int LIMIT_OF_POINT_COUNT = Math.Max(20, bezierPoints.Count * 20 / 100);
                        while (bezierPoints.Count > LIMIT_OF_POINT_COUNT)
                        {
                            List<Point> p = new List<Point>();
                            p.Add(bezierPoints[0]); /* 始点を追加 */

                            for (int i = 2; i <= bezierPoints.Count - 2; i += 2)
                            {
                                p.Add(new Point(
                                    (bezierPoints[i - 1].X + bezierPoints[i].X) / 2,
                                    (bezierPoints[i - 1].Y + bezierPoints[i].Y) / 2));
                            }
                            p.Add(bezierPoints[bezierPoints.Count - 1]);

                            bezierPoints = p; /* 終点を追加 */
                        }

                        g.SmoothingMode = SmoothingMode.HighQuality;
                        g.DrawCurve(pen, bezierPoints.ToArray());
                    }
                }

                isDragging = false;
            }
        }
    }
}

速さとかまったく度外視。

List<> とか、やめれ、自分。

わたしゃ文系人間なので、こういう時ってちゃんと数学的知識がある人がうらやましくなるなぁ…。こういうの詳しい方、ご教授くださいorz

PS:

最初、Bezier曲線で書こうと思ったけど、なんかエラーでた。

DrawCurve にしたら直ったんだけど、DrawBziers の引数って 4n+3 個のPoint配列じゃないとだめとか?多すぎるとあかんのかなぁー

ベジェ曲線(ベジェきょくせん、Bézier Curve)またはベジエ曲線とは、N 個の制御点から得られる N – 1 次曲線である。

from ベジェ曲線 – Wikipedia

だいたい、これを読んで(@@?な時点でダメなんだとも思うんだけどw

VS2008 .NET 3.5

blog comments powered by Disqus

Home > Study > てけとーにマウスで引いたギザギザな線を微妙にきれいな曲線で描画したい

My Friend Feed

http://friendfeed.com/daruyanagi

Google Analyticator

608
 Unique Visitors 
 (1 day) 
Powered By Google Analytics

Return to page top