用OxyPlot在WPF中演示正演磁异常的变化规律
为了在展示实验成果时动态演示理论球体磁异常随其埋深、磁化倾角的变化规律,我用WPF写了一个小程序来作演示。
MatLab计算磁异常数据
首先是计算理论球体磁异常数据,在Matlab中可以很方便地计算。
为了在展示时能够同时改变磁化倾角(is)、埋深(Deep),计算数据时套了两层循环,外层是is从0到90°,内层是Deep从10到100m,里面计算一条剖面上的Za和Hax磁异常数据。实现代码如下:
function Za=sphere_deeps()
% 测点分布范围
dx=5; % X方向测点间距
nx=81; % X方向测点数
xmin=-200; % X方向起点
x=xmin:dx:(xmin+(nx-1)*dx); % X方向范围
u=4*pi*10^(-7); %磁导率
i=pi/2; %有效磁化倾角is
a=0; %剖面磁方位角
T=50000;%地磁场T=50000nT
% 球体参数
R1=10; % 球体半径 m
%D1=30; % 球体埋深 m
v1=4*pi*R1^3;
k=0.2; %磁化率
M1=k*T/u; %磁化强度 A/m
m1=M1*v1; %磁矩
% 球体 理论磁异常主剖面
%(x-0),(y-0)
y=0;
Za=zeros(46,nx);
Hax=zeros(46,nx);
fp=fopen('za_all.out','w');
for ii=0:90
i=ii*pi/180;
for j=0:45
D1=10+j*2;
Za0=(u*m1*((2*D1.^2-x.^2-y.^2)*sin(i)-3*D1*x.*cos(i)*cos(a)-3*D1*y.*cos(i)*sin(a)))./(4*pi*(x.^2+y.^2+D1.^2).^(5/2));
for k=1:nx
fprintf(fp,'%g ',Za0(k));
end
fprintf(fp,'\n');
end
end
fclose(fp);
fp=fopen('hax_all.out','w');
for ii=0:90
i=ii*pi/180;
for j=0:45
D1=10+j*2;
Hax0=(u*m1*((2*x.^2-y.^2-D1.^2)*cos(i)*cos(a)-3*D1*x.*sin(i)+3*x.*y.*cos(i)*sin(a)))./(4*pi*(x.^2+y.^2+D1.^2).^(5/2));
for k=1:nx
fprintf(fp,'%g ',Hax0(k));
end
fprintf(fp,'\n');
end
end
fclose(fp);
最后是将所有数据都输出至za_all.out
以及hax_all.out
文件中,其中有91(is从0-90°)*46(Deep从10-100m,间隔2m)行数据,每一行中都有nx(81,测线上的点数)个数据。
C#处理数据文件
首先将之前的za_all.out
以及hax_all.out
文件复制到WPF项目中,并且对其设置属性为“内容”,并“始终复制”。
将数据读取后分别存储在一个三维数组中,即倾角*深度*测点
这样的结构。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Resources;
using System.Windows;
using System.Windows.Resources;
namespace GeoMag_Viewer
{
class Values
{
private int iNum = 91;
private int jNum = 81;
public double[, ,] Za3D
{
get;
private set;
}
public double[, ,] Hax3D
{
get;
private set;
}
public Values()
{
StreamResourceInfo za3DInfo = Application.GetContentStream(new Uri("Resources/za_all.out", UriKind.Relative));
var za3DStreamReader = new StreamReader(za3DInfo.Stream);
string content = za3DStreamReader.ReadToEnd();
string[] lines = content.Split(new string[] { " \n" }, StringSplitOptions.None);
Za3D = new Double[91, 46, jNum];
for (int l = 0; l < 91; l++)
{
for (int i = 0; i < 46; i++)
{
int index = l * 46 + i;
string[] words = lines[index].Split(new string[] { " " }, StringSplitOptions.None);
for (int j = 0; j < jNum; j++)
{
Za3D[l, i, j] = Double.Parse(words[j]);
}
}
}
StreamResourceInfo hax3DInfo = Application.GetContentStream(new Uri("Resources/hax_all.out", UriKind.Relative));
var hax3DStreamReader = new StreamReader(hax3DInfo.Stream);
content = hax3DStreamReader.ReadToEnd();
lines = content.Split(new string[] { " \n" }, StringSplitOptions.None);
Hax3D = new Double[91, 46, jNum];
for (int l = 0; l < 91; l++)
{
for (int i = 0; i < 46; i++)
{
int index = l * 46 + i;
string[] words = lines[index].Split(new string[] { " " }, StringSplitOptions.None);
for (int j = 0; j < jNum; j++)
{
Hax3D[l, i, j] = Double.Parse(words[j]);
}
}
}
}
}
}
使用OxyPlot组件
为了在WPF中绘制曲线图,通过搜索找到了OxyPlot这个开源库,可以方便地绘制我想要的图形。
创建WPF项目后,打开NUGet程序包管理器
,搜索OxyPlot
,安装OxyPlot for wpf
。
Xaml代码如下:
<Window x:Class="GeoMag_Viewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:local="clr-namespace:GeoMag_Viewer"
Title="GeoMag Viewer" Height="350" Width="525">
<Grid Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<oxy:PlotView Grid.Column="0" Name="MyPlotView">
<oxy:PlotView.Series>
<oxy:LineSeries Name="ZaLine"/>
<oxy:LineSeries Name="HaxLine"/>
</oxy:PlotView.Series>
</oxy:PlotView>
<Image Grid.Column="0"
Name="SphereImage"
Source="Resources/ci.jpg"
HorizontalAlignment="Left"
Margin="150,0,0,0"
Width="150"
Height="150"
/>
<Slider Grid.Column="1" Name="DeepSlider"
Orientation="Vertical"
Margin="5,10,5,10"
ValueChanged="DeepSlider_ValueChanged"
Maximum="45"
Minimum="0"
TickFrequency="1"
TickPlacement="TopLeft"
/>
<TextBlock Grid.Column="2"
Name="DeepText"
FontSize="20"
FontWeight="Bold"
TextWrapping="Wrap"
VerticalAlignment="Center"
/>
</Grid>
<Slider Grid.Row="1"
Name="angleSlider"
ValueChanged="angleSlider_ValueChanged"
Margin="10,5,10,5"
Maximum="90"
Minimum="0"
TickFrequency="1"
TickPlacement="TopLeft"/>
<TextBlock Grid.Row="2"
Name="tickText"
FontSize="24"
FontWeight="Bold"
Margin="150,0,150,0"
HorizontalAlignment="Center"/>
</Grid>
</Window>
MainWindow.xaml.cs:
OxyPlot绘制曲线是是将Line.ItemSource设置为List,在这儿使用一个列表的二维数组分别保存Za、Hax异常。数组的第一个下标表示角度,第二个下标表示深度。
当用于控制角度、深度的Slider值变化时,分别调用angleSlider_ValueChanged
和DeepSlider_ValueChanged
来改变所要呈现的曲线,即
ZaLine.ItemsSource = Za3DLists[angleIndex, deepIndex];
HaxLine.ItemsSource = Hax3DLists[angleIndex, deepIndex];
这样,拖动Slider滑块,异常曲线就能跟着动态变化了,达到了演示效果。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OxyPlot;
using OxyPlot.Series;
using OxyPlot.Wpf;
using Microsoft.Win32;
namespace GeoMag_Viewer
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.WindowState = WindowState.Maximized;
Values v = new Values();
MyPlotView.Title = "Za/Hax与磁化倾角的关系Demo";
var valueAxis = new LinearAxis() { Title = "磁异常/nT" };
MyPlotView.Axes.Add(valueAxis);
MyPlotView.LegendFontSize = 20;
ZaLine.Title = "Za异常";
HaxLine.Title = "Hax异常";
tickText.Text = "磁化倾角is=0";
DeepText.Text = "球体埋深";
double[, ,] Za3D = v.Za3D;
double[, ,] Hax3D = v.Hax3D;
int lNum = Za3D.GetLength(0);//角度数
int iNum = Za3D.GetLength(1);//深度数
int jNum = Za3D.GetLength(2);//单测线点数
Za3DLists = new List<DataPoint>[lNum, iNum];
Hax3DLists = new List<DataPoint>[lNum, iNum];
for (int l = 0; l < lNum; l++)
{
for (int i = 0; i < iNum; i++)
{
Za3DLists[l, i] = new List<DataPoint>();
Hax3DLists[l, i] = new List<DataPoint>();
for (int j = 0; j < jNum; j++)
{
int x = -200 + j * 5;
Za3DLists[l, i].Add(new DataPoint(x, Za3D[l, i, j]));
Hax3DLists[l, i].Add(new DataPoint(x, Hax3D[l, i, j]));
}
}
}
angleIndex = 0;
deepIndex = 0;
ZaLine.ItemsSource = Za3DLists[angleIndex, deepIndex];
HaxLine.ItemsSource = Hax3DLists[angleIndex, deepIndex];
width = 100;
height=100;
RotateTransform rt = new RotateTransform(0,width/2,height/2);
SphereImage.RenderTransform = rt;
}
double width;
double height;
private void angleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (tickText == null)
{
return;
}
int angle = (int)e.NewValue;
int iAngle = angle;
angleIndex = iAngle;
tickText.Text = "磁化倾角is=" + angle;
ZaLine.ItemsSource = Za3DLists[angleIndex, deepIndex];
HaxLine.ItemsSource = Hax3DLists[angleIndex, deepIndex];
//旋转球体图像
//width / 2, height / 2 使绕图像中心旋转
RotateTransform rt = new RotateTransform(angle, width / 2, height / 2);
SphereImage.RenderTransform = rt;
}
private void DeepSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (DeepText == null)
{
return;
}
int iDeep = (int)e.NewValue;
int deep = 10 + 2 * iDeep;
deepIndex = iDeep;
DeepText.Text = "球体埋深\n" + deep+"m";
ZaLine.ItemsSource = Za3DLists[angleIndex, deepIndex];
HaxLine.ItemsSource = Hax3DLists[angleIndex, deepIndex];
}
//角度*深度
public List<DataPoint>[,] Za3DLists
{
get;
private set;
}
//角度*深度
public List<DataPoint>[,] Hax3DLists
{
get;
private set;
}
public int angleIndex
{
get;
private set;
}
public int deepIndex
{
get;
private set;
}
}
}
另外,我还在程序中用了一个球体磁场图像,让它随着角度Slider的改变而旋转相应的角度,其实现也很简单,再次不再赘述。
版权声明:本文为博主原创文章,未经博主允许不得转载。
用OxyPlot在WPF中演示正演磁异常的变化规律的更多相关文章
- 在WPF中制作正圆形公章
原文:在WPF中制作正圆形公章 之前,我利用C#与GDI+程序制作过正圆形公章(利用C#制作公章 ,C#制作公章[续])并将它集成到一个小软件中(个性印章及公章的画法及实现),今天我们来探讨一下WPF ...
- 使用OxyPlot在WPF中创建图表
目录(?)[+] Using Nuget 包括OxyPlot在你的应用程序的最简单方法是使用NuGet包管理器在Visual Studio 运行 Visual Studio并开始创建一个新的WPF项目 ...
- MVVM模式和在WPF中的实现(二)数据绑定
MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
- WPF入门教程系列十五——WPF中的数据绑定(一)
使用Windows Presentation Foundation (WPF) 可以很方便的设计出强大的用户界面,同时 WPF提供了数据绑定功能.WPF的数据绑定跟Winform与ASP.NET中的数 ...
- WPF中查看PDF文件
需要打开PDF文件时,我们第一印象就是使用Adobe Reader.在开发中,经常会遇到需要展示PDF文件的需求.我们会借助于Adobe Reader的Active控件来实现.不过这需要客户的机器上安 ...
- WPF中使用ReportViewer报表
本篇博客将介绍如何在WPF中使用ReportViewer控件. 1. 环境准备:下载安装最新版ReportViewer(PS:需要安装Microsoft SQL Server System CLR T ...
- WPF中嵌入普通Win32程序的方法
公司现在在研发基于.Net中WPF技术的产品,由于要兼容旧有产品,比如一些旧有的Win32程序.第三方的Win32程序等等,还要实现自动登录这些外部Win32程序,因此必须能够将这些程序整合到我们的系 ...
- ckrule规则编辑器在wpf中的使用
当前,ckrule的IDE和业务管理系统都是由winform开发的,规则编辑器也只提供了winform的版本,所以很多的朋友都提出意见,要有wpf的版本.wpf的界面设置和管理都更加的方便. 事实上可 ...
- WPF多线程演示
WPF中的几种处理线程的工作方式: 1.简单的DispatcherTimer类似Timer控件 2.需要处理UI同步时,Dispatcher DispatcherOpertion 3.增强的Threa ...
随机推荐
- sql server sys.object表字段说明
列名 数据类型 说明 name sysname 对象名. object_id int 对象标识号. 在数据库中是唯一的. principal_id int 如果不是架构所有者,则为单个所有者的 ID. ...
- 可以通过Action来判断是什么操作触发了事件
ObservableCollection<T>当这个集合发生改变后会有相应的事件得到通知请看如下代码: static void Main(string[] args) { var a = ...
- CSS实例:水平居中和垂直居中的多种解决方案
1.单行垂直居中 文字在层中垂直居中vertical-align 属性是做不到的.我们这里有个比较巧妙的方法就是:设置height的高度与line-height的高度相同! Example Sourc ...
- 远程控制利器TeamViewer使用教程(图)
TeamViewer是什么? 他是一款免费的可以穿透内网的远程控制软件,可以实现桌面共享,文件传送等功能,简单一点说就是和QQ远程协助一样,但是比QQ的远程协助功能更为强大. TeamViewer与木 ...
- 【原】YUI Test自动化测试实例详解
测试在软件开发中至关重要,目前针对不同的开发语言,都有比较成熟的测试框架,如jUnit,cUnit,cppUnit,nUnit等,我们统称为xUnit,他们的都遵守统一的规则: 针对代码测试 断言 启 ...
- Ubuntu14.04安装Mongodb
官网获取到最新的tgz包: 请查看自己的cpu这里是32位的. $sudo wget htps://fastdl.mongodb.org/linux/mongodb-linux-i686-2.6.7. ...
- HttpContext.Cache和Application的区别
原文:HttpContext.Cache和Application的区别 (转载) 应用程序级的Cache和Application用户会话级的Session application的缺点是在读取时最 ...
- 远程监控 – 应用程序运行状况测量 CSF 博客
在远程监控基础知识和故障排除中,我们探讨了 Windows Azure 平台提供的基础指标.信息源.工具和脚本,介绍了有关监控和应用程序运行状况的基本原则.我们演示了如何利用这些基本原则对在 Wind ...
- Hadoop HA部署
因为公司旧系统的Hadoop版本是2.2,所以在部署新系统时使用了旧系统. 但是在部署ResourceManager auto failover时发现其他nodemanager总是向0.0.0.0请求 ...
- string 转换char类型
将string转换成char类型 const char *c = string.c_str() char转换string char *c_name = "char" string ...