EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

EaBIM

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
查看: 1267|回复: 23
打印 上一主题 下一主题

[用户交互] 交互式创建多义线

[复制链接]

1514

主题

7465

帖子

1万

积分

admin

Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10Rank: 10

积分
12404

社区QQ达人

跳转到指定楼层
楼主
发表于 2014-1-8 16:39:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Controlling interactive polyline creation - Part 1
I received this interesting question through by email over the weekend:
“How can I ask AutoCAD to let the user to draw a Polyline (just like the user pushed Polyline button) and then just after finishing drawing get the ObjectID of that entity? Is it possible?”
This is a fun one, as there are a number of different approaches to take. I’m going to outline (or just go ahead and implement, depending on the complexity) the various possibilities – taking the first two today and the others in (a) subsequent post(s).
The idea is to define our own command, say MYPOLY, and make sure we’re left with execution control – and the object ID/entity name – after the user has defined a polyline in the drawing window.
There are two basic ways to solve this problem, and each of these has two variants. The initial (and major) choice is whether to let the standard AutoCAD PLINE command provide the user-interface for creating the polyline. Doing so is certainly simpler, assuming you want the user to have access to all the polyline options. That said, you may actually prefer to limit the user’s options (for example, not to allow width or arc segments), in which case the approach to implement the UI yourself would be better suited.
So, now to tackle the first two options...
From the MYPOLY command, we want to call the PLINE command. Once the command has completed, we want to make sure our code is being executed, which will allow us to get the polyline's object ID.
This is where we get our next choice: how to find out when the PLINE command has ended. The first option (and the one typically used from Visual LISP for this type of task) is to loop until the command is finished, checking either CMDACTIVE or CMDNAMES. This is important, as polylines can have an arbitrary number of vertices, so we don’t know exactly how long the command will take to complete (in terms of how many “pauses” the command will have, requesting a point selection from the user).
  • using Autodesk.AutoCAD.EditorInput;
  • using Autodesk.AutoCAD.ApplicationServices;
  • using Autodesk.AutoCAD.DatabaseServices;
  • using Autodesk.AutoCAD.Runtime;
  • namespace MyPlineApp
  • {
  • public class MyPlineCmds : IExtensionApplication
  • {
  • // Flag used to check whether it's our command
  • // that launched PLINE
  • private static bool myCommandStarted = false;
  • public void Initialize()
  • {
  • Document doc =
  • Application.DocumentManager.MdiActiveDocument;
  • doc.CommandEnded += new
  • CommandEventHandler(
  • plineCommandEnded
  • );
  • }
  • public void Terminate()
  • {
  • Document doc =
  • Application.DocumentManager.MdiActiveDocument;
  • doc.CommandEnded -= new
  • CommandEventHandler(
  • plineCommandEnded
  • );
  • }
  • [CommandMethod("MYPOLY")]
  • public void MyPoly()
  • {
  • // Set the flag and launch PLINE
  • myCommandStarted = true;
  • Document doc =
  • Application.DocumentManager.MdiActiveDocument;
  • doc.SendStringToExecute("_PLINE ",false,false,false);
  • }
  • private void plineCommandEnded(
  • object sender,
  • CommandEventArgs e)
  • {
  • if (myCommandStarted
  • && e.GlobalCommandName.ToUpper() == "PLINE")
  • {
  • // We're just performing a simple check, so OK..
  • // We could launch a follow-on command, if needed
  • Document doc =
  • Application.DocumentManager.MdiActiveDocument;
  • PromptSelectionResult lastRes =
  • doc.Editor.SelectLast();
  • if (lastRes.Value != null
  • && lastRes.Value.Count == 1)
  • {
  • doc.Editor.WriteMessage(
  • "\nPolyline entity is: "
  • + lastRes.Value[0].ObjectId
  • );
  • }
  • myCommandStarted = false;
  • }
  • }
  • }
  • }

复制代码

That's where I'll stop it there for now… the other two options I want to look at both revolve around defining your own user-interface. The first will simply collect a sequence of points from the user using GetPoint(), the second uses a Jig to do the same thing (I haven’t yet decided whether to actually implement this last one or not – we’ll see how much time I have later in the week).
During the first part of this series, we looked at ways to drive the PLINE command while retaining (or regaining) the thread of execution in your application.
During this and the next post (yes, I've decided to spread the series a little thinner :-) we're going to look at how to completely replace the user-interface to the polyline command, a very useful technique in certain situations. This post focuses on the simple use of GetPoint() to request vertex information from the user; the next post will look at a more advanced technique, the Jig.
Even the "simple" user-interface implemented in the below code takes some effort. To keep things as simple as possible, the below UI code only allows the user to define zero-width, linear polyline segments - no arcs, widths, etc. As mentioned in the previous post, this might well be an advantage in your application, depending on whether you want to hide certain options from the user. This approach is certainly not ideal if you do want to allow interactive selection of arc segments; the two approaches suggested last time, or the one shown in the next entry, would work better in that case.
A few notes on the implementation:
Temporary graphics are used to draw each polyline segment as soon as both its vertices have been defined
The actual polyline entity is only created once all the vertices have been selected
Point selection happens in the User Coordinate System, so we need to do some work to transform selected points to the Entity Coordinate System (or Object Coordinate System) belonging to the polyline. 2-dimensional polylines are planar entities and have their vertices defined as 2D points relative to the origin and normal of the polyline, so we use a "Plane" object to help us get the 2D points to feed to the polyline's AddVertexAt() function
Here's the code in C#
  • using Autodesk.AutoCAD.ApplicationServices;
  • using Autodesk.AutoCAD.DatabaseServices;
  • using Autodesk.AutoCAD.EditorInput;
  • using Autodesk.AutoCAD.Runtime;
  • using Autodesk.AutoCAD.Geometry;
  • using Autodesk.AutoCAD.Colors;
  • namespace MyPlineApp
  • {
  • public class MyPlineCmds
  • {
  • [CommandMethod("MYPOLY")]
  • public void MyPoly()
  • {
  • Document doc =
  • Application.DocumentManager.MdiActiveDocument;
  • Database db = doc.Database;
  • Editor ed = doc.Editor;
  • // Get the current color, for our temp graphics
  • Color col = doc.Database.Cecolor;
  • // Create a point collection to store our vertices
  • Point3dCollection pts = new Point3dCollection();
  • // Set up the selection options
  • // (used for all vertices)
  • PromptPointOptions opt =
  • new PromptPointOptions(
  • "\nSelect polyline vertex: "
  • );
  • opt.AllowNone = true;
  • // Get the start point for the polyline
  • PromptPointResult res = ed.GetPoint(opt);
  • while (res.Status == PromptStatus.OK)
  • {
  • // Add the selected point to the list
  • pts.Add(res.Value);
  • // Drag a temp line during selection
  • // of subsequent points
  • opt.UseBasePoint = true;
  • opt.BasePoint = res.Value;
  • res = ed.GetPoint(opt);
  • if (res.Status == PromptStatus.OK)
  • {
  • // For each point selected,
  • // draw a temporary segment
  • ed.DrawVector(
  • pts[pts.Count - 1], // start point
  • res.Value, // end point
  • col.ColorIndex, // current color
  • false); // highlighted?
  • }
  • }
  • if (res.Status == PromptStatus.None)
  • {
  • // Get the current UCS
  • Matrix3d ucs =
  • ed.CurrentUserCoordinateSystem;
  • Point3d origin = new Point3d(0, 0, 0);
  • Vector3d normal = new Vector3d(0, 0, 1);
  • normal = normal.TransformBy(ucs);
  • // Create a temporary plane, to help with calcs
  • Plane plane = new Plane(origin, normal);
  • // Create the polyline, specifying
  • // the number of vertices up front
  • Polyline pline = new Polyline(pts.Count);
  • pline.Normal = normal;
  • foreach (Point3d pt in pts)
  • {
  • Point3d transformedPt =
  • pt.TransformBy(ucs);
  • pline.AddVertexAt(
  • pline.NumberOfVertices,
  • plane.ParameterOf(transformedPt),
  • 0, 0, 0
  • );
  • }
  • // Now let's add the polyline to the modelspace
  • Transaction tr =
  • db.TransactionManager.StartTransaction();
  • using (tr)
  • {
  • BlockTable bt =
  • (BlockTable)tr.GetObject(
  • db.BlockTableId,
  • OpenMode.ForRead
  • );
  • BlockTableRecord btr =
  • (BlockTableRecord)tr.GetObject(
  • bt[BlockTableRecord.ModelSpace],
  • OpenMode.ForWrite
  • );
  • ObjectId plineId = btr.AppendEntity(pline);
  • tr.AddNewlyCreatedDBObject(pline, true);
  • tr.Commit();
  • ed.WriteMessage("\nPolyline entity is: " +
  • plineId.ToString()
  • );
  • }
  • }
  • // Clear the temp graphics (polyline should be in
  • // the same location, if selection was not cancelled)
  • // We could "redraw" instead of "regen" here
  • ed.Regen();
  • }
  • }
  • }

复制代码

Here's what happens when we execute this code:
  • Command: mypoly
  • Select polyline vertex:
  • Select polyline vertex:
  • Select polyline vertex:
  • Regenerating model.
  • Polyline entity is: (2130239560)

复制代码
Next time we'll look at how we can use a Jig for this task.
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 转播转播 分享分享 分享淘帖 支持支持 反对反对
工作时间:工作日的9:00-12:00/13:30-18:00,节假日不在线,请勿留言

0

主题

836

帖子

1198

积分

BIM项目负责人

Rank: 5Rank: 5Rank: 5Rank: 5Rank: 5

积分
1198
推荐
发表于 2014-3-10 13:26:27 | 只看该作者
顶......
楼下跟上.....

14

主题

2892

帖子

2085

积分

BIM经理

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

积分
2085
7F
发表于 2014-3-14 11:19:01 | 只看该作者
路过!!!
不发表意见……

14

主题

867

帖子

1439

积分

BIM经理

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

积分
1439
14F
发表于 2014-5-13 10:32:15 | 只看该作者
顶......
楼下跟上.....
*滑块验证:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|EaBIM网 ( 苏ICP备2020058923号-1  苏公网安备32011502011255号

GMT+8, 2024-11-23 20:37

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

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