前言
前面写着一直絮絮叨叨,感觉不好。想找些表情包来,写得好玩点,但找不到合适的,或者说耗时费力又不满意,而自个儿又做不来表情包,就算了。
其次呢,之前会把部分类成员给抄表列出来,写全了又长又啰嗦,自己都不愿看,挑着写又可能会落下点有用的,所以就不列了。
那么,就闲话少说,直接讲。
一、这三个是什么
Family
(族),直接派生自Element
,在Revit中,绝大部分图元都是族。墙、梁、柱等模型是族,长度、角度、直径等图纸标注也是族。当然也有不是族的,比如DirectShape
,就单纯的只是模型。
按照编辑形式,族可分为系统族、内建族、可载入族3种。由于我对内建组不够了解,就不展开了,可自行去查阅。
FamilySymbol
(族类型),是族的一部分。比如一扇门,可以通过调整参数改变其宽、高、门把手的位置。但只有几种规格的门是实际用到的,这样就可以预设一些参数。这种预设好的,就是族类型。一个族可以有很多种类型。
FamilyInstance
(族实例),简单理解,就是族的实例。
但是呢,族实例这个类,特指可载入族(用户自己创建的族,体现为.rfa
格式的文件)的实例。系统族的实例,就是Wall
、Cloumn
这类由Revit内部定义与实现好的族。
二、它们如何获取
泛指的族实例的获取,可按照之前讲过的《Filter(过滤器)》进行。
族名称的获取,可以参照另一篇Revit获取元素的族名,或者直接采用以下代码。
// 扩展方法
public static string GetFamilyName(this Element element)
{
Parameter parameter = element.GetParameter(BuiltInParameter.ELEM_FAMILY_PARAM); // GetParameter也是扩展方法,自带的返回是一个List
string familyName = parameter.AsValueString();
return familyName;
}
族/族类型的获取,就要分情况了。族类型是绑定在族上的,所以获取到族,自然就可以拿到族类型了。
2.1. 可载入族-族与类型的获取
上面介绍到,FamilyInstance
类特指可载入族的实例,同样的,Family
类特指可载入族。FamilySymbol
例外,系统组和可载入族都有。
因此,
第一种方式,便是直接使用类过滤器,过滤Family类。
这种方式通常用于族的创建,比如我们要批量生成灯具,就可以通过这种方式检索到项目种已载入的灯族。
第二种方式,从FamilyInstance上拿到族。
族实例上,自然是包含了族信息的,这很合理,很自然就能想到。
但也有不自然的时候,等讲到Parameter
的时候再细说。
① 从属性上获取
// ① 从属性种获取
var familySymbol = familyInstance.Symbol;
var family = familySymbol.Family;
需要注意的是,族实例上的名称,是类型名,而不是族名。这也是上面写获取元素族名方法的原因。
② 用方法获取。
这是通用的方法,无论是可载入族,或者是系统族,都可以使用,在下面 2.2 讲。
2.2. 系统族-族与类型的获取
我们注意到,Element
上有俩方法:
GetTypeId()
:获取当前元素类型的ID,无类型则返回不可用ID。GetValidTypes()
:获取当前元素的所有类型的ID,无则返回空集合。
看,在Element那篇,就没有讲这俩方法。
// ② 用方法获取
var typeID = element.GetTypeId();
var familySymbol = document.GetElement(typeID) as FamilySymbol;
至于系统族的获取,那就直接过滤呗。要墙就过滤Wall
,要楼梯就过滤Stairs
。
三、作用、使用
从使用Revit的角度,族的作用就是让用户能够简单轻松的操作图元。而开发上呢,这几个类的作用就是让开发者能够对族、族实例进行调整,进行使用。
3.1. 族的载入与交互放置
使用交互的方式载入族,可以直接讲文件拖到Revit中。
而开发呢,则需要使用载入方法。
族的载入方法,在Document
上
// 载入族
bool loaded = document.LoadFamily(path);
// 其它重载
// public bool LoadFamily(string path,IFamilyLoadOptions familyLoadOptions,...);
这种直接载入的方式是不妥的,当项目中已经存在了同名族时,系统会进行提示。
Revit中,族不可同名。可载入族的名称,就是该族的文件名。
我们能不能默认对同名族进行替换呢?当然是可以的,这时需要实现IFamilyLoadOptions
接口,并使用对应的LoadFamily方法。
// 加载行为
class FamilpathyLoadOptions_Overwrite : IFamilyLoadOptions
{
bool IFamilyLoadOptions.OnFamilyFound(bool familyInUse, out bool overwriteParameterValues)
{
overwriteParameterValues = true; // 覆盖
return true;
}
bool IFamilyLoadOptions.OnSharedFamilyFound(Family sharedFamily, bool familyInUse, out FamilySource source, out bool overwriteParameterValues)
{
source = FamilySource.Project;
overwriteParameterValues = true;
return true;
}
};
现在族已经载入了,那么放置呢?
在UIDocument
上,有以下方法,这样就可以交互式放置,点哪儿方哪儿。
uiDoc.PromptForFamilyInstancePlacement(familySymbol);
3.2. 族实例的创建
族的交互放置方式,一般是在开发族库类插件时用到。
而在要求批量生成的功能中,则需要使用代码来创建,也就是前面的随笔中多次提到的Creation
。
var creation = document.Create; // 获取Creation实例
var instance = creation.NewFamilyInstance(setPoint, symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
需要注意的是,族实例的创建方法,足足有
12
个重载。上面只是按照位置放置的方法,具体是需要自己去看看。
3.3. 族参数的设置
Revit族是可以由参数控制的,比如有一个门的族,可以通过设置其宽、高参数来改变规格。
流程:① 拿到族实例,② 拿到指定参数,③ 设置参数值。
这里涉及到Parameter
了,简单讲一下使用。
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
internal class FamilyInstanceCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document document = uiDoc.Document;
Reference reference = uiDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
Element element = document.GetElement(reference);
//ElementId typeID = element.GetTypeId();
//FamilySymbol familySymbol = document.GetElement(typeID) as FamilySymbol;
//TaskDialog.Show("Family", $"Family: {familySymbol.Name}");
// 获取指定参数
Parameter width = element.FindParameter("宽度"); // Nice3Points.Revit.Extensions
Parameter height = element.FindParameter("高度");
if (width == null || height == null)
{
TaskDialog.Show("Family Instance", "No width or height parameter found.");
return Result.Failed;
}
// 修改参数值
using (Transaction transaction = new Transaction(document))
{
transaction.Start("Change Family Instance Parameters");
width.Set(1500d.FromMillimeters()); // Nice3Points.Revit.Extensions
height.Set(2100d.FromMillimeters());
transaction.Commit();
}
return Result.Succeeded;
}
}
代码中有两处Nice3Points.Revit.Extensions
的注释,这是一个三方库,提供了一些扩展方法。
第一处是找到参数,Revit本身也有查找参数查找参数方法,但返回的是列表。
第二处是单位转换,讲毫米转为Revit内部单位(英尺)。Revit也有单位转换相关的工具类UnitUtils
。
提示,可以使用插件RevitLookUp,方便查看元素的参数。
四、一些可能用到的东西
Family、FamilySymbol上的大部分属性方法继承自Element,而FamilyInsyance上,就有比较多属于自己的东西了。
这里还是看一下类成员。
-
变换(
Transform
)相关带有翻转、镜像、等含义的。
如属性上的 CanFlipFacing、FacingFlipped、FacingOrientation、Mirrored…
方法上的 flipFacing、flipHand,继承来的GetTransform。
对于上述类成员的作用,请查看Revit Transform和镜像(翻转)问题。 -
几何(
Geometry
)相关带有Geometry、Profile之类字样的,多少与图元的几何有关。
几何方面的,放到后面讲。 -
剪切相关
注意到有数个带有Coping资源的方法,但其含义我不够了解。
至于剪切,也放到后面讲。 -
结构相关
…
总结
这篇,讲了的与族相关的3个类,讲了族的获取,载入,创建和参数修改。
又提到了一些没有展开的东西,有 Creation
,Parameter
,Unit
,Transform
,Geoemtry
,Cut
等。
既然Creation已经提了好多次了,那么就下一篇写吧。