使用Nuget:
PM> Install-Package Du.SolidWorks -Version 0.1.1
一.IModelDoc2 介绍
首先我们来看ModelDoc2的对象关系图,使用ModelDoc2 我们可以转换为AssemblyDoc PartDoc DrawingDoc等特定文档类型,也可以获取ModelDocExtension等,从而调用很多常见的api,可以说IModelDoc2接口几乎是开发中使用频率最高的接口。
二.通过IModelDoc2获取文档类型
1.1 直接获取文档类型,GetType方法直接放回的此文档的类型,注意和 csharp 反射 自带的GetType区分
/// <summary>
/// 获取文档类型
/// </summary>
/// <param name="doc"><see cref="IModelDoc2"/></param>
/// <returns></returns>
public static swDocumentTypes_e GetTypeEx(this IModelDoc2 doc)
{
return (swDocumentTypes_e)doc.GetType();
}
1.2 判断此文档是否是某种类型
既然可以获取文档类型,我们便可以通过简单的封装来判断文档类型
/// <summary>
/// 是否是特定的类型
/// </summary>
/// <param name="doc"><see cref="IModelDoc2"/></param>
/// <param name="type">文档类型 <see cref="swDocumentTypes_e"/></param>
/// <returns></returns>
public static bool IsSpecType(this IModelDoc2 doc,swDocumentTypes_e type)
{
return doc.GetTypeEx() == type;
}
三.通过IModelDoc2 获取特定文档的接口
我们知道了ModelDoc2 可以转换为特定文档接口,我们也可以通过IModelDoc2的GetType方法获取文档类型,下面我们就可以将其转换为特定文档的接口。代码很简单,直接转换类型即可,实现如下。
1.转换为PartDoc
/// <summary>
/// 转换为零件文档
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
public static PartDoc AsPartDoc(this IModelDoc2 doc)
{
if (doc.GetTypeEx() != swDocumentTypes_e.swDocPART)
{
throw new Exception("错误的类型,无法转换为PartDoc");
}
return (PartDoc)doc;
}
2.转换为AssemblyDoc
/// <summary>
/// 转换为装配体
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
public static AssemblyDoc AsAssemblyDoc(this IModelDoc2 doc)
{
if (doc.GetTypeEx() != swDocumentTypes_e.swDocASSEMBLY)
{
throw new Exception("错误的类型,无法转换为PartDoc");
}
return (AssemblyDoc)doc;
}
3.转换为DrawingDoc
/// <summary>
/// 转换为 <see cref="IDrawingDoc"/>
/// </summary>
/// <param name="doc"><see cref="IModelDoc2"/></param>
/// <returns><see cref="IDrawingDoc"/></returns>
public static IDrawingDoc AsDrawingDoc(this IModelDoc2 doc)
{
if (doc.GetTypeEx() != swDocumentTypes_e.swDocDRAWING)
{
throw new Exception("错误的类型,无法转换为PartDoc");
}
return (IDrawingDoc)doc;
}
四.IModelDoc2 中对特征的获取
4.1 获取所有特征
通过IFeatureManager 中的GetFeatures便可以获取所有特征,下面代码通过此方法使得直接可以通过IModelDoc2接口获取所有特征
/// <summary>
/// 获取所有的某种类型的特征
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
public static IEnumerable<IFeature> GetFeats(this IModelDoc2 doc)
{
var feats = doc.FeatureManager
.GetFeatures(false)
as IFeature[];
return feats;
}
4.2 按顺序获取所有特征
上面的方法只是获取了所有的特征,但特征的顺序是随机的,下面的方法按照特征顺序遍历了所有的特征
/// <summary>
/// 按顺序遍历特征
/// </summary>
/// <param name="doc"></param>
/// <param name="TopOnly"></param>
/// <returns></returns>
public static List<IFeature> GetFirstToLastFeats(this IModelDoc2 doc,bool TopOnly = true)
{
List<IFeature> feats = new List<IFeature>();
var Feat = doc.FirstFeature() as IFeature;
while (Feat != null)
{
feats.Add(Feat);
if (!TopOnly)
{
var SubFeat = Feat.GetFirstSubFeature() as IFeature;
while (SubFeat != null)
{
feats.Add(SubFeat);
SubFeat = SubFeat.GetNextSubFeature() as IFeature;
}
}
Feat = Feat.GetNextFeature() as IFeature;
}
return feats;
}
对上面的方法,也可以返回一个IEnumerable<IFeature> 来实现懒加载,提高某些场景下的速度。
4.3 通过特征获取所有的特征尺寸
/// <summary>
/// 获取所有的特征尺寸
/// </summary>
/// <param name="doc"></param>
/// <param name="TopOnly"></param>
/// <returns></returns>
public static List<KeyValuePair<Feature,DisplayDimension>> GetModelDispalyDimensions(this ModelDoc2 doc,bool TopOnly = true)
{
var listResult = new List<KeyValuePair<Feature, DisplayDimension>>();
var feats = doc.FeatureManager.GetFeaturesEx(TopOnly);
foreach (var feat in feats)
{
var dims = feat.GetDisplayDimensions();
foreach (var dim in dims)
{
listResult.Add(new KeyValuePair<Feature, DisplayDimension>(feat.CastObj<Feature>(), dim));
}
}
return listResult;
}
五.IModelDoc2中的屏幕和视图的变换
5.1将屏幕坐标变换的模型空间
/// <summary>
/// 从一个给定的屏幕上的X,Y变换到视图模型中的点和方向
/// </summary>
/// <param name="doc"></param>
/// <param name="math"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public static PointDirection3 ScreenToView(this IModelDoc2 doc,MathUtility math ,int x, int y)
{
var view = doc.ActiveView as IModelView;
var t = view.Transform.Inverse() as MathTransform;
var eye = math.PointEx(new[] { x, y, 0.0 });
var look = math.ZAxis();
eye = eye.MultiplyTransform(t) as MathPoint;
look = look.MultiplyTransform(t) as MathVector;
return new PointDirection3(eye.ToVector3(), look.ToVector3());
}
5.2 模型空间到屏幕坐标
同样我们可以计算出模型空间到屏幕坐标
/// <summary>
/// 空间点变换到屏幕
/// </summary>
/// <param name="doc"></param>
/// <param name="math"></param>
/// <param name="point"></param>
/// <returns></returns>
public static Vector2 ViewToScreen(this IModelDoc2 doc, MathUtility math , Vector3 point)
{
var view = doc.ActiveView as IModelView;
var t = view.Transform as MathTransform;
var mathPoint = point.ToSwMathPoint(math);
mathPoint = mathPoint.MultiplyTransform(t) as MathPoint;
var v3 = mathPoint.ToVector3();
return new Vector2(v3.X, v3.Y);
}
六.关于SolidWorks对象的PID
在SolidWorks中对于特征,实体,边线面等对象都具有一个PID,PID即Persist ID ,持久性ID。此ID一般在创建后变不会改变。通过比较此ID,我们可以判断出这是不是我们以前操作过的对象。实现一些比较性的功能
6.1 pidcollector 获取PID
在SolidWork安装目录下,我的在C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\api 。SolidWorks提供了一个直接获取PID的工具
通过此工具,我们可以方便的获取SolidWorks中某个对象的PID
6.2 通过代码获取SolidWorks对象的PID
/// <summary>
/// 获取实体PID
/// Because we should use the same version of `GetPersistReference` and `GetObjectFromPersistReference` resp.
/// and the persist reference is saved with the models we should never ever use another version of the two methods.
/// For more details see http://help.solidworks.com/2016/english/api/sldworksapi/SolidWorks.interop.sldworks~SolidWorks.interop.sldworks.IModelDocExtension~GetPersistReference3.html#remarksSection
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelDoc"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] GetPersistReference<T>(this IModelDoc2 modelDoc, T obj)
{
return modelDoc.Extension.GetPersistReference3(obj) as byte[];
}
6.3 通过PID获取对象
这是PID最神奇的地方,我们可以在某些地方记录下某个对象的PID,然后我们可以通过这个PID再次获取某个SolidWorks对象。
/// <summary>
/// Get an entity from its persist id.
///
/// Because we should use the same version of `GetPersistReference` and `GetObjectFromPersistReference` resp.
/// and the persist reference is saved with the models we should never ever use another version of the two methods.
/// For more details see http://help.solidworks.com/2016/english/api/sldworksapi/SolidWorks.interop.sldworks~SolidWorks.interop.sldworks.IModelDocExtension~GetPersistReference3.html#remarksSection
/// </summary>
/// <param name="doc"></param>
/// <param name="persistId"></param>
/// <returns></returns>
public static object GetObjectFromPersistReference(this IModelDoc2 doc, byte[] persistId)
{
int errorCode;
var @object = doc.Extension.GetObjectByPersistReference3(persistId, out errorCode);
var result = (swPersistReferencedObjectStates_e)errorCode;
if (result != swPersistReferencedObjectStates_e.swPersistReferencedObject_Ok)
{
throw new Exception($"GetObjectByPersistReference3 returned {result}");
}
return @object;
}
七 .IModelDoc2 中的配置
通过ModelDoc2 可以获取配置信息
7.1 获取所有配置
/// <summary>
/// Get all configurations
/// </summary>
/// <param name="modelDoc"></param>
/// <returns></returns>
public static IEnumerable<Configuration> GetConfigurations(this IModelDoc2 modelDoc)
{
var configs = modelDoc
.GetConfigurationNames()
as string[];
return configs.Select(name => (Configuration)modelDoc.GetConfigurationByName(name));
}
7.2 通过ID获取配置
/// <summary>
/// Look-up a configuration based on it's ID
/// </summary>
/// <param name="modelDoc"></param>
/// <param name="ID"></param>
/// <returns></returns>
public static Configuration GetConfigurationFromID(this IModelDoc2 modelDoc, int ID)
{
return modelDoc
.GetConfigurations()
.FirstOrDefault(config => config.GetID() == ID);
}
总结
IModelDoc2 提供了对一个SolidWorks基础文档的很多访问和操作,当然有些更多的操作被转发到其他对象。但IModelDoc2接口依然是SolidWorks开发中不可避免的接口,其丰富的方法还需要去探索。