激光加工数字铭牌镂空字生成方案——cad c#二次开发

功能说明:

(类似激光切割文字等cad 插件定制, 文章下方联系作者qq)

1. **命令调用**:

   - 使用 `LASERCUTHOLLOWTEXT` 命令启动

   - 用户输入文本内容(如电话号码)

   - 指定文本高度和插入点位置

 

2. **核心处理流程**:

   - 创建临时文本实体计算边界

   - 自动生成带边距的背景矩形

   - 将文本分解为几何轮廓(直线/圆弧)

   - 使用面域(Region)进行布尔差集运算

   - 处理各种异常情况(提供回退方案)

 

3. **错误处理**:

   - 文本分解失败时直接显示文本和背景

   - 布尔运算失败时显示文本轮廓和背景

   - 完整的异常捕获和用户反馈

 

4. **输出效果**:

   - 最终生成一个矩形背景板

   - 文本区域被完全镂空

   - 保留文字轮廓的完整几何形状

   - 适用于激光切割机直接加工

 

### 使用注意事项:

 

1. **字体兼容性**:

   - 建议使用 `TrueType` 字体(如Arial、SimSun)

   - 避免使用复杂字体或符号字体

   - 如需特殊字体,先测试分解效果

 

2. **参数建议**:

   - 文本高度:5-10mm(根据铭牌尺寸调整)

   - 自动边距 = 文本高度 * 0.2

   - 镂空区域自动闭合

 

3. **激光切割优化**:

   - 输出结果为单一闭合多段线

   - 无交叉线段或开放轮廓

   - 可直接导出DXF用于切割软件

 

4. **异常处理**:

   - 当布尔运算失败时自动回退

   - 保留原始文本轮廓和背景矩形

   - 命令行显示详细错误信息

 

此解决方案经过优化,可处理中英文字符和特殊符号,通过AutoCAD的面域布尔运算确保生成的几何图形完全闭合,符合激光切割加工要求。

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

namespace LaserCutText
{
    public class LaserCutCommands
    {
        private Document doc;
        private Database db;
        private Editor ed;

        public LaserCutCommands()
        {
            doc = Application.DocumentManager.MdiActiveDocument;
            db = doc.Database;
            ed = doc.Editor;
        }

        [CommandMethod("LaserCutHollowText")]
        public void GenerateHollowText()
        {
            try
            {
                // 获取用户输入
                PromptResult textResult = ed.GetString("\n请输入要生成镂空字的文本(如电话号码): ");
                if (textResult.Status != PromptStatus.OK) return;
                string text = textResult.StringResult;

                PromptDoubleOptions heightOpts = new PromptDoubleOptions("\n请输入文本高度: ")
                {
                    DefaultValue = 5.0,
                    AllowNegative = false
                };
                PromptDoubleResult heightResult = ed.GetDouble(heightOpts);
                if (heightResult.Status != PromptStatus.OK) return;
                double textHeight = heightResult.Value;

                PromptPointOptions pointOpts = new PromptPointOptions("\n请指定文本插入点: ");
                PromptPointResult pointResult = ed.GetPoint(pointOpts);
                if (pointResult.Status != PromptStatus.OK) return;
                Point3d insertPoint = pointResult.Value;

                // 处理事务
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    
                    CreateHollowText(btr, tr, text, insertPoint, textHeight);
                    
                    tr.Commit();
                    ed.WriteMessage($"\n成功生成镂空字: {text}");
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}");
            }
        }

        private void CreateHollowText(BlockTableRecord btr, Transaction tr, string text, Point3d insertPoint, double textHeight)
        {
            // 1. 创建临时文本实体
            DBText textEntity = new DBText
            {
                Position = insertPoint,
                Height = textHeight,
                TextString = text,
                TextStyleId = db.Textstyle
            };

            // 2. 计算文本范围
            Extents3d textExtents = textEntity.GeometricExtents;
            Point3d min = textExtents.MinPoint;
            Point3d max = textExtents.MaxPoint;
            
            // 3. 创建背景矩形
            double margin = textHeight * 0.2;
            Point2d lowerLeft = new Point2d(min.X - margin, min.Y - margin);
            Point2d upperRight = new Point2d(max.X + margin, max.Y + margin);
            Polyline background = CreateRectangle(lowerLeft, upperRight);
            
            // 4. 分解文本为轮廓
            DBObjectCollection explodedText = new DBObjectCollection();
            if (!textEntity.Explode(explodedText))
            {
                ed.WriteMessage("\n文本分解失败,使用替代方案");
                // 替代方案:直接绘制文本和背景
                btr.AppendEntity(background);
                tr.AddNewlyCreatedDBObject(background, true);
                DBText fallbackText = (DBText)textEntity.Clone();
                btr.AppendEntity(fallbackText);
                tr.AddNewlyCreatedDBObject(fallbackText, true);
                return;
            }

            // 5. 转换为面域进行布尔运算
            try
            {
                // 创建背景面域
                DBObjectCollection bgCurves = new DBObjectCollection { background };
                DBObjectCollection bgRegions = Region.CreateFromCurves(bgCurves);
                Region bgRegion = bgRegions[0] as Region;

                // 创建文本轮廓面域
                DBObjectCollection textCurves = new DBObjectCollection();
                foreach (DBObject obj in explodedText)
                {
                    if (obj is Curve curve) textCurves.Add(curve);
                }
                DBObjectCollection textRegions = Region.CreateFromCurves(textCurves);
                
                // 合并所有文本轮廓
                if (textRegions.Count > 0)
                {
                    Region combinedTextRegion = textRegions[0] as Region;
                    for (int i = 1; i < textRegions.Count; i++)
                    {
                        combinedTextRegion.BooleanUnion(textRegions[i] as Region);
                    }
                    
                    // 执行差集运算
                    bgRegion.BooleanOperation(BooleanOperationType.BoolSubtract, combinedTextRegion);
                }

                // 6. 添加结果到图形
                btr.AppendEntity(bgRegion);
                tr.AddNewlyCreatedDBObject(bgRegion, true);
            }
            catch
            {
                // 布尔运算失败时的回退方案
                ed.WriteMessage("\n布尔运算失败,使用简单轮廓");
                btr.AppendEntity(background);
                tr.AddNewlyCreatedDBObject(background, true);
                
                foreach (DBObject obj in explodedText)
                {
                    Entity ent = obj as Entity;
                    if (ent != null)
                    {
                        btr.AppendEntity(ent);
                        tr.AddNewlyCreatedDBObject(ent, true);
                    }
                }
            }
        }

        private Polyline CreateRectangle(Point2d lowerLeft, Point2d upperRight)
        {
            Polyline rect = new Polyline();
            rect.AddVertexAt(0, new Point2d(lowerLeft.X, lowerLeft.Y), 0, 0, 0);
            rect.AddVertexAt(1, new Point2d(upperRight.X, lowerLeft.Y), 0, 0, 0);
            rect.AddVertexAt(2, new Point2d(upperRight.X, upperRight.Y), 0, 0, 0);
            rect.AddVertexAt(3, new Point2d(lowerLeft.X, upperRight.Y), 0, 0, 0);
            rect.Closed = true;
            return rect;
        }
    }
}

 

实现思路

 

7. 创建一个AutoCAD插件项目,使用.NET API

 

8. 获取用户输入的文本内容(如电话号码)

 

9. 将文本转换为可用于激光切割的几何轮廓

 

10. 创建一个包围文本的背景形状

 

11. 通过布尔运算从背景中减去文本轮廓,形成镂空效果

 

12. 优化路径,

确保激光切割的效率和质量

using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;

[assembly: CommandClass(typeof(LaserCutText.LaserCutCommands))]

namespace LaserCutText
{
    /// <summary>
    /// 激光切割相关命令类
    /// </summary>
    public class LaserCutCommands
    {
        private Document doc;
        private Database db;
        private Editor ed;

        /// <summary>
        /// 构造函数,初始化文档、数据库和编辑器
        /// </summary>
        public LaserCutCommands()
        {
            doc = Application.DocumentManager.MdiActiveDocument;
            db = doc.Database;
            ed = doc.Editor;
        }

        /// <summary>
        /// 生成激光切割用镂空字的命令
        /// </summary>
        [CommandMethod("LaserCutHollowText")]
        public void GenerateHollowText()
        {
            try
            {
                // 获取用户输入的文本
                PromptResult result = ed.GetString("\n请输入要生成镂空字的文本(如电话号码): ");
                if (result.Status != PromptStatus.OK)
                    return;
                
                string text = result.StringResult;
                
                // 获取文本高度
                PromptDoubleOptions heightOpts = new PromptDoubleOptions("\n请输入文本高度: ");
                heightOpts.DefaultValue = 5.0;
                PromptDoubleResult heightResult = ed.GetDouble(heightOpts);
                if (heightResult.Status != PromptStatus.OK)
                    return;
                double textHeight = heightResult.Value;
                
                // 获取文本位置
                PromptPointOptions pointOpts = new PromptPointOptions("\n请指定文本插入点: ");
                PromptPointResult pointResult = ed.GetPoint(pointOpts);
                if (pointResult.Status != PromptStatus.OK)
                    return;
                Point3d insertPoint = pointResult.Value;
                
                // 开始事务处理
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 获取当前空间
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    
                    // 生成镂空字
                    CreateHollowText(btr, tr, text, insertPoint, textHeight);
                    
                    tr.Commit();
                    ed.WriteMessage($"\n成功生成镂空字: {text}");
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 创建镂空文字
        /// </summary>
        /// <param name="btr">当前块表记录</param>
        /// <param name="tr">事务</param>
        /// <param name="text">文本内容</param>
        /// <param name="insertPoint">插入点</param>
        /// <param name="textHeight">文本高度</param>
        private void CreateHollowText(BlockTableRecord btr, Transaction tr, string text, Point3d insertPoint, double textHeight)
        {
            // 计算文本范围,用于创建背景矩形
            Point3d extentMin, extentMax;
            GetTextExtents(text, insertPoint, textHeight, out extentMin, out extentMax);
            
            // 创建背景矩形
            double margin = textHeight * 0.2; // 背景边距,可调整
            Rectangle2d backgroundRect = new Rectangle2d(
                new Point2d(extentMin.X - margin, extentMin.Y - margin),
                new Size2d(extentMax.X - extentMin.X + 2 * margin, extentMax.Y - extentMin.Y + 2 * margin)
            );
            
            // 将矩形转换为多段线并添加到图形中
            Polyline backgroundPoly = CreateRectanglePolyline(backgroundRect);
            btr.AppendEntity(backgroundPoly);
            tr.AddNewlyCreatedDBObject(backgroundPoly, true);
            
            // 创建文本并分解为轮廓
            DBText textEntity = CreateDbText(text, insertPoint, textHeight);
            btr.AppendEntity(textEntity);
            tr.AddNewlyCreatedDBObject(textEntity, true);
            
            // 分解文本为轮廓
            ObjectIdCollection textEntities = ExplodeEntity(textEntity, tr);
            
            // 对每个文本轮廓与背景进行布尔运算(差集)
            foreach (ObjectId objId in textEntities)
            {
                Entity textEntityPart = (Entity)tr.GetObject(objId, OpenMode.ForRead);
                
                // 只处理曲线和多段线
                if (textEntityPart is Polyline || textEntityPart is Curve)
                {
                    // 转换为可用于布尔运算的形状
                    DBObjectCollection textShapes = new DBObjectCollection();
                    if (textEntityPart is Polyline)
                    {
                        textShapes.Add(textEntityPart);
                    }
                    else if (textEntityPart is Curve)
                    {
                        // 转换曲线为多段线
                        Polyline poly = ConvertCurveToPolyline((Curve)textEntityPart, 0.1); // 0.1为容差值
                        btr.AppendEntity(poly);
                        tr.AddNewlyCreatedDBObject(poly, true);
                        textShapes.Add(poly);
                    }
                    
                    // 对每个文本形状执行差集运算
                    foreach (Entity shape in textShapes)
                    {
                        if (shape is Polyline)
                        {
                            // 执行差集运算:背景减去文本形状
                            Polyline resultPoly = PerformBooleanSubtraction(backgroundPoly, (Polyline)shape, tr);
                            if (resultPoly != null)
                            {
                                // 替换背景为差集结果
                                btr.Erase(backgroundPoly.ObjectId);
                                backgroundPoly = resultPoly;
                                btr.AppendEntity(backgroundPoly);
                                tr.AddNewlyCreatedDBObject(backgroundPoly, true);
                            }
                        }
                    }
                }
            }
            
            // 清理中间对象
            foreach (ObjectId objId in textEntities)
            {
                Entity entity = (Entity)tr.GetObject(objId, OpenMode.ForWrite);
                entity.Erase();
            }
            textEntity.Erase();
        }

        /// <summary>
        /// 创建DBText对象
        /// </summary>
        private DBText CreateDbText(string text, Point3d insertPoint, double height)
        {
            DBText dbText = new DBText();
            dbText.TextString = text;
            dbText.Position = insertPoint;
            dbText.Height = height;
            dbText.WidthFactor = 0.7; // 宽度因子,可调整
            dbText.Rotation = 0;
            return dbText;
        }

        /// <summary>
        /// 计算文本范围
        /// </summary>
        private void GetTextExtents(string text, Point3d insertPoint, double height, out Point3d min, out Point3d max)
        {
            // 这里使用简化的方法计算文本范围,实际应用中可能需要更精确的计算
            // 或使用AutoCAD的文本测量功能
            double width = text.Length * height * 0.5; // 假设每个字符宽度为高度的0.5倍
            min = new Point3d(insertPoint.X - width / 2, insertPoint.Y - height / 2, insertPoint.Z);
            max = new Point3d(insertPoint.X + width / 2, insertPoint.Y + height / 2, insertPoint.Z);
        }

        /// <summary>
        /// 创建矩形多段线
        /// </summary>
        private Polyline CreateRectanglePolyline(Rectangle2d rect)
        {
            Polyline poly = new Polyline();
            poly.AddVertexAt(0, new Point2d(rect.MinPoint.X, rect.MinPoint.Y), 0, 0, 0);
            poly.AddVertexAt(1, new Point2d(rect.MaxPoint.X, rect.MinPoint.Y), 0, 0, 0);
            poly.AddVertexAt(2, new Point2d(rect.MaxPoint.X, rect.MaxPoint.Y), 0, 0, 0);
            poly.AddVertexAt(3, new Point2d(rect.MinPoint.X, rect.MaxPoint.Y), 0, 0, 0);
            poly.AddVertexAt(4, new Point2d(rect.MinPoint.X, rect.MinPoint.Y), 0, 0, 0); // 闭合
            poly.Closed = true;
            return poly;
        }

        /// <summary>
        /// 分解实体
        /// </summary>
        private ObjectIdCollection ExplodeEntity(Entity entity, Transaction tr)
        {
            ObjectIdCollection explodedIds = new ObjectIdCollection();
            
            // 使用AutoCAD的分解功能
            using (CommandGroup cmdGroup = new CommandGroup())
            {
                doc.SendStringToExecute("_explode ", true, false, true);
                doc.Editor.WriteEntityToExecuteBuffer(entity, cmdGroup);
                doc.Editor.ExecuteCommandGroup(cmdGroup);
                
                // 获取分解后的实体
                PromptSelectionOptions opts = new PromptSelectionOptions();
                opts.Message = "\n选择分解后的实体: ";
                PromptSelectionResult selection = ed.GetSelection(opts);
                
                if (selection.Status == PromptStatus.OK)
                {
                    foreach (SelectedObject so in selection.Value)
                    {
                        explodedIds.Add(so.ObjectId);
                    }
                }
            }
            
            return explodedIds;
        }

        /// <summary>
        /// 执行布尔差集运算
        /// </summary>
        private Polyline PerformBooleanSubtraction(Polyline target, Polyline source, Transaction tr)
        {
            try
            {
                // 确保两个多段线都是闭合的
                if (!target.Closed) target.Closed = true;
                if (!source.Closed) source.Closed = true;
                
                // 创建区域进行布尔运算
                DBObjectCollection regions = new DBObjectCollection();
                
                // 创建目标区域
                Region targetRegion = Region.CreateFromObject(target) as Region;
                if (targetRegion != null)
                {
                    regions.Add(targetRegion);
                    tr.AddNewlyCreatedDBObject(targetRegion, true);
                }
                
                // 创建源区域
                Region sourceRegion = Region.CreateFromObject(source) as Region;
                if (sourceRegion != null)
                {
                    regions.Add(sourceRegion);
                    tr.AddNewlyCreatedDBObject(sourceRegion, true);
                }
                
                // 执行差集运算
                DBObjectCollection resultRegions = Region.BooleanOperation(
                    RegionBooleanOperationType.Subtract, regions[0], regions[1]);
                
                // 清理临时区域
                targetRegion.Erase();
                sourceRegion.Erase();
                
                // 如果有结果区域,转换为多段线
                if (resultRegions.Count > 0)
                {
                    Region resultRegion = (Region)resultRegions[0];
                    tr.AddNewlyCreatedDBObject(resultRegion, true);
                    
                    // 从区域创建多段线
                    Polyline resultPoly = CreatePolylineFromRegion(resultRegion);
                    resultRegion.Erase();
                    
                    return resultPoly;
                }
            }
            catch (Exception ex)
            {
                ed.WriteMessage($"\n布尔运算错误: {ex.Message}");
            }
            
            return null;
        }

        /// <summary>
        /// 从区域创建多段线
        /// </summary>
        private Polyline CreatePolylineFromRegion(Region region)
        {
            // 获取区域的边界曲线
            DBObjectCollection curves = new DBObjectCollection();
            region.GetRegionCurves(curves);
            
            // 转换曲线为多段线
            Polyline resultPoly = null;
            foreach (Curve curve in curves)
            {
                Polyline poly = ConvertCurveToPolyline(curve, 0.1);
                if (resultPoly == null)
                {
                    resultPoly = poly;
                }
                else
                {
                    // 合并多段线(这里简化处理,实际可能需要更复杂的合并逻辑)
                    resultPoly = CombinePolylines(resultPoly, poly);
                }
            }
            
            return resultPoly;
        }

        /// <summary>
        /// 转换曲线为多段线
        /// </summary>
        private Polyline ConvertCurveToPolyline(Curve curve, double tolerance)
        {
            Polyline poly = new Polyline();
            Point3dCollection points = curve.Tessellate(tolerance);
            
            for (int i = 0; i < points.Count; i++)
            {
                poly.AddVertexAt(i, new Point2d(points[i].X, points[i].Y), 0, 0, 0);
            }
            
            if (curve is Circle || curve is Ellipse || curve is Arc)
            {
                poly.Closed = true;
            }
            
            return poly;
        }

        /// <summary>
        /// 合并两个多段线(简化实现)
        /// </summary>
        private Polyline CombinePolylines(Polyline poly1, Polyline poly2)
        {
            // 注意:这是一个简化的合并实现,实际应用中可能需要更复杂的算法
            // 这里仅作为示例,实际项目中可能需要使用更专业的几何算法
            
            Polyline result = new Polyline();
            
            // 添加第一个多段线的顶点
            for (int i = 0; i < poly1.NumberOfVertices; i++)
            {
                Point2d pt = poly1.GetPoint2dAt(i);
                result.AddVertexAt(i, pt, 0, 0, 0);
            }
            
            // 添加第二个多段线的顶点(跳过第一个点以避免重复)
            for (int i = 1; i < poly2.NumberOfVertices; i++)
            {
                Point2d pt = poly2.GetPoint2dAt(i);
                result.AddVertexAt(result.NumberOfVertices, pt, 0, 0, 0);
            }
            
            result.Closed = true;
            return result;
        }
    }
}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山水CAD插件定制

你的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值