AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2013 Juergen Riegel <FreeCAD@juergen-riegel.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__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"
# the reader returns a dictionary in any case even if the file has problems
# an empty dict is returned in such case
card_name_file = os.path.splitext(os.path.basename(filename))[0]
f = open(filename, encoding="utf8")
try:
content = f.readlines()
except Exception:
# https://forum.freecad.org/viewtopic.php?f=18&t=56912#p489721
# older FreeCAD do not write utf-8 for special character on windows
# I have seen "ISO-8859-15" or "windows-1252"
# explicit utf-8 writing, https://github.com/FreeCAD/FreeCAD/commit/9a564dd906f
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 # CardName is the MatCard file name
section = ''
for ln, line in enumerate(content):
# line numbers are used for CardName and AuthorAndLicense
# the use of line number is not smart for a data model
# a wrong user edit could break the file
# comment
if line.startswith('#'):
# a '#' is assumed to be a comment which is ignored
continue
# CardName
if line.startswith(';') and ln == 0:
pass
# AuthorAndLicense
elif line.startswith(';') and ln == 1:
v = line.split(";")[1].strip() # Line 2
if hasattr(v, "decode"):
v = v.decode('utf-8')
d["General"]["AuthorAndLicense"] = v # Move the field to the general group
# rest
else:
# ; is a Comment
# [ is a Section
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 ";":
# split once on first occurrence
# a link could contain a '=' and thus would be split
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"
# Add UUIDs
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": # Handle the name change
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):
# Check which model we need
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')
# default mechanical model
return ""
def yamFluid(card):
# Split out density
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):
# Check which model we need
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')
# default rendering model
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)