C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: GraphicsPathの輪郭座標を取得するには?


(過去ログ 90 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■53787 / inTopicNo.1)  GraphicsPathの輪郭座標を取得するには?
  
□投稿者/ enough (1回)-(2010/09/27(Mon) 11:34:10)

分類:[VB.NET/VB2005 以降] 

OS:XP
開発環境:VB2005

いつも拝見させて頂き非常に参考にさせていただいております。

http://bbs.wankuma.com/index.cgi?mode=al2&namber=18137&KLOG=36
以前こちらで質問させて頂いた者ですが、恥ずかしながら未だ出来ずにおります…。

GraphicsPathに複数の矩形や多角形を追加し、その輪郭を構成する座標を取得したいのですが
何か良い方法は無いでしょうか?

輪郭の候補となる座標を取得し、凸包や時計回りに並び替える方法も試してみたのですが
様々な多角形が存在した場合、取得できない座標も出るなどして出来ませんでした。

調べていますと、下記のようなサイトを見つけましたが、gdiplus.dllのGraphicsPathではoutlineメソッド
が存在し、パスの輪郭座標を取得する事ができる様で試してみたのですが、戻り値に座標配列を指定することが
出来ず断念致しました…。
http://msdn.microsoft.com/ja-jp/library/dd296830.aspx


Dim path As New GraphicsPath
path.AddPolygon(polygon1)
path.AddPolygon(rect1)
path.AddPolygon(polygon2)

※追加する多角形の1辺はかならず隣接しています。
※輪郭を構成する座標は時計回りに取得します。

八方塞がりで困ってしまって、再び質問させて頂きました。何か、良い方法は無いものでしょうか。
引用返信 編集キー/
■53791 / inTopicNo.2)  Re[1]: GraphicsPathの輪郭座標を取得するには?
□投稿者/ よねKEN (619回)-(2010/09/27(Mon) 14:28:30)
よねKEN さんの Web サイト
2010/09/27(Mon) 14:35:24 編集(投稿者)
#VBの開発環境が手元になく、vbc.exeで手動コンパイルするのは面倒なのでC#でのコードですm(_ _)m

■No53787 (enough さん) に返信
> 調べていますと、下記のようなサイトを見つけましたが、gdiplus.dllのGraphicsPathではoutlineメソッド
> が存在し、パスの輪郭座標を取得する事ができる様で試してみたのですが、戻り値に座標配列を指定することが
> 出来ず断念致しました…。
> http://msdn.microsoft.com/ja-jp/library/dd296830.aspx

http://stackoverflow.com/questions/1592285/outline-a-path-with-gdi-in-net
のページにgdiplus.dllのOutlineの関数の呼び出し方法があったので試してみました。

以下のような図形に対しては上手く行きました。(立方体を下から見たような図形)

GraphicsPath path = new GraphicsPath();
path.AddPolygon(new PointF[] { new PointF(10F, 30F), new PointF(20F, 20F), new PointF(30F, 30F), new PointF(20F, 40F) });
path.AddPolygon(new PointF[] { new PointF(10F, 20F), new PointF(20F, 10F), new PointF(20F, 20F), new PointF(10F, 30F) });
path.AddPolygon(new PointF[] { new PointF(20F, 10F), new PointF(30F, 20F), new PointF(30F, 30F), new PointF(20F, 20F) });

ですが、同じ図形でもGraphicsPathの構築手順を変えるとうまく行きません。
例えば以下のコードは、上の図形のAddPolygonメソッド呼びだしの1行目と2行目を入れ替えただけですが。
一部の内部の線が消えません。

GraphicsPath path = new GraphicsPath();
path.AddPolygon(new PointF[] { new PointF(10F, 20F), new PointF(20F, 10F), new PointF(20F, 20F), new PointF(10F, 30F) });
path.AddPolygon(new PointF[] { new PointF(10F, 30F), new PointF(20F, 20F), new PointF(30F, 30F), new PointF(20F, 40F) });
path.AddPolygon(new PointF[] { new PointF(20F, 10F), new PointF(30F, 20F), new PointF(30F, 30F), new PointF(20F, 20F) });

上手く行く場合と行かない場合の理由がわからないので、このままでは実用には使えないですが、
何かの参考になればと思います。

-- 実験コード(C#:上手く行った例) --

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Reflection;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport(@"gdiplus.dll")]
        public static extern int GdipWindingModeOutline(HandleRef path, IntPtr matrix, float flatness); 

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            GraphicsPath path = new GraphicsPath();
            path.AddPolygon(new PointF[] { new PointF(10F, 30F), new PointF(20F, 20F), new PointF(30F, 30F), new PointF(20F, 40F) });
            path.AddPolygon(new PointF[] { new PointF(10F, 20F), new PointF(20F, 10F), new PointF(20F, 20F), new PointF(10F, 30F) });
            path.AddPolygon(new PointF[] { new PointF(20F, 10F), new PointF(30F, 20F), new PointF(30F, 30F), new PointF(20F, 20F) });

            this.BackgroundImage = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            Graphics g = Graphics.FromImage(this.BackgroundImage);

            //元図形の確認用 (輪郭を見るときはコメントアウトしてください)
            g.FillPath(Brushes.Blue, path);
            g.DrawPath(Pens.Black, path);

            HandleRef handle = new HandleRef(path, (IntPtr)path.GetType().GetField("nativePath", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(path));
            GdipWindingModeOutline(handle, IntPtr.Zero, 0.25F);

            //輪郭の確認用
            g.DrawPath(Pens.Red, path);

            //点の順番の確認用
            int i = 0;
            foreach (PointF p in path.PathPoints)
            {
                i++;
                g.DrawString(i.ToString(), new Font(this.Font.FontFamily, 7), Brushes.Black, p);
            }
        }
    }
}

---
※GdipWindingModeOutline関数の関数仕様のドキュメントを見つけられないため、
関数の使い方が正しいかどうかについてはわかりませんので、ご注意ください。

引用返信 編集キー/
■53798 / inTopicNo.3)  Re[2]: GraphicsPathの輪郭座標を取得するには?
□投稿者/ enough (3回)-(2010/09/27(Mon) 15:43:32)
よねKEN様

ご返信誠に有難う御座います。
コードまで書いて頂き、色々試させていただくことが出来ました。
しかし、複雑な多角形の組み合わせ等ではご記入の通りうまくいかないんですね…。

path.AddPolygon(New PointF() {New PointF(100.0F, 100.0F), New PointF(200.0F, 100.0F), New PointF(200.0F, 200.0F), New PointF(100.0F, 200.0F)})
path.AddPolygon(New PointF() {New PointF(200.0F, 200.0F), New PointF(150.0F, 300.0F), New PointF(100.0F, 200.0F)})

.NET Frameworkに存在しないメソッドということは、使用してはいけないという事なのでしょうか。
これが実用できればすごくいいんですが…。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -