RevitAPI:如何用API实现两条管道按中心线(Center Line)对齐

有客户问道如何用API实现两条管道在中心线(Center Line)上对齐,我觉得应该是有办法的,就像这样:

  1. 通过获取到中心线的几何信息
  2. 使用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).

于是问题愉快的解决了!

下面是几个关键的技术要点:

  1. 确保参数options的属性ComputeReferences被设置为true, 这样我们拿到的几何对象是有Reference的,Reference是创建约束必要的参数之一.
  2. 确保参数options的属性IncludeNonVisibleObjects 被设置为true,同时确保View属性是一个平面视图, 这样我们才可以拿到隐藏的中心线.
  3. 创建约束之前,确保两个管道在物理上是对齐的。可以调用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;
var geoElem = pipe.get_Geometry(options); foreach (var item in geoElem) { Line lineObj = item as Line; if (lineObj != null) { return lineObj; } } return null; }

你可能感兴趣的:(RevitAPI,Dimension)