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

わんくま同盟

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

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

■103796 / 7階層)  Visual Basicで簡易CADを作成
□投稿者/ 魔界の仮面弁士 (3874回)-(2025/07/31(Thu) 10:48:38)
No103795 (shiro さん) に返信
> ダブルクリックでの画像消去コード有難うございました。

先の例では、polygons.RemoveAt によって、選択中の四角形を削除したわけですよね。
後はその応用です。

たとえば、polygons(i) と polygons(j) のインデックスを入れ替えれば、
重なり合った図形の上下関係を入れ替える(手前に表示、奥に移動)実装を作れます。

polygons(n).Rect の座標を差し替えるコードを書けば、
選択中の四角形をドラッグ移動で別の場所に再配置することもできるでしょう。


> 参考のListは「polygon」となっています。
> これですと、グリッドの交点を掴むと、スパン幅(1m)に壁が配置されてしまいます。

グリッドには実線と破線がありますが、スナップ先はどちらの交点でも良いのですかね。

グリッドの実線最外周部にオブジェクトを配置すると、柱や壁の厚みが
方眼の外にはみ出る形になりそうですが…再外周部には柱を建てない方が良いのかな。


> 参考のListは「polygon」となっています。
Private polygons As New List(Of Polygon)
のことですね。VB は大文字小文字を区別しませんが、意識して使い分けましょう。

クラス名は通常、先頭を大文字で表記します。
Private 変数やローカル変数は先頭小文字にすることが多いです。


さて。参考コードでは描こうとしているのが「四角形」であることから、座標情報の保持のために
『Recangle 構造体をメンバーに持つ Polygon クラス』というオブジェクトを作っておられます。

まぁ、Polygon は本来「多角形」を表す単語ですし、
Recangle も四角形ではなく「矩形(長方形)」を表すものですから、
役割と名前に軽微なズレがあるのですが……それはさておき。


> しかし、今度は次の壁を描こうとすると前のが消えてしまいます。
「次の壁だけ」を描こうとするからいけないのです。

先の回答で、私は
>> Paint イベントでは「方眼グリッドと、4 本の柱と、3 枚の壁」を描画します
と書いています。配置しようとしている壁だけを描くのではありません。

各回の Paint イベントでは、
『今から配置しようとしているオブジェクトだけ』を描画するのではなく
『今までに配置してきたオブジェクトすべて』を毎回再描画することになります。

そもそも Invalidate メソッドは、これまでの描画結果をまっさらに無効化して、
最初から描画しなおすことを求めるメソッドです。当然、以前の描画内容は毎回クリアされます。

もしもそうした全描画が手間なのであれば、前回の回答のように、
>> 永続的に表示し続けたい画像を Bitmap として用意する方法
を併用することで、差分だけを描画する仕組みにすることもできます。


> 私のwallはグリッドの2点の交点を結んで、線分の幅で厚さを表そうとしています。
> これですと実際のCADに近くなり使いやすいです。
> その場合、Pointになるのではと思い、下記のとおり簡単なListを作ってみました。
いやいや。単に宣言しただけで、一切使われていませんよね。その List 変数…。


御存知の通り、Point が表す情報は「点」だけです。

そして List(Of Point) で表せる情報とは、「0個以上の点」の集合です。
保持される点は 2 個かもしれないし 3 個かも知れません。

しかし Wall を管理するなら、「点A、点B、厚み」の 3 情報が必要ではありませんか?
厚みが固定なら 2 情報ですかね。「左上点、右下点、壁の回転角」などの持ち方もできますが。

もしも壁が 3 箇所に配置されていたら、三枚分の座標情報が必要になります。

柱を配置している座標と、壁を配置する座標はそれぞれ別物なのですから
 Private pointList As New List(Of Point)
という変数だけでは、管理情報が曖昧になってしまいます。

そこで、それぞれの位置関係を分かりやすくするためにも、
Point の集合で管理するのではなく、Visual Basic 中学校のサンプルの考え方に倣って
壁を管理するための「Wall クラス」
柱を管理するための「Pillar クラス」
など、配置オブジェクトごとの管理クラスを用意することをおすすめします。


Wall(壁) クラスにせよ、Pillar(柱) クラスにせよ、
Dot(点) クラスにせよ、Line(線分) クラスにせよ、
Polygon(多角形) クラスにせよ、Ellipse(楕円) クラスにせよ、
それぞれに「自身の位置やサイズを表すためのプロパティ」を持たせます。

そして、柱や壁といったそれぞれのオブジェクトを List(Of ) コレクションなどで管理します。

個々のオブジェクトには、元サンプルのように IsSelected プロパティを設けても良いでしょうし、
BackColor プロパティや SelectionColor プロパティなどを追加することもできるでしょう。


もちろん、描画対象のオブジェクトによって、保持するべき情報は異なります。
壁なら「点A、点B、厚み」の 3 情報で管理されますが、
柱なら、「中心点、柱の太さ」の 2 情報ですかね。
円柱とか角柱といった追加情報を与えることもできそう。

それぞれを List(Of Wall) や List(Of Pillar) といった個別のコレクションで管理することもできますが、
すべての描画オブジェクトを束ねられるよう、Interface あるいは MustInherit を用いて
ポリモーフィズムな実装にするという選択肢もあります。


普段使う Form1 には、Label や TextBox や Button や PictureBox といった、
様々なオブジェクトを配置できますよね。これらのコントロールは、すべて Control クラスを
継承したクラスとして実装されており、Me.Controls のコレクションに束ねられています。



それと同様、この CAD アプリでも描画オブジェクトをポリモーフィズムな実装にしておけば、
Wall や Pillar などを、単一のコレクション上に束ねることができます。

ポリモーフィズムの例として…たとえば、全ての描画オブジェクトの継承元となる
 Public MustInherit Class DrawingObjectBase
  Public Property IsSelected As Boolean
  Public MustOverride Sub Draw(g As Graphics)
 End Class
といったベースクラスを用意してみます。

Form1 上のコレクションも、As New List(Of Polygon) ではなく
 Private drawItems As New List(Of DrawingObjectBase)()
のように、ベースクラスのコレクションに変更します。

Polygon や Wall や Pillar は、このDrawingObjectBase を継承させます。
たとえば Polygon であればこう。

 Public Class Polygon
  Inherits DrawingObjectBase

  Public Property Rect As Rectangle
  Public Overrides Sub Draw(g As Graphics)
   g.FillRectangle(If(IsSelected, Brushes.Yellow, Brushes.Cyan), Rect)
   g.DrawRectangle(Pens.Blue, Rect)
  End Sub
 End Class

このようにしておくと、List(Of )に追加したアイテムのインスタンスが
「壁」であれ「柱」であれ「矩形」であれ、PictureBox1 の Paint イベントの描画処理は

 For Each drawItem In drawItems
  drawItem.Draw(e.Graphics)
 Next

だけで済みます。コレクションにAdd したオブジェクトが柱であれ壁であれ矩形であれ、
PictureBox1_Paint 側ではそれらを区別せず、単に Draw メソッドを呼ぶだけで済むので、
配置オブジェクトの種類を増やすことも容易になります。



> Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
> Dim pen As New Pen(Color.Black, 1)
> Dim rubberPen As New Pen(Color.Blue, 5)
Pen は IDisposable なオブジェクトです。
繰り返しになりますが、自身で生成するのであれば、Using ステートメントで囲む癖をつけましょう。

とはいえ、これらの Pen は何度も使い続ける物ですから、描画のたびにその都度生成しなおすのではなく、
Form の起動時に一度だけ生成し、それを Private 変数で保持して使いまわすという方法でも構いません。
Visual Basic 中学校のサンプルで言うところの「Private selectPen As Pen」のように。

※本来は、フォーム終了時に selectPen も Dispose するコードを書くのが望ましいですが、
 Form1 終了時にはアプリ自体が終了して、自動的に解放されるため、先のサンプルでは省略されています。
編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[6]: Visual Basicで簡易CADを作成 /shiro →Re[8]: Visual Basicで簡易CADを作成 /shiro
 
上記関連ツリー

Visual Basicで簡易CADを作成 / shiro (25/07/25(Fri) 20:50) #103783
Re[1]: Visual Basicで簡易CADを作成 / KOZ (25/07/27(Sun) 14:35) #103784
  └ Re[2]: Visual Basicで簡易CADを作成 / shiro (25/07/28(Mon) 20:17) #103785
    ├ Re[3]: Visual Basicで簡易CADを作成 / kiku (25/07/29(Tue) 08:49) #103786
    └ Re[3]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/29(Tue) 14:06) #103791
      └ Re[4]: Visual Basicで簡易CADを作成 / shiro (25/07/30(Wed) 12:22) #103792
        └ Re[5]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/30(Wed) 15:46) #103794
          └ Re[6]: Visual Basicで簡易CADを作成 / shiro (25/07/31(Thu) 07:34) #103795
            └ Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/31(Thu) 10:48) #103796 ←Now
              └ Re[8]: Visual Basicで簡易CADを作成 / shiro (25/08/01(Fri) 06:15) #103797
                ├ Re[9]: Visual Basicで簡易CADを作成 / kiku (25/08/01(Fri) 08:47) #103798
                │└ Re[10]: Visual Basicで簡易CADを作成 / shiro (25/08/02(Sat) 03:40) #103803
                └ Re[9]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/01(Fri) 10:46) #103800
                  ├ Re[10]: Visual Basicで簡易CADを作成 / kiku (25/08/01(Fri) 10:50) #103801
                  └ Re[10]: Visual Basicで簡易CADを作成 / shiro (25/08/02(Sat) 03:38) #103802
                    └ Re[11]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/03(Sun) 11:50) #103805
                      └ Re[12]: Visual Basicで簡易CADを作成 / shiro (25/08/04(Mon) 05:10) #103806
                        └ Re[13]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/04(Mon) 11:36) #103808
                          └ Re[14]: Visual Basicで簡易CADを作成 / shiro (25/08/04(Mon) 18:59) #103811
                            └ Re[15]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/04(Mon) 19:43) #103812
                              └ Re[16]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 12:42) #103814
                                └ Re[17]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 12:44) #103815
                                  └ Re[18]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/05(Tue) 18:02) #103817
                                    └ Re[19]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 19:28) #103819
                                      └ Re[20]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/05(Tue) 20:39) #103821
                                        └ Re[21]: Visual Basicで簡易CADを作成 / shiro (25/08/06(Wed) 12:22) #103822
                                          └ Re[22]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 14:42) #103825
                                            ├ Re[23]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 17:53) #103828
                                            │└ Re[24]: Visual Basicで簡易CADを作成 / shiro (25/08/06(Wed) 19:13) #103830
                                            │  ├ Re[25]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 19:44) #103832
                                            │  │└ Re[26]: Visual Basicで簡易CADを作成 / shiro (25/08/07(Thu) 07:06) #103834
                                            │  │  └ Re[27]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/07(Thu) 12:18) #103835
                                            │  │    └ Re[28]: Visual Basicで簡易CADを作成 / shiro (25/08/07(Thu) 19:14) #103836
                                            │  │      └ Re[29]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/07(Thu) 20:25) #103837
                                            │  │        ├ Re[30]: Visual Basicで簡易CADを作成 / shiro (25/08/08(Fri) 03:34) #103838
                                            │  │        └ Re[30]: Visual Basicで簡易CADを作成 / shiro (25/08/08(Fri) 07:29) #103839
                                            │  │          └ Re[31]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/08(Fri) 09:40) #103841
                                            │  │            └ Re[32]: Visual Basicで簡易CADを作成 / shiro (25/08/09(Sat) 05:05) #103842
                                            │  │              └ Re[33]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/09(Sat) 14:24) #103843
                                            │  │                └ Re[34]: Visual Basicで簡易CADを作成 / shiro (25/08/09(Sat) 19:18) #103844
                                            │  └ Re[25]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 19:53) #103833
                                            └ Re[23]: Visual Basicで簡易CADを作成 / shiro (25/08/18(Mon) 12:41) #103847
                                              └ Re[24]: Visual Basicで簡易CADを作成 / kiku (25/08/20(Wed) 15:09) #103848
                                                └ Re[25]: Visual Basicで簡易CADを作成 / shiro (25/08/20(Wed) 18:35) #103849
                                                  └ Re[26]: Visual Basicで簡易CADを作成 / kiku (25/08/21(Thu) 09:03) #103850
                                                    └ Re[27]: Visual Basicで簡易CADを作成 / shiro (25/08/21(Thu) 22:01) #103851
                                                      └ Re[28]: Visual Basicで簡易CADを作成 / kiku (25/08/22(Fri) 08:45) #103852
                                                        └ Re[29]: Visual Basicで簡易CADを作成 / shiro (25/08/22(Fri) 13:20) #103853
                                                          └ Re[30]: Visual Basicで簡易CADを作成 / kiku (25/08/22(Fri) 16:45) #103854
                                                            └ Re[31]: Visual Basicで簡易CADを作成 / shiro (25/08/22(Fri) 20:33) #103855
                                                              └ Re[32]: Visual Basicで簡易CADを作成 / kiku (25/08/25(Mon) 08:42) #103857

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信