zoukankan      html  css  js  c++  java
  • cad.net 仿lisp函数专篇

    仿mapcar函数

    提供:雪山飞狐

    /// <summary>
    /// 仿lisp的mapcar函数
    /// </summary> 
    public static IEnumerable<TR> Mapcar<T1, T2, TR>(IEnumerable<T1> lst1, IEnumerable<T2> lst2, Func<T1, T2, TR> func)
    {
        var itor1 = lst1.GetEnumerator();
        var itor2 = lst2.GetEnumerator();
        while (itor1.MoveNext() && itor2.MoveNext())
            yield return func(itor1.Current, itor2.Current);
    }
    

    调用

    public class TestMapcar
    {
        [CommandMethod("tt")]
        public void tt()
        {
            Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
    
            var st1 = new List<double> { 1, 2, 3, 4 };
            var st2 = new List<double> { 1, 2, 3, 4 };
            var numbers = Mapcar(st1, st2, (a, b) => a + b);
    
            foreach (var item in numbers)
            {
                ed.WriteMessage("
    " + item.ToString());
            }
        }
    }
    =>输出: 2 4 6 8
    

    您可能还需要C#中的yield关键字的参考.
    避免判断yield中使用linq的Count()>0

    仿vlax-ldata-get函数

    先看lisp如何设置和获取一个词典对象:

    词典上面,设置: 词典名 mydict

    (vlax-ldata-put "mydict" "mykey" "Mumbo Dumbo")
    =>"Mumbo Dumbo"
    

    词典上面,获取: 词典名 mydict

    (vlax-ldata-get "mydict" "mykey")
    =>"Mumbo Dumbo"
    

    图元上面,设置:

    (vlax-ldata-put (car (entsel)) "mykey" "Mumbo Dumbo")
    =>"Mumbo Dumbo"
    

    图元上面,获取:

    (vlax-ldata-get (car (entsel)) "mykey")
    =>"Mumbo Dumbo"
    

    图元上面,删掉:

    (vlax-ldata-delete (car (entsel)) "mykey")
    =>T
    

    动态调用dll

    获取图元对象的词典:参考文章

    由于DllImport要写死dll名称,所以采取了一种动态调用dll内部方法的方式来进行优化:

    #if !HC2020
    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.Runtime;
    using Acap = Autodesk.AutoCAD.ApplicationServices.Application;
    #endif
    using System;
    using System.Runtime.InteropServices;
    using static JoinBox.src.试验库.AcdbAdsTool;
    
    namespace JoinBox.src.试验库
    {
        public class AcdbAdsTool
        { 
    #if AC2008 
            public struct AdsName
            {
                public IntPtr name1;
                public IntPtr name2;
            }
    
            //Acad2008的AcdbEntGetX参数必须加ref,而Acad2020不用(中间版本没有测试哦)..所以为了统一,就全部加了
            [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntGet")]
            public static extern IntPtr AcdbEntGet(ref AdsName objName);
    
            [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntGetX")]
            public static extern IntPtr AcdbEntGetX(ref AdsName objName, IntPtr app);
    #else
            [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl,EntryPoint = "acdbEntGet")]
            public static extern IntPtr AcdbEntGet(ref AdsName objName);
    
            [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl,EntryPoint = "acdbEntGetX")]
            public static extern IntPtr AcdbEntGetX(ref AdsName objName, IntPtr app);
    #endif
    
    
    #if false  //如果版本号 acdb17.acdb18.acdb19 不确定,那么就动态调用
            [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl,
                       EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
            static extern ErrorStatus AcdbGetAdsName32(out AdsName objName, ObjectId id);
            
            [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl,
                   EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
            static extern ErrorStatus AcdbGetAdsName64(out AdsName objName, ObjectId id); 
    #endif
    
            public static class Acdb
            {
                public static string Version()
                {
                    var acadver = Acap.GetSystemVariable("acadver").ToString();
                    var ver = acadver.Substring(0, 2);
                    return ver;
                }
    
                public static string AcdbDll()
                {
                    return "acdb" + Version() + ".dll";
                }
            }
    
            /// <summary>
            /// 将ObjectId转为AdsName
            /// </summary>
            /// <param name="name"></param>
            /// <param name="objId"></param>
            /// <returns></returns>
            public static ErrorStatus AcdbGetAdsName(out AdsName name, ObjectId objId)
            {
               //获取不同版本的cad版本号
                var dllName = Acdb.AcdbDll();
                IntPtr hModule = GetModuleHandle(dllName);
                if (hModule == IntPtr.Zero)
                    throw new System.Exception("AcdbGetAdsName找不到模块:" + dllName);
    
                string funcName;
    
                //判断系统运行环境
    #if false
                // DllImport 调用时候就这么直接调用就好了
                // 但是为了不每个版本都写一个预处理,所以采取动态调用.
                if (Marshal.SizeOf(IntPtr.Zero) > 4)
                {               
                    return AcdbGetAdsName64(out name, objId);              
                }
                else
                {
                    return AcdbGetAdsName32(out name, objId);              
                } 
    #else
                // 动态调用就要这样
                // funcName就是DllImport的Entrypoint
                if (Marshal.SizeOf(IntPtr.Zero) > 4)
                {
                    funcName = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z";
                }
                else
                {
                    funcName = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z";
                }
    #endif 
                //函数指针
                IntPtr funcAdress = GetProcAddress(hModule, funcName);
                if (funcAdress == IntPtr.Zero)
                    throw new System.Exception("AcdbGetAdsName没有找到这个函数的入口点:" + funcAdress);
    
                //利用委托调用函数指针,从而实现对方法的调用.
                var deFunc = Marshal.GetDelegateForFunctionPointer(funcAdress, typeof(DelegateAcdbGetAdsName)) as DelegateAcdbGetAdsName;
                return deFunc(out name, objId);
            }
    
            //委托,调用函数指针
            delegate ErrorStatus DelegateAcdbGetAdsName(out AdsName name, ObjectId objId);
        }
    
        public class TestGetIdata
        {
            [CommandMethod("tt")]
            public void CB_GetDict()
            {
                Document doc = Acap.DocumentManager.MdiActiveDocument;
                Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
    
                var promptEntity = ed.GetEntity("
    请选择图元:");
                if (promptEntity.Status != PromptStatus.OK) return;
    
                using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
                {
                    DBObject obj = tr.GetObject(promptEntity.ObjectId, OpenMode.ForRead);
    
                    //获取对象的扩展字典
                    if (!obj.ExtensionDictionary.IsOk())
                    {
                        return;
                    }
    
                    var objExDic = tr.GetObject(obj.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
                    if (objExDic == null)
                    {
                        return;
                    }
    
                    //词条id
                    ObjectId at = objExDic.GetAt("mykey");
                    //词条对象
                    DBObject bp = tr.GetObject(at, OpenMode.ForRead);
    
                    var rb = new ResultBuffer();
                    AcdbGetAdsName(out AdsName m_EName, bp.ObjectId);
                    IntPtr getx = AcdbEntGetX(ref m_EName, rb.UnmanagedObject);
                    if (getx == IntPtr.Zero)
                    {
                        return;
                    }
                    rb = ResultBuffer.Create(getx, true);                 
                    ed.WriteMessage(rb.ToString());
                }
            }
        }
    }
    

    一些必要的win32API:

    /// <summary>
    /// 获取一个应用程序或dll的模块句柄
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetModuleHandle(string name);
    
    /// <summary>
    /// 获取要引入的函数,将符号名或标识号转换为DLL内部地址
    /// </summary>
    /// <param name="hModule">exe/dll句柄</param>
    /// <param name="procName">接口名</param>
    /// <returns></returns>
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
    

    得到结果:

    ((-1,(-2173632))(0,VLO-VL)(5,1E0)(102,{ACAD_REACTORS)(330,(-2173640))(102,})(330,(-2173640))(100,vlo_VL)(90,-64512)(91,13)(92,0)(300,"Mumbo Dumbo"))
    

    仿ssnamex函数

    public class TestSsnamex
    {
        //获取选择的方式和选择的角点
        [CommandMethod("tt_getssgetpick", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
        public void tt_getssgetpick()
        {
            Database db = HostApplicationServices.WorkingDatabase;//当前的数据库
            Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage(Environment.NewLine + "****惊惊连盒-测试选择集的点选位置和点选方式");
    
            var tkids = new List<ObjectId>();
    
            //创建选择集过滤器,只选择块对象
            TypedValue[] filList = new TypedValue[]
            {
                // new TypedValue((int)DxfCode.Start, "INSERT")
            };
    
            SelectionFilter filter = new SelectionFilter(filList);
    
            //定义选择集选项
            var pso = new PromptSelectionOptions
            {
                RejectObjectsOnLockedLayers = true, //不选择锁定图层对象
                AllowDuplicates = true, //不允许重复选择 
            };
            var ssPsr = ed.GetSelection(pso, filter);
            if (ssPsr.Status != PromptStatus.OK)
            {
                return;
            }
    
            //foreach (var item in ssPsr.Value.GetObjectIds())
            //{
            //    Debug.WriteLine(item);//所有的角点信息 
            //}
    
            var va = ssPsr.Value;
            foreach (var vaItem in va)
            {
                if (vaItem is CrossingOrWindowSelectedObject cows)//框选方式
                {
                    foreach (var ppd in cows.GetPickPoints())
                    {
                        Debug.WriteLine(ppd.PointOnLine);//ppd内还有内容
                    }
                }
                else if (vaItem is PickPointSelectedObject pps)//点选方式
                {
                    Debug.WriteLine(pps.PickPoint);//pps内还有内容
                }
            } 
        }
    }
    

    (未完待续)

  • 相关阅读:
    (转)基于svnserve的服务器,权限文件authz配置的常见问题及解答
    How to merge two images into one using Actionscript
    Flash builder 4 (Flex builder 4) 正式版序列号生成器
    Linux安全配置步骤简述
    linux运行级别查看并更改研究
    Flex(flash)检测摄像头的3种状态(是否被占用,没安装摄像头,正常)
    推荐几个Adobe Flex Builder 3的插件(代码格式化和fms服务器通讯文件(main.asc)编写)
    OldHawk TODO on Unrealircd
    install flashpolicyd
    (转)谈linux安全设置
  • 原文地址:https://www.cnblogs.com/JJBox/p/12426728.html
Copyright © 2011-2022 走看看