二.SolidWorks 二次开发之 IModelDoc2

访问项目 Github仓库

查看在线文档

使用Nuget:

PM> Install-Package Du.SolidWorks -Version 0.1.1

去Github查看本节源代码

一.IModelDoc2 介绍

首先我们来看ModelDoc2的对象关系图,使用ModelDoc2 我们可以转换为AssemblyDoc PartDoc DrawingDoc等特定文档类型,也可以获取ModelDocExtension等,从而调用很多常见的api,可以说IModelDoc2接口几乎是开发中使用频率最高的接口。

IModelDoc2 Object Model

二.通过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的工具


pidcollector.exe

通过此工具,我们可以方便的获取SolidWorks中某个对象的PID

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开发中不可避免的接口,其丰富的方法还需要去探索。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容