| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | __title__ = "FreeCAD material card importer" |
| | __author__ = "Juergen Riegel" |
| | __url__ = "https://www.freecad.org" |
| |
|
| |
|
| | import os |
| | import glob |
| | import uuid |
| | from pathlib import Path |
| | import xml.etree.ElementTree as ET |
| |
|
| | def decode(name): |
| | "decodes encoded strings" |
| | try: |
| | decodedName = (name.decode("utf8")) |
| | except UnicodeDecodeError: |
| | try: |
| | decodedName = (name.decode("latin1")) |
| | except UnicodeDecodeError: |
| | print("Error: Couldn't determine character encoding") |
| | decodedName = name |
| | return decodedName |
| |
|
| | def read(filename): |
| | "reads a FCMat file and returns a dictionary from it" |
| |
|
| | |
| | |
| |
|
| | card_name_file = os.path.splitext(os.path.basename(filename))[0] |
| | f = open(filename, encoding="utf8") |
| | try: |
| | content = f.readlines() |
| | except Exception: |
| | |
| | |
| | |
| | |
| | print("Error on card loading. File might not utf-8.") |
| | error_message = "Error on loading. Material file '{}' might not utf-8.".format(filename) |
| | print("{}\n".format(error_message)) |
| | return {} |
| | d = {} |
| | d["Meta"] = {} |
| | d["General"] = {} |
| | d["Mechanical"] = {} |
| | d["Fluidic"] = {} |
| | d["Thermal"] = {} |
| | d["Electromagnetic"] = {} |
| | d["Architectural"] = {} |
| | d["Rendering"] = {} |
| | d["VectorRendering"] = {} |
| | d["Cost"] = {} |
| | d["UserDefined"] = {} |
| | d["Meta"]["CardName"] = card_name_file |
| | section = '' |
| | for ln, line in enumerate(content): |
| | |
| | |
| | |
| |
|
| | |
| | if line.startswith('#'): |
| | |
| | continue |
| | |
| | if line.startswith(';') and ln == 0: |
| | pass |
| |
|
| | |
| | elif line.startswith(';') and ln == 1: |
| | v = line.split(";")[1].strip() |
| | if hasattr(v, "decode"): |
| | v = v.decode('utf-8') |
| | d["General"]["AuthorAndLicense"] = v |
| |
|
| | |
| | else: |
| | |
| | |
| | if line[0] == '[': |
| | line = line[1:] |
| | k = line.split("]", 1) |
| | if len(k) >= 2: |
| | v = k[0].strip() |
| | if hasattr(v, "decode"): |
| | v = v.decode('utf-8') |
| | section = v |
| | elif line[0] not in ";": |
| | |
| | |
| | k = line.split("=", 1) |
| | if len(k) == 2: |
| | v = k[1].strip() |
| | if hasattr(v, "decode"): |
| | v = v.decode('utf-8') |
| | d[section][k[0].strip()] = v |
| | return d |
| |
|
| | def yamGeneral(card): |
| | father = "" |
| | materialStandard = "" |
| | yamModels = "" |
| | yam = "# File created by ConvertFCMat.py\n" |
| | yam += "General:\n" |
| |
|
| | |
| | yam += ' UUID: "{0}"\n'.format(uuid.uuid4()) |
| | for param in card: |
| | if param in ["Name", "AuthorAndLicense", "Description", "ReferenceSource", "SourceURL"]: |
| | yam += ' {0}: "{1}"\n'.format(param, card[param]) |
| | elif param in ["Father"]: |
| | father += ' {0}: "{1}"\n'.format(param, card[param]) |
| | elif param in ["KindOfMaterial", "MaterialNumber", "Norm", "StandardCode"]: |
| | if param == "Norm": |
| | materialStandard += ' {0}: "{1}"\n'.format("StandardCode", card[param]) |
| | else: |
| | materialStandard += ' {0}: "{1}"\n'.format(param, card[param]) |
| |
|
| | if len(father) > 0: |
| | yamModels += " {0}:\n".format('Father') |
| | yamModels += " UUID: '{0}'\n".format('9cdda8b6-b606-4778-8f13-3934d8668e67') |
| | yamModels += father |
| | if len(materialStandard) > 0: |
| | yamModels += " {0}:\n".format('MaterialStandard') |
| | yamModels += " UUID: '{0}'\n".format('1e2c0088-904a-4537-925f-64064c07d700') |
| | yamModels += materialStandard |
| |
|
| | return yam, yamModels |
| |
|
| | def yamSection(card, header, uuid): |
| | if len(card) > 0: |
| | yam = " {0}:\n".format(header) |
| | yam += " UUID: '{0}'\n".format(uuid) |
| | for param in card: |
| | yam += ' {0}: "{1}"\n'.format(param, card[param]) |
| | else: |
| | yam = "" |
| |
|
| | return yam |
| |
|
| | def yamMechanical(card): |
| | |
| | useDensity = False |
| | useIso = False |
| | useLinearElastic = False |
| | for param in card: |
| | if param in ["Density"]: |
| | useDensity = True |
| | elif param in ["BulkModulus", "PoissonRatio", "ShearModulus", "YoungsModulus"]: |
| | useIso = True |
| | elif param in ["AngleOfFriction", "CompressiveStrength", "FractureToughness", |
| | "UltimateStrain", "UltimateTensileStrength", "YieldStrength", "Stiffness", "Hardness"]: |
| | useLinearElastic = True |
| |
|
| | yam = "" |
| | if useLinearElastic: |
| | return yamSection(card, 'LinearElastic', '7b561d1d-fb9b-44f6-9da9-56a4f74d7536') |
| | if useIso: |
| | yam = yamSection(card, 'IsotropicLinearElastic', 'f6f9e48c-b116-4e82-ad7f-3659a9219c50') |
| | if useDensity: |
| | return yam + yamSection(card, 'Density', '454661e5-265b-4320-8e6f-fcf6223ac3af') |
| |
|
| | |
| | return "" |
| |
|
| | def yamFluid(card): |
| | |
| | for param in card: |
| | if param not in ["Density"]: |
| | return yamSection(card, 'Fluid', '1ae66d8c-1ba1-4211-ad12-b9917573b202') |
| |
|
| | return yamSection(card, 'Density', '454661e5-265b-4320-8e6f-fcf6223ac3af') |
| |
|
| | def yamThermal(card): |
| | return yamSection(card, 'Thermal', '9959d007-a970-4ea7-bae4-3eb1b8b883c7') |
| |
|
| | def yamElectromagnetic(card): |
| | return yamSection(card, 'Electromagnetic', 'b2eb5f48-74b3-4193-9fbb-948674f427f3') |
| |
|
| | def yamArchitectural(card): |
| | return yamSection(card, 'Architectural', '32439c3b-262f-4b7b-99a8-f7f44e5894c8') |
| |
|
| | def yamCost(card): |
| | return yamSection(card, 'Costs', '881df808-8726-4c2e-be38-688bb6cce466') |
| |
|
| | def yamRendering(card): |
| | |
| | useTexture = False |
| | useAdvanced = False |
| | for param in card: |
| | if param in ["TexturePath", "TextureScaling"]: |
| | useTexture = True |
| | elif param in ["FragmentShader", "VertexShader"]: |
| | useAdvanced = True |
| |
|
| | if useAdvanced: |
| | return yamSection(card, 'AdvancedRendering', 'c880f092-cdae-43d6-a24b-55e884aacbbf') |
| | if useTexture: |
| | return yamSection(card, 'TextureRendering', 'bbdcc65b-67ca-489c-bd5c-a36e33d1c160') |
| |
|
| | |
| | return yamSection(card, 'BasicRendering', 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e') |
| |
|
| | def yamVectorRendering(card): |
| | return yamSection(card, 'VectorRendering', 'fdf5a80e-de50-4157-b2e5-b6e5f88b680e') |
| |
|
| | def saveYaml(card, output): |
| | yam, yamModels = yamGeneral(card["General"]) |
| | if len(card["Mechanical"]) > 0 or \ |
| | len(card["Fluidic"]) > 0 or \ |
| | len(card["Thermal"]) > 0 or \ |
| | len(card["Electromagnetic"]) > 0 or \ |
| | len(card["Architectural"]) > 0 or \ |
| | len(card["Cost"]) > 0 or \ |
| | len(yamModels) > 0: |
| | yam += "Models:\n" |
| | yam += yamModels |
| | if "Mechanical" in card: |
| | yam += yamMechanical(card["Mechanical"]) |
| | if "Fluidic" in card: |
| | yam += yamFluid(card["Fluidic"]) |
| | if "Thermal" in card: |
| | yam += yamThermal(card["Thermal"]) |
| | if "Electromagnetic" in card: |
| | yam += yamElectromagnetic(card["Electromagnetic"]) |
| | if "Architectural" in card: |
| | yam += yamArchitectural(card["Architectural"]) |
| | if "Cost" in card: |
| | yam += yamCost(card["Cost"]) |
| | if len(card["Rendering"]) > 0 or len(card["VectorRendering"]) > 0: |
| | yam += "AppearanceModels:\n" |
| | if "Rendering" in card: |
| | yam += yamRendering(card["Rendering"]) |
| | if "VectorRendering" in card: |
| | yam += yamVectorRendering(card["VectorRendering"]) |
| |
|
| | file = open(output, "w", encoding="utf-8") |
| | file.write(yam) |
| | file.close() |
| |
|
| | def convert(infolder, outfolder): |
| | a_path = infolder + '/**/*.FCMat' |
| | dir_path_list = glob.glob(a_path, recursive=True) |
| |
|
| | for a_path in dir_path_list: |
| | p = Path(a_path) |
| | relative = p.relative_to(infolder) |
| | out = Path(outfolder) / relative |
| | print("('{0}', '{1}') -> {2}".format(infolder, relative, out)) |
| |
|
| | try: |
| | card = read(p) |
| | except Exception: |
| | print("Error converting card '{0}'. Skipped.") |
| | continue |
| |
|
| | out.parent.mkdir(parents=True, exist_ok=True) |
| | saveYaml(card, out) |
| |
|
| | import argparse |
| | parser = argparse.ArgumentParser() |
| | parser.add_argument("infolder", help="Input folder containing older material cards") |
| | parser.add_argument("outfolder", help="Output folder to place the converted material cards") |
| | args = parser.parse_args() |
| |
|
| | print("Input folder '{0}'".format(args.infolder)) |
| | print("Output folder '{0}'".format(args.outfolder)) |
| |
|
| | convert(args.infolder, args.outfolder) |