[Source code] C # implementation of GIS point and line buffer generation algorithm (V0.95)

Source: Internet
Author: User
Tags mathematical functions modulus

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 );

}

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.