找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 4418|回复: 1

[分享] PickFirst Set (ImpliedSelection) & Editor.SelectWindow & PointCollector

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-5-18 18:59:27 来自手机 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 csharp 于 2014-5-18 20:24 编辑

http://spiderinnet1.typepad.com/blog/2012/09/autocad-net-pickfirst-set-impliedselection-editorselectwindow-pointcollector.html
We demonstrated about some AutoCAD selection set building APIs such as the Editor.SelectFence, Editor.SelectWindow, and the Editor.SelectCrossingWindow before. We also presented the simple but cool PointCollector coder along, which supports a few selection modes such as Fence, Window, Polygon, Regular Polygon, and Circular.
Now let’s see how to use AutoCAD .NET selection set APIs and the PointCollector coder together to select some entities and merge them into the PickFirst selection set (the AutoCAD .NET API term ImpliedSelection) when existing.
[CommandMethod("SelectWindowWithPointCollectorAndPickFirst", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)]
public static void SelectWindowWithPointCollectorAndPickFirst_Method()
{
    Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
    try
    {
        using (PointCollector pc = new PointCollector(PointCollector.Shape.Window))
        {
            Point3dCollection points = pc.Collect();
            PromptSelectionResult prSelRes = ed.SelectWindow(points[0], points[1]);
            if (prSelRes.Status == PromptStatus.OK)
            {
                List<ObjectId> ids = new List<ObjectId>();
                using (SelectionSet ss = prSelRes.Value)
                {
                    using (SelectionSet pickFirst = ed.SelectImplied().Value)
                    {
                        if (ss != null && ss.Count > 0)
                            ids.AddRange(ss.GetObjectIds());
                        if (pickFirst != null && pickFirst.Count > 0)
                            ids.AddRange(pickFirst.GetObjectIds());
                        if (ids.Count > 0)
                        {
                            ed.SetImpliedSelection(ids.ToArray());
                            ed.WriteMessage("\nPress ENTER to contine (delete them) ...");
                            MgdAcApplication.DocumentManager.MdiActiveDocument.SendStringToExecute("(getstring)(command \"Erase\") ", false, false, false);
                        }
                    }
                }
            }
            else
                ed.WriteMessage("\nSelection failed!");
        }
    }
    catch (System.Exception ex)
    {
        ed.WriteMessage(Environment.NewLine + ex.ToString());
    }
}
The code of the PointCollector coder has not been appended here for brevity purpose. Please refer to earlier posts for details about it. Here is how the command behaves in AutoCAD.
    0.jpg
As can be seen, before our command ran, two line segments had already been pre-selected into the so called default PickFirst selection set (the Implied Selection in AutoCAD .NET term), and our command selected some more entities (in total three, two of which were circles and the remaining was rectangle) with the window option.   
After the window selection finished, the two pre-selected line segments plug the newly selected three entities would be merged into the new PickFirst set as highlighted, and the command line window prompted us to press Enter to continue.
   1.jpg
After the Enter was pressed, they would all be deleted by the ERASE command that was sent out to the AutoCAD command line window through code.
Command:
Command:
Command: SELECTWINDOWWITHPOINTCOLLECTORANDPICKFIRST
The 1st corner:
The 2nd corner:
Press ENTER to contine (delete them) ...
Command:
Erase nil
5 found
By the way, the first two empty lines were for the pre picking operations. There was a typo in the prompt string. Please bear it with me. Here is what the screen looked like at this moment.
   2.jpg
All these seem simple and natural, but quite some points have not been revealed yet.
&#8226; The command flags, CommandFlags.UsePickSet | CommandFlags.Redraw, here play key roles.
&#8226; The CommandFlags.UsePickSet indicates that the pre-picked-selection-set (PickFirst/FirstPick set or ImpliedSelection) will be honored through the Editor.SelectImplied() API call as demonstrated.
&#8226; The CommandFlags.Redraw indicates that the pre-picked-selection-set (PickFirst/FirstPick set or ImpliedSelection) can and will be updated through another API call, Editor.SetImpliedSelection, if applicable, as also demonstrated.
&#8226; Please note the PickFirst (ImpliedSelection) keep updated even after the command finishes, as suggested by the CommandFlags.Redraw.
&#8226; If the CommandFlags.Redraw were not specified for the test command, the PickFirst set (ImpliedSelection) would be cleared out when the command finished thus the ERASE command would wait for something to operate on. Please give it a try if interested in.
&#8226; The SelectWindow API does not return those pre-selected entities in this case since the picked window does not contain them. It makes sense here, otherwise would be unnatural.
&#8226; So the Editor.SelectImplied() is necessary to merge the two selection sets if that is what expected.
&#8226; If the SelectWindow did cover the two pre-selected line segments for example, they would be returned in the ss for sure, and the final ObjectId array would contain duplicate object ids, but that is not something we should worry about as the Editor.SetImpliedSelection() method takes care of this situation well.
&#8226; The ERASE command can pick up the updated PickFirst set (Implied Selection) because it runs after the command SelectWindowWithPointCollectorAndPickFirst finishes. That is what the MdiActiveDocument.SendStringToExecute() API is really about.
&#8226; Some measures have also been taken in the succinct code to look after the situations that the PickFirst set is valid or not.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 859个

财富等级: 财运亨通

 楼主| 发表于 2014-5-19 17:59:36 | 显示全部楼层
本帖最后由 csharp 于 2014-5-19 18:02 编辑

AutoCAD .NET: The PointCollector Coder (Collect Points by Fence/Window/Polygon/Regular Polygon/Circle Shapes) The .NET coder PointCollector has been demonstrated to work along with the AutoCAD .NET selection set APIs very well such as the Editor.SelectFence, Editor.SelectWindow, Editor.SelectCrossingWindow and Editor.SelectCrossingPolygon.
The PointCollector coder has been enhanced and refined greatly recently. Now it is more concise, more reliable, and more flexible. Here it is.
#region Namespaces
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;
using MgdAcApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using MgdAcDocument = Autodesk.AutoCAD.ApplicationServices.Document;
using AcWindowsNS = Autodesk.AutoCAD.Windows;
#endregion
using Autodesk.AutoCAD.GraphicsInterface;
namespace AcadNetAddinWizard_Namespace
{
    public class PointCollector : IDisposable
    {
        public enum Shape
        {
            Window,
            Fence,
            Polygon,
            RegularPolygon,
            Circle,
        }
        private Shape mShape;
        private Autodesk.AutoCAD.DatabaseServices.Polyline mTempPline;
        private short mColorIndex = 7;
        private TransientDrawingMode mMode;
        private int mSegmentCount = 36;
        
        private Point3d m1stPoint;
        private double mDist;
        public Point3dCollection CollectedPoints {  get; private set; }
        public PointCollector(Shape shape)
        {
            mShape = shape;
            switch (mShape)
            {
                case Shape.Fence:
                    mMode = TransientDrawingMode.Highlight;
                    break;
                case Shape.Window:
                case Shape.Polygon:
                case Shape.RegularPolygon:
                case Shape.Circle:
                    mMode = TransientDrawingMode.Contrast;
                    break;
                default:
                    mMode = TransientDrawingMode.Main;
                    break;
            }
            CollectedPoints = new Point3dCollection();
        }
        private void Editor_PointMonitor(object sender, PointMonitorEventArgs e)
        {
            if (mTempPline != null)
            {
                TransientManager.CurrentTransientManager.EraseTransient(mTempPline, new IntegerCollection());
                if (mTempPline != null && !mTempPline.IsDisposed)
                {
                    mTempPline.Dispose();
                    mTempPline = null;
                }
            }
            Point3d compPt = e.Context.ComputedPoint.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem.Inverse());
            if (mShape == Shape.Window)
            {
                BuildupWindowVertices(m1stPoint, compPt);
            }
            else if (mShape == Shape.Fence)
            {
                BuildupFenceVertices(compPt);
            }
            else if (mShape == Shape.Polygon)
            {
                BuildupPolygonVertices(compPt);
            }
            else if (mShape == Shape.RegularPolygon)
            {
                BuildupRegularPolygonVertices(compPt);
            }
            else if (mShape == Shape.Circle)
            {
                BuildupRegularPolygonVertices(compPt);
            }
            mTempPline.TransformBy(MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.CurrentUserCoordinateSystem);
            TransientManager.CurrentTransientManager.AddTransient(mTempPline, mMode, 0, new IntegerCollection());
        }
        public Point3dCollection Collect()
        {
            if (mShape == Shape.Window)
            {
                CollectWindowPoints();
            }
            else if (mShape == Shape.Fence)
            {
                CollectFencePoints();
            }
            else if (mShape == Shape.Polygon)
            {
                CollectPolygonPoints();
            }
            else if (mShape == Shape.RegularPolygon)
            {
                mSegmentCount = GetRegularPolygonSideCount();
                CollectRegularPolygonPoints();
            }
            else if (mShape == Shape.Circle)
            {
                CollectRegularPolygonPoints();
            }
            return CollectedPoints;
        }
        private int GetRegularPolygonSideCount()
        {
            PromptIntegerResult prPntRes;
            PromptIntegerOptions prPntOpt = new PromptIntegerOptions("");
            prPntOpt.AllowNone = true;
            prPntOpt.AllowArbitraryInput = true;
            prPntOpt.AllowNegative = false;
            prPntOpt.AllowZero = false;
            prPntOpt.DefaultValue = 5;
            prPntOpt.LowerLimit = 3;
            prPntOpt.Message = "\nRegular polygon side";
            prPntOpt.UpperLimit = 36;
            prPntOpt.UseDefaultValue = true;
            prPntRes = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetInteger(prPntOpt);
            if (prPntRes.Status == PromptStatus.OK)
                return prPntRes.Value;
            else
                throw new System.Exception("Regular polygon side input failed!");
        }
        private void BuildupRegularPolygonVertices(Point3d tempPt)
        {
            mTempPline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            mTempPline.SetDatabaseDefaults();
            mTempPline.Closed = true;
            mTempPline.ColorIndex = mColorIndex;
            mDist = m1stPoint.DistanceTo(tempPt);
            double angle = m1stPoint.GetVectorTo(tempPt).AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis));
            CollectedPoints.Clear();
            for (int i = 0; i < mSegmentCount; i++)
            {
                Point3d pt = m1stPoint.Add(new Vector3d(mDist * (Math.Cos(angle + Math.PI * 2 * i / mSegmentCount)),
                                                        mDist * (Math.Sin(angle + Math.PI * 2 * i / mSegmentCount)),
                                                        m1stPoint.Z));
                CollectedPoints.Add(pt);
                mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(pt.X, pt.Y), 0, 1, 1);
            }
        }
        private void CollectRegularPolygonPoints()
        {
            PromptPointResult prPntRes1;
            PromptPointOptions prPntOpt = new PromptPointOptions("\nCenter");
            prPntOpt.AllowNone = true;
            prPntRes1 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetPoint(prPntOpt);
            if (prPntRes1.Status == PromptStatus.OK)
                m1stPoint = prPntRes1.Value;
            else
                throw new System.Exception("Center picking failed!");
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor += Editor_PointMonitor;
            PromptDistanceOptions prPntOpt2 = new PromptDistanceOptions("");
            prPntOpt2.AllowArbitraryInput = true;
            prPntOpt2.AllowNegative = false;
            prPntOpt2.AllowNone = true;
            prPntOpt2.AllowZero = false;
            prPntOpt2.BasePoint = m1stPoint;
            prPntOpt2.DefaultValue = 10.0;
            prPntOpt2.Message = "\nRadius";
            prPntOpt2.Only2d = true;
            prPntOpt2.UseBasePoint = true;
            prPntOpt2.UseDashedLine = true;
            prPntOpt2.UseDefaultValue = true;
            PromptDoubleResult prPntRes2 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetDistance(prPntOpt2);
            if (prPntRes2.Status != PromptStatus.OK)
                throw new System.Exception("Radius input failed!");
            mDist = prPntRes2.Value;
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor -= Editor_PointMonitor;
        }
        private void CollectPolygonPoints()
        {
            PromptPointResult prPntRes1;
            PromptPointOptions prPntOpt = new PromptPointOptions("\nPolygon point: (Enter to finish)");
            prPntOpt.AllowNone = true;
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor += Editor_PointMonitor;
            do
            {
                prPntRes1 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetPoint(prPntOpt);
                if (prPntRes1.Status == PromptStatus.OK)
                {
                    m1stPoint = prPntRes1.Value;
                    CollectedPoints.Add(m1stPoint);
                }
                else if (prPntRes1.Status != PromptStatus.None)
                {
                    throw new System.Exception("Polygon point picking failed!");
                }
            } while (prPntRes1.Status == PromptStatus.OK);
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor -= Editor_PointMonitor;
        }
        private void BuildupPolygonVertices(Point3d tempPt)
        {
            mTempPline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            mTempPline.SetDatabaseDefaults();
            mTempPline.Closed = true;
            mTempPline.ColorIndex = mColorIndex;
            foreach (Point3d pt in CollectedPoints)
            {
                mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(pt.X, pt.Y), 0, 1, 1);
            }
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(tempPt.X, tempPt.Y), 0, 1, 1);
        }
        private void CollectFencePoints()
        {
            PromptPointResult prPntRes1;
            PromptPointOptions prPntOpt = new PromptPointOptions("\nFence point (Enter to finish)");
            prPntOpt.AllowNone = true;
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor += Editor_PointMonitor;
            do
            {
                prPntRes1 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetPoint(prPntOpt);
                if (prPntRes1.Status == PromptStatus.OK)
                {
                    m1stPoint = prPntRes1.Value;
                    CollectedPoints.Add(m1stPoint);
                }
            } while (prPntRes1.Status == PromptStatus.OK);
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor -= Editor_PointMonitor;
        }
        private void BuildupFenceVertices(Point3d tempPt)
        {
            mTempPline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            mTempPline.SetDatabaseDefaults();
            mTempPline.Closed = false;
            mTempPline.ColorIndex = mColorIndex;
            foreach (Point3d pt in CollectedPoints)
            {
                mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(pt.X, pt.Y), 0, 1, 1);
            }
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(tempPt.X, tempPt.Y), 0, 1, 1);
        }
        private void CollectWindowPoints()
        {
            PromptPointResult prPntRes1 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetPoint("\nThe 1st corner");
            if (prPntRes1.Status != PromptStatus.OK)
                throw new System.Exception("The 1st corner picking failed!");
            m1stPoint = prPntRes1.Value;
            CollectedPoints.Add(m1stPoint);
            BuildupWindowVertices(m1stPoint, m1stPoint);
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor += Editor_PointMonitor;
            PromptPointResult prPntRes2 = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.GetPoint("\nThe 2nd corner");
            if (prPntRes2.Status != PromptStatus.OK)
                throw new System.Exception("The 2nd corner picking failed!");
            CollectedPoints.Add(prPntRes2.Value);
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor -= Editor_PointMonitor;
        }
        private void BuildupWindowVertices(Point3d corner1, Point3d corner2)
        {
            mTempPline = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            mTempPline.SetDatabaseDefaults();
            mTempPline.Closed = true;
            mTempPline.ColorIndex = mColorIndex;
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(corner1.X, corner1.Y), 0, 1, 1);
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(corner2.X, corner1.Y), 0, 1, 1);
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(corner2.X, corner2.Y), 0, 1, 1);
            mTempPline.AddVertexAt(mTempPline.NumberOfVertices, new Point2d(corner1.X, corner2.Y), 0, 1, 1);
        }
        public void Dispose()
        {
            MgdAcApplication.DocumentManager.MdiActiveDocument.Editor.PointMonitor -= Editor_PointMonitor;
            if (mTempPline != null && !mTempPline.IsDisposed)
            {
                TransientManager.CurrentTransientManager.EraseTransient(mTempPline, new IntegerCollection());
                mTempPline.Dispose();
                mTempPline = null;
            }
            CollectedPoints.Dispose();
        }
    }
}
In terms of how to use it, please refer to earlier posts for details. Enjoy it, guys!



论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-1-6 00:47 , Processed in 0.437529 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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