Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。

AutoCAD API:ブール演算が失敗する

Issue

3D ソリッド オブジェクトを作成して API でブール演算すると、次のようなエラーメッセージを表示して処理に失敗してしまいます。

ソリッドまたはサーフェス ボディのブール演算に失敗しました。
モデリング操作エラー:
Error Code Number is xxxxxxx (xxxxxxx は数字)

ブール演算を成功させる方法はありますか?

 

Solution

モデリング操作エラーや、その要因となっているソリッドやサーフェスモデルの破損は、AutoCAD を含むオートデスク製品全般で共用している ACIS 由来のソリッド カーネル Autodesk Shape Manager の精度上の制限が原因となっているのが一般的です。このため、ObjectARX、.NET API、AutoLISP、ActiveX オートメーション(COM API)など、API の種類に関わらず発生することがあります。同様に、AutoCAD の UNION[和] コマンドや SUBTRACT[差] コマンドでも発生するはずです。また、複雑なソリッドやサーフェスモデルの作成時にも発生する場合があります。

 

AutoCAD 2027 以降のバージョンであれば、Autodesk Assistant がヒントを与えてくれる場合があります。Error Code Number is xxxxxxx ののエラー数字とともに確認することも出来ますので、念のため、確認してみてください。

 

aa.png

 

ソリッドやサーフェスモデルが破損しているか否かは、SOLIDEDIT[ソリッド編集] コマンドの B オプション >> C オプション([ボディ(B)]: [チェック(C)])で確認することが出来ます。まずは、ソリッドやサーフェスモデルが健全かどうかを確認してみてください。

すべてのケースで問題を回避出来る訳ではありませんが、一般に、ソリッドやサーフェスモデル内部情報の破損の可能性を低減する、または、ブール演算時のエラーを低減するには、次のような構造をアドイン アプリケーション内で実装が推奨されています。

 

  1. ソリッドモデル / サーフェスモデル、素材となるオブジェクトの境界ボックス座標 X、Y、Z 値の最大値が 10,000 以上(最小値の場合、-10,000)になる場合、
  2. 最大座標が 10,000 未満(あるいは、-10,000 未満)になるようにソリッド モデルを一時的に原点付近置くか、最大座標が 10,000 未満になるように縮小する。
  3. 原点付近、かつ、最大座標が 10,000 未満になる状態でソリッド モデルの編集、ブール演算をおこなう。
  4. ソリッドモデル / サーフェスモデルを縮小した場合、または、縮尺した状態で結果を得た場合には、元の尺度に拡大処理して、元の配置位置に移動する(戻す)。

 

次の C# コードは、3D 処理前後で原点を基準に 1/100 に縮尺➔処理➔100 倍に拡大(元の大きさ復元)する参考例です。

 

...
using (Transaction tr = db.TransactionManager.StartTransaction())
{
    Entity ent1 = (Entity)tr.GetObject(pent1.ObjectId, OpenMode.ForRead);
    Entity ent2 = (Entity)tr.GetObject(pent2.ObjectId, OpenMode.ForRead);

    // 原点(0,0,0)を基準に 1/100 へ縮尺するマトリックス
    Matrix3d scaleDownMat = Matrix3d.Scaling(1.0 / 100.0, Point3d.Origin);

    // 原点(0,0,0)を基準に 100 倍へ拡大するマトリックス
    Matrix3d scaleUpMat = Matrix3d.Scaling(100.0, Point3d.Origin);

    // 元オブジェクトは変更しないよう、複製してから縮尺
    using (Entity ent1Scaled = (Entity)ent1.Clone())
    using (Entity ent2Scaled = (Entity)ent2.Clone())
    {
        ent1Scaled.TransformBy(scaleDownMat);
        ent2Scaled.TransformBy(scaleDownMat);

        // 1/100 に縮尺したオブジェクトで 3D 処理(ブール演算・3D オブジェクト作成

        // 作成した結果(オブジェクト)を、同じ原点(0,0,0)基準で 100 倍に戻す
        entresult.TransformBy(scaleUpMat);

        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

        ms.AppendEntity(entresult);
        tr.AddNewlyCreatedDBObject(entresult, true);
    }

    tr.Commit();
}
...