@Moustafa_K thanks for the link!
I actually modified the method to fit my needs a little more. I actually assign those properties in code to the Area elements (for know) But I will have to add another functionality to only pick certain Generic Mass Elements from the Revit document. What I mean by that is to only assign those Shared Parameters to the created Direct Shape Masses which are of a Generic Mass Category. Ignore all the mess at the end of the method: options2... areaSharedParamDef2...
I will refine this later.
Here is the method:
private static void CreateSharedParameter(Autodesk.Revit.DB.Document doc, string name, string group, ParameterType type)
{
// Initilaize transaction
TransactionManager.Instance.EnsureInTransaction(doc);
try
{
DefinitionFile defFile = doc.Application.OpenSharedParameterFile();
String modulePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
String paramFile = modulePath + "\\AreasSharedParameters.txt";
// check whether shared parameter exists
if (defFile == null)
{
// create shared parameter file
if (File.Exists(paramFile))
{
File.Delete(paramFile);
}
FileStream fs = File.Create(paramFile);
fs.Close();
}
else
{
// cache application
Autodesk.Revit.ApplicationServices.Application revitApp = doc.Application;
// prepare shared parameter file
revitApp.SharedParametersFilename = paramFile;
// open shared parameter file
DefinitionFile parafile = revitApp.OpenSharedParameterFile();
// create a group
DefinitionGroup apiGroup = parafile.Groups.Create(group);
ExternalDefinitionCreationOptions options = new ExternalDefinitionCreationOptions(name, type);
ExternalDefinitionCreationOptions options2 = new ExternalDefinitionCreationOptions("Comments", ParameterType.Text);
// create parameter
Definition areaSharedParamDef = apiGroup.Definitions.Create(options);
Definition areaSharedParamDef2 = apiGroup.Definitions.Create(options2);
// get Areas category
Autodesk.Revit.DB.Category areaCat = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Areas);
CategorySet categories = revitApp.Create.NewCategorySet();
categories.Insert(areaCat);
// insert the new parameter
InstanceBinding binding = revitApp.Create.NewInstanceBinding(categories);
doc.ParameterBindings.Insert(areaSharedParamDef, binding);
doc.ParameterBindings.Insert(areaSharedParamDef2, binding);
}
}
catch (Exception ex)
{
throw new Exception("Failed to create shared parameter: " + ex.Message);
}
// Finalize transaction
TransactionManager.Instance.TransactionTaskDone();
}
Called within another method wrapped in a Dynamo node:
public static void CreateSharedParameter()
{
// Get current document
Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument;
CreateSharedParameter(doc, "Volume", "Areas Custom Properties", ParameterType.Volume);
}
@jeremytammik thank you as well for your prompt reply! I did remove the Dispose() but I still got those weird properties. I thought that since I am not returning the actually geometry from the method I had to manually dispose it from the Dynamo node, but I guess not?
But I have a much more worrysome problem I am having! The previous method I posted above was actually a separate test that I was doing, because when I try to use it with my actual geometry Dynamo and Revit freeze for some strange reason, and I dont have any idea why.
By the way I also found this post in your blog that is quite similar to what I am trying to do and it was very helpful:
https://thebuildingcoder.typepad.com/blog/2019/05/generate-directshape-element-to-represent-room-vol...
Its great how you added the Rooms properties in to its corresponding Direct Shape
here is the whole method:
[Autodesk.DesignScript.Runtime.MultiReturn(new[] { "Volumnes","Heights", "Boundary Curve", "Area Names"})] // wrappedRevitLevel
public static Dictionary<string, object> GetAreasByProperties(List<wrappedRevitElement> areaObjects, wrappedRevitLevel level, List<wrappedRevitElement> levelObjects, string inputAreaName,
bool filterByName, bool filterByLevel)
{
// Get current document
Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument;
// Initilaize transaction
TransactionManager.Instance.EnsureInTransaction(doc);
SpatialElementBoundaryOptions bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions();
// Create Revit Element list
List<unwrappedRevitElement> revitElements = new List<unwrappedRevitElement>();
List<string> JsonStrings = new List<string>();
// Create Level Elevation list
List<double> areaObjectElevations = new List<double>();
//
List<Area> areaObjectsTemp = new List<Area>();
// Loop through all wrapped Revit Elements and unwrapp them
for (int i = 0; i < areaObjects.Count; i++)
{
revitElements.Add(areaObjects[i].InternalElement);
}
// Convert Dynamo Level to Revit Level
unwrappedRevitLevel revitLevel = level.InternalElement as Autodesk.Revit.DB.Level;
// Get all Area object names
List<string> objectAreaNames = GetAllParametersByName(areaObjects,"Name");
// filter by name
string areaObjectName = GetAreaName(objectAreaNames, inputAreaName);
////////////////////////////////////////////// OUTPUTS //////////////////////////////////////////////
List<Autodesk.DesignScript.Geometry.PolyCurve> boundary = new List<Autodesk.DesignScript.Geometry.PolyCurve>();
List<string> areaNames = new List<string>();
List<double> heights = new List<double>();
List<Autodesk.DesignScript.Geometry.Solid> volumes = new List<Autodesk.DesignScript.Geometry.Solid>();
List<Autodesk.DesignScript.Geometry.Curve> crvs = new List<Autodesk.DesignScript.Geometry.Curve>();
////////////////////////////////////////////// OUTPUTS //////////////////////////////////////////////
#region FILTER BY NAME AND BY LEVEL
if (filterByName == true && filterByLevel == true)
{
XYZ firstCrvSrtPoint = new XYZ();
Area areaObj = null;
foreach (var item in revitElements)
{
if (item.Category.Name == "Areas")
{
areaObj = item as Area;
areaObjectElevations.Add(areaObj.Level.Elevation);
areaObjectsTemp.Add(areaObj);
if (areaObjectName == inputAreaName && areaObj.Level.Name == revitLevel.Name)
{
areaNames.Add(areaObj.Name);
List<XYZ> BoundaryCrvSegmentEndpoints = new List<XYZ>();
if (areaObj.Area <= 0) throw new ArgumentException("Area Element must have an Area greater than 0!");
else
{
string json = CreateJsonFromElementProperties(areaObj);
JsonStrings.Add(json);
IList<IList<BoundarySegment>> boundSegments = areaObj.GetBoundarySegments(bOptions);
for (int i = 0; i < boundSegments.Count; i++)
{
IList<BoundarySegment> data = boundSegments[i];
int count = 0;
for (int j = 0; j < data.Count; j++)
{
crvs.Add(data[j].GetCurve().ToProtoType());
count++;
if (count == 1)
{
Curve c = data[j].GetCurve();
firstCrvSrtPoint = c.GetEndPoint(0);
c.Dispose();
}
Curve unwrappedRevitCurve = data[j].GetCurve();
BoundaryCrvSegmentEndpoints.Add(unwrappedRevitCurve.GetEndPoint(0)); // 0 index for start point
// Dispose unwrappedRevitCurve Revit curve
unwrappedRevitCurve.Dispose();
}
}
}
BoundaryCrvSegmentEndpoints.Add(firstCrvSrtPoint);
boundary.Add(PolyLine.Create(BoundaryCrvSegmentEndpoints).ToProtoType());
//dispose points after used to create polyline
foreach (XYZ point in BoundaryCrvSegmentEndpoints)
{
point.ToPoint().Dispose();
}
}
}
else
{
throw new ArgumentException("Your Elements need to be of Category of type Area!");
}
}
bOptions.Dispose();
firstCrvSrtPoint.ToPoint().Dispose();
if (boundary.Count == 1)
{
unwrappedRevitLevel nextLevelUp = GetNextLevelUp(areaObj, levelObjects);
double nextLevelUpElevation = nextLevelUp.Elevation * 304.8; // convert decimal feet to mm
double areaObjElevation = areaObj.Level.Elevation * 304.8; // convert decimal feet to mm
double extrusionHeight = nextLevelUpElevation - areaObjElevation;
heights.Add(extrusionHeight);
// Create volumes
for (int i = 0; i < boundary.Count; i++)
{
Autodesk.DesignScript.Geometry.Solid solid = boundary[i].ExtrudeAsSolid(Autodesk.DesignScript.Geometry.Vector.ZAxis(), extrusionHeight);
volumes.Add(solid);
CreateDirectShape(doc, solid, JsonStrings[i], areaNames[i]);
}
}
if(boundary.Count > 1)
{
// // Sort area objects on their height
//List<Area> sortedAreaObjects = SortAreaObjectsOnHeight(areaObjectsTemp);
// for (int i = 0; i < sortedAreaObjects.Count; i++)
// {
// // Get the current Area Object's upper level
// unwrappedRevitLevel nextLevelUp = GetNextLevelUp(sortedAreaObjects[i], levelObjects);
// // Calculate extrusion height
// double extrusionHeight = (nextLevelUp.Elevation * 304.8) - (sortedAreaObjects[i].Level.Elevation * 304.8);
// heights.Add(extrusionHeight);
// }
// for (int i = 0; i < boundary.Count; i++)
// {
// // NOTE : SOLID CLASS CONTAINS METHOD TO CRERATE FAMILY TYPE!
// Autodesk.DesignScript.Geometry.Solid solid = boundary[i].ExtrudeAsSolid(Autodesk.DesignScript.Geometry.Vector.ZAxis(),heights[i]);
// volumes.Add(solid);
// }
}
}
TransactionManager.Instance.TransactionTaskDone();
return new Dictionary<string, object>
{
{"Volumnes", volumes },
{"Heights", heights },
{"Boundary Curve", boundary },
{"Area Names", areaNames },
};
}
Sorry for such a long post and thanks again!