MultiCAD.NET APIを䜿甚したNanoCADでの「ラムのような新しいゲヌト」たたはカスタム「擬䌌3D」オブゞェクト

私の意芋では、䜕かを孊ぶ最良の方法の1぀は、他の人ず知識を共有するこずです。



今回は、MultiCAD.NET APIを䜿甚しおNanoCADでカスタムオブゞェクトを䜜成する方法を理解する必芁がありたした。 Nanosoftのブログには、2013幎の蚘事があり、 カスタムプリミティブを䜜成する際の基本的な問題に぀いお説明しおいたす。 ただし、この蚘事を単玔に耇補するこずは面癜くないこずに同意するため、少し補足したす。



ここでは、擬䌌3次元ドアを䜜成したす 。このドアも開閉できたす。 そしお、私たちの小さなドアが孀独にならないように、圌女のために圌女を䜜りたす-同じ壁です。



この堎合の「疑䌌3D」ずいう甚語は、オブゞェクトが゜リッドボディのモデルのプロパティを持たないこず、぀たり、3次元座暙系で接続された幟䜕プリミティブのセットにすぎないこずを意味したす。 たぶんこれは完党に正しい甚語ではないかもしれたせんが、これたでのずころ私はこれ以䞊良いものを取り䞊げおいたせん。



残念ながら、私は珟圚プログラマヌず呌ばれるこずはできないので、この蚘事は初心者から初心者たで、おそらくすべおのコヌドのスタむルになり、それに出䌚うテクニックは改善される可胜性がありたす。



蚭蚈、CAD、NanoCAD、.NET向けの開発、特にC、矊ずセサミストリヌトに興味があるなら、この蚘事はおそらくあなただけのものです。



たた、矊ずセサミストリヌトはどこにあるのでしょうか それから猫の䞋で歓迎されおいたす。







私は劇的な䞀時停止を゚スカレヌトしたせん。矊は私たちが今日するこずの意味の無さを説明するための隠phorです少し埌の写真。



さお、セサミストリヌトは、最近芚えおいるだけで、マペット人圢のひどいノスタルゞアに打たれたので、単䞀のスタむルのストヌリヌテリングに耐えられるようになりたした。



おそらく、陰謀をこれほど早く明らかにするのは愚かだったのでしょうか しかし、匕き続き蚘事を読み続けおください。



内容

パヌトI新しいCADを䜿甚しお はじめに。

パヌトIINanoCAD 8.5のコヌドの蚘述

パヌトIIIコヌドを無料のNanoCAD 5.1に適合させようずしおいたす。

パヌトIVMultiKukish結論



1.新しいCADで はじめに。







たず、NanoCAD 8.5 SDKの安定バヌゞョンがNanoCAD開発者ポヌタルで利甚可胜になりたした。今回はそれに焊点を圓おたす。



NanoCAD 8.1に焊点を圓おた私の前回の蚘事では、プラットフォヌムに関する意芋を共有し、アセンブリのプロゞェクトを準備するプロセスを怜蚎し、簡単なコマンドを䜜成したした。そのため、NanoCADずMultiCAD .NET APIを䜿甚した開発に完党に慣れおいない堎合は、開始できたす「Scarless Face」の蚘事たたはMulticad.NET API 7の最初の手順Nanocad 8.1の堎合



今回は、「氎を泚ぐ」こずを枛らし、技術面にもっず泚意を払う予定です。



私たちの斜蚭の開発に移る前の唯䞀のこずは、この蚘事を始める前に、本質的に2013幎にすでにリリヌスされたNanoCADNC 5.1の無料版のみを䜿甚したずいうこずです。



これには2぀の理由がありたす。それはあらゆる目的で完党に無料であり、2番目の理由は私が非垞に匱いコンピュヌタヌを䜿甚しおいるため、AutoCADが遅くなり、負荷が非垞にかかるこずです。



しかし、この蚘事を曞く前に、「ペン」でオブゞェクトを描画する緎習をし、オブゞェクトの3D衚瀺の仕組みを理解し、最も重芁なこずずしお、デバッグプロセスで10,000回CADを再起動する必芁があったため、NanoCAD 8.5を少し調べたした。



したがっお、䞀芋するず、叀い無料バヌゞョンよりも描画する方が快適であり、叀いNanoCAD 5.1ず同じくらい速く読み蟌たれたす。぀たり、NC 8.5は他のピアよりも数倍速く起動したす-AutoCAD 2017ストップりォッチによる蚈枬。 い぀か䌚瀟が無料版を曎新し、「電子的集倧成」の機胜に関する新しいAPIず新しいチップに移行するこずを期埅するだけです。



最埌に、開発者が利甚できるNanoCADのバヌゞョンで理解しおいるように、3D゜リッドモデリングモゞュヌルが含たれおいたすが、特にナヌザヌが䜜成したオブゞェクトの堎合は、すぐにAPIを理解できたせんでした。 次回は勉匷するかもしれたせん。 それたでの間、「疑䌌3D」オブゞェクトに満足したす。



これには独自の利点もありたす。少し適応した埌のラむブラリは、無料のNanoCAD 5.1で開始され、゜リッドモデリングはたったくありたせん。 しかし、それに぀いおは埌で。



2. NanoCAD 8.5でコヌドを蚘述したす







はい、はい、フォン・ザナック䌯爵はすべおを正しく数えたした たくさんの矊、壁、ドアを最埌たで芋るず、終わりになりたす。 これで、サむンカりントに新しいタスクがありたす-蚘事のビュヌず投祚をカりントしたす。 私はすでにそれをたっすぐに聞くこずができたす「1、1ビュヌ、2-2ビュヌ、3 ...」

通垞どおり、完党なクラスコヌドずdwgファむルの䟋はGitHubにありたす 。



そしお今、それを郚品に分解し始めたす。 既補のアセンブリを適甚したせんでした。プロゞェクトを自分で組み立おるこずができるず思いたす。 前の蚘事で 、NanoCAD 8.1甚にMS Visual Studio 2015のプロゞェクトを䜜成および構成する方法を写真で詳しく説明したした。



したがっお、今回は、Nanocad 8.5でビルドする手順に぀いお簡単に説明したす。



  1. 新しいプロゞェクトを䜜成し、.NET Framework 4プラットフォヌムを遞択し、Cクラスラむブラリをテンプレヌトずしお遞択したす。
  2. Nanocadのx64バヌゞョンおよび1぀ありたすのSDK \ include-x64 \フォルダから、mapibasetypes.dll、mapimgd.dll、imapimgd.dllぞのプロゞェクトリンクを远加したす。 3぀のラむブラリすべおに぀いお、ロヌカルに蚭定されたプロパティをFalseにコピヌするこずを忘れないでください。
  3. たた、MicrosoftのアセンブリリンクSystem.Windows.Forms.dll、System.Drawing.dllを远加したす。
  4. プロゞェクトプロパティの[デバッグ]タブで、起動時のアクションずしお[倖郚プログラムで開く]を遞択し、NC 8.5実行可胜ファむルぞのパスを指定したすC\ Program Files \ Nanosoft \ nanoCAD x64 Plus 8.5 \ nCad.exeがありたす 
  5. ドアず壁にそれぞれDoorPseudo3D.csずWalllPseudo3D.csの2぀のクラスを䜜成したしょう。
  6. アドレスC\ ProgramData \ Nanosoft \ nanoCAD x64 Plus 8.5 \ DataRW倉曎される堎合がありたすに移動し、次の内容のファむルload.configを怜玢たたは䜜成したす


<root> <list> <module path="C:\Users\...\bin\Debug\nanodoor2.dll"/> </list> </root>
      
      





プロゞェクトの名前は圓然ありたすが、プロゞェクトぞのパスは異なる堎合がありたす。



さお、これで開発の準備は完了です。F5を抌すず、NC 8.5が自動的に起動し、アセンブリが盎ちに読み蟌たれたす。開発されたコマンドを入力するだけです。



もう䞀床申し䞊げたすが、私はプログラマヌではないため、コヌドに倚くの欠陥がある可胜性がありたす。オブゞェクトの保存、移動、コピヌ時の倱敗、および単に最適でない゜リュヌションです。 誰かが、コヌドを倧きく耇雑にするこずなく、゚ゎを思い起こさせるこずができるなら、「地面に匓」。



しかし、䜕らかの方法で、このコヌドに基づいお、あなたず私はオブゞェクトを䜜成する方法を少し理解するこずができたす。぀たり、圌は䞻な目暙を達成したす。



もちろん、NanoCAD開発者フォヌラムのAlexander Polkhovskyに倧いに感謝しなければなりたせん。圌はオブゞェクトの移動ず回転に関連する機胜の再定矩ドアの開閉に圹立぀を倧いに助けおくれたした。 そしお、他のすべおのフォヌラム参加者のおかげで、これは珟時点でMultiCAD.NET APIに関する最もアクセスしやすい情報源の1぀であるこずを思い出させおください。



実行がより簡単であるため、壁から始めたす。



たず、名前空間を远加したしょう。



 using System; using System.Collections.Generic; using System.ComponentModel; using Multicad.Runtime; using Multicad.DatabaseServices; using Multicad.Geometry; using Multicad.CustomObjectBase; using Multicad;
      
      





次に、カスタムオブゞェクトクラスを䜜成したす。



 namespace nanowall2 { //change "8b0986c0-4163-42a4-b005-187111b499d7" for your Guid from Assembly. // Be careful GUID for door and wall classes must be different! // Otherwise there will be problems with saving and moving [CustomEntity(typeof(WalllPseudo3D), "8b0986c0-4163-42a4-b005-187111b499d7", "WalllPseudo3D", "WalllPseudo3D Sample Entity")] [Serializable] public class WalllPseudo3D : McCustomBase {
      
      





奜きなクラス名を䜿甚したす私のものを残すこずができたす。䞻なこずは、McCustomBaseから継承するこずです。



すべおのクラス属性が必芁です。正盎に蚀うず、CustomEntity属性パラメヌタヌを完党に理解しおいないので、類掚しお愚かにそれをやり盎したした。



「8b0986c0-4163-42a4-b005-187111b499d7」-私の䟋では、これはGUIDです。.NETドキュメントでその操䜜方法を説明した瞬間に、「クリック」したようです。 簡単に蚀うず、䞀意にするために最埌の桁を眮き換えおアセンブリ蚭定ファむルから取埗したした。 ドアクラスず壁クラスのGUIDが完党に同じである堎合、奇跡が始たりたすコピヌするず壁がドアに倉わり、ファむルを保存した埌にドアの機胜が倱われたす。自分で修正しお、問題が発生しないこずを願っおいたす。



クラスのフィヌルドを定矩したす。



 private Point3d _pnt1 = new Point3d(100, 100, 0); private Point3d _pnt2 = new Point3d(500, 100, 0); private double _h = 2085;
      
      





フィヌルド_pnt1および_pnt12、これらは壁のゞオメトリが構築されるベヌスポむントです壁の長さは基本的に、_ hはデフォルトの壁の高さですオブゞェクトを䜜成した埌、修正できたす。



次に、コヌルチヌムを䜜成し、ドアの抂芁を説明したす。



CommandMethod属性のDrawWall。これは、オブゞェクトを呌び出すためにコマンドラむンに入力するコマンドの名前です。たずえば、機胜を倱うこずなく、DWallによっお短瞮できたす。



 [CommandMethod("DrawWall", CommandFlags.NoCheck | CommandFlags.NoPrefix)] public void DrawWall() { WalllPseudo3D wall = new WalllPseudo3D(); wall.PlaceObject(); }
      
      





チヌムを実装するクラスでは、wallクラスの新しいむンスタンスを䜜成しおいたすこれが行われない堎合、すべおの壁が1぀の「超」壁ずしお認識されるようになりたす。 PlaceObjectメ゜ッドを少し埌で定矩したす。



オブゞェクトをレンダリングする手順を定矩したす。



 public override void OnDraw(GeometryBuilder dc) { dc.Clear();
      
      





私はこの郚分を完党には理解しおいたせんが、どういうわけかAPIにはGeometryBuilderクラスがあり、それに基づいお壁のスカルプトを続けたす。

Dc.Clearは、クラスむンスタンス甚に以前に構築されたすべおのゞオメトリを毎回クリアするようです。



さらにシンプル。



  Point3d pnt1 = _pnt1; Point3d pnt2 = new Point3d(_pnt2.X, pnt1.Y, 0); Point3d pnt3 = new Point3d(pnt2.X, pnt1.Y+150, 0); Point3d pnt4 = new Point3d(pnt1.X , pnt3.Y, 0); // Set the color to ByObject value dc.Color = McDbEntity.ByObject; Vector3d hvec = new Vector3d(0, 0, _h);
      
      





壁のベヌスずトップが構築されるベヌスずなる4぀のベヌスポむントを定矩し、最初ず2番目のポむントはクラスのフィヌルドにリンクされたす。぀たり、埌でそれらを操䜜したす。 壁の長さは、ポむント_pnt1ずpnt2の間の距離に応じお構築されたすが、壁の幅は固定するのが難しく蚭定されおいたせん簡単にするために行われたすが、類掚によっお䜜業ロゞックを簡単に再定矩できたす。



dc.Color-オブゞェクトのブロックプロパティで色を蚭定しおいるようです。



ベクトルhvecは壁の高さです。これをベヌスに远加しお䞊郚を構築したす。



次に、壁の䞋偎ず䞊偎を描きたす。



  dc.DrawPolyline(new Point3d[] { pnt1, pnt2, pnt3, pnt4, _pnt1 }); dc.DrawPolyline(new Point3d[] { _pnt1.Add(hvec), pnt2.Add(hvec), pnt3.Add(hvec), pnt4.Add(hvec), pnt1.Add(hvec)});
      
      





䞋郚ず䞊郚をリブで接続したす。



  dc.DrawLine(pnt1, pnt1.Add(hvec)); dc.DrawLine(pnt2, pnt2.Add(hvec)); dc.DrawLine(pnt3, pnt3.Add(hvec)); dc.DrawLine(pnt4, pnt4.Add(hvec));
      
      





hatch化のための花粉の茪郭を䜜成し、レンガbrick化で塗り぀ぶしたすhatch化の名前はプログラム自䜓で確認できたす。 さらに、ポリラむンのリストをシェヌディングできず、手順を2回繰り返す必芁がありたした。 私は䜕かを考慮しなかったず思いたす。



ハッチングしおいるのは2぀の壁面のみです-䞀番長い堎合は、残りを自分でシェヌディングできたす。



 // Create contours for the front and rear sides and hatch them // In this demo, we hatch only two sides, you can tailor the others yourself List<Polyline3d> c1 = new List<Polyline3d>(); c1.Add(new Polyline3d( new List<Point3d>() { pnt1, pnt1.Add(hvec), pnt2.Add(hvec), pnt2, pnt1, })); dc.DrawGeometry(new Hatch(c1, "BRICK", 0, 20, false, HatchStyle.Normal, PatternType.PreDefined, 30), 1); List<Polyline3d> c2 = new List<Polyline3d>(); c2.Add(new Polyline3d( new List<Point3d>() { pnt4, pnt4.Add(hvec), pnt3.Add(hvec), pnt3, pnt4, })); dc.DrawGeometry(new Hatch(c2, "BRICK", 0, 20, false, HatchStyle.Normal, PatternType.PreDefined, 30), 1); }
      
      





オブゞェクトのカスタムプロパティを定矩したす。私の意芋では、2次元圢匏で描画する方が䟿利で、描画時に壁の高さを蚭定するのは䞍䟿です。壁の高さを描画手順の䞀郚ずしお蚭定できたすが、より簡単な方法でプロパティを远加したすそれを䜿甚しお、描画埌に高さを倉曎したす。



 //Define the custom properties of the object [DisplayName("Height")] [Description("Height of wall")] [Category("Wall options")] public double HWall { get { return _h; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; _h = value; } }
      
      





属性[DisplayName "高さ"]-プロパティりィンドりに衚瀺される名前[説明 "壁の高さ"]によるず、これは説明ですが、衚瀺堎所がわかりたせんでした[カテゎリ "壁オプション"] -ドアの䟋で埌述するように、フィヌルドのカテゎリは、䟿宜䞊フィヌルドをグルヌプ化できたす。

さお、通垞はプロパティが続きたす。Unity3Dでパブリックプロパティを䜜成したこずがある堎合、メカニズムは同様です。゚ディタヌからこの堎合はCADからクラスのフィヌルドに盎接アクセスできたす。



TryModifyは必須のメ゜ッドであり、オブゞェクトのプロパティを倉曎する前に呌び出す必芁があるこずを理解しおいたす。 あず数回圌に䌚いたす。



次に、オブゞェクトを図面に配眮するメ゜ッドを再定矩したす以前はコマンドで呌び出しおいたこずを思い出しおください。



  public override hresult PlaceObject(PlaceFlags lInsertType) { InputJig jig = new InputJig(); // Get the first box point from the jig InputResult res = jig.GetPoint("Select first point:"); if (res.Result != InputResult.ResultCode.Normal) return hresult.e_Fail; _pnt1 = res.Point; // Add the object to the database this.DbEntity.AddToCurrentDocument(); //Exclude the object from snap points jig.ExcludeObject(ID); // Monitoring mouse moving and interactive entity redrawing jig.MouseMove = (s, a) => { TryModify(); _pnt2 = a.Point; this.DbEntity.Update(); }; // Get the second box point from the jig res = jig.GetPoint("Select second point:"); if (res.Result != InputResult.ResultCode.Normal) { this.DbEntity.Erase(); return hresult.e_Fail; } _pnt2 = res.Point; return hresult.s_Ok; }
      
      





このコヌドは、最初の章で説明したNanosoftの䟋からほが完党に借甚されおいたすが、100理解できたせんが、壁の最初のポむントjig.GetPointを入力するコマンドを簡単に呌び出しおから、図面DbEntity。 AddToCurrentDocument。その埌、2番目のポむント_pnt2の入力を劚げないように、バむンディングからオブゞェクトを陀倖したす。



すべおが正垞な堎合、オブゞェクトは図面に配眮され、そうでない堎合たずえば、入力が完了しおいない堎合、オブゞェクトは削陀されたす。



そしお最埌の1぀は、壁のサむズを倉曎するためのハンドルを䜜成したす。



  // Create a grip for the base point of the object public override bool GetGripPoints(GripPointsInfo info) { info.AppendGrip(new McSmartGrip<WalllPseudo3D>(_pnt1, (obj, g, offset) => { obj.TryModify(); obj._pnt1 += offset; })); info.AppendGrip(new McSmartGrip<WalllPseudo3D>(_pnt2, (obj, g, offset) => { obj.TryModify(); obj._pnt2 += offset; })); return true; } } // TODO: There are many shortcomings in this code. // Including failures when working with copying, moving objects and saving files, you can improve it if you want. }
      
      





私が理解しおいるように、䞊蚘の䟋のコヌドは、ハンドル郚分NC 8.Xの堎合で叀くなっおいるため、この䟋のコヌドに泚目する方が良いでしょう。



もちろん、私のコヌドは理想ずはほど遠いこずを譊告したすので、適切で適切な線集に満足したす。



ドアを考えおみたしょう。 始たりは䌌おいたす。



 using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using Multicad.Runtime; using Multicad.DatabaseServices; using Multicad.Geometry; using Multicad.CustomObjectBase; using Multicad; namespace nanodoor2 { //change "8b0986c0-4163-42a4-b005-187111b499d7" for your Guid from Assembly. // Be careful GUID for door and wall classes must be different! // Otherwise there will be problems with saving and moving [CustomEntity(typeof(DoorPseudo3D), "8b0986c0-4163-42a4-b005-187111b499d9", "DoorPseudo3D", "DoorPseudo3D Sample Entity")] [Serializable] public class DoorPseudo3D : McCustomBase { // First and second vertices of the box private Point3d _pnt1 = new Point3d(0, 0, 0); private double _h = 2085; private Vector3d _vecStraightDirection = new Vector3d(1, 0, 0); private Vector3d _vecDirectionClosed = new Vector3d(1, 0, 0); public enum status { closed , middle, open }; private status _dStatus = status.closed; [CommandMethod("DrawDoor", CommandFlags.NoCheck | CommandFlags.NoPrefix)] public void DrawDoor() { DoorPseudo3D door = new DoorPseudo3D(); door.PlaceObject(); }
      
      





ドアが開いおいるか閉じおいるかを担圓するフィヌルドが远加されおいない限り、2぀のベクトル_vecStraightDirectionが衚瀺されたす-珟圚のドアの回転を担圓し、_vecDirectionClosed-ドアの回転に関するデヌタを閉じた状態で保存したす これは埌ですべお䟿利になりたす。



しかし、予想されるように、ドアのゞオメトリには盎接、小さな倉曎がありたす。



 public override void OnDraw(GeometryBuilder dc) { dc.Clear(); // Define the basic points for drawing Point3d pnt1 = new Point3d(0, 0, 0); Point3d pnt2 = new Point3d(pnt1.X + 984, pnt1.Y, 0); Point3d pnt3 = new Point3d(pnt2.X + 0, pnt1.Y+50, 0); Point3d pnt4 = new Point3d(pnt1.X , pnt3.Y, 0); // Set the color to ByObject value dc.Color = McDbEntity.ByObject; Vector3d hvec = new Vector3d(0, 0, _h); // Draw the upper and lower sides dc.DrawPolyline(new Point3d[] { pnt1, pnt2, pnt3, pnt4, pnt1 }); dc.DrawPolyline(new Point3d[] { pnt1.Add(hvec), pnt2.Add(hvec), pnt3.Add(hvec), pnt4.Add(hvec), pnt1.Add(hvec)}); // Draw the edges dc.DrawLine(pnt1, pnt1.Add(hvec)); dc.DrawLine(pnt2, pnt2.Add(hvec)); dc.DrawLine(pnt3, pnt3.Add(hvec)); dc.DrawLine(pnt4, pnt4.Add(hvec)); // Drawing a Door Handle dc.DrawLine(pnt2.Add(new Vector3d( - 190, -0, _h*0.45)), pnt2.Add(new Vector3d(-100, 0, _h * 0.45))); dc.DrawLine(pnt3.Add(new Vector3d(-190, 0, _h * 0.45)), pnt3.Add(new Vector3d(-100, 0, _h * 0.45))); // Create contours for the front and rear sides and hatch them // In this demo, we hatch only two sides, you can tailor the others yourself List<Polyline3d> c1 = new List<Polyline3d>(); c1.Add(new Polyline3d( new List<Point3d>() { pnt1, pnt1.Add(hvec), pnt2.Add(hvec), pnt2, pnt1, })); List<Polyline3d> c2 = new List<Polyline3d>(); c2.Add(new Polyline3d( new List<Point3d>() { pnt4, pnt4.Add(hvec), pnt3.Add(hvec), pnt3, pnt4, })); dc.DrawGeometry(new Hatch(c1, "JIS_WOOD", 0, 170, false, HatchStyle.Normal, PatternType.PreDefined, 500), 1); dc.DrawGeometry(new Hatch(c2, "JIS_WOOD", 0, 170, false, HatchStyle.Normal, PatternType.PreDefined, 500), 1); }
      
      





最初に、ドアを1぀のポむントで構築するこずに泚意しおください。぀たり、ドアの幅ず高さのサむズは厳密に固定されおいたす壁ずは異なるように。 たた、「//ドアハンドルの描画」セクションを远加したした。条件付きハンドルを瀺す2行がありたす。たた、ハッチングのタむプをJIS_WOODに眮き換えたした。



ただし、2番目のハンドルは必芁ないため、PlaceObjectメ゜ッドは単玔化されおいたす。



  public override hresult PlaceObject(PlaceFlags lInsertType) { InputJig jig = new InputJig(); // Get the first box point from the jig InputResult res = jig.GetPoint("Select first point:"); if (res.Result != InputResult.ResultCode.Normal) return hresult.e_Fail; _pnt1 = res.Point; // Add the object to the database DbEntity.AddToCurrentDocument(); return hresult.s_Ok; }
      
      





次に、壁のクラスに関する完党な新芏性がありたす。 蚘事の冒頭でアレクサンダヌに感謝した。



以䞋では、メ゜ッドを再定矩したす。このメ゜ッドは、ドアの倉換マトリックス移動および回転の䜜成に䜕らかの圢で䞍可解な責任を負いたす。



 /// <summary> /// Method for changing the object's SC (the graph is built at the origin of coordinates). /// </ summary> /// <param name = "tfm"> The matrix for changing the position of the object. </ param> /// <returns> True - if the matrix is passed, False - if not. </ returns> public override bool GetECS(out Matrix3d tfm) { // Create a matrix that transforms the object. // The object is drawn in coordinates(0.0), then it is transformed with the help of this matrix. tfm = Matrix3d.Displacement(this._pnt1.GetAsVector()) * Matrix3d.Rotation (-this._vecStraightDirection.GetAngleTo(Vector3d.XAxis, Vector3d.ZAxis), Vector3d.ZAxis, Point3d.Origin); return true; }
      
      





この方法の操䜜は完党には理解しおいたせんが、各動きでドアが基点ず回転ベクトルに応じお倉圢するため、最終的に図面でドアを開閉するこずができたす。



次に、オブゞェクトの倉換䞭に発生するず思われるむベントを再定矩したす。



  public override void OnTransform(Matrix3d tfm) { // To be able to cancel(Undo) McUndoPoint undo = new McUndoPoint(); undo.Start(); // Get the coordinates of the base point and the rotation vector this.TryModify(); this._pnt1 = this._pnt1.TransformBy(tfm); this.TryModify(); this._vecStraightDirection = this._vecStraightDirection.TransformBy(tfm); // We move the door only when it is closed if not - undo if (_dStatus == status.closed) _vecDirectionClosed = _vecStraightDirection; else { MessageBox.Show("Please transform only closed door"); undo.Undo(); } undo.Stop(); }
      
      





たず、開発にずらわれないために、いく぀かのポむント、特に私にずっお難しい゜リュヌションを簡略化したした。 これらの単玔化の1぀は、ドアの操䜜に関する制限です。



ドアは、閉じたずきにのみ移動、回転、コピヌ、および倉曎できたすデフォルトで蚭定されおいたす。



これを機胜させるために、取り消しオブゞェクトを䜜成し、倉曎をコミットするための開始点をマヌクしたす。



次に、すべおが正垞であれば、倉換埌の状態をポむント_pnt1ずベクトル._vecStraightDirectionに枡したす。



その埌、状態のチェックがあり、ドアが閉じられおいる堎合、倉曎が適甚され、さらに閉じたドアの䜍眮に関するデヌタを栌玍するベクトルに入力されたす。

ドアが開かれたたたは半開き堎合、゚ラヌメッセヌゞが衚瀺され、すべおの倉曎がキャンセルされたす。



ドアの高さフィヌルドは壁に䌌おいたす。



 //Define the custom properties of the object [DisplayName("Height")] [Description("Height of door")] [Category("Door options")] public double HDoor { get { return _h; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; _h = value; } }
      
      





しかし、次のフィヌルドは新しいです



  [DisplayName("Door status")] [Description("Door may be: closed, middle, open")] [Category("Door options")] public status Stat { get { return _dStatus; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; // Change the rotation vector for each of the door states switch (value) { case status.closed: _vecStraightDirection = _vecDirectionClosed; break; case status.middle: _vecStraightDirection = _vecDirectionClosed.Add(_vecDirectionClosed.GetPerpendicularVector().Negate() * 0.575) ; break; case status.open: _vecStraightDirection = _vecDirectionClosed.GetPerpendicularVector()*-1; break; default: _vecStraightDirection = _vecDirectionClosed; break; } _dStatus = value; } }
      
      





ドアの状態を担圓しおいるのは、プロパティりィンドりにドロップダりンリストが衚瀺されるこずです。倀は、closed、middle、open1察1、クラスの先頭の列挙の定矩ずしおです。



各倀を遞択するず、ドアの回転に関䞎するベクトルが最終的に倉化したす。



閉じられるず、以前に保存された状態_vecDirectionClosedに蚭定されたす。



半開状態では、結果のベクトルが取埗されたす。これにより、ドアが玄30床回転し、GOSTによる指定のようになりたす。



開いおいるずきは、負の倀を䜿甚しお閉じた状態ベクトルに察する垂盎線を取埗したすその結果、デフォルトでドアが開きたす。



デフォルトのケヌスはたったく必芁ないず思いたすが、私は去りたした。



さお、最埌は操䜜甚のハンドルです。



 // Create a grip for the base point of the object public override bool GetGripPoints(GripPointsInfo info) { info.AppendGrip(new McSmartGrip<DoorPseudo3D>(_pnt1, (obj, g, offset) => { obj.TryModify(); obj._pnt1 += offset; })); return true; } // TODO: There are many shortcomings in this code. // Including failures when working with copying, moving objects and saving files, you can improve it if you want. }
      
      





すべおドラッグできたす。 時々、できる限り䞡方のオブゞェクトにペンを持っおいたすが、それをデバッグする力はもはやありたせん蚘事を早く終わらせるず思っおいたしたが、すでに3日間完党に殺しおいたした。



したがっお、F5キヌを抌し、DRAWWALLおよびDRAWDOORコマンドを䜿甚しおドアず壁を挿入したす。

その結果、図にあるものが埗られたす。 その䞊で、私はあなたに4぀の異なる角床から図曞通の仕事を瀺したす。 残念ながら矊は平らで、私はそれらを手で描いた。 さお、壁のあるドアは、GitHubの.dwgファむルの最新バヌゞョンのドアずは少し異なり、2、3の倉曎を加えただけで、スクリヌンショットを撮り盎すのが面倒でした。



NETLOADコマンドを䜿甚しおラむブラリを手動でロヌドする堎合は、オブゞェクトでファむルを開く前にラむブラリをロヌドする必芁があるこずを忘れないでください。そうしないず、プロキシオブゞェクトずしお認識されたす。



Nanocadを初めお䜿甚する堎合は、次のようにオブゞェクトの3次元ビュヌを取埗するのが䟿利であるこずを思い出しおください。view-> orbit-> dependent orbitに戻り、2次元ビュヌを戻すには、view-> views andprojects-> view蚈画->珟圚のUCS









3.コヌドを無料のNanoCAD 5.1に適応させようずしおいたす。







前回の蚘事では、なんらかの理由で、フェむスペむンティングチヌムは私のために働いおいたせんでしたが、今回はコヌドを適合させ、わずかな制限でオブゞェクトをNanoCAD 5.1の無料バヌゞョンで起動したした。



たず、環境の蚭定方法に぀いお簡単に説明したすが、ほずんど違いはありたせん。



したがっお、ここでも、Nanocad 5.1でのビルド手順に぀いお簡単に説明したす。



  1. 新しいプロゞェクトを䜜成し、.NET Framework 3.5を遞択し、テンプレヌトずしおCクラスラむブラリを遞択したす。
  2. Nanocadのx32バヌゞョンおよび5.1のみの堎合、SDK \ include \フォルダヌからmapimgdぞのリンクをプロゞェクトに远加したす。 ロヌカルに蚭定されたプロパティを必ずFalseにコピヌしおください。
  3. たた、MicrosoftのアセンブリリンクSystem.Windows.Forms.dll、System.Drawing.dllを远加したす。
  4. プロゞェクトプロパティの[デバッグ]タブで、起動時のアクションずしお[倖郚プログラムで開く]を遞択し、NC 5.1実行可胜ファむルぞのパスを指定したすC\ Program Filesx86\ Nanosoft \ nanoCAD 5.1 \ nCadがありたす。 exe
  5. 「アセンブリ」セクションのヒヌプの前でさえ、最終プラットフォヌムであるx86をむンストヌルしたした。
  6. ドアず壁にそれぞれDoorPseudo3D_nc51.csずWalllPseudo3D_nc51.csの2぀のクラスを䜜成しおみたしょう。
  7. C\ ProgramData \ Nanosoft \ nanoCAD 5.1 \ DataRWこれはあなたずは異なる堎合がありたすを通り、次の内容のload.configファむルを芋぀けるか䜜成したす



 <root> <list> <module path="C:\Users\...\bin\Debug\ nanodoor2_51.dll"/> </list> </root>
      
      





ファむルぞの独自のパスがありたす。



コヌドに根本的な違いはないため、䞡方のクラスをネタバレの䞋に隠し、違いのみを説明したす。



だから壁



壁の完党なコヌド
 //Use Microsoft .NET Framework 3.5 and old version of MultiCad.NET (for NC 5.1) //Class for demonstrating the capabilities of MultiCad.NET //Assembly for the Nanocad 5.1 //Link mapimgd from Nanocad SDK //Link System.Windows.Forms and System.Drawing //The commands: draws a pseudo 3D wall. //This code in the part of non-infringing rights Nanosoft can be used and distributed in any accessible ways. //For the consequences of the code application, the developer is not responsible. //More detailed - https://habrahabr.ru/post/342680/ using System; using System.ComponentModel; using Multicad.Runtime; using Multicad.DatabaseServices; using Multicad.Geometry; using Multicad.CustomObjectBase; using Multicad; namespace nanowall2 { //change "8b0986c0-4163-42a4-b005-187111b499d7" for your Guid from Assembly. // Be careful GUID for door and wall classes must be different! // Otherwise there will be problems with saving and moving [CustomEntity(typeof(WalllPseudo3D_nc51), "b4edac1f-7978-483f-91b1-10503d20735a", "WalllPseudo3D_nc51", "WalllPseudo3D_nc51 Sample Entity")] [Serializable] public class WalllPseudo3D_nc51 : McCustomBase { // First and second vertices of the box private Point3d _pnt1 = new Point3d(100, 100, 0); private Point3d _pnt2 = new Point3d(500, 100, 0); private double _h = 2085; private double _scale = 1000; [CommandMethod("DrawWall", CommandFlags.NoCheck | CommandFlags.NoPrefix)] public void DrawWall() { WalllPseudo3D_nc51 wall = new WalllPseudo3D_nc51(); wall.PlaceObject(); } public override void OnDraw(GeometryBuilder dc) { dc.Clear(); // Define the basic points for drawing Point3d pnt1 = _pnt1; Point3d pnt2 = new Point3d(_pnt2.X, pnt1.Y, 0); Point3d pnt3 = new Point3d(pnt2.X, pnt1.Y+(150 * _scale), 0); Point3d pnt4 = new Point3d(pnt1.X , pnt3.Y, 0); // Set the color to ByObject value dc.Color = McDbEntity.ByObject; Vector3d hvec = new Vector3d(0, 0, _h * _scale); // Draw the upper and lower sidestes dc.DrawPolyline(new Point3d[] { pnt1, pnt2, pnt3, pnt4, pnt1 }); dc.DrawPolyline(new Point3d[] { _pnt1.Add(hvec), pnt2.Add(hvec), pnt3.Add(hvec), pnt4.Add(hvec), pnt1.Add(hvec)}); // Draw the edges dc.DrawLine(pnt1, pnt1.Add(hvec)); dc.DrawLine(pnt2, pnt2.Add(hvec)); dc.DrawLine(pnt3, pnt3.Add(hvec)); dc.DrawLine(pnt4, pnt4.Add(hvec)); } //Define the custom properties of the object [DisplayName("WScale")] [Description("Wall Scale")] [Category("Wall options")] public double WScale { get { return _scale; } set { if (!TryModify()) return; _scale = value; } } [DisplayName("Height")] [Description("Height of wall")] [Category("Wall options")] public double HWall { get { return _h; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; _h = value; } } public override hresult PlaceObject(PlaceFlags lInsertType) { InputJig jig = new InputJig(); // Get the first box point from the jig InputResult res = jig.GetPoint("Select first point:"); if (res.Result != InputResult.ResultCode.Normal) return hresult.e_Fail; _pnt1 = res.Point; // Add the object to the database this.DbEntity.AddToCurrentDocument(); //Exclude the object from snap points jig.ExcludeObject(ID); // Monitoring mouse moving and interactive entity redrawing jig.MouseMove = (s, a) => { TryModify(); _pnt2 = a.Point; this.DbEntity.Update(); }; // Get the second box point from the jig res = jig.GetPoint("Select second point:"); if (res.Result != InputResult.ResultCode.Normal) { this.DbEntity.Erase(); return hresult.e_Fail; } _pnt2 = res.Point; return hresult.s_Ok; } // Create a grip for the base point of the object public override bool GetGripPoints(GripPointsInfo info) { info.AppendGrip(new McSmartGrip<WalllPseudo3D_nc51>(_pnt1, (obj, g, offset) => { obj.TryModify(); obj._pnt1 += offset; })); info.AppendGrip(new McSmartGrip<WalllPseudo3D_nc51>(_pnt2, (obj, g, offset) => { obj.TryModify(); obj._pnt2 += offset; })); return true; } } // TODO: There are many shortcomings in this code. // Including failures when working with copying, moving objects and saving files, you can improve it if you want. }
      
      





違いは䜕ですかたず、空の図面にオブゞェクトを挿入しようずしたずきに、Nanocadがそれをスケヌリングしお壁やドアが芋えないようにし、スケヌル付きのフィヌルドを远加したした。



壁の堎合、壁の厚さを倉曎し、ドアの堎合、厚さず長さを倉曎したす。



したがっお、目的の座暙には、開いおいるプロパティがあるスケヌルが乗算されたす。



MultiCAD.NET APIの叀いバヌゞョンの2番目の違いは、ハッチングを操䜜するためのクラスがないこずです。通垞の.NETのAPIを介しお実装できるず想定できたすが、そうではありたせん。



今ドア



ドアの完党なコヌド
 //Use Microsoft .NET Framework 3.5 and old version of MultiCad.NET (for NC 5.1) //Class for demonstrating the capabilities of MultiCad.NET //Assembly for the Nanocad 5.1 //Link mapimgd from Nanocad SDK //Link System.Windows.Forms and System.Drawing //The commands: draws a pseudo 3D door. //This code in the part of non-infringing rights Nanosoft can be used and distributed in any accessible ways. //For the consequences of the code application, the developer is not responsible. //More detailed - https://habrahabr.ru/post/342680/ // PS A big thanks to Alexander Vologodsky for help in developing a method for pivoting object. using System; using System.ComponentModel; using System.Windows.Forms; using Multicad.Runtime; using Multicad.DatabaseServices; using Multicad.Geometry; using Multicad.CustomObjectBase; using Multicad; namespace nanodoor2 { //change "8b0986c0-4163-42a4-b005-187111b499d7" for your Guid from Assembly. // Be careful GUID for door and wall classes must be different! // Otherwise there will be problems with saving and moving [CustomEntity(typeof(DoorPseudo3D_nc51), "b4edac1f-7978-483f-91b1-10503d20735b", "DoorPseudo3D_nc51", "DoorPseudo3D_nc51 Sample Entity")] [Serializable] public class DoorPseudo3D_nc51 : McCustomBase { // First and second vertices of the box private Point3d _pnt1 = new Point3d(0, 0, 0); private double _scale = 1000; private double _h = 2085; private Vector3d _vecStraightDirection = new Vector3d(1, 0, 0); private Vector3d _vecDirectionClosed = new Vector3d(1, 0, 0); public enum status { closed , middle, open }; private status _dStatus = status.closed; [CommandMethod("DrawDoor", CommandFlags.NoCheck | CommandFlags.NoPrefix)] public void DrawDoor() { DoorPseudo3D_nc51 door = new DoorPseudo3D_nc51(); door.PlaceObject(); } public override void OnDraw(GeometryBuilder dc) { dc.Clear(); // Define the basic points for drawing Point3d pnt1 = new Point3d(0, 0, 0); Point3d pnt2 = new Point3d(pnt1.X + (984 * _scale), pnt1.Y, 0); Point3d pnt3 = new Point3d(pnt2.X + 0, pnt1.Y+(50 * _scale), 0); Point3d pnt4 = new Point3d(pnt1.X , pnt3.Y, 0) ; // Set the color to ByObject value dc.Color = McDbEntity.ByObject; Vector3d hvec = new Vector3d(0, 0, _h * _scale) ; // Draw the upper and lower sides dc.DrawPolyline(new Point3d[] { pnt1, pnt2, pnt3, pnt4, pnt1 }); dc.DrawPolyline(new Point3d[] { pnt1.Add(hvec), pnt2.Add(hvec), pnt3.Add(hvec), pnt4.Add(hvec), pnt1.Add(hvec)}); // Draw the edges dc.DrawLine(pnt1, pnt1.Add(hvec)); dc.DrawLine(pnt2, pnt2.Add(hvec)); dc.DrawLine(pnt3, pnt3.Add(hvec)); dc.DrawLine(pnt4, pnt4.Add(hvec)); // Drawing a Door Handle dc.DrawLine(pnt2.Add(new Vector3d( -190 * _scale, -0, _h*0.45 * _scale)), pnt2.Add(new Vector3d(-100 * _scale, 0, _h * 0.45 * _scale))); dc.DrawLine(pnt3.Add(new Vector3d(-190 * _scale, 0, _h * 0.45 * _scale)), pnt3.Add(new Vector3d(-100 * _scale, 0, _h * 0.45 * _scale))); } public override hresult PlaceObject(PlaceFlags lInsertType) { InputJig jig = new InputJig(); // Get the first box point from the jig InputResult res = jig.GetPoint("Select first point:"); if (res.Result != InputResult.ResultCode.Normal) return hresult.e_Fail; _pnt1 = res.Point; // Add the object to the database DbEntity.AddToCurrentDocument(); return hresult.s_Ok; } /// <summary> /// Method for changing the object's SC (the graph is built at the origin of coordinates). /// </ summary> /// <param name = "tfm"> The matrix for changing the position of the object. </ param> /// <returns> True - if the matrix is passed, False - if not. </ returns> public override bool GetECS(out Matrix3d tfm) { // Create a matrix that transforms the object. // The object is drawn in coordinates(0.0), then it is transformed with the help of this matrix. tfm = Matrix3d.Displacement(this._pnt1.GetAsVector()) * Matrix3d.Rotation (-this._vecStraightDirection.GetAngleTo(Vector3d.XAxis, Vector3d.ZAxis), Vector3d.ZAxis, Point3d.Origin); return true; } public override void OnTransform(Matrix3d tfm) { // To be able to cancel(Undo) McUndoPoint undo = new McUndoPoint(); undo.Start(); // Get the coordinates of the base point and the rotation vector this.TryModify(); this._pnt1 = this._pnt1.TransformBy(tfm); this.TryModify(); this._vecStraightDirection = this._vecStraightDirection.TransformBy(tfm); // We move the door only when it is closed if not - undo if (_dStatus == status.closed) _vecDirectionClosed = _vecStraightDirection; else { MessageBox.Show("Please transform only closed door (when its status = 0)"); undo.Undo(); } undo.Stop(); } //Define the custom properties of the object [DisplayName("Height")] [Description("Height of door")] [Category("Door options")] public double HDoor { get { return _h; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; _h = value; } } [DisplayName("DScale")] [Description("Door Scale")] [Category("Door options")] public double DScale { get { return _scale; } set { if (!TryModify()) return; _scale = value; } } [DisplayName("Door status")] [Description("0-closed, 1-midle, 2-open")] [Category("Door options")] public status Stat { get { return _dStatus; } set { //Save Undo state and set the object status to "Changed" if (!TryModify()) return; // Change the rotation vector for each of the door states switch (value) { case status.closed: _vecStraightDirection = _vecDirectionClosed; break; case status.middle: _vecStraightDirection = _vecDirectionClosed.Add(_vecDirectionClosed.GetPerpendicularVector().Negate() * 0.575) ; break; case status.open: _vecStraightDirection = _vecDirectionClosed.GetPerpendicularVector()*-1; break; default: break; } _dStatus = value; } } // Create a grip for the base point of the object public override bool GetGripPoints(GripPointsInfo info) { info.AppendGrip(new McSmartGrip<DoorPseudo3D_nc51>(_pnt1, (obj, g, offset) => { obj.TryModify(); obj._pnt1 += offset; })); return true; } } // TODO: There are many shortcomings in this code. // Including failures when working with copying, moving objects and saving files, you can improve it if you want. }
      
      





繰り返したすが、ほずんどすべおが同じです。唯䞀のこずです。バヌゞョン5.1では、フィヌルドは列挙を異なる方法で凊理し、closed / openの代わりにオブゞェクトのプロパティりィンドりに列挙倀が衚瀺されたす0、1、2はあたり明確ではないため、譊告を少し倉曎したした゚ラヌ。たた、ドアにはハッチングがなく、スケヌルに远加のプロパティがありたす必芁に応じお、NC 8.5のクラスにも実装できたす。



次のようになりたす。









4. MultiKukish結論









, , . MultiCAD.NET API AutoCAD ZWCAD , .



, . , , AutoCAD 2017, — «MultiCAD_AC_ZC_Enabler_2209_RU.zip» ( 1.5 ), AutoCAD 2016. .



今回、別のオプションを詊しおみるこずにし、ZWCAD + 2015の詊甚版をダりンロヌドしたした。これもこのレむダヌがサポヌトする最新バヌゞョンです。私は知りたせん、倚分私は「握手」かもしれたせんが、このラむブラリも前の蚘事のラむブラリもZWCADで急䞊昇したせんでした。したがっお、誰かが走っお、スクリヌンショットを共有しおくれたら、ありがたいです。



残りに぀いおは、このAPIを台無しにすればするほど、より深く関わり合い、奜きになり始めたす。APIが改善されおいるこず、APIクラスの䞀郚のメンバヌは既にロシア語で正気な説明を持っおいるこず、そしおAPI自䜓がより自絊自足になっおいるこずがわかりたす。



DWG 2018のサポヌトを備えたNanoCAD 9たたはそれが呌ばれるものがリリヌスされるず、さらに良くなるず思いたす特に、開発者がフォヌラムで玄束したように、新しい無料のNanocadが続く堎合。



だから、Nanocad開発者フォヌラムのすべおの参加者に-助けおくれお、開発者に-NC 8.5を投皿しおくれおありがずう、そしおすべおの読者に-最埌たで蚘事をマスタヌしおくれおありがずう。



PS最初は、タむトルの蚘事は別の写真になっおいるはずでしたが、「氷ではない」ず刀断し、最終的に政治的に正しいカヌミットずグロヌバヌに眮き換えたしたずころで、写真の䞀郚は私が芋぀けたビデオに぀ながりたす。しかし、私は蚘事の䞋で元の画像を隠すこずにしたした...



...ネタバレ





All Articles