一、使用Jig动态旋转实体(转载:明经通道 mccad 翻译)
原文转载自:http://through-the-interface.typepad.com/through_the_interface/jigs/(该口已无法访问)
可访问转载入口:http://bbs.mjtd.com/thread-75618-1-1.html(转载自明镜通道by雪山飞狐_lzh)
原kean博客已经无法看到,故转载明经通道雪山飞狐_lzh老师整理内容
1.keen源码内容翻译及源码展示:
2008年3月28日
通过 .NET 动态旋转AutoCAD 图元
本文由明经通道 mccad 翻译,转载请注明出处
在上一文章中有一有趣的需求与另一文章中的问题相似。原来的问题是以矩形的中心旋转矩形多段线图元,并且之后还可继续旋转它。有几点我比较感兴趣:
矩形是由四个点组成的简单多段线,它并不存在中心点和旋转角度的概念。
至少对我来说,很明显需要计算中心点并将旋转角度做为XData保存在多段线上。
要形象化的修改最好是以动态方式。
大部分示例是演示如何使用动态来创建新图元,而非修改现有图元。
因此,考虑到这一点,我使用以下C#代码来解决这个问题:
keen源码:
-
using Autodesk.AutoCAD.ApplicationServices; -
using Autodesk.AutoCAD.DatabaseServices; -
using Autodesk.AutoCAD.EditorInput; -
using Autodesk.AutoCAD.Runtime; -
using Autodesk.AutoCAD.Geometry; -
![]()
-
namespace RotatingRectangles -
{ -
public class Commands -
{ -
// Define some constants we'll use to -
// store our XData 定义一些常量,我们用来储存扩展数据 -
![]()
-
// AppName is our RDS (TTIF, for -
// "Through The InterFace") plus an indicator -
// what it's for (ROTation) 在解释那个TTIF_ROT RDS 远程数据服务? -
![]()
-
const string kRegAppName = "TTIF_ROT"; -
const int kAppCode = 1001; -
const int kRotCode = 1040; -
![]()
-
class RotateJig : EntityJig -
{ -
// Declare some internal state 声明一些内容状态 -
![]()
-
double m_baseAngle, m_deltaAngle; -
Point3d m_rotationPoint; -
Matrix3d m_ucs; -
![]()
-
// Constructor sets the state and clone the entity passed in (adequate for simple entities) -
构造器设置状态并且复制传入的实体
-
public RotateJig( -
Entity ent, -
Point3d rotationPoint, -
double baseAngle, -
Matrix3d ucs) -
: base(ent.Clone() as Entity) -
{ -
m_rotationPoint = rotationPoint; -
m_baseAngle = baseAngle; -
m_ucs = ucs; -
} -
![]()
-
protected override SamplerStatus Sampler( -
JigPrompts jp -
) -
{ -
// We acquire a single angular value -
![]()
-
JigPromptAngleOptions jo = -
new JigPromptAngleOptions( -
"\nAngle of rotation: " -
); -
jo.BasePoint = m_rotationPoint; -
jo.UseBasePoint = true; -
![]()
-
PromptDoubleResult pdr = -
jp.AcquireAngle(jo); -
![]()
-
if (pdr.Status == PromptStatus.OK) -
{ -
// Check if it has changed or not (reduces flicker) -
if (m_deltaAngle == pdr.Value) -
{ -
return SamplerStatus.NoChange; -
} -
else -
{ -
// Set the change in angle to the new value -
![]()
-
m_deltaAngle = pdr.Value; -
return SamplerStatus.OK; -
} -
} -
return SamplerStatus.Cancel; -
} -
![]()
-
protected override bool Update() -
{ -
// We rotate the polyline by the change minus the base angle -
![]()
-
Matrix3d trans = -
Matrix3d.Rotation( -
m_deltaAngle - m_baseAngle, -
m_ucs.CoordinateSystem3d.Zaxis, -
m_rotationPoint); -
Entity.TransformBy(trans); -
![]()
-
// The base becomes the previous delta and the delta gets set to zero -
![]()
-
m_baseAngle = m_deltaAngle; -
m_deltaAngle = 0.0; -
![]()
-
return true; -
} -
![]()
-
public Entity GetEntity() -
{ -
return Entity; -
} -
![]()
-
public double GetRotation() -
{ -
// The overall rotation is the base plus the delta -
return m_baseAngle + m_deltaAngle; -
} -
} -
[CommandMethod("ROT")] -
public void RotateEntity() -
{ -
Document doc = -
Application.DocumentManager.MdiActiveDocument; -
Editor ed = doc.Editor; -
Database db = doc.Database; -
// First we prompt for the entity to rotate -
PromptEntityOptions peo =
-
new PromptEntityOptions( -
"\nSelect entity to rotate: " -
); -
PromptEntityResult per = -
ed.GetEntity(peo); -
if (per.Status == PromptStatus.OK)
-
{ -
Transaction tr = -
db.TransactionManager.StartTransaction(); -
using (tr) -
{ -
DBObject obj = -
tr.GetObject(per.ObjectId, OpenMode.ForRead); -
Entity ent = obj as Entity; -
// Use the origin as the default center
-
Point3d rotationPoint = Point3d.Origin; -
// If the entity is a polyline,assume it is rectangular and then set the rotation point as its center -
Polyline pl = obj as Polyline; -
if (pl != null) -
{ -
LineSegment3d ps0 = -
pl.GetLineSegmentAt(0); -
LineSegment3d ps1 = -
pl.GetLineSegmentAt(1); -
Vector3d vec = -
((ps0.EndPoint - ps0.StartPoint) / 2.0) + -
((ps1.EndPoint - ps1.StartPoint) / 2.0); -
rotationPoint = pl.StartPoint + vec; -
} -
// Get the base rotation angle stored with the -
// entity, if there was one (default is 0.0) -
double baseAngle = GetStoredRotation(obj);![]()
-
if (ent != null) -
{ -
// Get the current UCS, to pass to the Jig -
Matrix3d ucs = -
ed.CurrentUserCoordinateSystem; -
// Create our jig object -
RotateJig jig = -
new RotateJig( -
ent, -
rotationPoint, -
baseAngle, -
ucs -
); -
PromptResult res = ed.Drag(jig); -
if (res.Status == PromptStatus.OK) -
{ -
// Get the overall rotation angle -
// and dispose of the temp clone -
double newAngle = jig.GetRotation(); -
jig.GetEntity().Dispose(); -
// Rotate the original entity -
Matrix3d trans = -
Matrix3d.Rotation( -
newAngle - baseAngle, -
ucs.CoordinateSystem3d.Zaxis, -
rotationPoint); -
ent.UpgradeOpen(); -
ent.TransformBy(trans); -
// Store the new rotation as XData -
SetStoredRotation(ent, newAngle); -
} -
} -
tr.Commit(); -
} -
} -
} -
// Helper function to create a RegApp -
static void AddRegAppTableRecord(string regAppName) -
{ -
Document doc = -
Application.DocumentManager.MdiActiveDocument; -
Editor ed = doc.Editor; -
Database db = doc.Database; -
Transaction tr = -
doc.TransactionManager.StartTransaction(); -
using (tr) -
{ -
RegAppTable rat = -
(RegAppTable)tr.GetObject( -
db.RegAppTableId, -
OpenMode.ForRead, -
false -
); -
if (!rat.Has(regAppName)) -
{ -
rat.UpgradeOpen(); -
RegAppTableRecord ratr = -
new RegAppTableRecord(); -
ratr.Name = regAppName; -
rat.Add(ratr); -
tr.AddNewlyCreatedDBObject(ratr, true); -
} -
tr.Commit(); -
} -
} -
// Store our rotation angle as XData -
private void SetStoredRotation( -
DBObject obj, double rotation) -
{ -
AddRegAppTableRecord(kRegAppName); -
ResultBuffer rb = obj.XData; -
if (rb == null) -
{ -
rb = -
new ResultBuffer( -
new TypedValue(kAppCode, kRegAppName), -
new TypedValue(kRotCode, rotation) -
); -
} -
else -
{ -
// We can simply add our values - no need -
// to remove the previous ones, the new ones -
// are the ones that get stored -
![]()
-
rb.Add(new TypedValue(kAppCode, kRegAppName)); -
rb.Add(new TypedValue(kRotCode, rotation)); -
} -
obj.XData = rb; -
rb.Dispose(); -
} -
![]()
-
// Retrieve the existing rotation angle from XData -
![]()
-
private double GetStoredRotation(DBObject obj) -
{ -
double ret = 0.0; -
![]()
-
ResultBuffer rb = obj.XData; -
if (rb != null) -
{ -
// If we find our group code, it means that on -
// the next iteration, we'll get our rotation -
![]()
-
bool bReadyForRot = false; -
foreach (TypedValue tv in rb) -
{ -
if (bReadyForRot) -
{ -
if (tv.TypeCode == kRotCode) -
ret = (double)tv.Value; -
bReadyForRot = false; -
} -
if (tv.TypeCode == kAppCode) -
bReadyForRot = true; -
} -
rb.Dispose(); -
} -
return ret; -
} -
} -
}
试用代码前,可用 RECTANG 命令创建一水平方向矩形,然后使用自定义的ROT命令来旋转它
之后再调用 ROT命令运行也会正常,因为图元“记住”了旋转角度。如果用了其它的工具旋转了这个矩形,这种效果就会消失。一种方法是深层的分析矩形来测量“旋转角度”:确定矩形的长边,获得它的角度。另一种毫无意义的方法是执行命令让用户输入角度(选择两个点或直接输入)。
2.keen源码的图形展示:
第一篇已有明经通道mccad 翻译,此部分内容直接转载了,接下来的日子里我争取在每周末对翻译的Kean的博客进行更新,也同时上传一些自己开发过程中实现的图形的以及图形的实现思路
using Autodesk.AutoCAD.ApplicationServices;
{
浙公网安备 33010602011771号