zoukankan      html  css  js  c++  java
  • AutoCad 二次开发 文字镜像

    AutoCad 二次开发 文字镜像

    在autocad中如果使用Mirror命令把块参照给镜像了(最终得到一个对称的块),块里面的文字包括DBText和MText以及标注上面的文字都会被对称,变得不易阅读。而在单个字体实体和标注实体镜像的时候只要设置系统变量mirrtext为0镜像后的文字就不会与原文字对称变成我们未学习过的文字了。
     
    所以我们在镜像块的时候就可以先把块炸开是用快捷键X,或者输入explode,然后在使用镜像命令。之后在把对称后的实体集合组成一个新的块。不过这样操作十分的繁琐,我觉得其中这样做的优势是mirror时的jig操作可以很方便的预先知道我们想要的对称后的结果。但如果用代码实现这种jig操作,我觉得有点复杂,目前我还不知道怎么实现。
     
    我要讲的主要就是用代码来实现块的镜像。难点就在与文字的镜像,和标注的镜像。这篇文章先讲文字的镜像。文字镜像的主要步骤分为:
    1.找到镜像前文字边界的四个角,这四个角构成了一个矩形,我们要求得这个矩形的长和宽所代表的向量。
    2.判断文字镜像后的方向,如果是偏向朝Y轴镜像,那么文字镜像后的方向是沿着X轴翻转的,如果是偏向朝X轴镜像,那么文字镜像后的方向是沿着X轴翻转的。这里我以沿着Y轴镜像为例子。
    3.移动镜像后切被翻转后的文字,这里也是根据镜像轴的不同,需按不同的向量来移动。
     
    详细情况见图:
    图中左边是要镜像的文字,文字上的蓝色线,和黄色线是我调试的时候加入的,黄线左端是 pt1,右端是pt2,蓝线左端是pt3,右端是pt4。 中间的竖线是Y轴镜像线,右边就是不同情况下镜像后的文字。其中黄色部分表示正确的镜像结果,红色部分表示:镜像后延第一个步骤移动后求得的向量移动了文字的position但是没翻转的结果。黑色部分表示:镜像后翻转了文字但文字的position没有按向量移动的结果。
    下面我就来仔细分析一下代码:
    要实现第一步骤,前提是要有一段P/Invoke的代码:
    其中 引入的acdb22.dll是 autocad2018中的版本,不同版本,这个dll后面的数字不一样。我们可以到cad安装目录下查找acdb几个字,找到后面带数字的就是了,64位的安装目录默认位置:C:Program FilesAutodeskAutoCAD 2018。这两个函数一个是32位,一个是64位,具体用哪个后面的代码会自动判断。这个函数作用我觉得主要是求 这个name。
     
    这里用到了accore.dll,有的cad版本没有这个dll,就用acad.exe代替就可以了。上面的acdbEntGet主要是根据entity的名字求的entity实体的Intptr,下面的函数时求的文字边界对角点,这里注意,我把这个两个点用直线打印在cad空间里,发现它时在原点,没旋转的线,但其实文字不的position不在原点,也带有旋转角度。后面要求的文字边界向量就是根据这两个点来的。
    上面求得的pt1,pt2 经过:
    pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
    pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
    这种操作就得到了第一幅图中的黄线。
    在经过这样的操作,得到的pt3 和pt4就是第一幅图的蓝线。这其中的rotDir和linDir就是我们要求得的宽和长代表的向量了,然后在把它给镜像了得到的mirRotDir和mirLinDir就是镜像后的文字要移动的向量了,这里第一步就结束了。
    第二步,第三步:
     
    大的话,就说明文字需要朝X轴翻转,所以这里的IsMirroredInX=true就代表需要朝X轴翻转。
    紧接着下面句,如果没加mirLineDir这个向量,就会出现第一幅图中的画黑线的情况,如果不加IsMirrorInX就会出现画红线的情况。
    到这里就全部结束了。
    下面给出所有代码:
    public class MyMirror
        {
            Document Doc = Application.DocumentManager.MdiActiveDocument;
            Editor Ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Database Db = Application.DocumentManager.MdiActiveDocument.Database;
    
            List<Entity> list = new List<Entity>();
            List<ObjectId> listOId = new List<ObjectId>();
    
            [CommandMethod("testM")]
    
            public void MirrorTextCmd()
    
            {
    
                Document doc = Application.DocumentManager.MdiActiveDocument;
    
                Database db = doc.Database;
    
                Editor ed = doc.Editor;
    
    
    
                //Entity selection
    
                PromptEntityOptions peo = new PromptEntityOptions(
    
                    "
    Select a text entity:");
    
    
    
                peo.SetRejectMessage("
    Must be text entity...");
    
                peo.AddAllowedClass(typeof(DBText), true);
    
    
    
                PromptEntityResult perText = ed.GetEntity(peo);
    
    
    
                if (perText.Status != PromptStatus.OK)
    
                    return;
    
    
    
                peo = new PromptEntityOptions("
    Select a mirror line:");
    
                peo.SetRejectMessage("
    Must be a line entity...");
    
                peo.AddAllowedClass(typeof(Line), true);
    
    
    
                PromptEntityResult perLine = ed.GetEntity(peo);
    
    
    
                if (perLine.Status != PromptStatus.OK)
    
                    return;
    
    
    
                using (Transaction tr = db.TransactionManager.StartTransaction())
    
                {
    
                    Line line = tr.GetObject(perLine.ObjectId, OpenMode.ForRead)
    
                        as Line;
    
    
    
                    Line3d mirrorLine = new Line3d(
    
                        line.StartPoint,
    
                        line.EndPoint);
    
    
    
                    MirrorText(perText.ObjectId, mirrorLine);
    
    
    
                    tr.Commit();
    
                }
    
            }
    
    
    
            void MirrorText(ObjectId oId, Line3d mirrorLine)
    
            {
    
                Database db = oId.Database;
    
    
    
                using (Transaction tr = db.TransactionManager.StartTransaction())
    
                {
    
                    // Get text entity
    
                    DBText dbText = tr.GetObject(oId, OpenMode.ForRead)
    
                        as DBText;
    
    
    
                    // Clone original entity
    
                    DBText mirroredTxt = dbText.Clone() as DBText;
    
    
    
                    // Create a mirror matrix
    
                    Matrix3d mirrorMatrix = Matrix3d.Mirroring(mirrorLine);
    
    
    
                    // Do a geometric mirror on the cloned text
    
                    mirroredTxt.TransformBy(mirrorMatrix);
    
    
    
                    // Get text bounding box
    
                    Point3d pt1, pt2, pt3, pt4;
    
                    GetTextBoxCorners(
    
                        dbText,
    
                        out pt1,
    
                        out pt2,
    
                        out pt3,
    
                        out pt4);
    
    
    
                    // Get the perpendicular direction to the original text
    
                    Vector3d rotDir =
    
                        pt4.Subtract(pt1.GetAsVector()).GetAsVector();
    
    
    
                    // Get the colinear direction to the original text
    
                    Vector3d linDir =
    
                        pt3.Subtract(pt1.GetAsVector()).GetAsVector();
    
    
    
                    // Compute mirrored directions
    
                    Vector3d mirRotDir = rotDir.TransformBy(mirrorMatrix);
    
                    Vector3d mirLinDir = linDir.TransformBy(mirrorMatrix);
    
    
    
                    //Check if we need to mirror in Y or in X
    
                    if (Math.Abs(mirrorLine.Direction.Y) >
    
                        Math.Abs(mirrorLine.Direction.X))
    
                    {
    
                        // Handle the case where text is mirrored twice
    
                        // instead of doing "oMirroredTxt.IsMirroredInX = true"
    
                        mirroredTxt.IsMirroredInX = !mirroredTxt.IsMirroredInX;
    
                        mirroredTxt.Position = mirroredTxt.Position + mirLinDir;
    
                    }
    
                    else
    
                    {
    
                        mirroredTxt.IsMirroredInY = !mirroredTxt.IsMirroredInY;
    
                        mirroredTxt.Position = mirroredTxt.Position + mirRotDir;
    
                    }
    
    
    
                    // Add mirrored text to database
    
                    //btr.AppendEntity(mirroredTxt);
    
                    //tr.AddNewlyCreatedDBObject(mirroredTxt, true);
    
                    //list.Add(mirroredTxt);
                    mirroredTxt.ToSpace();
                    tr.Commit();
    
                }
    
            }
            #region p/Invoke
    
    
            public struct ads_name
            {
    
                public IntPtr a;
    
                public IntPtr b;
    
            };
    
    
    
            // Exported function names valid only for R19
    
    
    
            [DllImport("acdb22.dll",
    
                CallingConvention = CallingConvention.Cdecl,
    
                EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
    
            public static extern int acdbGetAdsName32(
    
                ref ads_name name,
    
                ObjectId objId);
    
    
    
            [DllImport("acdb22.dll",
    
                CallingConvention = CallingConvention.Cdecl,
    
                EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
    
            public static extern int acdbGetAdsName64(
    
                ref ads_name name,
    
                ObjectId objId);
    
    
    
            public static int acdbGetAdsName(ref ads_name name, ObjectId objId)
    
            {
    
                if (Marshal.SizeOf(IntPtr.Zero) > 4)
    
                    return acdbGetAdsName64(ref name, objId);
    
    
    
                return acdbGetAdsName32(ref name, objId);
    
            }
    
    
    
            [DllImport("accore.dll",
    
                CharSet = CharSet.Unicode,
    
                CallingConvention = CallingConvention.Cdecl,
    
                EntryPoint = "acdbEntGet")]
    
            public static extern System.IntPtr acdbEntGet(
    
                ref ads_name ename);
    
    
    
            [DllImport("accore.dll",
    
                CharSet = CharSet.Unicode,
    
                CallingConvention = CallingConvention.Cdecl,
    
                EntryPoint = "acedTextBox")]
    
            public static extern System.IntPtr acedTextBox(
    
                IntPtr rb,
    
                double[] point1,
    
                double[] point2);
    
    
    
            void GetTextBoxCorners(DBText dbText, out Point3d pt1, out Point3d pt2, out Point3d pt3, out Point3d pt4)
    
            {
    
                ads_name name = new ads_name();
    
    
    
                int result = acdbGetAdsName(
    
                    ref name,
    
                    dbText.ObjectId);
    
    
    
                ResultBuffer rb = new ResultBuffer();
    
    
    
                Interop.AttachUnmanagedObject(
    
                    rb,
    
                    acdbEntGet(ref name), true);
    
    
    
                double[] point1 = new double[3];
    
                double[] point2 = new double[3];
    
    
    
                // Call imported arx function
    
                acedTextBox(rb.UnmanagedObject, point1, point2);
    
    
    
                pt1 = new Point3d(point1);
    
                pt2 = new Point3d(point2);
    
                var ptX = pt1 + Vector3d.XAxis * 40;
                var ptY = pt2 + Vector3d.YAxis * 50;
    
    
                var lX = new Line(pt1, ptX);
                var lY = new Line(pt2, ptY);
    
                lX.Color= Color.FromColor(System.Drawing.Color.Green);
                lY.Color= Color.FromColor(System.Drawing.Color.Orange);
    
    
                Line line = new Line(pt1, pt2);
    
                line.Color = Color.FromColor(System.Drawing.Color.Red);
    
                line.ToSpace();
                lX.ToSpace();
                lY.ToSpace();
    
                // Create rotation matrix
    
                Matrix3d rotMat = Matrix3d.Rotation(
    
                    dbText.Rotation,
    
                    dbText.Normal,
    
                    pt1);
    
    
    
                // The returned points from acedTextBox need
    
                // to be transformed as follow
    
                pt1 = pt1.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
    
                pt2 = pt2.TransformBy(rotMat).Add(dbText.Position.GetAsVector());
    
                Line linetrans = new Line(pt1, pt2);
    
                linetrans.Color = Color.FromColor(System.Drawing.Color.Yellow) ;
    
                linetrans.ToSpace();
    
    
                Vector3d rotDir = new Vector3d(
    
                    -Math.Sin(dbText.Rotation),
    
                    Math.Cos(dbText.Rotation), 0);
    
    
                //求垂直于rotDir和normal的法向量
                Vector3d linDir = rotDir.CrossProduct(dbText.Normal);
    
    
    
                double actualWidth =
    
                    Math.Abs((pt2.GetAsVector() - pt1.GetAsVector())
    
                        .DotProduct(linDir));
    
    
    
                pt3 = pt1.Add(linDir * actualWidth);
    
                pt4 = pt2.Subtract(linDir * actualWidth);
    
                Line linetrans2 = new Line(pt3, pt4);
    
                linetrans2.Color = Color.FromColor(System.Drawing.Color.Blue);
    
                linetrans2.ToSpace();
            }
    
            #endregion
        }
  • 相关阅读:
    RHEL6中LVM逻辑卷管理
    Linux配置iSCSI存储
    Linux中FTP服务器配置
    360浏览器兼容模式下IE内核版本
    Ocelot + Consul + Registrator 基于Docker 实现服务发现、服务自动注册
    电视接入系统页面、监控页面
    Registrator中文文档
    关于Skyline沿对象画boundingbox的探讨
    EntityFramework实体默认值遇到Oracle自增主键
    C# 6.0 11个新特性
  • 原文地址:https://www.cnblogs.com/HelloQLQ/p/11921618.html
Copyright © 2011-2022 走看看