Hide menu
Loading...
Searching...
No Matches
exploring/bom/bom.py

Refer to the Bill of Materials (BOM) Example.

1# $Id$
2
3# Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
4# Copyright (C) 2014-2025, CADEX. All rights reserved.
5
6# This file is part of the Manufacturing Toolkit software.
7
8# You may use this file under the terms of the BSD license as follows:
9
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are met:
12# * Redistributions of source code must retain the above copyright notice,
13# this list of conditions and the following disclaimer.
14# * Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29
30
31import sys
32import os
33
34from pathlib import Path
35
36import manufacturingtoolkit.CadExMTK as mtk
37
38sys.path.append(os.path.abspath(os.path.dirname(Path(__file__).resolve()) + "/../../"))
39
40import mtk_license as license
41
42class SceneGraphVisitor(mtk.ModelData_ModelElementVoidVisitor):
43 def __init__(self):
44 super().__init__()
45 self.myNestingLevel = 0
46 self.margin = 0; # This variable is used for formatting of output table
47 self.myElementMap = {}
48
49 def PrintName(self, theElement: mtk.ModelData_ModelElement, theName: str):
50 print("--- " * self.myNestingLevel, end="")
51
52 if theName:
53 print(f"{theElement}: {theName}")
54 else:
55 print(f"{theElement}: noname")
56
57 # Calculating spacing for output table columns
58 self.margin = max(self.margin, theName.Length())
59
60 def UpdateTable(self, theElement: mtk.ModelData_ModelElement):
61 if not self.myElementMap.get(theElement):
62 self.myElementMap[theElement] = 1
63 else:
64 self.myElementMap[theElement] += 1
65
66 def PrintElementType(self, theElement: mtk.ModelData_ModelElement) -> str:
67 if mtk.ModelData_Part.CompareType(theElement):
68 return "Part"
69 elif mtk.ModelData_Assembly.CompareType(theElement):
70 return "Assembly"
71 elif mtk.ModelData_Instance.CompareType(theElement):
72 return "Instance"
73 return "Undefined"
74
75 def PrintCounts(self):
76 print("Total:")
77 print("\t" + "name".ljust(self.margin) + " | " + "type".ljust(self.margin) + " | count")
78
79 for i in self.myElementMap:
80 aName = str(i.Name())
81 aType = self.PrintElementType(i)
82 print("\t" + aName.ljust(self.margin) + " | " +
83 aType.ljust(self.margin) + " | " + str(self.myElementMap[i]))
84
85 def VisitPart(self, thePart: mtk.ModelData_Part):
86 self.PrintName("Part", thePart.Name())
87 self.UpdateTable(thePart)
88
89 def VisitEnterAssembly(self, theAssembly: mtk.ModelData_Assembly) -> bool:
90 self.PrintName("Assembly", theAssembly.Name())
91 self.UpdateTable(theAssembly)
92 self.myNestingLevel += 1
93 return True
94
95 def VisitEnterInstance(self, theInstance: mtk.ModelData_Instance) -> bool:
96 self.PrintName("Instance", theInstance.Name())
97 self.myNestingLevel += 1
98 return True
99
100 def VisitLeaveAssembly(self, theAssembly: mtk.ModelData_Assembly):
101 self.myNestingLevel -= 1
102
103 def VisitLeaveInstance(self, theInstance: mtk.ModelData_Instance):
104 self.myNestingLevel -= 1
105
106def main(theSource: str):
107 aKey = license.Value()
108
109 if not mtk.LicenseManager.Activate(aKey):
110 print("Failed to activate Manufacturing Toolkit license.")
111 return 1
112
113 aModel = mtk.ModelData_Model()
114
115 if not mtk.ModelData_ModelReader().Read(mtk.UTF16String(theSource), aModel):
116 print("Failed to read the file " + theSource)
117 return 1
118
119 aVisitor = SceneGraphVisitor()
120
121 aModel.Accept(aVisitor)
122 aVisitor.PrintCounts()
123
124 print("Completed")
125 return 0
126
127if __name__ == "__main__":
128 if len(sys.argv) != 2:
129 print("Usage: " + os.path.abspath(Path(__file__).resolve()) + " <input_file>, where:")
130 print(" <input_file> is a name of the file to be read")
131 sys.exit()
132
133 aSource = os.path.abspath(sys.argv[1])
134
135 sys.exit(main(aSource))