AutoCAD .Net二次开发之JIG动态绘制详解
AutoCAD平台动态绘制分两种,单实体绘制EntityJig和多实体绘制DrawJig,需要自己自定义类去继承。(本人的理解全放在了代码注释中,请详看注释)
EntityJig(单实体绘制)
class MyLineJig : EntityJig//使用此基类来实现动态绘制只可以绘制一个实体
{
//基类EntityJig中有一个关键的成员变量Entity,也就是要绘制到模型空间的临时图形,在绘制完成后将其添加到模型空间以及数据库,既完成了动态绘制
public MyLineJig(Point3d _basePt) : base(new Line(_basePt, _basePt))//在构造之前调用基类构造为基类成员Entity初始化
{
m_AcquirePoint = _basePt;
}
public static bool StartDrag()//调用此方法开始绘制
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Point3d startPt = Point3d.Origin;
PromptStatus promptStatus = GetPoint("", ref startPt);//需自己实现(获取用户输入点)
if (promptStatus != PromptStatus.OK)
return false;
MyLineJig lineJig = new MyLineJig(startPt);
PromptResult PR = doc.Editor.Drag(lineJig);//开始绘制
if (PR.Status != PromptStatus.OK)
return false;
AppendEntityToModalSpace(doc, lineJig.Entity);//需自己实现(将实体添加进模型空间)
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)//提取输入数据并处理(鼠标移动时一定频率调用)
{
JigPromptPointOptions JPPO = new JigPromptPointOptions();//定义点绘制的配置类
JPPO.Message = "\n选择点";
PromptPointResult PR = prompts.AcquirePoint(JPPO);//当鼠标未移动时,程序会在这里阻塞,直到鼠标移动,提取出当前鼠标位置,继续往下运行
if (PR.Status != PromptStatus.OK)
{
return SamplerStatus.Cancel;
}
if (PR.Value.DistanceTo(((Line)Entity).EndPoint) < 0.000001f)//若当前鼠标位置离上一次绘制的位置很近,返回NoChange,不让系统去调用Update去刷新
//此举是为了减少刷新频率,避免绘制时的闪烁
//(需要注意的是Jig绘制刚开始和结束的瞬间, 即便Sampler返回的是NoChange,也会调用Update)
return SamplerStatus.NoChange;
m_AcquirePoint = PR.Value;//更新数据,返回OK,告诉系统,数据已整理好,需要刷新
return SamplerStatus.OK;
}
protected override bool Update()//刷新(方法中应写对Base.Entity的更改,Sampler返回OK时调用),(在开始绘制时即便Sampler返回NoChange也会调用,绘制的是圆时应避免给圆的半径赋值零,圆实体会退化成点)
{
((Line)Entity).EndPoint = m_AcquirePoint;//利用绘制好的点去改变实体属性(EntityJig内部实现会把Entity成员绘制到模型空间)
return true;
}
private Point3d m_AcquirePoint;//保存提取出来的鼠标位置
}
DrawJig(多实体绘制)
//DrawJig没有了Entity成员,需要自己定义绘制的实体的成员变量
class MyDoubleLineJig : DrawJig
{
public MyDoubleLineJig(Point3d _basePt)
{
line_1 = new Line();
line_2 = new Line();
m_BasePt = _basePt;
m_gap = 10.0f;
}
public static bool StartDraw()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Point3d startPt = Point3d.Origin;
PromptStatus promptStatus = GetPoint("\n输入起点", ref startPt);//需自己实现(获取用户的点输入)
if (promptStatus != PromptStatus.OK)
return false;
MyDoubleLineJig lineJig = new MyDoubleLineJig(startPt);
PromptResult PR = doc.Editor.Drag(lineJig);
if (PR.Status != PromptStatus.OK)
return false;
AppendEntityToModalSpace(doc, lineJig.line_1);//需自己实现(将实体添加进模型空间)
AppendEntityToModalSpace(doc, lineJig.line_2);
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions m_JPPO = new JigPromptPointOptions();
m_JPPO.Message = "\ninput end point";
m_JPPO.UserInputControls = (UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted | UserInputControls.AnyBlankTerminatesInput);
PromptPointResult PR = prompts.AcquirePoint(m_JPPO);
if (PR.Status != PromptStatus.OK)
return SamplerStatus.Cancel;
Point3d pt = PR.Value;
if (PR.Value == m_AcquirePt)
return SamplerStatus.NoChange;
m_AcquirePt = PR.Value;
return SamplerStatus.OK;
}
//与Entity最大不同的在这里(Update->WorldDraw)
protected override bool WorldDraw(WorldDraw draw)
{
Vector3d lineV = m_AcquirePt - m_BasePt;
Vector3d perpV = lineV.RotateBy(Math.PI / 2.0f, Vector3d.ZAxis);
perpV = perpV.GetNormal() * m_gap;
line_1.StartPoint = m_BasePt + perpV;
line_2.StartPoint = m_BasePt - perpV;
line_1.EndPoint = m_AcquirePt + perpV;
line_2.EndPoint = m_AcquirePt - perpV;
line_1.WorldDraw(draw);//需要调用WorldDraw将想要绘制的实体绘制到模型空间
line_2.WorldDraw(draw);
return true;
}
Line line_1;
Line line_2;
Point3d m_BasePt;
Point3d m_AcquirePt;
double m_gap;
}