034集——JIG效果实现(橡皮筋效果)(CAD—C#二次开发入门)
可实现效果如下(对象捕捉F3需打开,否则效果不好):
public class CircleJig : EntityJig
{
public static void DraCJig()
{
PromptPointResult ppr = Z.ed.GetPoint("a");
if (ppr.Value == null) return;
Point3d pt = ppr.Value;
CircleJig circle = new CircleJig(pt);
Polyjig poly = new Polyjig(pt);
for (; ; )
{
PromptResult resJig = Z.ed.Drag(circle);//拖动圆
if (resJig.Status == PromptStatus.Cancel)
{
return;
}
if (resJig.Status == PromptStatus.OK) //确定, 则将圆添加到数据库
// if (resJigpl.Status == PromptStatus.OK)
{
Z.db.AddEntityToModeSpace(circle.GetEntity());//画圆
break;
}
return;
}
for (; ; )//画完圆继续jig线,不需要可注释
{
PromptResult resJigpl = Z.ed.Drag(poly);//拖动线
if (resJigpl.Status == PromptStatus.Cancel)// 放弃, 则退出.
{
return;
}
if (resJigpl.Status == PromptStatus.OK) //确定, 则将线添加到数据库
{
Z.db.AddEntityToModeSpace(poly.Updata());//画多段线
break;
}
return;
}
}
// private Point3d jCenter; // 圆心
private double jRadius; // 半径
public CircleJig(Point3d center)
: base(new Circle()) // 继承父类Circle的属性
{
((Circle)Entity).Center = center; // Entity 转化为Cirecle 对象 复制center
}
// 用于更新图像对象 这里更新属性时无需使用事务处理
protected override bool Update()
{
if (jRadius > 0)
{
((Circle)Entity).Radius = jRadius;
}
return true;
}
// 这个函数的作用是当鼠标在屏幕上移动时 就会被调用 实现这个函数时 一般是用它改变图形的属性 我们在这个类定义的属性
protected override SamplerStatus Sampler(JigPrompts prompts)
{
// 声明拖拽类jig提示信息
JigPromptPointOptions jppo = new JigPromptPointOptions("\n 请指定圆上的一个点");
char space = (char)32;
jppo.Keywords.Add("U");
jppo.Keywords.Add(space.ToString());
jppo.UserInputControls = UserInputControls.Accept3dCoordinates;
jppo.Cursor = CursorType.RubberBand;
jppo.BasePoint = ((Circle)Entity).Center;
jppo.UseBasePoint = true;
// 获取拖拽时鼠标的位置状态
PromptPointResult ppr = prompts.AcquirePoint(jppo);
jRadius = ppr.Value.GetDistanceBetweenTwoPoint(((Circle)Entity).Center);
return SamplerStatus.NoChange; // 继续移动 循环检测
}
public Entity GetEntity()
{
return Entity;
}
}
public class Polyjig : Autodesk.AutoCAD.EditorInput.DrawJig
{
public Point3d location;
public Point3d basePoint;
public Polyline polyine = new Polyline();
public Plane plane = new Plane();
public int index;
public static void DrawPLJig()
{
PromptPointResult ppr = Z.ed.GetPoint("a");
if (ppr.Value == null) return;
Point3d pt = ppr.Value;
Polyjig poly = new Polyjig(pt);
for (; ; )
{
PromptResult resJigpl = Z.ed.Drag(poly);//拖动线
if (resJigpl.Status == PromptStatus.Cancel) // 放弃, 则退出.
{
return;
}
if (resJigpl.Status == PromptStatus.OK) //确定, 则将线添加到数据库
{
Z.db.AddEntityToModeSpace(poly.Updata());//画多段线
break;
}
return;
}
}
public Polyjig(Point3d basept)
{
location = basept;
basePoint = basept;
polyine.AddVertexAt(0, basePoint.Convert2d(plane), 0, 0, 0);
polyine.AddVertexAt(1, location.Convert2d(plane), 0, 0, 0);
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
var opts = new JigPromptPointOptions("\n 输入下一个点");
opts.UserInputControls = (UserInputControls.Accept3dCoordinates |
UserInputControls.NoZeroResponseAccepted
| UserInputControls.NoNegativeResponseAccepted);
var res = prompts.AcquirePoint(opts);
if (res.Value != location)
{
location = res.Value;
}
else
{
return SamplerStatus.NoChange;
}
if (res.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
else
{
return SamplerStatus.OK;
}
}
protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
{
Updata();
draw.Geometry.Draw(polyine);
return true;
}
public Polyline Updata()
{
index = polyine.NumberOfVertices - 1;
polyine.SetPointAt(index, location.Convert2d(plane));
basePoint = location;
return polyine;
}
}
其他形式:
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
namespace UseEntityJig
{
class CircleJig : EntityJig
{
private Point3d m_CenterPt;
public double m_Radius = 100.0;
// 派生类的构造函数.
public CircleJig(Vector3d normal)
: base(new Circle())
{
((Circle)Entity).Center = m_CenterPt;
((Circle)Entity).Normal = normal;
((Circle)Entity).Radius = m_Radius;
}
protected override bool Update()
{
((Circle)Entity).Center = m_CenterPt;
((Circle)Entity).Radius = m_Radius;
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
// 定义一个点拖动交互类.
JigPromptPointOptions optJig = new JigPromptPointOptions
("\n请指定圆的圆心或用右键修改半径");
optJig.Keywords.Add("100");
optJig.Keywords.Add("200");
optJig.Keywords.Add("300");
optJig.UserInputControls = UserInputControls.Accept3dCoordinates;
// 用AcquirePoint函数得到用户输入的点.
PromptPointResult resJigDis = prompts.AcquirePoint(optJig);
Point3d curPt = resJigDis.Value;
if (resJigDis.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
if (resJigDis.Status == PromptStatus.Keyword)
{
switch (resJigDis.StringResult)
{
case "100":
m_Radius = 100;
return SamplerStatus.NoChange;
case "200":
m_Radius = 200;
return SamplerStatus.NoChange;
case "300":
m_Radius = 300;
return SamplerStatus.NoChange;
}
}
if (m_CenterPt != curPt)
{
// 保存当前点.
m_CenterPt = curPt;
return SamplerStatus.OK;
}
else
{
return SamplerStatus.NoChange;
}
}
// GetEntity函数用于得到派生类的实体.
public Entity GetEntity()
{
return Entity;
}
}
}
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
namespace UseEntityJig
{
class EllipseJig : EntityJig
{
// 声明全局变量.
private Point3d m_CenterPt, m_MajorPt;
private Vector3d m_Normal, m_MajorAxis;
private int m_PromptCounter;
private double m_OtherAxisLength, m_RadiusRatio;
private double m_StartAng, m_EndAng, m_ang1, m_ang2;
// 派生类的构造函数.
public EllipseJig(Point3d center, Vector3d vec)
: base(new Ellipse())
{
m_CenterPt = center;
m_Normal = vec;
}
protected override bool Update()
{
if (m_PromptCounter == 0)
{
// 第一次拖拽时,椭圆的半径比为1,屏幕上显示的是一个圆.
m_RadiusRatio = 1;
m_MajorAxis = m_MajorPt - m_CenterPt;
m_StartAng = 0;
m_EndAng = 2 * Math.PI;
}
else if (m_PromptCounter == 1)
{
// 第二次拖拽时,修改了椭圆的半径比,屏幕上显示的是一个完整椭圆.
m_RadiusRatio = m_OtherAxisLength / m_MajorAxis.Length;
}
else if (m_PromptCounter == 2)
{
// 第三次拖拽时,修改了椭圆的起初角度,屏幕上显示的是一个终止角度为360度的椭圆弧.
m_StartAng = m_ang1;
}
else if (m_PromptCounter == 3)
{
// 第四次拖拽时,修改了椭圆的终止角度,屏幕上显示的是一个最终的椭圆弧.
m_EndAng = m_ang2;
}
try
{
if (m_RadiusRatio < 1)
// 更新椭圆的参数.
((Ellipse)(Entity)).Set(m_CenterPt, m_Normal, m_MajorAxis, m_RadiusRatio, m_StartAng, m_EndAng);
else
{
// 如另一条半轴长度超过椭圆弧长轴方向矢量的长度,则要重新定义椭圆弧长轴方向矢量的方向和长度.
Vector3d mMajorAxis2 = m_MajorAxis.RotateBy(0.5 * Math.PI, Vector3d.ZAxis).DivideBy(1 / m_RadiusRatio);
// 更新椭圆的参数.
((Ellipse)(Entity)).Set(m_CenterPt, m_Normal, mMajorAxis2, 1 / m_RadiusRatio, m_StartAng, m_EndAng);
}
}
catch
{
// 此处不需要处理.
}
return true;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
if (m_PromptCounter == 0)
{
// 定义一个点拖动交互类.
JigPromptPointOptions optJigPoint = new JigPromptPointOptions("\n请指定椭圆弧轴上一点");
// 设置拖拽的光标类型.
optJigPoint.Cursor = CursorType.RubberBand;
// 设置拖动光标基点.
optJigPoint.BasePoint = m_CenterPt;
optJigPoint.UseBasePoint = true;
// 用AcquirePoint函数得到用户输入的点.
PromptPointResult resJigPoint = prompts.AcquirePoint(optJigPoint);
Point3d curPt = resJigPoint.Value;
if (curPt != m_MajorPt)
{
// 保存当前点.
m_MajorPt = curPt;
}
else
{
return SamplerStatus.NoChange;
}
if (resJigPoint.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
else
{
return SamplerStatus.OK;
}
}
else if (m_PromptCounter == 1)
{
// 定义一个距离拖动交互类.
JigPromptDistanceOptions optJigDis = new JigPromptDistanceOptions
("\n请指定另一条半轴的长度");
// 设置对拖拽的约束:禁止输入零和负值.
optJigDis.UserInputControls = UserInputControls.NoZeroResponseAccepted |
UserInputControls.NoNegativeResponseAccepted;
// 设置拖拽的光标类型.
optJigDis.Cursor = CursorType.RubberBand;
// 设置拖动光标基点.
optJigDis.BasePoint = m_CenterPt;
optJigDis.UseBasePoint = true;
// 用AcquireDistance函数得到用户输入的距离值.
PromptDoubleResult resJigDis = prompts.AcquireDistance(optJigDis);
double radiusRatioTemp = resJigDis.Value;
if (radiusRatioTemp != m_OtherAxisLength)
{
// 保存当前距离值.
m_OtherAxisLength = radiusRatioTemp;
}
else
{
return SamplerStatus.NoChange;
}
if (resJigDis.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
else
{
return SamplerStatus.OK;
}
}
else if (m_PromptCounter == 2)
{
// 设置椭圆弧0度基准角.
double baseAng;
Vector2d mMajorAxis2d = new Vector2d(m_MajorAxis.X, m_MajorAxis.Y);
if (m_RadiusRatio < 1)
{
baseAng = mMajorAxis2d.Angle;
}
else
{
baseAng = mMajorAxis2d.Angle + 0.5 * Math.PI;
}
// 设置系统变量“ANGBASE”.
Application.SetSystemVariable("ANGBASE", baseAng);
// 定义一个角度拖动交互类.
JigPromptAngleOptions optJigAngle1 = new JigPromptAngleOptions("\n请指定椭圆弧的起始角度");
// 设置拖拽的光标类型.
optJigAngle1.Cursor = CursorType.RubberBand;
// 设置拖动光标基点.
optJigAngle1.BasePoint = m_CenterPt;
optJigAngle1.UseBasePoint = true;
// 用AcquireAngle函数得到用户输入的角度值.
PromptDoubleResult resJigAngle1 = prompts.AcquireAngle(optJigAngle1);
m_ang1 = resJigAngle1.Value;
if (m_StartAng != m_ang1)
{
// 保存当前角度值.
m_StartAng = m_ang1;
}
else
{
return SamplerStatus.NoChange;
}
if (resJigAngle1.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
else
{
return SamplerStatus.OK;
}
}
else if (m_PromptCounter == 3)
{
// 定义一个角度拖动交互类.
JigPromptAngleOptions optJigAngle2 = new JigPromptAngleOptions("\n请指定椭圆弧的终止角度");
// 设置拖拽的光标类型.
optJigAngle2.Cursor = CursorType.RubberBand;
// 设置拖动光标基点.
optJigAngle2.BasePoint = m_CenterPt;
optJigAngle2.UseBasePoint = true;
// 用AcquireAngle函数得到用户输入的角度值.
PromptDoubleResult resJigAngle2 = prompts.AcquireAngle(optJigAngle2);
m_ang2 = resJigAngle2.Value;
if (m_EndAng != m_ang2)
{
// 保存当前角度值.
m_EndAng = m_ang2;
}
else
{
return SamplerStatus.NoChange;
}
if (resJigAngle2.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
else
{
return SamplerStatus.OK;
}
}
else
{
return SamplerStatus.NoChange;
}
}
// GetEntity函数用于得到派生类的实体.
public Entity GetEntity()
{
return Entity;
}
// setPromptCounter过程用于控制不同的拖拽.
public void setPromptCounter(int i)
{
m_PromptCounter = i;
}
}
}
command
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace UseEntityJig
{
public class Command
{
[CommandMethod("jc")]
public void JigCircleTest()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Matrix3d mt = ed.CurrentUserCoordinateSystem;
Vector3d normal = mt.CoordinateSystem3d.Zaxis;
CircleJig circleJig = new CircleJig(normal);
for (; ; )
{
// 拖动
PromptResult resJig = ed.Drag(circleJig);
// 放弃, 则退出.
if (resJig.Status == PromptStatus.Cancel)
{
return;
}
// 确定, 则将圆添加到数据库
if (resJig.Status == PromptStatus.OK)
{
AppendEntity(circleJig.GetEntity());
break;
}
}
}
[CommandMethod("JigEllipse")]
public void JigEllipseTest()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = Application.DocumentManager.MdiActiveDocument.Database;
// 备份系统变量“ANGBASE”.
object oldAngBase = Application.GetSystemVariable("ANGBASE");
// 普通的点交互操作.
PromptPointOptions optPoint = new PromptPointOptions("\n请指定椭圆弧的圆心:");
PromptPointResult resPoint = ed.GetPoint(optPoint);
if (resPoint.Status != PromptStatus.OK)
{
return;
}
// 定义一个EntityJig派生类的实例.
EllipseJig myJig = new EllipseJig(resPoint.Value, Vector3d.ZAxis);
// 第一次拖拽.
myJig.setPromptCounter(0);
PromptResult resJig = ed.Drag(myJig);
if (resJig.Status != PromptStatus.OK)
{
return;
}
// 第二次拖拽.
myJig.setPromptCounter(1);
resJig = ed.Drag(myJig);
if (resJig.Status != PromptStatus.OK)
{
return;
}
// 第三次拖拽.
myJig.setPromptCounter(2);
resJig = ed.Drag(myJig);
if (resJig.Status != PromptStatus.OK)
{
return;
}
// 第四次拖拽.
myJig.setPromptCounter(3);
resJig = ed.Drag(myJig);
if (resJig.Status != PromptStatus.OK)
{
return;
}
AppendEntity(myJig.GetEntity());
// 还原系统变量“ANGBASE”.
Application.SetSystemVariable("ANGBASE", oldAngBase);
}
private ObjectId AppendEntity(Entity ent)
{
ObjectId entId;
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId,
OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject
(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
entId = btr.AppendEntity(ent);
trans.AddNewlyCreatedDBObject(ent, true);
trans.Commit();
}
return entId;
}
}
}