C# CAD programming

STLバイナリファイル出力機能の追加

STLバイナリファイルエクスポート処理の追加

C#にてSTLバイナリ出力機能を追加しました。基本的にはASCIIファイルで出力しなければデータの劣化が起きてしまうのですが、旧来からのCAD/CAMソフトには必ずある機能で相互のデータの受け渡しに必要なので追加しました。バイナリ出力フォーマットの解説もしています。コードの書き方やバイナリファイルの扱い方が知りたい方は必見です。

解説と結果画面の紹介

バイナリファイルのテスト処理を追加必須なのですが、バイナリエディタで出力を確認しながら開発しました。古典的ですが、一定の効果はあります。

結果としては「まだ出力内容に問題があるので、テストコード必要だよね。」という状態です。

エクスポートメニューのファイルの種類に「STLバイナリファイル」が追加されました。

STLバイナリファイルフォーマット

出力されるフォーマットは以下のようになります。

バイト数データ型データ内容
80char[ ]任意の文字列
4unsigned int三角形の枚数
--1つ目の三角形データ
4float三角形の法線ベクトルのX成分値
4float三角形の法線ベクトルのY成分値
4float三角形の法線ベクトルのZ成分値
4float三角形の1点目の頂点のX座標値
4float三角形の1点目の頂点のY座標値
4float三角形の1点目の頂点のZ座標値
4float三角形の2点目の頂点のX座標値
4float三角形の2点目の頂点のY座標値
4float三角形の2点目の頂点のZ座標値
4float三角形の3点目の頂点のX座標値
4float三角形の3点目の頂点のY座標値
4float三角形の3点目の頂点のZ座標値
2-未使用データ
--2つ目の三角形データ
4float三角形の法線ベクトルのX成分値
4float三角形の法線ベクトルのY成分値
4float三角形の法線ベクトルのZ成分値
4float三角形の1点目の頂点のX座標値
4float三角形の1点目の頂点のY座標値
4float三角形の1点目の頂点のZ座標値
4float三角形の2点目の頂点のX座標値
4float三角形の2点目の頂点のY座標値
4float三角形の2点目の頂点のZ座標値
4float三角形の3点目の頂点のX座標値
4float三角形の3点目の頂点のY座標値
4float三角形の3点目の頂点のZ座標値
2-未使用データ
・・・-(三角形の法線ベクトルのX成分値から未使用データまでを1枚の三角形データとして三角形枚数分のデータが続く)

実装コードの解説

C#のコードは以下の通りです。

        /// <summary>
        /// バイナリ(Binary)形式でのSTLファイル書き込み
        /// </summary>
        /// <param name="triangleMeshes">三角形メッシュ</param>
        /// <param name="filePath">ファイルパス</param>
        /// <returns></returns>
        public static async Task WriteBinaryAsync(IEnumerable<TriangleMesh> triangleMeshes, string filePath)
        {
            // filePath が入っていない場合はエラーとする
            if (filePath == null)
                throw new ArgumentNullException(nameof(filePath));

            // ファセットデータが無い場合はエラー
            if (triangleMeshes == null)
                throw new ArgumentNullException(nameof(triangleMeshes));

            try
            {
                // 上書きモードでファイルを開く
                using (var writer = new StreamWriter(filePath, false, Encoding.Unicode))
                {
                    await Task.Run(() =>
                    {
                        byte[] header = new byte[80];

                        // ヘッダ書き込み
                        writer.Write(header);

                        // ファセットの枚数書き込み
                        uint size = 0;

                        foreach (var triangleMesh in triangleMeshes)
                        {
                            size += (uint)triangleMesh.VertexIndices.Count();
                        }

                        writer.Write(size);

                        // 全ファセット書き込み
                        ushort buff = 0;

                        // 全ファセットデータ書き込み
                        foreach (var triangleMesh in triangleMeshes)
                        {
                            int i = 0;

                            foreach (var vertexIndces in triangleMesh.VertexIndices)
                            {
                                writer.Write(triangleMesh.VertexNormals.ElementAtOrDefault(i).X);
                                writer.Write(triangleMesh.VertexNormals.ElementAtOrDefault(i).Y);
                                writer.Write(triangleMesh.VertexNormals.ElementAtOrDefault(i).Z);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item1).X);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item1).Y);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item1).Z);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item2).X);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item2).X);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item2).X);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item3).X);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item3).Y);
                                writer.Write((float)triangleMesh.Vertices.ElementAtOrDefault(vertexIndces.Item3).Z);

                                writer.Write(buff);

                                i++;
                            }
                        }
                    });
                }
            }
            catch (Exception)
            {
                throw new Exception();
            }
        }

参考のGitHubリポジトリの紹介

ソースコードはGitHubに公開していますので、テストコード作成やバグフィックスにご協力していただく方募集中です。

https://github.com/redring1979/RedRing

-C#, CAD, programming
-

error: Content is protected !!