VDF常見問題整理(十二):復雜自定義對象的入門指南
VectorDraw Developer Framework(VDF)是一個用于應用程序可視化的圖形引擎庫。有了VDF提供的功能,您可以輕松地創(chuàng)建、編輯、管理、輸出、輸入和打印2D和3D圖形文件。
VectorDraw Developer Framework試用版下載
問:
能否提供復雜自定義對象的入門指南?
答:
我們將嘗試為您提供有關(guān)自定義對象的詳細說明以及您應該如何嘗試實現(xiàn)此類實現(xiàn)。我們的指南是針對C#中的.NET項目,主要是我們使用的編程語言。
首先,您必須創(chuàng)建一個包含2個項目的解決方案,就像我們的樣本中實現(xiàn)的那樣。一個項目將是一個非常簡單的控件形式(可滾動,框架無關(guān)緊要),最好是vdFramedControl,因為具有屬性列表和命令行的vdFramedControl將為您提供一個很好的調(diào)試項目。在任何情況下,您為vdFramedControl編寫的代碼對于vdScrollableControl都是相同的。所以我們有一個帶有vdFramedControl的項目和一些用于測試自定義對象的按鈕。
第二個項目將是一個DLL,它將包含您的自定義對象(與我們的示例中的完全相同)。具有該表單的其他項目需要此項目的引用,以便您可以使用自定義對象進行測試。
完成自定義對象的實現(xiàn)后,可以在主應用程序中引用dll而不會出現(xiàn)問題,您可以使用此解決方案來測試和調(diào)試自定義對象。
現(xiàn)在,在這些初始設(shè)置之后,我們開始使用自定義對象。
首先,您需要為自定義對象提供一些屬性,這些屬性與它的幾何有關(guān),以及如何繪制此對象。再找一個vdFigure對象并定義這樣的對象。
public class vdBox :vdFigure , IvdProxyFigure
作為vdFigure的vdBox,已經(jīng)有一個pencolor,一個圖層,一個penstyle等,接下來將可以用于繪制對象(稍后將在draw方法中解釋)。
這樣的自定義對象需要IvdProxyFigure,為對象添加一個空構(gòu)造函數(shù),還有一個傳遞Document的幫助構(gòu)造函數(shù)。您還可以添加一個傳遞一些基本屬性的構(gòu)造函數(shù),但這可以在我們完成屬性后添加。
/// Empty constructor of the object always required for creating a custom object. public vdBox() { } /// Helpfull constructor that also initializes the object with Document's defaults. /// The Document that the object will use.public vdBox(vdDocument Doc) { SetUnRegisterDocument(Doc); setDocumentDefaults(); }
我們還將為對象添加一些屬性:
-
我們需要一個VertexList(點集合)來保持小矩形的點。
-
您還需要一個主矩形的中心點(gPoint)。
-
main的MainWidth / MainHeight(雙精度值)。
-
小矩形的LittleWidth / LittleHeight(雙值)。
-
您應該添加所有自定義對象示例中所述的屬性,如下所示。
private gPoint mInsertionPoint = null; /// /// The Insertion Point of the vdBox object. /// [EditorAttribute(typeof(VectorDraw.Professional.PropertyList.vdPickPointDialog),typeof(System.Drawing.Design.UITypeEditor))] [GlobalizedCategory("Geometry")] [GlobalizedDisplayName("InsertionPoint")] [GlobalizedDescription("Get/Set the Insertion Point of the vdTable object in World Coordinative System.")] public gPoint InsertionPoint { get { if (mInsertionPoint == null)mInsertionPoint = new gPoint(); return mInsertionPoint; } set { if (InsertionPoint.AreEqual(value)) return; AddHistory("InsertionPoint", value); //For the Undo/Redo implementation of VectorDraw mInsertionPoint.CopyFrom(value); } }
Globalized ...在屬性列表中用于顯示按鈕的描述,屬性的名稱以及它的類別。如果您不打算在應用程序中使用我們的屬性列表,則不必添加這些內(nèi)容。
現(xiàn)在我們已經(jīng)完成了屬性的設(shè)置,接下來需要重寫Draw方法。
public override VectorDraw.Render.vdRender.DrawStatus Draw(VectorDraw.Render.vdRender render) { vdRender.DrawStatus doDraw = base.Draw(render); if (doDraw == vdRender.DrawStatus.Successed) { //Draw stuff here } AfterDraw(render); return doDraw; }
如果調(diào)用base.Draw,那么必須始終調(diào)用AfterDraw,小心任何try {} catch語句。
這些調(diào)用基本上會初始化繪制的一些功能,并設(shè)置基本顏色用vdFigure的pencolor等繪制,因此,如果我們在draw方法中繪制一條線并且該對象的pencolor為紅色,那么該線將為紅色。
您可以使用如下所示的渲染的PushPenStyle方法和PopPenStyle(總是在后面)來更改顏色。
render.PushPenstyle(BackGroundColor, false); render.DrawSolidPolygon(this, mSegments, vdRender.PolygonType.Simple); render.PopPenstyle();
現(xiàn)在需要繪制主矩形,但事先解釋一下ECS矩陣,您可以在我們的自定義對象和VDF對象中看到ECSMatrix。在用戶坐標系中繪制對象要容易得多,比方說0,0,0然后使用ECSMatrix轉(zhuǎn)換繪制對象。例如,我們將通過將中心點設(shè)置為0,0,0繪制主矩形,然后使用ECSMatrix上的InsertionPoint將對象轉(zhuǎn)換到那里。
double wid = 3.0; //(this Value will Be property among others) render.PushMatrix(ECSMatrix); gPoints pts = new gPoints(); pts.Add(new gPoint (-wid,-wid,0.0)); pts.Add(new gPoint(wid, -wid, 0.0)); pts.Add(new gPoint(wid, wid, 0.0)); pts.Add(new gPoint(-wid, wid, 0.0)); pts.Add(new gPoint (-wid,-wid,0.0)); render.DrawPLine(this, pts); render.PopMatrix();
這將繪制一個矩形。現(xiàn)在我們覆蓋ECSMatrix并設(shè)置InsertionPoint。
public override Matrix ECSMatrix { get { if (mEcsMatrix != null) return mEcsMatrix; mEcsMatrix = new Matrix(); mEcsMatrix.TranslateMatrix(InsertionPoint.x, InsertionPoint.y, InsertionPoint.z); return mEcsMatrix; } }
對于EcsMatrix,您可以添加屬性,如ExtrusionVector,Rotation,Scale等查看我們的樣品。在我們看到繪制對象之前需要實現(xiàn)的最后一件事是BoundingBox。
public override Box BoundingBox { get { if (mBoundBox.IsEmpty) { mBoundBox = new Box(); mBoundBox.AddPoint(new gPoint()); mBoundBox.AddWidth(3.0); mBoundBox.TransformBy(ECSMatrix); } return mBoundBox; } }
必須根據(jù)對象的各種屬性計算BoundingBox,它是一個始終包含對象的框。
現(xiàn)在,在初始編碼之后,我們可以將自定義對象添加到模型(文檔)的實體中并查看它。轉(zhuǎn)到用于調(diào)試的Sample應用程序,在添加所需的引用之后,讓我們將此自定義對象添加到Document。
Add the code to a simple test button : vdBox box = new vdBox(vdFramedControl1.BaseControl.ActiveDocument); box.InsertionPoint = new gPoint(10, 10, 0); vdFramedControl1.BaseControl.ActiveDocument.Model.Entities.AddItem(box); vdFramedControl1.BaseControl.ActiveDocument.Redraw(true);
注意:矩形以10,10繪制,寬度為3.0。
這個矩形已經(jīng)可以選擇,您可以看到它的屬性-framedControl的propertiesList,并且還可以更改它們以查看它們?nèi)绾闻c對象交互。
在我們完成對象的繪制和它的繪制屬性之后,我們將不得不實現(xiàn)一些基本的覆蓋方法,這些方法是幾種vdraw方法所必需的。
首先,我們添加Serialize / DeSerialize覆蓋方法,以便將對象保存在vdml / vdcl中(實現(xiàn)保存了對象的所有屬性,可以在我們的示例中看到)。
每次需要重繪項目時都會調(diào)用Update覆蓋。在這里,您可以初始化一些與對象繪制有關(guān)的私有數(shù)據(jù)。如果更改對象或任何其他屬性的顏色,則將調(diào)用此方法。例如,如果您對對象的繪制進行了必要的硬計算(并且需要時間來計算),則可以將結(jié)果保存在私有結(jié)構(gòu)中。然后在draw方法中,如果結(jié)果的值為null,則僅執(zhí)行此計算,并將此value = null設(shè)置為update方法。這樣,如果對象未更改,則除非需要更新對象,否則不會調(diào)用計算。如果更改基本屬性,則只在應用程序中的自定義對象外調(diào)用update。
移動或縮放對象時調(diào)用Transformby覆蓋。例如,您可以調(diào)用CmdMove命令并選擇對象。如果您實現(xiàn)TransformBy,那么您可以通過在此方法中更改它的InsertionPoint來移動您的對象。GetGripPoints是一種方法,您可以在其中添加對象所需的夾點。將對象添加到Document的實體時,將調(diào)用OnDocumentSelected override。你可以在這里為對象做初始化的東西。
克隆對象需要MatchProperties覆蓋。例如,當您調(diào)用move命令然后創(chuàng)建并繪制克隆對象以便您看到對象移動時,VectorDraw將使用克隆。了解如何使用示例中自定義對象的屬性實現(xiàn)此方法。
在爆炸自定義對象時調(diào)用爆炸方法,你應該在這里返回VectorDraw原語像vdRect,vdPolyline,vdCircle等對象。如果要在DWG / DXF文件中導出對象,也會調(diào)用此方法,結(jié)果將是以這些格式保存。
如果希望自定義對象在命令中顯示Osnaps,則會將getOsnapPoints覆蓋用于Osnaps。
完成上述操作后,您可以將自定義對象添加到文檔的實體中,以格式繪制,保存/導出。您可以使用代碼添加此對象。
現(xiàn)在,您必須創(chuàng)建一個命令CreateBox。通過向用戶詢問簡單的點和寬度然后創(chuàng)建對象,可以執(zhí)行如下的簡單命令。
public static bool CreateBox(vdDocument Doc) { gPoint cen = new gPoint(); Doc.Prompt("Insertion Point : "); object ret = Doc.ActionUtility.getUserPoint(); Doc.Prompt(null); if (ret == null || !(ret is gPoint)) return false; cen = ret as gPoint; Doc.Prompt("Width : "); ret = Doc.ActionUtility.getUserDist(cen); Doc.Prompt(null); if (ret == null) return false; double Width = (double)ret; vdBox box = new vdBox(Doc); box.InsertionPoint = cen; Doc.Model.Entities.AddItem(box); return true; }
并在測試按鈕中調(diào)用此方法。
vdBox.CreateBox(vdFramedControl1.BaseControl.ActiveDocument);
如果您希望用戶進行交互并在命令期間實時繪制對象,則可以實現(xiàn)更復雜的操作(例如,如果要在選擇框的寬度時查看要繪制的自定義對象) 使用ActionEntityEx。您可以在VectorDrawPolygon命令的CmdPolygon中看到一個很好的示例。
相關(guān)資料推薦:
VectorDraw Developer Framework(VDF)示例