How to Use NewFamilyInstance on Opposite Side of Wall for Wall-Mounted Families

Anonymous

How to Use NewFamilyInstance on Opposite Side of Wall for Wall-Mounted Families

Anonymous
Not applicable

I made a simple wall-mounted family using the "Generic Model wall based.rft" template. The family is just an extrusion attached to the top side of the wall as viewed in the Ref. Level

 

wall-mounted-box.rfa:

wall-mounted-box.PNG

I want to import this wall-mounted-box.rfa into another Family (I will call this import.rfa) that also uses the "Generic Model wall based.rft" template. I want to place the box on the opposite side of the wall though, like the picture below. I can do this easily within the Revit UI. But I can't figure it out with the Revit API.

 

import.rfa:

Capture.PNG

 

Here is code showing the methods I've tested

 

string templateFileName =
    @"C:\ProgramData\Autodesk\RAC 2016\Family Templates\English_I\Generic Model wall based.rft";
Document document = uiApplication.Application.NewFamilyDocument(templateFileName);
Family family;
using (Transaction transaction = new Transaction(document))
{
    transaction.Start("Load Family");
    document.LoadFamily(@"...\wall-mounted-box.rft", out family);
    transaction.Commit();
}
FamilySymbol symbol = document.GetElement(family.GetFamilySymbolIds().First()) as FamilySymbol;

FilteredElementCollector wallCollector = new FilteredElementCollector(document);
Wall wall = wallCollector.OfClass(typeof(Wall)).FirstElement() as Wall;

using (Transaction transaction = new Transaction(document))
{
    tx.Start("Instantiate Family");
    symbol.Activate();
    // METHOD 1: Default wall host
    FamilyInstance familyInstance = document.FamilyCreate.NewFamilyInstance(new XYZ(0,0,0), symbol, wall, StructuralType.NonStructural);
    
    // METHOD 2: try setting referenceDirection
    document.FamilyCreate.NewFamilyInstance(new XYZ(0,0,0), symbol, new XYZ(0,-1,0), wall, StructuralType.NonStructural);

// METHOD 3: Try flipping the FamilyInstance
familyInstance.flipFacing();

// setup for METHOD 4/5 Reference reference = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Interior).First(); // METHOD 4: use reference to face with method from this site // http://adndevblog.typepad.com/aec/2015/06/revitapi-create-familyinstance-on-a-wall-face.html document.FamilyCreate.NewFamilyInstance(reference, new XYZ(0, 0, 0), new XYZ(0, -1, 0), symbol); // METHOD 5: Get the face to place on // I just grabbed the index-2 face arbitrarily since this method doesn't work anyways Options opt = new Options(); opt.ComputeReferences = true; Face face = (wall.get_Geometry(opt).First() as Solid).Faces.get_Item(2); document.FamilyCreate.NewFamilyInstance(face, new XYZ(0, 0, 0), new XYZ(0, -1, 0), symbol); tx.Commit(); } SaveAsOptions saveAsOptions = new SaveAsOptions(); saveAsOptions.OverwriteExistingFile = true; document.SaveAs(@"...\import.rft", saveAsOptions);

 

METHOD 1 and METHOD 2 just places the box on the default side of the wall which is the top. Looks exactly like the wall-mounted-box.rfa picture.

 

METHOD 3 doesn't work because familyInstance.CanFlipFacing is false.

Here are the properties I grabbed from FamilyInstances I creating using the Revit UI.

 

default orientation on top of wall:

2017-07-18

 

opposite orientation on bottom of wall:

2017-07-18

 

METHOD 5 says "Family cannot be placed as hosted on an input face reference, because its FamilyPlacementType is not WorkPlaneBased"

METHOD 4 also says that FamilyPlacementType is not WorkPlaneBase.

 

How do I do this?

0 Likes
Reply
Accepted solutions (1)
1,609 Views
3 Replies
Replies (3)

FAIR59
Advisor
Advisor
Accepted solution

You can mirror the family twice, first  X-axis, then Y-axis.

 

			FamilyInstance temp=null;
			using (Transaction t = new Transaction(doc,"place instance"))
			{
				t.Start();
			
			using (SubTransaction st = new SubTransaction(doc))
			{
				st.Start();
				temp = doc.FamilyCreate.NewFamilyInstance(new XYZ(0,0,0), symb, new XYZ(1,0,0), wall,StructuralType.NonStructural);
				st.Commit();
			}
			IList<ElementId> mirrored = null;
			using (SubTransaction st = new SubTransaction(doc))
			{
				st.Start();
				mirrored = ElementTransformUtils.MirrorElements(doc,new List<ElementId>(){temp.Id},new Plane(XYZ.BasisY,XYZ.Zero),true);
			 	doc.Delete(temp.Id);
				st.Commit();
			}
			List<ElementId> mirrored2 = new List<ElementId>();
			foreach (var id in mirrored)
			{
				Element e = doc .GetElement(id);
				if (e==null) continue;
				mirrored2.Add(id);
			}
			using (SubTransaction st = new SubTransaction(doc))
			{
				st.Start();
				mirrored = ElementTransformUtils.MirrorElements(doc,mirrored2,new Plane(XYZ.BasisX,XYZ.Zero),true);
			 	doc.Delete(mirrored2);
				st.Commit();
			}
			t.Commit();
			}

 

Anonymous
Not applicable

Thanks Fair59, it works. I'm just wondering, how come you have to check for e==null? Will it ever be null from the output of MirrorElements()? You are just trying to create a copy of mirrored in mirrored2 right?

0 Likes

FAIR59
Advisor
Advisor

It seems I didn't clean up the code sufficiently, that is a remnant of some test code. Just making a copy will work.