Family Instance References w/ 2018 API

Family Instance References w/ 2018 API

Anonymous
Not applicable
5,962 Views
10 Replies
Message 1 of 11

Family Instance References w/ 2018 API

Anonymous
Not applicable

I am trying to make a command that makes copies of a family instance at every curtain grid line of a curtain wall and locks them. 

 

I have no trouble making the new family instances, locking them is where I have trouble. I am trying to use the NewAlignment method using...

 

1. CurtainGridLine reference

2. Family instance reference obtained from the 2018 API method GetReferences. 

 

When I tried to run the command I got an error that the family instance reference was not valid. The specific enum I used (CenterLeftRight) for FamilyInstanceReferenceType was the only CenterLeftRight reference in the family and also the reference I needed for the command.

 

Has anyone had similar issues? Maybe some reference types work better than others?

 

Thank you

0 Likes
Accepted solutions (1)
5,963 Views
10 Replies
Replies (10)
Message 2 of 11

Anonymous
Not applicable

Opened the family to verifiy that the reference i'm selecting is a valid reference. Tried changing it to strong, weak, center (front/back) and I get the same error message. Also tried with FamilyInstances of different families and got the same error.

0 Likes
Message 3 of 11

jeremytammik
Autodesk
Autodesk

Dear Adelira,

 

Thank you for your query.

 

I cannot tell what the problem might be from the hints you supply.

 

Maybe it would help if you add a full reproducible case, so we can see which part of the code works and which part fails:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Best regards,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 4 of 11

Anonymous
Not applicable
public static void CopyComponents(this Document doc, FamilyInstance SelectedFI, Wall SelectedWall)
{
//first get the vertical grid lines of a selected wall
List<CurtainGridLine> Verticals = doc.GetElements<CurtainGridLine>
(SelectedWall.CurtainGrid.GetVGridLineIds().ToList());
//create a new family instance at the location of vertical gridlines of selected wall
foreach (var vert in Verticals)
{
//get any point on the vertical curtain grid line
var VertLine = vert.FullCurve.GetEndPoint(0);
//create a placement point at the XY coordinates of the gridline at the height of the selected family instance
XYZ CurtainGridPt = new XYZ(VertLine.X, VertLine.Y,
(SelectedFI.Location as LocationPoint).Point.Z);
//create the new family instance at the location of the curtain grid line
var NewFI = doc.Create.NewFamilyInstance(SelectedFI.HostFace, CurtainGridPt,
SelectedFI.HandOrientation, SelectedFI.Symbol);
//get the (Center (Left/Right) reference inside of the family instance
var FIReference = NewFI.GetReferenceByName("Center (Left/Right)");
//
var NewAlignment = doc.Create.NewAlignment(doc.ActiveView, FIReference, vert.GetReference());
}
}
//extension methods 
public static List<T> GetElements<T>(this Document doc, List<ElementId> ids)
where T : class
{
//get a list of selected elements as specified generic type from list of elemntids
List<T> TList = new List<T>();
foreach (ElementId id in ids)
{
T NewElement = doc.GetElement(id) as T;
if (NewElement != null)
TList.Add(NewElement);
}
return TList;
}
public static Reference GetReference(this CurtainGridLine CurtainGridLine)
{
//get the curve reference of a curtaingridline
Autodesk.Revit.DB.Line GridLineWithRef = null;
foreach(Autodesk.Revit.DB.Line line in CurtainGridLine.get_Geometry(NewOptions()))
{
try
{
GridLineWithRef = line; //get a line with valid reference from geometry element
}
catch (System.Exception)
{
}
}
return GridLineWithRef.Reference;
}



 

This is simplified version of what my program does. The error occurs in CopyComponents when it tries to use the family instance reference FIReference. I've attached a test family I used, and I can post the code for the command too if needed. (selects the family instance and wall and starts transaction)

 

Thank you

0 Likes
Message 5 of 11

Anonymous
Not applicable

Okay, so I think I figured out what the problem is.

 

It seems like family instances created with the doc.Create.NewFamilyInstance() method do not have valid references available.

 

Family instances I create this way return null when using the FamilyInstance.GetReference() method. However family instances I create through the UI return valid references.

 

Hopefully I am just missing something and this is not a bug?

 

Thank you.

0 Likes
Message 6 of 11

Revitalizer
Advisor
Advisor

Hi,

 

perhaps the document needs to be regenerated after FamilyInstance creation, before getting valid references from the newly created FamilyInstances.

 

Or you could use a TransactionGroup, containing two separate transactions, one for creating the FamilyInstances, another one for getting and using their references.

 

 

Revitalizer




Rudolf Honke
Software Developer
Mensch und Maschine





Message 7 of 11

jeremytammik
Autodesk
Autodesk

Dear Adelira and Revitalizer,

 

Thank you for your update and suggestions.

 

Yes indeed, this sound like another example of the Need to Regenerate:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.33

 

Please confirm that it works, and how.

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 8 of 11

Anonymous
Not applicable

Tried the doc.Regenerate() method. Still get null for references that are normally returned as valid references from UI created family instances.

 

0 Likes
Message 9 of 11

Anonymous
Not applicable
Accepted solution

It ended up being an issue with the family I was trying to get the reference from. I had named two almost identical families very similar and one of them did not have the reference I was looking for.

 

Things are working great now.

 

Thank you for your suggestions guys.

0 Likes
Message 10 of 11

Anonymous
Not applicable

Hello everyone.
I'm trying to do something similar, namely to get a reference from a CurtainGridLine. As shown above. But from CurtainGridLine a related geometry I get only lines, and I can not extract the reference from them, because Line Class does not have a reference parameter, unlike Curve Class.

Where am I wrong, it seems that something is quite simple?

p.s. Yes its python:

 

rp = UnwrapElement(IN[1]) #Some Reference Plane
cgl = UnwrapElement(IN[2]) #CurtineGridLine
rpref = rp.GetReference()
r222 = 0
rptype = rpref.ElementReferenceType
cglref = Reference(cgl)
cgltype = cglref.ElementReferenceType

TransactionManager.Instance.EnsureInTransaction(doc)

#r22 = uidoc.Selection.PickObject(Selection.ObjectType.Edge, 'Pick first face for reference')

options = Options()
options.ComputeReferences = True
options.IncludeNonVisibleObjects = True
options.DetailLevel = ViewDetailLevel.Fine
 
geomElem = cgl.get_Geometry(options)
gridRef = Reference.ParseFromStableRepresentation(doc, cgl.UniqueId).ElementReferenceType

#lockedAlign = doc.Create.NewAlignment(view, r11, geomElem)
r222 = 0
for gr in geomElem:
	try:
		r222 = Reference(gr)
	except:	
		pass
TransactionManager.Instance.TransactionTaskDone()

#OUT = view , lockedAlign

OUT = ["Need reference here", r222], ["StableReference", gridRef], ["Geometry from CGL", geomElem], ["RP ref type", rptype], ["CGL ref type", cgltype]

 Python OUT.png

 

0 Likes
Message 11 of 11

Anonymous
Not applicable

Try using this method to get the reference from a curtaingridline. I believe I used this because sometimes curtaingridlines have segments with lines and segments without lines and I was getting an exception. This ensures you get a segment with a reference.

 

public static Reference GetReference(this CurtainGridLine CurtainGridLine)

{

Autodesk.Revit.DB.Line GridLineWithRef = null;

foreach(Autodesk.Revit.DB.Line line in CurtainGridLine.get_Geometry(NewOptions()))

{

try

{

GridLineWithRef = line; //get a line with valid reference from geometry element

}

catch (System.Exception)

{

}

}

return GridLineWithRef.Reference;

}

 

public static Options NewOptions()

{

Options DefaultOptions = new Options();

DefaultOptions.ComputeReferences = true;

DefaultOptions.IncludeNonVisibleObjects = true;

return DefaultOptions;

}

 

 

0 Likes