From 4786dc78a3f2177be2a77bc2b965aa5cc148d78d Mon Sep 17 00:00:00 2001 From: Jesusbill Date: Tue, 7 Apr 2020 16:10:42 +0200 Subject: [PATCH] create ifc2ca dedicated folder and populate with existing scripts --- src/ifc2ca/README.md | 53 ++ src/{ifcblenderexport => ifc2ca}/ifc2ca.py | 0 src/ifc2ca/scriptCodeAster.py | 566 +++++++++++++++++++++ src/ifc2ca/scriptSalome.py | 334 ++++++++++++ 4 files changed, 953 insertions(+) create mode 100644 src/ifc2ca/README.md rename src/{ifcblenderexport => ifc2ca}/ifc2ca.py (100%) create mode 100644 src/ifc2ca/scriptCodeAster.py create mode 100644 src/ifc2ca/scriptSalome.py diff --git a/src/ifc2ca/README.md b/src/ifc2ca/README.md new file mode 100644 index 0000000000..58cf6ffa28 --- /dev/null +++ b/src/ifc2ca/README.md @@ -0,0 +1,53 @@ +# ifc2ca +Files and scripts for the use of [`Code_Aster`](https://code-aster.org) in IFC-driven FEM analyses + +### File Organisation +#### Scripts: +- [`ifc2ca.py`](ifc2ca.py): a python script to extract and create a `json` file from an `ifc` file +- [`scriptSalome.py`](scriptSalome.py): a python script to run in the [`Salome-Meca`](https://www.code-aster.org/spip.php?article303) environment. Creates the geometry and the mesh of the structure +- [`scriptCodeAster.py`](scriptCodeAster.py): a python script to create the input file (`.comm`) for Code_Aster + +#### Examples + +All examples are contained in a separate repository within the IfcOpenShell organization (Work In Progress). + +- `cantilever_01` (model created by Dion Moult) +- `beam_01` (model created by Tandeep Singh) +- `portal_01` (model created by buildingSmart) +- `building-frame_01` (model created by Tandeep Singh) +- `building_01`] (model created by Tandeep Singh) + +All example folders contain the following files: + +__Input:__ +- `{example_name}.ifc`: ifc file of the example +- `{example_name}.json`: json data file of the example +- `bldMesh.med`: mesh file exported from Salome_Meca after executing `scriptSalome` +- `CA_input_00.comm`: command file generated from `scriptCodeAster` + +__Output:__ +- `result.mess`: message log file of the interpreted commands in Code_Aster +- `result.rmed`: result file on the mesh of the structure to visualize in Salome_Meca + +--- + +### Current Status +_As of 22/03/20:_ +- Added beam and building examples +- Added support for I sections and calculation of section properties if not provided (assuming fillet radius is zero) +- Added support for surface members (shells) +- Refactored the `ifc2ca.py` script +- Added support for rigid links +- Added advanced meshing script to correctly simulate connections and independent meshing of structural elements (no common nodes) + +_As of 26/02/20:_ +- Added portal example +- Changed `section` to `profile` and added I profile +- Modified material and profile schema with mechanical and common properties +- Added geometry identification for point connection from representation +- Added connections along with supports based on the number of elements a connection is applied to +- Applied conditions with elastic stiffness values is still not implemented. Only True/False values are accepted. + +_As of 16/01/20:_ +- Only line geometries for structural elements and point geometries for supports are considered +- The structure is analysed for gravity loads with a single linear static analysis diff --git a/src/ifcblenderexport/ifc2ca.py b/src/ifc2ca/ifc2ca.py similarity index 100% rename from src/ifcblenderexport/ifc2ca.py rename to src/ifc2ca/ifc2ca.py diff --git a/src/ifc2ca/scriptCodeAster.py b/src/ifc2ca/scriptCodeAster.py new file mode 100644 index 0000000000..373224f4b5 --- /dev/null +++ b/src/ifc2ca/scriptCodeAster.py @@ -0,0 +1,566 @@ +import json +import codecs + +def getGroupName(name): + info = name.split('|') + sortName = ''.join(c for c in info[0] if c.isupper()) + return str(sortName + '_' + info[1]) + +def createCommFile(FILENAME, FILENAMEASTER): + + AccelOfGravity = 9.806 # m/sec^2 + + # Read data from input file + with open(FILENAME) as dataFile: + data = json.load(dataFile) + + elements = data['elements'] + connections = data['connections'] + + edgeGroupNames = tuple([getGroupName(str(el['ifcName'])) for el in elements if el['geometryType'] == 'line']) + faceGroupNames = tuple([getGroupName(str(el['ifcName'])) for el in elements if el['geometryType'] == 'surface']) + + unifiedConnection = False + rigidLinkGroupNames = [] + for conn in connections: + conn['relatedGroupNames'] = tuple([getGroupName(str(rel['relatingElement'])) + '_0D_to_' + getGroupName(str(conn['ifcName'])) for rel in conn['relatedElements']]) + if not conn['appliedCondition'] and len(conn['relatedGroupNames']) == 1: + conn['appliedCondition'] = { + 'dx': True, + 'dy': True, + 'dz': True + } + if len(conn['relatedGroupNames']) > 1: + unifiedConnection = True + rigidLinkGroupNames.extend([getGroupName(str(rel['relatingElement'])) + '_1D_to_' + getGroupName(str(conn['ifcName'])) for rel in conn['relatedElements'] if rel['eccentricity']]) + rigidLinkGroupNames = tuple(rigidLinkGroupNames) + + # Define file to write command file for code_aster + f = open(FILENAMEASTER, 'w') + + f.write('# Command file generated for ifcOpenShell/BlenderBim\n') + f.write('# Aether Engineering - www.aethereng.com\n') + f.write('\n') + + f.write('# Linear Static Analysis With Self-Weight\n') + + f.write( +''' +# STEP: INITIALIZE STUDY +DEBUT( + PAR_LOT = 'NON' +) +''' + ) + + f.write( +''' +# STEP: READ MED FILE +mesh = LIRE_MAILLAGE( + FORMAT = 'MED' +) +''' + ) + + f.write( +''' +# STEP: DEFINE MODEL +model = AFFE_MODELE( + MAILLAGE = mesh, + AFFE = ( + _F( + TOUT = 'OUI', + PHENOMENE = 'MECANIQUE', + MODELISATION = '3D' + ),''' + ) + + if faceGroupNames: + template = \ + ''' + _F( + GROUP_MA = {group_names}, + PHENOMENE = 'MECANIQUE', + MODELISATION = 'DKT' + ),''' + + context = { + 'group_names': faceGroupNames + } + + f.write(template.format(**context)) + + if edgeGroupNames: + template = \ + ''' + _F( + GROUP_MA = {group_names}, + PHENOMENE = 'MECANIQUE', + MODELISATION = 'POU_D_E' + ),''' + + context = { + 'group_names': edgeGroupNames + } + + f.write(template.format(**context)) + + if rigidLinkGroupNames: + template = \ + ''' + _F( + GROUP_MA = {group_names}, + PHENOMENE = 'MECANIQUE', + MODELISATION = 'POU_D_E' + ),''' + + context = { + 'group_names': rigidLinkGroupNames + } + + f.write(template.format(**context)) + + f.write( +''' + ) +)\n +''' + ) + + + f.write('# STEP: DEFINE MATERIALS') + + for i,el in enumerate(elements): + template = \ +''' +{matNameID} = DEFI_MATERIAU( + ELAS = _F( + E = {youngModulus}, + NU = {poissonRatio}, + RHO = {massDensity} + ) +) +''' + if 'poissonRatio' in el['material']['mechProps']: + poissonRatio = el['material']['mechProps']['poissonRatio'] + else: + if 'shearModulus' in el['material']['mechProps']: + poissonRatio = (el['material']['mechProps']['youngModulus'] / 2.0 / el['material']['mechProps']['shearModulus']) - 1 + else: + poissonRation = 0 + + context = { + 'matNameID': 'matF'+ '_%s' % i, + 'youngModulus': float(el['material']['mechProps']['youngModulus']), + 'poissonRatio': float(poissonRatio), + 'massDensity': float(el['material']['commonProps']['massDensity']) + } + + f.write(template.format(**context)) + + + f.write( +''' +material = AFFE_MATERIAU( + MAILLAGE = mesh, + AFFE = (''' + ) + + for i,el in enumerate(elements): + template = \ + ''' + _F( + GROUP_MA = '{group_name}', + MATER = {matNameID}, + ),''' + + context = { + 'group_name': getGroupName(str(el['ifcName'])), + 'matNameID': 'matF'+ '_%s' % i + } + + f.write(template.format(**context)) + + if rigidLinkGroupNames: + template = \ + ''' + _F( + GROUP_MA = {group_names}, + MATER = {matNameID}, + ),''' + + context = { + 'group_names': rigidLinkGroupNames, + 'matNameID': 'matF_0' + } + + f.write(template.format(**context)) + + f.write( +''' + ) +) +''' + ) + + + f.write( +''' +# STEP: DEFINE ELEMENTS +element = AFFE_CARA_ELEM( + MODELE = model, + POUTRE = (''' + ) + + for el in [el for el in elements if el['geometryType'] == 'line']: + if el['profile']['profileShape'] == 'rectangular': + template = \ + ''' + _F( + GROUP_MA = '{group_name}', + SECTION = 'RECTANGLE', + CARA = ('HY', 'HZ'), + VALE = {profileDimensions} + ),''' + + context = { + 'group_name': getGroupName(str(el['ifcName'])), + 'profileDimensions': (el['profile']['xDim'], el['profile']['yDim']) + } + + f.write(template.format(**context)) + + elif el['profile']['profileShape'] == 'iSymmetrical': + template = \ + ''' + _F( + GROUP_MA = '{group_name}', + SECTION = 'GENERALE', + CARA = ('A', 'IY', 'IZ', 'JX'), + VALE = {profileProperties} + ),''' + + context = { + 'group_name': getGroupName(str(el['ifcName'])), + 'profileProperties': ( + el['profile']['mechProps']['crossSectionArea'], + el['profile']['mechProps']['momentOfInertiaY'], + el['profile']['mechProps']['momentOfInertiaZ'], + el['profile']['mechProps']['torsionalConstantX'] + ) + } + + f.write(template.format(**context)) + + if rigidLinkGroupNames: + template = \ + ''' + _F( + GROUP_MA = {group_names}, + SECTION = 'RECTANGLE', + CARA = ('HY', 'HZ'), + VALE = {profileDimensions} + ),''' + + context = { + 'group_names': rigidLinkGroupNames, + 'profileDimensions': (1, 1) + } + + f.write(template.format(**context)) + + f.write( +''' + ), + COQUE = (''' + ) + + for el in [el for el in elements if el['geometryType'] == 'surface']: + + template = \ + ''' + _F( + GROUP_MA = '{group_name}', + EPAIS = {thickness}, + VECTEUR = {orientationVector} + ),''' + + context = { + 'group_name': getGroupName(str(el['ifcName'])), + 'thickness': el['thickness'], + 'orientationVector': ( + el['geometry'][1][0] - el['geometry'][0][0], + el['geometry'][1][1] - el['geometry'][0][1], + el['geometry'][1][2] - el['geometry'][0][2] + ) + } + + f.write(template.format(**context)) + + f.write( +''' + ),''' + ) + + # f.write( + # ''' + # ORIENTATION = (''' + # ) + # + # for el in [el for el in elements if el['geometryType'] == 'line']: + # + # template = \ + # ''' + # _F( + # GROUP_MA = '{group_name}', + # CARA = ('ANGL_VRIL',), + # VALE = {rotation} + # ),''' + # + # context = { + # 'group_name': getGroupName(str(el['ifcName'])), + # 'rotation': 0 # (el['rotation'],) + # } + # + # f.write(template.format(**context)) + # + # f.write( + # ''' + # ),''' + # ) + + f.write( +''' +)\n +''' + ) + + + f.write('# STEP: DEFINE GROUND BOUNDARY CONDITIONS') + + f.write( +''' +grdSupps = AFFE_CHAR_MECA( + MODELE = model, + DDL_IMPO = (''' + ) + + for conn in [conn for conn in connections if conn['appliedCondition']]: + f.write( + ''' + _F( + GROUP_NO = '%s',''' % conn['relatedGroupNames'][0] + ) + for dof in conn['appliedCondition']: + if conn['appliedCondition'][dof]: + f.write( + ''' + %s = 0,''' % (str(dof).upper()) + ) + f.write( + ''' + ),''' + ) + + f.write( + ''' + ),''' + ) + + if unifiedConnection: + f.write( + ''' + LIAISON_UNIF = (''' + ) + + for conn in [conn for conn in connections if len(conn['relatedGroupNames']) > 1]: + template = \ + ''' + _F( + GROUP_NO = {group_names}, + DDL = ('DX', 'DY', 'DZ', 'DRX', 'DRY', 'DRZ') + ),''' + + context = { + 'group_names': conn['relatedGroupNames'] + } + + f.write(template.format(**context)) + + f.write( + ''' + ),''' + ) + + if rigidLinkGroupNames: + f.write( + ''' + LIAISON_SOLIDE = (''' + ) + + for groupName in rigidLinkGroupNames: + template = \ + ''' + _F( + GROUP_MA = '{group_name}' + ),''' + + context = { + 'group_name': groupName + } + + f.write(template.format(**context)) + + f.write( + ''' + ),''' + ) + + f.write( + ''' +)''' + ) + + template = \ +''' +# STEP: DEFINE LOAD +exPESA = AFFE_CHAR_MECA( + MODELE = model, + PESANTEUR = _F( + GRAVITE = {AccelOfGravity}, + DIRECTION = (0.,0.,-1.) + ) +) +''' + context = { + 'AccelOfGravity': AccelOfGravity, + } + + f.write(template.format(**context)) + + + f.write( +''' +# STEP: RUN ANALYSIS +res_Bld = MECA_STATIQUE( + MODELE = model, + CHAM_MATER = material, + CARA_ELEM = element, + EXCIT = ( + _F( + CHARGE = grdSupps + ), + _F( + CHARGE = exPESA + ) + ) +) +''' + ) + + +# f.write( +# ''' +# # STEP: POST-PROCESSING +# res_Bld = CALC_CHAMP( +# reuse = res_Bld, +# RESULTAT = res_Bld, +# CONTRAINTE = ('SIEF_ELNO', 'SIGM_ELNO', 'EFGE_ELNO',), +# FORCE = ('REAC_NODA', 'FORC_NODA',), +# ) +# ''' +# ) +# +# template = \ +# ''' +# # STEP: MASS EXTRACTION FOR EACH ASSEMBLE +# FaceMass = POST_ELEM( +# TITRE = 'TotMass', +# MODELE = model, +# CARA_ELEM = element, +# CHAM_MATER = material, +# MASS_INER = _F( +# GROUP_MA = {massList}, +# ), +# )\n''' +# +# context = { +# 'massList': massList, +# } +# +# f.write(template.format(**context)) +# +# f.write( +# ''' +# IMPR_TABLE( +# UNITE = 10, +# TABLE = FaceMass, +# SEPARATEUR = ',', +# NOM_PARA = ('LIEU', 'MASSE', 'CDG_X', 'CDG_Y', 'CDG_Z'), +# # FORMAT_R = '1PE15.6', +# ) +# ''' +# ) +# +# f.write( +# ''' +# # STEP: REACTION EXTRACTION AT THE BASE +# Reacs = POST_RELEVE_T( +# ACTION = _F( +# INTITULE = 'sumReac', +# GROUP_NO = 'grdSupps', +# RESULTAT = res_Bld, +# NOM_CHAM = 'REAC_NODA', +# RESULTANTE = ('DX','DY','DZ',), +# # MOMENT = ('DRX','DRY','DRZ',), +# # POINT = (0,0,0,), +# OPERATION = 'EXTRACTION', +# ), +# ) +# ''' +# ) +# +# f.write( +# ''' +# IMPR_TABLE( +# UNITE = 10, +# TABLE = Reacs, +# SEPARATEUR = ',', +# NOM_PARA = ('INTITULE', 'RESU', 'NOM_CHAM', 'INST', 'DX','DY','DZ'), +# # FORMAT_R = '1PE12.3', +# ) +# ''' +# ) +# + f.write( +''' +# STEP: DEFORMED SHAPE EXTRACTION +IMPR_RESU( + FORMAT = 'MED', + UNITE = 80, + RESU = _F( + RESULTAT = res_Bld, + NOM_CHAM = ('DEPL',), # 'REAC_NODA', 'FORC_NODA', + NOM_CHAM_MED = ('Bld_DISP',), # 'Bld_REAC', 'Bld_FORC' + ) +) +''' + ) + + f.write( +''' +# STEP: CONCLUDE STUDY +FIN() +''' + ) + + f.close() + +if __name__ == '__main__': + fileNames = ['cantilever_01', 'beam_01', 'portal_01', 'building_01', 'building-frame_01']; + files = [fileNames[3]] + + for fileName in files: + FILENAME = 'examples/' + fileName + '/' + fileName + '.json' + FILENAMEASTER = 'examples/' + fileName + '/CA_input_00.comm' + createCommFile(FILENAME, FILENAMEASTER) diff --git a/src/ifc2ca/scriptSalome.py b/src/ifc2ca/scriptSalome.py new file mode 100644 index 0000000000..c1dc6c0ec3 --- /dev/null +++ b/src/ifc2ca/scriptSalome.py @@ -0,0 +1,334 @@ +import os +import time +import json +import salome +import salome_notebook +import salome_version +from pprint import pprint + +class MODEL(object): + def __init__(self, filename, meshSize): + self.filename = filename + self.meshSize = meshSize + self.tolLoc = 0 + self.mesh = None + self.create(filename) + + def getGroupName(self, name): + info = name.split('|') + sortName = ''.join(c for c in info[0] if c.isupper()) + return str(sortName + '_' + info[1]) + + def makePoint(self, pl): + '''Function to define a Point from + a polyline (list of 1 point)''' + + (x, y, z) = pl + return self.geompy.MakeVertex(x, y, z) + + def makeLine(self, pl): + '''Function to define a Line from + a polyline (list of 2 points)''' + + (x, y, z) = pl[0] + P1 = self.geompy.MakeVertex(x, y, z) + (x, y, z) = pl[1] + P2 = self.geompy.MakeVertex(x, y, z) + + return self.geompy.MakeLineTwoPnt(P1, P2) + + def makeFace(self, pl): + '''Function to define a Face from + a polyline (list of points)''' + + pointList = [None for _ in range(len(pl))] + for ip, (x, y, z) in enumerate(pl): + pointList[ip] = self.geompy.MakeVertex(x, y, z) + + LineList = [None for _ in range(len(pl))] + for ip, P2 in enumerate(pointList): + P1 = pointList[ip - 1] + LineList[ip] = self.geompy.MakeLineTwoPnt(P1, P2) + + return self.geompy.MakeFaceWires(LineList, 1) + + def makeObject(self, geometry, geometryType): + if geometryType == 'point': + return self.makePoint(geometry) + if geometryType == 'line': + return self.makeLine(geometry) + if geometryType == 'surface': + return self.makeFace(geometry) + + def makePartition(self, objects, geometryType): + if geometryType == 'point': + shapeType = 'VERTEX' + if geometryType == 'line': + shapeType = 'EDGE' + if geometryType == 'surface': + shapeType = 'FACE' + return self.geompy.MakePartition(objects, [], [], [], self.geompy.ShapeType[shapeType], 0, [], 1) + + def findIntersection(self, geometry, ecc): + # TO DO: implement a more general procedure - understand better how it works + if ecc['inX'] >= 0: + return geometry[1] + else: + return geometry[0] + # elemLength = self.length(geometry) + # pLocal = [ + # (ecc['pointOnElement'][0] - ecc['inX']) / elemLength, + # (ecc['pointOnElement'][1] - ecc['inY']) / elemLength, + # (ecc['pointOnElement'][2] - ecc['inZ']) / elemLength + # ] + # pLocalX = pLocal[0] + # + # if abs(pLocalX) < self.tolLoc*100: + # return geometry[0] + # elif abs(pLocalX - 1) < self.tolLoc*100: + # return geometry[1] + # elif pLocalX > 0 and pLocalX < 1: + # return [ + # (1 - pLocalX) * geometry[0][0] + pLocalX * geometry[1][0], + # (1 - pLocalX) * geometry[0][1] + pLocalX * geometry[1][1], + # (1 - pLocalX) * geometry[0][2] + pLocalX * geometry[1][2] + # ] + # else: + # pprint('Warning: Connection point not identified with a tight tolerance.') + # pprint('Tolerance needed is: %.2f' % max(abs(pLocalX), abs(pLocalX - 1))) + # tolMax = 0.1 + # if abs(pLocalX) < tolMax: + # return geometry[0] + # elif abs(pLocalX - 1) < tolMax: + # return geometry[1] + # else: + # pprint('Error: Connection point not identified with a tolerance of 10%') + + def length(self, geometry): + return (( + (geometry[1][0] - geometry[0][0]) ** 2 + \ + (geometry[1][1] - geometry[0][1]) ** 2 + \ + (geometry[1][2] - geometry[0][2]) ** 2 \ + ) ** 0.5) + + def create(self, FILENAME): + # Read data from input file + with open(FILENAME) as dataFile: + data = json.load(dataFile) + + elements = data['elements'] + connections = data['connections'] + + meshSize = self.meshSize + + dec = 7 # 4 decimals for length in mm + tol = 10**(-dec-3+1) + + self.tolLoc = tol*10*2 + tolLoc = self.tolLoc + + NEW_SALOME = int(salome_version.getVersion()[0]) >= 9 + salome.salome_init() + theStudy = salome.myStudy + notebook = salome_notebook.NoteBook(theStudy) + + ### + ### GEOM component + ### + import GEOM + from salome.geom import geomBuilder + import math + import SALOMEDS + + gg = salome.ImportComponentGUI('GEOM') + if NEW_SALOME: + geompy = geomBuilder.New() + else: + geompy = geomBuilder.New(theStudy) + self.geompy = geompy + + O = geompy.MakeVertex(0, 0, 0) + OX = geompy.MakeVectorDXDYDZ(1, 0, 0) + OY = geompy.MakeVectorDXDYDZ(0, 1, 0) + OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) + geompy.addToStudy( O, 'O' ) + geompy.addToStudy( OX, 'OX' ) + geompy.addToStudy( OY, 'OY' ) + geompy.addToStudy( OZ, 'OZ' ) + + if len([e for e in elements if e['geometryType'] == 'line']) > 0: + buildingShapeType = 'EDGE' + if len([e for e in elements if e['geometryType'] == 'surface']) > 0: + buildingShapeType = 'FACE' + + ### Define entities ### + start_time = time.time() + pprint('Defining Object Geometry') + init_time = start_time + + # Loop 1 + for el in elements: + el['elemObj'] = self.makeObject(el['geometry'], str(el['geometryType'])) + + el['connObjs'] = [None for _ in el['connections']] + el['linkObjs'] = [None for _ in el['connections']] + for j,rel in enumerate(el['connections']): + conn = [c for c in connections if c['ifcName'] == rel['relatedConnection']][0] + el['connObjs'][j] = self.makeObject(conn['geometry'], str(conn['geometryType'])) + if rel['eccentricity']: + pointOnElement = self.findIntersection(el['geometry'], rel['eccentricity']) + geometry = [pointOnElement, conn['geometry']] + el['linkObjs'][j] = self.makeObject(geometry, 'line') + + el['partObj'] = self.makePartition([el['elemObj']] + el['connObjs'] + [e for e in el['linkObjs'] if e], str(el['geometryType'])) + + el['elemObj'] = geompy.GetInPlace(el['partObj'], el['elemObj']) + for j,rel in enumerate(el['connections']): + el['connObjs'][j] = geompy.GetInPlace(el['partObj'], el['connObjs'][j]) + if rel['eccentricity']: + el['linkObjs'][j] = geompy.GetInPlace(el['partObj'], el['linkObjs'][j]) + + # for conn in connections: + # if conn['appliedCondition']: + # conn['connObj'] = self.makeObject(conn['geometry'], str(conn['geometryType'])) + + # Make assemble of Building Object + bldObjs = [] + bldObjs.extend([el['partObj'] for el in elements]) + # bldObjs.extend([conn['connObj'] for conn in connections if conn['appliedCondition']]) + + bldComp = geompy.MakeCompound(bldObjs) + geompy.addToStudy(bldComp, 'bldComp') + + # Loop 2 + for el in elements: + # geompy.addToStudy(el['partObj'], self.getGroupName(str(el['ifcName']))) + + geompy.addToStudyInFather(el['partObj'], el['elemObj'], self.getGroupName(str(el['ifcName']))) + for j,rel in enumerate(el['connections']): + geompy.addToStudyInFather(el['partObj'], el['connObjs'][j], self.getGroupName(str(el['ifcName'])) + '_0D_to_' + self.getGroupName(str(rel['relatedConnection']))) + if rel['eccentricity']: + geompy.addToStudyInFather(el['partObj'], el['linkObjs'][j], self.getGroupName(str(el['ifcName'])) + '_1D_to_' + self.getGroupName(str(rel['relatedConnection']))) + + # for conn in connections: + # if conn['appliedCondition']: + # # geompy.addToStudy(conn['connObj'], self.getGroupName(str(conn['ifcName']))) + # geompy.addToStudyInFather(conn['connObj'], conn['connObj'], self.getGroupName(str(conn['ifcName']))) + + elapsed_time = time.time() - init_time + init_time += elapsed_time + pprint('Building Geometry Defined in %g sec' % (elapsed_time)) + + # Loop 3 + for el in elements: + # el['partObj'] = geompy.RestoreGivenSubShapes(bldComp, [el['partObj']], GEOM.FSM_GetInPlace, False, False)[0] + geompy.addToStudyInFather(bldComp, el['elemObj'], self.getGroupName(str(el['ifcName']))) + + for j,rel in enumerate(el['connections']): + geompy.addToStudyInFather(bldComp, el['connObjs'][j], self.getGroupName(str(el['ifcName'])) + '_0D_to_' + self.getGroupName(str(rel['relatedConnection']))) + if rel['eccentricity']: + el['linkObjs'][j].SetColor(SALOMEDS.Color(0, 0, 0)) + geompy.addToStudyInFather(bldComp, el['linkObjs'][j], self.getGroupName(str(el['ifcName'])) + '_1D_to_' + self.getGroupName(str(rel['relatedConnection']))) + + # for conn in connections: + # if conn['appliedCondition']: + # # conn['connObj'] = geompy.RestoreGivenSubShapes(bldComp, [conn['connObj']], GEOM.FSM_GetInPlace, False, False)[0] + # geompy.addToStudyInFather(bldComp, conn['connObj'], self.getGroupName(str(conn['ifcName']))) + + elapsed_time = time.time() - init_time + init_time += elapsed_time + pprint('Building Geometry Groups Defined in %g sec' % (elapsed_time)) + + ### + ### SMESH component + ### + + import SMESH + from salome.smesh import smeshBuilder + + pprint('Defining Mesh Components') + + if NEW_SALOME: + smesh = smeshBuilder.New() + else: + smesh = smeshBuilder.New(theStudy) + Mesh_1 = smesh.Mesh(bldComp) + Regular1D = Mesh_1.Segment() + Local_Length_1 = Regular1D.LocalLength(meshSize, None, tolLoc) + + if buildingShapeType == 'FACE': + NETGEN2D_ONLY = Mesh_1.Triangle(algo=smeshBuilder.NETGEN_2D) + NETGEN2D_Pars = NETGEN2D_ONLY.Parameters() + NETGEN2D_Pars.SetMaxSize(meshSize) + NETGEN2D_Pars.SetOptimize(1) + NETGEN2D_Pars.SetFineness(2) + NETGEN2D_Pars.SetMinSize(meshSize/5.0) + NETGEN2D_Pars.SetUseSurfaceCurvature(1) + NETGEN2D_Pars.SetQuadAllowed(1) + NETGEN2D_Pars.SetSecondOrder(0) + NETGEN2D_Pars.SetFuseEdges(254) + + isDone = Mesh_1.Compute() + + ## Set names of Mesh objects + smesh.SetName(Regular1D.GetAlgorithm(), 'Regular1D') + smesh.SetName(Local_Length_1, 'Local_Length_1') + + if buildingShapeType == 'FACE': + smesh.SetName(NETGEN2D_ONLY.GetAlgorithm(), 'NETGEN2D_ONLY') + smesh.SetName(NETGEN2D_Pars, 'NETGEN2D_Pars') + + smesh.SetName(Mesh_1.GetMesh(), 'bldMesh') + + elapsed_time = time.time() - init_time + init_time += elapsed_time + pprint('Meshing Operations Completed in %g sec' % (elapsed_time)) + + # Define groups in Mesh + for el in elements: + if el['geometryType'] == 'line': + shapeType = SMESH.EDGE + if el['geometryType'] == 'surface': + shapeType = SMESH.FACE + tempgroup = Mesh_1.GroupOnGeom(el['elemObj'], self.getGroupName(str(el['ifcName'])), shapeType) + smesh.SetName(tempgroup, self.getGroupName(str(el['ifcName']))) + + for j,rel in enumerate(el['connections']): + tempgroup = Mesh_1.GroupOnGeom(el['connObjs'][j], self.getGroupName(str(el['ifcName'])) + '_0D_to_' + self.getGroupName(str(rel['relatedConnection'])), SMESH.NODE) + smesh.SetName(tempgroup, self.getGroupName(str(el['ifcName'])) + '_0D_to_' + self.getGroupName(str(rel['relatedConnection']))) + if rel['eccentricity']: + tempgroup = Mesh_1.GroupOnGeom(el['linkObjs'][j], self.getGroupName(str(el['ifcName'])) + '_1D_to_' + self.getGroupName(str(rel['relatedConnection'])), SMESH.EDGE) + smesh.SetName(tempgroup, self.getGroupName(str(el['ifcName'])) + '_1D_to_' + self.getGroupName(str(rel['relatedConnection']))) + + # for conn in connections: + # if conn['appliedCondition']: + # tempgroup = Mesh_1.GroupOnGeom(conn['connObj'], self.getGroupName(str(conn['ifcName'])), SMESH.NODE) + # smesh.SetName(tempgroup, self.getGroupName(str(conn['ifcName']))) + + self.mesh = Mesh_1 + + elapsed_time = time.time() - init_time + init_time += elapsed_time + pprint('Mesh Groups Defined in %g sec' % (elapsed_time)) + + if salome.sg.hasDesktop(): + if NEW_SALOME: + salome.sg.updateObjBrowser() + else: + salome.sg.updateObjBrowser(1) + + + elapsed_time = init_time - start_time + pprint('ALL Operations Completed in %g sec' % (elapsed_time)) + +if __name__ == '__main__': + fileNames = ['cantilever_01', 'beam_01', 'portal_01', 'building_01', 'building-frame_01']; + files = [fileNames[3]] + meshSize = 200 + + for fileName in files: + # BASE_PATH = os.path.dirname(os.path.realpath('__file__')) + BASE_PATH = '/home/jesusbill/Dev-Projects/github.com/Jesusbill/ifc2ca' + FILENAME = BASE_PATH + '/examples/' + fileName + '/' + fileName + '.json' + FILENAMEMED = BASE_PATH + '/examples/' + fileName + '/bldMesh.med' + model = MODEL(FILENAME, meshSize)