AutoCad 二次开发 文字镜像
本文讲解:“AutoCad 二次开发 文字镜像”以下是相关内容。
AutoCad 二次开发 文字镜像
参考:https://adndevblog.typepad.com/autocad/2013/10/mirroring-a-dbtext-entity.html 在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 Files\Autodesk\AutoCAD 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(
"\nSelect a text entity:");
peo.SetRejectMessage("\nMust be text entity...");
peo.AddAllowedClass(typeof(DBText), true);
PromptEntityResult perText = ed.GetEntity(peo);
if (perText.Status != PromptStatus.OK)
return;
peo = new PromptEntityOptions("\nSelect a mirror line:");
peo.SetRejectMessage("\nMust 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
}
温馨提示
以上就是“AutoCad 二次开发 文字镜像”这篇文章的所有内容了,相信大家也都认真的看完了,如果大家还有不懂的问题,可以通过搜索来获取更多相关的内容,最后记得给蓝图技术网小编点个赞以及收藏内容。免责声明:
1、本站所有资源文章出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
2、本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户擦亮眼睛自行鉴别,做一个有主见和判断力的用户。
3、本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。
4、侵权违法和不良信息举报 举报邮箱:cnddit@qq.com

还没有评论,来说两句吧...