• 线缓冲区边界生成算法【转】


    /***********************************************************************
     *  文档作者:dxj
     *  创建时间:2010.3.7 20:17
     *  文档说明:
     *      本文件是线缓冲区边界生成算法的C#实现。
     **********************************************************************/
    using System;
    using System.Collections.Generic;
    using System.Text;

    using DXJ.Teresa.GIS.GeoObject;
    using DXJ.Teresa.GIS.Utility;

    namespace DXJ.Teresa.GIS.Buffer
    {
        /// <summary>
        /// 线缓冲区边界生成算法
        /// </summary>
        public class PolylineBuffer
        {
            /// <summary>
            /// 根据给定的一系列有顺序的坐标,逆时针生成缓冲区的边界坐标。
            /// </summary>
            /// <param name="strPolyLineCoords">一系列有顺序的坐标</param>
            /// <param name="radius">缓冲区半径</param>
            /// <returns>缓冲区的边界坐标</returns>
            public static string GetBufferEdgeCoords(string strPolyLineCoords, double radius)
            {
                //参数处理
                if (strPolyLineCoords.Trim().Length < 1) return "";
                string[] strCoords = strPolyLineCoords.Split(new char[] { ';' });
                List<Coordinate> coords = new List<Coordinate>();
                foreach (string coord in strCoords)
                {
                    coords.Add(new Coordinate(coord));
                }

                //分别生成左侧和右侧的缓冲区边界点坐标串
                string leftBufferCoords = GetLeftBufferEdgeCoords(coords, radius);
                coords.Reverse();
                string rightBufferCoords = GetLeftBufferEdgeCoords(coords, radius);
                return leftBufferCoords + ";" + rightBufferCoords;
            }
            #region Private Methods
            /// <summary>
            /// 根据给定的一系列有顺序的坐标,逆时针生成轴线左侧的缓冲区边界点
            /// </summary>
            /// <param name="coords">一系列有顺序的坐标</param>
            /// <param name="radius">缓冲区半径</param>
            /// <returns>缓冲区的边界坐标</returns>
            private static string GetLeftBufferEdgeCoords(IList<Coordinate> coords, double radius)
            {
                //参数处理
                if (coords.Count < 1) return "";
                else if (coords.Count < 2) return PointBuffer.GetBufferEdgeCoords(coords[0], radius);

                //计算时所需变量
                double alpha = 0.0;//向量绕起始点沿顺时针方向旋转到X轴正半轴所扫过的角度
                double delta = 0.0;//前后线段所形成的向量之间的夹角
                double l = 0.0;//前后线段所形成的向量的叉积

                //辅助变量
                StringBuilder strCoords = new StringBuilder();
                double startRadian = 0.0;
                double endRadian = 0.0;
                double beta = 0.0;
                double x = 0.0, y = 0.0;

                //第一节点的缓冲区
                {
                    alpha = MathTool.GetQuadrantAngle(coords[0], coords[1]);
                    startRadian = alpha + Math.PI;
                    endRadian = alpha + (3 * Math.PI) / 2;
                    strCoords.Append(GetBufferCoordsByRadian(coords[0], startRadian, endRadian, radius));
                }

                //中间节点
                for (int i = 1; i < coords.Count - 1; i++)
                {
                    alpha = MathTool.GetQuadrantAngle(coords[i], coords[i + 1]);
                    delta = MathTool.GetIncludedAngel(coords[i - 1], coords[i], coords[i + 1]);
                    l = GetVectorProduct(coords[i - 1], coords[i], coords[i + 1]);
                    if (l > 0)
                    {
                        startRadian = alpha + (3 * Math.PI) / 2 - delta;
                        endRadian = alpha + (3 * Math.PI) / 2;
                        if (strCoords.Length > 0) strCoords.Append(";");
                        strCoords.Append(GetBufferCoordsByRadian(coords[i], startRadian, endRadian, radius));
                    }
                    else if (l < 0)
                    {
                        beta = alpha - (Math.PI - delta) / 2;
                        x = coords[i].X + radius * Math.Cos(beta);
                        y = coords[i].Y + radius * Math.Sin(beta);
                        if (strCoords.Length > 0) strCoords.Append(";");
                        strCoords.Append(x.ToString() + "," + y.ToString());
                    }
                }

                //最后一个点
                {
                    alpha = MathTool.GetQuadrantAngle(coords[coords.Count - 2], coords[coords.Count - 1]);
                    startRadian = alpha + (3 * Math.PI) / 2;
                    endRadian = alpha + 2 * Math.PI;
                    if (strCoords.Length > 0) strCoords.Append(";");
                    strCoords.Append(GetBufferCoordsByRadian(coords[coords.Count - 1], startRadian, endRadian, radius));
                }

                return strCoords.ToString();
            }

            /// <summary>
            /// 获取指定弧度范围之间的缓冲区圆弧拟合边界点
            /// </summary>
            /// <param name="center">指定拟合圆弧的原点</param>
            /// <param name="startRadian">开始弧度</param>
            /// <param name="endRadian">结束弧度</param>
            /// <param name="radius">缓冲区半径</param>
            /// <returns>缓冲区的边界坐标</returns>
            private static string GetBufferCoordsByRadian(Coordinate center, double startRadian, double endRadian, double radius)
            {
                double gamma = Math.PI / 6;

                StringBuilder strCoords = new StringBuilder();
                double x = 0.0, y = 0.0;
                for (double phi = startRadian; phi <= endRadian + 0.000000000000001; phi += gamma)
                {
                    x = center.X + radius * Math.Cos(phi);
                    y = center.Y + radius * Math.Sin(phi);
                    if (strCoords.Length > 0) strCoords.Append(";");
                    strCoords.Append(x.ToString() + "," + y.ToString());
                }
                return strCoords.ToString();
            }
            /// <summary>
            /// 获取相邻三个点所形成的两个向量的交叉乘积
            /// </summary>
            /// <param name="preCoord">第一个节点坐标</param>
            /// <param name="midCoord">第二个节点坐标</param>
            /// <param name="nextCoord">第三个节点坐标</param>
            /// <returns>相邻三个点所形成的两个向量的交叉乘积</returns>
            private static double GetVectorProduct(Coordinate preCoord, Coordinate midCoord, Coordinate nextCoord)
            {
                return (midCoord.X - preCoord.X) * (nextCoord.Y - midCoord.Y) - (nextCoord.X - midCoord.X) * (midCoord.Y - preCoord.Y);
            }
            #endregion
        }
    }

  • 相关阅读:
    系列之前端:从重复造轮子说起
    Asp.Net Core基于JWT认证的数据接口网关Demo
    通过编写一个简单的日志类库来加深了解C#的文件访问控制
    .net core 的图片处理及二维码的生成及解析
    svmtrain和svmpredict简介
    svm小问题
    SVM (support vector machine)
    ubuntu在windows下的wubi安装
    ubuntu在windows下的wubi安装
    [转]无需看到你的脸就能认出你——实现Beyond Frontal Faces: Improving Person Recognition Using Multiple Cues
  • 原文地址:https://www.cnblogs.com/neumik/p/2557042.html
Copyright © 2020-2023  润新知