Cura/plugins/CuraSolidWorksPlugin/SolidWorksReader.py
Lipu Fei 1c39c90494 Add SolidWorks plugin
CURA-3823
2017-07-27 12:36:34 +02:00

231 lines
10 KiB
Python

# Copyright (c) 2017 Thomas Karl Pietrowski
# TODOs:
# * Adding selection to separately import parts from an assembly
# Buildings
import math
# Uranium/Cura
from UM.i18n import i18nCatalog
from UM.Message import Message
from UM.Logger import Logger
from UM.Math.Vector import Vector
from UM.Math.Quaternion import Quaternion
from UM.Mesh.MeshReader import MeshReader
# Our plugin
from .CommonComReader import CommonCOMReader
from .SolidWorksConstants import SolidWorksEnums
from .SolidWorksReaderUI import SolidWorksReaderUI
i18n_catalog = i18nCatalog("CuraSolidWorksIntegrationPlugin")
class SolidWorksReader(CommonCOMReader):
def __init__(self):
super().__init__("SldWorks.Application", "SolidWorks")
self._extension_part = ".SLDPRT"
self._extension_assembly = ".SLDASM"
self._supported_extensions = [self._extension_part.lower(),
self._extension_assembly.lower(),
]
self._convert_assembly_into_once = True # False is not implemented now!
self._file_formats_first_choice = []
self._revision = None
self._revision_major = None
self._revision_minor = None
self._revision_patch = None
self._ui = SolidWorksReaderUI()
self._selected_quality = None
self._quality_value_map = {"coarse": SolidWorksEnums.swSTLQuality_e.swSTLQuality_Coarse,
"find": SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine}
self.root_component = None
def preRead(self, file_name, *args, **kwargs):
self._ui.showConfigUI()
self._ui.waitForUIToClose()
if self._ui.getCancelled():
return MeshReader.PreReadResult.cancelled
# get quality
self._selected_quality = self._ui.quality
if self._selected_quality is None:
self._selected_quality = "fine"
self._selected_quality = self._selected_quality.lower()
# give actual value for quality
self._selected_quality = self._quality_value_map.get(self._selected_quality,
SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine)
return MeshReader.PreReadResult.accepted
def setAppVisible(self, state, **options):
options["app_instance"].Visible = state
def getAppVisible(self, state, **options):
return options["app_instance"].Visible
def startApp(self, visible=False):
app_instance = super().startApp(visible = visible)
# Getting revision after starting
revision_number = app_instance.RevisionNumber()
Logger.log("d", "SolidWorks RevisionNumber: %s", revision_number)
self._revision = [int(x) for x in revision_number.split(".")]
self._revision_major = self._revision[0]
self._revision_minor = self._revision[1]
self._revision_patch = self._revision[2]
# Re-generate a list of preferred file formats
self.updateFormatsFirstChoise()
return app_instance
def updateFormatsFirstChoise(self):
self._file_formats_first_choice = ["stl"]
if self._revision_major >= 25 and "3mf" in self._reader_for_file_format.keys():
self._file_formats_first_choice.insert(0, "3mf")
return self._file_formats_first_choice
def checkApp(self, **options):
functions_to_be_checked = ("OpenDoc", "CloseDoc")
for func in functions_to_be_checked:
try:
getattr(options["app_instance"], func)
except:
Logger.logException("e", "Error which occurred when checking for a valid app instance")
return False
return True
def closeApp(self, **options):
if "app_instance" in options.keys():
del options["app_instance"]
def walkComponentsInAssembly(self, root = None):
if root is None:
root = self.root_component
children = root.GetChildren
if children:
children = [self.walkComponentsInAssembly(child) for child in children]
return root, children
else:
return root
"""
models = options["sw_model"].GetComponents(True)
for model in models:
#Logger.log("d", model.GetModelDoc2())
#Logger.log("d", repr(model.GetTitle))
Logger.log("d", repr(model.GetPathName))
#Logger.log("d", repr(model.GetType))
if model.GetPathName in ComponentsCount.keys():
ComponentsCount[model.GetPathName] = ComponentsCount[model.GetPathName] + 1
else:
ComponentsCount[model.GetPathName] = 1
for key in ComponentsCount.keys():
Logger.log("d", "Found %s %s-times in the assembly!" %(key, ComponentsCount[key]))
"""
def openForeignFile(self, **options):
if options["foreignFormat"].upper() == self._extension_part:
filetype = SolidWorksEnums.FileTypes.SWpart
elif options["foreignFormat"].upper() == self._extension_assembly:
filetype = SolidWorksEnums.FileTypes.SWassembly
else:
raise NotImplementedError("Unknown extension. Something went terribly wrong!")
#options["sw_model"] = options["app_instance"].OpenDoc(options["foreignFile"], filetype)
documentSpecification = options["app_instance"].GetOpenDocSpec(options["foreignFile"])
## NOTE: SPEC: FileName
#documentSpecification.FileName
## NOTE: SPEC: DocumentType
## TODO: Really needed here?!
documentSpecification.DocumentType = filetype
## TODO: Test the impact of LightWeight = True
#documentSpecification.LightWeight = True
documentSpecification.Silent = True
## TODO: Double check, whether file was really opened read-only..
documentSpecification.ReadOnly = True
options["sw_model"] = options["app_instance"].OpenDoc7(documentSpecification._comobj)
if documentSpecification.Warning:
Logger.log("w", "Warnings happened while opening your SolidWorks file!")
if documentSpecification.Error:
Logger.log("e", "Errors happened while opening your SolidWorks file!")
error_message = Message(i18n_catalog.i18nc("@info:status", "Errors appeared while opening your SolidWorks file! \
Please check, whether it is possible to open your file in SolidWorks itself without any problems as well!" % (self._app_friendly_name)))
error_message.show()
# Might be useful in the future, but no need for this ATM
#self.configuration = self.model.getActiveConfiguration
#self.root_component = self.configuration.GetRootComponent
## EXPERIMENTAL: Browse single parts in assembly
#if filetype == SolidWorksEnums.FileTypes.SWassembly:
# Logger.log("d", 'walkComponentsInAssembly: ' + repr(self.walkComponentsInAssembly()))
return options
def exportFileAs(self, **options):
if options["tempType"] == "stl":
if options["foreignFormat"].upper() == self._extension_assembly:
# Backing up current setting of swSTLComponentsIntoOneFile
swSTLComponentsIntoOneFileBackup = options["app_instance"].GetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile)
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile, self._convert_assembly_into_once)
swExportSTLQualityBackup = options["app_instance"].GetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality)
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality, SolidWorksEnums.swSTLQuality_e.swSTLQuality_Fine)
# Changing the default unit for STLs to mm, which is expected by Cura
swExportStlUnitsBackup = options["app_instance"].GetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits)
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits, SolidWorksEnums.swLengthUnit_e.swMM)
# Changing the output type temporary to binary
swSTLBinaryFormatBackup = options["app_instance"].GetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat)
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat, True)
options["sw_model"].SaveAs(options["tempFile"])
if options["tempType"] == "stl":
# Restoring swSTLBinaryFormat
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.swUserPreferenceToggle_e.swSTLBinaryFormat, swSTLBinaryFormatBackup)
# Restoring swExportStlUnits
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportStlUnits, swExportStlUnitsBackup)
# Restoring swSTLQuality_Fine
options["app_instance"].SetUserPreferenceIntegerValue(SolidWorksEnums.swUserPreferenceIntegerValue_e.swExportSTLQuality, swExportSTLQualityBackup)
if options["foreignFormat"].upper() == self._extension_assembly:
# Restoring swSTLComponentsIntoOneFile
options["app_instance"].SetUserPreferenceToggle(SolidWorksEnums.UserPreferences.swSTLComponentsIntoOneFile, swSTLComponentsIntoOneFileBackup)
def closeForeignFile(self, **options):
options["app_instance"].CloseDoc(options["foreignFile"])
def areReadersAvailable(self):
return bool(self._reader_for_file_format)
def nodePostProcessing(self, node):
if self._revision_major == 24: # Known problem under SolidWorks 2016: Exported models are rotated by -90 degrees. This rotates it back!
rotation = Quaternion.fromAngleAxis(math.radians(90), Vector.Unit_X)
node.rotate(rotation)
return node
## Decide if we need to use ascii or binary in order to read file