Hide menu
Loading...
Searching...
No Matches
projector/poly_projector/poly_projector.py
Refer to the Projector Example
1# $Id$
2
3# Copyright (C) 2008-2014, Roman Lygin. All rights reserved.
4# Copyright (C) 2014-2026, 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
30import os
31import sys
32from pathlib import Path
33
34import mtk.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 LicenseHelper
40
41import mtk_license as license
42
43def main(theSource: str, theOutFolder: str) -> int:
44 aKey = license.Value()
45
46 if not LicenseHelper.SetupRuntimeKey() :
47 return 1
48
49 try:
50 mtk.LicenseManager.Activate(aKey)
51 except mtk.LicenseError as anException:
52 mtk.LicenseManager.Deactivate()
53 print("Failed to activate Manufacturing Toolkit license: " + anException.what())
54 return 1
55
56 aModel = mtk.ModelData_Model()
57 aReader = mtk.ModelData_ModelReader()
58
59 # Reading the file
60 if not aReader.Read(mtk.UTF16String(theSource), aModel):
61 mtk.LicenseManager.Deactivate()
62 print("Failed to read the file " + theSource)
63 return 1
64
65 print("Model: " + str(aModel.Name()) + "\n")
66
67 aProjectionDataCollection = [
68 (mtk.UTF16String("X"), mtk.Geom_Direction.XDir()),
69 (mtk.UTF16String("Y"), mtk.Geom_Direction.YDir()),
70 (mtk.UTF16String("Z"), mtk.Geom_Direction.ZDir()),
71 ]
72
73 for aProjectionName, aProjectionDirection in aProjectionDataCollection:
74 anOutFilePath = mtk.UTF16String(theOutFolder + "projection_" + str(aProjectionName) + ".stl")
75
76 if ComputeProjection(aModel, aProjectionDirection, aProjectionName, anOutFilePath):
77 print("The output projection is written: " + str(anOutFilePath) + "\n")
78 else:
79 print("Failed to save the result: " + str(anOutFilePath) + "\n")
80
81 mtk.LicenseManager.Deactivate()
82
83 return 0
84
85if __name__ == "__main__":
86 if len(sys.argv) != 3:
87 print("Usage: " + sys.argv[0] + " <input_file> <output_folder>, where:")
88 print(" <input_file> is a name of the file to be read")
89 print(" <output_folder> is a folder to save projections to (must end with '/' or '\\')")
90 sys.exit(1)
91
92 aSource = os.path.abspath(sys.argv[1])
93 aOutFolder = os.path.abspath(sys.argv[2])
94
95 sys.exit(main(aSource, aOutFolder))
96
97def PrintProjectionInfo(thePart: mtk.ModelData_Part,
98 theDirectionName: mtk.UTF16String,
99 theProjection: mtk.Projector_Projection) -> None:
100 print(f"Part [{thePart.Name()}], projection {theDirectionName}:")
101 if theProjection:
102 print(f" area = {theProjection.Area()} mm")
103 print(f" outer perimeter = {theProjection.OuterPerimeter()} mm")
104 else:
105 print(" undefined")
106 print("")
107
108class ProjectionComputer(mtk.ModelData_ModelElementVoidVisitor):
109 def __init__(self, theDirection: mtk.Geom_Direction, theDirectionName: mtk.UTF16String):
110 super().__init__()
111 self.myDirection = theDirection
112 self.myDirectionName = theDirectionName
113 self.myProjector = mtk.Projector_PolyProjector()
114 self.myPartProjections = []
115
116 def SaveProjection(self, theFileName: mtk.UTF16String) -> bool:
117 if len(self.myPartProjections) == 0:
118 return False
119
120 aPart = mtk.ModelData_Part(mtk.UTF16String("Projections"))
121
122 for aProjection in self.myPartProjections:
123 aMeshBody = mtk.ModelData_MeshBody(aProjection.Mesh())
124 aPart.AddBody(aMeshBody)
125
126 anOutModel = mtk.ModelData_Model(mtk.UTF16String("Projector"))
127 anOutModel.AddRoot(aPart)
128
129 aWriter = mtk.ModelData_ModelWriter()
130 return aWriter.Write(anOutModel, theFileName)
131
132 def VisitPart(self, thePart: mtk.ModelData_Part):
133 aProjection = self.myProjector.Perform(thePart, self.myDirection)
134 PrintProjectionInfo(thePart, self.myDirectionName, aProjection)
135 if aProjection:
136 self.myPartProjections.append(aProjection)
137
138def ComputeProjection(theModel: mtk.ModelData_Model,
139 theDirection: mtk.Geom_Direction,
140 theDirectionName: mtk.UTF16String,
141 theOutFileName: mtk.UTF16String) -> bool:
142 aComputer = ProjectionComputer(theDirection, theDirectionName)
143 theModel.Accept(aComputer)
144 return aComputer.SaveProjection(theOutFileName)