Revit二次开发将族实例移动到指定位置

2019年5月7号。Revit版本2017,VS版本2017

Revit提供的MoveElement方法是以自身为基点移动,例如使用MoveElement方法传入参数为(0,0,0)就相当于对移动物体本身不做任何改变。如何实现输入一个坐标系并将物体移动到该坐标上,其实只需要做一个简单的坐标转换即可。本例子涉及到简单的WPF窗体以及窗体数据的传递。

先看看最终效果

实现方法:ElementTransformUtils.MoveElement(Document document, ElementId elementToMove, XYZ translation)。

实现功能:选择族实例并移动到指定的世界坐标系。

首先创建数据类DataInfo用于存储窗体上XYZ的值代码如下

 public class DataInfo
    {
        public string Xnum { get; set; }
        public string Ynum { get; set; }
        public string Znum { get; set; }
    }

其次是WPF窗体代码

<Window x:Class="MoveElementBywpf.MoveForm"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MoveElementBywpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Height="120" Width="370" Title="MoveForm">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Border Background="LightBlue" Margin="2" Padding="2">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <StackPanel Grid.Column="0" Orientation="Horizontal">
                    <TextBlock VerticalAlignment="Center" Margin="2" Padding="2"> X坐标:</TextBlock>
                    <TextBox Name="XText" Width="60" Height="20" Margin="2" Padding="2"></TextBox>
                    <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="2" Padding="2">Y坐标:</TextBlock>
                    <TextBox Name="YText" Width="60" Height="20" Grid.Column="2" Margin="2" Padding="2"></TextBox>
                    <TextBlock VerticalAlignment="Center" Grid.Column="3" Margin="2" Padding="2">Z坐标:</TextBlock>
                    <TextBox Name="ZText" Width="60" Height="20" Grid.Column="3" Margin="2" Padding="2"></TextBox>
                </StackPanel>
            </Grid>
        </Border>
        <Button Grid.Row="1" HorizontalAlignment="Right" Height="20" Width="60" Margin="4" Padding="2" Click="Confirm_Click">确定</Button>
    </Grid>
</Window>

接下来是窗体后台代码,由于实现的功能简单,代码比较少

 public partial class MoveForm : Window
    {
        //数据类,用于存储窗体的信息。
        public DataInfo DataInfo;
        public MoveForm()
        {
            InitializeComponent();
            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            DataInfo=new DataInfo();
        }

        private void Confirm_Click(object sender, RoutedEventArgs e)
        {
            DataInfo.Xnum = this.XText.Text;
            DataInfo.Ynum = this.YText.Text;
            DataInfo.Znum = this.ZText.Text;
            this.DialogResult = true;
        }
    }

其后,是Revit外部命令类 

public class MoveElementByWpf : IExternalCommand
    {
        DataInfo dataInfo=new DataInfo();
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;
            Selection sel = uidoc.Selection;
            View view = uidoc.ActiveView;
            ElementId eleId= doc.GetElement(sel.PickObject(ObjectType.Element, "请选择要移动的元素")).Id;
            /
            MoveForm mf=new MoveForm();
            if (mf.ShowDialog()==true)
            {
               dataInfo = mf.DataInfo;
            }
            //目的获取要移动元素的坐标,通过Transform获取
            FamilyInstance fi=doc.GetElement(eleId) as FamilyInstance;
            XYZ nowXyz = fi.GetTransform().Origin;
            //目标坐标
            XYZ target = new XYZ(Convert.ToDouble(dataInfo.Xnum)/ 304.8, Convert.ToDouble(dataInfo.Ynum)/ 304.8, Convert.ToDouble(dataInfo.Znum)/ 304.8);
            //计算目标位置相对于当前物体位置的关系
            XYZ newXyz = VectorHeleper.CalculationVector(target, nowXyz);
            Transaction ts = new Transaction(doc, "移动元素");
            try
            {
                ts.Start();
                ElementTransformUtils.MoveElement(doc, eleId, newXyz);
                ts.Commit();
            }
            catch (Exception ex)
            {
                if (ts.GetStatus() == TransactionStatus.Started)
                {
                    ts.RollBack();
                }

                TaskDialog.Show("Revit", ex.Message);

            }

            return Result.Succeeded;
        }
    }

 最后是计算相对位移的VectorHeleper()类

public static XYZ CalculationVector(XYZ targetXyz,XYZ nowXyz)
        {
            XYZ newXyz=new XYZ(targetXyz.X- nowXyz.X, targetXyz.Y - nowXyz.Y, targetXyz.Z - nowXyz.Z);
            return newXyz;
        }

 最后,需要注意的是并不是所有的族实例都能移动z值的。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值