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

Refer to the B-Rep Topology Exploration Example.

1#!/usr/bin/env python3
2
3# $Id$
4
5# Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
6# Copyright (C) 2014-2025, CADEX. All rights reserved.
7
8# This file is part of the Manufacturing Toolkit software.
9
10# You may use this file under the terms of the BSD license as follows:
11
12# Redistribution and use in source and binary forms, with or without
13# modification, are permitted provided that the following conditions are met:
14# * Redistributions of source code must retain the above copyright notice,
15# this list of conditions and the following disclaimer.
16# * Redistributions in binary form must reproduce the above copyright notice,
17# this list of conditions and the following disclaimer in the documentation
18# and/or other materials provided with the distribution.
19
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30# POSSIBILITY OF SUCH DAMAGE.
31
32import sys
33import os
34
35from pathlib import Path
36
37import manufacturingtoolkit.CadExMTK as mtk
38
39sys.path.append(os.path.abspath(os.path.dirname(Path(__file__).resolve()) + "/../../"))
40
41import mtk_license as license
42
43class PartBRepVisitor(mtk.ModelData_ModelElementVoidVisitor):
44 def __init__(self):
45 super().__init__()
46 self.myNestingLevel = 0
47 self.myShapeSet = set()
48
49 def PrintUniqueShapesCount(self):
50 print();
51 print(f"Total unique shapes count: {len(self.myShapeSet)}")
52
53 def VisitPart(self, thePart: mtk.ModelData_Part):
54 aBodies = thePart.Bodies()
55 if thePart.NumberOfBodies() > 0:
56 self.ExploreBRep(aBodies)
57
58 def ExploreBRep(self, theBodies: mtk.Collections_BodyList):
59 for i, aBody in enumerate(theBodies):
60 print("Body ", i, ": -type ", self.PrintBodyType(aBody))
61 aShapeIt = mtk.ModelData_ShapeIterator(aBody)
62 for aShape in aShapeIt:
63 self.ExploreShape(aShape)
64
65 # Recursive iterating over the Shape until reaching vertices
66 def ExploreShape(self, theShape: mtk.ModelData_Shape):
67 self.myShapeSet.add(theShape)
68 self.myNestingLevel += 1
69 aShapeIt = mtk.ModelData_ShapeIterator(theShape)
70 while aShapeIt.HasNext():
71 aShape = aShapeIt.Next()
72 self.PrintShapeInfo(aShape)
73 self.ExploreShape(aShape)
74
75 self.myNestingLevel -= 1
76
77 # Returns body type name
78 def PrintBodyType(self, theBody: mtk.ModelData_Body) -> str:
79 if mtk.ModelData_SolidBody.CompareType(theBody):
80 return "Solid"
81 if mtk.ModelData_SheetBody.CompareType(theBody):
82 return "Sheet"
83 if mtk.ModelData_WireframeBody.CompareType(theBody):
84 return "Wireframe"
85 return "Undefined"
86
87 # Prints shape type name and prints shape info in some cases
88 def PrintShapeInfo(self, theShape: mtk.ModelData_Shape) -> str:
89 self.PrintTabulation()
90
91 aType = theShape.Type()
92 if aType == mtk.ShapeType_Solid:
93 print("Solid", end="")
94 elif aType == mtk.ShapeType_Shell:
95 print("Shell", end="")
96 elif aType == mtk.ShapeType_Wire:
97 print("Wire", end="")
98 self.PrintWireInfo(mtk.ModelData_Wire.Cast(theShape))
99 elif aType == mtk.ShapeType_Face:
100 print("Face", end="")
101 self.PrintFaceInfo(mtk.ModelData_Face.Cast(theShape))
102 elif aType == mtk.ShapeType_Edge:
103 print("Edge", end="")
104 self.PrintEdgeInfo(mtk.ModelData_Edge.Cast(theShape))
105 elif aType == mtk.ShapeType_Vertex:
106 print("Vertex", end="")
107 self.PrintVertexInfo(mtk.ModelData_Vertex.Cast(theShape))
108 else:
109 print("Undefined", end="")
110
111 print()
112
113 def PrintOrientationInfo(self, theShape: mtk.ModelData_Shape):
114 print(". Orientation: ", end="")
115 anOrientation = theShape.Orientation()
116 if anOrientation == mtk.ShapeOrientation_Forward:
117 print("Forward", end="")
118 elif anOrientation == mtk.ShapeOrientation_Reversed:
119 print("Reversed", end="")
120
121 def PrintWireInfo(self, theWire: mtk.ModelData_Wire):
122 self.myNestingLevel += 1
123 self.PrintOrientationInfo(theWire)
124 self.myNestingLevel -= 1
125
126 def PrintFaceInfo(self, theFace: mtk.ModelData_Face):
127 self.myNestingLevel += 1
128 self.PrintOrientationInfo(theFace)
129 print()
130 aSurface = theFace.Surface()
131 self.PrintTabulation()
132 print(f"Surface: {self.PrintSurfaceType(aSurface)}", end="")
133 self.myNestingLevel -= 1
134
135 def PrintSurfaceType(self, theSurface: mtk.Geom_Surface) -> str:
136 aType = theSurface.Type()
137 if aType == mtk.SurfaceType_Plane:
138 return "Plane"
139 if aType == mtk.SurfaceType_Cylinder:
140 return "Cylinder"
141 if aType == mtk.SurfaceType_Cone:
142 return "Cone"
143 if aType == mtk.SurfaceType_Sphere:
144 return "Sphere"
145 if aType == mtk.SurfaceType_Torus:
146 return "Torus"
147 if aType == mtk.SurfaceType_LinearExtrusion:
148 return "LinearExtrusion"
149 if aType == mtk.SurfaceType_Revolution:
150 return "Revolution"
151 if aType == mtk.SurfaceType_Bezier:
152 return "Bezier"
153 if aType == mtk.SurfaceType_BSpline:
154 return "BSpline"
155 if aType == mtk.SurfaceType_Offset:
156 return "Offset"
157 return "Undefined"
158
159 def PrintEdgeInfo(self, theEdge: mtk.ModelData_Edge):
160 self.myNestingLevel += 1
161 if theEdge.IsDegenerated():
162 print("(Degenerated)", end="")
163 self.PrintOrientationInfo(theEdge)
164 print(f". Tolerance {theEdge.Tolerance()}", end="")
165
166 if not theEdge.IsDegenerated():
167 print()
168 aCurve, aParamFirst, aParamLast = theEdge.Curve()
169 self.PrintTabulation()
170 print(f"Curve: {self.PrintCurveType(aCurve)}", end="")
171
172 self.myNestingLevel -= 1
173
174 def PrintCurveType(self, theCurve: mtk.Geom_Curve) -> str:
175 aType = theCurve.Type()
176 if aType == mtk.CurveType_Line:
177 return "Line"
178 if aType == mtk.CurveType_Circle:
179 return "Circle"
180 if aType == mtk.CurveType_Ellipse:
181 return "Ellipse"
182 if aType == mtk.CurveType_Hyperbola:
183 return "Hyperbola"
184 if aType == mtk.CurveType_Parabola:
185 return "Parabola"
186 if aType == mtk.CurveType_Bezier:
187 return "Bezier"
188 if aType == mtk.CurveType_BSpline:
189 return "BSpline"
190 if aType == mtk.CurveType_Offset:
191 return "Offset"
192 return "Undefined"
193
194 def PrintVertexInfo(self, theVertex: mtk.ModelData_Vertex):
195 self.PrintOrientationInfo(theVertex)
196 print(f". Tolerance {theVertex.Tolerance()}", end="")
197
198 def PrintTabulation(self):
199 print("- " * self.myNestingLevel, end="")
200
201import sys
202
203from os.path import abspath, dirname
204from pathlib import Path
205
206def main(theSource:str):
207 aKey = license.Value()
208
209 if not mtk.LicenseManager.Activate(aKey):
210 print("Failed to activate Manufacturing Toolkit license.")
211 return 1
212
213 aModel = mtk.ModelData_Model()
214
215 if not mtk.ModelData_ModelReader().Read(mtk.UTF16String(theSource), aModel):
216 print("Failed to read the file " + theSource)
217 #return 1
218
219 # Explore B-Rep representation of model parts
220 aVisitor = PartBRepVisitor()
221 aModel.Accept(aVisitor)
222
223 aVisitor.PrintUniqueShapesCount()
224
225 print("Completed")
226 return 0
227
228if __name__ == "__main__":
229 if len(sys.argv) != 2:
230 print("Usage: " + os.path.abspath(Path(__file__).resolve()) + " <input_file>, where:")
231 print(" <input_file> is a name of the file to be read")
232 sys.exit(1)
233
234 aSource = os.path.abspath(sys.argv[1])
235 sys.exit(main(aSource))