Ejemplo n.º 1
0
def exportDxf(filename_string, view, folderpath_string): 
    # DWGExport Options, get Current Active
    firstdxfsetting = DB.FilteredElementCollector(doc).OfClass(DXFExportOptions) \
                                                    .FirstElement()
    currentactiveset= firstdwgsetting.GetActivePredefinedSettings(doc)
    dwgopt= currentactiveset.GetDWGExportOptions()
    views = List[ElementId]()
    views.Add(view.Id)
    result = doc.Export(folderpath_string, filename_string, views, dwgopt) #Revit API func
    return result 
Ejemplo n.º 2
0
 def in_use_dict(doc=revit.doc):
     """ Return a dictionary of fluids in use with system as key
     >>> FluidType.in_use_dict() # return format: {system.name:{'name':fluid.name, 'temperature':temperature}
     {'Hydronic Return': {'name': 'Water', 'temperature': 283.15000000000003}, ...}
     """
     result = {}
     for system in DB.FilteredElementCollector(doc).OfClass(DB.Plumbing.PipingSystemType):
         rpw_system = Element(system)
         rpw_fluid_type = Element.from_id(system.FluidType)
         result[rpw_system.name] = {'name': rpw_fluid_type.name, 'temperature': rpw_system.FluidTemperature}
     return result
Ejemplo n.º 3
0
def selectschedule():
    FECsched = DB.FilteredElementCollector(doc).OfClass(
        DB.ViewSchedule).ToElements()
    #sched = [i for i in FECsched if i.Name == schedName + " Schedule"][0]
    returnlist = forms.SelectFromList.show(sorted(
        [ScheduleOption(x) for x in FECsched], key=lambda x: x.name),
                                           title="Schedules")
    if returnlist:
        return [i.item for i in returnlist]
    else:
        sys.exit()
Ejemplo n.º 4
0
def get_viewName_prefix_byTemplate(templates):
    templatePrefix = []
    for template in templates:
        if int(template) != -1:
            vtn = (doc.GetElement(DB.ElementId(int(template))).Name)
            templatePrefix.append(vtn.replace(" ","-"))
        else :
            templatePrefix.append("No-Template")
    
    res = MultipleTextInput("Add view prefix according to template :", templatePrefix )
    return list(res)
Ejemplo n.º 5
0
def createMultiCategoryFilter():
    listOfCategories = list()
    listOfCategories.append(db.BuiltInCategory.OST_Floors)
    listOfCategories.append(db.BuiltInCategory.OST_StructuralColumns)
    listOfCategories.append(db.BuiltInCategory.OST_StructuralFraming)
    listOfCategories.append(db.BuiltInCategory.OST_StructuralFoundation)
    listOfCategories.append(db.BuiltInCategory.OST_Walls)
    iCollectionOfCategoriesForMultiCategoryFIlter = List[db.BuiltInCategory](
        listOfCategories)
    multiCategoryFilter = db.ElementMulticategoryFilter(
        iCollectionOfCategoriesForMultiCategoryFIlter)
    return multiCategoryFilter
Ejemplo n.º 6
0
def RemoveViewTemplate(viewtype_id):
    view_type = doc.GetElement(viewtype_id)
    template_id = view_type.DefaultTemplateId
    if template_id.IntegerValue != -1:
        if forms.alert(
                "You are about to remove the ViewTempalte associated with this View Type. Is that cool with ya?",
                ok=False,
                yes=True,
                no=True,
                exitscript=True):
            with revit.Transaction("Remove ViewTemplate"):
                view_type.DefaultTemplateId = DB.ElementId(-1)
Ejemplo n.º 7
0
def preview_rhino_line(rhinoline):
    if type(rhinoline) == rg.Curve:
        beam_start_pt, beam_end_pt = rhinoline.PointAtStart, rhinoline.PointAtEnd
    elif type(rhinoline) == rg.Line:
        beam_start_pt, beam_end_pt = rhinoline.From, rhinoline.To

    p0 = DB.XYZ(beam_start_pt.X, beam_start_pt.Y, beam_start_pt.Z)
    p1 = DB.XYZ(beam_end_pt.X, beam_end_pt.Y, beam_end_pt.Z)

    p2 = p1 + DB.XYZ(0, 1, 0)
    revit_line = DB.Line.CreateBound(p0, p2)

    bmplane = DB.Plane.CreateByThreePoints(p0, p1, p2)
    with DB.Transaction(revit.doc) as t1:
        #print revit.doc.Title
        t1.Start("Create Model Line")
        skp = DB.SketchPlane.Create(revit.doc, bmplane)
        #print revit_line
        #print p0,p1
        revit.doc.Create.NewModelCurve(revit_line, skp)
        t1.Commit()
Ejemplo n.º 8
0
def firstrun():
    # get Drafting View named "xForm" for object creation and Selection.
    fecv = DB.FilteredElementCollector(doc).OfClass(DB.ViewDrafting) \
            .WhereElementIsNotElementType().ToElements()
    dv = [i for i in fecv if i.ViewName.Equals("xForm")]
    draftview = dv[0] if dv else None 

    if not draftview: 
        t = Transaction(doc, "xForm")
        t.Start() 
        fec = DB.FilteredElementCollector(doc).OfClass(DB.ViewFamilyType).ToElements()
        viewdrafttype = [i for i in fec if i.ViewFamily.Equals(DB.ViewFamily.Drafting)][0]
        draftview = DB.ViewDrafting.Create(doc, viewdrafttype.Id)
        draftview.Name = "xForm"  
        draftview.Scale = 100
        t.Commit()
        #print draftview, draftview.Name

    notes = FilteredElementCollector(doc, draftview.Id).OfClass(TextNote) \
                .WhereElementIsNotElementType() \
                .ToElements()

    notetypes = sorted(DB.FilteredElementCollector(doc).OfClass(DB.TextNoteType).ToElements(),
                    key = lambda x: x.GetParameters("Type Name")[0].AsString() )
      
    if not notes or not len(notes) == len(notetypes):       
        
        # TextNote Create( Document document, ElementId viewId, XYZ position, string text, ElementId typeId )
        t= Transaction(doc, "Create TextNotes of all TextTypes in DraftingView")
        t.Start() 
        if not len(notes) == len(notetypes): 
            [doc.Delete(i.Id) for i in notes]

        for i, j in enumerate(notetypes):
            text = j.GetParameters("Type Name")[0].AsString()
            textnote = DB.TextNote.Create(doc, draftview.Id, XYZ(0,-i*3.5, 0), text , j.Id)
        t.Commit()    


    return  [(i.GetParameters("Type Name")[0].AsString(), i) for i in notetypes] # Tupel
Ejemplo n.º 9
0
def get_piping_system_type(param_name):
    # Accesses the ID associated with the built-in paramater "System Classification"
    # See RevitApiDocs: BuiltInParameter Enumeration
    param_id = DB.ElementId(DB.BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM)
    # The filter needs the ID of the parameter we are searching for:
    # See RevitApiDocs: FilterableValueProvider Class
    param_prov = DB.ParameterValueProvider(param_id)
    # The filter also takes a rule evaluation
    # See RevitApiDocs: FilterStringRuleEvaluator Look at the inheritance Heirarchy
    # to get an idea of what options this has.
    filter_rule = DB.FilterStringContains()
    # This line directly translates from the C# example provided in the documentation
    # to the python equivalent. See RevitApiDocs: ElementParameterFilter Class
    case_sensitive = False
    param_filter = DB.FilterStringRule(param_prov, \
                                            filter_rule, \
                                            param_name, \
                                            case_sensitive)
    # Assigns our filter to the element parameter filter so it fits into the
    # 'WherePasses' method
    element_filter = DB.ElementParameterFilter(param_filter)
    # Collect a list of items eligible to get picked by the filter.
    # I found OST_PipeCurves from a combination of looking over the built in categories and
    collected_elements = DB.FilteredElementCollector(doc) \
            .OfCategory(DB.BuiltInCategory.OST_PipeCurves) \
            .WherePasses(element_filter) \
            .ToElements()

    return collected_elements
Ejemplo n.º 10
0
def PrintView(doc, sheet, pRange, printerName, combined, filePath,
              printSetting):
    # create view set for this one sheet
    viewSet = rvt_db.ViewSet()
    viewSet.Insert(sheet)

    # determine print range
    printManager = doc.PrintManager
    printManager.PrintRange = pRange
    printManager.Apply()

    # make new view set current
    viewSheetSetting = printManager.ViewSheetSetting
    viewSheetSetting.CurrentViewSheetSet.Views = viewSet

    # set printer
    printManager.SelectNewPrintDriver(printerName)
    printManager.Apply()

    # set combined and print to file
    if printManager.IsVirtual:
        printManager.CombinedFile = combined
        printManager.Apply()
        printManager.PrintToFile = True
        printManager.Apply()
    else:
        printManager.CombinedFile = combined
        printManager.Apply()
        printManager.PrintToFile = False
        printManager.Apply()

    # set file path
    printManager.PrintToFileName = filePath
    printManager.Apply()

    # apply print setting
    try:
        printSetup = printManager.PrintSetup
        printSetup.CurrentPrintSetting = printSetting
        printManager.Apply()
    except:
        pass

    # save settings and submit print
    rvt_db.TransactionManager.Instance.EnsureInTransaction(doc)
    viewSheetSetting.SaveAs("tempSetName")
    printManager.Apply()
    printManager.SubmitPrint()
    viewSheetSetting.Delete()
    rvt_db.TransactionManager.Instance.TransactionTaskDone()

    return True
Ejemplo n.º 11
0
def selectsheets2print():
    all_sheets = DB.FilteredElementCollector(doc).OfClass(DB.ViewSheet) \
                        .WhereElementIsNotElementType().ToElements()
    sortlist = sorted([SheetOption(x) for x in all_sheets], key = lambda x: x.number)
    selsheet = SelectFromCheckBoxes(sortlist, title = "Select Sheets",
                        width = 500, height = 400, 
                        button_name = "Select / PRINT")  
    selsheet.ShowDialog() #.Net Method, Modal Window, no other window is active
    write_dic(selsheet.dic_dlgval)  
    if selsheet.response:           
        return ([i.item for i in selsheet.response if i.state], selsheet.dic_dlgval)
    else: 
        sys.exit() #selsheet.response does not exist 
Ejemplo n.º 12
0
def deletefromdoc(obj_del):
    t = DB.Transaction(doc, "Delete SystemFamilyType")
    t.Start()
    for i in obj_del:
        try:
            text = i.GetParameters("Type Name")[0].AsString()  #> 4mm Arial
            print " {}, id={}  --> deleting".format(text, i.Id)
            doc.Delete(i.Id)
            print " Done"
        except:
            import traceback
            print traceback.format_exc()
    t.Commit()
Ejemplo n.º 13
0
def deletefromdoc(obj_del, doc):
    ilist = List[ElementId]()
    [ilist.Add(i.Id) for i in obj_del]
    try:
        t = DB.Transaction(doc, "Delete Types")
        t.Start()
        doc.Delete(ilist)
        t.Commit()
    except:
        import traceback
        print traceback.format_exc()
    for i in obj_del:
        print extract(i) + " --> Deleting "
def colection_original():
    uiapp = __revit__ # noqa F821
    uidoc = uiapp.ActiveUIDocument
    app = uiapp.Application # noqa F841
    doc = uidoc.Document

    sheets = (
        DB.FilteredElementCollector(doc)
        .OfClass(DB.ViewSheet)
        .WhereElementIsNotElementType()
        .ToElements())
    for sheet in sheets:
        print(sheet)
        print(sheet.Name)
Ejemplo n.º 15
0
def exportschedule():
    # ViewScheduleExportOptions
    options = DB.ViewScheduleExportOptions()
    options.Title = False

    folderpath = filepath("filepath.txt")
    sched_list = selectschedule()
    if sched_list:
        for i in sched_list:
            filenamestr = i.Name + ".csv"
            i.Export(folderpath, filenamestr, options)
            #print i.Name, "exported to" , folderpath , filenamestr
    else:
        sys.exit()
Ejemplo n.º 16
0
def selectschedule():
    selection = [doc.GetElement(elId) for elId in uidoc.Selection.GetElementIds()
                    if doc.GetElement(elId).ViewType == ViewType.Schedule]
    if selection:       
        return selection
    else:               
        FECsched = DB.FilteredElementCollector(doc).OfClass(DB.ViewSchedule).ToElements()
    #sched = [i for i in FECsched if i.Name == schedName + " Schedule"][0]
        returnlist = AddSelectFromList.show(sorted([ScheduleOption(x) for x in FECsched],
                                            key = lambda x: x.name),
                                            title = "Schedules")
    if returnlist:
        return [i.item for i in returnlist]
    else:
        sys.exit()
Ejemplo n.º 17
0
def main():
    source_vp_reference = uidoc.Selection.PickObject(
        UI.Selection.ObjectType.Element, CustomISelectionFilter(DB.Viewport),
        "Select Source Viewport")
    target_vps_reference = uidoc.Selection.PickObjects(
        UI.Selection.ObjectType.Element, CustomISelectionFilter(DB.Viewport),
        "Select Target Viewport(s)")
    source_vp = doc.GetElement(source_vp_reference.ElementId)
    source_vp_xyz = source_vp.GetBoxCenter()
    with revit.Transaction("Aign ViewPort - Vertical"):
        for target_vp_reference in target_vps_reference:
            target_vp = doc.GetElement(target_vp_reference.ElementId)
            delta = DB.XYZ(0.0, source_vp_xyz.Y - target_vp.GetBoxCenter().Y,
                           0.0)
            target_vp.Location.Move(delta)
Ejemplo n.º 18
0
def decode_valuestring(target_parameter_value, target_category,
                       target_parameter):
    "Value strings are Revit representation and as such cannot be filtered using fast filters"
    elementids = DB.FilteredElementCollector(doc, curview.Id)\
        .OfCategory(target_category)\
        .WhereElementIsNotElementType()\
        .ToElementIds() # select category
    collect_eleid = []
    for eleid in elementids:
        ele = revit.doc.GetElement(eleid)
        ele_parameter_value = ele.Parameter[target_parameter].AsValueString()
        if ele_parameter_value == target_parameter_value:
            collect_eleid.append(eleid)

    return collect_eleid
Ejemplo n.º 19
0
def deletefromdoc(obj_del):
    print "DEleting test"
    print type(obj_del) 
    
    t= DB.Transaction(doc, "Delete SystemFamilyType")
    t.Start()
    for i in obj_del:
		try: 
			print " {}, id={}  --> deleting".format(extract(i), i.Id)
			doc.Delete(i.Id)
			print " Done" 
		except:
			import traceback
			print traceback.format_exc()
    t.Commit()			
Ejemplo n.º 20
0
def exportDwg(filename, view, folderpath): 
    # DWGExport Options, get Current Active
    firstdwgsetting = DB.FilteredElementCollector(doc).OfClass(ExportDWGSettings) \
                                                      .FirstElement()
    if not firstdwgsetting:
        forms.alert("There is NO DwgSetting in Project", ok=True)
    currentactiveset= firstdwgsetting.GetActivePredefinedSettings(doc)
    if not currentactiveset:
        dwgopt = firstdwgsetting.GetDWGExportOptions()
    else: 
        dwgopt= currentactiveset.GetDWGExportOptions()
    views = List[ElementId]() # empty .Net List
    views.Add(view.Id)
    result = doc.Export(folderpath, filename, views, dwgopt) #Revit API func
    return result 
Ejemplo n.º 21
0
def exportschedule():
    # ViewScheduleExportOptions
    options = DB.ViewScheduleExportOptions()
    options.Title = False # no Title in first line of csv file
    mess = []                           
    folderpath = filepath("filepath.txt")
    sched_list = selectschedule()
    if sched_list:               
        for i in sched_list:     
            filenamestr = i.Name + ".csv"
            export =  i.Export(folderpath, filenamestr, options)
            mess.append(filenamestr)
            #print i.Name, "exported to" , folderpath , filenamestr
        return mess
    else:
        sys.exit()
Ejemplo n.º 22
0
def GetInstanceParameters(_cat):
    el = DB.FilteredElementCollector(doc) \
    .WhereElementIsNotElementType() \
    .OfCategory(_cat) \
    .ToElements()

    if not el:
        forms.alert("No elements of this category found in the project.")
        script.exit()

    parameters = [p.Definition.Name for p in el[0].Parameters \
        if p.StorageType == DB.StorageType.String and \
         p.Definition.ParameterType == DB.ParameterType.Text and \
         not p.IsReadOnly]

    return parameters
Ejemplo n.º 23
0
def revit_clash_plane_curve(beamline, pipeline):

    p0 = beamline.GetEndPoint(0)
    p1 = beamline.GetEndPoint(1)
    p2 = p1 + DB.XYZ(0, 0, 1)
    bmplane = DB.Plane.CreateByThreePoints(p0, p1, p2)

    #project pipe line onto plane
    pipe_projected_startpoint, dist = bmplane.Project(pipeline.GetEndPoint(0))

    pipe_projected_endpoint, dist = bmplane.Project(pipeline.GetEndPoint(1))
    #print (pipe_projected_startpoint)
    #print pipe_projected_endpoint
    pipe_projected = DB.Line.CreateBound(pipe_projected_startpoint,
                                         pipe_projected_endpoint)
    intpoint = pipe_projected.Intersect(pipeline)
Ejemplo n.º 24
0
    def category_changed(self, sender, args):
        self.cat_id = self.dict_cat_id[self.selected_category]
        elements = DB.FilteredElementCollector(doc)\
                        .OfCategoryId(self.cat_id)\
                        .WhereElementIsElementType()\
                        .ToElements() 
        
        families = [ele.FamilyName for ele in elements]

        self.family_ele_dict = defaultdict(list)
        for k,v in zip(families,elements):
            self.family_ele_dict[k].append(v)

        self._setup_family()
        self.rename_list = [] # clear the list view in GUI when category changed
        self.rename_button.IsEnabled = False 
Ejemplo n.º 25
0
def copyfromdoc(typelist, sourcedoc, activedoc):
    idlist = List[ElementId]()
    [idlist.Add(i.Id) for i in typelist]

    try:
        t = Transaction(doc, "copy ViewTemplates")
        t.Start()
        DB.ElementTransformUtils.CopyElements(sourcedoc, idlist, activedoc,
                                              None, DB.CopyPasteOptions())
        t.Commit()
        for i in typelist:
            print i.ToString(
            ) + "  --> copied "  #"{} - {} --> copied ".format(i.Name , i.Id)

        #forms.alert("Copied from {} to {} : \n{}".format(sourcedoc.Title, activedoc.Title, text ))
    except:
        print traceback.format_exc()
Ejemplo n.º 26
0
def boundingboxWall(elem):
    # Location Line of Wall
    line = elem.Location.Curve  # Everything is a Curve, in Revit
    p1 = line.GetEndPoint(0)
    p2 = line.GetEndPoint(1)
    v = p2 - p1  # vector

    # BoundingBox Wall
    bbwall = elem.get_BoundingBox(None)
    minZ = bbwall.Min.Z
    maxZ = bbwall.Max.Z
    # print "MIN= ", bbwall.Min
    # print "MAX= ", bbwall.Max
    # print p1
    # print p2

    width = v.GetLength()  #  sqrt(x*x + y*y + z*s)
    height = maxZ - minZ  # height calculation
    depth = elem.Width
    offset = 0.2 / 0.3048  #

    # Set 2pt Min & Max to define BoundaryBox of Section
    minpt = XYZ(-width / 2.0, minZ - offset,
                -depth / 2.0)  #from midpoint of wall. X = wall-length /2
    maxpt = XYZ(width / 2.0, maxZ + offset, depth + offset)

    midpoint = p1 + 0.5 * v  # midpoint of whole wall startpt.X + 0.5 * v.X
    walldir = v.Normalize()  # X/ Length, Y/ Length , Z/ Length
    updir = XYZ.BasisZ  # Basisvektor in Z Richtung (0,0,1)
    viewdir = walldir.CrossProduct(updir)  #  XYZ(0, 1, 0)

    # set transform of SectionBox
    trans = DB.Transform.Identity  #  .Identity has to be called to
    trans.Origin = midpoint
    trans.BasisX = walldir
    trans.BasisY = updir
    trans.BasisZ = viewdir

    # create SectionBox
    sectionBox = DB.BoundingBoxXYZ()  # instantiate
    sectionBox.Transform = trans
    sectionBox.Min = minpt
    sectionBox.Max = maxpt
    return sectionBox
Ejemplo n.º 27
0
def exportschedule():
    # ViewScheduleExportOptions
    options = DB.ViewScheduleExportOptions()
    options.Title = False
    folderpath = filepath("filepath.txt")
    sched_list = selectschedule()
    list = []
    print "sched_list: ", len(sched_list)
    if sched_list:
        for i in sched_list:
            filenamestr = i.Name + ".csv"
            list.append(filenamestr)
            i.Export(folderpath, filenamestr, options)
            out = "{} --> exported".format(filenamestr)
            print(out)
            #print i.Name, "exported to" , folderpath , filenamestr
        return (folderpath, list)
    else:
        sys.exit()
Ejemplo n.º 28
0
def main():
    tempfile = os.path.join(gettempdir(), "ViewPort")
    try:
        with open(tempfile, "rf") as fp:
            source_point = pickle.load(fp)
    except Exception:
        message = 'を除外します'
        ui.forms.Alert(content=message, title="シート以外が選択されました", exit=True)
    target_vp_reference = uidoc.Selection.PickObject(
        UI.Selection.ObjectType.Element, CustomISelectionFilter(DB.Viewport),
        "Select Source Viewport")
    target_vp = doc.GetElement(target_vp_reference.ElementId)
    target_vp_xyz = target_vp.GetBoxCenter()

    with revit.Transaction("Move ViewPort Location"):
        delta = DB.XYZ((source_point[0] - target_vp_xyz.X),
                       (source_point[1] - target_vp_xyz.Y),
                       (source_point[2] - target_vp_xyz.Z))
        target_vp.Location.Move(delta)
Ejemplo n.º 29
0
def createobj(type):

    # get Drafting View named "xForm" for object creation and Selection.
    fecv = DB.FilteredElementCollector(doc).OfClass(DB.ViewDrafting) \
            .WhereElementIsNotElementType().ToElements()
    dv = [i for i in fecv if i.ViewName.Equals("xForm")]
    draftview = dv[0] if dv else None

    # if not draftview:
    # t = Transaction(doc, "xForm")
    # t.Start()
    # fec = DB.FilteredElementCollector(doc).OfClass(DB.ViewFamilyType).ToElements()
    # viewdrafttype = [i for i in fec if i.ViewFamily.Equals(DB.ViewFamily.Drafting)][0]
    # draftview = DB.ViewDrafting.Create(doc, viewdrafttype.Id)
    # draftview.Name = "xForm"
    # t.Commit()
    #print draftview.Name

    # Get line of linestyle = type
    fec = FilteredElementCollector(doc, draftview.Id).OfCategory(DB.BuiltInCategory.OST_Lines) \
                .ToElements()
    detailc = [
        i for i in fec
        if i.CurveElementType.Equals(DB.CurveElementType.DetailCurve)
    ]
    li = [i for i in detailc if i.LineStyle.Id.Equals(type.Id)]
    line = li[0] if li else None

    if line and draftview:
        # Select it/Add it to Selection
        listId = List[ElementId]()
        listId.Add(line.Id)
        uidoc.Selection.SetElementIds(listId)
        # Start CreateSimilar Command.
        try:
            revitcomid = UI.RevitCommandId.LookupPostableCommandId(
                UI.PostableCommand.CreateSimilar)
            if revitcomid:
                uiapp.PostCommand(revitcomid)
        except:
            import traceback
            print traceback.format_exc()
def main():
    """Main Script. """

    print("🐍 Running {fname} version {ver}...".format(fname=__name,
                                                      ver=__version))

    # STEP 0: Setup
    doc = __revit__.ActiveUIDocument.Document
    view = doc.ActiveView

    # STEP 1: Get all pipes in the model
    print("Getting all pipe from the model...", end="")
    pipes = db.FilteredElementCollector(doc)\
              .OfCategory(db.BuiltInCategory.OST_PipeCurves)\
              .WhereElementIsNotElementType()\
              .ToElements()
    print("✔")
    print("  ➜ Found {num} pipes = {len} m in the model.".format(
        num=len(pipes), len=total_length(pipes)))

    # STEP 2: Filter pipes
    print("Filtering pipes by system type...", end="")
    sorted_pipes = sort_pipes(pipes, doc)
    print("✔")
    for key in sorted_pipes.keys():
        print("  ➜ Found {num} pipes = {len} m of type '{key}' in the model.".
              format(num=len(sorted_pipes[key]),
                     len=total_length(sorted_pipes[key]),
                     key=key))

    # STEP 3: Categorize pipes
    print("Categorizing pipes...", end="")
    categorized_pipes = categorize_pipes(sorted_pipes)
    print("✔")
    for key in categorized_pipes.keys():
        print(
            "  ➜ Found {numh} horizontal pipes = {lenh} m an {numv} vertical pipes = {lenv} m of type '{key}' in the model."
            .format(numh=len(categorized_pipes[key]["horizontal"]),
                    lenh=total_length(categorized_pipes[key]["horizontal"]),
                    numv=len(categorized_pipes[key]["vertical"]),
                    lenv=total_length(categorized_pipes[key]["vertical"]),
                    key=key))