# Use the node springs.familyinstance.bygeometry to import the model into revit

**URL:** <https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873>\
**Category:** Revit\
**Created:** [April 24, 2023, 11:15am UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873 "2023-04-24T11:15:09Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![3495707914](https://avatars.discourse-cdn.com/v4/letter/3/d6d6ee/32.png) [@3495707914](https://forum.dynamobim.com/u/3495707914)\
**Post date:** [April 24, 2023, 11:15am UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/1 "2023-04-24T11:15:09Z")

</div>

In dynamo, the tunnel model is created through the tunnel outline family. When I import the tunnel model into Revit through the node springs.familyinstance.bygeometry to create a solid, the “instance” and “family” below the node box appears empty when the operation is completed.How can I solve this problem please?

 ![1](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/0/1/01bb2b4db42489e2eb12cb3bbe042dec90fa2ca3.png)

---

<div class="post-metadata">

**Author:** ![sovitek](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/sovitek/32/116237_2.png) [@sovitek](https://forum.dynamobim.com/u/sovitek)\
**Post date:** [April 24, 2023, 11:16am UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/2 "2023-04-24T11:16:59Z")

</div>

You will need feed in a categori and if you feed in multiple object they will need a unique name as well…

 ![Capture](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/2/c/2c13cba0e808de9bae6706cd16e24334b88a7a2c.png)

---

<div class="post-metadata">

**Author:** ![trawordwud49](https://avatars.discourse-cdn.com/v4/letter/t/e56c9b/32.png) [@trawordwud49](https://forum.dynamobim.com/u/trawordwud49)\
**Post date:** [October 30, 2026, 4:12pm UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/3 "2026-10-30T16:12:27Z")

</div>

![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/6/0/60cb0475fe90d3c3da6e8efe50f2023137bd8643.png)Excuse me for bothering you，I tried what you suggested but it still isn’t working.

---

<div class="post-metadata">

**Author:** ![sovitek](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/sovitek/32/116237_2.png) [@sovitek](https://forum.dynamobim.com/u/sovitek)\
**Post date:** [October 30, 2026, 4:33pm UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/4 "2026-10-30T16:33:14Z")

</div>

4 years after 😉 nope dont know, which revit and dynamo build are you working in ?, in newer version we can just do it OOTB with FamilyType.ByGeometry and insert witth FamilyInstance.ByCoordinates or other nodes there can insert a family type as instance

---

<div class="post-metadata">

**Author:** ![BimAmbit](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/bimambit/32/192629_2.png) [@BimAmbit](https://forum.dynamobim.com/u/BimAmbit)\
**Post date:** [October 31, 2026, 7:01am UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/5 "2026-10-31T07:01:15Z")

</div>

> [@Convert CAD Block Geometry to Revit Family](https://forum.dynamobim.com/t/convert-cad-block-geometry-to-revit-family/109202/4):
>
> Below you can find a link to my project files. I would rather not recreate the circles in the family editor because I already have them created in Dynamo from the CAD file’s geometries. It’s just a matter of joining the circles together. [https://github.com/ikassab578/Dynamo.git](https://github.com/ikassab578/Dynamo.git)

op from that post used rhythm, so i was testing with rhythm as well which did work, if memory serves. worth a try if ootb nodes are not available.

---

<div class="post-metadata">

**Author:** ![Mark.Ackerley](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/mark.ackerley/32/79310_2.png) [@Mark.Ackerley](https://forum.dynamobim.com/u/Mark.Ackerley)\
**Post date:** [November 4, 2026, 12:01pm UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/6 "2026-11-04T12:01:55Z")

</div>

Hey, we gave Springs a reboot…

Here is a screen grab using Revit 2027…

 ![image](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/5/0/50695f502158b2d648d7e566987c29434daf1b39.png)

If you have a look here [SpringNodes/\_tests/Revit/FamilyInstance/InstanceByGeometry at master · dimven/SpringNodes · GitHub](https://github.com/dimven/SpringNodes/tree/master/_tests/Revit/FamilyInstance/InstanceByGeometry) you will see the example files.

Hope that helps.

Mark

---

<div class="post-metadata">

**Author:** ![sovitek](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/sovitek/32/116237_2.png) [@sovitek](https://forum.dynamobim.com/u/sovitek)\
**Post date:** [November 4, 2026, 12:38pm UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/7 "2026-11-04T12:38:04Z")

</div>

Thx Mark…so great i use this version here for pythonnet 3, work great at least fo me 😉 but again its build on Dimitars first code for that in ironPython at that time …so great, what a legend…and thanks for that

```auto
import clr
import os
import traceback
import System

clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('ProtoGeometry')
clr.AddReference('RevitNodes')

from Autodesk.DesignScript.Geometry import *
from Autodesk.DesignScript.Geometry import Point as DynPoint
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Structure import StructuralType
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
tManager = TransactionManager.Instance

def tolist(obj):
    return list(obj) if isinstance(obj, (list, tuple)) else [obj]

def pad(lst, n):
    lst = list(lst)
    if not lst:
        return [None] * n
    while len(lst) < n:
        lst.append(lst[-1])
    return lst[:n]

_rn_asm = next((a for a in System.AppDomain.CurrentDomain.GetAssemblies()
                if a.GetName().Name == 'RevitNodes'), None)
_ds_methods = []

def _collect_ds_methods():
    if _rn_asm is None:
        return
    try:
        types = _rn_asm.GetTypes()
    except System.Reflection.ReflectionTypeLoadException as e:
        types = [t for t in e.Types if t is not None]
    for t in types:
        if not (t.IsAbstract and t.IsSealed):
            continue
        for m in t.GetMethods():
            if m.Name == 'ToDSType' and m.IsStatic and len(m.GetParameters()) == 2:
                _ds_methods.append(m)

_collect_ds_methods()

def to_ds(el):
    et = el.GetType()
    for m in _ds_methods:
        if m.GetParameters()[0].ParameterType.IsAssignableFrom(et):
            try:
                return m.Invoke(None, System.Array[System.Object]([el, True]))
            except:
                pass
    return el

class FamLoadOpt(IFamilyLoadOptions):
    __namespace__ = "SovitekFamLoadOpt"
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
        return (True, True)
    def OnSharedFamilyFound(self, familyInUse, source, overwriteParameterValues):
        return (True, FamilySource.Family, True)

geom = tolist(IN[0])
fam_path = IN[1]
names = tolist(IN[2])
categories = tolist(IN[3])
materials = tolist(IN[4])
subcats = tolist(IN[5])

if int(doc.Application.VersionNumber) > 2021:
    units = doc.GetUnits().GetFormatOptions(ForgeTypeId("autodesk.spec.aec:length")).GetUnitTypeId()
else:
    units = doc.GetUnits().GetFormatOptions(UnitType.UT_Length).DisplayUnits
factor = UnitUtils.ConvertToInternalUnits(1, units)

origin = XYZ.Zero
str_type = StructuralType.NonStructural
temp_path = System.IO.Path.GetTempPath()
invalid_chars = list(System.IO.Path.GetInvalidFileNameChars())
acceptable_views = ('ThreeD', 'FloorPlan', 'EngineeringPlan', 'CeilingPlan', 'Elevation', 'Section')

satOpt = SATImportOptions()
satOpt.Placement = ImportPlacement.Origin
satOpt.Unit = ImportUnit.Foot

opt = Options()
opt.ComputeReferences = True

saveOpt = SaveAsOptions()
saveOpt.OverwriteExistingFile = True

def load_family(fam_doc, name):
    fam = fam_doc.LoadFamily(doc, FamLoadOpt())
    if isinstance(fam, tuple):
        fam = fam[-1]
    if fam is None:
        raise Exception("LoadFamily returned None for '{}'".format(name))
    return fam

def create_solid_family(geom_obj, name, category, material, subcat):
    sat_file = None
    rfa_path = None
    try:
        if any(c in name for c in invalid_chars):
            raise Exception("Family name contains invalid characters")

        tManager.ForceCloseTransaction()
        fam_doc = doc.Application.NewFamilyDocument(fam_path)

        if factor != 1:
            geom_obj = geom_obj.Scale(factor)
        offset_vec = Vector.ByTwoPoints(BoundingBox.ByGeometry(geom_obj).MinPoint, DynPoint.Origin())
        geom_obj = geom_obj.Translate(offset_vec)

        sat_file = os.path.join(temp_path, name + ".sat")
        geom_obj.ExportToSAT(sat_file, 1.0)

        view = next((v for v in FilteredElementCollector(fam_doc).OfClass(View)
                     if str(v.ViewType) in acceptable_views and not v.IsTemplate), None)

        tManager.EnsureInTransaction(fam_doc)
        import_id = fam_doc.Import(sat_file, satOpt, view)
        if isinstance(import_id, tuple):
            import_id = import_id[-1]
        imported_el = fam_doc.GetElement(import_id)
        geom_iter = imported_el.get_Geometry(opt)

        solid = None
        for geo in geom_iter:
            if not isinstance(geo, GeometryInstance):
                continue
            for item in geo.GetInstanceGeometry():
                if isinstance(item, Solid) and item.Volume > 0:
                    solid = item
                    break
            if solid is not None:
                break

        if solid is None:
            raise Exception("No solid found in imported SAT geometry")

        import_ids = [imp.Id for imp in FilteredElementCollector(fam_doc).OfClass(ImportInstance)]
        for imp_id in import_ids:
            try:
                el = fam_doc.GetElement(imp_id)
                if el.Pinned:
                    el.Pinned = False
                fam_doc.Delete(imp_id)
            except:
                pass

        try:
            fam_cat = fam_doc.Settings.Categories.get_Item(category.Name)
            fam_doc.OwnerFamily.FamilyCategory = fam_cat
        except:
            pass

        elem = FreeFormElement.Create(fam_doc, solid)

        if material:
            try:
                mat_fec = FilteredElementCollector(fam_doc).OfClass(Material)
                fam_mat = next((m for m in mat_fec if m.Name == material), None)
                if fam_mat:
                    elem.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM).Set(fam_mat.Id)
            except:
                pass

        if subcat:
            try:
                fam_category = fam_doc.OwnerFamily.FamilyCategory
                cat_subs = fam_category.SubCategories
                if cat_subs.Contains(subcat):
                    elem.Subcategory = cat_subs.get_Item(subcat)
                else:
                    elem.Subcategory = fam_doc.Settings.Categories.NewSubcategory(fam_category, subcat)
            except:
                pass

        tManager.ForceCloseTransaction()

        rfa_path = os.path.join(temp_path, name + ".rfa")
        fam_doc.SaveAs(rfa_path, saveOpt)
        family = load_family(fam_doc, name)
        fam_doc.Close(False)

        target = XYZ(-offset_vec.X, -offset_vec.Y, -offset_vec.Z)

        existing = [i for i in FilteredElementCollector(doc).OfClass(FamilyInstance)
                    if i.Symbol.Family.Id == family.Id]

        if existing:
            instance = existing[0]
            loc = instance.Location
            if loc is not None and hasattr(loc, "Point"):
                delta = target - loc.Point
                if delta.GetLength() > 1e-9:
                    tManager.EnsureInTransaction(doc)
                    ElementTransformUtils.MoveElement(doc, instance.Id, delta)
                    tManager.ForceCloseTransaction()
        else:
            symbol = doc.GetElement(list(family.GetFamilySymbolIds())[0])
            tManager.EnsureInTransaction(doc)
            if not symbol.IsActive:
                symbol.Activate()
            instance = doc.Create.NewFamilyInstance(origin, symbol, str_type)
            ElementTransformUtils.MoveElement(doc, instance.Id, target)
            tManager.ForceCloseTransaction()

        return to_ds(instance), to_ds(family), None

    except:
        try:
            tManager.ForceCloseTransaction()
        except:
            pass
        return None, None, traceback.format_exc()
    finally:
        for p in (sat_file, rfa_path):
            try:
                if p and os.path.exists(p):
                    System.IO.File.Delete(p)
            except:
                pass

if len(geom) == len(names):
    n = len(geom)
    results = [create_solid_family(g, nm, c, m, s)
               for g, nm, c, m, s in zip(geom, names, pad(categories, n), pad(materials, n), pad(subcats, n))]
else:
    results = [(None, None, "Ensure each geometry has a unique family name.")]

OUT = [r[0] for r in results], [r[1] for r in results], [r[2] for r in results]

satOpt.Dispose()
opt.Dispose()
saveOpt.Dispose()

```

---

<div class="post-metadata">

**Author:** ![sovitek](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/sovitek/32/116237_2.png) [@sovitek](https://forum.dynamobim.com/u/sovitek)\
**Post date:** [November 4, 2026, 12:53pm UTC](https://forum.dynamobim.com/t/use-the-node-springs-familyinstance-bygeometry-to-import-the-model-into-revit/88873/8 "2026-11-04T12:53:53Z")

</div>

and PS material in that with only work if it already is in the template…but can easy be done after run, even as family parameter or shared family parameter in the project file ;)…just another script
