在好例子网,分享、交流、成长!
您当前所在位置:首页C# 开发实例C#语言基础 → 等高线的绘制

等高线的绘制

C#语言基础

下载此实例
  • 开发语言:C#
  • 实例大小:3.54KB
  • 下载次数:19
  • 浏览次数:308
  • 发布时间:2021-03-05
  • 实例类别:C#语言基础
  • 发 布 人:TIN2Point
  • 文件格式:.zip
  • 所需积分:2
 相关标签:

实例介绍

【实例简介】
【实例截图】

【核心代码】

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;
    }
}


标签:

实例下载地址

等高线的绘制

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警