import os import time import json import salome import salome_notebook import salome_version import numpy as np from pprint import pprint class MODEL: def __init__(self, dataFilename, medFilename, meshSize): self.dataFilename = dataFilename self.medFilename = medFilename self.meshSize = meshSize self.tolLoc = 0 self.mesh = None self.meshNodes = None self.create() 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 getLinkGeometry(self, ecc, orientation, finalPoint): # vector = np.array(orientation).transpose().dot(ecc['vector']) # initialPoint = (np.array(finalPoint) - vector).tolist() # return [initialPoint, finalPoint] 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): # Read data from input file with open(self.dataFilename) as dataFile: data = json.load(dataFile) elements = data['elements'] connections = data['connections'] # --> Delete this reference data and repopulate it with the objects # while going through elements for conn in connections: conn['relatedElements'] = [] # End <-- 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'], el['geometryType']) el['connObjs'] = [None for _ in el['connections']] for j,rel in enumerate(el['connections']): conn = [c for c in connections if c['ifcName'] == rel['relatedConnection']][0] conn['relatedElements'].append(rel) if conn['geometryType'] == 'point': if not rel['eccentricity']: el['connObjs'][j] = self.makeObject(conn['geometry'], conn['geometryType']) else: pass # geometry = self.getLinkGeometry(rel['eccentricity'], el['orientation'], conn['geometry']) # el['linkObjs'][j] = self.makeObject(geometry, 'line') elif conn['geometryType'] == 'line': pass elif conn['geometryType'] == 'surface': pass el['partObj'] = self.makePartition([el['elemObj']] + el['connObjs'], 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'], conn['geometryType']) # Make assemble of Building Object bldObjs = [] bldObjs.extend([el['partObj'] for el in elements]) bldObjs.extend([conn['connObj'] for conn in connections]) # bldObjs.extend([conn['connObj'] for conn in connections if conn['appliedCondition']]) bldComp = geompy.MakeCompound(bldObjs) # bldComp = geompy.MakePartition(bldObjs, [], [], [], self.geompy.ShapeType[buildingShapeType], 0, [], 1) geompy.addToStudy(bldComp, 'bldComp') # Loop 2 for el in elements: # geompy.addToStudy(el['partObj'], self.getGroupName(el['ifcName'])) geompy.addToStudyInFather(el['partObj'], el['elemObj'], self.getGroupName(el['ifcName'])) for j,rel in enumerate(el['connections']): geompy.addToStudyInFather(el['partObj'], el['connObjs'][j], self.getGroupName(el['ifcName']) + '_0DC_' + self.getGroupName(rel['relatedConnection'])) # if rel['eccentricity']: # geompy.addToStudyInFather(el['partObj'], el['linkObjs'][j], self.getGroupName(el['ifcName']) + '_1DC_' + self.getGroupName(rel['relatedConnection'])) for conn in connections: # if conn['appliedCondition']: # geompy.addToStudy(conn['connObj'], self.getGroupName(conn['ifcName'])) geompy.addToStudyInFather(conn['connObj'], conn['connObj'], self.getGroupName(conn['ifcName'])) elapsed_time = time.time() - init_time init_time += elapsed_time pprint('Building Geometry Defined in %g sec' % (elapsed_time)) 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 and add groups for all curve and surface members if len([e for e in elements if e['geometryType'] == 'line']) > 0: # Make compound of requested group compoundTemp = geompy.MakeCompound([e['elemObj'] for e in elements if e['geometryType'] == 'line']) # Define group object and add to study curveCompound = geompy.GetInPlace(bldComp, compoundTemp) geompy.addToStudyInFather(bldComp, curveCompound, 'CurveMembers') if len([e for e in elements if e['geometryType'] == 'surface']) > 0: # Make compound of requested group compoundTemp = geompy.MakeCompound([e['elemObj'] for e in elements if e['geometryType'] == 'surface']) # Define group object and add to study surfaceCompound = geompy.GetInPlace(bldComp, compoundTemp) geompy.addToStudyInFather(bldComp, surfaceCompound, 'SurfaceMembers') # 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(el['ifcName'])) for j,rel in enumerate(el['connections']): geompy.addToStudyInFather(bldComp, el['connObjs'][j], self.getGroupName(el['ifcName']) + '_0DC_' + self.getGroupName(rel['relatedConnection'])) # if rel['eccentricity']: # el['linkObjs'][j].SetColor(SALOMEDS.Color(0, 0, 0)) # geompy.addToStudyInFather(bldComp, el['linkObjs'][j], self.getGroupName(el['ifcName']) + '_1DC_' + self.getGroupName(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(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) bldMesh = smesh.Mesh(bldComp) Regular_1D = bldMesh.Segment() Local_Length_1 = Regular_1D.LocalLength(meshSize, None, tolLoc) if buildingShapeType == 'FACE': NETGEN2D_ONLY = bldMesh.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 = bldMesh.Compute() ## Set names of Mesh objects smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D') 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(bldMesh.GetMesh(), 'bldMesh') elapsed_time = time.time() - init_time init_time += elapsed_time pprint('Meshing Operations Completed in %g sec' % (elapsed_time)) # Define and add groups for all curve and surface members if len([e for e in elements if e['geometryType'] == 'line']) > 0: tempgroup = bldMesh.GroupOnGeom(curveCompound, 'CurveMembers', SMESH.EDGE) smesh.SetName(tempgroup, 'CurveMembers') if len([e for e in elements if e['geometryType'] == 'surface']) > 0: tempgroup = bldMesh.GroupOnGeom(surfaceCompound, 'SurfaceMembers', SMESH.FACE) smesh.SetName(tempgroup, 'SurfaceMembers') # Define groups in Mesh for el in elements: if el['geometryType'] == 'line': shapeType = SMESH.EDGE if el['geometryType'] == 'surface': shapeType = SMESH.FACE tempgroup = bldMesh.GroupOnGeom(el['elemObj'], self.getGroupName(el['ifcName']), shapeType) smesh.SetName(tempgroup, self.getGroupName(el['ifcName'])) for j,rel in enumerate(el['connections']): tempgroup = bldMesh.GroupOnGeom(el['connObjs'][j], self.getGroupName(el['ifcName']) + '_0DC_' + self.getGroupName(rel['relatedConnection']), SMESH.NODE) smesh.SetName(tempgroup, self.getGroupName(el['ifcName']) + '_0DC_' + self.getGroupName(rel['relatedConnection'])) # if rel['eccentricity']: # tempgroup = bldMesh.GroupOnGeom(el['linkObjs'][j], self.getGroupName(el['ifcName']) + '_1DC_' + self.getGroupName(rel['relatedConnection']), SMESH.EDGE) # smesh.SetName(tempgroup, self.getGroupName(el['ifcName']) + '_1DC_' + self.getGroupName(rel['relatedConnection'])) for conn in connections: # if conn['appliedCondition']: tempgroup = bldMesh.GroupOnGeom(conn['connObj'], self.getGroupName(conn['ifcName']), SMESH.NODE) smesh.SetName(tempgroup, self.getGroupName(conn['ifcName'])) nodesId = bldMesh.GetIDSource(tempgroup.GetNodeIDs(), SMESH.NODE) tempgroup = bldMesh.Add0DElementsToAllNodes(nodesId, self.getGroupName(conn['ifcName'])) smesh.SetName(tempgroup, self.getGroupName(conn['ifcName'])) self.mesh = bldMesh self.meshNodes = bldMesh.GetNodesId() elapsed_time = time.time() - init_time init_time += elapsed_time pprint('Mesh Groups Defined in %g sec' % (elapsed_time)) try: if NEW_SALOME: bldMesh.ExportMED( self.medFilename, auto_groups = 0, minor = 40, overwrite = 1, meshPart = None, autoDimension = 0 ) else: bldMesh.ExportMED(self.medFilename, 0, SMESH.MED_V2_2, 1, None, 0) except: pprint('ExportMED() failed. Invalid file name?') 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', 'portal_01']; files = fileNames meshSize = 0.1 for fileName in files: BASE_PATH = '/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/' DATAFILENAME = BASE_PATH + fileName + '/' + fileName + '.json' MEDFILENAME = BASE_PATH + fileName + '/' + fileName + '.med' model = MODEL(DATAFILENAME, MEDFILENAME, meshSize)