为了在展示实验成果时动态演示理论球体磁异常随其埋深、磁化倾角的变化规律,我用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_ValueChangedDeepSlider_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中演示正演磁异常的变化规律的更多相关文章

  1. 在WPF中制作正圆形公章

    原文:在WPF中制作正圆形公章 之前,我利用C#与GDI+程序制作过正圆形公章(利用C#制作公章 ,C#制作公章[续])并将它集成到一个小软件中(个性印章及公章的画法及实现),今天我们来探讨一下WPF ...

  2. 使用OxyPlot在WPF中创建图表

    目录(?)[+] Using Nuget 包括OxyPlot在你的应用程序的最简单方法是使用NuGet包管理器在Visual Studio 运行 Visual Studio并开始创建一个新的WPF项目 ...

  3. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  4. WPF入门教程系列十五——WPF中的数据绑定(一)

    使用Windows Presentation Foundation (WPF) 可以很方便的设计出强大的用户界面,同时 WPF提供了数据绑定功能.WPF的数据绑定跟Winform与ASP.NET中的数 ...

  5. WPF中查看PDF文件

    需要打开PDF文件时,我们第一印象就是使用Adobe Reader.在开发中,经常会遇到需要展示PDF文件的需求.我们会借助于Adobe Reader的Active控件来实现.不过这需要客户的机器上安 ...

  6. WPF中使用ReportViewer报表

    本篇博客将介绍如何在WPF中使用ReportViewer控件. 1. 环境准备:下载安装最新版ReportViewer(PS:需要安装Microsoft SQL Server System CLR T ...

  7. WPF中嵌入普通Win32程序的方法

    公司现在在研发基于.Net中WPF技术的产品,由于要兼容旧有产品,比如一些旧有的Win32程序.第三方的Win32程序等等,还要实现自动登录这些外部Win32程序,因此必须能够将这些程序整合到我们的系 ...

  8. ckrule规则编辑器在wpf中的使用

    当前,ckrule的IDE和业务管理系统都是由winform开发的,规则编辑器也只提供了winform的版本,所以很多的朋友都提出意见,要有wpf的版本.wpf的界面设置和管理都更加的方便. 事实上可 ...

  9. WPF多线程演示

    WPF中的几种处理线程的工作方式: 1.简单的DispatcherTimer类似Timer控件 2.需要处理UI同步时,Dispatcher DispatcherOpertion 3.增强的Threa ...

随机推荐

  1. 详解Activity的四种启动模式

    在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. Ac ...

  2. Why AIXTHREAD_SCOPE Should Be Set To 'S' On AIX

    In a multi-processor environment running on an AIX platform, if you are intending to use multi-threa ...

  3. 在一个RAC集群中最多支持多少节点

    How many nodes can one have in an HP-UX/Solaris/AIX/Windows/Linux cluster? Technically and since Ora ...

  4. Java 四种线程池的使用

    java线程线程池监控 Java通过Executors提供四种线程池,分别为: newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收 ...

  5. N皇后问题 深搜+剪枝 hdu-2553

    N 皇后问题在此就不多介绍了,相信CS的同学都应经清楚了,不清楚也可自行Google(听说国内用不了Google了?令人发指!).在此以一道例题为引. hdu-2553 1 #include < ...

  6. Android.Hacks.01_Centering views using weights

    Android.Hacks读书笔记01 #1#权重布局之解析: LinearLayout ’s android:weightSum      LinearLayout ’s child android ...

  7. Android L 之 RecyclerView 、CardView 、Palette

    转: http://blog.csdn.net/xyz_lmn/article/details/38735117 <Material Design>提到,Android L版本中新增了Re ...

  8. Linux06--Shell程序设计02 数据流重定向与管道

    包含3种数据流: •标准输入(stdin):代码为0,符号为<或<<; •标准输出(stdout):代码为1,符号为>或>>; •标准错误输出(stderr):代码 ...

  9. 使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法

    1. 简要说明 JLink的调试功能.烧写Flash的功能都很强大,但是对于S3C2410.S3C2440的Flash操作有些麻烦:烧写Nor Flash时需要设置SDRAM,否则速率很慢:烧写Nan ...

  10. Delphi 进阶基础技能说明

    以下讨论均基于Delphi XE8,主要是利用DELPHI新版的功能,如:Unicode,泛型,匿名函数等[XE2 后应该都支持]. 用新特性的好处是少写代码,提高效率.本博客不再讨论Delphi旧版 ...