愿你出走半生,归来仍是少年!
环境:.NET FrameWork4.5、ObjectArx 2016 64bit、Entity Framework 6.
目录
2.2.1 MoveBlockSingleAttributeJig(DrawJig实现类)
1. 来源
在CAD数据编辑时,实体的位置移动是时常需要遇见的操作。通过的方式是选中实体后再选择新的位置,然后将实体直接挪过去,虽然这样达到了移动实体的目的,但是交互效果过于糟糕。举个例子,在内业人员进行标注文本的位置挪动时,直接通过点选的方式进行文本的位置变更会导致在变更完成前内业人员无法确定变更后的效果,是否盖压严重、重叠等等问题。 由于带来的需求是需要实现配合鼠标移动的实体动态绘制效果。例如动态绘制一个矩形,而不是让用户去点击矩形的四个顶点;移动实体的时候,在选中实体后生成一根跟随鼠标的虚线,标识出新的位置等等。
2. Jig类
在CAD中提供了Autodesk.AutoCAD.EditorInput.Jig类。在CAD的二次开发中,使用JIG技术可实现操作的动态性、交互,在交互中可在鼠标移动的同时实现拖动、牵引等效果表达,达到所见即所得的交互效果。
Jig内部逻辑在停止前会不断进行循环,每次循环总体上分为四步
- 获取用户拖动、移动的鼠标
- 将其解释为距离、角度或点
- 使用该值更新实体的数据
- 调用实体的WorldDraw方法在屏幕上重绘它
Jig类作为一个抽象类,拥有两个派生类:Autodesk.AutoCAD.EditorInput.DrawJig
、Autodesk.AutoCAD.EditorInput.EntityJig。
2.1 EntityJig类
针对单个实体提供拖拽的效果实现和最终的更新。
2.2 DrawJig类
无特定的实体,可针对的实体相对宽松,自由度更高。此处以移动块参考中的属性实体为例,先看效果如下:
2.2.1 MoveBlockSingleAttributeJig(DrawJig实现类)
该类继承于DrawJig类,通过Sampler方法实现目标点的确定,通过WorldDraw方法实现绘制。
/// <summary>
/// 移动块的指定属性
/// </summary>
public class MoveBlockSingleAttributeJig : DrawJig
{
//要挪到的目标点
private Point3d selectedPt;
//属性
private AttributeReference attrRef;
//字宽
private double textWidth = 0;
private BlockReference br = null;
#region 结果
/// <summary>
///属性的位置
/// </summary>
private Point3d selfAttributePosition;
public Point3d AttributePosition { get { return selfAttributePosition; } }
/// <summary>
/// 牵引线
/// </summary>
private Autodesk.AutoCAD.DatabaseServices.Polyline selfDraftLine;
public Autodesk.AutoCAD.DatabaseServices.Polyline DraftLine { get { return selfDraftLine; } }
#endregion
public MoveBlockSingleAttributeJig(BlockReference blockReference,AttributeReference attribute)
{
attrRef = attribute;
double textHeight = attrRef.Height;
//0.72是赵总根据经验推出的比例
textWidth = attrRef.WidthFactor * textHeight * attrRef.TextString.GetByteLength() * 0.72;
br = blockReference;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
PromptPointResult ppr = prompts.AcquirePoint("请选择属性的新位置!");
if (ppr.Status != PromptStatus.OK)
{
return SamplerStatus.Cancel;
}
selectedPt = ppr.Value;
return SamplerStatus.OK;
}
protected override bool WorldDraw(WorldDraw draw)
{
Autodesk.AutoCAD.DatabaseServices.Polyline pl = new Autodesk.AutoCAD.DatabaseServices.Polyline();
pl.AddVertexAt(0, new Point2d(br.Position.X, br.Position.Y), 0, 0, 0);
pl.AddVertexAt(1, new Point2d(selectedPt.X, selectedPt.Y), 0, 0, 0);
var cloneAttr = (AttributeReference)attrRef.Clone();
if (selectedPt.X >= attrRef.Position.X)
{
cloneAttr.Position = new Point3d(selectedPt.X, selectedPt.Y + 0.4, 0);
pl.AddVertexAt(2, new Point2d(selectedPt.X + textWidth, selectedPt.Y), 0, 0, 0);
}
else
{
cloneAttr.Position = new Point3d(selectedPt.X - textWidth, selectedPt.Y + 0.4, 0);
pl.AddVertexAt(2, new Point2d(cloneAttr.Position.X, selectedPt.Y), 0, 0, 0);
}
pl.Linetype = "DASHED2";
selfDraftLine = (Autodesk.AutoCAD.DatabaseServices.Polyline)pl.Clone();
selfAttributePosition = cloneAttr.Position;
draw.Geometry.Draw(pl);
draw.Geometry.Draw(cloneAttr);
return true;
}
}
2.2.2 ToolMoveFlag(业务实现类)
该类调用动态绘制,结合业务实现功能需求。通过SelectBlockReferenceByPointer方法选择指定图层中的引用指定块定义的块参考实体,并在回调中获取块中的第一个属性进行位置动效操作。针对操作完成后将属性的位置进行更新以及添加牵引线。
[CommandMethod("MF")]
public override void Command()
{
FileInfo absSymbolFile = new FileInfo(ModuleConfig.CadConfig.Symbol.AbsPointSymbol);
SelectionHelper.SelectBlockReferenceByPointer(new BlockReferenceSelectOptions()
{
BlockDefindName = absSymbolFile.Name.Replace(absSymbolFile.Extension, ""),
LayerName = ModuleConfig.CadConfig.Layers.AbsoluteLayers.AbsoluteRelationLayer.Name
},
(doc,db,editor,trans, entity) =>
{
BlockReference br = entity as BlockReference;
AttributeReference attrRef=null;
var enumerator = br.AttributeCollection.GetEnumerator();
while (enumerator.MoveNext())
{
var tempId = (ObjectId)enumerator.Current;
AttributeReference tempAttr = (AttributeReference)trans.GetObject(tempId, OpenMode.ForRead, false, true);
attrRef = tempAttr;
break;
}
doc.LoadLineType("DASHED2");
MoveBlockSingleAttributeJig moveJig = new MoveBlockSingleAttributeJig(br,attrRef);
PromptResult pr = editor.Drag(moveJig);
if (pr.Status == PromptStatus.OK)
{
//更新属性
attrRef.UpgradeOpen();
attrRef.Position = moveJig.AttributePosition;
//添加牵引线
BlockTable blockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
moveJig.DraftLine.Linetype = "Continuous";
moveJig.DraftLine.Layer = ModuleConfig.CadConfig.Layers.AbsoluteLayers.AbsoluteFlagLineLayer.Name;
btr.AppendEntity(moveJig.DraftLine);
trans.AddNewlyCreatedDBObject(moveJig.DraftLine, true);
moveJig.DraftLine.Dispose();
}
});
}