在实际项目构建中,很多时候需要对一个模型进行包裹,给模型生成一层包裹层,最近做的项目刚好和这个相关,把代码整理了一下提供给大家,大家可以一起看看,共同寻找不足点,以及更好的方法。具体思路如下:
- 选择需要包覆的模型
- 将模型转换成为几何模型,获取模型的每个面
- 循环每个面,根据每个面的BoundingUV,获取创建常规模型包覆族需要的参数
- 生成包裹层,Load到项目文件中
有以下几个注意点:
1.创建包覆层需要在族文档环境下,而不是打开的项目文档
2.参数添加要在生成族模型的时候添加,不然是无法完成操作的
3.因为新生成的包覆层是以族的形式加载到项目文件中,所以,在项目文件关闭之前是无法删除的,为了防止包覆层文
件一直存在,所以在包覆层生成的时候,会执行命令,自动删除日期在今天之前生成的包覆层
代码如下:
var dir = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
//选择模型
Reference eleRef = uiDocument.Selection.PickObject(ObjectType.Element, "请选择需要包覆的实体模型:");
Element pickEle = document.GetElement(eleRef);
//创建几何选项
Options opt = new Options();
opt.ComputeReferences = true;
opt.DetailLevel = ViewDetailLevel.Fine;
//实体转换为几何元件
GeometryElement geoElem = pickEle.get_Geometry(opt);
FaceArray solidFaces = new FaceArray();
foreach (GeometryObject geomObj in geoElem)
{
if (geomObj is Solid)
{
Solid solid = geomObj as Solid;
if (solid != null && 0 != solid.Faces.Size)
{
//得到元素面
solidFaces = solid.Faces;
}
}
else if (geomObj is GeometryInstance)
{
GeometryInstance geomInst = geomObj as GeometryInstance;
GeometryElement instGeomElem = geomInst.GetInstanceGeometry();
foreach (GeometryObject instGeomObj in instGeomElem)
{
if (instGeomObj is Solid)
{
Solid solid = instGeomObj as Solid;
if (solid != null && 0 != solid.Faces.Size)
{
//得到元素面
solidFaces = solid.Faces;
}
}
}
}
}
//循环每个面,获取到法向量,原点。
//构造工作平面,
//根据每个面的所有边,构造常规模型,创建拉伸实体
int count = 0;
List<Element> newElems = new List<Element>();
//因为生成的包覆层模型会加载到项目文件中,在项目关闭之前无法删除,防止占用太多内存,每次执行命令时。会删除保存路径下生成日期在Today之前的文件
DirectoryInfo dyInfo = new DirectoryInfo(Path.Combine(dir, @"RDPN"));
FileInfo[] files = dyInfo.GetFiles();
foreach (FileInfo file in files)
{
if (file.CreationTime < DateTime.Today)
{
file.Delete();
}
}
foreach (Face anyFace in solidFaces)
{
BoundingBoxUV bBox = anyFace.GetBoundingBox();
UV uv = (bBox.Max + bBox.Min) / 2;
//法向量
XYZ faceVect = anyFace.ComputeNormal(uv);
//获取构成面的边
IList<CurveLoop> faceEdg = anyFace.GetEdgesAsCurveLoops();
CurveLoop cl = faceEdg[0];
List<Curve> faceCur = new List<Curve>();
CurveLoop profileloop = CurveLoop.CreateViaOffset(faceEdg[0], 10 / 304.8, faceVect);
CurveLoopIterator iteraor = faceEdg[0].GetCurveLoopIterator();
while (iteraor.MoveNext())
{
Curve cur = iteraor.Current;
faceCur.Add(cur);
}
//建族模型导入,每个人的导入路径都不一样,具体找一下《公制常规模型.rft》这个文件路径就行
string runPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string filePath = Path.Combine(runPath.Substring(0, runPath.LastIndexOf(Path.DirectorySeparatorChar)), @"Revit\Family\公制常规模型.rft");
//创建族文档
Autodesk.Revit.DB.Document familyDoc = revit.Application.Application.NewFamilyDocument(filePath);
//开启事务时,使用的文档,必须是族文档
Transaction familyTrans = new Transaction(familyDoc, "family");
familyTrans.Start();
CurveArrArray curveArrArr = revit.Application.Application.Create.NewCurveArrArray();
CurveArray curveArr = revit.Application.Application.Create.NewCurveArray();
XYZ pos = dropLocation(faceCur);
foreach (Curve cu in faceCur)
{
//将放置位置转换为原点
Curve cur = Line.CreateBound(new XYZ(cu.GetEndPoint(0).X - pos.X, cu.GetEndPoint(0).Y - pos.Y, cu.GetEndPoint(0).Z - pos.Z)
, new XYZ(cu.GetEndPoint(1).X - pos.X, cu.GetEndPoint(1).Y - pos.Y, cu.GetEndPoint(1).Z - pos.Z));
curveArr.Append(cur);
}
curveArrArr.Append(curveArr);
//创建平面
Plane plane = Plane.CreateByNormalAndOrigin(faceVect, new XYZ(0, 0, 0));
//创建草图平面,文档必须是族文档
SketchPlane sp = SketchPlane.Create(familyDoc, plane);
Line li = faceCur[0] as Line;
//创建拉伸,最后的10/304.8是客户的要求10,可以后期修改
var newEle = familyDoc.FamilyCreate.NewExtrusion(true, curveArrArr, sp, 10 / 304.8);
因为生成的包覆层可能还需要添加参数,所以把所有新生成的包覆层统一进行添加参数
FamilyManager manager = familyDoc.FamilyManager;
FamilyParameter param = manager.AddParameter("体积_手动填写", BuiltInParameterGroup.PG_DATA, ParameterType.Text, true);
familyTrans.Commit();
//族文件保存
string settingFile = pickEle.Id.ToString()+"模型包覆层" + count.ToString() + ".rfa";
string filepath = Path.Combine(dir, @"RDPN\" + settingFile);
count++;
familyDoc.SaveAs(filepath);
Transaction familyTrans1 = new Transaction(document, "family2");
familyTrans1.Start();
Family family;
//新建的族加载到当前项目
document.LoadFamily(filepath, out family);
var familySymbolIds = family.GetFamilySymbolIds();
FamilySymbol fs = document.GetElement(familySymbolIds.First()) as FamilySymbol;
//族实例可能需要激活,做一个判断
if (!fs.IsActive)
{
fs.Activate();
}
FamilyInstance fi = document.Create.NewFamilyInstance(pos, fs, pickEle, StructuralType.NonStructural);
newElems.Add(fi);
familyTrans1.Commit();
}
// 因为生成的包覆层可能还需要设置一些参数,所以把所有新生成的包覆层统一进行参数设置
Transaction tr = new Transaction(document, "setpara");
tr.Start();
foreach (Element elem in newElems)
{
ParameterSet attributes = elem.Parameters;
IEnumerator iter = attributes.GetEnumerator();
iter.Reset();
while (iter.MoveNext())
{
Parameter attribute = iter.Current as Autodesk.Revit.DB.Parameter;
Definition information = attribute.Definition;
if (information.Name == "体积_手动填写")
{
//参数设置,写入参数的形式和系统自带的数据形式一样,保留小数点后三位,并且不做四舍五入处理
string volume = elem.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsValueString();
volume = volume.Trim();
volume = volume.Substring(0,volume.Length-2);
double voi = double.Parse(volume) * 0.01;
voi -= 0.0005;
attribute.Set(voi.ToString("N3"));
}
}
}
tr.Commit();
}
//设置包覆层新建族的位置
public XYZ dropLocation(List<Curve> curves)
{
HashSet<XYZ> allPoints = new HashSet<XYZ>();
foreach (Curve cu in curves)
{
allPoints.Add(cu.GetEndPoint(0));
allPoints.Add(cu.GetEndPoint(1));
}
XYZ dropLocation = allPoints.First();
foreach (XYZ pt in allPoints)
{
if (pt.Y < dropLocation.Y)
{
dropLocation = pt;
}
if (pt.Y == dropLocation.Y)
{
dropLocation = pt.X < dropLocation.X ? pt : dropLocation;
}
}
return dropLocation;
}```