zoukankan      html  css  js  c++  java
  • 线缓冲区边界生成算法【转】

    /***********************************************************************
     *  文档作者: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
        }
    }

  • 相关阅读:
    C#获取ip地址
    WPF拖动按钮实现(一)
    数据实体层
    在MSN、QQ群、论坛上提问的决窍
    控件开发及组件开发之我见
    数据结构与算法(2) vector概念介绍
    数据结构与算法(1) 数据结构概览
    Android反编译实战(5)
    自己实现CursorAdapter
    自己实现ArrayAdapter
  • 原文地址:https://www.cnblogs.com/neumik/p/2557042.html
Copyright © 2011-2022 走看看