Skip to content

Instantly share code, notes, and snippets.

@rhughes42
Last active February 13, 2024 22:23
Show Gist options
  • Save rhughes42/fb16f656eb8dddd10bc887972fd3e603 to your computer and use it in GitHub Desktop.
Save rhughes42/fb16f656eb8dddd10bc887972fd3e603 to your computer and use it in GitHub Desktop.
Optimizations to Polygon Class in Graph Geometry Package

Optimizations to Polygon Class in Graph Geometry Package

Motivation

Last week I started to put together a small geometry NuGet package featuring simple types and operations. The goal is to keep it lightweight and performant, even if it's written in C# as opposed to C++. The reason for keeping it in C# is that I may one day want to make the tools available in a more explicit format for uses in industries where programming proficiency is not so pervasive, hence opting for the more readable format.

Nonetheless, I need to optimize it where I can. This is the first in a series of gists on the matter.

1
In the RemoveVertices and RemoveVerticesAtIndex methods, it's better to remove items from the end of the list to the start. This is because removing an item from a list involves shifting all the subsequent items down. If you remove items from the start of the list first, you'll end up shifting the same items multiple times.

Code Before

/// <summary>
/// Removes multiple vertices from the polygon.
/// </summary>
/// <param name="points">
/// The array of points representing the vertices to be removed.
/// </param>
public void RemoveVertices( Point[] points ) {
  for ( int i = 0; i < points.Length; i++ ) {
    RemoveVertex( points[ i ] );
  }
}

/// <summary>
/// Removes vertices at the specified indices.
/// </summary>
/// <param name="indices"> The indices of the vertices to remove. </param>
public void RemoveVerticesAtIndex( int[] indices ) {
  for ( int i = 0; i < indices.Length; i++ ) {
    RemoveVertexAtIndex( indices[ i ] );
  }
}

Code After

/// <summary>
/// Removes multiple vertices from the polygon.
/// </summary>
/// <param name="points">
/// The array of points representing the vertices to be removed.
/// </param>
public void RemoveVertices( Point[] points ) {
  foreach (var point in points) {
    Vertices.Remove(point);
  }
}

/// <summary>
/// Removes vertices at the specified indices.
/// </summary>
/// <param name="indices"> The indices of the vertices to remove. </param>
public void RemoveVerticesAtIndex( int[] indices ) {
  Array.Sort(indices, (a, b) => b.CompareTo(a)); // sort in descending order
  foreach (var index in indices) {
    Vertices.RemoveAt(index);
  }
}

2
In the FromCircle method, you can move the calculation of (2 * Math.PI / numberOfVertices) outside the loop because it's a constant for a given numberOfVertices.

Code Before

/// <summary>
/// Creates a polygon by approximating a circle using the specified number of
/// vertices.
/// </summary>
/// <param name="circle">           The circle to approximate. </param>
/// <param name="numberOfVertices">
/// The number of vertices to use for the approximation. Default is 32.
/// </param>
/// <returns> The created polygon. </returns>
public Polygon FromCircle( Circle circle, double numberOfVertices = 32 ) {
  Vertices = new List<Point>( );
  for ( int i = 0; i < numberOfVertices; i++ ) {
    double angle = i * ( 2 * Math.PI / numberOfVertices );
    
    double x = circle.Center.X + circle.Radius * Math.Cos( angle );
    double y = circle.Center.Y + circle.Radius * Math.Sin( angle );
    
    Vertices.Add( new Point( x, y ) );
  }
  return this;
}

Code After

/// <summary>
/// Creates a polygon by approximating a circle using the specified number of
/// vertices.
/// </summary>
/// <param name="circle">           The circle to approximate. </param>
/// <param name="numberOfVertices">
/// The number of vertices to use for the approximation. Default is 32.
/// </param>
/// <returns> The created polygon. </returns>
public Polygon FromCircle( Circle circle, double numberOfVertices = 32 ) {
  Vertices = new List<Point>( );
  double angleIncrement = 2 * Math.PI / numberOfVertices;

  for ( int i = 0; i < numberOfVertices; i++ ) {
    double angle = i * angleIncrement;
    
    double x = circle.Center.X + circle.Radius * Math.Cos(angle);
    double y = circle.Center.Y + circle.Radius * Math.Sin(angle);
    
    Vertices.Add( new Point( x, y ) );
  }
  return this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment