Replace Family by another Family

Hey guys,

I’m searching for a method to replace familyinstances (of the same category). I don’t want to change the type! I want to change the whole family using dynamo.

I’ve tried to get the points of the existing instances and place the new instances by this information. But I’m not able to get the reference plane or face for placing the new instances correctly.

Any better ideas around here?

Thanks in advance,
Martin

Hey,

Was there a reason that you weren’t using familyinstance.bypoint?

If you are needing to place a face based family, perhaps this topic is of interest…

http://dynamobim.org/forums/topic/place-a-face-based-family/

Hope that helps,

Mark

1 Like

Which kind of host has it? If it is hosted in a wall, you can’t input a face (I have just tried it)

Is it completely impossible in Dynamo to replace a family with another one???

Thanks for your reply!

If I use familyinstance.bypoint, I can’t change the families host. So I can’t move it later (or set it to a refPlane).

Thanks for the hint of using familyInstance.byFacePoints. I’ll give it a try later.

cheers,
Martin

In the most cases, the host should be a ceiling. The Family itself was created using the face-based template.

Martin

In that case you can try to use Element.Faces to get the face of the ceiling and feed FamilyInstance.ByFace with it

1 Like

Thanks for your help! I’ve tried it yesterday: If i delete the “first” family, the host of the “second” family changes to “not associated”. In case of moving the ceiling, the second family won’t move with it.

I’ve also tried to set the parameter “host” by the value of the first family (familyInstance.getHost). Unfortunately it is a read-only Parameter.

edit: I read your post again… If i use element.faces of the host (ceiling) of the first family, the elevation is set to “0” … I keep trying :slight_smile:

As long as the hosting is the same you just need to use SetParameterByName node to set the family. If you’re changing from say a point-and-place family to a face based family you will have to create a new instance with the appropriate hosting in mind.

2 Likes

Thanks everyone!

I got it. I had to pick the “right” surface. I don’t know wheter thats the best solution but it works fine for me. See Picture below

cheers
Martin

Hi MrMinister,
Can I have your full image of this script? Cause I also do some stuff relate to your idea.
Thank you.

Hi Peter,

I couldn’t find the script for now. But imho there is nothing important missing.

Input of the FamilyInstance.GetHost node is the list of the “old” instances.
Input of the FamilyInstance.ByFace node is the list of the “new” instances.

Martin

I trying to replace family as well using set parameter value by Name … and I define the parameter name as Family but it isn’t working anyone has an idea?

With Dynamo it looks like this: (pardon the mess of it, it was a draft script)


More complex and a cross of Dynamo/Python:

import clr
import sys

pyPath = r"C:\Program Files (x86)\IronPython 2.7\Lib"
sys.path.append(pyPath)

import System 
import System.Collections
#Access to Revit Document
clr.AddReference("RevitServices")
import RevitServices
#To Get Doc, UI and Application Objects
from RevitServices.Persistence import DocumentManager
#Needed to make any changes in Revit
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *

from Autodesk.Revit.DB.Structure import *
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import *
import traceback

doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIDocument
app = DocumentManager.Instance.CurrentUIApplication.Application


#Define Lists

elemTypeName = []

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
famTypeToChange = IN[0]
famTypeToChangeTo = IN[1]

famTypeToChangeName = famTypeToChange.Name.ToString()
famTypeToChangeFamName = UnwrapElement(famTypeToChange).FamilyName.ToString()

famTypeToChangeToName = famTypeToChangeTo.Name.ToString()
famTypeToChangeToFamName = UnwrapElement(famTypeToChange).FamilyName.ToString()



TransactionManager.Instance.EnsureInTransaction(doc)
#Get Elements with Family Name Matching info Above

string = famTypeToChangeFamName
case = IN[2]
search = "Family"

bips = System.Enum.GetValues(BuiltInParameter)

bm = doc.ParameterBindings
bmlist = bm.ForwardIterator()
paramId = None
testout = []
while bmlist.MoveNext():
	binddef = bmlist.Key
	testout.append(binddef.Name)
	if binddef.Name == search:
		paramId = binddef.Id
		break

param = None
if paramId == None:
	biplist = []
	for bip in bips:
		try:
			name = LabelUtils.GetLabelFor(bip)
		except:
			continue
		if name == search:
			biplist.append(bip)

sharedparamrule = SharedParameterApplicableRule(search)

evaluator = FilterStringContains()
parameter = None
if paramId == None and len(biplist) == 0:
	coll = FilteredElementCollector(doc)
	sharedparams = coll.OfClass(ParameterElement)
	
	for param in sharedparams:
		name = param.GetDefinition().Name
		if name == search:
			parameter = param
	
	if parameter != None:
		ruleslist = List[FilterRule]()
		provider = ParameterValueProvider(parameter.Id)
		filterrule = FilterStringRule(provider, evaluator, string , case)
		ruleslist.Add(filterrule)
		ruleslist.Add(sharedparamrule)
		paramFilter = ElementParameterFilter(ruleslist)
		collector = FilteredElementCollector(doc)
		collector.OfClass(FamilyInstance).WherePasses(paramFilter)
		
		collector2 = FilteredElementCollector(doc)
		collector2.OfClass(HostObject).WherePasses(paramFilter)
		collector2.UnionWith(collector)

		
elif paramId == None:
	if len(biplist) == 1:
		provider = ParameterValueProvider(ElementId(biplist[0]))
		filterrule = FilterStringRule(provider, evaluator, string , case)
		paramFilter = ElementParameterFilter(filterrule)
		collector = FilteredElementCollector(doc)
		collector.OfClass(FamilyInstance).WherePasses(paramFilter)
		
		collector2 = FilteredElementCollector(doc)
		collector2.OfClass(HostObject).WherePasses(paramFilter)
		collector2.UnionWith(collector)
	else:
		provider = ParameterValueProvider(ElementId(biplist[0]))
		filterrule = FilterStringRule(provider, evaluator, string , case)
		paramFilter = ElementParameterFilter(filterrule)
		collector = FilteredElementCollector(doc)
		collector.OfClass(FamilyInstance).WherePasses(paramFilter)
		
		collector2 = FilteredElementCollector(doc)
		collector2.OfClass(HostObject).WherePasses(paramFilter)
		collector2.UnionWith(collector)
		for i,param in enumerate(biplist):
			if i == 0:
				continue
			provider = ParameterValueProvider(ElementId(param))
			filterrule = FilterStringRule(provider, evaluator, string , case)
			paramFilter = ElementParameterFilter(filterrule)
			tempcollector1 = FilteredElementCollector(doc)
			tempcollector1.OfClass(FamilyInstance).WherePasses(paramFilter)
			tempcollector2 = FilteredElementCollector(doc)
			tempcollector2.OfClass(HostObject).WherePasses(paramFilter)
			tempcollector2.UnionWith(tempcollector1)
			collector2.UnionWith(tempcollector2)
	
else:
	ruleslist = List[FilterRule]()
	provider = ParameterValueProvider(paramId)
	filterrule = FilterStringRule(provider, evaluator, string , case)
	ruleslist.Add(filterrule)
	ruleslist.Add(sharedparamrule)
	paramFilter = ElementParameterFilter(ruleslist)
	collector = FilteredElementCollector(doc)
	collector.OfClass(FamilyInstance).WherePasses(paramFilter)
	
	collector2 = FilteredElementCollector(doc)
	collector2.OfClass(HostObject).WherePasses(paramFilter)
	collector2.UnionWith(collector)
if parameter == None and paramId == None and len(biplist) == 0:
	OUT = "Does not work with non-shared family parameters"
else:
	elements = collector2.ToElements()
TransactionManager.Instance.EnsureInTransaction(doc)

#Check Family Names of Selected, check to ensure Family Type Matches Also
try:
	elems = []
	for e in elements:
		elemTypeName = e.Name == famTypeToChangeName
		if elemTypeName == True:
			elems.append(e)
		
		
except:
	OUT = elemTypeName = "No Elements Match"


#Get All Parameter Names, and Values for Any that have a value
#Set New Family Name and Type, Set Parameter Values
Output = []
try:
		
	for setElems in elems:
		Output.append("Start")
		elemParamMap = []
		filterReadOnlyFalseAll = []
		elemParamName = []
		elemParamNameAll = []
		elemParamValue = []
		elemParamValueAll = []
		parameter = []

		elemParamMap = setElems.ParametersMap
		for ePS in elemParamMap:
			if not ePS.IsReadOnly:
				filterReadOnlyFalseAll.append(ePS)
		for fROFA in filterReadOnlyFalseAll:
			if fROFA.UserModifiable:
				elemParamName = fROFA.Definition.Name
				elemParamNameAll.append(elemParamName)
				elemParamValue = None
				if fROFA.StorageType == StorageType.String:
					elemParamValue = fROFA.AsString()
				else:
					elemParamValue = fROFA.AsValueString()
				elemParamValueAll.append(elemParamValue)

		TransactionManager.Instance.EnsureInTransaction(doc)
		setElems.ChangeTypeId(UnwrapElement(famTypeToChangeTo).Id)
		TransactionManager.Instance.EnsureInTransaction(doc)

		TransactionManager.Instance.EnsureInTransaction(doc)
		for elemParamName, elemParamValue in zip(elemParamNameAll, elemParamValueAll):
			if elemParamValue == elemParamName:
				elemParamValue = elemParamName.Id
				Output.add(elemParamValue)
			parameter = setElems.LookupParameter(elemParamName)
			if parameter.StorageType == StorageType.String:
				parameter.Set(str(elemParamValue))
			else:
				parameter.SetValueString(elemParamValue)
		TransactionManager.Instance.EnsureInTransaction(doc)
		Output.append("Done")
		
		
except ValueError as ve:
	Output.append("Family Swap Failed")
	Output.append(ve)


OUT = elems.Count, Output

It is still a prototype script,(of which a majority of the code is from MEPover Filter Contains node) I am missing the ability to handle parameters with shared parameter(what my company calls ctrl parameters that allow a drop down selection on the properties bar) that you need to grab their elementId instead of their string.

MM - Family Swap Generic.dyn (30.9 KB)

3 Likes