Message 1 of 4
Creating dimensions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi forum,
My task is to make the dimensions of the objects that I create with my plugin. I ran into a problem that I can't add references to a variable of the Reference Array type. I have been trying to solve this problem for 2 weeks now, but so far without results, there are many examples of adding dimensions on the Internet, but it seems to me that my case does not come across anywhere.
I'm new to revit api programming, so I'm asking you to help me with my problem. getting the dimensions starts with line 169
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace DeVision.LegendWindows
{
[Transaction(TransactionMode.Manual)]
internal class LegendWindowsCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
using (Transaction trans = new Transaction(doc, "Create Legend Copy and Insert Windows"))
{
trans.Start();
// legend
View originalLegend = new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
.FirstOrDefault(view => view.ViewType == ViewType.Legend);
if (originalLegend == null)
{
message = "Failed to find legend.";
return Result.Failed;
}
// duplicate legend
View duplicatedLegend = doc.GetElement(originalLegend.Duplicate(ViewDuplicateOption.WithDetailing)) as View;
// unique name for legend, so multiple copies can be created
string legendNameBase = "Window Legend";
int counter = 2;
string newLegendName = legendNameBase;
while (new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
.Any(view => view.Name == newLegendName))
{
newLegendName = $"{legendNameBase} {counter++}";
}
duplicatedLegend.Name = newLegendName;
//duplicatedLegend.Name = "Window Legend";
TaskDialog.Show("New Legend Created", $"Legend with name \"{duplicatedLegend.Name}\" and ID {duplicatedLegend.Id} was created.");
if (duplicatedLegend == null)
{
message = "Failed to create legend copy.";
return Result.Failed;
}
trans.Commit();
trans.Start();
// delete elements from new legend
var elementsInLegend = new FilteredElementCollector(doc, duplicatedLegend.Id)
.WhereElementIsNotElementType()
.ToElementIds();
foreach (ElementId elementId in elementsInLegend)
{
Element element = doc.GetElement(elementId);
// delete elements that are not null, have a non-empty category, and whose category does not match the legend view (to avoid deleting the legend itself)
if (element != null && element.Category != null && element.Category.Id.IntegerValue != (int)BuiltInCategory.OST_Views)
{
doc.Delete(elementId);
}
}
// all windows in the project
FilteredElementCollector windowsCollector = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Windows)
.WhereElementIsNotElementType();
List<ElementId> windowIds = windowsCollector
.Select(window => window.Id)
.ToList();
if (windowIds.Count == 0)
{
message = "No windows found in the project.";
return Result.Failed;
}
// component from another legend
Element legendComponent = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_LegendComponents)
.WhereElementIsNotElementType()
.FirstOrDefault();
// id of legendComponent
ElementId legendComponentId = legendComponent.Id;
// id of the legend on which legendComponent is located
ElementId ownerlegendComponent = legendComponent.OwnerViewId;
// name of the legend on which legendComponent is located
Element nameLegend = doc.GetElement(ownerlegendComponent);
//
View nameLegendView = doc.GetElement(nameLegend.Id) as View;
// created a list and added one element (legendComponent) to it
ICollection<ElementId> oneElem = new List<ElementId>();
oneElem.Add(legendComponent.Id);
if (legendComponent == null)
{
message = "Failed to find legend component.";
return Result.Failed;
}
// for offset
double offsetX = 7;
double currentX = 0;
foreach (ElementId windowId in windowIds)
{
// get FamilySymbol of windows and their id (for changing object type)
FamilySymbol windowSymbol = (doc.GetElement(windowId) as FamilyInstance).Symbol;
ElementId windowsSymbolId = windowSymbol.Id;
Transform translation = Transform.CreateTranslation(new XYZ(currentX, 0, 0));
// copy element from the oneElem list
ICollection<ElementId> copiedElementIds = ElementTransformUtils.CopyElements(nameLegendView, oneElem, duplicatedLegend, translation, new CopyPasteOptions());
foreach (ElementId copiedElementId in copiedElementIds)
{
Element copiedElement = doc.GetElement(copiedElementId);
//// text label
// first available text type
TextNoteType textNoteType = new FilteredElementCollector(doc)
.OfClass(typeof(TextNoteType))
.Cast<TextNoteType>()
.FirstOrDefault();
// horizontally centered
TextNoteOptions textNoteOptions = new TextNoteOptions(textNoteType.Id)
{
HorizontalAlignment = HorizontalTextAlignment.Center
};
FamilyInstance originalWindow = doc.GetElement(windowId) as FamilyInstance;
if (originalWindow != null)
{
// get the "ADSK_Mark" parameter from the original window
Parameter markParam = originalWindow.LookupParameter("ADSK_Марка");
string windowMark = markParam.AsString();
// create text
XYZ pointText = new XYZ((copiedElement.get_BoundingBox(duplicatedLegend).Min.X + copiedElement.get_BoundingBox(duplicatedLegend).Max.X) / 2,
copiedElement.get_BoundingBox(duplicatedLegend).Min.Y + 6.5,
0);
TextNote textNote = TextNote.Create(doc, duplicatedLegend.Id, pointText, windowMark, textNoteOptions);
}
// change object type
var parametertype = copiedElement.get_Parameter(BuiltInParameter.LEGEND_COMPONENT);
parametertype.Set(windowsSymbolId);
// change object facade
var parameterView = copiedElement.get_Parameter(BuiltInParameter.LEGEND_COMPONENT_VIEW);
parameterView.Set(-7);
//// dimensions
BoundingBoxXYZ boundingBox = copiedElement.get_BoundingBox(duplicatedLegend);
if (boundingBox == null) continue;
XYZ minPoint = new XYZ(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Min.Z);
XYZ maxPoint = new XYZ(boundingBox.Max.X, boundingBox.Min.Y, boundingBox.Min.Z);
Line line = Line.CreateBound(minPoint, maxPoint);
ReferenceArray array = new ReferenceArray();
Options options = new Options
{
View = duplicatedLegend,
ComputeReferences = true
};
GeometryElement geom = copiedElement.get_Geometry(options);
foreach (GeometryObject go in geom)
{
if (go is Solid solid)
{
// work directly with Solid
ProcessSolid(solid);
}
else if (go is GeometryInstance instance)
{
GeometryElement instanceGeometry = instance.GetInstanceGeometry();
foreach (GeometryObject nestedGo in instanceGeometry)
{
if (nestedGo is Solid nestedSolid)
{
// work with Solid inside GeometryInstance
ProcessSolid(nestedSolid);
}
}
}
}
void ProcessSolid(Solid solid)
{
foreach (Face face in solid.Faces)
{
foreach (EdgeArray edgeArray in face.EdgeLoops)
{
foreach (Edge edge in edgeArray)
{
if (edge.Reference != null &&
edge.Reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR)
{
array.Append(edge.Reference);
}
}
}
}
}
Dimension dimension = doc.Create.NewDimension(duplicatedLegend, line, array);
}
currentX += offsetX;
doc.Regenerate();
}
trans.Commit();
}
return Result.Succeeded;
}
}
}