有客户问道如何用API实现两条管道在中心线(Center Line)上对齐,我觉得应该是有办法的,就像这样:
- 通过获取到中心线的几何信息
- 使用Document.Create.NewAlignment()方法创建这个对齐约束
结果碰到了莫名其妙异常:ArgumentException: One of the conditions for the inputs was not satisfied. Consult the documentation for requirements for each argument.
头疼了一会...
在开发部Phil的帮助下找到了原因,我需要先把管道移动到物理上是对齐的,然后才能再创建约束
再仔细看说明文档,确实有这样一句话:
These references must be already geometrically aligned (this function will not force them to become aligned).
于是问题愉快的解决了!
下面是几个关键的技术要点:
- 确保参数options的属性ComputeReferences被设置为true, 这样我们拿到的几何对象是有Reference的,Reference是创建约束必要的参数之一.
- 确保参数options的属性IncludeNonVisibleObjects 被设置为true,同时确保View属性是一个平面视图, 这样我们才可以拿到隐藏的中心线.
- 创建约束之前,确保两个管道在物理上是对齐的。可以调用ElementTransformUtils.MoveElement()方法来移动管道.
下面是完整代码
//这里假定两个管道是平行的
//假定当前视图是平面视图
private static Dimension
Align2PipesViaCenterline(Pipe pipeBase, Pipe pipe)
{
Dimension dimension = null;
Document doc = pipeBase.Document;
View view = doc.ActiveView;
Line baseLine = GetCenterline(pipeBase);
if (baseLine == null) return null;
Line line = GetCenterline(pipe);
if (line == null) return null;
var clone = line.Clone();
clone.MakeUnbound();
IntersectionResult result = clone.Project(baseLine.Origin);
if (result != null)
{
var point = result.XYZPoint;
var translate = baseLine.Origin - point;
using (Transaction transaction = new Transaction(doc))
{
try
{
transaction.Start("Align pipes");
ElementTransformUtils.MoveElement(
doc, pipe.Id, translate);
dimension = doc.Create.NewAlignment(view,
baseLine.Reference, line.Reference);
transaction.Commit();
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
transaction.RollBack();
}
}
}
return dimension;
}
private static Line GetCenterline(Pipe pipe)
{
Options options = new Options();
options.ComputeReferences = true; //!!!
options.IncludeNonVisibleObjects = true; //!!!
if (pipe.Document.ActiveView != null)
options.View = pipe.Document.ActiveView;
else
options.DetailLevel = ViewDetailLevel.Fine;<br />
var geoElem = pipe.get_Geometry(options);
foreach (var item in geoElem)
{
Line lineObj = item as Line;
if (lineObj != null)
{
return lineObj;
}
}
return null;
}