Mstn中有很多种类型的元素,我们可以将其分成图形元素和非图形元素。本章主要讨论如何在Addin中利用Mstn对象模型创建图形元素。下图是CE版本Addins的整体架构。其中我们创建图形元素用到的对象主要在DgnPlatformNET下。
有关Mstn对象模型更详细的信息请参考位于…\ Bentley\MicroStationCONNECTSDK\doc文件夹下的帮助文档。另外,当你在VS中引用了Mstn对象模型后也能通过VS中的对象浏览器查看到整个对象模型,如下图所示。(VS中的对象浏览器是通过选VS菜单View > Object Browser打开的)
既然了解了图形元素的一些知识,就让我们通过一步步的操作在DGN模型中建立一些图形元素。
1.在解决方案浏览器中右击csAddins,选菜单Add > New Item…,在弹出的窗体中选Visual C# Items下的Class,文件名输入CreateElement.cs。点击Add按钮为当前项目添加一个新的CreateElement.cs文件。
2.修改并键入代码。最终的CreateElement.cs文件内容如下。其中绘制了九组元素,分别是LineAndLineString1、LineAndLineString2、LineAndLineString3、ShapeAndComplexShape、TextString、Cell、Dimension、BsplineCurve和Cone。
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BIM = Bentley.Interop.MicroStationDGN;
namespace csAddins
{
//尺寸标注元素的构造函数会调用DimensionCreateData的各个成员函数去获取创建尺寸标注元素需要的各种参数
class CreateDimensionCallbacks : DimensionCreateData
{
private DimensionStyle m_dimStyle;
private DgnTextStyle m_textStyle;
private Symbology m_symbology;
private LevelId m_levelId;
private DirectionFormatter m_directionFormatter;
public CreateDimensionCallbacks(DimensionStyle dimStyle, DgnTextStyle textStyle, Symbology symb, LevelId levelId, DirectionFormatter formatter)
{
m_dimStyle = dimStyle;
m_textStyle = textStyle;
m_symbology = symb;
m_levelId = levelId;
m_directionFormatter = formatter;
}
public override DimensionStyle GetDimensionStyle()
{
return m_dimStyle;
}
public override DgnTextStyle GetTextStyle()
{
return m_textStyle;
}
public override Symbology GetSymbology()
{
return m_symbology;
}
public override LevelId GetLevelId()
{
return m_levelId;
}
public override int GetViewNumber()
{
return 0;
}
//此函数返回的旋转矩阵与GetViewRotation返回的旋转矩阵共同定义了尺寸标注元素的方向
public override DMatrix3d GetDimensionRotation()
{
return DMatrix3d.Identity;
}
public override DMatrix3d GetViewRotation()
{
return DMatrix3d.Identity;
}
//用于从数字方向值构造字符串。
public override DirectionFormatter GetDirectionFormatter()
{
return m_directionFormatter;
}
}
class CreateElement
{
//函数后台坐标值使用的单位都是Uor单位,我们需要将传递给函数接口的值从主单位乘上此值变为Uor单位
static double UorPerMas = Session.Instance.GetActiveDgnModel().GetModelInfo().UorPerMaster;
//创建图形元素首先按框架分有两种创建方式,正如我们在第零章中开头部分介绍的那样,本函数简单演示了从v8i继承的COM接口创建图形元素的方式
public static void LineAndLineString1()
{
//从v8i继承的编程框架创建元素的函数都在Bentley.Interop.MicroStationDGN.Application接口下
BIM.Application app = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp;
BIM.Point3d ptStart = app.Point3dZero();
BIM.Point3d ptEnd = ptStart;
//使用这套编程框架时,函数接受参数的单位都是主单位,这一点是跟新的编程框架最大的不同之处
ptStart.X = 10;
BIM.LineElement lineEle = app.CreateLineElement2(null, ref ptStart, ref ptEnd);
lineEle.Color = 0; lineEle.LineWeight = 2;
app.ActiveModelReference.AddElement(lineEle);
}
//新的编程框架下创建元素的方式又可以分为两大种,本函数演示了其中一种直接通过特定类型元素的构造函数去构造,直接将坐标值传递给
//特定类型的构造函数去创建指定类型的元素
public static void LineAndLineString2()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
ModelInfo modelInfo = dgnModel.GetModelInfo();
DSegment3d seg = new DSegment3d(0 * UorPerMas, 5 * UorPerMas, 0 * UorPerMas, 10 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
LineElement lineEle = new LineElement(dgnModel, null, seg);
lineEle.AddToModel();
DPoint3d[] ptArr = new DPoint3d[5];
ptArr[0] = new DPoint3d(15 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(16 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(18 * UorPerMas, 8 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(20 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(21 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
LineStringElement lineStrEle = new LineStringElement(dgnModel, null, ptArr);
lineStrEle.AddToModel();
}
//本函数演示了新框架下另外一种创建图形元素的方法,即先构造图形元素的几何数据,最后调用统一的DraftingElementSchema.ToElement函数完成几何数据到特定类型元素的创建
public static void LineAndLineString3()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
ModelInfo modelInfo = dgnModel.GetModelInfo();
DPoint3d[] ptArr = new DPoint3d[5];
ptArr[0] = new DPoint3d(0 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(1 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(3 * UorPerMas, 8 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(5 * UorPerMas, 12 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(6 * UorPerMas, 10 * UorPerMas, 0 * UorPerMas);
//CurvePrimitive仅仅保存基本曲线的几何数据,不包含Mstn元素的其他任何数据(例如元素的颜色,线型等属性)
CurvePrimitive curPri = CurvePrimitive.CreateLineString(ptArr);
//DraftingElementSchema.ToElement将几何数据转换成Mstn中对应类型的元素(ArcElement,LineElement等)
Element ele = DraftingElementSchema.ToElement(dgnModel, curPri, null);
ele.AddToModel();
}
public static void ShapeAndComplexShape()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
DPoint3d[] ptArr = new DPoint3d[6];
ptArr[0] = new DPoint3d(0 * UorPerMas, -6 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(0 * UorPerMas, -2 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(2 * UorPerMas, -2 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(2 * UorPerMas, -4 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(4 * UorPerMas, -4 * UorPerMas, 0 * UorPerMas);
ptArr[5] = new DPoint3d(4 * UorPerMas, -6 * UorPerMas, 0 * UorPerMas);
ShapeElement shapeEle = new ShapeElement(dgnModel, null, ptArr);
//ElementPropertiesSetter用来设置元素Symbol属性(颜色,线型等属性)
ElementPropertiesSetter elePropSet = new ElementPropertiesSetter();
elePropSet.SetColor(0);
elePropSet.SetWeight(2);
elePropSet.Apply(shapeEle);
shapeEle.AddToModel();
for (int i = 0; i < 6; i++)
ptArr[i].X += 5 * UorPerMas;
CurvePrimitive curvePri = CurvePrimitive.CreateLineString(ptArr);
//CurveVector是CurvePrimitive的集合,用来表示任意复杂的线型几何数据
CurveVector curVec = CurveVector.Create(CurveVector.BoundaryType.Outer);
curVec.Add(curvePri);
ptArr[2].Y = -8;
DEllipse3d ellipse = new DEllipse3d();
if (DEllipse3d.TryCircularArcFromCenterStartEnd(ptArr[2], ptArr[5], ptArr[0], out ellipse))
{
curvePri = CurvePrimitive.CreateArc(ellipse);
curVec.Add(curvePri);
Element eleTemp = DraftingElementSchema.ToElement(dgnModel, curVec, null);
eleTemp.AddToModel();
elePropSet.SetColor(1);
elePropSet.SetWeight(2);
elePropSet.Apply(eleTemp);
eleTemp.AddToModel();
}
}
//文本元素需要的各种参数分了Block,Paragraph,Run等层级,每一层设置其包含的属性,有点类似于Word中的管理结构
public static void TextString()
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
TextBlockProperties txtBlockProp = new TextBlockProperties(dgnModel);
txtBlockProp.IsViewIndependent = true;
ParagraphProperties paraProp = new ParagraphProperties(dgnModel);
DgnTextStyle txtStyle = DgnTextStyle.GetSettings(dgnFile);
RunProperties runProp = new RunProperties(txtStyle, dgnModel);
TextBlock txtBlock = new TextBlock(txtBlockProp, paraProp, runProp, dgnModel);
txtBlock.AppendText("This is a textBlock Element");
TextHandlerBase txtHandlerBase = TextHandlerBase.CreateElement(null, txtBlock);
DTransform3d trans = DTransform3d.Identity;
trans.Translation = new DVector3d(6 * UorPerMas, 2 * UorPerMas, 3 * UorPerMas); //UOR unit
TransformInfo transInfo = new TransformInfo(trans);
//对图形元素进行旋转平移的变换可以将元素变换到任意位置,此处只做了平移变换,没有旋转
txtHandlerBase.ApplyTransform(transInfo);
txtHandlerBase.AddToModel();
}
//单元是由若干个子元素加一个单元头元素构成的复杂元素,子元素也可是一个单元
public static void Cell()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
DPoint3d[] ptArr = new DPoint3d[5];
ptArr[0] = new DPoint3d(-15 * UorPerMas, -5 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(-15 * UorPerMas, 5 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(-5 * UorPerMas, 5 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(-5 * UorPerMas, -5 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(-15 * UorPerMas, -5 * UorPerMas, 0 * UorPerMas);
ShapeElement shapeEle = new ShapeElement(dgnModel, null, ptArr);
DPlacementZX dPlaceZX = DPlacementZX.Identity;
dPlaceZX.Origin = new DPoint3d(-10 * UorPerMas, 0, 0);
DEllipse3d ellipse = new DEllipse3d(dPlaceZX, 5 * UorPerMas, 5 * UorPerMas, Angle.Zero, Angle.TWOPI);
EllipseElement elliEle = new EllipseElement(dgnModel, null, ellipse);
List<Element> listEle = new List<Element>();
listEle.Add(shapeEle);
listEle.Add(elliEle);
DPoint3d ptOri = new DPoint3d();
DMatrix3d rMatrix = DMatrix3d.Identity;
DPoint3d ptScale = new DPoint3d(1, 1, 1);
CellHeaderElement cellHeaderEle = new CellHeaderElement(dgnModel, "CellElementSample", ptOri, rMatrix, listEle);
cellHeaderEle.AddToModel();
}
public static void Dimension()
{
DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
double uorPerMast = dgnModel.GetModelInfo().UorPerMaster;
//获取当前dgn文件中名字为"DimStyle"的标注样式,尺寸标注元素的外貌由上百个属性控制,而标注样式是一组预先设置好的属性
//获取了预先订制好的标注样式之后,还可以调用DimensionStyle下的各种SetXXX成员函数修改设置的属性
DimensionStyle dimStyle = new DimensionStyle("DimStyle", dgnFile);
dimStyle.SetBooleanProp(true, DimStyleProp.Placement_UseStyleAnnotationScale_BOOLINT);
dimStyle.SetDoubleProp(1, DimStyleProp.Placement_AnnotationScale_DOUBLE);
dimStyle.SetBooleanProp(true, DimStyleProp.Text_OverrideHeight_BOOLINT);
dimStyle.SetDistanceProp(0.5 * uorPerMast, DimStyleProp.Text_Height_DISTANCE, dgnModel);
dimStyle.SetBooleanProp(true, DimStyleProp.Text_OverrideWidth_BOOLINT);
dimStyle.SetDistanceProp(0.4 * uorPerMast, DimStyleProp.Text_Width_DISTANCE, dgnModel);
dimStyle.SetBooleanProp(true, DimStyleProp.General_UseMinLeader_BOOLINT);
dimStyle.SetDoubleProp(0.01, DimStyleProp.Terminator_MinLeader_DOUBLE);
dimStyle.SetBooleanProp(true, DimStyleProp.Value_AngleMeasure_BOOLINT);
dimStyle.SetAccuracyProp((byte)AnglePrecision.Use1Place, DimStyleProp.Value_AnglePrecision_INTEGER);
int alignInt = (int)DimStyleProp_General_Alignment.True;
StatusInt status = dimStyle.SetIntegerProp(alignInt, DimStyleProp.General_Alignment_INTEGER);
int valueOut;
dimStyle.GetIntegerProp(out valueOut, DimStyleProp.General_Alignment_INTEGER);
DgnTextStyle textStyle = new DgnTextStyle("TestStyle", dgnFile);
LevelId lvlId = Settings.GetLevelIdFromName("Default");
CreateDimensionCallbacks callbacks = new CreateDimensionCallbacks(dimStyle, textStyle, new Symbology(), lvlId, null);
DimensionElement dimEle = new DimensionElement(dgnModel, callbacks, DimensionType.SizeArrow);
if (dimEle.IsValid)
{
DPoint3d pt1 = DPoint3d.Zero, pt2 = DPoint3d.FromXY(uorPerMast * 10, uorPerMast * 0);
dimEle.InsertPoint(pt1, null, dimStyle, -1);
dimEle.InsertPoint(pt2, null, dimStyle, -1);
//设置尺寸标注元素的高度
dimEle.SetHeight(uorPerMast);
DMatrix3d rMatrix = DMatrix3d.Identity;
dimEle.SetRotationMatrix(rMatrix);
dimEle.AddToModel();
}
}
public static void BsplineCurve()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
DPoint3d[] ptArr = new DPoint3d[5];
ptArr[0] = new DPoint3d(0 * UorPerMas, 25 * UorPerMas, 0 * UorPerMas);
ptArr[1] = new DPoint3d(5 * UorPerMas, 35 * UorPerMas, 0 * UorPerMas);
ptArr[2] = new DPoint3d(10 * UorPerMas, 25 * UorPerMas, 0 * UorPerMas);
ptArr[3] = new DPoint3d(15 * UorPerMas, 35 * UorPerMas, 0 * UorPerMas);
ptArr[4] = new DPoint3d(20 * UorPerMas, 25 * UorPerMas, 0 * UorPerMas);
MSBsplineCurve msBsplineCurve = MSBsplineCurve.CreateFromPoles(ptArr, null, null, 3, false, true);
CurvePrimitive curvePri = CurvePrimitive.CreateBsplineCurve(msBsplineCurve);
Element ele = DraftingElementSchema.ToElement(dgnModel, curvePri, null);
ele.AddToModel();
}
public static void Cone()
{
DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
DPoint3d ptTop = new DPoint3d(2 * UorPerMas, -15 * UorPerMas, 0 * UorPerMas);
DPoint3d ptBottom = new DPoint3d(2 * UorPerMas, -15 * UorPerMas, 3 * UorPerMas);
DMatrix3d rMatrix = DMatrix3d.Identity;
ConeElement coneEle = new ConeElement(dgnModel, null, 2 * UorPerMas, 1 * UorPerMas, ptTop, ptBottom, rMatrix, true);
coneEle.AddToModel();
}
}
}
4.打开MyAddins.cs文件修改如下。
protected override int Run(string[] commandLine)
{
CreateElement.LineAndLineString1();
CreateElement.LineAndLineString2();
CreateElement.LineAndLineString3();
CreateElement.ShapeAndComplexShape();
CreateElement.TextString();
CreateElement.Cell();
CreateElement.Dimension();
CreateElement.BsplineCurve();
CreateElement.Cone();
return 0;
}
5.通过选菜单Build > Build Solution来重新生成目标文件。记住,在执行生成前要记住退出Mstn。
6.启动Mstn,装载csAddins程序,则能看到如下图所示的图形。请注意,你当前的DGN文件模型应该是一个三维模型,否则Cone方法将不能被正确执行。
在以上代码中我们用了三种方法画线元素。LineAndLineString1用的是CE版本之前Addins开放框架。LineAndLineString2用的是CE上Addins开发框架,通过元素类型的构造函数创建元素。LineAndLineString3用的是CE上Addins开发框架的一种全新的创建元素的方法,即先创建几何,最后通过DraftingElementSchema 下的静态成员函数ToElement把几何转换为元素。我们可以看到CE Addins框架为我们提供了丰富的创建元素的方法,具体使用哪一种我们可以根据实际情况选择。