GIS 点、线缓冲区生成算法的C#实现(V0.95)
来源:互联网 发布:流星网络电视apk下载 编辑:程序博客网 时间:2024/06/08 16:27
声明:
1.当初自己在找缓冲区生成算法时,非常难找,网上实现的代码更是没有,只有寥寥的几句理论,在N天之后在网上搜到了两篇论文,是《一种GIS缓冲区矢量生成算法及实现》和《GIS缓冲区和叠加分析》,自己根据自己的理解,写出了这个实现的代码,希望能给需要的人员一点帮助,当然,写的非常简单,没有处理锐角情况(下一步计划将会实现),也没有处理自相交情况(正在解决......),大家若是有什么好的意见,请告诉我。谢谢。
2.本代码只实现了生成缓冲区边界点,没有处理锐角情况(下一步计划将会实现),也没有处理自相交情况(正在解决......),希望大家能给写帮助。谢谢。
3.代码之中有很多的不足,和考虑不到的情况,希望大家能给我一些指点,谢谢。
/***********************************************************************
* 文档作者: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);
leftBufferCoords = leftBufferCoords.Substring(leftBufferCoords.IndexOf(';') + 1);
coords.Reverse();
string rightBufferCoords = GetLeftBufferEdgeCoords(coords, radius);
rightBufferCoords = rightBufferCoords.Substring(rightBufferCoords.IndexOf(';') + 1);
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 (Math.Abs(l) < 1E-15)//由于C#中double的精度位数为15位,第16位是不准确的,加上此调整值,可以在一定程度上减小第16位随机数的影响。
{
coords.Remove(coords[i]);//当三点共线时删除这个中间点
}
else 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)//加入了一个调整C#double类型的值
{
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
}
}
- 关于《GIS 点、线缓冲区生成算法的C#实现(V0.95)》的一点备注
- GIS 点、线缓冲区生成算法的C#实现(V0.95)
- 【源代码】GIS 点、线缓冲区生成算法的C#实现(V0.95)
- GIS 缓冲区应用及算法实现
- GIS 缓冲区应用及算法实现
- 环行缓冲区的实现(V0.2,C++源码)
- GIS中由点生成线,点生成面的方法介绍
- gis点云生成
- 环行缓冲区实现(V0.3) C++源码
- 环行缓冲区实现(C++版本)V0.31
- 环行缓冲区实现(C++版本)V0.31
- GIS习题:制作一个上海地铁(进一步考虑到公交)的最佳点到点路径规划生成算法?
- ArcGIS Server中缓冲区分析的实现(点)
- GIS缓冲区算法对比研究(Buffer Algorithm)
- GIS缓冲区算法对比研究(Buffer Algorithm)
- GIS缓冲区算法对比研究(Buffer Algorithm)
- 基于折线生成平行线的C#算法实现
- Arcgis 由点生成方形缓冲区
- ora_01034:oracle not available报错 解决方法
- 内核中修饰的函数的__init的含义
- ASP.NET面试题(二)
- 共享内存应用于进程通信
- 进程间通讯的几种假设
- GIS 点、线缓冲区生成算法的C#实现(V0.95)
- 从搜索引擎角度优化网站
- 为Eclipse安装金蝶Apusic插件
- ssh
- spring容器的三种初始化方法
- strcpy()的实现
- UNIX下退出文件编辑模式
- ARM与THumb基于ARM的嵌入式系统程序开发要点(五)
- 如何打开指定路径的对话框