一、使用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(
-
" Angle 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(
-
" Select 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的博客进行更新,也同时上传一些自己开发过程中实现的图形的以及图形的实现思路