实例介绍
【实例截图】
【核心代码】
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
namespace WPFCtrlLib
{
/// <summary>
/// 等高线图控件
/// </summary>
public partial class IsoHeightCtrl : UserControl
{
private const int grid_w = 10;
private const int grid_h = 10;
private double w;
private double h;
private int bitmap_w;
private int bitmap_h;
private int x_num;
private int y_num;
private float[,] data;
private float min;
private float max;
private byte[] Rs, Gs, Bs;
private Bitmap bitmap;
private Graphics graphics;
public IsoHeightCtrl()
{
InitializeComponent();
}
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
Draw();
}
/// <summary>
/// 离散高度点列表
/// XY总长为单位1
/// </summary>
public MeasureData[] HeightDots
{
get { return (MeasureData[])GetValue(HeightDotsProperty); }
set { SetValue(HeightDotsProperty, value); }
}
public static readonly DependencyProperty HeightDotsProperty =
DependencyProperty.Register("HeightDots", typeof(MeasureData[]), typeof(IsoHeightCtrl), new PropertyMetadata(null, (s, e) =>
{
IsoHeightCtrl ihc = s as IsoHeightCtrl;
ihc.Draw();
}));
/// <summary>
/// 颜色列表
/// 其数量决定了等高线的层数
/// </summary>
public string ColorList
{
get { return (string)GetValue(ColorListProperty); }
set { SetValue(ColorListProperty, value); }
}
public static readonly DependencyProperty ColorListProperty =
DependencyProperty.Register("ColorList", typeof(string), typeof(IsoHeightCtrl), new PropertyMetadata("#072FFA,#0779FA,#07C4FA,#07DFD0,#07FAA7,#79FA57,#ECFA07,#F3D307,#FAAD07,#F67207,#FA1207", (s, e) =>
{
IsoHeightCtrl ihc = s as IsoHeightCtrl;
ihc.ParseColor();
}));
/// <summary>
/// 绘制图形
/// </summary>
private void Draw()
{
if (HeightDots == null)
{
return;
}
w = this.ActualWidth;
h = this.ActualHeight;
if (w <= 0 || h <= 0)
{
return;
}
if (Rs == null)
{
ParseColor();
}
InitData();
CreateBitmap();
float gap = (max - min) / Rs.Length;
for (int i = 0; i < Rs.Length; i )
{
List<List<PointF>> shapes = CreateMapData(min i * gap);
DrawMap(shapes, i);
}
FinishDraw();
}
/// <summary>
/// 数据插值
/// </summary>
private void InitData()
{
x_num = (int)(w / grid_w);
y_num = (int)(h / grid_h);
data = new float[x_num, y_num];
IntMeasureData[] measure_data = new IntMeasureData[HeightDots.Length];
for (int i = HeightDots.Length - 1; i >= 0; i--)
{
measure_data[i] = new IntMeasureData(HeightDots[i], x_num, y_num);
}
min = float.MaxValue;
max = float.MinValue;
for (int i = 0; i < x_num; i )
{
for (int j = 0; j < y_num; j )
{
float value = 0;
bool find = false;
foreach (IntMeasureData imd in measure_data)
{
if (i == imd.X && j == imd.Y)
{
value = imd.Z;
find = true;
break;
}
}
if (!find)
{
double D = 0;
double DV = 0;
foreach (IntMeasureData imd in measure_data)
{
double d = 1.0 / ((imd.X - i) * (imd.X - i) (imd.Y - j) * (imd.Y - j));
D = d;
DV = imd.Z * d;
}
value = (float)(DV / D);
}
data[i, j] = value;
min = Math.Min(min, value);
max = Math.Max(max, value);
}
}
}
/// <summary>
/// 创建位图
/// </summary>
private void CreateBitmap()
{
bitmap_w = (x_num - 1) * grid_w;
bitmap_h = (y_num - 1) * grid_h;
bitmap = new Bitmap(bitmap_w, bitmap_h, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
graphics = Graphics.FromImage(bitmap);
}
/// <summary>
/// 获取某个阈值下的图形数据
/// </summary>
/// <param name="threshold">阈值</param>
/// <returns>图形数据</returns>
private List<List<PointF>> CreateMapData(float threshold)
{
byte[,] binary_data = new byte[x_num, y_num];
for (int i = 0; i < x_num; i )
{
for (int j = 0; j < y_num; j )
{
binary_data[i, j] = (byte)((data[i, j] >= threshold) ? 1 : 0);
}
}
List<List<PointF>> shapes = new List<List<PointF>>();
for (int i = 1; i < x_num; i )
{
for (int j = 1; j < y_num; j )
{
int num = (binary_data[i - 1, j - 1] << 3) (binary_data[i, j - 1] << 2) (binary_data[i, j] << 1) binary_data[i - 1, j];
List<PointF> points = new List<PointF>();
switch (num)
{
case 0:
break;
case 1:
AddLeft(points, i, j, threshold);
AddLeftBottom(points, i, j);
AddBottom(points, i, j, threshold);
break;
case 2:
AddRight(points, i, j, threshold);
AddRightBottom(points, i, j);
AddBottom(points, i, j, threshold);
break;
case 3:
AddLeft(points, i, j, threshold);
AddLeftBottom(points, i, j);
AddRightBottom(points, i, j);
AddRight(points, i, j, threshold);
break;
case 4:
AddTop(points, i, j, threshold);
AddRightTop(points, i, j);
AddRight(points, i, j, threshold);
break;
case 5:
AddLeft(points, i, j, threshold);
AddRightTop(points, i, j);
AddRight(points, i, j, threshold);
AddBottom(points, i, j, threshold);
AddLeftBottom(points, i, j);
AddLeft(points, i, j, threshold);
break;
case 6:
AddTop(points, i, j, threshold);
AddRightTop(points, i, j);
AddRightBottom(points, i, j);
AddBottom(points, i, j, threshold);
break;
case 7:
AddTop(points, i, j, threshold);
AddRightTop(points, i, j);
AddRightBottom(points, i, j);
AddLeftBottom(points, i, j);
AddLeft(points, i, j, threshold);
break;
case 8:
AddTop(points, i, j, threshold);
AddLeftTop(points, i, j);
AddLeft(points, i, j, threshold);
break;
case 9:
AddTop(points, i, j, threshold);
AddLeftTop(points, i, j);
AddLeftBottom(points, i, j);
AddBottom(points, i, j, threshold);
break;
case 10:
AddTop(points, i, j, threshold);
AddLeftTop(points, i, j);
AddLeft(points, i, j, threshold);
AddBottom(points, i, j, threshold);
AddRightBottom(points, i, j);
AddRight(points, i, j, threshold);
break;
case 11:
AddTop(points, i, j, threshold);
AddLeftTop(points, i, j);
AddLeftBottom(points, i, j);
AddRightBottom(points, i, j);
AddRight(points, i, j, threshold);
break;
case 12:
AddLeft(points, i, j, threshold);
AddRight(points, i, j, threshold);
AddRightTop(points, i, j);
AddLeftTop(points, i, j);
break;
case 13:
AddRight(points, i, j, threshold);
AddRightTop(points, i, j);
AddLeftTop(points, i, j);
AddLeftBottom(points, i, j);
AddBottom(points, i, j, threshold);
break;
case 14:
AddLeft(points, i, j, threshold);
AddBottom(points, i, j, threshold);
AddRightBottom(points, i, j);
AddRightTop(points, i, j);
AddLeftTop(points, i, j);
break;
case 15:
AddLeftTop(points, i, j);
AddRightTop(points, i, j);
AddRightBottom(points, i, j);
AddLeftBottom(points, i, j);
break;
}
if (num != 0)
{
shapes.Add(points);
}
}
}
return shapes;
}
/// <summary>
/// 绘制图形
/// </summary>
/// <param name="shapes">图形数据</param>
/// <param name="color_index">颜色索引</param>
private void DrawMap(List<List<PointF>> shapes, int color_index)
{
System.Drawing.Brush brush = new SolidBrush(Color.FromArgb(Rs[color_index], Gs[color_index], Bs[color_index]));
foreach (List<PointF> shape in shapes)
{
graphics.FillPolygon(brush, shape.ToArray());
}
}
/// <summary>
/// 完成绘制
/// </summary>
private void FinishDraw()
{
graphics.Dispose();
Container.Width = bitmap_w;
Container.Height = bitmap_h;
Container.Source = BitmapToBitmapSource(bitmap);
bitmap.Dispose();
}
private void AddLeft(List<PointF> list, int x, int y, float threshold)
{
list.Add(new PointF((x - 1) * grid_w, (y - 1 V(data[x - 1, y - 1], data[x - 1, y], threshold)) * grid_h));
}
private void AddRight(List<PointF> list, int x, int y, float threshold)
{
list.Add(new PointF(x * grid_w, (y - 1 V(data[x, y - 1], data[x, y], threshold)) * grid_h));
}
private void AddTop(List<PointF> list, int x, int y, float threshold)
{
list.Add(new PointF((x - 1 V(data[x - 1, y - 1], data[x, y - 1], threshold)) * grid_w, (y - 1) * grid_h));
}
private void AddBottom(List<PointF> list, int x, int y, float threshold)
{
list.Add(new PointF((x - 1 V(data[x - 1, y], data[x, y], threshold)) * grid_w, y * grid_h));
}
private void AddLeftTop(List<PointF> list, int x, int y)
{
list.Add(new PointF((x - 1) * grid_w, (y - 1) * grid_h));
}
private void AddRightTop(List<PointF> list, int x, int y)
{
list.Add(new PointF(x * grid_w, (y - 1) * grid_h));
}
private void AddLeftBottom(List<PointF> list, int x, int y)
{
list.Add(new PointF((x - 1) * grid_w, y * grid_h));
}
private void AddRightBottom(List<PointF> list, int x, int y)
{
list.Add(new PointF(x * grid_w, y * grid_h));
}
private float V(float min, float max, float threshold)
{
return (threshold - min) / (max - min);
}
/// <summary>
/// 转换颜色列表
/// </summary>
private void ParseColor()
{
string[] colors = ColorList.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int color_len = colors.Length;
Rs = new byte[color_len];
Gs = new byte[color_len];
Bs = new byte[color_len];
for (int i = color_len - 1; i >= 0; i--)
{
ParseColor(colors[i], out byte R, out byte G, out byte B);
Rs[i] = R;
Gs[i] = G;
Bs[i] = B;
}
}
private void ParseColor(string str, out byte R, out byte G, out byte B)
{
R = Convert.ToByte(str.Substring(1, 2), 16);
G = Convert.ToByte(str.Substring(3, 2), 16);
B = Convert.ToByte(str.Substring(5, 2), 16);
}
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// Bitmap转BitmapSource
/// </summary>
private BitmapSource BitmapToBitmapSource(Bitmap bitmap)
{
IntPtr ptr = bitmap.GetHbitmap();
BitmapSource result = Imaging.CreateBitmapSourceFromHBitmap(
ptr, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr);
return result;
}
}
/// <summary>
/// 测量数据
/// </summary>
public struct MeasureData
{
/// <summary>
/// 初始化测量数据
/// </summary>
/// <param name="x">坐标x</param>
/// <param name="y">坐标y</param>
/// <param name="z">高度</param>
public MeasureData(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
/// <summary>
/// 坐标X
/// </summary>
public float X;
/// <summary>
/// 坐标Y
/// </summary>
public float Y;
/// <summary>
/// 高度
/// </summary>
public float Z;
}
internal struct IntMeasureData
{
public IntMeasureData(MeasureData md, int x_num, int y_num)
{
X = (int)(md.X * x_num);
if (X >= x_num)
{
X = x_num - 1;
}
Y = (int)(md.Y * y_num);
if (Y >= y_num)
{
Y = y_num - 1;
}
Z = md.Z;
}
public int X;
public int Y;
public float Z;
}
}
标签:
相关软件
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论