放射線被爆状況 視覚支援 即時描画システム (通称TDRシステム)
(VisualAid & RealTimeRenderingSystem WQHD 2560x1440)
- ファクトリ内の汎用機から中継されUNIX系からDGRAMで流れてきます。データはAPPレベルに昇華されている為、データの扱いが楽です。
- ケックではこの試作公開は問題ありません。
- 視覚化されて検査時間の短縮化に繋がります。
- 配列にデータ入れれば他にも流用でき汎用性があります。
1.キー操作説明
[メインキャンパス]
-
[マウス]......................メインキャンパスに置くとその方向にスクロール(8方向)
-
[マウスホイール]....データマーク大きさ可変
-
[マウスボタン]........スクロール速度の調整 左ボタンで少し早くなり、右ボタンで最速
[ディスプレイエリアマップキャンパス]
- [マウス左ボタン]....その地点のデータ表示。左押しながらマウス移動で即時表示
2.動画 YouTube ダミーデータ使用
3.コードについて
- ソケット受信部は除いてます。
- 起動後、データ生成に時間掛かります。private void Window_LoadedのTitle2matrixを削除すると早く動作します。 非同期化させてましたが動作がおかしく場合があったので同期で動作しています。
- MainCanvasの幅高さとマーク大きさから表示可能なXY軸の個数を算出し余計な描画をしないように最適化。その為、メモリが許す限り例え100万x100万の二次元配列にも対応。
- 円グラフはコントロールを使わず自力で描画し細かい制御に対応。
- 高速スクロール対応。
4.WPF Sourcecode
//////////////////////////////////////
// TDR System Testtype
// WPF + SkiaSharp
// inf102 S.H 2025.
//////////////////////////////////////
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace SkiaSharpSample {
public partial class MainWindow : Window {
int[,] mat = new int[1000, 1000];
// ローカルウィンドウ マウス位置
static int XX,YY;
// MATREX 表示位置(左上)
static int START_X=500;
static int START_Y=500;
// 初期マーク大きさ
static int CIRCEL_R=10;
// マウスがエリアに入っているか
static bool MOUSE_IN=false;
// マウスボタン押し状態
static bool LEFT_BTN=false;
static bool RIGHT_BTN=false;
// MAP
static bool MAP_LEFT_BTN=false;
// 速度
static int SPEED=100;
// マーク表示数 縦に5個表示中なら Y_CNT=5
static int CNT_Y,CNT_X;
// オーバーフロー管理 false==正常
static bool FLG_X=false;
static bool FLG_Y=false;
// 枠位置
static int LAT_X1,LAT_X2,LAT_Y1,LAT_Y2;
// Alpha
static SKPaint LV1_LINE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
Color = new SKColor(0,255,00)
};
// Beta
static SKPaint LV2_LINE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
Color = new SKColor(0,0,255)
};
// Gamma
static SKPaint LV3_LINE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
Color = new SKColor(255,0,0)
};
// Unknow
static SKPaint LV4_LINE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
Color = new SKColor(0,255,255)
};
// MAP XY補助線
static float[] dashArray = new float[2];
SKPaint XY_ARAY= new SKPaint{
Style = SKPaintStyle.StrokeAndFill,
Color = new SKColor(0, 191, 200),
IsAntialias=true,
PathEffect = SKPathEffect.CreateDash(dashArray, 10),
StrokeWidth =1
};
// メインXY格子
SKPaint MAIN_XY_LINE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
StrokeWidth = 6,
Color = new SKColor(255,255,255)
};
// MAP枠
SKPaint MAP_RECT= new SKPaint{
Style = SKPaintStyle.Stroke,
IsAntialias=true,
StrokeWidth = 4,
Color = new SKColor(0,0,255)
};
// MAP数値
SKPaint MAP_NO= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
StrokeWidth = 1,
Color = new SKColor(255,255,255)
};
// MAP
SKPaint MAP_CENTER= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
StrokeWidth = 2,
Color = new SKColor(255,255,0)
};
// MAPマーク
SKPaint MAP_MARK= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
Color = new SKColor(255,0,0)
};
// TOP-TITLE
SKPaint TOP_TITLE= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
TextAlign=SKTextAlign.Center,
TextSize=30,
Color = new SKColor(0,100,255)
};
// DATA CIRCEL
SKPaint DATA_CIRCLE= new SKPaint{
Style = SKPaintStyle.Stroke,
IsAntialias=true,
StrokeWidth=2,
Color = new SKColor(0,155,255)
};
// NUM数値
SKPaint NUM_NO= new SKPaint{
Style = SKPaintStyle.Fill,
IsAntialias=true,
TextAlign=SKTextAlign.Left,
TextSize=15,
StrokeWidth = 1,
};
public void msg(string s) {
MessageBox.Show(s);
}
public MainWindow() {
InitializeComponent();
Random rnd = new Random();
for (int y=0;y<1000;y++){
for(int x = 0; x < 1000; x++) {
mat[y,x] = rnd.Next(0,4);
}
}
for (int y=500;y<550;y++){
for(int x = 540; x < 590; x++) {
mat[y,x] = 1;
}
}
for (int y=20;y<50;y++){
for(int x = 10; x < 130; x++) {
mat[y,x] = 3;
}
}
for (int y=560;y<580;y++){
for(int x = 600; x < 620; x++) {
mat[y,x] = 2;
}
}
for (int y=590;y<620;y++){
for(int x = 630; x < 650; x++) {
mat[y,x] = 0;
}
}
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
// Title2matrix
for (int xx=683;xx<1100;xx++){
for (int yy=5;yy<29;yy++){
var RGB=GetPixelColorAt (TopCanvas,xx,yy);
if (RGB.R==0 && RGB.G == 100 && RGB.B == 255) {
mat[yy,xx-600]=1;
mat[yy+500,xx-200]=2;
}
else {
mat[yy,xx-600]=4;
mat[yy+500,xx-200]=4;
}
}
}
_=Task.Run ( async ()=> {
while (true){
await Task.Delay(SPEED);
if ( MOUSE_IN == false ) continue;
// 左上
if (XX < LAT_X1 && YY <LAT_Y1 ) {
START_Y--;
START_X--;
if (START_Y <= -1 ) START_Y=0;
if (START_X <= -1 ) START_X=0;
}
// 上
if ( (XX >LAT_X1 && XX <LAT_X2 ) && YY<LAT_Y1 ){
START_Y--;
if (START_Y <=-1 ) START_Y=0;
}
// 右上
if ( XX > LAT_X2 && YY < LAT_Y1){
if (FLG_X==false) START_X++;
START_Y--;
if (START_Y<=-1 ) START_Y=0;
}
// 左
if ( XX <LAT_X1 && YY > LAT_Y1 && YY < LAT_Y2){
START_X--;
if (START_X <=-1 ) START_X=0;
}
// 右
if ( XX > LAT_X2 && YY > LAT_Y1 && YY <LAT_Y2 ){
if (FLG_X==false) START_X++;
// START_X が大きい時に画面左を左にリサイズした時、START_Xを順次補正して右側に表示を展開させる
if (START_X+CNT_X >=1000) START_X=1000-CNT_X;
}
// 左下
if ( XX < LAT_X1 && YY > LAT_Y2 ) {
if (FLG_Y==false) START_Y++;
START_X--;
if (START_X <=-1 ) START_X=0;
if (START_Y+CNT_Y >=1000) START_Y=1000-CNT_Y;
}
// 下
if (XX > LAT_X1 && XX < LAT_X2 && YY > LAT_Y2) {
if (FLG_Y==false) START_Y++;
if (START_Y+CNT_Y >=1000) START_Y=1000-CNT_Y;
}
// 右下
if (XX >LAT_X2 && YY > LAT_Y2){
if (FLG_Y==false) START_Y++;
if (FLG_X==false) START_X++;
if (START_X+CNT_X >=1000) START_X=1000-CNT_X;
if (START_Y+CNT_Y >=1000) START_Y=1000-CNT_Y;
}
this.Dispatcher.Invoke((Action)(() =>{
// Title="MATRIX_X,Y="+START_X+","+START_Y+ "/L_MOUSE="+XX+ ","+YY +"/R="+CIRCEL_R+"/SPEED"+SPEED +"/CNT_X,Y="+CNT_X+ ","+CNT_Y;
MainCanvas.InvalidateVisual();
MapCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}));
}
});
}
// 描画
void MainPaintSurface(object sender, SKPaintSurfaceEventArgs args){
var CAX=args.Info.Width;
var CAY=args.Info.Height;
int XX=10;
int YY=10;
int CAS_Y= 0;
if (CIRCEL_R == 9) {
XX=9;
YY=9;
}
if (CIRCEL_R == 8) {
XX=8;
YY=8;
}
if (CIRCEL_R == 7) {
XX=7;
YY=7;
}
args.Surface.Canvas.Clear(SKColors.Black);
for (int y=START_Y;y<START_Y+CNT_Y;y++){
for (int x = START_X; x < START_X+CNT_X; x++) {
if (x>=999){
FLG_X=true;
continue;
}
else FLG_X=false;
if (y>=999){
FLG_Y=true;
continue;
}
else FLG_Y=false;
CAS_Y=0;
if(CIRCEL_R <= 9) {
XX += 1;
CAS_Y=1;
}
if(CIRCEL_R == 10) {
XX += 2;
CAS_Y=2;
}
if(CIRCEL_R == 11) {
XX += 4;
CAS_Y=4;
}
if(CIRCEL_R == 12) {
XX += 6;
CAS_Y=6;
}
if(CIRCEL_R == 13) {
XX += 8;
CAS_Y=8;
}
if(CIRCEL_R == 14) {
XX += 10;
CAS_Y=10;
}
if(CIRCEL_R == 15) {
XX += 12;
CAS_Y=12;
}
if ( mat[y,x] == 0 && D1_CHK.IsChecked == true) args.Surface.Canvas.DrawCircle (XX,YY+CAS_Y,CIRCEL_R,LV1_LINE);
if ( mat[y,x] == 1 && D2_CHK.IsChecked == true) args.Surface.Canvas.DrawCircle (XX,YY+CAS_Y,CIRCEL_R,LV2_LINE);
if ( mat[y,x] == 2 && D3_CHK.IsChecked == true) args.Surface.Canvas.DrawCircle (XX,YY+CAS_Y,CIRCEL_R,LV3_LINE);
if ( mat[y,x] == 3 && D4_CHK.IsChecked == true) args.Surface.Canvas.DrawCircle (XX,YY+CAS_Y,CIRCEL_R,LV4_LINE);
if (CIRCEL_R==7) XX+=15;
if (CIRCEL_R==8) XX+=17;
if (CIRCEL_R==9) XX+=19;
if (CIRCEL_R>=10) XX+=20;
}
if (CIRCEL_R ==7){
XX =7;
YY+=15+CAS_Y;
}
if (CIRCEL_R ==8){
XX =8;
YY+=17+CAS_Y;
}
if (CIRCEL_R ==9){
XX =9;
YY+=19+CAS_Y;
}
if (CIRCEL_R >=10){
XX =10;
YY+=20+CAS_Y;
}
}
// MAIN格子
args.Surface.Canvas.DrawLine ((int)(CAX/3),0,(int)CAX/3,CAY,MAIN_XY_LINE);
args.Surface.Canvas.DrawLine ((int)(CAX/3*2),0,(int)CAX/3*2,CAY,MAIN_XY_LINE);
args.Surface.Canvas.DrawLine (0,(int)(CAY/3),CAX,(int)CAY/3,MAIN_XY_LINE);
args.Surface.Canvas.DrawLine (0,(int)(CAY/3*2),CAX,(int)(CAY/3*2),MAIN_XY_LINE);
}
// DisplayAreaMAP
void MapPaintSurface(object sender, SKPaintSurfaceEventArgs args){
args.Surface.Canvas.Clear(SKColors.Black);
// ヘッダ文字
MAP_NO.TextSize=16;
args.Surface.Canvas.DrawText ("DisplayAreaMap",55,23,MAP_NO);
// MAP枠
args.Surface.Canvas.DrawRect (15,45,205,205,MAP_RECT);
// XY中央線
args.Surface.Canvas.DrawLine (18,150,218,150,MAP_CENTER);
args.Surface.Canvas.DrawLine (115,47,115,248,MAP_CENTER);
// 数値
MAP_NO.TextSize=13;
args.Surface.Canvas.DrawText ("1",10,40,MAP_NO);
args.Surface.Canvas.DrawText ("1000",205,40,MAP_NO);
args.Surface.Canvas.DrawText ("1000",0,265,MAP_NO);
args.Surface.Canvas.DrawText ("500",105,40,MAP_NO);
args.Surface.Canvas.DrawText ("500",105,40,MAP_NO);
args.Surface.Canvas.DrawText ("500",5,165,MAP_NO);
// XY補助線
dashArray[0] = 0.21f; //0.21 2.5 2.5
dashArray[1] = 2.5f;
args.Surface.Canvas.DrawLine (16,100,218,100,XY_ARAY);
args.Surface.Canvas.DrawLine (16,200,218,200,XY_ARAY);
args.Surface.Canvas.DrawLine (65,47,65,248,XY_ARAY);
args.Surface.Canvas.DrawLine (167,47,167,248,XY_ARAY);
// MAP赤丸
int MX2=((CNT_X/2)+START_X)/5;
int MY2=((CNT_Y/2)+START_Y)/5;
if((int)MainCanvas.ActualWidth < 500) {
args.Surface.Canvas.DrawCircle(MX2+16, MY2+45, 6, MAP_MARK);
return;
}
if((int)MainCanvas.ActualWidth < 1000) {
args.Surface.Canvas.DrawCircle (MX2+17,MY2+47,6,MAP_MARK);
return;
}
if((int)MainCanvas.ActualWidth < 1500) {
args.Surface.Canvas.DrawCircle (MX2+15,MY2+47,6,MAP_MARK);
return;
}
if((int)MainCanvas.ActualWidth < 3000) {
args.Surface.Canvas.DrawCircle (MX2+6,MY2+47,6,MAP_MARK);
return;
}
}
void TopPaintSurface(object sender, SKPaintSurfaceEventArgs args){
args.Surface.Canvas.Clear(SKColors.Black);
args.Surface.Canvas.DrawText ("RadiationExposure TDR System",args.Info.Width/2,38,TOP_TITLE);
}
// ALLDATA CIRCLE ALLCircle_PaintSurface
void ALLCircle_PaintSurface(object sender, SKPaintSurfaceEventArgs args){
args.Surface.Canvas.Clear(SKColors.Black);
int code1=0,code2=0,code3=0,code4=0;
for (int y=0;y<1000;y++){
for(int x = 0; x < 1000; x++) {
if (mat[y,x] == 0) code1++;
if (mat[y,x] == 1) code2++;
if (mat[y,x] == 2) code3++;
if (mat[y,x] == 3) code4++;
}
}
int SS1=code1/10000*36;
int SS2=code2/10000*36;
int SS3=code3/10000*36;
double X4,Y4;
for(int h = 00; h < SS1; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV1_LINE);
}
for(int h= SS1; h < SS1+SS2; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV2_LINE);
}
for(int h= SS1+SS2; h < SS1+SS2+SS3; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV3_LINE);
}
for(int h = SS1+SS2+SS3; h < 3600; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV4_LINE);
}
args.Surface.Canvas.DrawCircle (115,95,70,DATA_CIRCLE);
MAP_NO.TextSize=16;
args.Surface.Canvas.DrawText ("AllData",92,17,MAP_NO);
NUM_NO.Color=new SKColor (0,255,0);
args.Surface.Canvas.DrawText ("Alpha",47,190,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code1.ToString()+ " "+(code1/10000).ToString()+"%",107,190,NUM_NO);
NUM_NO.Color=new SKColor (0,0,255);
args.Surface.Canvas.DrawText ("Beta",52,205,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code2.ToString()+ " "+(code2/10000).ToString()+"%",107,205,NUM_NO);
NUM_NO.Color=new SKColor (255,0,0);
args.Surface.Canvas.DrawText ("Gamma",42,220,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code3.ToString()+ " "+(code3/10000).ToString()+"%",107,220,NUM_NO);
NUM_NO.Color=new SKColor (0,255,255);
args.Surface.Canvas.DrawText ("Unknown",37,235,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code4.ToString()+ " "+(code4/10000).ToString()+"%",107,235,NUM_NO);
// 区切線
args.Surface.Canvas.DrawLine (40,250,190,250,LV1_LINE
}
// CRENT DATA CIRCLE [All]
void CrentA_CirclePaintSurface(object sender, SKPaintSurfaceEventArgs args){
int code1=0,code2=0,code3=0,code4=0;
for (int y=START_Y ;y<START_Y+CNT_Y;y++){
for(int x = START_X; x < START_X+CNT_X; x++) {
if (y<=999 && x<=999) {
if (mat[y,x] == 0 && D1_CHK.IsChecked == true) code1++;
if (mat[y,x] == 1 && D2_CHK.IsChecked == true) code2++;
if (mat[y,x] == 2 && D3_CHK.IsChecked == true) code3++;
if (mat[y,x] == 3 && D4_CHK.IsChecked == true) code4++;
}
}
}
double FD=CNT_X * CNT_Y;
double SS1=code1 / FD * 3600;
double SS2=code2 / FD * 3600;
double SS3=code3 / FD * 3600;
double SS4=code4 / FD * 3600;
args.Surface.Canvas.Clear(SKColors.Black);
double X4,Y4;
for(int h = 00; h < (int)SS1; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV1_LINE);
}
for(int h = (int)SS1; h < (int)(SS1+SS2); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV2_LINE);
}
for(int h = (int)(SS1+SS2); h < (int)(SS1+SS2+SS3); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV3_LINE);
}
for(int h = (int)(SS1+SS2+SS3); h < (int)(SS1+SS2+SS3+SS4); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 96 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 96, (int)X4, (int)Y4, LV4_LINE);
}
args.Surface.Canvas.DrawCircle (116,96,70,DATA_CIRCLE);
MAP_NO.TextSize=16;
args.Surface.Canvas.DrawText ("DisplayData(All)",55,19,MAP_NO);
int CN=CNT_X*CNT_Y;
if (CN==0) return;
double xp;
xp=code1/(double)CN*100f;
NUM_NO.Color=new SKColor (0,255,0);
args.Surface.Canvas.DrawText ("Alpha",52,190,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code1.ToString("0000")+" "+xp.ToString("00.0")+"%",110,190,NUM_NO);
xp=code2/(double)CN*100.0;
NUM_NO.Color=new SKColor (0,0,255);
args.Surface.Canvas.DrawText ("Beta",56,205,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code2.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,205,NUM_NO);
xp=code3/(double)CN*100.0;
NUM_NO.Color=new SKColor (255,0,0);
args.Surface.Canvas.DrawText ("Gamma",46,220,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code3.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,220,NUM_NO);
xp=code4/(double)CN*100.0;
NUM_NO.Color=new SKColor (0,255,255);
args.Surface.Canvas.DrawText ("Unknown",43,235,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code4.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,235,NUM_NO);
// 区切線
args.Surface.Canvas.DrawLine (40,250,190,250,LV1_LINE);
}
// CRENT DATA CIRCLE [CHK.BOX SELECT]
void CrentB_CirclePaintSurface(object sender, SKPaintSurfaceEventArgs args){
int code1=0,code2=0,code3=0,code4=0;
for (int y=START_Y ;y<START_Y+CNT_Y;y++){
for(int x = START_X; x < START_X+CNT_X; x++) {
if (y<=999 && x<=999) {
if (mat[y,x] == 0 && D1_CHK.IsChecked == true) code1++;
if (mat[y,x] == 1 && D2_CHK.IsChecked == true) code2++;
if (mat[y,x] == 2 && D3_CHK.IsChecked == true) code3++;
if (mat[y,x] == 3 && D4_CHK.IsChecked == true) code4++;
}
}
}
double FD=code1+code2+code3+code4;
double SS1=code1 / FD * 3600;
double SS2=code2 / FD * 3600;
double SS3=code3 / FD * 3600;
double SS4=code4 / FD * 3600;
args.Surface.Canvas.Clear(SKColors.Black);
double X4,Y4;
for(int h = 00; h < (int)SS1; h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 102 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 102, (int)X4, (int)Y4, LV1_LINE);
}
for(int h = (int)SS1; h < (int)(SS1+SS2); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 102 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 102, (int)X4, (int)Y4, LV2_LINE);
}
for(int h = (int)(SS1+SS2); h < (int)(SS1+SS2+SS3); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 102 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 102, (int)X4, (int)Y4, LV3_LINE);
}
for(int h = (int)(SS1+SS2+SS3); h < (int)(SS1+SS2+SS3+SS4); h++) {
X4 =116 + 70 * Math.Sin(h * Math.PI / 1800);
Y4 = 102 - 70 * Math.Cos(h * Math.PI / 1800);
args.Surface.Canvas.DrawLine(116, 102, (int)X4, (int)Y4, LV4_LINE);
}
args.Surface.Canvas.DrawCircle (116,102,70,DATA_CIRCLE);
MAP_NO.TextSize=16;
args.Surface.Canvas.DrawText ("DisplayData(Select)",46,25,MAP_NO);
// int CN=CNT_X*CNT_Y;
//if (CN==0) return;
double xp;
xp=code1/(double)FD*100f;
NUM_NO.Color=new SKColor (0,255,0);
args.Surface.Canvas.DrawText ("Alpha",52,198,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code1.ToString("0000")+" "+xp.ToString("00.0")+"%",110,198,NUM_NO);
xp=code2/(double)FD*100.0;
NUM_NO.Color=new SKColor (0,0,255);
args.Surface.Canvas.DrawText ("Beta",56,213,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code2.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,213,NUM_NO);
xp=code3/(double)FD*100.0;
NUM_NO.Color=new SKColor (255,0,0);
args.Surface.Canvas.DrawText ("Gamma",46,228,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code3.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,228,NUM_NO);
xp=code4/(double)FD*100.0;
NUM_NO.Color=new SKColor (0,255,255);
args.Surface.Canvas.DrawText ("Unknown",43,243,NUM_NO);
NUM_NO.Color=new SKColor (255,255,255);
args.Surface.Canvas.DrawText (code4.ToString("0000")+ " "+xp.ToString("00.0")+"%",110,243,NUM_NO);
// 区切線
args.Surface.Canvas.DrawLine (40,257,190,257,LV1_LINE);
NUM_NO.TextSize=15;
args.Surface.Canvas.DrawText ("StartingPoint X"+START_X.ToString() +" / Y"+START_Y.ToString(),30,285,NUM_NO);
args.Surface.Canvas.DrawText ("X,Y COUNT X"+CNT_X.ToString()+" / Y"+CNT_Y.ToString(),30,300,NUM_NO);
args.Surface.Canvas.DrawText ("TOTAL "+(CNT_X * CNT_Y).ToString(),30,315,NUM_NO);
}
private void MainCanvas_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) {
if (e.Delta > 0 ){
CIRCEL_R++;
if (CIRCEL_R >=16 ) CIRCEL_R=15;
}
if (e.Delta <0 ){
CIRCEL_R--;
if (CIRCEL_R <=7 ) CIRCEL_R=7;
}
CanvasWidthHighALU();
MainCanvas.InvalidateVisual();
}
private void MainCanvas_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) {
MOUSE_IN=false;
}
private void MainCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
LEFT_BTN=true;
if (RIGHT_BTN==true ) SPEED=25;
if (RIGHT_BTN==false) SPEED=50;
}
private void MainCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
LEFT_BTN=false;
if (RIGHT_BTN==false) SPEED=100;
if (RIGHT_BTN==true ) SPEED=20;
}
private void MainCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) {
RIGHT_BTN=true;
if (LEFT_BTN==false) SPEED=20;
if (LEFT_BTN==true) SPEED=25;
}
// MAP L-BUTTON ON
private void MapCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
MAP_LEFT_BTN=true;
MapCanvasGetMouseXY (sender,e);
MainCanvas.InvalidateVisual();
MapCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
void MapCanvasGetMouseXY(object sender, MouseEventArgs e) {
var mainWindow = Application.Current.MainWindow;
Matrix m = PresentationSource.FromVisual(mainWindow).CompositionTarget.TransformToDevice;
var dpiScaleX = m.M11;
var dpiScaleY = m.M22;
var pixelPosition = e.GetPosition(sender as Canvas);
var scaledPixelPosition = new System.Windows.Point(pixelPosition.X * dpiScaleX, pixelPosition.Y * dpiScaleY);
// ローカルマウス現在位置
XX=(int)scaledPixelPosition.X;
YY=(int)scaledPixelPosition.Y-(int)H1.ActualHeight;
if (XX-(int)MainCanvas.ActualWidth-13<=0) return;
// if (XX-(int)MainCanvas.ActualWidth-13>=200) return;
if ( (YY-46) <=0 ) return;
// if ( (YY-46) >=196) return;
//CanvasWidthHighALU();
START_X=(XX-(int)MainCanvas.ActualWidth-13)*5;
START_Y=(YY-46)*5;
if (START_X+CNT_X >=1000) START_X=1000-CNT_X;
if (START_Y+CNT_Y >=1000) START_Y=1000-CNT_Y;
}
// MAP移動
private void MapCanvas_PreviewMouseMove(object sender, MouseEventArgs e) {
if (MAP_LEFT_BTN==false) return;
MapCanvasGetMouseXY (sender,e);
MainCanvas.InvalidateVisual();
MapCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
// MAP 移動キャンセル
private void MapCanvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) {
MAP_LEFT_BTN=false;
}
private void D1_CHK_Click(object sender, RoutedEventArgs e) {
MainCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
private void D3_CHK_Click(object sender, RoutedEventArgs e) {
MainCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
private void D4_CHK_Click(object sender, RoutedEventArgs e) {
MainCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
private void D2_CHK_Click(object sender, RoutedEventArgs e) {
MainCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
private void MainCanvas_MouseRightButtonUp(object sender, MouseButtonEventArgs e) {
RIGHT_BTN = false;
if (LEFT_BTN ==true ) SPEED = 50;
if (LEFT_BTN ==false ) SPEED =100;
}
private void MainCanvas_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) {
MOUSE_IN=true;
MAP_LEFT_BTN=false;
}
// 表示させる個数の算出
public void CanvasWidthHighALU() {
if (CIRCEL_R >= 2 && CIRCEL_R<=6){
CNT_X= (int)MainCanvas.ActualWidth /17;
CNT_Y= (int)MainCanvas.ActualHeight /16;
}
if (CIRCEL_R == 7 ){
CNT_X= (int)MainCanvas.ActualWidth /16;
CNT_Y= (int)MainCanvas.ActualHeight /16;
}
if (CIRCEL_R == 8 ){
CNT_X= (int)MainCanvas.ActualWidth /18;
CNT_Y= (int)MainCanvas.ActualHeight /18;
}
if (CIRCEL_R == 9 ){
CNT_X= (int)MainCanvas.ActualWidth /20;
CNT_Y= (int)MainCanvas.ActualHeight /20;
}
if (CIRCEL_R == 10 ){
CNT_X= (int)MainCanvas.ActualWidth /22;
CNT_Y= (int)MainCanvas.ActualHeight /22;
}
if (CIRCEL_R == 11 ){
CNT_X= (int)MainCanvas.ActualWidth /24;
CNT_Y= (int)MainCanvas.ActualHeight /24;
}
if (CIRCEL_R == 12 ){
CNT_X= (int)MainCanvas.ActualWidth /26;
CNT_Y= (int)MainCanvas.ActualHeight /26;
}
if (CIRCEL_R == 13 ){
CNT_X= (int)MainCanvas.ActualWidth /28;
CNT_Y= (int)MainCanvas.ActualHeight /28;
}
if (CIRCEL_R == 14 ){
CNT_X= (int)MainCanvas.ActualWidth /30;
CNT_Y= (int)MainCanvas.ActualHeight /30;
}
if (CIRCEL_R == 15 ){
CNT_X= (int)MainCanvas.ActualWidth /32;
CNT_Y= (int)MainCanvas.ActualHeight /32;
}
}
private void MainCanvas_SizeChanged(object sender, SizeChangedEventArgs e) {
// メインXY格子
LAT_X1=(int)MainCanvas.ActualWidth /3;
LAT_X2=LAT_X1*2;
LAT_Y1= (int)MainCanvas.ActualHeight /3 ;
LAT_Y2=LAT_Y1*2;
// CNT_X CNT_Y算出
CanvasWidthHighALU();
// START_X が大きい時、画面左を左にリサイズした時、START_Xを順次補正して右側に表示を展開させる
if (START_X+CNT_X >=1000) START_X=1000-CNT_X;
// Y軸
if (START_Y+CNT_Y >=1000) START_Y=1000-CNT_Y;
MainCanvas.InvalidateVisual();
CrentA_CIRCLECanvas.InvalidateVisual();
CrentB_CIRCLECanvas.InvalidateVisual();
}
// ローカルマウス現在位置
private void MainCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) {
var mainWindow = Application.Current.MainWindow;
Matrix m = PresentationSource.FromVisual(mainWindow).CompositionTarget.TransformToDevice;
var dpiScaleX = m.M11;
var dpiScaleY = m.M22;
var pixelPosition = e.GetPosition(sender as Canvas);
var scaledPixelPosition = new System.Windows.Point(pixelPosition.X * dpiScaleX, pixelPosition.Y * dpiScaleY);
// ローカルマウス現在位置
XX=(int)scaledPixelPosition.X;
YY=(int)scaledPixelPosition.Y-(int)H1.ActualHeight;
}
private System.Drawing.Color GetPixelColorAt(UIElement visualElement,int x,int y){
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)visualElement.RenderSize.Width, (int)visualElement.RenderSize.Height, 96, 96, PixelFormats.Pbgra32);
renderBitmap.Render(visualElement);
byte[] pixels = new byte[4]; // BGRA format, 4 bytes
renderBitmap.CopyPixels(new Int32Rect(x, y, 1, 1), pixels, 4, 0);
System.Drawing.Color color = System.Drawing.Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
return color;
}
}
}
5.WPF XAML
<!-- ///////////////////////////////////////////////////////////////// -->
<!-- RadiationExposure VisualAid And RealTimeRenderingSystem TestType -->
<!-- inf102 S.H 2025. -->
<!-- ///////////////////////////////////////////////////////////////// -->
<Window x:Class="SkiaSharpSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SkiaSharpSample"
xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF"
xmlns:wpf="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" mc:Ignorable="d" Title="RadiationExposure VisualAid And RealTimeRenderingSystem"
Loaded="Window_Loaded" Height="1270" Width="1800" Background="Black">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="35" x:Name="H1"/>
<RowDefinition Height="271"/>
<RowDefinition Height="260"/>
<RowDefinition Height="252"/>
<RowDefinition Height="318"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="250" x:Name="W2"/>
</Grid.ColumnDefinitions>
<wpf:SKElement x:Name="MainCanvas" PaintSurface="MainPaintSurface" Grid.Row="1" Grid.Column="0" MouseMove="MainCanvas_MouseMove" MouseWheel="MainCanvas_MouseWheel" SizeChanged="MainCanvas_SizeChanged" MouseLeave="MainCanvas_MouseLeave" MouseEnter="MainCanvas_MouseEnter" MouseLeftButtonDown="MainCanvas_MouseLeftButtonDown" MouseLeftButtonUp="MainCanvas_MouseLeftButtonUp" MouseRightButtonDown="MainCanvas_MouseRightButtonDown" MouseRightButtonUp="MainCanvas_MouseRightButtonUp" Grid.RowSpan="5" />
<wpf:SKElement x:Name="MapCanvas" PaintSurface="MapPaintSurface" Grid.Row="1" Grid.Column="1" PreviewMouseLeftButtonDown="MapCanvas_PreviewMouseLeftButtonDown" PreviewMouseMove="MapCanvas_PreviewMouseMove" PreviewMouseLeftButtonUp="MapCanvas_PreviewMouseLeftButtonUp" Grid.RowSpan="1" />
<wpf:SKElement x:Name="TopCanvas" PaintSurface="TopPaintSurface" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,-10,0,0" />
<wpf:SKElement x:Name="All_CIRCLECanvas" PaintSurface="ALLCircle_PaintSurface" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" />
<wpf:SKElement x:Name="CrentA_CIRCLECanvas" PaintSurface="CrentA_CirclePaintSurface" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" />
<wpf:SKElement x:Name="CrentB_CIRCLECanvas" PaintSurface="CrentB_CirclePaintSurface" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="1" Grid.RowSpan="1" />
<StackPanel Orientation="Vertical" Grid.Row="5" Grid.Column="1">
<Label Content=" Enable" Foreground="White" FontSize="16" />
<StackPanel Orientation="Horizontal" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Center" Width="246" Height="80" VerticalAlignment="Top" >
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="32,-20,2,2">
<CheckBox Foreground="#00FF00" IsChecked="True" FontSize="19" x:Name="D1_CHK" Content="Alpha" Margin="2,0,2,2" VerticalAlignment="Top" Click="D1_CHK_Click"/>
<CheckBox IsChecked="True" FontSize="19" Foreground="#FF0000" x:Name="D3_CHK" Content="Gamma" Margin="2,0,2,2" VerticalAlignment="Center" Click="D3_CHK_Click"/>
</StackPanel>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="20,-20,2,2">
<CheckBox IsChecked="True" FontSize="19" Foreground="#0000FF" x:Name="D2_CHK" Content="Beta" Margin="2,0,2,2" VerticalAlignment="Top" Click="D2_CHK_Click"/>
<CheckBox IsChecked="True" FontSize="19" Foreground="#00FFFF" x:Name="D4_CHK" Content="Unknown" Margin="2,0,2,2" VerticalAlignment="Center" Click="D4_CHK_Click"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Window>