Today, the source code is pasted on. Please give me more criticism.
I hope you can point out some mistakes. Thank you.
In the future, I will take the time to learn how to deal with special cases and add them. I hope you will have more support.
Source code structure:
Source code is attached respectively:
1. MathTool. cs
/*************************************** ****************
* Author: dxj
* Creation Time: 2010.3.7
* Document Description:
* Common mathematical functions commonly used in GIS.
**************************************** **************/
Using system;
Using system. Collections. Generic;
Using system. text;
Using dxj. Teresa. GIS. geoobject;
Namespace dxj. Teresa. GIS. Utility
{
/// <Summary>
/// Common mathematical functions
/// </Summary>
Public static class mathtool
{
/// <Summary>
/// Obtain the quadrant angle of the vector formed by two points
/// </Summary>
/// <Param name = "preCoord"> coordinates of the first vertex </param>
/// <Param name = "nextCoord"> coordinates of the second vertex </param>
/// <Returns> </returns>
Public static double GetQuadrantAngle (Coordinate preCoord, Coordinate nextCoord)
{
Return GetQuadrantAngle (nextCoord. X-preCoord. X, nextCoord. Y-preCoord. Y );
}
/// <Summary>
/// Quadrant angle of the vector formed by incremental X and incremental Y
/// </Summary>
/// <Param name = "x"> incremental X </param>
/// <Param name = "y"> incremental Y </param>
/// <Returns> quadrant </returns>
Public static double GetQuadrantAngle (double x, double y)
{
Double theta = Math. Atan (y/x );
If (x> 0 & Y> 0) return Theta;
If (x> 0 & Y <0) return math. Pi * 2 + Theta;
If (x <0 & Y> 0) return Theta + math. Pi;
If (x <0 & Y <0) return Theta + math. Pi;
Return Theta;
}
/// <Summary>
/// Obtain the angle between two vectors formed by three adjacent points
/// </Summary>
/// <Param name = "precoord"> </param>
/// <Param name = "midcoord"> </param>
/// <Param name = "nextcoord"> </param>
/// <Returns> </returns>
Public static double getincludedangel (coordinate precoord, coordinate midcoord, coordinate nextcoord)
{
Double innerproduct = (midcoord. x-precoord. x) * (nextcoord. x-midcoord. x) + (midcoord. y-precoord. y) * (nextcoord. y-midcoord. Y );
Double mode1 = Math. sqrt (Math. pow (midCoord. x-preCoord. x), 2.0) + Math. pow (midCoord. y-preCoord. y), 2.0 ));
Double mode2 = Math. sqrt (Math. pow (nextCoord. x-midCoord. x), 2.0) + Math. pow (nextCoord. y-midCoord. y), 2.0 ));
Return Math. Acos (innerProduct/(mode1 * mode2 ));
}
/// <Summary>
/// Obtain the modulus (length) of the vector formed by two points)
/// </Summary>
/// <Param name = "preCoord"> first vertex </param>
/// <Param name = "nextCoord"> second vertex </param>
/// <Returns> modulus (length) of the vector formed by two points </returns>
Public static double GetDistance (Coordinate preCoord, Coordinate nextCoord)
{
Return Math. Sqrt (Math. Pow (nextCoord. X-preCoord. X), 2) + Math. Pow (nextCoord. Y-preCoord. Y), 2 ));
}
}
}
2. Coordinate. cs
/*************************************** ****************
* Author: dxj
* Creation Time: 2010.3.7
* Document Description:
* This file is a coordinate class.
**************************************** **************/
Using system;
Using system. Collections. Generic;
Using system. text;
Namespace dxj. Teresa. GIS. geoobject
{
/// <Summary>
/// Geoobject coordinate class
/// </Summary>
Public class Coordinate
{
# Region Private Members
Private double _ x = 0.0;
Private double _ y = 0.0;
# Endregion
# Region Public construtors
Public coordinate ()
{
//
}
Public coordinate (Double X, Double Y)
{
This. _ x = X;
This. _ y = y;
}
Public coordinate (string X, string y)
{
Try
{
This. _ x = x. Trim () = ""? 0.0: Convert. ToDouble (x. Trim ());
This. _ y = y. Trim () = ""? 0.0: Convert. ToDouble (y. Trim ());
}
Catch (Exception)
{
}
}
Public Coordinate (string coord)
{
If (coord. Trim (). length> 0)
{
String [] coords = coord. Split (New char [] {','});
If (coords. Length = 2)
{
This. _ x = coords [0]. Trim (). length> 0? Convert. todouble (coords [0]. Trim (): 0.0;
This. _ y = coords [1]. Trim (). Length> 0? Convert. ToDouble (coords [1]. Trim (): 0.0;
}
}
}
# Endregion
# Region Public Properities
Public double X
{
Get
{
Return this. _ x;
}
Set
{
This. _ x = value;
}
}
Public Double Y
{
Get
{
Return this. _ y;
}
Set
{
This. _ y = value;
}
}
# Endregion
# Region Public override Methods
Public override string tostring ()
{
Return "(" + this. _ x. tostring () + "," + this. _ y. tostring () + ")";
}
# Endregion
}
}
3. PointBuffer. cs
/*************************************** *********************
* Author: dxj
* Creation Time: 2010.3.7
* Document Description:
* This file is the C # Implementation of the vertex buffer boundary generation algorithm.
*
**************************************** ********************/
Using system;
Using system. Collections. Generic;
Using system. text;
Using dxj. Teresa. GIS. geoobject;
Namespace dxj. Teresa. GIS. Buffer
{
/// <Summary>
/// Vertex buffer Boundary Generation Algorithm
/// </Summary>
Public class pointbuffer
{
# Region Public Members
/// <Summary>
/// Used to approximate the number of edges of the inner positive polygon at the vertex buffer boundary n
/// </Summary>
Public static int n = 12;
# Endregion
# Region Public static methods
/// <Summary>
/// Generate the coordinate string of the boundary point in the point Buffer Based on a given coordinate point (counterclockwise)
/// </Summary>
/// <Param name = "center"> coordinates of a given point </param>
/// <Param name = "radius"> buffer radius </param>
/// <Returns> coordinate string of the vertex boundary point (counterclockwise) </returns>
Public static string GetBufferEdgeCoords (Coordinate center, double radius)
{
Double alpha = 0.0; // Math. PI/6;
Double gamma = (2 * Math. PI)/N;
Stringbuilder strcoords = new stringbuilder ();
Double X = 0.0, y = 0.0;
For (double Phi = 0; Phi <(n-1) * gamma; Phi + = gamma)
{
X = center. x + radius * Math. Cos (alpha + PHI );
Y = center. Y + radius * Math. Sin (alpha + PHI );
If (strcoords. length> 0) strcoords. append (";");
Strcoords. append (X. tostring () + "," + Y. tostring ());
}
Return strcoords. tostring ();
}
# Endregion
}
}
4. PolylineBuffer. cs
/*************************************** ********************************
* Author: dxj
* Creation Time: 2010.3.7
* Document Description:
* This file is the C # Implementation of the line buffer boundary generation algorithm.
**************************************** ******************************/
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>
/// Line buffer Boundary Generation Algorithm
/// </Summary>
Public class polylinebuffer
{
/// <Summary>
/// Generates the boundary coordinates of the buffer counterclockwise Based on the given sequence coordinates.
/// </Summary>
/// <Param name = "strpolylinecoords"> A series of ordered coordinates </param>
/// <Param name = "radius"> buffer radius </param>
/// <Returns> the Boundary Coordinate of the buffer </returns>
Public static string GetBufferEdgeCoords (string strPolyLineCoords, double radius)
{
// Parameter Processing
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 ));
}
// Generate the coordinate string of the buffer Edge Points on the left and right respectively.
String leftBufferCoords = GetLeftBufferEdgeCoords (coords, radius );
Coords. Reverse ();
String rightBufferCoords = GetLeftBufferEdgeCoords (coords, radius );
Return leftBufferCoords + ";" + rightBufferCoords;
}
# Region Private Methods
/// <Summary>
/// Generates the buffer boundary point on the left of the Axis counterclockwise based on a series of ordered coordinates.
/// </Summary>
/// <Param name = "coords"> A series of ordered coordinates </param>
/// <Param name = "radius"> buffer radius </param>
/// <Returns> the Boundary Coordinate of the buffer </returns>
Private static string GetLeftBufferEdgeCoords (IList <Coordinate> coords, double radius)
{
// Parameter Processing
If (coords. Count <1) return "";
Else if (coords. Count <2) return PointBuffer. GetBufferEdgeCoords (coords [0], radius );
// Required variable for Calculation
Double alpha = 0.0; // the angle from which the vector rotates around the starting point clockwise to the x-axis minus axis
Double delta = 0.0; // The angle between the vectors formed by the front and back line segments
Double L = 0.0; // cross product of the vector formed by the front and back line segments
// Auxiliary variable
Stringbuilder strcoords = new stringbuilder ();
Double startradian = 0.0;
Double endradian = 0.0;
Double Beta = 0.0;
Double X = 0.0, y = 0.0;
// The buffer at the first node
{
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 ));
}
// Intermediate node
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 ());
}
}
// Last Vertex
{
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>
/// Obtain the edge point of the buffer Arc Fitting between the specified radians
/// </Summary>
/// <Param name = "center"> specify the origin for fitting an arc </param>
/// <Param name = "startradian"> Start radian </param>
/// <Param name = "endradian"> end radian </param>
/// <Param name = "radius"> buffer radius </param>
/// <Returns> the Boundary Coordinate of the buffer </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>
/// Obtain the cross product of two vectors formed by three adjacent points
/// </Summary>
/// <Param name = "preCoord"> coordinates of the first node </param>
/// <Param name = "midCoord"> coordinates of the second node </param>
/// <Param name = "nextCoord"> coordinates of the third node </param>
/// <Returns> cross product of two vectors formed by three adjacent points </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
}
}
4. Test code
/*************************************** *********************
* Author: dxj
* Creation Time: 2010.3.7
* Document Description:
* This document is a test program that generates a boundary value based on a series of points.
*
**************************************** ********************/
Using system;
Using system. Collections. Generic;
Using system. Web;
Using system. Web. UI;
Using system. Web. UI. webcontrols;
Using dxj. Teresa. GIS. buffer;
Using dxj. Teresa. GIS. geoobject;
Public partial class _ default: system. Web. UI. Page
{
Protected void page_load (Object sender, eventargs E)
{
// Coordinate coord = new coordinate (117.9761419921875, 36.7177825 );
Double Radius = 0.0058633144143721562925090295041981;
// String strcoords = pointbuffer. getbufferedgecoords (coord, radius );
// Response. Write (strCoords );
String coords = "117.3469162109375, 36.552475; 118.77600527343749, 36.56047375; 118.49871933593751, 37.11772; 117.5442158203125, 37.000405; 117.680192578125, 37.405675; 119.1386099609375, 37.15238125; 119.162605859375, 36.45649; 118.89865097656251, 36.28851625; 118.63736230468748, 36.19253125; 118.5093841796875, 36.189865 ";
String strCoords = PolylineBuffer. GetBufferEdgeCoords (coords, radius );
Response. Write (strCoords );
}
}