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

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

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

Re[6]: C# WPF Canvas


(過去ログ 105 を表示中)

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

■62817 / inTopicNo.1)  C# WPF Canvas
  
□投稿者/ Toshio Uramoto (1回)-(2011/11/03(Thu) 22:06:01)

分類:[C#] 

開発環境は Windows7 X64 C#(C# 2010 Express:とりあえず) です。
テキストファイルには描画のモトネタがあって、 XAML ではなくプログラムで Canvas に SHAPE などを使い作図しています。
テキストファイルはSVGでもなく、某会社の独自のフォーマットです。
絵に鮮明が求められるので WPF のアプリケーションとして構成しています。
描画のコマンド(線、円、ポリゴン、円弧、拡大、縮小、など)が多彩で、しかも数十万を軽く超えるような UIElement が必要になっています。
実際に Canvas に作図し、画面には表示していますが、UIElement数が25万程度で Canvas に展開してから表示されるまで数十秒かかっています。先日、もっと大きなテキストファイルを作図したところ OutofMemory になってしまいました。
WPFがこんなにメモリを消費するものだとは知らずに開発を始めてしまいました。PCには12Gのメモリとビデオボードの2Gのメモリがあります。思うに同一 Canvas に展開出来る UIElement の最大数を超えたのではないかと思っています。(限度はあるのでしょうか?)
質問は以下です。
小さな四角エリア(以後、小四角と呼ぶ)に展開する UIElement 数も膨大ですが、たかだか10万以下です。
小四角に展開(描画)する内容は全て同じですし同じ大きさです。
この小四角をもっと大きな四角の中に数百個ちりばめます。小四角同士は重なる事はありません。(碁盤の目のように配置。)
今は、一つの Canvas に全てを展開しようとして? OutofMemory になっています。
本来?なら、小さな四角エリアを一つだけ作図して、他の部位にコピーするようなイメージの方法が可能ならいいのですが、UIElement のインスタンスコピーも出来ず、かといって他の部位に Child.Add() すると怒られるし、手詰まりとなっています。
ドットイメージならVB6ですが画面の自由位置にコピーして表示したりは出来るのですが、 WPF はそのようにはいかないようです。
何とか、小さな四角エリアを一つだけ作図し、他にコピーするようなイメージで表示は出来ないものか、の質問です。
当然ですが、作図&表示の速度アップも目指しています。
どなたか、解決法をご存知の方、宜しくお願いいたします。

引用返信 編集キー/
■62828 / inTopicNo.2)  Re[1]: C# WPF Canvas
□投稿者/ radlon (3回)-(2011/11/04(Fri) 21:05:57)
たぶんToshio Uramotoさんがやりたいことだと、大量のUIElementが表示範囲に配置されるんですよね?
となるとUIElementを配置する方法ではどうやっても処理速度に無理がでてくるかと…

やりたいことは描画だけみたいですし、無理に大量のUIElementを配置して描画するのではなく
自力で描画した方が良いんじゃないですかね?

引用返信 編集キー/
■62843 / inTopicNo.3)  Re[2]: C# WPF Canvas
□投稿者/ Toshio Uramoto (2回)-(2011/11/05(Sat) 14:49:30)
No62828 (radlon さん) に返信
> たぶんToshio Uramotoさんがやりたいことだと、大量のUIElementが表示範囲に配置されるんですよね?
> となるとUIElementを配置する方法ではどうやっても処理速度に無理がでてくるかと…
>
> やりたいことは描画だけみたいですし、無理に大量のUIElementを配置して描画するのではなく
> 自力で描画した方が良いんじゃないですかね?
>

確かに描画するだけです。
鮮明、高速描画、拡大縮小、回転 がテーマです。
何か方法をご存知ならご教授願えますでしょうか。
自力での描画とはベクタ描画ではなくピクセル描画ですか?


引用返信 編集キー/
■62866 / inTopicNo.4)  Re[3]: C# WPF Canvas
□投稿者/ ツPツAツTツIツO (6回)-(2011/11/07(Mon) 10:41:14)
自力で描画と言うのはWPFではなくて自前でGraphicsを使って描画すると言う話ではないかと思うのですが、

WPFで実装してみるにあたってC#でベタに描画を行ったケースについては何か実験をして見られたのでしょうか?
.NET Frameworkを使った描画であれば、上記の方法でも同じような結果は得られそうな気がします。
描画する時にアンチエイリアスを使うとか諸々の設定もできると思うのでそこまで見劣りするとも思えないです。
求めているレベルが文章では分からないので足りないと言われてしまうとそれまでですけれど。

引用返信 編集キー/
■62867 / inTopicNo.5)  Re[4]: C# WPF Canvas
□投稿者/ PATIO (132回)-(2011/11/07(Mon) 10:42:57)
ぐわっ、また名前が化けている。
上記の書き込みは私の書き込みです。
Firefoxのバージョンが上がって以来、名前が化ける事が多い。

引用返信 編集キー/
■62885 / inTopicNo.6)  Re[5]: C# WPF Canvas
□投稿者/ Toshio Uramoto (3回)-(2011/11/08(Tue) 10:39:08)
No62867 (PATIO さん) に返信
> ぐわっ、また名前が化けている。
> 上記の書き込みは私の書き込みです。
> Firefoxのバージョンが上がって以来、名前が化ける事が多い。
>

参照して下さって、ありがとうございます。

目的は、例えば、大きな地図を虫眼鏡のように小さなエリアを拡大したり縮小(虫眼鏡にはありませんが)したりして見ることです。
再描画しないで、画像がボケないで、高速にです。(無理なのはある程度承知しています。)
2p辺の四角形内に5万描画程度なので、それが50cm辺程度の四角形に入るだけ詰めます。
全部で25万描画程度ならSHAPEでも完璧に全体を作図し描画出来ます。(これは2mm辺の四角形内に5千描画程度で全体で90個です。他にも描画はあります。全部で25万程度です。)
問題は一番多いのではその100倍程度の物があって、それの描画です。(ベクタ描画では出来ないと言うか、最近の実験では限界を超過していると思ってます。)
一番細い一本の線の幅が1ミル(25.4ミクロン)付近なので、かなり拡大する必要があります。
また、画面に全体像の表示が必要なので、縮小も必要になります。
現在のめざしている方法は2通りです。
1.は
 2p辺を任意の縮小、拡大率でベクタ描画し、そのオブジェクトをビットイメージにする。(必要個数)
 その他の描画はベクタ描画のまま専用CANVASへ、ビットイメージも該当CANVASに散りばめる。
 ベクタ描画CANVASとビットイメージCANVASを親CANVASの子として登録し表示する。
2.は
 拡大が200倍を超えるものは描画範囲が限られているので表示する四角範囲しか描画しない。
 回転、ミラー、シフトがあるので範囲を絞るのは結構面倒だと思っています。
の2通りです。
1.については拡大するとボケるので拡大しません。
2.は完全にベクタ描画なので拡大・縮小は問題ありませんが、全体を描画しないので結局は描画しなおしになります。
WPFの”再描画しない”の利点は使えません。
まだ解決済みとまで至っていません。






引用返信 編集キー/
■62894 / inTopicNo.7)  Re[6]: C# WPF Canvas
□投稿者/ PATIO (134回)-(2011/11/08(Tue) 14:37:00)
2011/11/08(Tue) 14:43:04 編集(投稿者)
2011/11/08(Tue) 14:38:51 編集(投稿者)

一般論で書きますので外しているかもしれませんが、

基本的に拡大縮小に強いのはベクタ描画です。
建物等のオブジェクトを構成する座標点列を演算によって描画座標に変換する際に
拡縮率を勘案して計算する事で描画用座標点列を得て描画します。
拡大時は対象オブジェクトが少なくなりますから演算対象を描画対象に絞る事で
演算負荷を減らせますし、描画負荷も減少します。

逆に縮小する場合は演算対象が増加するので演算負荷が増大します。
場合によっては点になってしまうような形状に関しては演算対象からも外して
描画しないと言う処理も必要になると思います。
縮小する事で同一点になるような部分を間引くようにすると描画負荷をもう少し減らせると思います。

基本的にラスタ化してしまうと拡大するにしても縮小するにしても画像が崩れてしまうので
綺麗に描画と言うのはなかなか難しいと思います。
特殊なロジックを使って補完したり補正をするようにすれば可能かもしれませんが。
ベクトルデータであれば、拡大、縮小、回転は座標変換の演算で解決できます。
描画時にアンチエイリアスを有効する等でより綺麗な描画も可能だと思います。

一般的にメモリ上で描画して描画面に転送と言うのが一般的な高速描画手法です。
(いわゆるバックバッファを使って描画し、描画結果を転送する方法)
昨今のPCはかなり強力なCPUをもっていますし、描画性能も高いのでベクトルデータを
保持しているのであれば、その手法を使う事でそこそこのスピードは出ると思います。
どの程度のスピードが出ればOKなのかわかりませんけれど、そこは考え方だと思います。
オブジェクト数によりますが、ベクタ描画で実用的なスピードは出せると思いますよ。

ちなみにWPFにしても能動的に描画処理を呼んでいないだけなのではと思います。
実際には画面に表示する必要がある以上はなんらかの形で描画しているはずです。
正直言って地図を描画しようとしているのであれば、UIElementを使ったやり方は現実的ではないと思います。
構成オブジェクト数が多すぎますから。

追伸:私はもっぱらC++での開発が仕事なのでC#は殆ど使い込んでいません。
C#のグラフィック描画がどの程度のスピードなのかは実際に確認する必要があると思います。

引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -