- Refer to the MTK Converter Example.
MTKConverter_PartProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28from abc import abstractmethod
29
30import manufacturingtoolkit.MTKCore as mtk
31
32class MTKConverter_ProcessData:
33 def __init__(self, thePart: mtk.ModelData_Part = None, theSheets = None):
34 if thePart is None:
35 thePart = mtk.ModelData_Part(mtk.UTF16String(""))
36 self.myPart = thePart
37 self.mySourceSheets = [] if theSheets is None else list(theSheets)
38
39class MTKConverter_PartProcessor(mtk.ModelData_ModelElementVoidVisitor):
40 def __init__(self):
41 super().__init__()
42 self.myData = []
43
44 def VisitPart(self, thePart: mtk.ModelData_Part):
45 aPartWasProcessed = False
46 aProcessData = self.CreateProcessData(thePart)
47
48 aBodyList = thePart.Bodies()
49 for aBody in aBodyList:
50 if mtk.ModelData_MeshBody.CompareType(aBody):
51 if self._ProcessMeshBody(aProcessData, mtk.ModelData_MeshBody.Cast(aBody)):
52 aPartWasProcessed = True
53 elif self._ProcessBRepBody(aProcessData, aBody):
54 aPartWasProcessed = True
55
56 if aPartWasProcessed:
57 self.PostProcessPart (thePart)
58 self.myData.append(aProcessData)
59
60 def _ProcessBRepBody(self, theProcessData : MTKConverter_ProcessData, theBody : mtk.ModelData_Body):
61 aBodyWasProcessed = False
62 aShapeIt = mtk.ModelData_ShapeIterator(theBody)
63 for aShape in aShapeIt:
64 if aShape.Type() == mtk.ShapeType_Solid:
65 self.ProcessSolid(theProcessData, mtk.ModelData_Solid.Cast(aShape))
66 aBodyWasProcessed = True
67 elif aShape.Type() == mtk.ShapeType_Shell:
68 self.ProcessShell(theProcessData, mtk.ModelData_Shell.Cast(aShape))
69 aBodyWasProcessed = True
70 return aBodyWasProcessed
71
72 def _ProcessMeshBody(self, theProcessData : MTKConverter_ProcessData, theBody : mtk.ModelData_MeshBody):
73 aBodyWasProcessed = False
74 for aMeshShape in theBody.Shapes():
75 if mtk.ModelData_IndexedTriangleSet.CompareType(aMeshShape):
76 self.ProcessMesh(theProcessData, mtk.ModelData_IndexedTriangleSet.Cast(aMeshShape))
77 aBodyWasProcessed = True
78
79 return aBodyWasProcessed
80
81 @abstractmethod
82 def CreateProcessData(self, thePart: mtk.ModelData_Part):
83 pass
84
85 @abstractmethod
86 def ProcessSolid(self, theProcessData: MTKConverter_ProcessData, theSolid: mtk.ModelData_Solid):
87 pass
88
89 @abstractmethod
90 def ProcessShell(self, theProcessData: MTKConverter_ProcessData, theShell: mtk.ModelData_Shell):
91 pass
92
93 @abstractmethod
94 def ProcessMesh(self, theProcessData: MTKConverter_ProcessData, theMesh: mtk.ModelData_IndexedTriangleSet):
95 pass
96
97 @abstractmethod
98 def PostProcessPart(self, thePart: mtk.ModelData_Part):
99 pass
100
101class MTKConverter_VoidPartProcessor(MTKConverter_PartProcessor):
102 def __init__(self):
103 super().__init__()
104
105 def ProcessSolid (self, theProcessData: MTKConverter_ProcessData, theSolid: mtk.ModelData_Solid):
106 pass
107
108 def ProcessShell (self, theProcessData: MTKConverter_ProcessData, theShell: mtk.ModelData_Shell):
109 pass
110
111 def ProcessMesh (self, theProcessData: MTKConverter_ProcessData, theMesh: mtk.ModelData_IndexedTriangleSet):
112 pass
113
114 def PostProcessPart(self, thePart: mtk.ModelData_Part):
115 pass
MTKConverter_DrawingProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import manufacturingtoolkit.MTKCore as mtk
29
30class MTKConverter_DrawingProcessor:
31 def __init__(self):
32 self.myData = []
33
34 def Apply(self, theDrawing: mtk.Drawing_Drawing):
35 raise NotImplementedError()
36
37 @staticmethod
38 def ExtractDrawingSheets(theDrawing: mtk.Drawing_Drawing):
39 aSheets = []
40 aSheetIt = mtk.Drawing_Drawing_SheetIterator(theDrawing)
41 while aSheetIt.HasNext():
42 aSheets.append(aSheetIt.Next())
43 return aSheets
44
45 @staticmethod
46 def AddSheets(theSrc: mtk.Drawing_Drawing, theDst: mtk.Drawing_Drawing):
47 if not theSrc:
48 return
49
50 anIt = mtk.Drawing_Drawing_SheetIterator(theSrc)
51 while anIt.HasNext():
52 theDst.AddSheet(anIt.Next())
MTKConverter_MachiningProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import manufacturingtoolkit.MTKCore as mtk
29
30import MTKConverter_PartProcessor as part_proc
31
32class MTKConverter_MachiningData(part_proc.MTKConverter_ProcessData):
33 def __init__(self, thePart: mtk.ModelData_Part):
34 super().__init__(thePart)
35 self.myFeatureList = mtk.MTKBase_FeatureList()
36 self.myIssueList = mtk.MTKBase_FeatureList()
37 self.myOperation = mtk.Machining_OT_Undefined
38
39class MTKConverter_MachiningProcessor(part_proc.MTKConverter_VoidPartProcessor):
40 def __init__(self, theOperation):
41 super().__init__()
42 self.myOperation = theOperation
43
44 def CreateProcessData(self, thePart: mtk.ModelData_Part):
45 return MTKConverter_MachiningData(thePart)
46
47 def ProcessSolid (self, theMachiningData: MTKConverter_MachiningData, theSolid: mtk.ModelData_Solid):
48 theMachiningData.myOperation = self.myOperation
49
50 aParams = mtk.Machining_FeatureRecognizerParameters()
51 aParams.SetOperation(self.myOperation)
52 aFeatureRecognizer = mtk.Machining_FeatureRecognizer(aParams)
53 anAnalyzer = mtk.Machining_Analyzer()
54 anAnalyzer.AddTool (aFeatureRecognizer)
55 aData = anAnalyzer.Perform(theSolid)
56 if aData.IsEmpty():
57 return
58
59
60 for i in aData.FeatureList():
61 theMachiningData.myFeatureList.Append(i)
62
63
64 aDrillingParameters = mtk.DFMMachining_DrillingAnalyzerParameters()
65 aDrillingAnalyzer = mtk.DFMMachining_Analyzer(aDrillingParameters)
66 theMachiningData.myIssueList.Append(aDrillingAnalyzer.Perform(theSolid, aData))
67
68 aMillingParameters = mtk.DFMMachining_MillingAnalyzerParameters()
69 aMillingAnalyzer = mtk.DFMMachining_Analyzer(aMillingParameters)
70 aMillingIssueList = aMillingAnalyzer.Perform(theSolid, aData)
71 for anIssue in aMillingIssueList:
72 if self.myOperation == mtk.Machining_OT_LatheMilling and not mtk.DFMMachining_DeepPocketIssue.CompareType(anIssue):
73 continue
74 theMachiningData.myIssueList.Append(anIssue)
75
76 if self.myOperation == mtk.Machining_OT_LatheMilling:
77 aTurninigParameters = mtk.DFMMachining_TurningAnalyzerParameters()
78 aTurningAnalyzer = mtk.DFMMachining_Analyzer(aTurninigParameters)
79 aTurningIssueList = aTurningAnalyzer.Perform(theSolid, aData)
80 for anIssue in aTurningIssueList:
81 theMachiningData.myIssueList.Append(anIssue)
MTKConverter_MoldingProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import manufacturingtoolkit.MTKCore as mtk
29
30import MTKConverter_PartProcessor as part_proc
31
32class MTKConverter_MoldingData(part_proc.MTKConverter_ProcessData):
33 def __init__(self, thePart: mtk.ModelData_Part):
34 super().__init__(thePart)
35 self.myFeatureList = mtk.MTKBase_FeatureList()
36 self.myIssueList = mtk.MTKBase_FeatureList()
37
38class MTKConverter_MoldingProcessor(part_proc.MTKConverter_VoidPartProcessor):
39 def __init__(self, theExtraDataModel: mtk.ModelData_Model):
40 super().__init__()
41 self.myExtraDataModel = theExtraDataModel
42 self.myCurrentNewFaces = mtk.ModelData_SheetBody()
43
44 def __AddNewFacesFromFeatures(self, theFeatureList : mtk.MTKBase_FeatureList, theSolid : mtk.ModelData_Solid):
45 aFaceIdSet = set()
46 aShapeIt = mtk.ModelData_ShapeIterator(theSolid, mtk.ShapeType_Face)
47 for aFace in aShapeIt:
48 aFaceIdSet.add(aFace.Id())
49
50 for aFeature in theFeatureList:
51 aShapeFeature = mtk.MTKBase_ShapeFeature.Cast(aFeature)
52 aFaceIt = mtk.ModelData_ShapeIterator(aShapeFeature.Shape(), mtk.ShapeType_Face)
53 for aFace in aFaceIt:
54 if aFace.Id() not in aFaceIdSet:
55 self.myCurrentNewFaces.Append(mtk.ModelData_Face.Cast(aFace))
56
57 def CreateProcessData(self, thePart: mtk.ModelData_Part):
58 return MTKConverter_MoldingData(thePart)
59
60 def ProcessSolid (self, theMoldingData: MTKConverter_MoldingData, theSolid: mtk.ModelData_Solid):
61 aParams = mtk.Molding_FeatureRecognizerParameters()
62 aFeatureRecognizer = mtk.Molding_FeatureRecognizer(aParams)
63 anAnalyzer = mtk.Molding_Analyzer()
64 anAnalyzer.AddTool(aFeatureRecognizer)
65 aData = anAnalyzer.Perform(theSolid)
66 if aData.IsEmpty():
67 return
68
69
70 theMoldingData.myFeatureList.Append(aData.FeatureList())
71 self.__AddNewFacesFromFeatures(aData.FeatureList(), theSolid)
72
73
74 aParameters = mtk.DFMMolding_AnalyzerParameters()
75 aDFMAnalyzer = mtk.DFMMolding_Analyzer(aParameters)
76 anIssueList = aDFMAnalyzer.Perform(aData)
77 theMoldingData.myIssueList.Append(anIssueList)
78
79 def PostProcessPart(self, thePart: mtk.ModelData_Part):
80 if len(self.myCurrentNewFaces.Shapes()) == 0:
81 return
82
83 anExtraDataPart = mtk.ModelData_Part(thePart.Name())
84 anExtraDataPart.SetUuid(thePart.Uuid())
85 anExtraDataPart.AddBody(self.myCurrentNewFaces)
86
87 self.myExtraDataModel.AddRoot(anExtraDataPart)
88 self.myCurrentNewFaces = mtk.ModelData_SheetBody()
MTKConverter_SheetMetalProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import manufacturingtoolkit.MTKCore as mtk
29
30import MTKConverter_PartProcessor as part_proc
31import MTKConverter_DrawingProcessor as drawing_proc
32
33
34class MTKConverter_UnfoldedPartData:
35 def __init__(self):
36 self.myFlatPatterns = []
37 self.myIssueList = mtk.MTKBase_FeatureList()
38
39 def IsInit(self):
40 return len(self.myFlatPatterns) > 0
41
42class MTKConverter_SheetMetalData(part_proc.MTKConverter_ProcessData):
43 def __init__(self, thePart: mtk.ModelData_Part):
44 super().__init__(thePart)
45 self.myIsSheetMetalPart = False
46 self.myFeatureList = mtk.MTKBase_FeatureList()
47 self.myIssueList = mtk.MTKBase_FeatureList()
48 self.myUnfoldedPartData = MTKConverter_UnfoldedPartData()
49
50class MTKConverter_SheetMetalProcessor(part_proc.MTKConverter_VoidPartProcessor):
51 def __init__(self, theUnfoldedModel: mtk.ModelData_Model):
52 super().__init__()
53 self.myAnalyzer = mtk.SheetMetal_Analyzer()
54 self.myAnalyzer.AddTool(mtk.SheetMetal_FeatureRecognizer())
55 self.myAnalyzer.AddTool(mtk.SheetMetal_Unfolder())
56 self.mySheetMetalResult = []
57
58 self.myUnfoldedModel = theUnfoldedModel
59 self.myCurrentUnfoldedBody = mtk.ModelData_SheetBody()
60
61 def CreateProcessData(self, thePart: mtk.ModelData_Part):
62 return MTKConverter_SheetMetalData(thePart)
63
64 def ProcessSolid(self, theProcessData: MTKConverter_SheetMetalData, theSolid: mtk.ModelData_Solid):
65 aData = self.myAnalyzer.Perform(theSolid)
66 self.mySheetMetalResult.append(aData)
67 self._Process(theProcessData, aData)
68
69 def ProcessShell(self, theProcessData: MTKConverter_SheetMetalData, theShell: mtk.ModelData_Shell):
70 aData = self.myAnalyzer.Perform(theShell)
71 self.mySheetMetalResult.append(aData)
72 self._Process(theProcessData, aData)
73
74 def PostProcessPart(self, thePart: mtk.ModelData_Part):
75 if len(self.myCurrentUnfoldedBody.Shapes()) == 0:
76 return
77
78 anUnfoldedPart = mtk.ModelData_Part(thePart.Name())
79 anUnfoldedPart.SetUuid(thePart.Uuid())
80 anUnfoldedPart.AddBody(self.myCurrentUnfoldedBody)
81
82 self.myUnfoldedModel.AddRoot(anUnfoldedPart)
83 self.myCurrentUnfoldedBody = mtk.ModelData_SheetBody()
84
85 def _Process(self, theProcessData: MTKConverter_SheetMetalData, theData: mtk.SheetMetal_Data):
86 if theData.IsEmpty():
87 return
88
89 theProcessData.myIsSheetMetalPart = True
90 theProcessData.myFeatureList.Append(theData.FeatureList())
91
92 aFlatPattern = theData.FlatPattern()
93 anUnfoldedShell = None
94 if aFlatPattern:
95 anUnfoldedShell = aFlatPattern.UnfoldedShell()
96
97 anUnfoldedData = theProcessData.myUnfoldedPartData
98 if anUnfoldedShell:
99 self.myCurrentUnfoldedBody.Append(anUnfoldedShell)
100 anUnfoldedData.myFlatPatterns.append(aFlatPattern)
101
102 aDrawingParams = mtk.DrawingParameters()
103 aDrawingParams.SetIsIgnoreBendingLines(True)
104
105 aFlatPatternDrawing = aFlatPattern.ToDrawing(aDrawingParams)
106 if aFlatPatternDrawing:
107 aSheetIt = mtk.Drawing_Drawing_SheetIterator(aFlatPatternDrawing)
108 while aSheetIt.HasNext():
109 aSheet = aSheetIt.Next()
110 aSheet.SetUuid(theProcessData.myPart.Uuid())
111
112 aDrawing = self.myUnfoldedModel.Drawing()
113 if not aDrawing:
114 self.myUnfoldedModel.SetDrawing(aFlatPatternDrawing)
115 else:
116 drawing_proc.MTKConverter_DrawingProcessor.AddSheets(aFlatPatternDrawing, aDrawing)
117 self.myUnfoldedModel.SetDrawing(aDrawing)
118
119 aDFMAnalyzer = mtk.DFMSheetMetal_Analyzer()
120 anIssueList = aDFMAnalyzer.Perform(theData)
121 for anIssue in anIssueList:
122 if (anUnfoldedData.IsInit() and
123 (mtk.DFMSheetMetal_FlatPatternInterferenceIssue.CompareType(anIssue) or
124 mtk.DFMSheetMetal_NonStandardSheetSizeIssue.CompareType(anIssue) or
125 mtk.DFMSheetMetal_NonStandardSheetThicknessIssue.CompareType(anIssue))):
126 anUnfoldedData.myIssueList.Append(anIssue)
127 else:
128 theProcessData.myIssueList.Append(anIssue)
MTKConverter_NestingProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import uuid
29
30import manufacturingtoolkit.MTKCore as mtk
31
32import MTKConverter_PartProcessor as part_proc
33import MTKConverter_DrawingProcessor as drawing_proc
34
35class MTKConverter_NestingData(part_proc.MTKConverter_ProcessData):
36 def __init__(self, theSheets):
37 super().__init__(theSheets=theSheets)
38 self.mySourceSheetUuids = [aSheet.Uuid() for aSheet in theSheets]
39 self.myPatterns = []
40 self.myResultDrawing = mtk.Drawing_Drawing(mtk.Initialized())
41 self.myPatternCountTotal = 0
42 self.myNestingResult = mtk.Nesting_Data()
43
44class MTKConverter_NestingProcessor(drawing_proc.MTKConverter_DrawingProcessor):
45 def __init__(self, theProcessModel: mtk.ModelData_Model, theNestingParameters):
46 super().__init__()
47 self.myProcessModel = theProcessModel
48 self.myNestingParameters = theNestingParameters
49
50 @staticmethod
51 def _ExtractPatternViews(theSheet: mtk.Drawing_Sheet):
52 aPatterns = []
53 aViewIt = mtk.Drawing_Sheet_ViewIterator(theSheet)
54 while aViewIt.HasNext():
55 aPatterns.append(aViewIt.Next())
56 return aPatterns
57
58 @staticmethod
59 def _AssignSheetUuids(theDrawing: mtk.Drawing_Drawing):
60 aSheetIt = mtk.Drawing_Drawing_SheetIterator(theDrawing)
61 while aSheetIt.HasNext():
62 aSheet = aSheetIt.Next()
63 aSheet.SetUuid(uuid.uuid4())
64
65 @staticmethod
66 def _MakeTrimmedLine(theStart: mtk.Geom_Point2d, theEnd: mtk.Geom_Point2d):
67 aDx = theEnd.X() - theStart.X()
68 aDy = theEnd.Y() - theStart.Y()
69 aLength = (aDx * aDx + aDy * aDy) ** 0.5
70
71 aLine = mtk.Geom_Line2d(theStart, mtk.Geom_Direction2d(aDx, aDy))
72 aLine.SetTrim(0.0, aLength)
73 return aLine
74
75 @staticmethod
76 def _AddNestingSheetFrames(theDrawing: mtk.Drawing_Drawing):
77 aSheetIt = mtk.Drawing_Drawing_SheetIterator(theDrawing)
78 while aSheetIt.HasNext():
79 aSheet = aSheetIt.Next()
80 aWidth = aSheet.Width()
81 aHeight = aSheet.Height()
82
83 aP1 = mtk.Geom_Point2d(0.0, 0.0)
84 aP2 = mtk.Geom_Point2d(aWidth, 0.0)
85 aP3 = mtk.Geom_Point2d(aWidth, aHeight)
86 aP4 = mtk.Geom_Point2d(0.0, aHeight)
87
88 aFrameContour = mtk.Drawing_PiecewiseContour()
89 aFrameContour.AddCurve(MTKConverter_NestingProcessor._MakeTrimmedLine(aP1, aP2))
90 aFrameContour.AddCurve(MTKConverter_NestingProcessor._MakeTrimmedLine(aP2, aP3))
91 aFrameContour.AddCurve(MTKConverter_NestingProcessor._MakeTrimmedLine(aP3, aP4))
92 aFrameContour.AddCurve(MTKConverter_NestingProcessor._MakeTrimmedLine(aP4, aP1))
93
94 aFrameView = mtk.Drawing_View(mtk.Initialized())
95 aFrameView.Add(aFrameContour)
96 aSheet.AddView(aFrameView)
97
98 def _CreateProcessData(self, theSheets):
99 return MTKConverter_NestingData(theSheets)
100
101 def _Process(self, theNestingData: MTKConverter_NestingData):
102 aComputer = mtk.Nesting_Computer()
103 aComputer.SetParameters(self.myNestingParameters.myComputerParameters)
104 aComputer.AddMaterial(
105 self.myNestingParameters.myMaterialParameters.myLength,
106 self.myNestingParameters.myMaterialParameters.myWidth,
107 self.myNestingParameters.myMaterialParameters.myCount)
108
109 theNestingData.myPatternCountTotal = (
110 len(theNestingData.myPatterns) * self.myNestingParameters.myPatternRepeatCount)
111
112 for aPattern in theNestingData.myPatterns:
113 aComputer.AddPattern(aPattern, self.myNestingParameters.myPatternRepeatCount)
114
115 theNestingData.myNestingResult = aComputer.Perform()
116
117 def _ProcessAllSheets(self, theSourceSheets):
118 aNestingData = self._CreateProcessData(theSourceSheets)
119
120 for aSourceSheet in theSourceSheets:
121 aNestingData.myPatterns.extend(MTKConverter_NestingProcessor._ExtractPatternViews(aSourceSheet))
122
123 self._Process(aNestingData)
124
125 aResultNestingDrawing = aNestingData.myNestingResult.ToDrawing()
126 if aResultNestingDrawing:
127 MTKConverter_NestingProcessor._AddNestingSheetFrames(aResultNestingDrawing)
128 MTKConverter_NestingProcessor._AssignSheetUuids(aResultNestingDrawing)
129 aNestingData.myResultDrawing = aResultNestingDrawing
130
131 self.myProcessModel.SetDrawing(aResultNestingDrawing)
132 self.myData.append(aNestingData)
133 return True
134
135 def _ProcessPerSheet(self, theSourceSheets):
136 aResultNestingDrawing = mtk.Drawing_Drawing(mtk.Initialized())
137
138 for aSourceSheet in theSourceSheets:
139 aNestingData = self._CreateProcessData([aSourceSheet])
140 aNestingData.myPatterns = MTKConverter_NestingProcessor._ExtractPatternViews(aSourceSheet)
141
142 self._Process(aNestingData)
143
144 aSourceNestingDrawing = aNestingData.myNestingResult.ToDrawing()
145 if aSourceNestingDrawing:
146 MTKConverter_NestingProcessor._AddNestingSheetFrames(aSourceNestingDrawing)
147 MTKConverter_NestingProcessor._AssignSheetUuids(aSourceNestingDrawing)
148 aNestingData.myResultDrawing = aSourceNestingDrawing
149 drawing_proc.MTKConverter_DrawingProcessor.AddSheets(aSourceNestingDrawing, aResultNestingDrawing)
150
151 self.myData.append(aNestingData)
152
153 self.myProcessModel.SetDrawing(aResultNestingDrawing)
154 return True
155
156 def Apply(self, theDrawing: mtk.Drawing_Drawing):
157 self.myData.clear()
158 aSourceSheets = drawing_proc.MTKConverter_DrawingProcessor.ExtractDrawingSheets(theDrawing)
159 if not aSourceSheets:
160 print("\nERROR: Nesting requires at least one sheet in the source drawing.")
161 return False
162
163 if self.myNestingParameters.myMode == self.myNestingParameters.NestingMode.AllSheets:
164 return self._ProcessAllSheets(aSourceSheets)
165 return self._ProcessPerSheet(aSourceSheets)
MTKConverter_WallThicknessProcessor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import sys
29
30import manufacturingtoolkit.MTKCore as mtk
31
32import MTKConverter_PartProcessor as part_proc
33from mesh_colorizer import MeshColorizer
34
35
36class PointPair:
37 def __init__(self, theFirst=None, theSecond=None):
38 self.First = mtk.Geom_Point() if theFirst is None else theFirst
39 self.Second = mtk.Geom_Point() if theSecond is None else theSecond
40
41
42class MTKConverter_WallThicknessData(part_proc.MTKConverter_ProcessData):
43 def __init__(self, thePart: mtk.ModelData_Part):
44 super().__init__(thePart)
45 self.myIsInit = False
46
47 self.myMinThickness = sys.float_info.max
48 self.myMaxThickness = -sys.float_info.max
49 self.myAvgThickness = 0.0
50 self.myThicknessPointCount = 0
51
52 self.myMinThicknessPoints = PointPair()
53 self.myMaxThicknessPoints = PointPair()
54
55
56class MTKConverter_WallThicknessProcessor(part_proc.MTKConverter_VoidPartProcessor):
57 def __init__(self, theExtraDataModel: mtk.ModelData_Model, theWallThicknessParameters):
58 super().__init__()
59 self.myAnalyzer = mtk.WallThickness_Analyzer(theWallThicknessParameters.myAnalyzerParameters)
60 self.myExtraDataModel = theExtraDataModel
61 self.myColorizer = MeshColorizer(theWallThicknessParameters.myColorSmoothness)
62 self.myColoredITS = None
63
64 def CreateProcessData(self, thePart: mtk.ModelData_Part):
65 return MTKConverter_WallThicknessData(thePart)
66
67 def ProcessSolid(self, theProcessData: MTKConverter_WallThicknessData, theSolid: mtk.ModelData_Solid):
68 aWTData = self.myAnalyzer.Perform(theSolid)
69
70 aMesh = mtk.ModelAlgo_MeshGenerator().Generate(theSolid, False)
71 if aMesh:
72 self._ProcessResult(theProcessData, mtk.ModelData_IndexedTriangleSet.Cast(aMesh), aWTData)
73
74 def ProcessMesh(self, theProcessData: MTKConverter_WallThicknessData, theMesh: mtk.ModelData_IndexedTriangleSet):
75 aWTData = self.myAnalyzer.Perform(theMesh)
76 self._ProcessResult(theProcessData, theMesh, aWTData)
77
78 def _ProcessResult(
79 self,
80 theWTData: MTKConverter_WallThicknessData,
81 theMesh: mtk.ModelData_IndexedTriangleSet,
82 theData: mtk.WallThickness_Data):
83 if theData.IsEmpty():
84 return
85
86 theWTData.myIsInit = True
87
88 if theWTData.myMinThickness > theData.MinThickness():
89 theWTData.myMinThickness = theData.MinThickness()
90 aFirstPoint = mtk.Geom_Point()
91 aSecondPoint = mtk.Geom_Point()
92 theData.PointsOfMinThickness(aFirstPoint, aSecondPoint)
93 theWTData.myMinThicknessPoints = PointPair(aFirstPoint, aSecondPoint)
94
95 if theWTData.myMaxThickness < theData.MaxThickness():
96 theWTData.myMaxThickness = theData.MaxThickness()
97 aFirstPoint = mtk.Geom_Point()
98 aSecondPoint = mtk.Geom_Point()
99 theData.PointsOfMaxThickness(aFirstPoint, aSecondPoint)
100 theWTData.myMaxThicknessPoints = PointPair(aFirstPoint, aSecondPoint)
101
102 aThicknessSum = 0.0
103 aThicknessList = theData.ThicknessList()
104 if not aThicknessList.IsEmpty():
105 aThicknessListSize = len(aThicknessList)
106 for i in range(aThicknessListSize):
107 aThicknessSum += aThicknessList.Value(i)
108
109 aPrevThicknessPointCount = theWTData.myThicknessPointCount
110 aTotalThicknessPointCount = aPrevThicknessPointCount + aThicknessListSize
111 theWTData.myAvgThickness = (
112 theWTData.myAvgThickness * (aPrevThicknessPointCount / aTotalThicknessPointCount)
113 + aThicknessSum / aTotalThicknessPointCount)
114 theWTData.myThicknessPointCount = aTotalThicknessPointCount
115
116 aColoredITS = self.myColorizer.Perform(theMesh, theData)
117
118 if aColoredITS is not None:
119 if self.myColoredITS is not None:
120 self.myColoredITS.AddTriangles(aColoredITS)
121 else:
122 self.myColoredITS = aColoredITS
123
124 def PostProcessPart(self, thePart: mtk.ModelData_Part):
125 if self.myColoredITS is None:
126 return
127
128 anExtraDataPart = mtk.ModelData_Part(thePart.Name())
129 anExtraDataPart.SetUuid(thePart.Uuid())
130 aMeshBody = mtk.ModelData_MeshBody(self.myColoredITS)
131 anExtraDataPart.AddBody(aMeshBody)
132
133 self.myExtraDataModel.AddRoot(anExtraDataPart)
134 self.myColoredITS = None
MTKConverter_Report.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import os
29import sys
30
31from pathlib import Path
32from typing import Any, Iterable, List, Sequence
33
34import manufacturingtoolkit.MTKCore as mtk
35
36import MTKConverter_PartProcessor as part_proc
37import MTKConverter_MachiningProcessor as mach_proc
38import MTKConverter_MoldingProcessor as mold_proc
39import MTKConverter_SheetMetalProcessor as sm_proc
40import MTKConverter_WallThicknessProcessor as wt_proc
41import MTKConverter_DrawingProcessor as drawing_proc
42import MTKConverter_NestingProcessor as nesting_proc
43
44sys.path.append(os.path.abspath(os.path.dirname(Path(__file__).resolve()) + "/../helpers/"))
45
46from JSONWriter import JSONWriter
47
48class Point:
49 def __init__(self, theX: float, theY: float, theZ: float) -> None:
50 self.X = theX
51 self.Y = theY
52 self.Z = theZ
53
54 def __repr__(self) -> str:
55 return f"Point({self.X}, {self.Y}, {self.Z})"
56
57 def __str__(self) -> str:
58 return f"({self.X:.2f}, {self.Y:.2f}, {self.Z:.2f})"
59
60class MTKConverter_Report:
61 def __init__(self) -> None:
62 self.myData: List[part_proc.MTKConverter_ProcessData] = []
63
64 def AddData(self, theData: part_proc.MTKConverter_ProcessData) -> None:
65 self.myData.append(theData)
66
67 @staticmethod
68 def _WriteParameter(
69 theWriter: JSONWriter,
70 theParamName: str,
71 theParamUnits: str,
72 theParamValue: Any) -> None:
73 theWriter.OpenSection()
74 theWriter.WriteData("name", theParamName)
75 theWriter.WriteData("units", theParamUnits)
76 theWriter.WriteData("value", theParamValue)
77 theWriter.CloseSection()
78
79 @staticmethod
80 def _WriteFeatures(
81 theWriter: JSONWriter,
82 theGroupName: str,
83 theSubgroupName: str,
84 theFeatures: mtk.MTKBase_FeatureList,
85 theMessageForEmptyList: str) -> bool:
86 theWriter.OpenSection(theSubgroupName)
87 theWriter.WriteData("name", theGroupName)
88
89 if theFeatures.IsEmpty():
90 theWriter.WriteData("message", theMessageForEmptyList)
91 else:
92 aParams = mtk.Utilities_JSONSerializerParameters()
93 aParams.SetStartIndentLevel(theWriter.NestingLevel())
94 aJSONSerializer = mtk.Utilities_JSONSerializer(aParams)
95 aFeaturesJSON = aJSONSerializer.Serialize(theFeatures)
96 theWriter.WriteRawData(aFeaturesJSON)
97
98 theWriter.CloseSection()
99 return True
100
101 @staticmethod
102 def _MachiningProcessName(theOperation: int) -> str:
103 if theOperation == mtk.Machining_OT_Milling:
104 return "CNC Machining Milling"
105 if theOperation == mtk.Machining_OT_LatheMilling:
106 return "CNC Machining Lathe+Milling"
107 return "CNC Machining"
108
109 @staticmethod
110 def _HasShapes(theBodies: Iterable[Any], theType: int) -> bool:
111 for aBody in theBodies:
112 aShapeIt = mtk.ModelData_ShapeIterator(aBody, theType)
113 if aShapeIt.HasNext():
114 return True
115 return False
116
117 @staticmethod
118 def _WriteThicknessNode(
119 theWriter: JSONWriter,
120 theParamName: str,
121 theParamValue: float,
122 thePoints: wt_proc.PointPair,
123 theNodeName: str) -> None:
124 aFirstPoint = thePoints.First
125 aSecondPoint = thePoints.Second
126 theWriter.OpenSection(theNodeName)
127 theWriter.WriteData("name", theParamName)
128 theWriter.WriteData("units", "mm")
129 theWriter.WriteData("value", theParamValue)
130 theWriter.WriteData("firstPoint", Point(aFirstPoint.X(), aFirstPoint.Y(), aFirstPoint.Z()))
131 theWriter.WriteData("secondPoint", Point(aSecondPoint.X(), aSecondPoint.Y(), aSecondPoint.Z()))
132 theWriter.CloseSection()
133
134 @staticmethod
135 def _WriteWallThicknessData(theWriter: JSONWriter, theWTData: wt_proc.MTKConverter_WallThicknessData) -> None:
136 MTKConverter_Report._WriteThicknessNode(
137 theWriter,
138 "Minimum Thickness",
139 theWTData.myMinThickness,
140 theWTData.myMinThicknessPoints,
141 "minThickness")
142 MTKConverter_Report._WriteThicknessNode(
143 theWriter,
144 "Maximum Thickness",
145 theWTData.myMaxThickness,
146 theWTData.myMaxThicknessPoints,
147 "maxThickness")
148
149 theWriter.OpenArraySection("parameters")
150 MTKConverter_Report._WriteParameter(theWriter, "Minimum Thickness", "mm", theWTData.myMinThickness)
151 MTKConverter_Report._WriteParameter(theWriter, "Maximum Thickness", "mm", theWTData.myMaxThickness)
152 MTKConverter_Report._WriteParameter(theWriter, "Average Thickness", "mm", theWTData.myAvgThickness)
153 theWriter.CloseArraySection()
154
155 @staticmethod
156 def _WriteUnfoldedPartFeatures(theWriter: JSONWriter, theData: sm_proc.MTKConverter_UnfoldedPartData) -> None:
157 theWriter.OpenSection("featureRecognitionUnfolded")
158 theWriter.WriteData("name", "Feature Recognition")
159
160 if theData.IsInit():
161 aParams = mtk.Utilities_JSONSerializerParameters()
162 aParams.SetStartIndentLevel(4)
163 aJSONSerializer = mtk.Utilities_JSONSerializer(aParams)
164 aFeaturesJSON = aJSONSerializer.Serialize(theData.myFlatPatterns[0])
165 theWriter.WriteRawData(aFeaturesJSON)
166 else:
167 theWriter.WriteData("message", "Unfolded part wasn't generated.")
168
169 theWriter.CloseSection()
170
171 @staticmethod
172 def _WriteNestingData(
173 theWriter: JSONWriter,
174 theResultSheets: Sequence[Any],
175 theFreeSpaces: Sequence[float],
176 thePatternCountTotal: int,
177 theNestedPatternCounts: Sequence[int]) -> None:
178 theWriter.OpenSection("nesting")
179 theWriter.OpenArraySection("sheets")
180 for i in range(len(theResultSheets)):
181 aResultSheet = theResultSheets[i]
182 aFreeSpace = theFreeSpaces[i] if i < len(theFreeSpaces) else 0.0
183 aNestedPatternCount = theNestedPatternCounts[i] if i < len(theNestedPatternCounts) else 0
184
185 theWriter.OpenSection()
186 theWriter.WriteData("sheetId", aResultSheet.Uuid())
187 theWriter.OpenArraySection("parameters")
188 MTKConverter_Report._WriteParameter(theWriter, "Sheet Length", "mm", aResultSheet.Height())
189 MTKConverter_Report._WriteParameter(theWriter, "Sheet Width", "mm", aResultSheet.Width())
190 MTKConverter_Report._WriteParameter(theWriter, "Free Space", "mm^2", aFreeSpace)
191 MTKConverter_Report._WriteParameter(theWriter, "Requested Pattern Count", "pcs", thePatternCountTotal)
192 MTKConverter_Report._WriteParameter(theWriter, "Nested Pattern Count", "pcs", aNestedPatternCount)
193 theWriter.CloseArraySection()
194 theWriter.CloseSection()
195 theWriter.CloseArraySection()
196 theWriter.CloseSection()
197
198 @staticmethod
199 def _WriteUuidArray(theWriter: JSONWriter, theName: str, theUuids: Sequence[Any]) -> None:
200 aCurrentIndent = " " * (theWriter.NestingLevel() * 4)
201 aArrayValueIndent = " " * ((theWriter.NestingLevel() + 1) * 4)
202
203 aRawData = aCurrentIndent + "\"" + theName + "\": ["
204 if theUuids:
205 aRawData += "\n"
206 for i in range(len(theUuids)):
207 aRawData += aArrayValueIndent + "\"" + str(theUuids[i]) + "\""
208 if i + 1 < len(theUuids):
209 aRawData += ","
210 aRawData += "\n"
211 aRawData += aCurrentIndent
212 aRawData += "]"
213 theWriter.WriteRawData(aRawData)
214
215 @staticmethod
216 def _IsSheetProcessData(theProcessData: part_proc.MTKConverter_ProcessData) -> bool:
217 return isinstance(theProcessData, nesting_proc.MTKConverter_NestingData)
218
219 def _WritePartProcessData(self, theWriter: JSONWriter, theProcessData: part_proc.MTKConverter_ProcessData) -> None:
220 aRes = False
221 theWriter.WriteData("partId", theProcessData.myPart.Uuid())
222
223 anErrorMsg = "An error occurred while processing the part."
224 if isinstance(theProcessData, mach_proc.MTKConverter_MachiningData):
225 theWriter.WriteData("process", self._MachiningProcessName(theProcessData.myOperation))
226 aBodies = theProcessData.myPart.Bodies()
227 if not theProcessData.myFeatureList.IsEmpty():
228 self._WriteFeatures(theWriter, "Feature Recognition", "featureRecognition", theProcessData.myFeatureList, "")
229 self._WriteFeatures(
230 theWriter,
231 "Design for Manufacturing",
232 "dfm",
233 theProcessData.myIssueList,
234 "Part contains no DFM improvement suggestions.")
235 aRes = True
236 elif len(aBodies) == 0 or not self._HasShapes(aBodies, mtk.ShapeType_Solid):
237 anErrorMsg = "The part can't be analyzed due to lack of: BRep representation or solids in BRep representation."
238 elif isinstance(theProcessData, wt_proc.MTKConverter_WallThicknessData):
239 theWriter.WriteData("process", "Wall Thickness Analysis")
240 aBodies = theProcessData.myPart.Bodies()
241 if theProcessData.myIsInit:
242 self._WriteWallThicknessData(theWriter, theProcessData)
243 aRes = True
244 elif len(aBodies) == 0 or not self._HasShapes(aBodies, mtk.ShapeType_Solid):
245 anErrorMsg = "The part can't be analyzed due to lack of: BRep representation, solids in BRep representation."
246 elif isinstance(theProcessData, mold_proc.MTKConverter_MoldingData):
247 aBodies = theProcessData.myPart.Bodies()
248 if not theProcessData.myFeatureList.IsEmpty():
249 theWriter.WriteData("process", "Molding Analysis")
250 self._WriteFeatures(theWriter, "Feature Recognition", "featureRecognition", theProcessData.myFeatureList, "")
251 self._WriteFeatures(
252 theWriter,
253 "Design for Manufacturing",
254 "dfm",
255 theProcessData.myIssueList,
256 "Part contains no DFM improvement suggestions.")
257 aRes = True
258 elif len(aBodies) == 0 or not self._HasShapes(aBodies, mtk.ShapeType_Solid):
259 anErrorMsg = "The part can't be analyzed due to lack of: BRep representation or solids in BRep representation."
260 elif isinstance(theProcessData, sm_proc.MTKConverter_SheetMetalData):
261 theWriter.WriteData("process", "Sheet Metal")
262 aBodies = theProcessData.myPart.Bodies()
263 if theProcessData.myIsSheetMetalPart:
264 self._WriteFeatures(
265 theWriter,
266 "Feature Recognition",
267 "featureRecognition",
268 theProcessData.myFeatureList,
269 "Part contains no features.")
270 self._WriteFeatures(
271 theWriter,
272 "Design for Manufacturing",
273 "dfm",
274 theProcessData.myIssueList,
275 "Part contains no DFM improvement suggestions.")
276
277 anUnfoldedPartData = theProcessData.myUnfoldedPartData
278 self._WriteUnfoldedPartFeatures(theWriter, anUnfoldedPartData)
279 if anUnfoldedPartData.IsInit():
280 self._WriteFeatures(
281 theWriter,
282 "Design for Manufacturing",
283 "dfmUnfolded",
284 anUnfoldedPartData.myIssueList,
285 "Unfolded part contains no DFM improvement suggestions.")
286 aRes = True
287 elif len(aBodies) == 0 or (
288 not self._HasShapes(aBodies, mtk.ShapeType_Solid) and
289 not self._HasShapes(aBodies, mtk.ShapeType_Shell)):
290 anErrorMsg = "The part can't be analyzed due to lack of: BRep representation, solids and shells in BRep representation."
291 else:
292 anErrorMsg = "The part wasn't recognized as a sheet metal part."
293 else:
294 anErrorMsg = "Unrecognized process"
295
296 if not aRes:
297 theWriter.WriteData("error", anErrorMsg)
298
299 def _WriteSheetProcessData(self, theWriter: JSONWriter, theProcessData: part_proc.MTKConverter_ProcessData) -> None:
300 aRes = False
301 if isinstance(theProcessData, nesting_proc.MTKConverter_NestingData):
302 self._WriteUuidArray(theWriter, "sourceIds", theProcessData.mySourceSheetUuids)
303
304 aResultSheets = drawing_proc.MTKConverter_DrawingProcessor.ExtractDrawingSheets(theProcessData.myResultDrawing)
305 aSheetFreeSpaces = []
306 aNestedPatternCounts = []
307 for aSheet in theProcessData.myNestingResult.Sheets():
308 aSheetFreeSpaces.append(aSheet.Scrap() * aSheet.SheetArea())
309 aNestedPatternCounts.append(aSheet.NestedParts())
310
311 if aResultSheets:
312 theWriter.WriteData("process", "Nesting")
313 self._WriteNestingData(
314 theWriter,
315 aResultSheets,
316 aSheetFreeSpaces,
317 theProcessData.myPatternCountTotal,
318 aNestedPatternCounts)
319 aRes = True
320
321 if not aRes:
322 theWriter.WriteData("error", "An error occurred while processing the sheet.")
323
324 def WriteToJSON(self, thePath: str) -> bool:
325 try:
326 with open(thePath, "w", encoding="utf-8") as aFile:
327 aWriter = JSONWriter(aFile)
328 aWriter.OpenSection()
329 aWriter.WriteData("version", "1")
330
331 if not self.myData:
332 aWriter.WriteData("error", "The model doesn't contain any parts.")
333 else:
334 aHasPartProcessData = False
335 aHasSheetProcessData = False
336 for aProcessData in self.myData:
337 if self._IsSheetProcessData(aProcessData):
338 aHasSheetProcessData = True
339 else:
340 aHasPartProcessData = True
341
342 if aHasPartProcessData:
343 aWriter.OpenArraySection("parts")
344 for aProcessData in self.myData:
345 if self._IsSheetProcessData(aProcessData):
346 continue
347 aWriter.OpenSection()
348 self._WritePartProcessData(aWriter, aProcessData)
349 aWriter.CloseSection()
350 aWriter.CloseArraySection()
351
352 if aHasSheetProcessData:
353 aWriter.OpenArraySection("sheets")
354 for aProcessData in self.myData:
355 if not self._IsSheetProcessData(aProcessData):
356 continue
357 aWriter.OpenSection()
358 self._WriteSheetProcessData(aWriter, aProcessData)
359 aWriter.CloseSection()
360 aWriter.CloseArraySection()
361
362 aWriter.CloseSection()
363 except Exception:
364 return False
365
366 return True
MTKConverter_Application.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28from enum import Enum
29import os
30
31import manufacturingtoolkit.MTKCore as mtk
32import manufacturingtoolkit.MTKView as view
33
34import MTKConverter_PartProcessor as part_proc
35import MTKConverter_DrawingProcessor as drawing_proc
36from MTKConverter_Report import MTKConverter_Report
37from MTKConverter_MachiningProcessor import MTKConverter_MachiningProcessor
38from MTKConverter_MoldingProcessor import MTKConverter_MoldingProcessor
39from MTKConverter_SheetMetalProcessor import MTKConverter_SheetMetalProcessor
40from MTKConverter_WallThicknessProcessor import MTKConverter_WallThicknessProcessor
41from MTKConverter_NestingProcessor import MTKConverter_NestingProcessor
42
43class MTKConverter_ReturnCode(Enum):
44
45 Ok = 0
46 UnknownError = 1
47 GeneralException = 2
48 NoValidLicense = 3
49 InvalidArgumentsNumber = 4
50 InvalidArgument = 5
51
52
53 UnsupportedVersion = 100
54 UnexpectedFormat = 101
55 UnsupportedFileVariant = 102
56 ImportError = 103
57
58
59 ProcessError = 200
60
61
62 ExportError = 300
63
64class MTKConverter_ProcessType(Enum):
65 Undefined = -1
66 WallThickness = 0
67 MachiningMilling = 1
68 MachiningTurning = 2
69 Molding = 3
70 SheetMetal = 4
71 Nesting = 5
72
73class MTKConverter_ArgumentType(Enum):
74 Neutral = 0
75 Import = 1
76 Process = 2
77 Export = 3
78
79class MTKConverter_Argument:
80 def __init__(self, theArgumentType: MTKConverter_ArgumentType, theValue: str):
81 self.myArgumentType = theArgumentType
82 self.myValue = theValue
83
84class MTKConverter_ImportParameters:
85 def __init__(self):
86 self.myReaderParameters = mtk.ModelData_ModelReaderParameters()
87 self.myReaderParameters.SetReadPMI(False)
88 self.myReaderParameters.SetReadDrawing(False)
89 self.myReaderParameters.SetEnableAnalyticalRecognition(True)
90
91class MTKConverter_NestingParameters:
92 class NestingMode(Enum):
93 PerSheet = 0
94 AllSheets = 1
95
96 class MaterialParameters:
97 def __init__(self):
98 self.myLength = 500.0
99 self.myWidth = 500.0
100 self.myCount = 1
101
102 def __init__(self):
103 self.myMaterialParameters = self.MaterialParameters()
104 self.myPatternRepeatCount = 4
105 self.myMode = self.NestingMode.PerSheet
106 self.myComputerParameters = mtk.Nesting_ComputerParameters()
107 self.myComputerParameters.SetIterationCount(20)
108 self.myComputerParameters.SetGenerationSize(3)
109 self.myComputerParameters.SetMutationRate(2.0)
110 self.myComputerParameters.SetCurveTolerance(100.0)
111 self.myComputerParameters.SetPartToPartDistance(0)
112 self.myComputerParameters.SetPartToSheetBoundaryDistance(0)
113 self.myComputerParameters.SetRotationCount(4)
114 self.myComputerParameters.SetMirrorControl(False)
115 self.myComputerParameters.SetNestingInHoles(False)
116
117class MTKConverter_WallThicknessParameters:
118 def __init__(self):
119 self.myAnalyzerParameters = mtk.WallThickness_AnalyzerParameters()
120 aVoxelizationParameters = self.myAnalyzerParameters.VoxelizationParameters()
121 aVoxelizationParameters.SetResolution(800)
122 self.myColorSmoothness = 0.75
123
124class MTKConverter_ExportParameters:
125 def __init__(self):
126 self.myIsScreenshotGenerationEnabled = True
127 self.myIsExportMTKEnabled = False
128
129class MTKConverter_Parameters:
130 def __init__(self):
131 self.myImportParameters = MTKConverter_ImportParameters()
132 self.myNestingParameters = MTKConverter_NestingParameters()
133 self.myWallThicknessParameters = MTKConverter_WallThicknessParameters()
134 self.myExportParameters = MTKConverter_ExportParameters()
135
136class MTKConverter_Application:
137 @staticmethod
138 def _FindProcessType(theProcessName: str):
139 aProcessMap = {
140 "wall_thickness": MTKConverter_ProcessType.WallThickness,
141 "machining_milling": MTKConverter_ProcessType.MachiningMilling,
142 "machining_turning": MTKConverter_ProcessType.MachiningTurning,
143 "molding": MTKConverter_ProcessType.Molding,
144 "sheet_metal": MTKConverter_ProcessType.SheetMetal,
145 "nesting": MTKConverter_ProcessType.Nesting
146 }
147 return aProcessMap.get(theProcessName, MTKConverter_ProcessType.Undefined)
148
149 @staticmethod
150 def _Import(
151 theFilePath: str,
152 theModel: mtk.ModelData_Model,
153 theImportParameters: MTKConverter_ImportParameters):
154 print("Importing ", theFilePath, "...", sep="", end="", flush=True)
155
156 aReader = mtk.ModelData_ModelReader()
157 aReader.SetParameters(theImportParameters.myReaderParameters)
158 if not aReader.Read(mtk.UTF16String(theFilePath), theModel):
159 print("\nERROR: Failed to import ", theFilePath, ". Exiting", sep="")
160 return MTKConverter_ReturnCode.ImportError
161
162 return MTKConverter_ReturnCode.Ok
163
164 @staticmethod
165 def _ApplyPartProcessorToModel(
166 theModel: mtk.ModelData_Model,
167 theReport: MTKConverter_Report,
168 theProcessor: part_proc.MTKConverter_PartProcessor):
169 aVisitor = mtk.ModelData_ModelElementUniqueVisitor(theProcessor)
170 theModel.Accept(aVisitor)
171 for i in theProcessor.myData:
172 theReport.AddData(i)
173 return MTKConverter_ReturnCode.Ok
174
175 @staticmethod
176 def _ApplyDrawingProcessorToModel(
177 theModel: mtk.ModelData_Model,
178 theProcessModel: mtk.ModelData_Model,
179 theReport: MTKConverter_Report,
180 theProcessor: drawing_proc.MTKConverter_DrawingProcessor):
181 aDrawing = theProcessModel.Drawing()
182 if not aDrawing:
183 aDrawing = theModel.Drawing()
184 if not aDrawing:
185 print("\nERROR: Drawing is required, but none was found in the process/source model.")
186 return MTKConverter_ReturnCode.ProcessError
187
188 if not theProcessor.Apply(aDrawing):
189 return MTKConverter_ReturnCode.ProcessError
190
191 for i in theProcessor.myData:
192 theReport.AddData(i)
193 return MTKConverter_ReturnCode.Ok
194
195 @staticmethod
196 def _Process(
197 theProcess: str,
198 theModel: mtk.ModelData_Model,
199 theReport: MTKConverter_Report,
200 theProcessModel: mtk.ModelData_Model,
201 theParameters: MTKConverter_Parameters):
202 print("Processing ", theProcess, "...", sep="", end="", flush=True)
203
204 aProcessType = MTKConverter_Application._FindProcessType(theProcess)
205 if aProcessType == MTKConverter_ProcessType.WallThickness:
206 theProcessModel.SetName(mtk.UTF16String("extra"))
207 aProcessor = MTKConverter_WallThicknessProcessor(theProcessModel, theParameters.myWallThicknessParameters)
208 return MTKConverter_Application._ApplyPartProcessorToModel(theModel, theReport, aProcessor)
209 if aProcessType == MTKConverter_ProcessType.MachiningMilling:
210 aProcessor = MTKConverter_MachiningProcessor(mtk.Machining_OT_Milling)
211 return MTKConverter_Application._ApplyPartProcessorToModel(theModel, theReport, aProcessor)
212 if aProcessType == MTKConverter_ProcessType.MachiningTurning:
213 aProcessor = MTKConverter_MachiningProcessor(mtk.Machining_OT_LatheMilling)
214 return MTKConverter_Application._ApplyPartProcessorToModel(theModel, theReport, aProcessor)
215 if aProcessType == MTKConverter_ProcessType.Molding:
216 theProcessModel.SetName(mtk.UTF16String(str(theModel.Name()) + "_extra"))
217 aProcessor = MTKConverter_MoldingProcessor(theProcessModel)
218 return MTKConverter_Application._ApplyPartProcessorToModel(theModel, theReport, aProcessor)
219 if aProcessType == MTKConverter_ProcessType.SheetMetal:
220 theProcessModel.SetName(mtk.UTF16String(str(theModel.Name()) + "_unfolded"))
221 aProcessor = MTKConverter_SheetMetalProcessor(theProcessModel)
222 return MTKConverter_Application._ApplyPartProcessorToModel(theModel, theReport, aProcessor)
223 if aProcessType == MTKConverter_ProcessType.Nesting:
224 theProcessModel.SetName(mtk.UTF16String(str(theModel.Name()) + "_nested"))
225 aProcessor = MTKConverter_NestingProcessor(theProcessModel, theParameters.myNestingParameters)
226 return MTKConverter_Application._ApplyDrawingProcessorToModel(theModel, theProcessModel, theReport, aProcessor)
227 return MTKConverter_ReturnCode.InvalidArgument
228
229 @staticmethod
230 def _CreateOriginModelThumbnail(theFilePath: str, theModel: mtk.ModelData_Model):
231 aWriter = view.View_ImageWriter()
232 aParameters = aWriter.Parameters()
233 aParameters.SetImageHeight(800)
234 aParameters.SetImageWidth(600)
235 aParameters.SetViewCameraProjection(view.CameraProjectionType_Perspective)
236 aParameters.SetViewCameraPosition(view.CameraPositionType_Default)
237 aParameters.SetViewIsFitAll(True)
238 aParameters.SetViewAntialiasing(view.AntialiasingMode_High)
239 aParameters.SetViewBackground(view.View_ColorBackgroundStyle(mtk.Materials_Color(255, 255, 255)))
240 aWriter.SetParameters(aParameters)
241 return aWriter.WriteFile(theModel, mtk.UTF16String(theFilePath))
242
243 @staticmethod
244 def _ExportMTKWEB(theFolderPath: str, theModelToExport: mtk.ModelData_Model, theBaseName: str):
245 aPath = theFolderPath + "/" + theBaseName + ".mtkweb/scenegraph.mtkweb"
246 if not theModelToExport.Save(mtk.UTF16String(aPath), mtk.ModelData_Model.FileFormatType_MTKWEB):
247 print("\nERROR: Failed to export ", aPath, ". Exiting", sep="")
248 return False
249 return True
250
251 @staticmethod
252 def _ExportMTK(theFolderPath: str, theModelToExport: mtk.ModelData_Model, theBaseName: str):
253 aSanitizedBaseName = theBaseName.replace(".", "_")
254 aPath = theFolderPath + "/" + aSanitizedBaseName + "_processed.mtk"
255 if not theModelToExport.Save(mtk.UTF16String(aPath), mtk.ModelData_Model.FileFormatType_MTK):
256 print("\nERROR: Failed to save MTK model ", aPath, ". Exiting", sep="")
257 return False
258 return True
259
260 @staticmethod
261 def _Export(
262 theFolderPath: str,
263 theExportParameters: MTKConverter_ExportParameters,
264 theModel: mtk.ModelData_Model,
265 theReport: MTKConverter_Report,
266 theProcessModel: mtk.ModelData_Model):
267 print("Exporting ", theFolderPath, "...", sep="", end="", flush=True)
268 os.makedirs(theFolderPath, exist_ok=True)
269
270 aModelBaseName = str(theModel.Name())
271 aProcessedBaseName = str(theProcessModel.Name())
272
273 if not MTKConverter_Application._ExportMTKWEB(theFolderPath, theModel, aModelBaseName):
274 return MTKConverter_ReturnCode.ExportError
275
276 aThumbnailPath = theFolderPath + "/thumbnail.png"
277 if (theExportParameters.myIsScreenshotGenerationEnabled and
278 not MTKConverter_Application._CreateOriginModelThumbnail(aThumbnailPath, theModel)):
279 print("\nERROR: Failed to create thumbnail ", aThumbnailPath, ". Exiting", sep="")
280 return MTKConverter_ReturnCode.ExportError
281
282 aProcessDrawing = theProcessModel.Drawing()
283 if (not theProcessModel.IsEmpty()) or aProcessDrawing:
284 if not MTKConverter_Application._ExportMTKWEB(theFolderPath, theProcessModel, aProcessedBaseName):
285 return MTKConverter_ReturnCode.ExportError
286 if (theExportParameters.myIsExportMTKEnabled and
287 not MTKConverter_Application._ExportMTK(theFolderPath, theProcessModel, aProcessedBaseName)):
288 return MTKConverter_ReturnCode.ExportError
289
290 aJsonPath = theFolderPath + "/process_data.json"
291 if not theReport.WriteToJSON(aJsonPath):
292 print("\nERROR: Failed to create JSON file ", aJsonPath, ". Exiting", sep="")
293 return MTKConverter_ReturnCode.ExportError
294
295 return MTKConverter_ReturnCode.Ok
296
297 @staticmethod
298 def _ParseArguments(theArgs, theParameters: MTKConverter_Parameters, theArguments):
299 anArgumentType = MTKConverter_ArgumentType.Neutral
300 i = 0
301 while i < len(theArgs):
302 anArgument = theArgs[i]
303
304 if anArgument == "--no-screenshot":
305 theParameters.myExportParameters.myIsScreenshotGenerationEnabled = False
306 elif anArgument == "--export_mtk":
307 theParameters.myExportParameters.myIsExportMTKEnabled = True
308 elif anArgument == "--sheet_size":
309 if i + 2 >= len(theArgs):
310 print("ERROR: Missing values for --sheet_size. Use --sheet_size <L> <W> with values > 0.")
311 return MTKConverter_ReturnCode.InvalidArgument
312 try:
313 aSheetLength = float(theArgs[i + 1])
314 aSheetWidth = float(theArgs[i + 2])
315 except Exception:
316 print("ERROR: Invalid sheet size. Use --sheet_size <L> <W> with values > 0.")
317 return MTKConverter_ReturnCode.InvalidArgument
318 if aSheetLength <= 0.0 or aSheetWidth <= 0.0:
319 print("ERROR: Invalid sheet size. Use --sheet_size <L> <W> with values > 0.")
320 return MTKConverter_ReturnCode.InvalidArgument
321 theParameters.myNestingParameters.myMaterialParameters.myLength = aSheetLength
322 theParameters.myNestingParameters.myMaterialParameters.myWidth = aSheetWidth
323 i += 2
324 elif anArgument == "--pattern_count":
325 if i + 1 >= len(theArgs):
326 print("ERROR: Missing value for --pattern_count. Use --pattern_count <N> with value > 0.")
327 return MTKConverter_ReturnCode.InvalidArgument
328 try:
329 aPatternRepeatCount = int(theArgs[i + 1])
330 except Exception:
331 print("ERROR: Invalid pattern count. Use --pattern_count <N> with value > 0.")
332 return MTKConverter_ReturnCode.InvalidArgument
333 if aPatternRepeatCount <= 0:
334 print("ERROR: Invalid pattern count. Use --pattern_count <N> with value > 0.")
335 return MTKConverter_ReturnCode.InvalidArgument
336 theParameters.myNestingParameters.myPatternRepeatCount = aPatternRepeatCount
337 i += 1
338 elif anArgument == "--nesting_mode":
339 if i + 1 >= len(theArgs):
340 print("ERROR: Missing value for --nesting_mode. Use --nesting_mode per_sheet|all_sheets.")
341 return MTKConverter_ReturnCode.InvalidArgument
342 aModeArg = theArgs[i + 1]
343 if aModeArg == "per_sheet":
344 theParameters.myNestingParameters.myMode = MTKConverter_NestingParameters.NestingMode.PerSheet
345 elif aModeArg == "all_sheets":
346 theParameters.myNestingParameters.myMode = MTKConverter_NestingParameters.NestingMode.AllSheets
347 else:
348 print("ERROR: Invalid nesting mode \"", aModeArg,
349 "\". Use --nesting_mode per_sheet|all_sheets.", sep="")
350 return MTKConverter_ReturnCode.InvalidArgument
351 i += 1
352 elif anArgument == "-i":
353 anArgumentType = MTKConverter_ArgumentType.Import
354 elif anArgument == "-p":
355 anArgumentType = MTKConverter_ArgumentType.Process
356 elif anArgument == "-e":
357 anArgumentType = MTKConverter_ArgumentType.Export
358 else:
359 if anArgumentType == MTKConverter_ArgumentType.Import:
360 theArguments.append(MTKConverter_Argument(MTKConverter_ArgumentType.Import, anArgument))
361 elif anArgumentType == MTKConverter_ArgumentType.Process:
362 aProcessType = MTKConverter_Application._FindProcessType(anArgument)
363 if aProcessType == MTKConverter_ProcessType.Undefined:
364 print("ERROR: Unknown process \"", anArgument, "\".", sep="")
365 print("Type -h for recognized processes.")
366 return MTKConverter_ReturnCode.InvalidArgument
367 if aProcessType == MTKConverter_ProcessType.Nesting:
368 theParameters.myImportParameters.myReaderParameters.SetReadDrawing(True)
369 theArguments.append(MTKConverter_Argument(MTKConverter_ArgumentType.Process, anArgument))
370 elif anArgumentType == MTKConverter_ArgumentType.Export:
371 theArguments.append(MTKConverter_Argument(MTKConverter_ArgumentType.Export, anArgument))
372 else:
373 print("ERROR!: Invalid argument ", anArgument, ". Exiting", sep="")
374 print("Type -h for help.")
375 return MTKConverter_ReturnCode.InvalidArgument
376 i += 1
377
378 if not theArguments:
379 print("ERROR: No commands specified. Use -i/-p/-e.")
380 return MTKConverter_ReturnCode.InvalidArgument
381
382 return MTKConverter_ReturnCode.Ok
383
384 @staticmethod
385 def _Execute(theArguments, theParameters: MTKConverter_Parameters):
386 aModel = mtk.ModelData_Model()
387 aProcessModel = mtk.ModelData_Model()
388 aReport = MTKConverter_Report()
389 aResultCode = MTKConverter_ReturnCode.Ok
390
391 for anArgument in theArguments:
392 if aResultCode != MTKConverter_ReturnCode.Ok:
393 break
394
395 try:
396 if anArgument.myArgumentType == MTKConverter_ArgumentType.Import:
397 aProcessModel = mtk.ModelData_Model()
398 aResultCode = MTKConverter_Application._Import(
399 anArgument.myValue, aModel, theParameters.myImportParameters)
400 if aResultCode == MTKConverter_ReturnCode.Ok:
401 aModel.AssignUuids()
402 elif anArgument.myArgumentType == MTKConverter_ArgumentType.Process:
403 aResultCode = MTKConverter_Application._Process(
404 anArgument.myValue, aModel, aReport, aProcessModel, theParameters)
405 elif anArgument.myArgumentType == MTKConverter_ArgumentType.Export:
406 aResultCode = MTKConverter_Application._Export(
407 anArgument.myValue,
408 theParameters.myExportParameters,
409 aModel,
410 aReport,
411 aProcessModel)
412 else:
413 aResultCode = MTKConverter_ReturnCode.InvalidArgument
414
415 if aResultCode == MTKConverter_ReturnCode.Ok:
416 print("Done.")
417 except Exception:
418 print("Failed.\nERROR: Unhandled exception caught.")
419 return MTKConverter_ReturnCode.GeneralException
420
421 return aResultCode
422
423 def Run(self, theArgs):
424 if (len(theArgs) == 0 or
425 theArgs[0] == "-?" or
426 theArgs[0] == "/?" or
427 theArgs[0] == "-h" or
428 theArgs[0] == "--help"):
429 self.PrintUsage()
430 return MTKConverter_ReturnCode.Ok
431
432 if len(theArgs) < 6:
433 print("Invalid number of arguments. Please use \"-h\" or \"--help\" for usage information.")
434 return MTKConverter_ReturnCode.InvalidArgumentsNumber
435
436 aParameters = MTKConverter_Parameters()
437 anArguments = []
438 aParseRes = MTKConverter_Application._ParseArguments(theArgs, aParameters, anArguments)
439 if aParseRes != MTKConverter_ReturnCode.Ok:
440 return aParseRes
441
442 return MTKConverter_Application._Execute(anArguments, aParameters)
443
444 def PrintUsage(self):
445 print("Usage:")
446 print("MTKConverter -i <import_file> -p <process> ... -e <export_target> [options]")
447
448 print("\nArguments:")
449 print(" <import_file> - import file name")
450 print(" <process> - manufacturing process or algorithm name")
451 print(" <export_target> - export folder name")
452
453 print("\nExport Options:")
454 print(" --no-screenshot - disable screenshot generation (optional)")
455 print(" --export_mtk - additionally save process model as *.mtk in <export_target>")
456
457 print("\nExample:")
458 print("MTKConverter -i C:\\models\\test.step -p machining_milling -e C:\\models\\out")
459 print("MTKConverter -i C:\\models\\test.step -p nesting -e C:\\models\\out --export_mtk")
460 print("MTKConverter -i C:\\models\\test.step -p sheet_metal -e C:\\models\\out "
461 "-p nesting --nesting_mode all_sheets --sheet_size 500 500 --pattern_count 4 "
462 "-e C:\\models\\out --export_mtk")
463
464 print("\nRecognized processes:")
465 print(" wall_thickness :\t Wall Thickness analysis")
466 print(" machining_milling:\t CNC Machining Milling feature recognition and DFM analysis")
467 print(" machining_turning:\t CNC Machining Lathe+Milling feature recognition and DFM analysis")
468 print(" molding :\t Molding feature recognition and DFM analysis")
469 print(" sheet_metal :\t Sheet Metal feature recognition, unfolding and DFM analysis")
470 print(" nesting :\t Nesting using source drawing or sheet metal unfolding drawing")
471 print(" parameters :\t --sheet_size <L> <W> (default: 500 500)")
472 print(" :\t --pattern_count <N> (default: 4)")
473 print(" :\t --nesting_mode per_sheet|all_sheets (default: per_sheet)")
MTKConverter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import os
29import sys
30
31from pathlib import Path
32from typing import Sequence
33
34import manufacturingtoolkit.MTKCore as mtk
35
36sys.path.append(os.path.abspath(os.path.dirname(Path(__file__).resolve()) + "/../"))
37sys.path.append(os.path.abspath(os.path.dirname(Path(__file__).resolve()) + "/../helpers/"))
38
39import mtk_license as license
40import MTKConverter_Application as app
41
42
43def main(theArgs: Sequence[str]) -> int:
44 aKey = license.Value()
45 if not mtk.LicenseManager.Activate(aKey):
46 print("Failed to activate Manufacturing Toolkit license.")
47 return 1
48
49 anApp = app.MTKConverter_Application()
50 aRes = anApp.Run(list(theArgs))
51 return aRes.value
52
53if __name__ == "__main__":
54 if (len(sys.argv) == 1 or
55 sys.argv[1] == "-?" or sys.argv[1] == "/?" or
56 sys.argv[1] == "-h" or sys.argv[1] == "--help"):
57 app.MTKConverter_Application().PrintUsage()
58 sys.exit(0)
59
60 if len(sys.argv) < 6:
61 print("Invalid number of arguments. Please use \"-h\" or \"--help\" for usage information.")
62 sys.exit(app.MTKConverter_ReturnCode.InvalidArgumentsNumber.value)
63
64 sys.exit(main(sys.argv[1:]))