Multiple solids into one family

Hi Arno,

Nice image! I’m struggling to reproduce your scaling issue, but I think I’ve got it working. Could you send me a file to check?

An issue for assigning materials seems to be that though the family contains (in my example) 2 cubes, the family is treating them as 1 solid :frowning:

Here’s a graph using Orchid nodes that associates the family to 1 material parameter, as indicated above Revit Dynamo Combining Spring node family instance by geometry with Associate Family parameter

It could be possible to background open the family once created and add geometry to it? I’ve not investigated that though.

I’ll be going to the BILT hackathon (BILT is too close to my wife’s birthday!) it would be great to meet up :slight_smile:

Cheers,

Mark

Yes in my family everything has turned into one solid. which is strange because the join solid node doesn’t work and won’t combine the solids.
So you already made a better solid join node.

Let’s discus this further next month, with a BIMBeer… if anyone wants to join this conversation in Edinburgh please let me know…

1 Like

Hi @Arno_De_Lange @Mark.Ackerley @Dimitar_Venkov

I was wondering if anyone had looked at this now we are in Revit/Dynamo 2023? The FamilyInstance.ByGeometry seems to be working well in 2023, but I am also looking to output multiple materials into a single family with separate materials assigned as discussed above. Is this still unlikely with the FamilyInstance.ByGeometry node?

Thank you very much for any insight.
Tim

Hi, I’m not sure about Springs, but I think Synthesize might have a node? Maybe have a hunt around?

Cheers,

Mark

Hi Mark

Thank you very much for the suggestion, I will try Synthesize.

Thanks again!
Tim

1 Like

Check this out, I defined another method based on Dimitar Venkov’s original “NewForm_background”, and it works for me(MultiSolidToOneFamily() can give each solid different material either):

def MultiSolidToOneFamily(s1, name1, cat1, isVoid1, mat1, subcat1):
	enable_mat = False if mat1 is None else True
	enable_subcat = False if subcat1 is None else True
	TransactionManager.ForceCloseTransaction(t1)
	famdoc = doc.Application.NewFamilyDocument(fam_path)
	message = None
	temp_path = System.IO.Path.GetTempPath()
	sat_path = "%s%s.sat" % (temp_path, name1)
	try:
		vec1 = Vector.ByTwoPoints(BoundingBox.ByGeometry(s1).MinPoint, DynPoint.Origin())
		for i in xrange(0,len(s1)):
			if factor != 1:
				s1[i] = s1[i].Scale(factor)
			s1[i] = s1[i].Translate(vec1)
			sat1 = Geometry.ExportToSAT(s1[i], sat_path)
			view_fec = FilteredElementCollector(famdoc).OfClass(View)
			view1 = None
			for v in view_fec:
				if str(v.ViewType) in acceptable_views and not v.IsTemplate:
					view1 = v
					break
			t1.EnsureInTransaction(famdoc)
			satId = famdoc.Import(sat1, satOpt, view1)
			el1 = famdoc.GetElement(satId)
			geom1 = el1.get_Geometry(opt1)
			enum = geom1.GetEnumerator()
			enum.MoveNext()
			geom2 = enum.Current.GetInstanceGeometry()
			enum2 = geom2.GetEnumerator()
			enum2.MoveNext()
			s1[i] = enum2.Current
			famdoc.Delete(satId)
			System.IO.File.Delete(sat_path)
	except:
		message = (traceback.format_exc(),"")
		pass
	if message is None:
		try:
			save_path = "%s%s.rfa" % (temp_path, name1)
			try: #set the category
				fam_cat = famdoc.Settings.Categories.get_Item(cat1.Name)
				famdoc.OwnerFamily.FamilyCategory = fam_cat
			except: pass
			for i in xrange(0,len(s1)):
				s2 = FreeFormElement.Create(famdoc,s1[i])
				try:
					mat_fec = FilteredElementCollector(famdoc).OfClass(Material)
					for m in mat_fec:
						if m.Name == mat1[i]:
							fam_mat = m
							break
					mat_par = s2.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM).Set(fam_mat.Id)
				except: pass
			TransactionManager.ForceCloseTransaction(t1)
			famdoc.SaveAs(save_path, SaveAsOpt)
			family1 = famdoc.LoadFamily(doc, FamOpt1() )
			famdoc.Close(False)
			System.IO.File.Delete(save_path)
			symbols = family1.GetFamilySymbolIds().GetEnumerator()
			symbols.MoveNext()
			symbol1 = doc.GetElement(symbols.Current)
			t1.EnsureInTransaction(doc)
			if not symbol1.IsActive: symbol1.Activate()
			inst1 = doc.Create.NewFamilyInstance(origin, symbol1, str_typ)
			ElementTransformUtils.MoveElement(doc,inst1.Id, vec1.Reverse().ToXyz() )
			TransactionManager.ForceCloseTransaction(t1)
			#set ToDSType() to True so that the second run of script won't override result of first run, based on what you prefer
			return inst1.ToDSType(True), family1.ToDSType(False)
		except:
			message = (traceback.format_exc(),"")
			return message
	else : return message

And The OUT variable is set to this(I didn’t figure out how to use map(), and so I made some change :rofl:)

if len(geom) == len(names) == len(category) == len(isVoid) == len(material) == len(subcat):
	return1 = map(NewForm_background, geom, names, category, isVoid, material, subcat)
	OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
elif len(geom) == len(names):
	padded = PadLists([geom, category, isVoid, material,subcat])
	p_category, p_isVoid, p_material, p_subcat = padded[1], padded[2], padded[3], padded[4]
	return1 = map(NewForm_background, geom, names, p_category, p_isVoid, p_material, p_subcat)
	OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
elif len(geom) > 1 and len(names) == 1: 
	OUT = MultiSolidToOneFamily(geom, names[0], category[0], isVoid[0], material, subcat[0])
else : 
	return1 = [("Make sure that each geometry\nobject has a unique family name.", "")]
	OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
satOpt.Dispose()
opt1.Dispose()
SaveAsOpt.Dispose()

thanks for looking into this… will have a look when i have a spare moment… thanks for the efforts

BTW, I didn’t need subcategory, so I deleted some code from Venkov’s original “NewForm_background”