Revit API C# 插入和旋转族
Revit API C# Insert and Rotate Family
我正在尝试插入一个元素并将其旋转 90 度,但在获取 ElementId 以使用 ElementTransformUtils.RotateElement 时遇到问题,我已尝试按顺序遵循 https://thebuildingcoder.typepad.com/blog/2010/06/place-family-instance.html在我插入元素并通过 GetAddedElementIds 获取元素 Id 之前设置一个事件处理程序,但我无法让它为我工作:(
在这方面,我将不胜感激。
下面是我的代码,我开始一个事务来放置家庭(符号),我做了一个 for 循环来插入 5 次,我想将插入的元素旋转 90 度,我尝试在for 循环在插入每个元素时旋转它们,但也许只在 1 条指令中旋转所有插入的元素会更好?
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
}
trans.Commit();
}
非常感谢。
--编辑--
我确实认为可以使用的代码如下所示,但是,当我尝试执行它时,它指出:"Error: Sequence contains no elements"
代码:
if (!symbol4.IsActive)
{
symbol4.Activate();
}
for (int x = 0; x < 4; x++)
{
double xloc = x * BayLength / 304.8;
_added_element_ids.Clear();
app.DocumentChanged += new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged);
doc.Create.NewFamilyInstance(new XYZ(xloc, 0, 1.021), symbol4, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
app.DocumentChanged -= new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged);
ElementId LastModifiedElementId = _added_element_ids.Last();
XYZ p1= new XYZ(xloc, 0.0, 1.021);
XYZ p2 = new XYZ(xloc, 0.0, 2.021);
Line Axis = Line.CreateBound(p1, p2);
double angle = -90 * Math.PI / 180;
ElementTransformUtils.RotateElement(doc, LastModifiedElementId, Axis, angle);
}
void OnDocumentChanged(object sender, DocumentChangedEventArgs e)
{
_added_element_ids.AddRange(e.GetAddedElementIds());
}
如有任何帮助,我将不胜感激,谢谢
有两种方法可以解决这个问题,而且都不需要使用 DocumentChanged 事件。困难的部分是弄清楚旋转轴使用什么。
第一种方法在创建后立即使用 RotateElement:
public void PlaceAndRotateFamilyMethod1()
{
Document doc = this.ActiveUIDocument.Document;
FamilySymbol symbol = GetFamilySymbolToPlace(doc);
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
FamilyInstance fi = doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
XYZ point1 = new XYZ(0, 10, 0);
XYZ point2 = new XYZ(0, 10, 10);
Line axis = Line.CreateBound(point1, point2);
double angleToRotate = 45;
ElementTransformUtils.RotateElement(doc, fi.Id, axis, ConvertToRadians(angleToRotate));
}
trans.Commit();
}
}
第二种方法使用第二个事务来旋转元素,因为在这种方法中我使用了元素的边界框来获取它的中心。必须先完成创建事务才能获取其 BoundingBox。
public void PlaceAndRotateFamilyMethod2()
{
Document doc = this.ActiveUIDocument.Document;
FamilySymbol symbol = GetFamilySymbolToPlace(doc);
List<FamilyInstance> newFamInstToRotate = new List<FamilyInstance>();
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
FamilyInstance fi = doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
newFamInstToRotate.Add(fi);
}
trans.Commit();
}
using (Transaction trans = new Transaction(doc, "Rotate Families"))
{
trans.Start();
foreach (FamilyInstance fi in newFamInstToRotate)
{
XYZ center = (fi.get_BoundingBox(doc.ActiveView).Max + fi.get_BoundingBox(doc.ActiveView).Min) * 0.5;
Line axis = Line.CreateBound(center, center + XYZ.BasisZ);
double angleToRotate = 45;
ElementTransformUtils.RotateElement(doc, fi.Id, axis, ConvertToRadians(angleToRotate));
}
trans.Commit();
}
}
辅助方法:
private FamilySymbol GetFamilySymbolToPlace(Document doc)
{
FamilySymbol symbol = null;
foreach (FamilySymbol fSym in new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Furniture))
{
if (fSym.FamilyName == "Desk" && fSym.Name == "60\" x 30\"")
{
symbol = fSym;
break;
}
}
return symbol;
}
private double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
我正在尝试插入一个元素并将其旋转 90 度,但在获取 ElementId 以使用 ElementTransformUtils.RotateElement 时遇到问题,我已尝试按顺序遵循 https://thebuildingcoder.typepad.com/blog/2010/06/place-family-instance.html在我插入元素并通过 GetAddedElementIds 获取元素 Id 之前设置一个事件处理程序,但我无法让它为我工作:(
在这方面,我将不胜感激。
下面是我的代码,我开始一个事务来放置家庭(符号),我做了一个 for 循环来插入 5 次,我想将插入的元素旋转 90 度,我尝试在for 循环在插入每个元素时旋转它们,但也许只在 1 条指令中旋转所有插入的元素会更好?
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
}
trans.Commit();
}
非常感谢。
--编辑--
我确实认为可以使用的代码如下所示,但是,当我尝试执行它时,它指出:"Error: Sequence contains no elements"
代码:
if (!symbol4.IsActive)
{
symbol4.Activate();
}
for (int x = 0; x < 4; x++)
{
double xloc = x * BayLength / 304.8;
_added_element_ids.Clear();
app.DocumentChanged += new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged);
doc.Create.NewFamilyInstance(new XYZ(xloc, 0, 1.021), symbol4, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
app.DocumentChanged -= new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged);
ElementId LastModifiedElementId = _added_element_ids.Last();
XYZ p1= new XYZ(xloc, 0.0, 1.021);
XYZ p2 = new XYZ(xloc, 0.0, 2.021);
Line Axis = Line.CreateBound(p1, p2);
double angle = -90 * Math.PI / 180;
ElementTransformUtils.RotateElement(doc, LastModifiedElementId, Axis, angle);
}
void OnDocumentChanged(object sender, DocumentChangedEventArgs e)
{
_added_element_ids.AddRange(e.GetAddedElementIds());
}
如有任何帮助,我将不胜感激,谢谢
有两种方法可以解决这个问题,而且都不需要使用 DocumentChanged 事件。困难的部分是弄清楚旋转轴使用什么。 第一种方法在创建后立即使用 RotateElement:
public void PlaceAndRotateFamilyMethod1()
{
Document doc = this.ActiveUIDocument.Document;
FamilySymbol symbol = GetFamilySymbolToPlace(doc);
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
FamilyInstance fi = doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
XYZ point1 = new XYZ(0, 10, 0);
XYZ point2 = new XYZ(0, 10, 10);
Line axis = Line.CreateBound(point1, point2);
double angleToRotate = 45;
ElementTransformUtils.RotateElement(doc, fi.Id, axis, ConvertToRadians(angleToRotate));
}
trans.Commit();
}
}
第二种方法使用第二个事务来旋转元素,因为在这种方法中我使用了元素的边界框来获取它的中心。必须先完成创建事务才能获取其 BoundingBox。
public void PlaceAndRotateFamilyMethod2()
{
Document doc = this.ActiveUIDocument.Document;
FamilySymbol symbol = GetFamilySymbolToPlace(doc);
List<FamilyInstance> newFamInstToRotate = new List<FamilyInstance>();
using (Transaction trans = new Transaction(doc, "Place Family"))
{
trans.Start();
if (!symbol.IsActive)
{
symbol.Activate();
}
for (int x = 0; x < 5; x++)
{
FamilyInstance fi = doc.Create.NewFamilyInstance(new XYZ(x, 0, 0), symbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
newFamInstToRotate.Add(fi);
}
trans.Commit();
}
using (Transaction trans = new Transaction(doc, "Rotate Families"))
{
trans.Start();
foreach (FamilyInstance fi in newFamInstToRotate)
{
XYZ center = (fi.get_BoundingBox(doc.ActiveView).Max + fi.get_BoundingBox(doc.ActiveView).Min) * 0.5;
Line axis = Line.CreateBound(center, center + XYZ.BasisZ);
double angleToRotate = 45;
ElementTransformUtils.RotateElement(doc, fi.Id, axis, ConvertToRadians(angleToRotate));
}
trans.Commit();
}
}
辅助方法:
private FamilySymbol GetFamilySymbolToPlace(Document doc)
{
FamilySymbol symbol = null;
foreach (FamilySymbol fSym in new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Furniture))
{
if (fSym.FamilyName == "Desk" && fSym.Name == "60\" x 30\"")
{
symbol = fSym;
break;
}
}
return symbol;
}
private double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}