こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

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
となっています。
この作成した図形の緑色で着色した部分の面積を出したいと考えております。


もしお時間等ありましたら、お力添えをいただけると嬉しく思います。

どうかよろしくお願いします。

投稿日時 - 2013-02-02 15:11:11

QNo.7924106

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(18)

ANo.18

こんばんは
突然の割り込み失礼します。
私も今同じようなことをしていてここにたどり着きました。

ここに書かれてあるコードを試してみました。

「heit = hmax(hmax.Count - 1) - hmin(0) '図形のheightの最大値を求める」
のところで
「インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
パラメーター名: index」
という表示がでてしまいます。

Visual Basicを始めたばかりの初心者なのでわからないことばかりです。
これをどう解決すればいいのか教えていただきたいです。
よろしくお願いいたします。

最後に、私の質問なのにここの回答欄を使ってしまい、申し訳ありません。
もし気に障るなら削除していただいても構いません。

投稿日時 - 2013-11-25 22:12:28

こんにちは


区切りが悪くてページ数が増えてしまいました、


>下1/4に関しては問題なく実行することができます。
良かったです。


>上1/4、右1/4、左1/4に関しては今まで触れていないのですが、
先に、上1/4を片付けましょう。
同様の方法で右1/4、左1/4も計算できます。



>button2をクリックしたら上1/4の面積が出せる
>ということは可能なのでしょうか?
追加してみました。
メソッドで対応してますので、少し機能が悪いですね。クラスの作成の学習が終わったら、クラス化してください。(ゆっくり学習してください。)



>undoでのカウンターをどのようにすればよいのか。
>というこの前の状態でとまっております。
先日紹介していただいたサイトを見て思い立ったところがありますので、時間のあるときにundoのスレッドの方に記入してみます。


1m2   (青) 
0.25m2 (赤) 
0.09m2 (黄) 
上記は算出した面積の比率から算出できますね。


なるべく共通で使えるコードはメソッド化しましたが、もう少し工夫すればもっと短く出来ると思います。
ちょっとコードが長くなってしまいましたので、正しく計算されるかわかりません。
実験をしてください。問題がある場合は修正するか返信をお願いします。


'上1/4の線の座標より上の面積を求めるメッソド
Private Sub calucup()
'上1/4の線の座標より上か線をまたいでいるPanelをリストにする
For Each pnl As Control In Panel4.Controls
If pnl.Size = New Size(pn1, pn11) Then
'上1/4の線をまたいでいるPanelの判断
If upline < pnl.Location.Y + pn11 AndAlso upline >= pnl.Location.Y Then
'面積の計算
areaup.Add((upline - pnl.Location.Y) * pn1)
'上1/4の線をまたいでいるPanelのリストにAddする
arup.Add(pnl)
ElseIf upline > pnl.Location.Y + pn11 Then '上1/4の線の座標より上の判断
'面積の計算
areaup.Add(pnl.Width * pnl.Height)
End If
ElseIf pnl.Size = New Size(pn2, pn2) Then
'上1/4の線をまたいでいるPanelの判断
If upline < pnl.Location.Y + pn2 AndAlso upline >= pnl.Location.Y Then
'面積の計算
areaup.Add((upline - pnl.Location.Y) * pn2)
'上1/4の線をまたいでいるPanelのリストにAddする
arup.Add(pnl)
ElseIf underline > pnl.Location.Y + pn2 Then '上1/4の線の座標より上の判断
'面積の計算
areaup.Add(pnl.Width * pnl.Height)
End If
ElseIf pnl.Size = New Size(pn3, pn3) Then
'上1/4の線をまたいでいるPanelの判断
If upline < pnl.Location.Y + pn3 AndAlso upline >= pnl.Location.Y Then
'面積の計算
areaup.Add((upline - pnl.Location.Y) * pn3)
'上1/4の線をまたいでいるPanelのリストにAddする
arup.Add(pnl)
ElseIf upline > pnl.Location.Y + pn3 Then '上1/4の線の座標より上の判断
'面積の計算
areaup.Add(pnl.Width * pnl.Height)
End If
End If
Next

'上1/4の線の座標より上の面積を求めます。
Dim mensekiup As Integer
For Each pntotal As Integer In areaup
mensekiup += pntotal
Next

MsgBox("上1/4の線をまたいでいるPanelの数は" & vbNewLine & arup.Count & "枚です。" & _
vbNewLine & "上1/4の線の座標より上の面積は" & mensekiup & "です。")

'リストのクリア
arclr()
End Sub
'リストのクリアメッソド
Private Sub arclr()
hmin.Clear()
hmax.Clear()
arsiz.Clear()
areadown.Clear()
areaup.Clear()
arunder.Clear()
arup.Clear()
End Sub
End Class



以上です。

投稿日時 - 2013-02-11 12:41:38

5通目

'下3/4の線の座標より下の面積を求めるメッソド
Private Sub calucunder()
'下3/4の線の座標より下か線をまたいでいるPanelをリストにする
For Each pnl As Control In Panel4.Controls
If pnl.Size = New Size(pn1, pn11) Then
'下3/4の線をまたいでいるPanelの判断
If underline < pnl.Location.Y + pn11 AndAlso underline >= pnl.Location.Y Then
'面積の計算
areadown.Add((pnl.Location.Y + pn11 - underline) * pn1)
'下3/4の線をまたいでいるPanelのリストにAddする
arunder.Add(pnl)
ElseIf underline < pnl.Location.Y Then '下3/4の線の座標より下の判断
'面積の計算
areadown.Add(pnl.Width * pnl.Height)
End If
ElseIf pnl.Size = New Size(pn2, pn2) Then
'下3/4の線をまたいでいるPanelの判断
If underline < pnl.Location.Y + pn2 AndAlso underline >= pnl.Location.Y Then
'面積の計算
areadown.Add((pnl.Location.Y + pn2 - underline) * pn2)
'下3/4の線をまたいでいるPanelのリストにAddする
arunder.Add(pnl)
ElseIf underline < pnl.Location.Y Then '下3/4の線の座標より下の判断
'面積の計算
areadown.Add(pnl.Width * pnl.Height)
End If
ElseIf pnl.Size = New Size(pn3, pn3) Then
'下3/4の線をまたいでいるPanelの判断
If underline < pnl.Location.Y + pn3 AndAlso underline >= pnl.Location.Y Then
'面積の計算
areadown.Add((pnl.Location.Y + pn3 - underline) * pn3)
'下3/4の線をまたいでいるPanelのリストにAddする
arunder.Add(pnl)
ElseIf underline < pnl.Location.Y Then '下3/4の線の座標より下の判断
'面積の計算
areadown.Add(pnl.Width * pnl.Height)
End If
End If
Next

'下3/4の線の座標より下の面積を求めます。
Dim mensekidown As Integer
For Each pntotal As Integer In areadown
mensekidown += pntotal
Next

MsgBox("下3/4の線をまたいでいるPanelの数は" & vbNewLine & arunder.Count & "枚です。" & _
vbNewLine & "下3/4の線の座標より下の面積は" & mensekidown & "です。")

'リストのクリア
arclr()
End Sub

続く

投稿日時 - 2013-02-11 12:23:13

4通目

'上下共通メソッド
Private Sub floor()

'追加した各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, pn11) Then '変更箇所
hmax.Add(ocntrl.Location.Y + pn11) '変更箇所
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
heit = hmax(hmax.Count - 1) - hmin(0) '図形のheightの最大値を求める
upline = heit * 1 / 4 + hmin(0) '上1/4の線の座標
underline = heit * 3 / 4 + hmin(0) '下3/4の線の座標

'テスト用のライン
Dim space As New Bitmap(Panel4.Width, Panel4.Height)
'Class picturに値を渡す
gragh.pant(space, Panel4.Width, Panel4.Height, hmin(0), heit, underline, upline)
'Panel4に線を描画
Panel4.BackgroundImage = gragh.spc

End Sub

投稿日時 - 2013-02-11 12:18:40

3通目


Dim arsiz As New List(Of Size) '各PanelのSizeのリスト
Dim hmin As New List(Of Integer) '各Panelの高さのリスト(座標)最小値
Dim hmax As New List(Of Integer) '各Panelの高さのリスト(座標)最大値
Dim gragh As New pictur 'Class picturのインスタンス
Dim areadown As New List(Of Integer) '下3/4の面積を計算したPanelのリスト
Dim areaup As New List(Of Integer) '上1/4の面積を計算したPanelのリスト
Dim arunder As New List(Of Panel) '下3/4の線の座標より下か線をまたいでいるPanelのリスト
Dim arup As New List(Of Panel) '上1/4の線の座標より下か線をまたいでいるPanelのリスト
Dim upline As Decimal '上1/4の線の座標
Dim underline As Decimal '下3/4の線の座標
'下3/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

'メソッド化
floor()

'下3/4の線の座標より下の面積を求めるメッソド
calucunder()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'メソッド化
floor()

'上1/4の線の座標より下の面積を求めるメッソド
calucup()
End Sub

投稿日時 - 2013-02-11 12:14:24

2通目

Class Form1側

Public Class Form1
Const pn1 As Integer = 50 'Panel1に固定
Const pn11 As Integer = 100 '変更箇所
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の面積
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
'Panelサイズを設定
Panel1.Size = New Size(pn1, pn11)
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


続く

投稿日時 - 2013-02-11 12:08:13

1通目


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, underlin As Decimal, uplin As Decimal)
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, CInt(uplin), panlw, CInt(uplin)) '上1/4の線
g.DrawLine(pr, 0, CInt(underlin), panlw, CInt(underlin)) '下3/4の線
g.Dispose()
_spc = sp
End Sub
'Bitmapオブジェクトの読み込み
Public ReadOnly Property spc() As Bitmap
Get
Return _spc
End Get
End Property
End Class


続く

投稿日時 - 2013-02-11 12:06:48

続きです。


下記のようにすると、 Panelのサイズをいろいろ変更しても対応できますね。
Dim pn1 As Integer
Dim pn11 As Integer
pn1 = Panel1.Width
pn11 = Panel1.Width


先回のURLを見て思いましたが、UNDOの件は解決されましたか?
先回のURLの内容からすると、画像を前回の状態にすればいいのかな~なんておもいました。
もし解決していなければ、そちらのスレッドでサンプルを掲載します。
できるかな~?


'バブルソート
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, pn11) Then '変更箇所
'下3/4の線をまたいでいるPanelの判断
If line < pnl.Location.Y + pn11 AndAlso line >= pnl.Location.Y Then
'面積の計算
area.Add((pnl.Location.Y + pn11 - 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


以上です、あってるかな~?
間違っていましたらごめんなさい。

投稿日時 - 2013-02-08 19:47:40

補足

毎回親切にありがとうございます。
これで下1/4に関しては問題なく実行することができます。
上1/4、右1/4、左1/4に関しては今まで触れていないのですが、
同様のコードbutton2をクリックしたら上1/4の面積が出せる
ということは可能なのでしょうか?


undoでのカウンターをどのようにすればよいのか。
というこの前の状態でとまっております。

投稿日時 - 2013-02-11 06:22:23

続きです。


Dim arsiz As New List(Of Size) '各PanelのSizeのリスト
Dim hmin As New List(Of Integer) '各Panelの高さのリスト(座標)最小値
Dim hmax As New List(Of Integer) '各Panelの高さのリスト(座標)最大値
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, pn11) Then '変更箇所
hmax.Add(ocntrl.Location.Y + pn11) '変更箇所
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 'ループカウンター



続く

投稿日時 - 2013-02-08 19:37:17

こんばんは


もうだいぶ日にちも経ちましたので、「既に時遅し」でしょうか?



>お忙しいにもかかわらず、お時間を割いていただき恐縮です。
お気遣い有難うございます。



>この部分はどのように変更すればよいのでしょうか?
サンプルを修正しました。わかりづらいコードですね。


既に解決済みかもしれませんが、念のために修正したサンプルを掲載します。
Button1_Clickプロシージャでしか使わないリストは、Button1_Clickプロシージャの上に移動しました。
最初から掲載しますので、3回位に分かれると思います。
「Class pictur」は変更しませんので掲載しません。



Public Class Form1
Const pn1 As Integer = 50 'Panel1に固定
Const pn11 As Integer = 100 '変更箇所
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の面積
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
'Panelサイズを設定
Panel1.Size = New Size(pn1, pn11)
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


次に続く

投稿日時 - 2013-02-08 19:35:13

続き


'バブルソート
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


これであってるかな~

間違ってたら返信してください。

すいません、週中は返信できない可能性が高いです。

投稿日時 - 2013-02-05 21:58:03

補足

回答ありがとうございます。
下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

ここでもコードを書き換える必要があると思うのですが、よくわからないです。

投稿日時 - 2013-02-05 23:51:48

>知識が乏しいにも関わらず
そんなことはありません、十分優秀です。


クラスの学習がまだであれば、無理をしてクラス化することはありません。



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 'ループカウンター


バブルソートをしたのは画像の上端のラインと下端のラインを求めるためと簡単なためです。

下端のラインはパネルのサイズがわからないと求めることができませんのでバブルソートの中で同じループカウンターをもちいいてパネルのリストのインデックスを同一にします。これでどのパネルを用いれば下端のラインを求めればいいかがわかります。




次に続く

投稿日時 - 2013-02-05 21:54:10

続きです。


'-------------------------------------------
'ここから
'高さの最大値を求めるループ 
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


以上です。

投稿日時 - 2013-02-03 20:02:32

補足

回答ありがとうございます。
知識が乏しいにも関わらず、複雑なことをしようとしているのだなと実感しております。


>本当はButton1_Clickプロシージャの中はデータ計算用のクラスを別ファイルで作成した方が可読せいがいいでしょうか?
私の場合は計算処理やファイル処理、画像処理がある場合は必ず別クラスにしますけど、どちらがいいでしょうか?
別クラスで作成したほうが可読性は上がると思います。
しかし、私のレベルがそこまで達していないので実際にやってみるとなると、難しいです。

http://www.house-support.net/seinou/bunnkatu.htm
↑私がやりたいと考えているものに近いものを発見いたしました。
現在bybalsendercaseさんに作成して頂いているコードでは下部1/4についてですが、同時に上部1/4
,右側1/4...もbutton1のイベントで取得することは可能でしょうか?

投稿日時 - 2013-02-04 03:46:32

どうしても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
'------------------------------------

投稿日時 - 2013-02-03 20:00:55

説明が悪いですね~
ごめんなさい。


「ここから」~~~「ここまではバブルソート関係」の部分は私が説明すると混乱を招きますので下記を参考にしてください。
私はこのサイトの画像をもとにしてバブルソートのループをしています。
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プロシージャの中はデータ計算用のクラスを別ファイルで作成した方が可読せいがいいでしょうか?
私の場合は計算処理やファイル処理、画像処理がある場合は必ず別クラスにしますけど、どちらがいいでしょうか?

投稿日時 - 2013-02-03 19:54:23

遅くなりました。


ちょっと外出したら、うちの奥さんが鍵を閉めて外出してしまいましたので、締め出し状態でした。



本題です。

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


ちょうど文字制限です。

投稿日時 - 2013-02-03 12:59:06

補足

回答ありがとうございます。
補足をしたいのですが、このコードがどういうことになってどのように座標を取得しているのか全く分からないのでどういう補足をしていいのかわからない状態です。苦笑

上部1/4で同じことをしようとした場合、どのように行えばよいでしょうか?(同時に下側1/4の座標を取得する)

投稿日時 - 2013-02-03 15:34:46

度々すいません。


今度は本題です。
>下側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


すいません文字制限のため次のページに記入します。
 

投稿日時 - 2013-02-03 08:48:59

失礼します。


先程文字数制限のため記入できませんでしたので、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

この投稿は後でスタッフさんに削除して頂きます。

投稿日時 - 2013-02-02 16:38:15

あなたにオススメの質問