- 締切済み
VB2010 面積算出
panelを用いた図形の作成を行っております。 コード Public Class Form1 Dim p1 As Integer 'Panel1のカウンター Dim p2 As Integer 'Panel2のカウンター Dim p3 As Integer 'Panel3のカウンター Dim p1size As Single 'Panel1の面積 Dim p2size As Single 'Panel2の面積 Dim p3size As Single 'Panel3の面積 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown Dim p1clnt As Drawing.Size = Panel1.ClientSize Dim p2clnt As Drawing.Size = Panel2.ClientSize Dim p3clnt As Drawing.Size = Panel3.ClientSize p1size = p1clnt.Width * p1clnt.Height p2size = p2clnt.Width * p2clnt.Height p3size = p3clnt.Width * p3clnt.Height Panel4.AllowDrop = True End Sub Private Sub Panel1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown, Panel2.MouseDown, Panel3.MouseDown sender.DoDragDrop(sender, DragDropEffects.Move) End Sub Private Sub Panel4_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel4.DragDrop Dim srsPnl As Panel = e.Data.GetData(GetType(Panel)) Dim dstPnl As New Panel dstPnl.Size = srsPnl.Size Dim dropp1 As Integer = srsPnl.Size.Width * srsPnl.Size.Height If dropp1 = p1size Then p1 += 1 ElseIf dropp1 = p2size Then p2 += 1 ElseIf dropp1 = p3size Then p3 += 1 End If dstPnl.Location = Panel4.PointToClient(CursorPosition) 'New Point(e.X, e.Y) dstPnl.BackColor = srsPnl.BackColor AddHandler dstPnl.MouseDown, AddressOf dstPnl_MouseDown AddHandler dstPnl.MouseMove, AddressOf dstPnl_MouseMove Panel4.Controls.Add(dstPnl) End Sub Private Sub Panel4_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel4.DragEnter If e.Data.GetDataPresent(GetType(Panel)) Then e.Effect = DragDropEffects.Move End If End Sub Private previousPos As Point Private Sub dstPnl_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown previousPos = CursorPosition() End Sub Private Sub dstPnl_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Then Dim nowPos As Point = CursorPosition() DirectCast(sender, Panel).Left += nowPos.X - previousPos.X DirectCast(sender, Panel).Top += nowPos.Y - previousPos.Y Console.WriteLine(nowPos.X & "-" & previousPos.X) previousPos = nowPos End If End Sub Function CursorPosition() As Point Return New Point(CInt(Cursor.Position.X / 10) * 10, CInt(Cursor.Position.Y / 10) * 10) End Function Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ans As Single ans = (p1 * p1size + p2 * p2size + p3 * p3size) * 0.0001 TextBox1.Text = ans End Sub End Class 上記のコードは、GroupBox内のpanelをpanel4へ移動させて図形を作成するものです。 移動させたpanelの数を数えて、全体の面積を算出させているのですが、 作成させた図形の右側1/4の面積だけ(左側1/4,下側1/4といった風に)の面積を算出させることは可能でしょうか? 画像 ※図形は任意 重複なし(panel同士) 1m2 (青) 3枚 0.25m2 (赤) 5枚 0.09m2 (黄) 5枚 計 4.7m2 となっています。 この作成した図形の緑色で着色した部分の面積を出したいと考えております。 もしお時間等ありましたら、お力添えをいただけると嬉しく思います。 どうかよろしくお願いします。
- みんなの回答 (18)
- 専門家の回答
みんなの回答
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
続き 'バブルソート For l1 = 1 To dtcnt For l2 = 0 To dtcnt - 1 - l1 If hmax(l2) > hmax(l2 + 1) Then uptmp = hmax(l2) '入れ替え前の上の値 downtmp = hmax(l2 + 1) '入れ替え前の下の値 hmax(l2) = downtmp '入れ替え後の上の値 hmax(l2 + 1) = uptmp '入れ替え後の下の値 upsiz = arsiz(l2) '入れ替え前の上の値 downsiz = arsiz(l2 + 1) '入れ替え前の下の値 arsiz(l2) = downsiz '入れ替え後の上の値 arsiz(l2 + 1) = upsiz '入れ替え後の下の値 End If Next Next 'ここまではバブルソート関係 Dim heit As Integer Dim line As Decimal '図形のheightの最大値を求める heit = hmax(hmax.Count - 1) - hmin(0) '下3/4の線の座標 line = heit * 3 / 4 + hmin(0) Label1.Text = "高さの座標最大値は" & hmax(hmax.Count - 1) & " " & "その時の図形のheightは" & _ arsiz(arsiz.Count - 1).Height & vbNewLine & "図形の座標最小値は" & hmin(0) & " " & "合成された図形の最大幅は" & heit & " " & "下3/4の線の座標は" & line 'テスト用のライン Dim space As New Bitmap(Panel4.Width, Panel4.Height) 'Class picturに値を渡す gragh.pant(space, Panel4.Width, Panel4.Height, hmin(0), heit, line) 'Panel4に線を描画 Panel4.BackgroundImage = gragh.spc '下3/4の線の座標より下か線をまたいでいるPanelをリストにする For Each pnl As Control In Panel4.Controls If pnl.Size = New Size(pn1, pn1) Then '下3/4の線をまたいでいるPanelの判断 If line < pnl.Location.Y + pn1 AndAlso line >= pnl.Location.Y Then '面積の計算 area.Add((pnl.Location.Y + pn1 - line) * pn1) '下3/4の線の座標より下か線をまたいでいるPanelのリストにAddする arlne.Add(pnl) ElseIf line < pnl.Location.Y Then '下3/4の線の座標より下の判断 '面積の計算 area.Add(pnl.Width * pnl.Height) End If ElseIf pnl.Size = New Size(pn2, pn2) Then '下3/4の線をまたいでいるPanelの判断 If line < pnl.Location.Y + pn2 AndAlso line >= pnl.Location.Y Then '面積の計算 area.Add((pnl.Location.Y + pn2 - line) * pn2) '下3/4の線の座標より下か線をまたいでいるPanelのリストにAddする arlne.Add(pnl) ElseIf line < pnl.Location.Y Then '下3/4の線の座標より下の判断 '面積の計算 area.Add(pnl.Width * pnl.Height) End If ElseIf pnl.Size = New Size(pn3, pn3) Then '下3/4の線をまたいでいるPanelの判断 If line < pnl.Location.Y + pn3 AndAlso line >= pnl.Location.Y Then '面積の計算 area.Add((pnl.Location.Y + pn3 - line) * pn3) '下3/4の線の座標より下か線をまたいでいるPanelのリストにAddする arlne.Add(pnl) ElseIf line < pnl.Location.Y Then '下3/4の線の座標より下の判断 '面積の計算 area.Add(pnl.Width * pnl.Height) End If End If Next '下3/4の線の座標より下の面積を求めます。 Dim menseki As Integer For Each pntotal As Integer In area menseki += pntotal Next MsgBox("下3/4の線の座標より下か線をまたいでいるPanelの数は" & vbNewLine & arlne.Count & "枚です。" & _ vbNewLine & "下3/4の線の座標より下の面積は" & menseki & "です。") 'リストのクリア hmin.Clear() hmax.Clear() arsiz.Clear() area.Clear() arlne.Clear() End Sub End Class これであってるかな~ 間違ってたら返信してください。 すいません、週中は返信できない可能性が高いです。
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
>知識が乏しいにも関わらず そんなことはありません、十分優秀です。 クラスの学習がまだであれば、無理をしてクラス化することはありません。 URLを拝見しました。 スゴ~い。なんかCADみたいですね。 >同時に上部1/4,右側1/4...もbutton1のイベントで取得することは可能でしょうか? 可能です、面積の計算方法は4箇所とも同じですので、面積算出クラスを作成して、値をクラスに渡せばクラスが勝手に算出して、必要な値を取得できます。(言うのは簡単ですけど、行うのはかなり時間がかかりそう) 今回は、下3/4の線の座標より下のPanelの面積と下3/4の線をまたいでいるPanelの面積の算出 テスト用のラインのクラス化をしました。 面積が算出できましたので、TMYMSさんが提示された 1m2 (青) 3枚 0.25m2 (赤) 5枚 0.09m2 (黄) 5枚 を最初のPanelの大きさの比率設定すればOKです。又は下3/4の線をまたいでいるPanelの判断のIf文の中で比率をかければOKです。(言うのは簡単ですけど、行うのはかなり時間がかかりそう). クラスの作成です。 「pictur」というクラスを作成します、 クラスの追加で「pictur」という名前のクラスを追加してください。 Class picturに下記をコピペしてください。 Public Class pictur Private _spc As Bitmap 'Bitmapの作成 Public Sub pant(sp As Bitmap, panlw As Integer, pankh As Integer, hmin As Integer, ht As Integer, lin As Integer) Dim g As Graphics = Graphics.FromImage(sp) Dim pb As New Pen(Color.Black, 1) Dim pr As New Pen(Color.Red, 3) '線を5本引く For i As Integer = 0 To 4 g.DrawLine(pb, 0, hmin + CInt(ht / 4) * i, panlw, hmin + CInt(ht / 4) * i) Next '赤い線を引く g.DrawLine(pr, 0, lin, panlw, lin) g.Dispose() _spc = sp End Sub 'Bitmapオブジェクトの読み込み Public ReadOnly Property spc() As Bitmap Get Return _spc End Get End Property End Class これでラインの描画はクラスに任せて私たちはPanelの面積の算出に専念しましょう。 Button1_Clickプロシージャを下記に変更してください。 Dim gragh As New pictur 'Class picturのインスタンス Dim area As New List(Of Integer) '面積を計算したPanelのリスト Dim arlne As New List(Of Panel) '下3/4の線の座標より下か線をまたいでいるPanelのリスト Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ans As Single ans = (p1 * p1size + p2 * p2size + p3 * p3size) * 0.0001 TextBox1.Text = ans '各PanelのY座標(高さ)をリストにする For Each cntrl As Control In Panel4.Controls hmin.Add(cntrl.Location.Y) Next 'ここから '高さの最少値を求めるループ Dim cnt As Integer 'リストの数 cnt = hmin.Count 'リストの数 Dim uptp As Integer '大きい値 Dim downtp As Integer '入れ替え前の下の要素 Dim lp1 As Integer 'ループカウンター Dim lp2 As Integer 'ループカウンター '高さの最小値を求めるループ バブルソート For lp1 = 1 To cnt For lp2 = 0 To cnt - 1 - lp1 If hmin(lp2) > hmin(lp2 + 1) Then uptp = hmin(lp2) '入れ替え前の上の値 downtp = hmin(lp2 + 1) '入れ替え前の下の値 hmin(lp2) = downtp '入れ替え後の上の値 hmin(lp2 + 1) = uptp '入れ替え後の下の値 End If Next Next 'ここまではバブルソート関係 '高さの最大値を求めるループ + pn1 + pn2 + pn3は移動したPanelの下端 'の座標を取得するためです。 For Each ocntrl As Control In Panel4.Controls If ocntrl.Size = New Size(pn1, pn1) Then hmax.Add(ocntrl.Location.Y + pn1) ElseIf ocntrl.Size = New Size(pn2, pn2) Then hmax.Add(ocntrl.Location.Y + pn2) ElseIf ocntrl.Size = New Size(pn3, pn3) Then hmax.Add(ocntrl.Location.Y + pn3) End If arsiz.Add(ocntrl.Size) Next 'ここから '高さの最大値を求めるループ Dim dtcnt As Integer 'リストの数 dtcnt = hmax.Count 'リストの数 Dim uptmp As Integer '大きい値 Dim downtmp As Integer '入れ替え前の下の要素 Dim upsiz As Size Dim downsiz As Size Dim l1 As Integer 'ループカウンター Dim l2 As Integer 'ループカウンター バブルソートをしたのは画像の上端のラインと下端のラインを求めるためと簡単なためです。 下端のラインはパネルのサイズがわからないと求めることができませんのでバブルソートの中で同じループカウンターをもちいいてパネルのリストのインデックスを同一にします。これでどのパネルを用いれば下端のラインを求めればいいかがわかります。 次に続く
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
続きです。 '------------------------------------------- 'ここから '高さの最大値を求めるループ Dim dtcnt As Integer 'リストの数 dtcnt = hmax.Count 'リストの数 Dim uptmp As Integer '大きい値 Dim downtmp As Integer '入れ替え前の下の要素 Dim upsiz As Size Dim downsiz As Size Dim l1 As Integer 'ループカウンター Dim l2 As Integer 'ループカウンター 'バブルソート For l1 = 1 To dtcnt For l2 = 0 To dtcnt - 1 - l1 If hmax(l2) > hmax(l2 + 1) Then uptmp = hmax(l2) '入れ替え前の上の値 downtmp = hmax(l2 + 1) '入れ替え前の下の値 hmax(l2) = downtmp '入れ替え後の上の値 hmax(l2 + 1) = uptmp '入れ替え後の下の値 upsiz = arsiz(l2) '入れ替え前の上の値 downsiz = arsiz(l2 + 1) '入れ替え前の下の値 arsiz(l2) = downsiz '入れ替え後の上の値 arsiz(l2 + 1) = upsiz '入れ替え後の下の値 End If Next Next 'ここまではバブルソート関係 Dim heit As Integer Dim line As Decimal '図形のheightの最大値を求める heit = hmax(hmax.Count - 1) - hmin(0) '下3/4の線の座標 line = heit * 3 / 4 + hmin(0) Label1.Text = "高さの座標最大値は" & hmax(hmax.Count - 1) & " " & "その時の図形のheightは" & _ arsiz(arsiz.Count - 1).Height & vbNewLine & "図形の座標最小値は" & hmin(0) & " " & "合成された図形の最大幅は" & heit & " " & "下3/4の線の座標は" & line 'テスト用のライン Dim space As New Bitmap(Panel4.Width, Panel4.Height) Dim g As Graphics = Graphics.FromImage(space) Dim pb As New Pen(Color.Black, 1) Dim pr As New Pen(Color.Red, 3) For i As Integer = 0 To 4 g.DrawLine(pb, 0, hmin(0) + CInt(heit / 4) * i, Panel4.Width, hmin(0) + CInt(heit / 4) * i) Next g.DrawLine(pr, 0, line, Panel4.Width, line) g.Dispose() Panel4.BackgroundImage = space '下3/4の線の座標より下か線をまたいでいるPanelをリストにする For Each pnl As Control In Panel4.Controls If pnl.Size = New Size(pn1, pn1) Then If line < pnl.Location.Y + pn1 Then arlne.Add(pnl) End If ElseIf pnl.Size = New Size(pn2, pn2) Then If line < pnl.Location.Y + pn2 Then arlne.Add(pnl) End If ElseIf pnl.Size = New Size(pn3, pn3) Then If line < pnl.Location.Y + pn3 Then arlne.Add(pnl) End If End If Next MsgBox("下3/4の線の座標より下か線をまたいでいるPanelの数は" & vbNewLine & arlne.Count & "枚です。") 'リストのクリア hmin.Clear() hmax.Clear() arsiz.Clear() End Sub End Class 以上です。
補足
回答ありがとうございます。 知識が乏しいにも関わらず、複雑なことをしようとしているのだなと実感しております。 >本当はButton1_Clickプロシージャの中はデータ計算用のクラスを別ファイルで作成した方が可読せいがいいでしょうか? 私の場合は計算処理やファイル処理、画像処理がある場合は必ず別クラスにしますけど、どちらがいいでしょうか? 別クラスで作成したほうが可読性は上がると思います。 しかし、私のレベルがそこまで達していないので実際にやってみるとなると、難しいです。 http://www.house-support.net/seinou/bunnkatu.htm ↑私がやりたいと考えているものに近いものを発見いたしました。 現在bybalsendercaseさんに作成して頂いているコードでは下部1/4についてですが、同時に上部1/4 ,右側1/4...もbutton1のイベントで取得することは可能でしょうか?
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
どうしても1回で掲載できません。 Dim arlne As New List(Of Panel) '下3/4の線の座標より下か線をまたいでいるPanelのリスト Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ans As Single ans = (p1 * p1size + p2 * p2size + p3 * p3size) * 0.0001 TextBox1.Text = ans '高さの最小値を求める For Each cntrl As Control In Panel4.Controls hmin.Add(cntrl.Location.Y) Next 'ここから '高さの最少値を求めるループ Dim cnt As Integer 'リストの数 cnt = hmin.Count 'リストの数 Dim uptp As Integer '大きい値 Dim downtp As Integer '入れ替え前の下の要素 Dim lp1 As Integer 'ループカウンター Dim lp2 As Integer 'ループカウンター '高さの最小値を求めるループ バブルソート For lp1 = 1 To cnt For lp2 = 0 To cnt - 1 - lp1 If hmin(lp2) > hmin(lp2 + 1) Then uptp = hmin(lp2) '入れ替え前の上の値 downtp = hmin(lp2 + 1) '入れ替え前の下の値 hmin(lp2) = downtp '入れ替え後の上の値 hmin(lp2 + 1) = uptp '入れ替え後の下の値 End If Next Next 'ここまではバブルソート関係 '高さの最大値を求めるループ + pn1 + pn2 + pn3は移動したPanelの下端 'の座標を取得するためで。 For Each ocntrl As Control In Panel4.Controls If ocntrl.Size = New Size(pn1, pn1) Then hmax.Add(ocntrl.Location.Y + pn1) ElseIf ocntrl.Size = New Size(pn2, pn2) Then hmax.Add(ocntrl.Location.Y + pn2) ElseIf ocntrl.Size = New Size(pn3, pn3) Then hmax.Add(ocntrl.Location.Y + pn3) End If arsiz.Add(ocntrl.Size) Next '------------------------------------
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
説明が悪いですね~ ごめんなさい。 「ここから」~~~「ここまではバブルソート関係」の部分は私が説明すると混乱を招きますので下記を参考にしてください。 私はこのサイトの画像をもとにしてバブルソートのループをしています。 http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/ Button1_Clickプロシージャを下記と変更してください。 画像のように下1/4の線(赤い線。またPanel4に描画してますので移動したPanelの下敷きになっています、ご了承ください)をまたいでいるPanel又は下にあるPanelを全て取得して Dim arlne As New List(Of Panel)の arlneに全て格納しました。 後はarlneに格納されたPanelがどの程度線を越えているのか、又は完全に線より下になっているのか調べれば面積を計算することができます。(言うのは簡単ですけど、実際にやってみると結構複雑かも) あの~また文字制限です。コードが途中で途切れてしまいますので、次のページに掲載します。 本当はButton1_Clickプロシージャの中はデータ計算用のクラスを別ファイルで作成した方が可読せいがいいでしょうか? 私の場合は計算処理やファイル処理、画像処理がある場合は必ず別クラスにしますけど、どちらがいいでしょうか?
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
遅くなりました。 ちょっと外出したら、うちの奥さんが鍵を閉めて外出してしまいましたので、締め出し状態でした。 本題です。 1.パネルの位置情報を取得しますが、全く移動しないところで取得する必要がありますので、Button1_Clickプロシージャの中で取得します。 2.同じところで各パネルのサイズも取得します。 3.取得した情報をリストにします。(配列は機能が弱いため) 4.各パネルの位置情報をソートします、この時にインデックスを利用してパネルサイズのリストもソートしてセットにする。 5.TMYMSさんの情報では5枚でしたし、 Panel4の大きさから考えても移動したパネルの数が10000枚とか1000000枚とかはありえませんので、パネルの位置情報のソートは実行速度は遅いですが簡単なバブルソートにしました。 6.バブルソートが2回ありますので1回で終わるように改造してください。 7.Labelを貼り付けて状態がわかるようにしてます。変数lineが1/4の位置の線です。 サンプルはここまでです。 あとはまたほかの方にお願いします。 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ans As Single ans = (p1 * p1size + p2 * p2size + p3 * p3size) * 0.0001 TextBox1.Text = ans '高さの最小値を求める For Each cntrl As Control In Panel4.Controls hmin.Add(cntrl.Location.Y) Next '高さの最少値を求めるループ Dim cnt As Integer 'リストの数 cnt = hmin.Count 'リストの数 Dim uptp As Integer '大きい値 Dim downtp As Integer '入れ替え前の下の要素 Dim lp1 As Integer 'ループカウンター Dim lp2 As Integer 'ループカウンター '高さの最小値を求めるループ バブルソート For lp1 = 1 To cnt For lp2 = 0 To cnt - 1 - lp1 If hmin(lp2) > hmin(lp2 + 1) Then uptp = hmin(lp2) '入れ替え前の上の値 downtp = hmin(lp2 + 1) '入れ替え前の下の値 hmin(lp2) = downtp '入れ替え後の上の値 hmin(lp2 + 1) = uptp '入れ替え後の下の値 End If Next Next '高さの最大値を求めるループ + pn1 + pn2 + pn3は移動したPanelの下端 'の座標を取得するためで。 For Each ocntrl As Control In Panel4.Controls If ocntrl.Size = New Size(pn1, pn1) Then hmax.Add(ocntrl.Location.Y + pn1) ElseIf ocntrl.Size = New Size(pn2, pn2) Then hmax.Add(ocntrl.Location.Y + pn2) ElseIf ocntrl.Size = New Size(pn3, pn3) Then hmax.Add(ocntrl.Location.Y + pn3) End If arsiz.Add(ocntrl.Size) Next '高さの最大値を求めるループ Dim dtcnt As Integer 'リストの数 dtcnt = hmax.Count 'リストの数 Dim uptmp As Integer '大きい値 Dim downtmp As Integer '入れ替え前の下の要素 Dim upsiz As Size Dim downsiz As Size Dim l1 As Integer 'ループカウンター Dim l2 As Integer 'ループカウンター 'バブルソート For l1 = 1 To dtcnt For l2 = 0 To dtcnt - 1 - l1 If hmax(l2) > hmax(l2 + 1) Then uptmp = hmax(l2) '入れ替え前の上の値 downtmp = hmax(l2 + 1) '入れ替え前の下の値 hmax(l2) = downtmp '入れ替え後の上の値 hmax(l2 + 1) = uptmp '入れ替え後の下の値 upsiz = arsiz(l2) '入れ替え前の上の値 downsiz = arsiz(l2 + 1) '入れ替え前の下の値 arsiz(l2) = downsiz '入れ替え後の上の値 arsiz(l2 + 1) = upsiz '入れ替え後の下の値 End If Next Next Dim heit As Integer Dim line As Decimal '図形のheightの最大値を求める heit = hmax(hmax.Count - 1) - hmin(0) '下3/4の線の座標 line = heit * 3 / 4 + hmin(0) Label1.Text = "高さの座標最大値は" & hmax(hmax.Count - 1) & " " & "その時の図形のheightは" & -arsiz(arsiz.Count - 1).Height & vbNewLine & "図形の座標最小値は" & hmin(0) & " " & "合成された図形の最大幅は" & heit & " " & "下3/4の線の座標は" & line 'リストのクリア hmin.Clear() hmax.Clear() arsiz.Clear() End Sub End Class ちょうど文字制限です。
補足
回答ありがとうございます。 補足をしたいのですが、このコードがどういうことになってどのように座標を取得しているのか全く分からないのでどういう補足をしていいのかわからない状態です。苦笑 上部1/4で同じことをしようとした場合、どのように行えばよいでしょうか?(同時に下側1/4の座標を取得する)
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
度々すいません。 今度は本題です。 >下側1/4 の面積の算出方法ですが、左横は今回は考慮しません。 前提 #「図形は重複しない」でしたね。 #図形は突出している部分がある。 #凹んだところもある。 ですね。 1.図形の一番高いところの(突出したところ)座標を取得します。 2.図形の一番低いところの座標を求めます。 3.1と2を差し引いて図形の最大値と最小値の幅を求めます。 4.3を3/4して1を足します。これで下の図の線の位置座標を求めることができます。 5.パネルが4で求めた線より下にある又は線に重なっている物を取得します。 6.線に重なったパネルがどのくらい線より下か求めます。 7.6で求めた値で各パネルの面積を求めて合計すればOK これ、くちで言うのは簡単ですけど、ちょっと複雑ですよ。 サンプルは途中4の線の座標を求めるところまでです。 わかりやすいように各パネルは対辺が50、100、150にしてあります。 Public Class Form1 Const pn1 As Integer = 50 'Panel1に固定 Const pn2 As Integer = 100 'Panel2に固定 Const pn3 As Integer = 150 'Panel3に固定 Dim p1 As Integer 'Panel1のカウンター Dim p2 As Integer 'Panel2のカウンター Dim p3 As Integer 'Panel3のカウンター Dim p1size As Single 'Panel1の面積 Dim p2size As Single 'Panel2の面積 Dim p3size As Single 'Panel3の面積 Dim hmin As New List(Of Integer) '各Panelの高さのリスト(座標)最小値 Dim hmax As New List(Of Integer) '各Panelの高さのリスト(座標)最大値 Dim arsiz As New List(Of Size) '各PanelのSizeのリスト Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown 'Panelサイズを設定 Panel1.Size = New Size(pn1, pn1) Panel2.Size = New Size(pn2, pn2) Panel3.Size = New Size(pn3, pn3) Dim p1clnt As Drawing.Size = Panel1.ClientSize Dim p2clnt As Drawing.Size = Panel2.ClientSize Dim p3clnt As Drawing.Size = Panel3.ClientSize p1size = p1clnt.Width * p1clnt.Height p2size = p2clnt.Width * p2clnt.Height p3size = p3clnt.Width * p3clnt.Height Panel4.AllowDrop = True End Sub Private Sub Panel1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown, Panel2.MouseDown, Panel3.MouseDown sender.DoDragDrop(sender, DragDropEffects.Move) End Sub Private Sub Panel4_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel4.DragDrop Dim srsPnl As Panel = e.Data.GetData(GetType(Panel)) Dim dstPnl As New Panel dstPnl.Size = srsPnl.Size Dim dropp1 As Integer = srsPnl.Size.Width * srsPnl.Size.Height If dropp1 = p1size Then p1 += 1 ElseIf dropp1 = p2size Then p2 += 1 ElseIf dropp1 = p3size Then p3 += 1 End If dstPnl.Location = Panel4.PointToClient(CursorPosition) 'New Point(e.X, e.Y) dstPnl.BackColor = srsPnl.BackColor AddHandler dstPnl.MouseDown, AddressOf dstPnl_MouseDown AddHandler dstPnl.MouseMove, AddressOf dstPnl_MouseMove Panel4.Controls.Add(dstPnl) End Sub Private Sub Panel4_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel4.DragEnter If e.Data.GetDataPresent(GetType(Panel)) Then e.Effect = DragDropEffects.Move End If End Sub Private previousPos As Point Private Sub dstPnl_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown previousPos = CursorPosition() End Sub Private Sub dstPnl_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Then Dim nowPos As Point = CursorPosition() DirectCast(sender, Panel).Left += nowPos.X - previousPos.X DirectCast(sender, Panel).Top += nowPos.Y - previousPos.Y Console.WriteLine(nowPos.X & "-" & previousPos.X) previousPos = nowPos End If End Sub Function CursorPosition() As Point Return New Point(CInt(Cursor.Position.X / 10) * 10, CInt(Cursor.Position.Y / 10) * 10) End Function すいません文字制限のため次のページに記入します。
- 田中 裕之(@bybalsendercase)
- ベストアンサー率88% (56/63)
失礼します。 先程文字数制限のため記入できませんでしたので、OKWaveさんのスタッフさんにお願いしましたが、念のためにここに記載させて頂きます。 単純に画像のBitmapオブジェクトを作成する場合は、先程のButton1_Clickイベントハンドラで良いのですが、キャプチャでしたらButton1_Clickイベントハンドラを下記のように変更してください。 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim pnsze As Rectangle pnsze = Me.RectangleToScreen(Panel4.Bounds) Dim space As New Bitmap(pnsze.Width, pnsze.Height, PixelFormat.Format32bppArgb) Dim g As Graphics = Graphics.FromImage(space) g.CopyFromScreen(pnsze.X, pnsze.Y, 0, 0, pnsze.Size, CopyPixelOperation.SourceCopy) Dim pnsize As Size 'Panel4のサイズを取得 pnsize.Width = Panel4.Width pnsize.Height = Panel4.Height 'Panel4のサイズをプロパティに書き込む capt.sze = pnsize 'Bitmapオブジェクトをプロパティに書き込む capt.mp = space End Sub この投稿は後でスタッフさんに削除して頂きます。
- 1
- 2
補足
回答ありがとうございます。 下1/4部分の面積が出ています!!!!! お忙しいにもかかわらず、お時間を割いていただき恐縮です。 さっそくですが Const pn1 As Integer = 50 Panel1.Size = New Size(pn1, pn1) ではサイズが(50,50)のpanelを形成しているかと思います。 サイズを(50,100)としたい場合は、 Const pn1 As Integer = 50 Const pn11 As Integer = 100 Panel1.Size = New Size(pn1, pn11) としました。 この場合 'ここまではバブルソート関係 '高さの最大値を求めるループ + pn1 + pn2 + pn3は移動したPanelの下端 'の座標を取得するためです。 For Each ocntrl As Control In Panel4.Controls If ocntrl.Size = New Size(pn1, pn1) Then hmax.Add(ocntrl.Location.Y + pn1) ここでは If ocntrl.Size = New Size(pn1, pn1) Then ↓ If ocntrl.Size = New Size(pn1, pn11) Then しかし、 hmax.Add(ocntrl.Location.Y + pn1) この部分はどのように変更すればよいのでしょうか? また、 '下3/4の線の座標より下か線をまたいでいるPanelをリストにする For Each pnl As Control In Panel4.Controls If pnl.Size = New Size(pn1, pn1) Then '下3/4の線をまたいでいるPanelの判断 If line < pnl.Location.Y + pn1 AndAlso line >= pnl.Location.Y Then '面積の計算 area.Add((pnl.Location.Y + pn1 - line) * pn1) '下3/4の線の座標より下か線をまたいでいるPanelのリストにAddする arlne.Add(pnl) ElseIf line < pnl.Location.Y Then '下3/4の線の座標より下の判断 '面積の計算 area.Add((pnl.Width * pnl.Height) * 0.0001) End If ここでもコードを書き換える必要があると思うのですが、よくわからないです。