1313
1414namespace Mathematics
1515{
16- /// <inheritdoc />
1716 /// <summary>
18- /// In the future will be retooled to polygons.
17+ /// Helper Object to handle the description of a 3D object.
18+ /// Supports triangles and larger polygons.
1919 /// </summary>
2020 public sealed class PolyTriangle : IEquatable < PolyTriangle >
2121 {
2222 /// <summary>
23- /// Initializes a new instance of the <see cref="PolyTriangle" /> class.
23+ /// Gets the vertices.
24+ /// </summary>
25+ /// <value>
26+ /// The vertices.
27+ /// </value>
28+ public Vector3D [ ] Vertices { get ; }
29+
30+ /// <summary>
31+ /// Gets the vertex count.
32+ /// </summary>
33+ /// <value>
34+ /// The vertex count.
35+ /// </value>
36+ public int VertexCount => Vertices . Length ;
37+
38+ /// <summary>
39+ /// Initializes a new instance for a generic polygon (N-gon).
2440 /// </summary>
2541 /// <param name="array">The array.</param>
2642 public PolyTriangle ( IReadOnlyList < Vector3D > array )
2743 {
2844 Vertices = new Vector3D [ array . Count ] ;
29-
3045 for ( var i = 0 ; i < array . Count ; i ++ )
3146 {
3247 Vertices [ i ] = array [ i ] ;
3348 }
3449 }
3550
3651 /// <summary>
37- /// Gets the normal.
52+ /// HIGH PERFORMANCE CONSTRUCTOR: Specifically for standard Triangles.
53+ /// Prevents double heap-allocation of temporary arrays.
54+ /// </summary>
55+ public PolyTriangle ( Vector3D v1 , Vector3D v2 , Vector3D v3 )
56+ {
57+ Vertices = new [ ] { v1 , v2 , v3 } ;
58+ }
59+
60+ /// <summary>
61+ /// Gets the normal of the polygon.
3862 /// </summary>
3963 /// <value>
40- /// The normal.
64+ /// The normal.
4165 /// </value>
4266 public Vector3D Normal
4367 {
4468 get
4569 {
70+ // Safety check: A line or point doesn't have a 3D normal
71+ if ( VertexCount < 3 ) return Vector3D . ZeroVector ;
72+
4673 var u = Vertices [ 1 ] - Vertices [ 0 ] ;
4774 var v = Vertices [ 2 ] - Vertices [ 0 ] ;
4875
@@ -51,94 +78,38 @@ public Vector3D Normal
5178 }
5279
5380 /// <summary>
54- /// Gets the vertex count .
81+ /// Gets or sets the <see cref="Vector3D"/> with the specified i .
5582 /// </summary>
5683 /// <value>
57- /// The vertex count.
58- /// </value>
59- public int VertexCount => Vertices . Length ;
60-
61- /// <summary>
62- /// Gets or sets the vertices.
63- /// </summary>
64- /// <value>
65- /// The vertices.
66- /// </value>
67- public Vector3D [ ] Vertices { get ; }
68-
69- /// <summary>
70- /// Gets or sets the <see cref="Vector3D" /> with the specified i.
71- /// </summary>
72- /// <value>
73- /// The <see cref="Vector3D" />.
84+ /// The <see cref="Vector3D"/>.
7485 /// </value>
7586 /// <param name="i">The i.</param>
76- /// <returns>vector by id </returns>
87+ /// <returns></returns>
7788 public Vector3D this [ int i ]
7889 {
7990 get => Vertices [ i ] ;
8091 set => Vertices [ i ] = value ;
8192 }
8293
8394 /// <summary>
84- /// Indicates whether the current object is equal to another object of the same type.
85- /// </summary>
86- /// <param name="other">An object to compare with this object.</param>
87- /// <returns>
88- /// <see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise,
89- /// <see langword="false" />.
90- /// </returns>
91- public bool Equals ( PolyTriangle other )
92- {
93- // If the other object is null, return false
94- if ( other == null )
95- {
96- return false ;
97- }
98-
99- // If the other object is the same instance as this object, return true
100- if ( ReferenceEquals ( this , other ) )
101- {
102- return true ;
103- }
104-
105- // If the number of vertices is different, the triangles are not equal
106- if ( VertexCount != other . VertexCount )
107- {
108- return false ;
109- }
110-
111- // Compare each vertex of the triangles
112- for ( var i = 0 ; i < VertexCount ; i ++ )
113- {
114- if ( Vertices [ i ] != other . Vertices [ i ] )
115- {
116- return false ;
117- }
118- }
119-
120- // If all vertices are equal, the triangles are equal
121- return true ;
122- }
123-
124- /// <summary>
125- /// Creates the triangle set.
126- /// Triangles need to be supplied on a CLOCKWISE order
95+ /// Creates the triangle set from a raw list of vertices.
96+ /// Triangles need to be supplied in a CLOCKWISE order.
12797 /// </summary>
12898 /// <param name="triangles">The triangles.</param>
129- /// <returns>A list with Triangles, three Vectors in one Object </returns>
99+ /// <returns>List of Poly Triangles. </returns>
130100 public static List < PolyTriangle > CreateTri ( List < TertiaryVector > triangles )
131101 {
132- var polygons = new List < PolyTriangle > ( ) ;
102+ // Pre-allocate list capacity for a slight performance boost
103+ var polygons = new List < PolyTriangle > ( triangles . Count / 3 ) ;
133104
134105 for ( var i = 0 ; i <= triangles . Count - 3 ; i += 3 )
135106 {
136- var v1 = triangles [ i ] ;
137- var v2 = triangles [ i + 1 ] ;
138- var v3 = triangles [ i + 2 ] ;
139-
140- var array = new [ ] { ( Vector3D ) v1 , ( Vector3D ) v2 , ( Vector3D ) v3 } ;
141- var tri = new PolyTriangle ( array ) ;
107+ // Use the new highly optimized constructor directly
108+ var tri = new PolyTriangle (
109+ ( Vector3D ) triangles [ i ] ,
110+ ( Vector3D ) triangles [ i + 1 ] ,
111+ ( Vector3D ) triangles [ i + 2 ]
112+ ) ;
142113
143114 polygons . Add ( tri ) ;
144115 }
@@ -147,93 +118,98 @@ public static List<PolyTriangle> CreateTri(List<TertiaryVector> triangles)
147118 }
148119
149120 /// <summary>
150- /// Gets the plot point.
121+ /// Gets the plot point.
151122 /// </summary>
152123 /// <param name="id">The identifier.</param>
153- /// <returns>2d Vector, we only need these anyways for drawing. </returns>
124+ /// <returns></returns>
154125 public Vector2D GetPlotPoint ( int id )
155126 {
156- if ( id >= VertexCount || id < 0 )
157- {
158- return Vector2D . ZeroVector ;
159- }
127+ if ( id >= VertexCount || id < 0 ) return Vector2D . ZeroVector ;
128+
160129 return ( Vector2D ) Vertices [ id ] ;
161130 }
162131
163- /// <summary>
164- /// Returns a hash code for this instance.
165- /// </summary>
166- /// <returns>
167- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
168- /// </returns>
169- public override int GetHashCode ( )
170- {
171- return Vertices [ 0 ] . GetHashCode ( ) ;
172- }
173132
174133 /// <summary>
175- /// Converts to string .
134+ /// Indicates whether the current object is equal to another object of the same type .
176135 /// </summary>
136+ /// <param name="other">An object to compare with this object.</param>
177137 /// <returns>
178- /// A <see cref="string " /> that represents this instance .
138+ /// <see langword="true" /> if the current object is equal to the <paramref name="other " /> parameter; otherwise, <see langword="false" /> .
179139 /// </returns>
180- public override string ToString ( )
140+ public bool Equals ( PolyTriangle other )
181141 {
182- var sb = new StringBuilder ( ) ;
183- for ( var i = 0 ; i < Vertices . Length ; i ++ )
142+ if ( other is null ) return false ;
143+ if ( ReferenceEquals ( this , other ) ) return true ;
144+ if ( VertexCount != other . VertexCount ) return false ;
145+
146+ for ( var i = 0 ; i < VertexCount ; i ++ )
184147 {
185- sb . Append ( i ) . Append ( MathResources . Separator ) . Append ( Vertices [ i ] ) . Append ( Environment . NewLine ) ;
148+ if ( Vertices [ i ] != other . Vertices [ i ] ) return false ;
186149 }
187150
188- return sb . ToString ( ) ;
151+ return true ;
189152 }
190153
191154 /// <summary>
192- /// Determines whether the specified <see cref="Object" />, is equal to this instance.
155+ /// Determines whether the specified <see cref="System. Object" />, is equal to this instance.
193156 /// </summary>
194- /// <param name="obj">The <see cref="Object" /> to compare with this instance.</param>
157+ /// <param name="obj">The <see cref="System. Object" /> to compare with this instance.</param>
195158 /// <returns>
196- /// <c>true</c> if the specified <see cref="Object" /> is equal to this instance; otherwise, <c>false</c>.
159+ /// <c>true</c> if the specified <see cref="System. Object" /> is equal to this instance; otherwise, <c>false</c>.
197160 /// </returns>
198- public override bool Equals ( object obj )
199- {
200- return obj is PolyTriangle other && Equals ( other ) ;
201- }
161+ public override bool Equals ( object obj ) => obj is PolyTriangle other && Equals ( other ) ;
202162
203163 /// <summary>
204- /// Implements the operator == .
164+ /// Returns a hash code for this instance .
205165 /// </summary>
206- /// <param name="first">The first.</param>
207- /// <param name="second">The second.</param>
208166 /// <returns>
209- /// The result of the operator .
167+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table .
210168 /// </returns>
211- public static bool operator == ( PolyTriangle first , PolyTriangle second )
169+ public override int GetHashCode ( )
212170 {
213- if ( first is null && second is null )
214- {
215- return true ;
216- }
217-
218- if ( first is null || second is null )
219- {
220- return false ;
221- }
171+ // Safely combine the hashes of up to the first 3 vertices
172+ // to drastically reduce hash collisions for connected geometry.
173+ if ( VertexCount >= 3 )
174+ return HashCode . Combine ( Vertices [ 0 ] , Vertices [ 1 ] , Vertices [ 2 ] ) ;
175+ if ( VertexCount == 2 )
176+ return HashCode . Combine ( Vertices [ 0 ] , Vertices [ 1 ] ) ;
177+ if ( VertexCount == 1 )
178+ return Vertices [ 0 ] . GetHashCode ( ) ;
179+
180+ return 0 ;
181+ }
222182
183+ public static bool operator == ( PolyTriangle first , PolyTriangle second )
184+ {
185+ if ( first is null ) return second is null ;
223186 return first . Equals ( second ) ;
224187 }
225188
226189 /// <summary>
227- /// Implements the operator !=.
190+ /// Implements the operator !=.
228191 /// </summary>
229192 /// <param name="first">The first.</param>
230193 /// <param name="second">The second.</param>
231194 /// <returns>
232- /// The result of the operator.
195+ /// The result of the operator.
233196 /// </returns>
234- public static bool operator != ( PolyTriangle first , PolyTriangle second )
197+ public static bool operator != ( PolyTriangle first , PolyTriangle second ) => ! ( first == second ) ;
198+
199+ /// <summary>
200+ /// Converts to string.
201+ /// </summary>
202+ /// <returns>
203+ /// A <see cref="System.String" /> that represents this instance.
204+ /// </returns>
205+ public override string ToString ( )
235206 {
236- return ! ( first == second ) ;
207+ var sb = new StringBuilder ( ) ;
208+ for ( var i = 0 ; i < Vertices . Length ; i ++ )
209+ {
210+ sb . Append ( i ) . Append ( MathResources . Separator ) . Append ( Vertices [ i ] ) . Append ( Environment . NewLine ) ;
211+ }
212+ return sb . ToString ( ) ;
237213 }
238214 }
239215}
0 commit comments