• C#任意图形加权Voronoi图生成


        距离变换是计算并标识空间点(对目标点)距离的过程,它最终把二值图像变换为灰度图像[1](其中每个栅格的灰度值等于它到最近目标点的距离)。目前距离变换被广泛应用于计算机图形学、GIS空间分析和模式识别等领域。
        按距离类型划分,距离变换可分为:非欧氏距离变换和欧氏距离变换(EDT)。其中EDT精度高,与实际距离相符,应用更广泛。目前随着应用的需要,已经有多种EDT算法[2-6]。按变换方式分,这些算法可以分为:基于目标点变换算法[2,3]和基于背景点变换算法[4-6],其中基于目标点变换算法又可分为:传播算法[4]、光栅扫描算法[5]和独立扫描算法[6]。上述算法大多致力于算法效率和完全性上的研究,其算法扩展性十分有限。
        为此,作者提出了一种新的EDT算法,该算法在原有光栅扫描算法基础上,进行了改进,算法在信息传递的时候,用最近目标点的行列号代替与最近目标点行列号的差异,这样通过这些行列号可以轻松实现欧氏距离变换。和原有算法相比,该算法扩展后可以用于加权欧氏距离变换、任意图形加权Voronoi图的生成。以下为实现代码:
    
    
    //VoronoiClass.cs文件
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    [assembly: CLSCompliant(true)]
    namespace Voronoi
    {
       public class VoronoiClass : IVoronoiClass
        {
            private struct RC
            {
                public int i;
                public int j;
            }
            private class Mark
            {
                private int o_x;
    
    
                public int O_x
                {
                    get { return o_x; }
                    set { o_x = value; }
                }
                private int o_y;
                public int O_y
                {
                    get { return o_y; }
                    set { o_y = value; }
                }
                private double weight;
                public double Weight
                {
                    get { return weight; }
                    set { weight = value; }
                }
                private double o_num;
                public double O_num
                {
                    get { return o_num; }
                    set { o_num = value; }
                }
            }
            private class Recode
            {
                private int o_x;
                public int O_x
                {
                    get { return o_x; }
                    set { o_x = value; }
                }
                private int o_y;
                public int O_y
                {
                    get { return o_y; }
                    set { o_y = value; }
                }
                private double o_num;
                public double O_num
                {
                    get { return o_num; }
                    set { o_num = value; }
                }
                private double weight;
                public double Weight
                {
                    get { return weight; }
                    set { weight = value; }
                }
                private double distance;
                public double Distance
                {
                    get { return distance; }
                    set { distance = value; }
                }
            }
            //公共变量        
            Mark[,] T;
            int max = 10000000;  
            Array IVoronoiClass.doVoronoi(Array pixelData, int W, int H)
            {         
                T new Mark[W + 2, H + 2];//加个框框
                Array ResultData;
                ///////////////////////////////预处理
                for (int i = 0; i < W + 2; i++)
                    for (int j = 0; j < H + 2; j++)
                    {
                        T[i, j] new Mark();
                        double weight;
                        try
                        {
                            weight = Convert.ToDouble(pixelData.GetValue(i - 1, j - 1));
                        }
                        catch (Exception ex)
                        {
                            weight 0;
                            string a = ex.Message;//日魂归
                        }
                        if (weight > 0)//目标
                        {
                            T[i, j].O_x = i;
                            T[i, j].O_y = j;
                            T[i, j].Weight = weight;
                            T[i, j].O_num 0;
                        }
                        else//背景
                        {
                            T[i, j].O_x = max;
                            T[i, j].O_y = max;
                            T[i, j].Weight 1.1;
                            T[i, j].O_num 0;
                        }
                    }           
                double num = 1;
                for (int i = 0; i < W + 2; i++)
                    for (int j = 0; j < H + 2; j++)
                    {
                        if (T[i, j].Weight != 1.1 && T[i, j].O_num == 0)
                        {
                            T[i, j].O_num = num;
                            Stack process new Stack();
                            FindPolygon(process, i, j,W,H);
                            while (process.Count > 0)
                            {
                                RC rc = (RC)process.Pop();
                                FindPolygon(process, rc.i, rc.j,W,H);
                            }
                            GC.Collect();
                            num++;
                        }
                    }
                //////////////////////////////上行扫描
                Recode[] recode = new Recode[9];
                for (int i = 1; i < W + 1; i++)
                    for (int j = 1; j < H + 1; j++)
                    {
                        recode[1] = new Recode();
                        recode[1].Distance = Math.Sqrt(Math.Pow(i - T[i, j - 1].O_x, 2) + Math.Pow(j - T[i, j - 1].O_y, 2)) / T[i, j - 1].Weight;
                        recode[1].O_x = T[i, j - 1].O_x;
                        recode[1].O_y = T[i, j - 1].O_y;
                        recode[1].O_num = T[i, j - 1].O_num;
                        recode[1].Weight = T[i, j - 1].Weight;
    
                        recode[2] = new Recode();
                        recode[2].Distance = Math.Sqrt(Math.Pow(i - T[i - 1, j - 1].O_x, 2) + Math.Pow(j - T[i - 1, j - 1].O_y, 2)) / T[i - 1, j - 1].Weight;
                        recode[2].O_x = T[i - 1, j - 1].O_x;
                        recode[2].O_y = T[i - 1, j - 1].O_y;
                        recode[2].O_num = T[i - 1, j - 1].O_num;
                        recode[2].Weight = T[i - 1, j - 1].Weight;
    
                        recode[3] = new Recode();
                        recode[3].Distance = Math.Sqrt(Math.Pow(i - T[i - 1, j].O_x, 2) + Math.Pow(j - T[i - 1, j].O_y, 2)) / T[i - 1, j].Weight;
                        recode[3].O_x = T[i - 1, j].O_x;
                        recode[3].O_y = T[i - 1, j].O_y;
                        recode[3].O_num = T[i - 1, j].O_num;
                        recode[3].Weight = T[i - 1, j].Weight;
    
                        recode[4] = new Recode();
                        {
                            recode[4].Distance = Math.Sqrt(Math.Pow(i - T[i - 1, j + 1].O_x, 2) + Math.Pow(j - T[i - 1, j + 1].O_y, 2)) / T[i - 1, j + 1].Weight;
                            recode[4].O_x = T[i - 1, j + 1].O_x;
                            recode[4].O_y = T[i - 1, j + 1].O_y;
                            recode[4].O_num = T[i - 1, j + 1].O_num;
                            recode[4].Weight = T[i - 1, j + 1].Weight;
                        }
                        for (int k = 1; k < 5; k++)
                        {
                            double distance = Math.Sqrt(Math.Pow(i - T[i, j].O_x, 2) + Math.Pow(j - T[i, j].O_y, 2)) / T[i, j].Weight;
                            if (recode[k].Distance < distance)
                            {
                                T[i, j].O_x = recode[k].O_x;
                                T[i, j].O_y = recode[k].O_y;
                                T[i, j].O_num = recode[k].O_num;
                                T[i, j].Weight = recode[k].Weight;
                            }
                        }
                    }
                //////////////////////上行扫描结束
                ///////////////////////下行扫描
                for (int i = W; i > 0; i--)
                    for (int j = H; j > 0; j--)
                    {
                        recode[5] = new Recode();
                        recode[5].Distance = Math.Sqrt(Math.Pow(i - T[i, j + 1].O_x, 2) + Math.Pow(j - T[i, j + 1].O_y, 2)) / T[i, j + 1].Weight;
                        recode[5].O_x = T[i, j + 1].O_x;
                        recode[5].O_y = T[i, j + 1].O_y;
                        recode[5].O_num = T[i, j + 1].O_num;
                        recode[5].Weight = T[i, j + 1].Weight;
    
    
                        recode[6] = new Recode();
                        recode[6].Distance = Math.Sqrt(Math.Pow(i - T[i + 1, j + 1].O_x, 2) + Math.Pow(j - T[i + 1, j + 1].O_y, 2)) / T[i + 1, j + 1].Weight;
                        recode[6].O_x = T[i + 1, j + 1].O_x;
                        recode[6].O_y = T[i + 1, j + 1].O_y;
                        recode[6].O_num = T[i + 1, j + 1].O_num;
                        recode[6].Weight = T[i + 1, j + 1].Weight;
    
    
                        recode[7] = new Recode();
                        recode[7].Distance = Math.Sqrt(Math.Pow(i - T[i + 1, j].O_x, 2) + Math.Pow(j - T[i + 1, j].O_y, 2)) / T[i + 1, j].Weight;
                        recode[7].O_x = T[i + 1, j].O_x;
                        recode[7].O_y = T[i + 1, j].O_y;
                        recode[7].O_num = T[i + 1, j].O_num;
                        recode[7].Weight = T[i + 1, j].Weight;
    
    
                        recode[8] = new Recode();
                        {
                            recode[8].Distance = Math.Sqrt(Math.Pow(i - T[i + 1, j - 1].O_x, 2) + Math.Pow(j - T[i + 1, j - 1].O_y, 2)) / T[i + 1, j - 1].Weight;
                            recode[8].O_x = T[i + 1, j - 1].O_x;
                            recode[8].O_y = T[i + 1, j - 1].O_y;
                            recode[8].O_num = T[i + 1, j - 1].O_num;
                            recode[8].Weight = T[i + 1, j - 1].Weight;
                        }
                        for (int k = 5; k < 9; k++)
                        {
                            double distance = Math.Sqrt(Math.Pow(i - T[i, j].O_x, 2) + Math.Pow(j - T[i, j].O_y, 2)) / T[i, j].Weight;
                            if (recode[k].Distance < distance)
                            {
                                T[i, j].O_x = recode[k].O_x;
                                T[i, j].O_y = recode[k].O_y;
                                T[i, j].O_num = recode[k].O_num;
                                T[i, j].Weight = recode[k].Weight;
                            }
                        }
                    }
                ///////////////////下行扫描结束
                ResultData = Array.CreateInstance(typeof(Byte), W, H);
                for (int i = 1; i < W + 1; i++)
                    for (int j = 1; j < H + 1; j++)
                    {
                        ResultData.SetValue(Convert.ToByte(T[i, j].O_num), i 1, j - 1);
                    }
                return ResultData;
            }
            private void digui(int i, int j,int W,int H)
            {
                #region           
                #endregion
                if (i > 1)
                {
                    if (T[i - 1, j].Weight != 1.1 && T[i - 1, j].O_num == 0)
                    {
                        T[i 1, j].O_num = T[i, j].O_num;
                        digui(i 1, j,W,H);
                    }
                }
                if (i > 1 && j > 1)
                {
                    if (T[i - 1, j - 1].Weight != 1.1 && T[i - 1, j - 1].O_num == 0)
                    {
                        T[i 1, j - 1].O_num = T[i, j].O_num;
                        digui(i 1, j - 1,W,H);
                    }
                }
                if (j > 1)
                {
                    if (T[i, j - 1].Weight != 1.1 && T[i, j - 1].O_num == 0)
                    {
                        T[i, j 1].O_num = T[i, j].O_num;
                        digui(i, j 1,W,H);
                    }
                }
                if (i < W && j > 0)
                {
                    if (T[i + 1, j - 1].Weight != 1.1 && T[i + 1, j - 1].O_num == 0)
                    {
                        T[i 1, j - 1].O_num = T[i, j].O_num;
                        digui(i 1, j - 1,W,H);
                    }
                }
                if (i < W)
                {
                    if (T[i + 1, j].Weight != 1.1 && T[i + 1, j].O_num == 0)
                    {
                        T[i 1, j].O_num = T[i, j].O_num;
                        digui(i 1, j,W,H);
                    }
                }
                if (i < W && j < H)
                {
                    if (T[i + 1, j + 1].Weight != 1.1 && T[i + 1, j + 1].O_num == 0)
                    {
                        T[i 1, j + 1].O_num = T[i, j].O_num;
                        digui(i 1, j + 1,W,H);
                    }
                }
                if (j < H)
                {
                    if (T[i, j + 1].Weight != 1.1 && T[i, j + 1].O_num == 0)
                    {
                        T[i, j 1].O_num = T[i, j].O_num;
                        digui(i, j 1,W,H);
                    }
                }
                if (i > 1 && j < H)
                {
                    if (T[i - 1, j + 1].Weight != 1.1 && T[i - 1, j + 1].O_num == 0)
                    {
                        T[i 1, j + 1].O_num = T[i, j].O_num;
                        digui(i 1, j + 1,W,H);
                    }
                }
                GC.Collect();
                
            }
            private void FindPolygon(Stack process, int i, int j,int W,int H)
            {
                if (i > 1)
                {
                    if (T[i - 1, j].Weight != 1.1 && T[i - 1, j].O_num == 0)
                    {
                        T[i 1, j].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j);
                    }
                }
                if (i > 1 && j > 1)
                {
                    if (T[i - 1, j - 1].Weight != 1.1 && T[i - 1, j - 1].O_num == 0)
                    {
                        T[i 1, j - 1].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j - 1);
                    }
                }
                if (j > 1)
                {
                    if (T[i, j - 1].Weight != 1.1 && T[i, j - 1].O_num == 0)
                    {
                        T[i, j 1].O_num = T[i, j].O_num;
                        AddValue(process, i, j 1);
                    }
                }
                if (i < W && j > 0)
                {
                    if (T[i + 1, j - 1].Weight != 1.1 && T[i + 1, j - 1].O_num == 0)
                    {
                        T[i 1, j - 1].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j - 1);
                    }
                }
                if (i < W)
                {
                    if (T[i + 1, j].Weight != 1.1 && T[i + 1, j].O_num == 0)
                    {
                        T[i 1, j].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j);
                    }
                }
                if (i < W && j < H)
                {
                    if (T[i + 1, j + 1].Weight != 1.1 && T[i + 1, j + 1].O_num == 0)
                    {
                        T[i 1, j + 1].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j + 1);
                    }
                }
                if (j < H)
                {
                    if (T[i, j + 1].Weight != 1.1 && T[i, j + 1].O_num == 0)
                    {
                        T[i, j 1].O_num = T[i, j].O_num;
                        AddValue(process, i, j 1);
                    }
                }
                if (i > 1 && j < H)
                {
                    if (T[i - 1, j + 1].Weight != 1.1 && T[i - 1, j + 1].O_num == 0)
                    {
                        T[i 1, j + 1].O_num = T[i, j].O_num;
                        AddValue(process, i 1, j + 1);
                    }
                }
            }
            private void AddValue(Stack process, int i, int j)
            {           
                {
                    RC rc new RC();
                    rc.i = i;
                    rc.j = j;
                    process.Push(rc);
                }
            }
        }
    }
    
    using System;
    namespace Voronoi
    {
        public interface IVoronoiClass
        {
            Array doVoronoi(Array pixelData, int W, int H);
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using System.IO;
    using System.Collections;
    
    namespace GLCStatisticalAnalysis
    {
        public partial class BuiltVoronoiFrom : Form
        {
            public BuiltVoronoiFrom()
            {
                InitializeComponent();
                worker.WorkerReportsProgress true;
                worker.WorkerSupportsCancellation true;
                //正式做事情的地方
                worker.DoWork += new DoWorkEventHandler(DoWork);
                //任务完称时要做的,比如提示等等
                worker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
                //任务进行时,报告进度
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
            }
            Thread mainThread;
            public BackgroundWorker worker = new BackgroundWorker();
            bool progress = true;  //进度条控制参
            VoronoiProcess pProcess = new VoronoiProcess();
            string classField;
            string cellSize;
            private void OK_Click(object sender, EventArgs e)
            {
                bool start = checkFilePath();
                if (start)
                {
                    classField = comboBox1.Text;
                    cellSize = textBox2.Text;
                    mainThread new Thread(mainThreadProcess);
                    mainThread.SetApartmentState(ApartmentState.STA);
                    mainThread.Start();
                    worker.RunWorkerAsync();//进度条控制
                    this.panel_hidden.Enabled = false;
                    OK.Enabled false;
                }
            }
            private bool checkFilePath()
            {
    
    
                bool start = true;
                if (textBox1.Text == "")
                { MessageBox.Show("请输入要素文件!"); start = falsereturn start; }
                else if (textBox2.Text == "")
                { MessageBox.Show("请输入影像文件!"); start = falsereturn start; }
                
                else if (comboBox1.Text == "")
                { MessageBox.Show("请输入权重字段!"); start = falsereturn start; }
                else if (textBox2.Text == "")
                { MessageBox.Show("请输入精度!"); start = falsereturn start; }
                else if (!File.Exists(textBox1.Text))
                { MessageBox.Show("要素文件不存在!"); start = falsereturn start; }
               
                else if (File.Exists(textBox3.Text))
                {
                    try { System.IO.File.Delete(textBox3.Text); }
                    catch (Exception ex)
                    {
                        start false;
                        MessageBox.Show(ex.Message);
                        return start;
                    }
                }
                else
                {
                    //检验输出路径是否存在
                    string outPath = textBox3.Text;
                    int index = outPath.LastIndexOf("\\");
                    if ((index == -1) || (index >= outPath.Length - 1))
                    {
                        MessageBox.Show("输出文件路径有误!");
                        start false;
                        return start;
                    }
                    else
                    {
                        string outFilePath = outPath.Remove(index);
                        if (!(Directory.Exists(outFilePath)))
                        {
                            MessageBox.Show("输出文件路径有误!");
                            start false;
                            return start;
                        }
                    }
                }          
    
                return start;
            }
            private void Cancel_Click(object sender, EventArgs e)
            {
                progress false;
                this.Close();
            }
    
    
            private void pictureBox1_Click(object sender, EventArgs e)
            {
                openFileDialog1.FileName null;//清楚文件路径,防止再次导入时,取消后依然导入
                openFileDialog1.Filter = "Shapefile(*.shp)|*.shp";
                openFileDialog1.ShowDialog();
             
                this.textBox1.Text=openFileDialog1.FileName;
                if (textBox1.Text != "")
                { 
                    AddComboBox1();
                    this.textBox3.Text = this.textBox1.Text.Replace(".shp""_voronoi.shp");
                }
            }
            [STAThread]
            private void mainThreadProcess()
            {
                //try
                {
                    pProcess.run(textBox1.Text, textBox3.Text, classField, cellSize);
                }
                //catch (Exception ex)
                //{
    
    
                //    MessageBox.Show(ex.Message);
    
    
                //}
            }
            #region 进度条
            public void DoWork(object sender, DoWorkEventArgs e)
            {
                e.Result = ComputeFibonacci(worker, e);//当ComputeFibonacci(worker, e)返回时,异步过程结束
            }
            //调用 ReportProgress 时发生
            public void ProgessChanged(object sender, ProgressChangedEventArgs e)
            {
                this.toolStripProgressBar1.Value = e.ProgressPercentage;
    
    
                this.toolStripStatusLabel2.Text = Convert.ToString(e.ProgressPercentage);
            }
            //当后台操作已完成、被取消或引发异常时发生
            public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
            {
                MessageBox.Show("Complete!");
                this.Close();
                
            }
    
    
            private int ComputeFibonacci(object sender, DoWorkEventArgs e)
            {
                int i = 0;
                while (mainThread.IsAlive)
                {
                    if (progress == false)
                    {
                        MessageBox.Show("Cancelled!");
                        mainThread.Abort();//叫停处理图像进程              
                        System.Threading.Thread.CurrentThread.Abort();
                        
                    }
                    if (worker.CancellationPending)
                    {
                        e.Cancel true;
                    }
                    else
                    {
                        worker.ReportProgress(i);
                    }
                    System.Threading.Thread.Sleep(300);
                    i++; if (i == 100) i = 0;
                }
                worker.ReportProgress(100);
                return -1;
    
    
            }
            #endregion
    
    
            private void CalculateStatisticsFrom_FormClosed(object sender, FormClosedEventArgs e)
            {
                progress false;
            }   
          
            private void AddComboBox1()
            {
                comboBox1.Items.Clear();
                ArrayList pValue new ArrayList();
                pValue = pProcess.getZoneField(textBox1.Text);
                for (int i = 0; i < pValue.Count; i++)
                {
                    comboBox1.Items.Add(pValue[i]);
                }
                comboBox1.Text = Convert.ToString(comboBox1.Items[3]);
            }
            private void pictureBox3_Click(object sender, EventArgs e)
            {
                saveFileDialog1.FileName null;//清楚文件路径,防止再次导入时,取消后依然导入
                saveFileDialog1.Filter = "Shapefile(*.shp)|*.shp";
                saveFileDialog1.ShowDialog();
                this.textBox3.Text = saveFileDialog1.FileName;
            }                 
        }
    }
  • 相关阅读:
    微信小程序购物商城系统开发系列-工具篇
    CSS实现导航条Tab切换的三种方法
    最详细win7下手动搭建PHP环境:apache2.4.23+php7.0.11
    读书笔记:《HTML5开发手册》Web表单
    jQuery可拖拽3D万花筒旋转特效
    框架基础:关于ajax设计方案(三)---集成ajax上传技术
    框架基础:ajax设计方案(二)---集成轮询技术
    框架基础:ajax设计方案(一)---集成核心请求
    Apache+PHP+MySQL
    自学 PHP,如何不走弯路?
  • 原文地址:https://www.cnblogs.com/devgis/p/16366169.html
Copyright © 2020-2023  润新知