public static Component_Mesh.StructureClass CreateMeshStructure(Face[] faces)
        {
            var result         = new Component_Mesh.StructureClass();
            int vertexMaxIndex = 0;

            //faces
            result.Faces = new Component_Mesh.StructureClass.Face[faces.Length];
            for (int nFace = 0; nFace < faces.Length; nFace++)
            {
                var face = faces[nFace];

                var triangles2 = new Component_Mesh.StructureClass.FaceVertex[face.Triangles.Length];
                for (int n = 0; n < triangles2.Length; n++)
                {
                    var faceVertex = face.Triangles[n];
                    triangles2[n] = new Component_Mesh.StructureClass.FaceVertex(faceVertex.Vertex, 0, faceVertex.RawVertex);

                    vertexMaxIndex = Math.Max(vertexMaxIndex, faceVertex.Vertex);
                }

                result.Faces[nFace] = new Component_Mesh.StructureClass.Face(triangles2, null, 0);
            }

            //edges
            var edges = new ESet <Vector2I>(vertexMaxIndex * 3);

            for (int nFace = 0; nFace < faces.Length; nFace++)
            {
                var face = faces[nFace];

                var edgeCounts = new Dictionary <Vector2I, int>(face.Triangles.Length);

                for (int nTriangle = 0; nTriangle < face.Triangles.Length / 3; nTriangle++)
                {
                    var faceVertex0 = face.Triangles[nTriangle * 3 + 0];
                    var faceVertex1 = face.Triangles[nTriangle * 3 + 1];
                    var faceVertex2 = face.Triangles[nTriangle * 3 + 2];

                    void AddEdge(int vertex1, int vertex2)
                    {
                        int v1, v2;

                        if (vertex1 > vertex2)
                        {
                            v1 = vertex2;
                            v2 = vertex1;
                        }
                        else
                        {
                            v1 = vertex1;
                            v2 = vertex2;
                        }
                        var key = new Vector2I(v1, v2);

                        edgeCounts.TryGetValue(key, out var count);
                        edgeCounts[key] = count + 1;
                    }

                    AddEdge(faceVertex0.Vertex, faceVertex1.Vertex);
                    AddEdge(faceVertex1.Vertex, faceVertex2.Vertex);
                    AddEdge(faceVertex2.Vertex, faceVertex0.Vertex);
                }

                foreach (var pair in edgeCounts)
                {
                    if (pair.Value == 1)
                    {
                        var edge = pair.Key;
                        edges.AddWithCheckAlreadyContained(new Vector2I(edge.X, edge.Y));
                    }
                }

                //for( int nTriangle = 0; nTriangle < face.Triangles.Length / 3; nTriangle++ )
                //{
                //	var faceVertex0 = face.Triangles[ nTriangle * 3 + 0 ];
                //	var faceVertex1 = face.Triangles[ nTriangle * 3 + 1 ];
                //	var faceVertex2 = face.Triangles[ nTriangle * 3 + 2 ];

                //	void AddEdge( int vertex1, int vertex2 )
                //	{
                //		int v1, v2;
                //		if( vertex1 > vertex2 )
                //		{
                //			v1 = vertex2;
                //			v2 = vertex1;
                //		}
                //		else
                //		{
                //			v1 = vertex1;
                //			v2 = vertex2;
                //		}
                //		edges.AddWithCheckAlreadyContained( new Vector2I( v1, v2 ) );
                //	}

                //	AddEdge( faceVertex0.Vertex, faceVertex1.Vertex );
                //	AddEdge( faceVertex1.Vertex, faceVertex2.Vertex );
                //	AddEdge( faceVertex2.Vertex, faceVertex0.Vertex );
                //}
            }
            result.Edges = edges.Select(e => new Component_Mesh.StructureClass.Edge(e.X, e.Y)).ToArray();

            //vertices
            result.Vertices = new Component_Mesh.StructureClass.Vertex[vertexMaxIndex + 1];

            return(result);
        }