@@ -45,7 +45,7 @@ public Delaunator(IPoint[] points)
4545 coords [ 2 * i + 1 ] = p . Y ;
4646 }
4747
48- var n = coords . Length >> 1 ;
48+ var n = points . Length ;
4949 var maxTriangles = 2 * n - 5 ;
5050
5151 Triangles = new int [ maxTriangles * 3 ] ;
@@ -384,7 +384,7 @@ private int Legalize(int a)
384384
385385 return ar ;
386386 }
387- private bool InCircle ( double ax , double ay , double bx , double by , double cx , double cy , double px , double py )
387+ private static bool InCircle ( double ax , double ay , double bx , double by , double cx , double cy , double px , double py )
388388 {
389389 var dx = ax - px ;
390390 var dy = ay - py ;
@@ -422,12 +422,12 @@ private void Link(int a, int b)
422422 if ( b != - 1 ) Halfedges [ b ] = a ;
423423 }
424424 private int HashKey ( double x , double y ) => ( int ) ( Math . Floor ( PseudoAngle ( x - cx , y - cy ) * hashSize ) % hashSize ) ;
425- private double PseudoAngle ( double dx , double dy )
425+ private static double PseudoAngle ( double dx , double dy )
426426 {
427427 var p = dx / ( Math . Abs ( dx ) + Math . Abs ( dy ) ) ;
428428 return ( dy > 0 ? 3 - p : 1 + p ) / 4 ; // [0..1]
429429 }
430- private void Quicksort ( int [ ] ids , double [ ] dists , int left , int right )
430+ private static void Quicksort ( int [ ] ids , double [ ] dists , int left , int right )
431431 {
432432 if ( right - left <= 20 )
433433 {
@@ -474,14 +474,14 @@ private void Quicksort(int[] ids, double[] dists, int left, int right)
474474 }
475475 }
476476 }
477- private void Swap ( int [ ] arr , int i , int j )
477+ private static void Swap ( int [ ] arr , int i , int j )
478478 {
479479 var tmp = arr [ i ] ;
480480 arr [ i ] = arr [ j ] ;
481481 arr [ j ] = tmp ;
482482 }
483- private bool Orient ( double px , double py , double qx , double qy , double rx , double ry ) => ( qy - py ) * ( rx - qx ) - ( qx - px ) * ( ry - qy ) < 0 ;
484- private double Circumradius ( double ax , double ay , double bx , double by , double cx , double cy )
483+ private static bool Orient ( double px , double py , double qx , double qy , double rx , double ry ) => ( qy - py ) * ( rx - qx ) - ( qx - px ) * ( ry - qy ) < 0 ;
484+ private static double Circumradius ( double ax , double ay , double bx , double by , double cx , double cy )
485485 {
486486 var dx = bx - ax ;
487487 var dy = by - ay ;
@@ -494,7 +494,7 @@ private double Circumradius(double ax, double ay, double bx, double by, double c
494494 var y = ( dx * cl - ex * bl ) * d ;
495495 return x * x + y * y ;
496496 }
497- private Point Circumcenter ( double ax , double ay , double bx , double by , double cx , double cy )
497+ private static Point Circumcenter ( double ax , double ay , double bx , double by , double cx , double cy )
498498 {
499499 var dx = bx - ax ;
500500 var dy = by - ay ;
@@ -508,7 +508,7 @@ private Point Circumcenter(double ax, double ay, double bx, double by, double cx
508508
509509 return new Point ( x , y ) ;
510510 }
511- private double Dist ( double ax , double ay , double bx , double by )
511+ private static double Dist ( double ax , double ay , double bx , double by )
512512 {
513513 var dx = ax - bx ;
514514 var dy = ay - by ;
@@ -558,29 +558,54 @@ public IEnumerable<IVoronoiCell> GetVoronoiCells(Func<int, IPoint> triangleVerti
558558 if ( triangleVerticeSelector == null ) triangleVerticeSelector = x => GetCentroid ( x ) ;
559559
560560 var seen = new HashSet < int > ( ) ;
561+ var vertices = new List < IPoint > ( 10 ) ; // Keep it outside the loop, reuse capacity, less resizes.
562+
561563 for ( var triangleId = 0 ; triangleId < Triangles . Length ; triangleId ++ )
562564 {
563565 var id = Triangles [ NextHalfedge ( triangleId ) ] ;
564- if ( ! seen . Any ( x => x == id ) )
566+ // True if element was added, If resize the set? O(n) : O(1)
567+ if ( seen . Add ( id ) )
565568 {
566- seen . Add ( id ) ;
567- var edges = EdgesAroundPoint ( triangleId ) ;
568- var triangles = edges . Select ( x => TriangleOfEdge ( x ) ) ;
569- var vertices = triangles . Select ( triangleVerticeSelector ) . ToArray ( ) ;
570- yield return new VoronoiCell ( id , vertices ) ;
569+ foreach ( var edge in EdgesAroundPoint ( triangleId ) )
570+ {
571+ // triangleVerticeSelector cant be null, no need to check before invoke (?.).
572+ vertices . Add ( triangleVerticeSelector . Invoke ( TriangleOfEdge ( edge ) ) ) ;
573+ }
574+ yield return new VoronoiCell ( id , vertices . ToArray ( ) ) ;
575+ vertices . Clear ( ) ; // Clear elements, keep capacity
571576 }
572577 }
573578 }
574579
575580 public IEnumerable < IVoronoiCell > GetVoronoiCellsBasedOnCircumcenters ( ) => GetVoronoiCells ( GetTriangleCircumcenter ) ;
576581 public IEnumerable < IVoronoiCell > GetVoronoiCellsBasedOnCentroids ( ) => GetVoronoiCells ( GetCentroid ) ;
577-
582+
578583 public IEnumerable < IEdge > GetHullEdges ( ) => CreateHull ( GetHullPoints ( ) ) ;
579- public IPoint [ ] GetHullPoints ( ) => hull . Select ( x => Points [ x ] ) . ToArray ( ) ;
580- public IPoint [ ] GetTrianglePoints ( int t ) => PointsOfTriangle ( t ) . Select ( p => Points [ p ] ) . ToArray ( ) ;
581- public IPoint [ ] GetRellaxedPoints ( ) => GetVoronoiCellsBasedOnCircumcenters ( ) . Select ( x => GetCentroid ( x . Points ) ) . ToArray ( ) ;
584+
585+ public IPoint [ ] GetHullPoints ( ) => Array . ConvertAll < int , IPoint > ( hull , ( x ) => Points [ x ] ) ;
586+
587+ public IPoint [ ] GetTrianglePoints ( int t )
588+ {
589+ var points = new List < IPoint > ( ) ;
590+ foreach ( var p in PointsOfTriangle ( t ) )
591+ {
592+ points . Add ( Points [ p ] ) ;
593+ }
594+ return points . ToArray ( ) ;
595+ }
596+
597+ public IPoint [ ] GetRellaxedPoints ( )
598+ {
599+ var points = new List < IPoint > ( ) ;
600+ foreach ( var cell in GetVoronoiCellsBasedOnCircumcenters ( ) )
601+ {
602+ points . Add ( GetCentroid ( cell . Points ) ) ;
603+ }
604+ return points . ToArray ( ) ;
605+ }
606+
582607 public IEnumerable < IEdge > GetEdgesOfTriangle ( int t ) => CreateHull ( EdgesOfTriangle ( t ) . Select ( p => Points [ p ] ) ) ;
583- public IEnumerable < IEdge > CreateHull ( IEnumerable < IPoint > points ) => points . Zip ( points . Skip ( 1 ) . Append ( points . FirstOrDefault ( ) ) , ( a , b ) => new Edge ( 0 , a , b ) ) . OfType < IEdge > ( ) ;
608+ public static IEnumerable < IEdge > CreateHull ( IEnumerable < IPoint > points ) => points . Zip ( points . Skip ( 1 ) . Append ( points . FirstOrDefault ( ) ) , ( a , b ) => new Edge ( 0 , a , b ) ) . OfType < IEdge > ( ) ;
584609 public IPoint GetTriangleCircumcenter ( int t )
585610 {
586611 var vertices = GetTrianglePoints ( t ) ;
@@ -591,14 +616,15 @@ public IPoint GetCentroid(int t)
591616 var vertices = GetTrianglePoints ( t ) ;
592617 return GetCentroid ( vertices ) ;
593618 }
594- public IPoint GetCircumcenter ( IPoint a , IPoint b , IPoint c ) => Circumcenter ( a . X , a . Y , b . X , b . Y , c . X , c . Y ) ;
595- public IPoint GetCentroid ( IPoint [ ] points )
619+ public static IPoint GetCircumcenter ( IPoint a , IPoint b , IPoint c ) => Circumcenter ( a . X , a . Y , b . X , b . Y , c . X , c . Y ) ;
620+
621+ public static IPoint GetCentroid ( IPoint [ ] points )
596622 {
597623 double accumulatedArea = 0.0f ;
598624 double centerX = 0.0f ;
599625 double centerY = 0.0f ;
600626
601- for ( int i = 0 , j = points . Count ( ) - 1 ; i < points . Count ( ) ; j = i ++ )
627+ for ( int i = 0 , j = points . Length - 1 ; i < points . Length ; j = i ++ )
602628 {
603629 var temp = points [ i ] . X * points [ j ] . Y - points [ j ] . X * points [ i ] . Y ;
604630 accumulatedArea += temp ;
@@ -674,7 +700,13 @@ public IEnumerable<int> EdgesAroundPoint(int start)
674700 incoming = Halfedges [ outgoing ] ;
675701 } while ( incoming != - 1 && incoming != start ) ;
676702 }
677- public IEnumerable < int > PointsOfTriangle ( int t ) => EdgesOfTriangle ( t ) . Select ( e => Triangles [ e ] ) ;
703+ public IEnumerable < int > PointsOfTriangle ( int t )
704+ {
705+ foreach ( var edge in EdgesOfTriangle ( t ) )
706+ {
707+ yield return Triangles [ edge ] ;
708+ }
709+ }
678710 public IEnumerable < int > TrianglesAdjacentToTriangle ( int t )
679711 {
680712 var adjacentTriangles = new List < int > ( ) ;
@@ -690,10 +722,10 @@ public IEnumerable<int> TrianglesAdjacentToTriangle(int t)
690722 return adjacentTriangles ;
691723 }
692724
693- public int NextHalfedge ( int e ) => ( e % 3 == 2 ) ? e - 2 : e + 1 ;
694- public int PreviousHalfedge ( int e ) => ( e % 3 == 0 ) ? e + 2 : e - 1 ;
695- public int [ ] EdgesOfTriangle ( int t ) => new int [ ] { 3 * t , 3 * t + 1 , 3 * t + 2 } ;
696- public int TriangleOfEdge ( int e ) { return ( int ) Math . Floor ( ( double ) ( e / 3 ) ) ; }
725+ public static int NextHalfedge ( int e ) => ( e % 3 == 2 ) ? e - 2 : e + 1 ;
726+ public static int PreviousHalfedge ( int e ) => ( e % 3 == 0 ) ? e + 2 : e - 1 ;
727+ public static int [ ] EdgesOfTriangle ( int t ) => new int [ ] { 3 * t , 3 * t + 1 , 3 * t + 2 } ;
728+ public static int TriangleOfEdge ( int e ) { return e / 3 ; }
697729 #endregion Methods based on index
698730 }
699- }
731+ }
0 commit comments