jxzz016590 发表于 2011-6-1 10:20:58

我写的图纸框选程序,写的不好,想拿出来给大家批评指正一下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace KX
{
    public class KX
    {
      
      public void Select()
      {
            //获取当前文档,打开数据库
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = Application.DocumentManager.MdiActiveDocument.Database;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Point3dCollection vertex = SelectRectangleArea(doc);
            DBObjectCollection objects = SelectEntityInRectangleArea(doc,vertex);
            PromptPointResult promptPtResult = ed.GetPoint("\n选择要复制到的点");
            Point3d cpyPtn = promptPtResult.Value;
         
            foreach (Entity entity in objects)
            {
                if ( (entity is DBText) | (entity is MText) | (entity is DBPoint))
                {
                  //if (JudgeWhetherInRect(entity, vertex))
                  //{
                        CopyToNewPoint(entity, vertex, cpyPtn, doc);
                  //}
                }
                else if((entity is Line) | (entity is Polyline) |(entity is Circle)|(entity is Arc))
                {
                  MovePartOf(entity, vertex, cpyPtn, doc);
                }
                else
                {
                  DBObjectCollection newObjects = new DBObjectCollection();
                  entity.Explode(newObjects);
                  foreach (Entity ent in newObjects)
                  {
                        if (JudgeWhetherInRect(ent, vertex))
                        {
                            MovePartOf(ent, vertex, cpyPtn, doc);
                        }
                  }
                  newObjects.Dispose();
                }
            }
            objects.Dispose();
      }

      public static Point3dCollection SelectRectangleArea(Document doc)
      {
            Database db = doc.Database;
            PromptPointResult promptPointResult = doc.Editor.GetPoint("\n选择第一个点");
            Point3d ptStart = promptPointResult.Value;
            promptPointResult =
            doc.Editor.GetCorner("\n选择对角点", ptStart);
            Point3d ptEnd = promptPointResult.Value;
            Point3d point1 = ptStart;
            Point3d point2 = new Point3d(ptEnd.X, ptStart.Y, 0);
            Point3d point3 = ptEnd;
            Point3d point4 = new Point3d(ptStart.X, ptEnd.Y, 0);
            Point3dCollection points = new Point3dCollection();
            points.Add(point1);
            points.Add(point2);
            points.Add(point3);
            points.Add(point4);
            return points;
      }
      public static DBObjectCollection SelectEntityInRectangleArea(Document doc, Point3dCollection vertex)
      {
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Entity entity = null;
            DBObjectCollection entitys = new DBObjectCollection();
            PromptSelectionResult promptSelectResult = ed.SelectCrossingPolygon(vertex);
            if (promptSelectResult.Status == PromptStatus.OK)
            {
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                  SelectionSet ss = promptSelectResult.Value;
                  foreach (ObjectId id in ss.GetObjectIds())
                  {
                        entity = (Entity)trans.GetObject(id, OpenMode.ForWrite, true);
                        if (entity != null)
                        {
                            entitys.Add(entity);
                        }
                  }
                  trans.Commit();
                  trans.Dispose();
                }
            }
            return entitys;
      }
      public void CopyToNewPoint(Entity entity, Point3d sourcePt, Point3d targetPt, Document doc)
      {
            Vector3d vec = targetPt - sourcePt;
            Matrix3d mt = Matrix3d.Displacement(vec);
            Entity newEnt = entity.GetTransformedCopy(mt);
            Database db = doc.Database;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                btr.AppendEntity(newEnt);
                trans.AddNewlyCreatedDBObject(newEnt, true);
                trans.Commit();
            }
      }
      /// <summary>
      /// 计算曲线与选择框的交点
      /// </summary>
      /// <param name="vertexOfBoundary">选择框的顶点</param>
      /// <param name="curve">与选择框相交的曲线</param>
      /// <returns>交点集合</returns>
      public static Point3dCollection CalculateInstersection(Point3dCollection vertexOfBoundary, Curve curve)
      {
            Point3dCollection points = new Point3dCollection();
            Line line1 = new Line(vertexOfBoundary, vertexOfBoundary);
            Line line2 = new Line(vertexOfBoundary, vertexOfBoundary);
            Line line3 = new Line(vertexOfBoundary, vertexOfBoundary);
            Line line4 = new Line(vertexOfBoundary, vertexOfBoundary);
            //求所有交点,并将交点存入points集合中
            //Intersect.OnBothOperands表示不延伸相交
            Point3dCollection pts1 = new Point3dCollection();
            curve.IntersectWith(line1, Intersect.OnBothOperands, pts1, 0, 0);
            Point3dCollection pts2 = new Point3dCollection();
            curve.IntersectWith(line2, Intersect.OnBothOperands, pts2, 0, 0);
            Point3dCollection pts3 = new Point3dCollection();
            curve.IntersectWith(line3, Intersect.OnBothOperands, pts3, 0, 0);
            Point3dCollection pts4 = new Point3dCollection();
            curve.IntersectWith(line4, Intersect.OnBothOperands, pts4, 0, 0);
            foreach (Point3d pt in pts1)
            {
                if (pt != null)
                {
                  points.Add(pt);
                }
            }
            foreach (Point3d pt in pts2)
            {
                if (pt != null)
                {
                  points.Add(pt);
                }
            }
            foreach (Point3d pt in pts3)
            {
                if (pt != null)
                {
                  points.Add(pt);
                }
            }
            foreach (Point3d pt in pts4)
            {
                if (pt != null)
                {
                  points.Add(pt);
                }
            }
            return points;
      }
      /// <summary>
      /// 从交点处打断
      /// </summary>
      /// <param name="breakPoint">要打断的点</param>
      /// <param name="curve">要打断的曲线</param>
      /// <param name="db">当前数据库</param>
      /// <returns>打断后的曲线集合</returns>
      public static DBObjectCollection BreakCurve(Point3dCollection breakPoint, Curve curve, Database db)
      {
            DBObjectCollection curs = new DBObjectCollection();
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                if (breakPoint != null)
                {
                  Point3d[] pts = breakPoint.Cast<Point3d>().OrderBy(point => curve.GetDistAtPoint(point)).ToArray();
                  foreach (Point3d pt in pts)
                  {
                        breakPoint.Add(pt);
                  }
                  curs = curve.GetSplitCurves(breakPoint);
                }
            }
            return curs;
      }
      /// <summary>
      /// 平移到新的位置
      /// </summary>
      /// <param name="db">当前数据库</param>
      /// <param name="newobjects">要平移的对象</param>
      /// <param name="sourcePt">平移的基点</param>
      /// <param name="newPoint">平移的目标点</param>
      public static void MoveToNewPoint(Database db, Entity newobjects, Point3d sourcePt, Point3d newPoint)
      {
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(HostApplicationServices.WorkingDatabase.CurrentSpaceId, OpenMode.ForWrite);
                Vector3d vector = sourcePt.GetVectorTo(newPoint);
                newobjects.TransformBy(Matrix3d.Displacement(vector));
                btr.AppendEntity(newobjects);
                trans.AddNewlyCreatedDBObject(newobjects, true);
                trans.Commit();
            }
      }
      /// <summary>
      /// 判断是否在矩形范围内
      /// </summary>
      /// <param name="entity">要判断的实体</param>
      /// <param name="vertex">矩形顶点</param>
      /// <returns></returns>
      public static bool JudgeWhetherInRect(Entity entity, Point3dCollection vertex)
      {
            
            Point3d maxPt =new Point3d( entity.GeometricExtents.MaxPoint.X,entity.GeometricExtents.MaxPoint.Y,0);
            Point3d minPt = new Point3d(entity.GeometricExtents.MinPoint.X,entity.GeometricExtents.MinPoint.Y,0);
            bool judgeCondition = (maxPt.X >= vertex.X) & (maxPt.X <= vertex.X) & (maxPt.Y <= vertex.Y) & (maxPt.Y >= vertex.Y)
                & (minPt.X >= vertex.X) & (minPt.X <= vertex.X) & (minPt.Y <= vertex.Y) & (minPt.Y >= vertex.Y);
            return judgeCondition;
      }
      public void MovePartOf(Entity entity,Point3dCollection vertex,Point3d targetPt,Document doc)
      {
            Database db = doc.Database;
            Curve cve = (Curve)entity;
            
            Point3dCollection ptnOfIntersection = CalculateInstersection(vertex, cve);
            if (ptnOfIntersection.Count == 0)
            {
                CopyToNewPoint(entity, vertex, targetPt, doc);
            }
            else
            {
                DBObjectCollection newObjects = BreakCurve(ptnOfIntersection, cve, db);
                foreach (Entity ent in newObjects)
                {
                  //对打断后的曲线判断是否在矩形框内,若在就将其移到指定位置
                  if (JudgeWhetherInRect(ent, vertex))
                  {
                        MoveToNewPoint(db, ent, vertex, targetPt);
                  }
                }
            }
      }
    }
}

程序写的不好,如果大家能有什么改进的方法,请一定不吝指教。谢谢!

sieben 发表于 2011-6-1 12:11:05

1,你使用了SelectCrossingPolygon函数,做的事情其实是个矩形框选,为何不使用SelectCrossingWindow函数?
2,SelectEntityInRectangleArea 里面的事务打开了实体,打开的实体作为返回值在事务外被使用,这是很危险的
3,CalculateInstersection 函数要做的事情是求曲线与边界的交点,为什么不画一条多义线Polyline作为边界曲线,这样就不用一段一段的去求交点了
4,多说一句,不要想当然函数返回值一定是预期的,当返回值不是预期的时候怎么办?
5,再多说一句,使用SelectCrossing这类函数要注意要保证点在可视范围内.
6,最后一句,我没有详细看完代码.

jxzz016590 发表于 2011-6-1 13:59:31

谢谢楼上。我收缴了

jxzz016590 发表于 2011-6-1 14:00:57

希望能有人继续指正我的错误。这样我才能学到东西

jxzz016590 发表于 2011-6-1 14:20:21

还想再问一句怎么样才能不通过事物把选择集里面的实体存入对象集合里面呢?
页: [1]
查看完整版本: 我写的图纸框选程序,写的不好,想拿出来给大家批评指正一下