基于.NET三维控件的个性化管道软件开发
1 简介
管道广泛用于化工、工厂、建筑、市政等方面,关系到国计民生。虽然管道设计软件种类繁多,有的也非常强大(然而也非常昂贵),但也并不能完全满足个性化需要。 如何快速开发一款满足自己需求的三维管道设计软件?本文提供一种基于AnyCAD .NET SDK的开发解决方案,不妨一试。
2 方案
《.NET6: 开发基于WPF的摩登三维工业软件》系列提供了一种插件式的开发工业软件的框架(源码详见:https://gitee.com/anycad/RapidCAX )。本案例基于该框架开发。
整体上采用MVVM模式,以直管为例,整体架构如下:
注:上述架构在《.NET6: 开发基于WPF的摩登三维工业软件》系列有详细说明。
3 实现
本案例中,管道由直管和弯管组成,两种的参数不一样,因此需要按照不同的类型来处理。由于篇幅所限,此处以直管为例的MVVM架构实现。
3.1 Model实现
// 定义管子的参数
public class PipeModel : ElementModel
{
public GPnt Position = new GPnt();
public GDir Direction = new GDir();
public double Thickness = 2;
public double InnerRadius = 5;
public double Length = 100;
public PipeModel()
{
}
// 根据参数创建几何
public TopoShape CreateShape()
{
return ShapeBuilder.MakeTube(Position, Direction, InnerRadius, Thickness, Length);
}
}
//参数化机制实现
class PipeSchema : ElementSchema
{
public PipeSchema()
: base(nameof(PipeModel))
{
this.SetTitle("管");
}
public override ElementModel CreateModel()
{
return new PipeModel();
}
public override Element OnCreateInstance()
{
return new ShapeInstance();
}
public override bool OnParameterChanged(Document document, Element instance, ParameterDict parameters)
{
var element = ShapeInstance.Cast(instance);
if (element == null)
return false;
PipeModel model = new PipeModel();
model.Load(parameters);
var shape = model.CreateShape();
element.SetShape(shape);
return true;
}
}
3.2 ViewModel实现
internal class PipeViewModel : ElementViewModel
{
public PipeModel Model { get { return (PipeModel)_Model; } }
public PipeViewModel(Element model, Document doc)
: base(new PipeModel(), model, doc)
{
SetPickFilter(EnumShapeFilter.VertexEdgeFace);
}
public GPnt Position
{
get => Model.Position;
set => SetProperty(nameof(Position), ref Model.Position, value, nameof(X), nameof(Y), nameof(Z));
}
public double X
{
get => Model.Position.x;
set
{
if(X != value)
{
Position = new GPnt(value, Model.Position.y, Model.Position.z);
}
}
}
public double Y
{
get => Model.Position.y;
set
{
if (Y != value)
{
Position = new GPnt(Model.Position.x, value, Model.Position.z);
}
}
}
public double Z
{
get => Model.Position.z;
set
{
if (Z != value)
{
Position = new GPnt(Model.Position.x, Model.Position.y, value);
}
}
}
public GDir Direction
{
get => Model.Direction;
set => SetProperty(nameof(Direction), ref Model.Direction, value);
}
public double InnerRadius
{
get => Model.InnerRadius;
set => SetProperty(nameof(InnerRadius), ref Model.InnerRadius, value,
() => { return value > 0; }, nameof(OutterRadius));
}
public double Thickness
{
get => Model.Thickness;
set => SetProperty(nameof(Thickness