Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
質問 AutoCADの.net APIで寸法拘束の拘束フォームを変更する方法はありますか。 回答 残念ながら、AutoCADの.net APIには寸法拘束の拘束フォームを変更するAPIはありません。 一方でObjectARX C++のAPIには対応するAPIが存在するため、.netのプログラムからは、P/Invoke を用いることで.netから寸法拘束の拘束フォームを変更することが可能です。   寸法拘束の拘束フォームの変更には、ObjectARX C++の寸法線の基底クラスAcDbDimensionの、isConstraintDynamic()メソッドおよびsetConstraintDynamic(bool isDynamic)メソッドを使用します。   isConstraintDynamic()メソッドは、その戻り値で現在の拘束フォームの設定状態を確認することが出来ます(true:ダイナミック, false:注釈)。 また、setConstraintDynamic(bool isDynamic)メソッドは、引数に指定した値で拘束フォームの設定状態を変更することが可能です。   以下は、AutoCAD 2023でP/Invokeを用いて.net で作成したAutoCADのカスタムコマンドから、選択した寸法拘束の拘束フォームの設定を変更するサンプルコードとなります。 [CommandMethod("FlipConstraintsForm")] public void FlipConstraintsForm() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; var option = new PromptEntityOptions("\n" + "Select a dimension constraints."); PromptEntityResult result = ed.GetEntity(option); if (result.Status != PromptStatus.OK) return; ObjectId id = result.ObjectId; using (Transaction tx = db.TransactionManager.StartTransaction()) { Dimension dim = tx.GetObject(id, OpenMode.ForWrite) as Dimension; DatabaseExtensions.DatabaseExtensions.Dimension_FlipConstraintsForm(dim); tx.Commit(); } } //DatabaseExtensions.cs namespace DatabaseExtensions { public class DatabaseExtensions { private static class AcDbDimension { [DllImport("acdb24.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?isConstraintDynamic@AcDbDimension@@QEBA_NXZ")] [return: MarshalAs(UnmanagedType.Bool)] public static extern Boolean isConstraintDynamic(IntPtr dimension); [DllImport("acdb24.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?setConstraintDynamic@AcDbDimension@@QEAA?AW4ErrorStatus@Acad@@_N@Z")] public static extern ErrorStatus setConstraintDynamic(IntPtr dimension, [MarshalAs(UnmanagedType.Bool)] Boolean bDynamic); } public static void Dimension_FlipConstraintsForm(Dimension dim) { dim.UpgradeOpen(); bool isDynamic = AcDbDimension.isConstraintDynamic(dim.UnmanagedObject); AcDbDimension.setConstraintDynamic(dim.UnmanagedObject, !isDynamic); } } }   DllImportによりImportするdllファイル名は、対象のAutoCADのバージョンに依存して変わる点にご留意ください。   なお、P/Invokeを用いたAPIの実装方法についてはこちらの記事に開設がありますので、ご参照ください。
記事全体を表示
Issue Civil3DのImportSubassembly APIでSubassemblyComposerで作成したサブアセンブリが正しく挿入されmせん。API自体はエラーもなく実行できていますが、挿入したサブアセンブリには作成時に設定したパラメータも表示されず、また形状もSubassemblyComposerで作成したものではなく、「○」の状態となってしまう。 なお、対象のサブアセンブリはツールパレットには読み込まれており、GUIからは正しく図面に挿入することが出来ています。   Solution ImportSubassembly APIの不具合により、正しく挿入ができていない状況と思われます。   ImportSubassemblyの引数に指定しているatcファイルをテキストエディタで開き、ファイル内のDataTypeの記述を編集することでImportSubassembly にて配置をすることが可能となります。   DataType="long" → DataType="Long" DataType="double" → DataType="Double" DataType="bool" → DataType="Bool" DataType="string" → DataType="String"  
記事全体を表示
Issue 図面ファイルを開いた際に、その図面ファイルの DWG ファイル形式が表示されます。 この情報を AutoCAD .NET API で取得することは出来ますか?    Solution 図面ファイル形式は、Database.OriginalFileVersion プロパティで返される DwgVersion 値で取得することが出来ます。    次のコードは、その C# 使用例です。   [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = Application.DocumentManager.MdiActiveDocument.Database; ed.WriteMessage("\nSaved DWG format:{0}", GetDwgFormat(db.OriginalFileVersion)); } private string GetDwgFormat(DwgVersion ver) { string dwgFormat = string.Empty; switch (ver) { case DwgVersion.AC1002: dwgFormat = "AutoCAD 2.5 形式"; break; case DwgVersion.AC1003: dwgFormat = "AutoCAD 2.6 形式"; break; case DwgVersion.AC1004: dwgFormat = "AutoCAD R9 形式"; break; case DwgVersion.AC1006: dwgFormat = "AutoCAD R10 形式"; break; case DwgVersion.AC1009: dwgFormat = "AutoCAD R11/R12 形式"; break; case DwgVersion.AC1012: dwgFormat = "AutoCAD R13 形式"; break; case DwgVersion.AC1014: dwgFormat = "AutoCAD R14 形式"; break; case DwgVersion.AC1015: dwgFormat = "AutoCAD 2000 形式"; break; case DwgVersion.AC1021: dwgFormat = "AutoCAD 2007 形式"; break; case DwgVersion.AC1024: dwgFormat = "AutoCAD 2010 形式"; break; case DwgVersion.AC1027: dwgFormat = "AutoCAD 2013 形式"; break; case DwgVersion.AC1032: dwgFormat = "AutoCAD 2018 形式"; break; case DwgVersion.AC1800: case DwgVersion.AC1800a: dwgFormat = "AutoCAD 2004 形式"; break; default: dwgFormat = "Unknown 形式"; break; } return dwgFormat; }    
記事全体を表示
Issue AutoCAD .NET API:ダウンロードしたアセンブリが NETLOAD 出来ない - Autodesk Community の内容に沿ってブロック解除したアドイン アプリ アセンブリがロード出来ません。  なぜでしょうか?     Solution アセンブリ ファイルのブロックを解除しても改善が見られないようでしたら、SECURITYOPTIONS コマンドで [セキュリティ オプション] ダイアログの信頼できるパスにアセンブリ ファイルの配置パスをに追加してみてください。     セキュリティ オプションを変更したら、AutoCAD を再起動して、再度、NETLOAD してみてください。   ご参考: AutoCAD 2016 のセキュリティとアドインのデジタル署名 - Technology Perspective from Japan (typepad.com) アドイン ロード時の警告ダイアログ抑止 - Technology Perspective from Japan (typepad.com)
記事全体を表示
Issue .NET API で開発したアドイン アプリのアセンブリを他のコンピューターで動作テストしようとしています。 一旦、アセンブリを共有サーバーにアップロードして他のコンピューターにダウンロードすると、そのアセンブリがロード出来ません。  具体的には System.IO.FileLoadException 例外エラーが表示されてロードできません。 どうすればいいでしょうか?     Solution .NET Framework のセキュリティ ポリシーにより、クラウド ストレージを含むネットワーク リソースからダウンロードしたアセンブリ ファイルは読み込みがブロックされています。 Windows エクスプローラーからアセンブリのプロパティ ダイアログを表示させると、「許可する」項(Windows バージョンによっては「ブロック解除」項)が表示されます。 この項目にチェックしてブロックを解除すると、NETLOAD 出来るようになります。 一度、NETLOAD 時に例外エラーが発生した場合には、次の NETLOAD 作業前に AutoCAD を再起動してください。(キャッシュされたアセンブリ情報をクリアする目的)
記事全体を表示
Issue 連続実行で図形を順番に開いて、処理、保存しようとしています。図面を順次開く必要があるので、定義コマンドに CommandFlags.Session フラグを指定してアプリケーション実行コンテキスト コマンドにしていますが、この実行コンテキストだと、 開いた図面に対して Editor.Command メソッドでコマンド実行させることが出来ません。    次の C# コードでは、C:\temp フォルダ内の図面(.dwg)を順に開き、ZOOM コマンドを実行、図面を同じ名前で保存するものですが、ZOOM コマンドの実行で例外エラーになってしまいます。  [CommandMethod("UpdateDrawings", CommandFlags.Session)] public void UpdateDrawings() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; DocumentCollection docMgr = Application.DocumentManager; Document doc = null; try { string[] fnames = Directory.GetFiles(@"c:\temp", "*.dwg"); foreach (string fname in fnames) { ed.WriteMessage("\n--- {0}", fname); doc = docMgr.Open(fname, false); Application.DocumentManager.MdiActiveDocument.Editor.Command("ZOOM", "E"); doc.CloseAndSave(fname); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage("\n ERROR:{0}", ex.Message); } } なにかよい方法はないでしょうか?    Solution プリケーション実行コンテキスト コマンド(CommandFlags.Session フラグ指定コマンド)では、Editor.Command メソッドを利用したコマンドの同期コマンド呼び出しは出来ません。 今回のようなケースでは、通常、Document.SendStringToExecute メソッドで非同期的に実行させたいコマンドを送信することで、便宜上、ドキュメント実行コンテキスト でコマンド実行する対応が考えられます。 また、実行する内容にもよりますが、AutoCAD .NET API 環境では、DocumentCollection.ExecuteInCommandContextAsync メソッドを用いることで、アプリケーション実行コンテキスト コマンド内でドキュメント実行コンテキストを非同期的(Async/Await)にコマンド実行することも可能です。 [CommandMethod("UpdateDrawings", CommandFlags.Session)] public async void UpdateDrawings() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; DocumentCollection docMgr = Application.DocumentManager; Document doc = null; try { string[] fnames = Directory.GetFiles(@"c:\temp", "*.dwg"); foreach (string fname in fnames) { ed.WriteMessage("\n--- {0}", fname); doc = docMgr.Open(fname, false); await Application.DocumentManager.ExecuteInCommandContextAsync( async (obj) => { await Application.DocumentManager.MdiActiveDocument.Editor.CommandAsync("ZOOM", "E"); }, null ); doc.CloseAndSave(fname); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage("\n ERROR:{0}", ex.Message); } } 同様に、 スクリプト(.scr)を用いた処理も考えることも出来ます。 ご参考:AutoCAD 雑学:図面のサムネイル画像 - Technology Perspective from Japan (typepad.com)
記事全体を表示
Issue MSPACE[モデル空間] コマンドや PSPACE[ペーパー空間] コマンド のように、レイアウト上に配置したビューポートの編集モードを変更するメソッドはありますか?     Solution Editor.SwitchToModelSpace メソッドと Editor.SwitchToPaperSpace メソッドがそれぞれ該当します。   Editor.SwitchToModelSpace メソッドは、現在のビューポートをモデル空間編集モードに切り替えます。同様に、Editor.SwitchToPaperSpace メソッドは、現在のビューポートをペーパー空間編集モードに切り替えます。   AutoCAD のオンラインヘルプ「AutoCAD 2024 Developer and ObjectARX ヘルプ | 浮動ビューポート(.NET) | Autodesk」も参考にしてください。
記事全体を表示
Issue 寸法が参照する画層が、同寸法の削除後も削除出来ません。     ただし、一度、図面を保存して開き直すと削除出来ます。 図面を開き直さなくても、この画層を削除したいのですが、AutoCAD .NET API で可能でしょうか?   Solution AutoCAD .NET API では、Database.ReclaimMemoryFromErasedObjects メソッドでメモリ上の図面データベースからオブジェクトを削除する方法を利用することが出来ます。   このメソッドは、元々、32 ビット環境で大規模図面を操作する際の消費メモリ低減を狙ったものですが、図面を保存して開き直さなくても、同じセッションで図面データベース内の削除フラグが付いたオブジェクトをメモリから削除することが可能です。 下記コード例では、対象の寸法オブジェクトの削除後に ReclaimMemoryFromErasedObjects メソッドで同オブジェクトをメモリ上から削除、その後、参照画層と寸法を表現していた匿名ブロックを削除している点にご注意ください。 後半の処理(下部の Using スコープ)がないと、AUDIT コマンドで図面破損が報告されてしまうので注意が必要です。 少し趣旨が異なりますが、ちょうど、LAYDEL[画層削除] コマンドが処理する内容と似ています。   Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions peo1 = new PromptEntityOptions("\n削除する寸法を選択:"); PromptEntityResult pent = ed.GetEntity(peo1); if (pent.Status != PromptStatus.OK) { return; } ObjectIdCollection erased = new ObjectIdCollection(); ObjectId layId = ObjectId.Null; ObjectId blkId = ObjectId.Null; using (Transaction tr = db.TransactionManager.StartTransaction()) { Dimension dim = (Dimension)tr.GetObject(pent.ObjectId, OpenMode.ForWrite); erased.Add(pent.ObjectId); layId = dim.LayerId; blkId = dim.DimBlockId; dim.Erase(); tr.Commit(); } db.ReclaimMemoryFromErasedObjects(erased); using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTableRecord lay = (LayerTableRecord)tr.GetObject(layId, OpenMode.ForWrite); lay.Erase(); BlockTableRecord blk = (BlockTableRecord)tr.GetObject(blkId, OpenMode.ForWrite); blk.Erase(); tr.Commit(); }  
記事全体を表示
Issue 寸法を分解すると寸法値にあたる文字が MText オブジェクトとして分解されます。 この MText オブジェクトについて、MText.Contents プロパティから寸法値の文字を取得すると、寸法値にないコードが返される場合があります。   例:\A1;57,{\H0.7x;\S66^;}   このコードはどのようなものでしょうか?   Solution このコードは、マルチテキストの整形するために用意された「書式コード」と呼ばれるコードで、AutoCAD のオンラインヘルプ ページで内容を確認することが出来ます。 AutoCAD 2024 ヘルプ | 他のテキスト エディタの書式コード リファレンス | Autodesk AutoCAD .NET API で MText オブジェクトの文字列の内容を確認する場合には、Contents プロパティが書式コード付きの内容を、Text プロパティが書式コードを削除した内容を返すので、用途に応じてプロパティを使い分けることが出来ます。   Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityOptions peo = new PromptEntityOptions("\nMText オブジェクトを選択:"); peo.SetRejectMessage("\nMText オブジェクトではありません."); peo.AddAllowedClass(typeof(MText), true); PromptEntityResult pent = ed.GetEntity(peo); if (pent.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(pent.ObjectId, OpenMode.ForRead) as Entity; ed.WriteMessage("\nObject Type : " + ent.GetType().ToString()); MText mtext = (MText)ent; ed.WriteMessage("\n\tMText Text : {0}", mtext.Text); ed.WriteMessage("\n\tMText Contents : {0}", mtext.Contents); tr.Commit(); }   寸法オブジェクトを分解せずに、AutoCAD .NET API :分解せずに寸法文字の情報を取得するには? (autodesk.co.jp) の方法も利用することが可能です。 
記事全体を表示
Issue Database.CurrentSpaceId プロパティでアクティブなレイアウトのレイアウト(ペーパー空間)の BlockTableRecord を取得して、対応する Layout を得ています。   [CommandMethod("GetLayoutId", CommandFlags.NoTileMode | CommandFlags.Modal)] public void GetLayoutId() { Database acCurDb = Application.DocumentManager.MdiActiveDocument.Database; Editor acDocEd = Application.DocumentManager.MdiActiveDocument.Editor; using (Transaction acTr = acCurDb.TransactionManager.StartTransaction()) { ObjectId objId = acCurDb.CurrentSpaceId; BlockTableRecord oRec = (BlockTableRecord)acTr.GetObject(objId, OpenMode.ForRead); if (oRec.IsLayout) { Layout oLay = (Layout)acTr.GetObject(oRec.LayoutId, OpenMode.ForRead); acDocEd.WriteMessage("\nCurrent LayoutId:{0}, Tab Name:{1}", oLay.ObjectId.ToString(), oLay.LayoutName); } acTr.Commit(); } }   ただ、レイアウト上のビューポートでモデル空間がアクティブになっていると、モデル空間を表す BlockTableRecord に対するレイアウト名(モデル空間のタブ名「モデル」は英語の「Model」)が表示されてしまいます。      ビューポートでモデル空間がアクティブな状態でも、アクティブなレイアウトに対応する Layout を得ることは出来るでしょうか?   Solution Database.CurrentSpaceId プロパティは、アクティブな空間の ID を返すプロパティです。 アクティブなレイアウトタブに対応する BlockTableRecord の ID を得るためには、システム変数 CTAB を利用することが出来ます。   [CommandMethod("GetLayoutId2", CommandFlags.NoTileMode | CommandFlags.Modal)] public void GetLayoutId2() { Database acCurDb = Application.DocumentManager.MdiActiveDocument.Database; Editor acDocEd = Application.DocumentManager.MdiActiveDocument.Editor; string strLay = (string)Application.GetSystemVariable("CTAB"); using (Transaction acTr = acCurDb.TransactionManager.StartTransaction()) { BlockTable oTbl = (BlockTable)acTr.GetObject(acCurDb.BlockTableId, OpenMode.ForRead); Layout oLay; BlockTableRecord oRec; foreach (ObjectId objId in oTbl) { oRec = (BlockTableRecord)acTr.GetObject(objId, OpenMode.ForRead); if (oRec.IsLayout) { oLay = (Layout)acTr.GetObject(oRec.LayoutId, OpenMode.ForRead); if (oLay.LayoutName == strLay) acDocEd.WriteMessage("\nCurrent LayoutId:{0}, Tab Name:{1}", oLay.ObjectId.ToString(), strLay); } } acTr.Commit(); } }  
記事全体を表示
Issue 特定の作図コマンドの実行を抑止する目的で、CommandWillStart イベント ハンドラ内で Document.SendStringToExecute メソッドを使って ESC コード(C#:"\x1B"、VB.NET:Chr$(27) )を送信してコマンドの実行をキャンセルしています。   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; doc.SendStringToExecute("\x1B\x1B", false, true, false);   他にコマンドの実行を抑止する方法はないでしょうか?   Solution ドキュメント ウィンドウに表示されている図面に作図をする場合、AutoCAD は内部的にドキュメントをロックします。   ドキュメント ロックはアプリケーション実行コンテキストで定義したコマンドの実装時に必要になる知識と言えますが、この仕組みをイベント ハンドラで取得、利用することが出来ます。   この場合、DocumentLockModeChanged イベント ハンドラで DocumentLockModeChangedEventArgs.Veto メソッドを呼び出すことで、作図コマンドの実行時にドキュメント ロックを拒否してコマンドの実行そのものを抑止することが出来ます。    次の C# コードは、LINE コマンドの実行を抑止する例です。   ... [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; Application.DocumentManager.DocumentLockModeChanged += DocumentEvent_LockModeChanged_Handler; } private static void DocumentEvent_LockModeChanged_Handler(object sender, DocumentLockModeChangedEventArgs e) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; if (e.GlobalCommandName == "LINE") { e.Veto(); ed.WriteMessage(string.Format("\n{0} command was vetoed\n", e.GlobalCommandName)); } } ...    
記事全体を表示
質問 AutoCAD Plant3D .net API でデータマネージャで表示されているガスケットのプロパティ情報を取得したい。 回答 ガスケット(≒ コネクタ)の場合、Connector.AllSubPartsからサブパーツ数を取得し、DataLinksManager.MakeAcPpObjectId()をsubIndexを指定してrowIdを取得後にDataLinksManager.GetAllProperties()を実行することでプロパティを取得することが可能となります。   以下は、選択したガスケットのプロパティ情報を取得するC#のサンプルコードとなります。 [CommandMethod("GetPipingProperties")] public void GetPipingProperties() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityResult res = ed.GetEntity("Pick Object obtain properties : "); if (res.Status == PromptStatus.OK) { ObjectId objectId = res.ObjectId; PlantProject currentProj = PlantApplication.CurrentProject; PipingProject pipingProj = (PipingProject)currentProj.ProjectParts["Piping"]; DataLinksManager dlm = pipingProj.DataLinksManager; int rowId = dlm.FindAcPpRowId(res.ObjectId); List<KeyValuePair<string, string>> properties; properties = dlm.GetAllProperties(rowId, true); for (int i = 0; i < properties.Count; i++) ed.WriteMessage("\nProperty name:" + properties[i].Key + " = " + properties[i].Value); Database trDatabase = objectId.Database; using (Transaction tr = trDatabase.TransactionManager.StartTransaction()) { Connector connector = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Connector; if (connector != null) { SubPartCollection subPartCollection = connector.AllSubParts; int index = 1; foreach (object connectorSubPart in subPartCollection) { int acPcRowId = dlm.FindAcPpRowId(dlm.MakeAcPpObjectId(objectId, index)); List<KeyValuePair<string, string>> subProps = dlm.GetAllProperties(acPcRowId, true); if (subProps != null) { foreach(var subProp in subProps) ed.WriteMessage("\nProperty name:" + subProp.Key + " = " + subProp.Value); } index++; } } } } }
記事全体を表示
質問 AutoCAD .net APIで寸法補助線の開始、終了点と寸法線と寸法補助線の交差点の座標を取得したいのですが、方法はありますか。 回答 AutoCADの.net APIには、直接的に寸法補助線の開始・終了点や寸法線と寸法補助線の交差点の座標を取得するメソッドやプロパティはありません。このため、対象の寸法線の幾何情報から算出して取得する必要があります。 最も簡便な方法としては、対象の寸法線をExplodeにより分解し、分解して取得したオブジェクトの内容から計算をして取得する形となります。   以下は、平行寸法線に対して、寸法補助線の開始・終了点や寸法線と寸法補助線の交差点に点オブジェクトを作成するC#のサンプルコードです。  private static void makePoint(Point2d point, Transaction tx, BlockTableRecord acBlkTblRec) { DBPoint acPoint = new DBPoint(new Point3d(point.X, point.Y, 0)); acPoint.SetDatabaseDefaults(); acBlkTblRec.AppendEntity(acPoint); tx.AddNewlyCreatedDBObject(acPoint, true); } [CommandMethod("GetPointsOnAlignedDimension")] public static void GetPointsOnAlignedDimension() { Document dc = Application.DocumentManager.MdiActiveDocument; Database db = dc.Database; Editor ed = dc.Editor; PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\nSelect an Aligned Dimension:"; pso.SingleOnly = true; pso.SinglePickInSpace = true; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; SelectionSet ss = psr.Value; SelectedObject so = ss[0]; if (!so.ObjectId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AlignedDimension)))) { ed.WriteMessage("\nSelected entity is not Aligned Dimension..."); return; } ObjectId id = so.ObjectId; using (Transaction tx = db.TransactionManager.StartTransaction()) { try { // Open the Block table for read BlockTable acBlkTbl = tx.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // Open the Block table record Model space for write BlockTableRecord acBlkTblRec = tx.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; AlignedDimension dim = tx.GetObject(id, OpenMode.ForRead) as AlignedDimension; DBObjectCollection col = new DBObjectCollection(); dim.Explode(col); Point3d dimLoc = dim.DimLinePoint; Point3d xPt1 = dim.XLine1Point; Point3d xPt2 = dim.XLine2Point; Line2d entityLine = new Line2d(new Point2d(xPt1.X, xPt1.Y), new Point2d(xPt2.X, xPt2.Y)); Line2d dimensionLine = new Line2d(new Point2d(dimLoc.X, dimLoc.Y), entityLine.Direction); Line2d lineStargingFromPt1 = entityLine.GetPerpendicularLine(new Point2d(xPt1.X, xPt1.Y)); Line2d lineStargingFromPt2 = entityLine.GetPerpendicularLine(new Point2d(xPt2.X, xPt2.Y)); Point2d interSection1 = lineStargingFromPt1.IntersectWith(dimensionLine).First(); Point2d interSection2 = lineStargingFromPt2.IntersectWith(dimensionLine).First(); makePoint(interSection1, tx, acBlkTblRec); makePoint(interSection2, tx, acBlkTblRec); foreach(DBObject dbObj in col) { Line line = dbObj as Line; if (line == null) { continue; } Point2d startPt = new Point2d(line.StartPoint.X, line.StartPoint.Y); Point2d endPt = new Point2d(line.EndPoint.X, line.EndPoint.Y); if (lineStargingFromPt1.IsOn(startPt) && lineStargingFromPt1.IsOn(endPt)) { makePoint(startPt, tx, acBlkTblRec); makePoint(endPt, tx, acBlkTblRec); } else if (lineStargingFromPt2.IsOn(startPt) && lineStargingFromPt2.IsOn(endPt)) { makePoint(startPt, tx, acBlkTblRec); makePoint(endPt, tx, acBlkTblRec); } } db.Pdmode = 34; db.Pdsize = 1; tx.Commit(); } catch (System.Exception e) { tx.Abort(); ed.WriteMessage(e.Message); } } }   平行寸法線以外の場合にも、Explodeしたオブジェクトから各寸法線の特徴に合わせて幾何計算を行うことで取得が可能です。
記事全体を表示
質問 Inventor iLogicで現在開いているファイルがVaultに登録されているかを知る方法はありますか。 回答 Inventor iLogicからVaultのAPIを用いて、Vaultのチェックイン状態を確認することが可能です。   Vaultでのチェックイン状態を知るためには、対象のファイルのVualtのフォルダ構造のパス情報を用いてDocumentService.FindLatestFilesByPaths()メソッドを利用します。     以下は、現在Inventorで開いているファイルおよびその参照ファイルがVaultに登録されているかを確認し、Vaultに登録されていない場合は、iLogicのログにファイルのパスを出力するサンプルコードとなります。   なお、サンプルコードではわかりやすさを優先して、1ファイルずつDocumentService.FindLatestFilesByPaths()メソッドを実行していますが、 DocumentService.FindLatestFilesByPaths()メソッドには複数のパス情報を配列として指定可能なため、パフォーマンスを考慮した場合には、まとめて実行することをお勧めいたします。     ◆iLogicのファイルヘッダ AddReference "Autodesk.Connectivity.WebServices.dll" Imports AWS = Autodesk.Connectivity.WebServices AddReference "Autodesk.DataManagement.Client.Framework.Vault.dll" Imports VDF = Autodesk.DataManagement.Client.Framework AddReference "Connectivity.Application.VaultBase.dll" Imports VB = Connectivity.Application.VaultBase AddReference "Autodesk.DataManagement.Client.Framework"   ・ iLogicソース  Sub Main() Dim conn As VDF.Vault.Currency.Connections.Connection conn = VB.ConnectionManager.Instance.Connection If conn Is Nothing Then MessageBox.Show("Vaultにログインしていません。") Return End If Dim rootFolder As String rootFolder = conn .WorkingFoldersManager.GetWorkingFolder("$/").FullPath For Each doc As Inventor.Document In ThisDoc.Document.AllReferencedDocuments If (FindFileInVault(doc.FullFileName, rootFolder, conn)) Then Else Logger.Trace("{0} is not checked in to Vault ", doc.FullFileName) End If Next End Sub Public Function FindFileInVault(localfilePath As String, workingfolder As String, conn As VDF.Vault.Currency.Connections.Connection) As Boolean Dim VaultPath As String = localfilePath.Replace(workingfolder, "$/") VaultPath = VaultPath.Replace("\", "/") Dim VaultPaths() As String = New String() {VaultPath} Dim wsFiels() As AWS.File = conn.WebServiceManager.DocumentService.FindLatestFilesByPaths(VaultPaths) If wsFiels(0).Id <> -1 Then Return True End If Logger.Trace("localfilePath is {0}", localfilePath) Logger.Trace("VaultPath={0}, id={1}", VaultPath, wsFiels(0).Id) Return False End Function  
記事全体を表示
質問 AutoCAD .net API でパレットを作成しました。パレットには、テキストボックスを配置したカスタムコントロールを配置しています。パレットを表示しテキストボックスに値を入力している途中で、マウスカーソルをパレットから外すと、フォーカスがテキストボックスから外れ、以後のキー入力はAutoCADのコマンド入力として処理されてしまいます。 パレットからマウスカーソルを外してもフォーカスが外れないようにすることはできますか。   回答 PaletteSetを継承したクラスを作成し、KeepFocusメソッドをオーバライドして、フォーカスを外したくない場合には戻り値falseを戻すように実装することで実現が可能です。   以下は、テキストボックス(textBox1)を配置したユーザコントロール(UserControl1)をパレットに配置し、textBox1にフォーカスがある場合は、コントロールからフォーカスを外さない処理をKeepFocusメソッドに記述したサンプルコードとなります。   public class MyPalettSet : PaletteSet { private UserControl1 uctl1 = new UserControl1(); public MyPalettSet(string name) : base(name) { this.Style = PaletteSetStyles.ShowTabForSingle | PaletteSetStyles.ShowPropertiesMenu | PaletteSetStyles.ShowAutoHideButton | PaletteSetStyles.ShowCloseButton; this.MinimumSize = new System.Drawing.Size(400, 100); this.Add("uctl", uctl1); this.Visible = true; this.Size = new System.Drawing.Size(400, 100); this.DockEnabled = DockSides.None; } public override bool KeepFocus { get { return uctl1.Controls["textBox1"] != null ? uctl1.Controls["textBox1"].Focused : false; } } }
記事全体を表示
Issue AutoCAD のダイナミック ブロックについて、VBA でどの程度操作ができるかわかりません。 モデル空間などに配置されているダイナミック ブロックのパラメータの状態を取得したり、パラメータの値を更新して、形状や表示状態を変更することはできますか?   Solution ダイナミックブロックとして配置されているブロック参照からは、ある程度の情報を取得したり、その値を変化させることができます。ただし、現在のバージョンでは一部制限があるため、すべての情報の制御や、パラメータ間の関連付けを得ることができません。   ブロック参照からダイナミックブロック固有の情報にアクセスするには、AcadBlockReference オブジェクトの GetDynamicBlockProperties メソッドを使用して、パラメータ情報を含むコレクションを取得します。このコレクションには、DynamicBlockReferenceProperty オブジェクトがパラメータ(アクションとの組み合わせ)数分含まれます。   DynamicBlockReferenceProperty オブジェクトを取得した後は、このオブジェクトが持つプロパティを使って、パラメータ別の情報にアクセスできます。つまり、ダイナミック ブロック参照の現在の設定値を得ることが可能です。   なお、パラメータによっては、ルックアップ テーブルや可視テーブルなど、リスト化された情報も存在します。このような場面では、パラメータを表す DynamicBlockReferenceProperty.Value プロパティは配列として返されます。これをチェックすれば、その内容を AllowedValues プロパティから閲覧することもできます。   添付のコードは、ダイナミックブロックの情報を取得する例です。   Dim nDataIndex As Long Dim vDataInfo As Variant Dim oData As AcadDynamicBlockReferenceProperty Dim nListIndex As Long Dim vListInfo As Variant Dim nRound As Integer Dim oEnt As AcadEntity Dim oBlkRef As AcadBlockReference nRound = ThisDrawing.GetVariable("LUPREC") For Each pEnt In ThisDrawing.ModelSpace If pEnt.ObjectName = "AcDbBlockReference" Then Set oBlkRef = pEnt If oBlkRef.IsDynamicBlock Then ThisDrawing.Utility.Prompt vbCrLf & "***** ダイナミックブロック - " ThisDrawing.Utility.Prompt oBlkRef.EffectiveName & " : " & oBlkRef.Name nCtrlIndex = 1 For nDataIndex = LBound(oBlkRef.GetDynamicBlockProperties) To UBound(oBlkRef.GetDynamicBlockProperties) Set oData = oBlkRef.GetDynamicBlockProperties(nDataIndex) If oData.show Then ' パラメータ名ラベル ThisDrawing.Utility.Prompt vbCrLf & oData.PropertyName & " : " ' パラメータが配列か確認 vDataInfo = oData.Value If IsArray(vDataInfo) Then ' 座標データの場合 ThisDrawing.Utility.Prompt Round(vDataInfo(0), nRound) & "," & Round(vDataInfo(1), nRound) & "," & Round(vDataInfo(2), nRound) Else ' リスト要素か確認 vListInfo = oData.AllowedValues If UBound(vListInfo) > 0 Then ' リスト要素の場合 For nListIndex = LBound(vListInfo) To UBound(vListInfo) If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt vbCrLf & vbTab & CStr(Round(vListInfo(nListIndex), nRound)) Else ThisDrawing.Utility.Prompt vbCrLf & vbTab & vListInfo(nListIndex) End If Next nListIndex If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt vbCrLf & vbTab & "現在値 : " & CStr(Round(vDataInfo, nRound)) Else ThisDrawing.Utility.Prompt vbCrLf & vbTab & "現在値 : " & vDataInfo End If Else ' 通常データの場合 If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt Round(vDataInfo, nRound) Else ThisDrawing.Utility.Prompt vDataInfo End If End If End If End If ThisDrawing.Utility.Prompt vbCrLf Next End If End If Next
記事全体を表示
Issue FIELD コマンドで選択したオブジェクトの面積をフィールド文字として作成することは出来ますか?        Solution AutoCAD .NET API では、文字(DBText)または、マルチテキスト(MText)ブロックを作成後、[フィールド] ダイアログ下部に表示される「フィールド式」を SetField メソッドで設定することで、特定のオブジェクトを参照するフィールド文字を作成することが出来ます。     フィールド式中の _ObjId の値は、選択したオブジェクトの ObjectId 値になります。 次の C# コードは、ポリラインの面積をフィールド文字として作図する例です。   [CommandMethod("MyCommand")] public void MyCommand() // This method can have any name { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions options = new PromptEntityOptions("\nポリラインを選択:"); options.SetRejectMessage("\nポリラインを選択"); options.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Polyline), false); PromptEntityResult acSSPrompt = ed.GetEntity(options); if (acSSPrompt.Status != PromptStatus.OK) return; PromptPointOptions ppo = new PromptPointOptions("\n挿入点を指示:"); PromptPointResult ppr = ed.GetPoint(ppo); if (ppr.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { // %<\AcObjProp.16.2 Object(%<\_ObjId 3132455955584>%).Area \f "%lu2%pr1%ps[面積:, ㎡]%ct8[0.001]">% string strId = acSSPrompt.ObjectId.OldIdPtr.ToString(); string str1 = "%<\\AcObjProp.16.2 Object(%<\\_ObjId "; string str2 = ">%).Area \\f \"%lu2%pr1%ps[面積:, ㎡]%ct8[0.001]\">%"; string format = str1 + strId + str2; DBText text = new DBText(); text.Height = 10.0; text.Position = ppr.Value; ObjectId objId = SymbolUtilityServices.GetBlockModelSpaceId(db); BlockTableRecord btr = tr.GetObject(objId, OpenMode.ForWrite) as BlockTableRecord; btr.AppendEntity(text); tr.AddNewlyCreatedDBObject(text, true); Field entField = new Field(format); entField.Evaluate(); text.SetField(entField); tr.AddNewlyCreatedDBObject(entField, true); tr.Commit(); } }   作図したフィールド文字は、参照したポリラインの変化に追従するようになります。  
記事全体を表示
Issue 選択セットで条件に合った複数のオブジェクトを取得する際、特定の座標を持つ要素を条件に設定するにはどうしたらいいでしょうか?   Solution 選択セットのフィルタリングで座標を扱う際には、オンラインヘルプ 概要 - 選択セットのフィルタ リストでの関係テスト(AutoLISP) で触れられている、カンマ区切りで関係演算子を利用する方法を利用することが出来ます。   点グループ コードの場合、X、Y、Z に対するテストを結合して単一の文字列にできます。このとき、各演算子をカンマで区切ります(たとえば、">,>,*")。文字列から演算子を省略すると、すべてを選択する演算子 "*" とみなされます(たとえば、"=,<>" では Z がチェックされません)。 次のコードは、円オブジェクトの中心のX 座標が 123.45 以上123.46 以下で、Y 座標が 500.0、Z 座標値を無視するフィルタリングを指定した C# コードの例です。 Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; TypedValue[] typeAry = new TypedValue[9]; typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<and"), 0); typeAry.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 1); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<and"), 2); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, ">=,=,*"), 3); typeAry.SetValue(new TypedValue((int)DxfCode.XCoordinate, new Point3d(123.45, 500.0, 0.0)), 4); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "<=,=,*"), 5); typeAry.SetValue(new TypedValue((int)DxfCode.XCoordinate, new Point3d(123.46, 500.0, 0.0)), 6); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "and>"), 7); typeAry.SetValue(new TypedValue((int)DxfCode.Operator, "and>"), 8); SelectionFilter filter = new SelectionFilter(typeAry); PromptSelectionResult psr = ed.SelectAll(filter); if (psr.Status == PromptStatus.OK) { SelectionSet sset = psr.Value; ed.WriteMessage("\nNumber of objects selected : {0}", sset.Count.ToString()); ObjectIdCollection objIds = new ObjectIdCollection(sset.GetObjectIds()); using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent; foreach (ObjectId objId in objIds) { ent = (Entity)tr.GetObject(objId, OpenMode.ForRead); ent.Highlight(); } tr.Commit(); } } else { Application.ShowAlertDialog("\nNumber of objects selected: 0"); }  
記事全体を表示
現象 C#のコンソールアプリケーションで、Inventor Apprentice Server のApprenticeServerDocument.Thumbnailプロパティにアクセスするとエラーが発生します。 回避方法はありますか。   解決策 C#のコンソールApplicationの場合、Main関数に[STAThread]属性を付加しSTAで動作するように指定することで、Thumbnailプロパティにアクセスできるようになります。   [STAThread] static void Main(string[] args) {   なお、VB.netの場合コンソールアプリケーションはデフォルトでSTAで動作する設定のため、[STAThread]属性を付加する必要はありません。 また、C#の場合でもWindows フォームアプリケーションの場合も[STAThread]属性を付加する必要はありません。
記事全体を表示
Issue オンラインヘルプ「レイアウトをパブリッシュする(.NET) 」の例では、PublishExecute メソッドを利用して DSD ファイルを使ったバッチ印刷の方法を説明しています。ただし、この例では "DWG to PDF.PC3" を指定してプロッタ環境設定をオーバーライド(上書き)しています。 印刷対象のレイアウトに設定されたページ設定を利用してバッチ印刷する方法はありますか?   Solution PublishDsd メソッドで、定義済みのページ設定(印刷デバイスと設定)を使用してレイアウトを印刷、または、/ファイル出力することが出来ます。この場合、また、DsdData.SheetType の値を SheetType.OriginalDevice に指定することで、プロッタ環境設定(.pc3)を指定せずに連続印刷をおこなうことが可能です。 次のコードは、その C# 例です。 Try Dim collection As DsdEntryCollection = New DsdEntryCollection() Dim entry As DsdEntry entry = New DsdEntry() entry.Layout = "レイアウト1" entry.DwgName = "c:\Temp\Drawing1.dwg" entry.Nps = "Setup1" entry.Title = "Sheet1" collection.Add(entry) entry = New DsdEntry() entry.Layout = "レイアウト1" entry.DwgName = "c:\Temp\Drawing2.dwg" entry.Nps = "Setup1" entry.Title = "Sheet2" collection.Add(entry) Dim dsd As DsdData = New DsdData() dsd.SetDsdEntryCollection(collection) dsd.ProjectPath = "c:\Temp\" dsd.LogFilePath = "c:\Temp\logdwf.log" dsd.SheetType = SheetType.OriginalDevice dsd.NoOfCopies = 1 dsd.SheetSetName = "PublisherSet" dsd.WriteDsd("c:\Temp\publisher.dsd") Dim nbSheets As Integer = collection.Count Using progressDlg As PlotProgressDialog = New PlotProgressDialog(False, nbSheets, True) progressDlg.UpperPlotProgressRange = 100 progressDlg.LowerPlotProgressRange = 0 progressDlg.UpperSheetProgressRange = 100 progressDlg.LowerSheetProgressRange = 0 progressDlg.IsVisible = True Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("BACKGROUNDPLOT", 0) Dim publisher As Autodesk.AutoCAD.Publishing.Publisher = Autodesk.AutoCAD.ApplicationServices.Application.Publisher publisher.PublishDsd("c:\Temp\publisher.dsd", progressDlg) progressDlg.Destroy() End Using Catch ex As Autodesk.AutoCAD.Runtime.Exception MsgBox(ex.Message) End Try End Sub なお、PublishDsd メソッドを使用して DSD ファイルをパブリッシュする前に、BACKGROUNDPLOT システム変数を 0 に設定する必要があります。
記事全体を表示