明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
楼主: cairunbin

[资源] 高手写的自动裁剪程序,C#源码

  [复制链接]
发表于 2021-2-24 08:29 | 显示全部楼层
cairunbin 发表于 2021-1-12 21:50
你下载一个新版WinRAR就行了。

楼主你好,我安装了最新版的WinRAR v6.0都打不开
 楼主| 发表于 2021-2-24 11:23 | 显示全部楼层
kosan 发表于 2021-2-24 08:29
楼主你好,我安装了最新版的WinRAR v6.0都打不开

我刚试了一下,文件好像是坏了。
我试着重新上传,系统提示不成功。
估计是网站服务器的问题。
 楼主| 发表于 2021-2-24 11:32 | 显示全部楼层
kosan 发表于 2021-2-24 08:29
楼主你好,我安装了最新版的WinRAR v6.0都打不开

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;

namespace mExTrim
{
    public class Class1
    {
        Editor m_ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
        Database m_db = HostApplicationServices.WorkingDatabase;

        [CommandMethod("MEXTRIM")]
        public void m_ExPressTrim()
        {
            #region 选择剪切边界实体
            PromptEntityResult m_Per = null;
            if (!m_SelectEntity("选择裁剪实体", "", new Type[] { typeof(Entity) }, ref m_Per)) return;

            Entity m_TrimEdgeEnt = (Entity)m_OpenEntity(m_Per.ObjectId);//剪切边界实体
            Curve m_TrimEdge = m_TrimEdgeEnt as Curve;
            if (m_TrimEdge == null)
                m_TrimEdge = m_CreateRectangle(m_TrimEdgeEnt.GeomExtents.MinPoint, m_TrimEdgeEnt.GeomExtents.MaxPoint, false);
            #endregion

            #region 选择剪切方向
            Point3d m_Pt = new Point3d();
            if (!m_GetPoint("\n剪切方向", ref m_Pt, new Point3d(), false, false)) return;

            Point3d m_Pt1 = m_TrimEdge.GetClosestPointTo(m_Pt, false);//曲线外一点距曲线最近的点
            Vector3d m_Vect = m_TrimEdge.GetFirstDerivative(m_Pt1);//曲线上此点的切向量
            int m_Direct = m_PtSide(m_Pt1.Convert2d(new Plane()), m_Pt1.Add(m_Vect).Convert2d(new Plane()), m_Pt.Convert2d(new Plane()));//裁剪方向
            #endregion


            //选择与剪切边包围的所有实体
            PromptSelectionResult m_psr = m_ed.SelectCrossingWindow(m_TrimEdge.GeomExtents.MinPoint, m_TrimEdge.GeomExtents.MaxPoint);

            #region 剪切
            int i = 0;
            foreach (ObjectId objid in m_psr.Value.GetObjectIds())
            {
                if (!objid.Equals(m_Per.ObjectId))
                {
                    Curve m_Cur = m_OpenEntity(objid) as Curve;
                    if (m_Cur != null)//判断是否曲线实体
                    {
                        if (m_Cur is Polyline2d)
                            m_Cur = m_Polyline2dToLWPolyline(objid);//二维多段线转换为轻量多段线

                        DBObjectCollection m_ObjColl = new DBObjectCollection();
                        if (m_TrimCurve(m_Cur, m_TrimEdge, m_Direct, ref m_ObjColl))
                        {
                            foreach (Entity ent in m_ObjColl) m_CreateEntity(ent);
                            m_EraseEntity(objid);
                        }
                    }
                }
                m_ed.WriteMessage("\r正在裁剪...已完成{0}%", ((double)(++i * 100.0 / m_psr.Value.GetObjectIds().GetLength(0))).ToString("0"));
            }
            #endregion

        }
        private bool m_TrimCurve(Curve m_Cur, Entity m_TrimEdgeEnt, int m_Direction, ref DBObjectCollection m_ObjColl)
        {
            //m_Cur —被剪曲线;m_TrimEdge  —剪切边界曲线
            //m_Direction —剪切方向,只能是1或-1,1—剪掉边界曲线右边的线,-1—剪左边
            //返回true  —剪切成功,保留的实体保存在m_ObjColl中

            //判断被剪曲线是否位于锁定图层上
            LayerTableRecord m_ltr = (LayerTableRecord)m_OpenEntity(m_Cur.LayerId);
            if (m_ltr.IsLocked) return false;

            if (!(m_TrimEdgeEnt is Curve))//剪切实体不是曲线类,则用其边界框做为剪切边界
                m_TrimEdgeEnt = m_CreateRectangle(m_TrimEdgeEnt.GeomExtents.MinPoint, m_TrimEdgeEnt.GeomExtents.MaxPoint, false);
            Curve m_TrimEdge = m_TrimEdgeEnt as Curve;

            bool m_ReturnFlag = true;
            m_ObjColl = new DBObjectCollection();//初始化为空

            Point3dCollection m_InterPts = m_GetIntersectPoints(m_Cur, (Curve)m_TrimEdge);//求被剪曲线与剪切边的交点
            if (m_InterPts.Count > 0)//判断曲线是否与剪切边相交
            {
                try
                {
                    #region 生成交点处拆分的实体集合
                    DBObjectCollection m_Objs = new DBObjectCollection();
                    m_Objs = m_Cur.GetSplitCurves(m_InterPts);//拆分曲线实体
                    #endregion

                    #region 对拆分实体集合中各实体进行判断,那些需要保留
                    foreach (Curve cur in m_Objs)
                    {
                        ObjectId m_CurId = m_CreateEntity(cur);//先生成实体,主要是三维多段线有问题,EndPoint属性老是错误!!!
                        Curve m_CurNew = m_OpenEntity(m_CurId) as Curve;

                        double m_Param = m_CurNew.StartParam + 0.0001;
                        if (!m_InterPts.Contains(m_CurNew.StartPoint))//点不是交点
                            m_Param = m_CurNew.EndParam - 0.0001;

                        Point3d m_Pt1 = m_CurNew.GetPointAtParameter(m_Param);
                        Point3d m_Pt2 = m_TrimEdge.GetClosestPointTo(m_Pt1, false);
                        Vector3d m_Vect = m_TrimEdge.GetFirstDerivative(m_Pt2);

                        int m_Direct = m_PtSide(m_Pt2.Convert2d(new Plane()), m_Pt2.Add(m_Vect).Convert2d(new Plane()), m_Pt1.Convert2d(new Plane()));
                        if (m_Direct != m_Direction) m_ObjColl.Add((DBObject)m_CurNew.Clone());//保存被剪之后的新实体

                        m_EraseEntity(m_CurId);
                    }
                    #endregion
                }
                catch
                {
                    m_ReturnFlag = false;
                }
            }
            else
                m_ReturnFlag = false;

            return m_ReturnFlag;
        }

 楼主| 发表于 2021-2-24 11:32 | 显示全部楼层
cairunbin 发表于 2021-2-24 11:32
using System;
using System.IO;
using System.Collections;

        #region 公共函数
        //创建实体,把实体加入CAD数据库
        public ObjectId m_CreateEntity(Entity m_entity)
        {
            ObjectId m_objid = new ObjectId();
            if (m_entity != null)
            {
                using (Application.DocumentManager.MdiActiveDocument.LockDocument())
                {
                    using (Transaction m_tr = m_db.TransactionManager.StartTransaction())
                    {
                        BlockTableRecord m_btr = (BlockTableRecord)m_tr.GetObject(m_db.CurrentSpaceId, OpenMode.ForWrite, false);
                        m_objid = m_btr.AppendEntity(m_entity);
                        m_tr.AddNewlyCreatedDBObject(m_entity, true);
                        m_tr.Commit();
                    }
                }
            }
            return m_objid;
        }

        //删除实体
        public void m_EraseEntity(ObjectId m_EntityId)
        {
            using (DocumentLock m_doclock = Application.DocumentManager.MdiActiveDocument.LockDocument())
            {
                if (!m_EntityId.IsNull && !m_EntityId.IsErased)
                {
                    Entity m_Ent = m_OpenEntity(m_EntityId) as Entity;
                    LayerTableRecord m_ltr = (LayerTableRecord)m_OpenEntity(m_Ent.LayerId);
                    if (!m_ltr.IsLocked)//实体不在锁定图层上
                    {
                        using (Transaction m_tr = m_db.TransactionManager.StartTransaction())
                        {
                            try
                            {
                                Entity m_Entity = (Entity)m_tr.GetObject(m_EntityId, OpenMode.ForWrite, false);
                                if (m_Entity != null) m_Entity.Erase();
                            }
                            catch { }
                            m_tr.Commit();
                        }
                    }
                }
            }
        }
        public void m_EraseEntity(Entity m_Entity)
        {
            using (DocumentLock m_doclock = Application.DocumentManager.MdiActiveDocument.LockDocument())
            {
                if (m_Entity != null) m_Entity.Erase();
                else m_Entity.Dispose();
            }
        }

        //打开实体
        public Object m_OpenEntity(ObjectId m_ObjId)
        {
            Object m_Obj = new Object();
            if (!m_ObjId.IsNull)
            {
                using (Transaction m_tr = m_db.TransactionManager.StartTransaction())
                {
                    m_Obj = (Object)m_tr.GetObject(m_ObjId, OpenMode.ForRead);
                    m_tr.Commit();
                }
            }

            return m_Obj;
        }

        //生成矩形
        public Autodesk.AutoCAD.DatabaseServices.Polyline m_CreateRectangle(Point3d m_Pt1, Point3d m_Pt2, bool m_bLUorLW)
        {
            if (!m_bLUorLW)//不是左上和右下点,而是左下点和右上点
            {
                Point3d m_Pt3 = m_Pt1, m_Pt4 = m_Pt2;
                m_Pt1 = new Point3d(m_Pt3.X, m_Pt4.Y, 0);
                m_Pt2 = new Point3d(m_Pt4.X, m_Pt3.Y, 0);
            }

            Autodesk.AutoCAD.DatabaseServices.Polyline m_lwpline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            m_lwpline.AddVertexAt(0, m_Pt1.Convert2d(new Plane()), 0, 0, 0);
            m_lwpline.AddVertexAt(1, new Point2d(m_Pt2.X, m_Pt1.Y), 0, 0, 0);
            m_lwpline.AddVertexAt(2, m_Pt2.Convert2d(new Plane()), 0, 0, 0);
            m_lwpline.AddVertexAt(3, new Point2d(m_Pt1.X, m_Pt2.Y), 0, 0, 0);
            m_lwpline.Closed = true;
            return m_lwpline;
        }

        //提示用户输入一点
        public bool m_GetPoint(string m_Msg, ref Point3d m_Pt, Point3d m_BasePoint, bool m_AllowNone, bool m_UseBasePoint)
        {
            if (!m_Pt.Equals(new Point3d())) m_Msg += "<" + m_Pt.X.ToString() + "," + m_Pt.Y.ToString() + "," + m_Pt.Z.ToString() + ">";

            PromptPointOptions m_ppo = new PromptPointOptions("\n" + m_Msg);
            m_ppo.AllowNone = m_AllowNone;
            m_ppo.BasePoint = m_BasePoint;
            m_ppo.UseBasePoint = m_UseBasePoint;

            PromptPointResult m_ppr = m_ed.GetPoint(m_ppo);

            if (m_ppr.Status != PromptStatus.OK)
            {
                if (m_ppr.Status == PromptStatus.None) { m_Pt = m_BasePoint; return true; }
                else return false;
            }
            m_Pt = m_ppr.Value;

            return true;
        }

        //提示选择单个实体
        public bool m_SelectEntity(string m_MSG, string m_RejectMSG, Type[] m_EntityType, ref PromptEntityResult m_PER)
        {
            PromptEntityOptions m_peo = new PromptEntityOptions((m_MSG.Substring(0, 2).Equals("\n") ? m_MSG : "\n" + m_MSG));
            m_peo.SetRejectMessage(m_RejectMSG);
            foreach (Type et in m_EntityType) m_peo.AddAllowedClass(et, false);
            m_peo.AllowNone = true;

            m_PER = m_ed.GetEntity(m_peo);
            if (m_PER.Status != PromptStatus.OK) return false;
            else return true;
        }

        //判断点pt在直线pt1->Pt2的哪一侧?返回值:1右侧;0三点共线;-1左侧
        public int m_PtSide(Point2d pt1, Point2d pt2, Point2d pt)
        {
            Vector2d m_vect1 = pt1.GetVectorTo(pt2);
            Vector2d m_vect2 = pt1.GetVectorTo(pt);
            double m_value = m_vect2.X * m_vect1.Y - m_vect1.X * m_vect2.Y;
            if (Math.Abs(m_value) < 0.0000001) return 0;
            else if (m_value > 0) return 1;
            else return -1;
        }

        //求空间两曲线c1与c2在c1上的交点(带标高值)
        public Point3dCollection m_GetIntersectPoints(Curve c1, Curve c2)
        {
            Point3dCollection m_interpts = new Point3dCollection(), m_interpts1 = new Point3dCollection();
            Point3dCollection m_VertexPoints = new Point3dCollection();
            c1.IntersectWith(c2, Intersect.OnBothOperands, new Plane(), m_interpts, 0, 0);//求交点

            if (c1 is Polyline3d && !(c2 is Polyline3d))
            {
                foreach (Point3d pt in m_interpts)
                {
                    Polyline3d m_pl3d = new Polyline3d(Poly3dType.SimplePoly,
                        new Point3dCollection(new Point3d[] { pt, pt.Add(new Vector3d(0, 0, 10)) }), false);

                    Point3dCollection m_Pts = new Point3dCollection();
                    c1.IntersectWith(m_pl3d, Intersect.ExtendArgument, new Plane(), m_Pts, 0, 0);
                    foreach (Point3d pt1 in m_Pts) m_interpts1.Add(pt1);
                }
                m_interpts = m_interpts1;
            }

            //去掉不正确的交点(IntersectWith求出的交点有可能不正确!!!)
            ArrayList m_DistPtList = new ArrayList();
            foreach (Point3d pt in m_interpts)
            {
                try
                {
                    double m_Dist = c1.GetDistAtPoint(pt);//点是否在曲线上?
                    m_DistPoint3d m_DP = new m_DistPoint3d();
                    m_DP.m_dist = m_Dist;
                    m_DP.m_pt = pt;
                    m_DistPtList.Add(m_DP);
                }
                catch { }
            }

            m_DistPtList.Sort(new m_DistPtsSort());//排序
            m_interpts1 = new Point3dCollection();
            foreach (m_DistPoint3d dp in m_DistPtList) m_interpts1.Add(dp.m_pt);

            return m_interpts1;
        }
        private struct m_DistPoint3d
        {
            public double m_dist;
            public Point3d m_pt;
        }
        private class m_DistPtsSort : IComparer
        {
            int IComparer.Compare(object a, object b)
            {
                m_DistPoint3d dp1 = (m_DistPoint3d)a;
                m_DistPoint3d dp2 = (m_DistPoint3d)b;
                if (dp1.m_dist > dp2.m_dist)
                    return 1;
                if (dp1.m_dist < dp2.m_dist)
                    return -1;
                else
                    return 0;
            }
        }

        //二维多段线转换为轻量多段线
        public Autodesk.AutoCAD.DatabaseServices.Polyline m_Polyline2dToLWPolyline(ObjectId m_ObjId)
        {
            Autodesk.AutoCAD.DatabaseServices.Polyline m_pl = new Autodesk.AutoCAD.DatabaseServices.Polyline();

            Polyline2d m_pl2d = m_OpenEntity(m_ObjId) as Polyline2d;
            if (m_pl2d != null)
            {
                switch (m_pl2d.PolyType)
                {
                    case Poly2dType.FitCurvePoly:
                        m_pl.ConvertFrom(m_pl2d, false);
                        break;
                    case Poly2dType.SimplePoly:
                    case Poly2dType.CubicSplinePoly:
                    case Poly2dType.QuadSplinePoly:
                        int index = 0;
                        foreach (ObjectId vid in m_pl2d)
                        {
                            Vertex2d v2d = m_OpenEntity(vid) as Vertex2d;
                            if (v2d.VertexType != Vertex2dType.SplineControlVertex)
                                m_pl.AddVertexAt(index++, new Point2d(v2d.Position.X, v2d.Position.Y), 0, v2d.StartWidth, v2d.EndWidth);
                        }
                        m_pl.LayerId = m_pl2d.LayerId;//继承层属性
                        m_pl.Elevation = m_pl2d.Elevation;//继承高程属性
                        m_pl.LinetypeId = m_pl2d.LinetypeId;//继承线型属性
                        m_pl.ColorIndex = m_pl2d.ColorIndex;//继承颜色属性
                        break;
                    default:
                        break;
                }
            }
            return m_pl;
        }
        #endregion
    }
}
 楼主| 发表于 2021-2-24 11:33 | 显示全部楼层
kosan 发表于 2021-2-24 08:29
楼主你好,我安装了最新版的WinRAR v6.0都打不开

直接发源码了。
回复 支持 1 反对 0

使用道具 举报

发表于 2021-12-11 19:57 | 显示全部楼层
请问楼主,含圆弧二维多端线转换为轻量多段线,有啥好的思路没
 楼主| 发表于 2021-12-12 08:33 | 显示全部楼层
成精的熊大 发表于 2021-12-11 19:57
请问楼主,含圆弧二维多端线转换为轻量多段线,有啥好的思路没

您说的轻量多段线,就是Polyline类对象吗?
Polyline.AddVertexAt方法,可以定义顶点为圆弧。
发表于 2021-12-12 13:25 | 显示全部楼层
cairunbin 发表于 2021-12-12 08:33
您说的轻量多段线,就是Polyline类对象吗?
Polyline.AddVertexAt方法,可以定义顶点为圆弧。

谢谢
发表于 2021-12-14 13:21 | 显示全部楼层
非常感谢正想写个类似于cass自带批量生成宗地图的功能 希望能有所启发  还发下你发的cad加载大影像 那个可以用c#开发吗  不会c++
 楼主| 发表于 2021-12-14 16:30 | 显示全部楼层
852456 发表于 2021-12-14 13:21
非常感谢正想写个类似于cass自带批量生成宗地图的功能 希望能有所启发  还发下你发的cad加载大影像 那个可 ...

大影像的用C#可能不行。我用的是只有C++支持的自定义实体。不知道在C#下是否有类似技术。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-5-5 11:43 , Processed in 0.450572 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表