/// Create a loop. This automatically adjusts connectivity. /// @param vertices an array of vertices, these are copied /// @param count the vertex count public void CreateLoop(Vector2[] vertices, int count = -1) { if (count == -1) { count = vertices.Length; } Debug.Assert(Vertices == null && Count == 0); Debug.Assert(count >= 3); if (count < 3) { return; } for (var i = 1; i < count; ++i) { var v1 = vertices[i - 1]; var v2 = vertices[i]; // If the code crashes here, it means your vertices are too close together. Debug.Assert(Vector2.DistanceSquared(v1, v2) > Settings.LinearSlop * Settings.LinearSlop); } Count = count + 1; Vertices = new Vector2[Count]; Array.Copy(vertices, Vertices, count); Vertices[count] = Vertices[0]; PrevVertex = Vertices[Count - 2]; NextVertex = Vertices[1]; }
/// <summary> /// Create a chain with ghost vertices to connect multiple chains together. /// </summary> /// <param name="vertices">an array of vertices, these are copied</param> /// <param name="count">the vertex count</param> /// <param name="prevVertex">previous vertex from chain that connects to the start</param> /// <param name="nextVertex">next vertex from chain that connects to the end</param> public void CreateChain(Vector2[] vertices, int count, Vector2 prevVertex, Vector2 nextVertex) { Debug.Assert(Vertices == null && Count == 0); Debug.Assert(count >= 2); for (var i = 1; i < count; ++i) { // If the code crashes here, it means your vertices are too close together. Debug.Assert( Vector2.DistanceSquared(vertices[i - 1], vertices[i]) > Settings.LinearSlop * Settings.LinearSlop); } Count = count; Vertices = new Vector2[count]; Array.Copy(vertices, Vertices, count); PrevVertex = prevVertex; NextVertex = nextVertex; }
/// Create a convex hull from the given array of local points. /// The count must be in the range [3, b2_maxPolygonVertices]. /// @warning the points may be re-ordered, even if they form a convex polygon /// @warning collinear points are handled but not removed. Collinear points /// may lead to poor stacking behavior. public void Set(Vector2[] vertices, int count = -1) { if (count == -1) { count = vertices.Length; } Debug.Assert(3 <= count && count <= MaxPolygonVertices); // 顶点数小于3,视为盒子 if (count < 3) { SetAsBox(1.0f, 1.0f); return; } // 顶点数最大为 MaxPolygonVertices var n = Math.Min(count, MaxPolygonVertices); // Perform welding and copy vertices into local buffer. Span <Vector2> ps = stackalloc Vector2[MaxPolygonVertices]; var tempCount = 0; for (var i = 0; i < n; ++i) { var v = vertices[i]; var unique = true; for (var j = 0; j < tempCount; ++j) { if (Vector2.DistanceSquared(v, ps[j]) < 0.5f * Settings.LinearSlop * (0.5f * Settings.LinearSlop)) { unique = false; break; } } if (unique) { ps[tempCount] = v; tempCount++; } } n = tempCount; if (n < 3) { // Polygon is degenerate. throw new InvalidOperationException("Invalid polygon shape"); } // Create the convex hull using the Gift wrapping algorithm // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm // Find the right most point on the hull var i0 = 0; var x0 = ps[0].x; for (var i = 1; i < n; ++i) { var x = ps[i].x; if (x > x0 || x.Equals(x0) && ps[i].y < ps[i0].y) { i0 = i; x0 = x; } } Span <int> hull = stackalloc int[MaxPolygonVertices]; var m = 0; var ih = i0; for (;;) { Debug.Assert(m < MaxPolygonVertices); hull[m] = ih; var ie = 0; for (var j = 1; j < n; ++j) { if (ie == ih) { ie = j; continue; } var r = ps[ie] - ps[hull[m]]; var v = ps[j] - ps[hull[m]]; var c = MathUtils.Cross(r, v); if (c < 0.0f) { ie = j; } // Collinearity check if (c.Equals(0.0f) && v.LengthSquared() > r.LengthSquared()) { ie = j; } } ++m; ih = ie; if (ie == i0) { break; } } if (m < 3) { // Polygon is degenerate. throw new InvalidOperationException("Invalid polygon shape"); } Count = m; // Copy vertices. for (var i = 0; i < m; ++i) { Vertices[i] = ps[hull[i]]; } // Compute normals. Ensure the edges have non-zero length. for (var i = 0; i < m; ++i) { var i1 = i; var i2 = i + 1 < m ? i + 1 : 0; var edge = Vertices[i2] - Vertices[i1]; Debug.Assert(edge.LengthSquared() > Settings.Epsilon * Settings.Epsilon); Normals[i] = MathUtils.Cross(edge, 1.0f); Normals[i].Normalize(); } // Compute the polygon centroid. Centroid = ComputeCentroid(Vertices, m); }