mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-30 16:43:00 +00:00
ifc2ca major update - todo: update readme file
This commit is contained in:
@@ -0,0 +1,525 @@
|
||||
|
||||
# Ifc2CA - IFC Code_Aster utility
|
||||
# Copyright (C) 2020, 2021 Ioannis P. Christovasilis <ipc@aethereng.com>
|
||||
#
|
||||
# This file is part of Ifc2CA.
|
||||
#
|
||||
# Ifc2CA is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ifc2CA 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Ifc2CA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
import ifcopenshell
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class CA2IFC:
|
||||
def __init__(self, inputFilename, outputFilename):
|
||||
self.inputFilename = inputFilename
|
||||
self.outputFilename = outputFilename
|
||||
self.data = None
|
||||
self.f = None
|
||||
self.reps = {}
|
||||
self.origin = None
|
||||
self.xAxis = None
|
||||
self.yAxis = None
|
||||
self.zAxis = None
|
||||
|
||||
def convert(self):
|
||||
# load json file
|
||||
with open(self.inputFilename) as dataFile:
|
||||
self.data = json.load(dataFile)
|
||||
|
||||
# initiate ifc file
|
||||
self.f = ifcopenshell.file()
|
||||
|
||||
# create header
|
||||
self.create_header()
|
||||
|
||||
# create global axes
|
||||
globalAxes = self.create_global_axes()
|
||||
localPlacement = self.f.createIfcLocalPlacement(None, globalAxes)
|
||||
|
||||
# TODO: create units
|
||||
lengthUnit = self.f.createIfcSIUnit(None, "LENGTHUNIT", None, "METRE")
|
||||
unitAssignment = self.f.createIfcUnitAssignment((lengthUnit,))
|
||||
|
||||
# create owner history
|
||||
ownerHistory = self.create_owner_history()
|
||||
|
||||
# create representations and subrepresentations
|
||||
self.reps = self.create_reference_subrep(globalAxes)
|
||||
|
||||
# create project and model
|
||||
project = self.f.createIfcProject(
|
||||
self.guid(), ownerHistory, "A Project", None, None, None, None, (self.reps["model"],), unitAssignment
|
||||
)
|
||||
model = self.f.createIfcStructuralAnalysisModel(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
self.data["name"],
|
||||
None,
|
||||
None,
|
||||
"NOTDEFINED",
|
||||
globalAxes,
|
||||
None,
|
||||
None,
|
||||
localPlacement,
|
||||
)
|
||||
self.f.createIfcRelDeclares(self.guid(), ownerHistory, None, None, project, (model,))
|
||||
|
||||
# create materials
|
||||
ifcMaterials = [None for _ in range(len(self.data["db"]["materials"]))]
|
||||
for i, material in enumerate(self.data["db"]["materials"]):
|
||||
ifcMaterials[i] = self.create_material(material)
|
||||
|
||||
# create profiles
|
||||
ifcProfiles = [None for _ in range(len(self.data["db"]["profiles"]))]
|
||||
for i, profile in enumerate(self.data["db"]["profiles"]):
|
||||
ifcProfiles[i] = self.create_profile(profile)
|
||||
|
||||
# create material-profile sets
|
||||
mpSets = list(
|
||||
set([el["material"] + "-" + el["profile"] for el in self.data["elements"] if el["geometryType"] == "line"])
|
||||
)
|
||||
ifcMaterialProfileSets = [None for _ in range(len(mpSets))]
|
||||
for i, mpSet in enumerate(mpSets):
|
||||
materialIndex = [mat["referenceName"] for mat in self.data["db"]["materials"]].index(mpSet.split("-")[0])
|
||||
profileIndex = [prof["referenceName"] for prof in self.data["db"]["profiles"]].index(mpSet.split("-")[1])
|
||||
material = ifcMaterials[materialIndex]
|
||||
profile = ifcProfiles[profileIndex]
|
||||
matProf = self.f.createIfcMaterialProfile(
|
||||
self.data["db"]["materials"][materialIndex]["name"]
|
||||
+ " | "
|
||||
+ self.data["db"]["profiles"][profileIndex]["profileName"],
|
||||
None,
|
||||
material,
|
||||
profile,
|
||||
)
|
||||
ifcMaterialProfileSets[i] = self.f.createIfcMaterialProfileSet(None, None, (matProf,))
|
||||
|
||||
# create structural elements
|
||||
ifcElements = [None for _ in range(len(self.data["elements"]))]
|
||||
for i, el in enumerate(self.data["elements"]):
|
||||
# geometry - product definition shape
|
||||
prodDefShape = self.create_geometry(el)
|
||||
|
||||
if el["geometryType"] == "line":
|
||||
# z axis TODO: group by elements
|
||||
localZAxis = self.f.createIfcDirection(tuple(el["orientation"][2]))
|
||||
# element
|
||||
ifcElements[i] = self.f.createIfcStructuralCurveMember(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
el["name"],
|
||||
None,
|
||||
None,
|
||||
localPlacement,
|
||||
prodDefShape,
|
||||
el["predefinedType"],
|
||||
localZAxis,
|
||||
)
|
||||
|
||||
if el["geometryType"] == "surface":
|
||||
ifcElements[i] = self.f.createIfcStructuralSurfaceMember(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
el["name"],
|
||||
None,
|
||||
None,
|
||||
localPlacement,
|
||||
prodDefShape,
|
||||
el["predefinedType"],
|
||||
el["thickness"],
|
||||
)
|
||||
|
||||
# create structural point connections
|
||||
ifcConnections = [None for _ in range(len(self.data["connections"]))]
|
||||
for i, conn in enumerate(self.data["connections"]):
|
||||
# geometry - product definition shape
|
||||
prodDefShape = self.create_geometry(conn)
|
||||
|
||||
# boundary conditions
|
||||
if conn["appliedCondition"]:
|
||||
bc = self.create_applied_conditions(conn["appliedCondition"], conn["geometryType"])
|
||||
if conn["geometryType"] == "point":
|
||||
appliedCondition = self.f.createIfcBoundaryNodeCondition(
|
||||
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
|
||||
)
|
||||
if conn["geometryType"] == "line":
|
||||
appliedCondition = self.f.createIfcBoundaryEdgeCondition(
|
||||
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
|
||||
)
|
||||
if conn["geometryType"] == "surface":
|
||||
appliedCondition = self.f.createIfcBoundaryFaceCondition(None, bc["dx"], bc["dy"], bc["dz"])
|
||||
else:
|
||||
appliedCondition = None
|
||||
|
||||
if conn["geometryType"] == "point":
|
||||
# local axes
|
||||
localAxes = self.create_orientation(conn["orientation"])
|
||||
# connection
|
||||
ifcConnections[i] = self.f.createIfcStructuralPointConnection(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
conn["name"],
|
||||
None,
|
||||
None,
|
||||
localPlacement,
|
||||
prodDefShape,
|
||||
appliedCondition,
|
||||
localAxes,
|
||||
)
|
||||
|
||||
if conn["geometryType"] == "line":
|
||||
# z axis TODO: group by elements
|
||||
localZAxis = self.f.createIfcDirection(tuple(conn["orientation"][2]))
|
||||
# connection
|
||||
ifcConnections[i] = self.f.createIfcStructuralCurveConnection(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
conn["name"],
|
||||
None,
|
||||
None,
|
||||
localPlacement,
|
||||
prodDefShape,
|
||||
appliedCondition,
|
||||
localZAxis,
|
||||
)
|
||||
|
||||
if conn["geometryType"] == "surface":
|
||||
ifcConnections[i] = self.f.createIfcStructuralSurfaceConnection(
|
||||
self.guid(), ownerHistory, conn["name"], None, None, localPlacement, prodDefShape, appliedCondition
|
||||
)
|
||||
|
||||
# assign material-profile-sets
|
||||
for i, mpSet in enumerate(mpSets):
|
||||
groupOfElements = []
|
||||
for j, el in enumerate(self.data["elements"]):
|
||||
if el["geometryType"] == "line" and el["material"] + "-" + el["profile"] == mpSet:
|
||||
groupOfElements.append(ifcElements[j])
|
||||
|
||||
if groupOfElements:
|
||||
self.f.createIfcRelAssociatesMaterial(
|
||||
self.guid(), ownerHistory, None, None, tuple(groupOfElements), ifcMaterialProfileSets[i]
|
||||
)
|
||||
|
||||
# assign materials
|
||||
for i, mat in enumerate(self.data["db"]["materials"]):
|
||||
groupOfElements = []
|
||||
for j, el in enumerate(self.data["elements"]):
|
||||
if el["geometryType"] == "surface" and el["material"] == mat["referenceName"]:
|
||||
groupOfElements.append(ifcElements[j])
|
||||
if groupOfElements:
|
||||
self.f.createIfcRelAssociatesMaterial(
|
||||
self.guid(), ownerHistory, None, None, tuple(groupOfElements), ifcMaterials[i]
|
||||
)
|
||||
|
||||
# create connections with elements
|
||||
for i, el in enumerate(self.data["elements"]):
|
||||
for conn in el["connections"]:
|
||||
j = [c["referenceName"] for c in self.data["connections"]].index(conn["relatedConnection"])
|
||||
geometryType = self.data["connections"][j]["geometryType"]
|
||||
|
||||
if conn["appliedCondition"]:
|
||||
bc = self.create_applied_conditions(conn["appliedCondition"], geometryType)
|
||||
if geometryType == "point":
|
||||
appliedCondition = self.f.createIfcBoundaryNodeCondition(
|
||||
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
|
||||
)
|
||||
if geometryType == "line":
|
||||
appliedCondition = self.f.createIfcBoundaryEdgeCondition(
|
||||
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
|
||||
)
|
||||
if geometryType == "surface":
|
||||
appliedCondition = self.f.createIfcBoundaryFaceCondition(None, bc["dx"], bc["dy"], bc["dz"])
|
||||
else:
|
||||
appliedCondition = None
|
||||
|
||||
# local axes
|
||||
localAxes = self.create_orientation(conn["orientation"])
|
||||
|
||||
if geometryType == "point":
|
||||
if not conn["eccentricity"]:
|
||||
self.f.createIfcRelConnectsStructuralMember(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
None,
|
||||
None,
|
||||
ifcElements[i],
|
||||
ifcConnections[j],
|
||||
appliedCondition,
|
||||
None,
|
||||
None,
|
||||
localAxes,
|
||||
)
|
||||
else:
|
||||
pointOnElement = self.f.createIfcCartesianPoint(tuple(conn["eccentricity"]["pointOnElement"]))
|
||||
vector = conn["eccentricity"]["vector"]
|
||||
connPointEcc = self.f.createIfcConnectionPointEccentricity(
|
||||
pointOnElement, None, vector[0], vector[1], vector[2]
|
||||
)
|
||||
self.f.createIfcRelConnectsWithEccentricity(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
None,
|
||||
None,
|
||||
ifcElements[i],
|
||||
ifcConnections[j],
|
||||
appliedCondition,
|
||||
None,
|
||||
None,
|
||||
localAxes,
|
||||
connPointEcc,
|
||||
)
|
||||
|
||||
if geometryType in ["line", "surface"]:
|
||||
self.f.createIfcRelConnectsStructuralMember(
|
||||
self.guid(),
|
||||
ownerHistory,
|
||||
None,
|
||||
None,
|
||||
ifcElements[i],
|
||||
ifcConnections[j],
|
||||
appliedCondition,
|
||||
None,
|
||||
None,
|
||||
localAxes,
|
||||
)
|
||||
|
||||
# assign elements and connections to group
|
||||
self.f.createIfcRelAssignsToGroup(
|
||||
self.guid(), ownerHistory, None, None, tuple(ifcElements + ifcConnections), None, model
|
||||
)
|
||||
|
||||
# finalize ifc file
|
||||
self.f.write(self.outputFilename)
|
||||
|
||||
def guid(self):
|
||||
return ifcopenshell.guid.new()
|
||||
|
||||
def create_header(self):
|
||||
self.f.wrapped_data.header.file_name.name = os.path.basename(self.outputFilename)
|
||||
|
||||
def create_global_axes(self):
|
||||
self.xAxis = self.f.createIfcDirection((1.0, 0.0, 0.0))
|
||||
self.yAxis = self.f.createIfcDirection((0.0, 1.0, 0.0))
|
||||
self.zAxis = self.f.createIfcDirection((0.0, 0.0, 1.0))
|
||||
self.origin = self.f.createIfcCartesianPoint((0.0, 0.0, 0.0))
|
||||
axes = self.f.createIfcAxis2Placement3D(self.origin, self.zAxis, self.xAxis)
|
||||
|
||||
return axes
|
||||
|
||||
def create_orientation(self, orientation):
|
||||
xAxis = self.f.createIfcDirection(tuple(orientation[0]))
|
||||
zAxis = self.f.createIfcDirection(tuple(orientation[2]))
|
||||
axes = self.f.createIfcAxis2Placement3D(self.origin, zAxis, xAxis)
|
||||
|
||||
return axes
|
||||
|
||||
def create_owner_history(self):
|
||||
actor = self.f.createIfcActorRole("ENGINEER", None, None)
|
||||
person = self.f.createIfcPerson("Christovasilis", None, "Ioannis", None, None, None, (actor,))
|
||||
organization = self.f.createIfcOrganization(
|
||||
None,
|
||||
"IfcOpenShell",
|
||||
"IfcOpenShell, an open source (LGPL) software library that helps users and software developers to work with the IFC file format.",
|
||||
)
|
||||
p_o = self.f.createIfcPersonAndOrganization(person, organization)
|
||||
application = self.f.createIfcApplication(organization, "v0.0.x", "IFC2CA", "IFC2CA")
|
||||
timestamp = int(datetime.now().timestamp())
|
||||
ownerHistory = self.f.createIfcOwnerHistory(p_o, application, "READWRITE", None, None, None, None, timestamp)
|
||||
|
||||
return ownerHistory
|
||||
|
||||
def create_reference_subrep(self, globalAxes):
|
||||
modelRep = self.f.createIfcGeometricRepresentationContext(None, "Model", 3, 1.0e-05, globalAxes, None)
|
||||
bodySubRep = self.f.createIfcGeometricRepresentationSubContext(
|
||||
"Body", "Model", None, None, None, None, modelRep, None, "MODEL_VIEW", None
|
||||
)
|
||||
refSubRep = self.f.createIfcGeometricRepresentationSubContext(
|
||||
"Reference", "Model", None, None, None, None, modelRep, None, "GRAPH_VIEW", None
|
||||
)
|
||||
|
||||
return {"model": modelRep, "body": bodySubRep, "reference": refSubRep}
|
||||
|
||||
def create_material(self, material):
|
||||
ifcMaterial = self.f.createIfcMaterial(material["name"], None, material["category"])
|
||||
|
||||
mechProps = []
|
||||
if "youngModulus" in material["mechProps"]:
|
||||
youngModulus = self.f.createIfcPropertySingleValue(
|
||||
"YoungModulus", None, self.f.createIfcModulusOfElasticityMeasure(material["mechProps"]["youngModulus"])
|
||||
)
|
||||
mechProps.append(youngModulus)
|
||||
if "shearModulus" in material["mechProps"]:
|
||||
shearModulus = self.f.createIfcPropertySingleValue(
|
||||
"ShearModulus", None, self.f.createIfcModulusOfElasticityMeasure(material["mechProps"]["shearModulus"])
|
||||
)
|
||||
mechProps.append(shearModulus)
|
||||
if "poissonRatio" in material["mechProps"]:
|
||||
poissonRatio = self.f.createIfcPropertySingleValue(
|
||||
"PoissonRatio", None, self.f.createIfcPositiveRatioMeasure(material["mechProps"]["poissonRatio"])
|
||||
)
|
||||
mechProps.append(poissonRatio)
|
||||
if mechProps:
|
||||
self.f.createIfcMaterialProperties(
|
||||
"Pset_MaterialMechanical", material["name"], tuple(mechProps), ifcMaterial
|
||||
)
|
||||
|
||||
commonProps = []
|
||||
if "massDensity" in material["commonProps"]:
|
||||
massDensity = self.f.createIfcPropertySingleValue(
|
||||
"MassDensity", None, self.f.createIfcMassDensityMeasure(material["commonProps"]["massDensity"])
|
||||
)
|
||||
commonProps.append(massDensity)
|
||||
if commonProps:
|
||||
self.f.createIfcMaterialProperties("Pset_MaterialCommon", material["name"], tuple(commonProps), ifcMaterial)
|
||||
|
||||
return ifcMaterial
|
||||
|
||||
def create_profile(self, profile):
|
||||
if profile["profileShape"] == "rectangular":
|
||||
ifcProfile = self.f.createIfcRectangleProfileDef(
|
||||
profile["profileType"], profile["profileName"], None, profile["xDim"], profile["yDim"]
|
||||
)
|
||||
|
||||
if profile["profileShape"] == "iSymmetrical":
|
||||
ifcProfile = self.f.createIfcIShapeProfileDef(
|
||||
profile["profileType"],
|
||||
profile["profileName"],
|
||||
None,
|
||||
profile["commonProps"]["overallWidth"],
|
||||
profile["commonProps"]["overallDepth"],
|
||||
profile["commonProps"]["webThickness"],
|
||||
profile["commonProps"]["flangeThickness"],
|
||||
profile["commonProps"]["filletRadius"],
|
||||
)
|
||||
|
||||
mechProps = []
|
||||
if "massPerLength" in profile["mechProps"]:
|
||||
massPerLength = self.f.createIfcPropertySingleValue(
|
||||
"MassPerLength", None, self.f.createIfcMassPerLengthMeasure(profile["mechProps"]["massPerLength"])
|
||||
)
|
||||
mechProps.append(massPerLength)
|
||||
if "crossSectionArea" in profile["mechProps"]:
|
||||
crossSectionArea = self.f.createIfcPropertySingleValue(
|
||||
"CrossSectionArea", None, self.f.createIfcAreaMeasure(profile["mechProps"]["crossSectionArea"])
|
||||
)
|
||||
mechProps.append(crossSectionArea)
|
||||
if "momentOfInertiaY" in profile["mechProps"]:
|
||||
momentOfInertiaY = self.f.createIfcPropertySingleValue(
|
||||
"MomentOfInertiaY",
|
||||
None,
|
||||
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["momentOfInertiaY"]),
|
||||
)
|
||||
mechProps.append(momentOfInertiaY)
|
||||
if "momentOfInertiaZ" in profile["mechProps"]:
|
||||
momentOfInertiaZ = self.f.createIfcPropertySingleValue(
|
||||
"MomentOfInertiaZ",
|
||||
None,
|
||||
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["momentOfInertiaZ"]),
|
||||
)
|
||||
mechProps.append(momentOfInertiaZ)
|
||||
if "torsionalConstantX" in profile["mechProps"]:
|
||||
torsionalConstantX = self.f.createIfcPropertySingleValue(
|
||||
"TorsionalConstantX",
|
||||
None,
|
||||
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["torsionalConstantX"]),
|
||||
)
|
||||
mechProps.append(torsionalConstantX)
|
||||
if mechProps:
|
||||
self.f.createIfcProfileProperties(
|
||||
"Pset_ProfileMechanical", profile["profileName"], tuple(mechProps), ifcProfile
|
||||
)
|
||||
|
||||
return ifcProfile
|
||||
|
||||
def create_geometry(self, object):
|
||||
if object["geometryType"] == "point":
|
||||
point = self.f.createIfcCartesianPoint(tuple(object["geometry"]))
|
||||
vertex = self.f.createIfcVertexPoint(point)
|
||||
vertexTopologyRep = self.f.createIfcTopologyRepresentation(
|
||||
self.reps["reference"], "Reference", "Vertex", (vertex,)
|
||||
)
|
||||
vertexProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (vertexTopologyRep,))
|
||||
|
||||
return vertexProdDefShape
|
||||
|
||||
if object["geometryType"] == "line":
|
||||
startPoint = self.f.createIfcCartesianPoint(tuple(object["geometry"][0]))
|
||||
startVertex = self.f.createIfcVertexPoint(startPoint)
|
||||
endPoint = self.f.createIfcCartesianPoint(tuple(object["geometry"][1]))
|
||||
endVertex = self.f.createIfcVertexPoint(endPoint)
|
||||
edge = self.f.createIfcEdge(startVertex, endVertex)
|
||||
edgeTopologyRep = self.f.createIfcTopologyRepresentation(
|
||||
self.reps["reference"], "Reference", "Edge", (edge,)
|
||||
)
|
||||
edgeProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (edgeTopologyRep,))
|
||||
|
||||
return edgeProdDefShape
|
||||
|
||||
if object["geometryType"] == "surface":
|
||||
verts = [None for _ in range(len(object["geometry"]))]
|
||||
for i, p in enumerate(object["geometry"]):
|
||||
point = self.f.createIfcCartesianPoint(tuple(p))
|
||||
verts[i] = self.f.createIfcVertexPoint(point)
|
||||
|
||||
orientedEdges = [None for _ in range(len(object["geometry"]))]
|
||||
for i, v in enumerate(verts):
|
||||
v2Index = (i + 1) if i < len(verts) - 1 else 0
|
||||
edge = self.f.createIfcEdge(v, verts[v2Index])
|
||||
orientedEdges[i] = self.f.createIfcOrientedEdge(None, None, edge, True)
|
||||
|
||||
edgeLoop = self.f.createIfcEdgeLoop(tuple(orientedEdges))
|
||||
localAxes = self.create_orientation(object["orientation"])
|
||||
plane = self.f.createIfcPlane(localAxes)
|
||||
faceBound = self.f.createIfcFaceBound(edgeLoop, True)
|
||||
face = self.f.createIfcFaceSurface((faceBound,), plane, True)
|
||||
faceTopologyRep = self.f.createIfcTopologyRepresentation(
|
||||
self.reps["reference"], "Reference", "Face", (face,)
|
||||
)
|
||||
faceProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (faceTopologyRep,))
|
||||
|
||||
return faceProdDefShape
|
||||
|
||||
def create_applied_conditions(self, bc, geometryType):
|
||||
for dof in ["dx", "dy", "dz"]:
|
||||
if isinstance(bc[dof], bool):
|
||||
bc[dof] = self.f.createIfcBoolean(bc[dof])
|
||||
else:
|
||||
if geometryType == "point":
|
||||
bc[dof] = self.f.createIfcLinearStiffnessMeasure(bc[dof])
|
||||
if geometryType == "line":
|
||||
bc[dof] = self.f.createIfcModulusOfLinearSubgradeReactionMeasure(bc[dof])
|
||||
if geometryType == "surface":
|
||||
bc[dof] = self.f.createIfcModulusOfSubgradeReactionMeasure(bc[dof])
|
||||
|
||||
for dof in ["drx", "dry", "drz"]:
|
||||
if isinstance(bc[dof], bool):
|
||||
bc[dof] = self.f.createIfcBoolean(bc[dof])
|
||||
else:
|
||||
if geometryType == "point":
|
||||
bc[dof] = self.f.createIfcRotationalStiffnessMeasure(bc[dof])
|
||||
if geometryType == "line":
|
||||
bc[dof] = self.f.createIfcModulusOfRotationalSubgradeReactionMeasure(bc[dof])
|
||||
|
||||
return bc
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
inputFilename = "grid_of_beams.json"
|
||||
outputFilename = "grid_of_beams.ifc"
|
||||
|
||||
ca2ifc = CA2IFC(inputFilename, outputFilename)
|
||||
ca2ifc.convert()
|
||||
@@ -0,0 +1,580 @@
|
||||
# Ifc2CA - IFC Code_Aster utility
|
||||
# Copyright (C) 2020, 2021 Ioannis P. Christovasilis <ipc@aethereng.com>
|
||||
#
|
||||
# This file is part of Ifc2CA.
|
||||
#
|
||||
# Ifc2CA is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ifc2CA 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Ifc2CA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
import numpy as np
|
||||
import itertools
|
||||
from pathlib import Path
|
||||
|
||||
flatten = itertools.chain.from_iterable
|
||||
|
||||
ScaleFactor = 1.0
|
||||
|
||||
AccelOfGravity = 9.806 * 1000
|
||||
|
||||
|
||||
class COMMANDFILE:
|
||||
def __init__(self, dataFilename, asterFilename):
|
||||
self.dataFilename = dataFilename
|
||||
self.asterFilename = asterFilename
|
||||
self.create()
|
||||
|
||||
def getGroupName(self, name):
|
||||
if "|" in name:
|
||||
info = name.split("|")
|
||||
sortName = "".join(c for c in info[0] if c.isupper())
|
||||
return f"{sortName[2:]}_{info[1]}"
|
||||
else:
|
||||
return name
|
||||
|
||||
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"] = []
|
||||
for el in elements:
|
||||
for rel in el["connections"]:
|
||||
conn = [
|
||||
c for c in connections if c["referenceName"] == rel["relatedConnection"]
|
||||
][0]
|
||||
conn["relatedElements"].append(rel)
|
||||
# End <--
|
||||
|
||||
materials = data["db"]["materials"]
|
||||
profiles = data["db"]["profiles"]
|
||||
|
||||
edgeGroupNames = tuple(
|
||||
[
|
||||
self.getGroupName(el["referenceName"])
|
||||
for el in elements
|
||||
if el["geometryType"] == "line"
|
||||
]
|
||||
)
|
||||
faceGroupNames = tuple(
|
||||
[
|
||||
self.getGroupName(el["referenceName"])
|
||||
for el in elements
|
||||
if el["geometryType"] == "surface"
|
||||
]
|
||||
)
|
||||
|
||||
rigidLinkGroupNames = []
|
||||
for conn in connections:
|
||||
rigidLinkGroupNames.extend(
|
||||
[
|
||||
self.getGroupName(rel["relatingElement"])
|
||||
+ "_1DR_"
|
||||
+ self.getGroupName(conn["referenceName"])
|
||||
for rel in conn["relatedElements"]
|
||||
if rel["eccentricity"]
|
||||
]
|
||||
)
|
||||
rigidLinkGroupNames = tuple(rigidLinkGroupNames)
|
||||
|
||||
# Define file to write command file for code_aster
|
||||
f = open(self.asterFilename, "w")
|
||||
|
||||
f.write("# Command file generated by IfcOpenShell/ifc2ca scripts\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',
|
||||
UNITE = 20
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
f.write(
|
||||
"""
|
||||
# STEP: DEFINE MODEL
|
||||
model = AFFE_MODELE(
|
||||
MAILLAGE = mesh,
|
||||
AFFE = (
|
||||
_F(
|
||||
TOUT = 'OUI',
|
||||
PHENOMENE = 'MECANIQUE',
|
||||
MODELISATION = '3D'
|
||||
),"""
|
||||
)
|
||||
|
||||
if faceGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
PHENOMENE = 'MECANIQUE',
|
||||
MODELISATION = 'DKT'
|
||||
),"""
|
||||
|
||||
context = {"groupNames": faceGroupNames}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
if edgeGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
PHENOMENE = 'MECANIQUE',
|
||||
MODELISATION = 'POU_D_E'
|
||||
),"""
|
||||
|
||||
context = {"groupNames": edgeGroupNames}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
if rigidLinkGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
PHENOMENE = 'MECANIQUE',
|
||||
MODELISATION = 'POU_D_E'
|
||||
),"""
|
||||
|
||||
context = {"groupNames": rigidLinkGroupNames}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
f.write(
|
||||
"""
|
||||
)
|
||||
)\n
|
||||
"""
|
||||
)
|
||||
|
||||
f.write("# STEP: DEFINE MATERIALS")
|
||||
|
||||
for i, material in enumerate(materials):
|
||||
template = """
|
||||
{matNameID} = DEFI_MATERIAU(
|
||||
ELAS = _F(
|
||||
E = {youngModulus},
|
||||
NU = {poissonRatio},
|
||||
RHO = {massDensity}
|
||||
)
|
||||
)
|
||||
"""
|
||||
if "poissonRatio" in material["mechProps"]:
|
||||
poissonRatio = material["mechProps"]["poissonRatio"]
|
||||
else:
|
||||
if "shearModulus" in material["mechProps"]:
|
||||
poissonRatio = (
|
||||
material["mechProps"]["youngModulus"]
|
||||
/ 2.0
|
||||
/ material["mechProps"]["shearModulus"]
|
||||
) - 1
|
||||
else:
|
||||
poissonRatio = 0.0
|
||||
|
||||
context = {
|
||||
"matNameID": "mat" + "_%s" % i,
|
||||
"youngModulus": float(material["mechProps"]["youngModulus"])
|
||||
* ScaleFactor ** 2,
|
||||
"poissonRatio": float(poissonRatio),
|
||||
"massDensity": float(material["commonProps"]["massDensity"])
|
||||
* ScaleFactor ** 3,
|
||||
}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
f.write(
|
||||
"""
|
||||
material = AFFE_MATERIAU(
|
||||
MAILLAGE = mesh,
|
||||
AFFE = ("""
|
||||
)
|
||||
|
||||
for i, material in enumerate(materials):
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
MATER = {matNameID},
|
||||
),"""
|
||||
|
||||
context = {
|
||||
"groupNames": tuple(
|
||||
[self.getGroupName(rel) for rel in material["relatedElements"]]
|
||||
),
|
||||
"matNameID": "mat" + "_%s" % i,
|
||||
}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
if rigidLinkGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
MATER = {matNameID},
|
||||
),"""
|
||||
|
||||
context = {"groupNames": rigidLinkGroupNames, "matNameID": "mat_0"}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
f.write(
|
||||
"""
|
||||
)
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
f.write(
|
||||
"""
|
||||
# STEP: DEFINE ELEMENTS
|
||||
element = AFFE_CARA_ELEM(
|
||||
MODELE = model,
|
||||
POUTRE = ("""
|
||||
)
|
||||
|
||||
for profile in profiles:
|
||||
if (
|
||||
profile["profileShape"] == "rectangular"
|
||||
and profile["profileType"] == "AREA"
|
||||
):
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
SECTION = 'RECTANGLE',
|
||||
CARA = ('HY', 'HZ'),
|
||||
VALE = {profileDimensions}
|
||||
),"""
|
||||
|
||||
context = {
|
||||
"groupNames": tuple(
|
||||
[self.getGroupName(rel) for rel in profile["relatedElements"]]
|
||||
),
|
||||
"profileDimensions": (
|
||||
profile["xDim"] / ScaleFactor,
|
||||
profile["yDim"] / ScaleFactor,
|
||||
),
|
||||
}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
elif (
|
||||
profile["profileShape"] == "iSymmetrical"
|
||||
and profile["profileType"] == "AREA"
|
||||
):
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
SECTION = 'GENERALE',
|
||||
CARA = ('A', 'IY', 'IZ', 'JX'),
|
||||
VALE = {profileProperties}
|
||||
),"""
|
||||
|
||||
context = {
|
||||
"groupNames": tuple(
|
||||
[self.getGroupName(rel) for rel in profile["relatedElements"]]
|
||||
),
|
||||
"profileProperties": (
|
||||
profile["mechProps"]["crossSectionArea"] / ScaleFactor ** 2,
|
||||
profile["mechProps"]["momentOfInertiaY"] / ScaleFactor ** 4,
|
||||
profile["mechProps"]["momentOfInertiaZ"] / ScaleFactor ** 4,
|
||||
profile["mechProps"]["torsionalConstantX"] / ScaleFactor ** 4,
|
||||
),
|
||||
}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
if rigidLinkGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = {groupNames},
|
||||
SECTION = 'RECTANGLE',
|
||||
CARA = ('HY', 'HZ'),
|
||||
VALE = {profileDimensions}
|
||||
),"""
|
||||
|
||||
context = {"groupNames": 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 = '{groupName}',
|
||||
EPAIS = {thickness},
|
||||
VECTEUR = {localAxisX}
|
||||
),"""
|
||||
|
||||
context = {
|
||||
"groupName": self.getGroupName(el["referenceName"]),
|
||||
"thickness": el["thickness"] / ScaleFactor,
|
||||
"localAxisX": tuple(el["orientation"][0]),
|
||||
}
|
||||
|
||||
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 = '{groupName}',
|
||||
CARA = 'VECT_Y',
|
||||
VALE = {localAxisY}
|
||||
),"""
|
||||
|
||||
context = {
|
||||
"groupName": self.getGroupName(el["referenceName"]),
|
||||
"localAxisY": tuple(el["orientation"][1]),
|
||||
}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
f.write(
|
||||
"""
|
||||
),"""
|
||||
)
|
||||
|
||||
f.write(
|
||||
"""
|
||||
)\n
|
||||
"""
|
||||
)
|
||||
|
||||
f.write("# STEP: DEFINE SUPPORTS AND CONSTRAINTS")
|
||||
|
||||
f.write(
|
||||
"""
|
||||
liaisons = AFFE_CHAR_MECA(
|
||||
MODELE = model,
|
||||
DDL_IMPO = (
|
||||
_F(
|
||||
GROUP_NO = 'grdSupps',
|
||||
DX = 0.0,
|
||||
DY = 0.0,
|
||||
DZ = 0.0,
|
||||
DRX = 0.0,
|
||||
DRY = 0.0,
|
||||
DRZ = 0.0
|
||||
)
|
||||
),"""
|
||||
)
|
||||
|
||||
if rigidLinkGroupNames:
|
||||
f.write(
|
||||
"""
|
||||
LIAISON_SOLIDE = ("""
|
||||
)
|
||||
|
||||
for groupName in rigidLinkGroupNames:
|
||||
template = """
|
||||
_F(
|
||||
GROUP_MA = '{groupName}'
|
||||
),"""
|
||||
|
||||
context = {"groupName": groupName}
|
||||
|
||||
f.write(template.format(**context))
|
||||
|
||||
f.write(
|
||||
"""
|
||||
),"""
|
||||
)
|
||||
|
||||
f.write(
|
||||
"""
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
template = """
|
||||
# STEP: DEFINE LOAD
|
||||
gravLoad = AFFE_CHAR_MECA(
|
||||
MODELE = model,
|
||||
PESANTEUR = _F(
|
||||
GRAVITE = {AccelOfGravity},
|
||||
DIRECTION = (0.0, 0.0, -1.0)
|
||||
)
|
||||
)
|
||||
"""
|
||||
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 = liaisons
|
||||
),
|
||||
_F(
|
||||
CHARGE = gravLoad
|
||||
)
|
||||
)
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
# 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',
|
||||
# )
|
||||
# '''
|
||||
# )
|
||||
#
|
||||
# template = \
|
||||
# '''
|
||||
# # STEP: REACTION EXTRACTION AT THE BASE
|
||||
# Reacs = POST_RELEVE_T(
|
||||
# ACTION = _F(
|
||||
# INTITULE = 'sumReac',
|
||||
# GROUP_NO = {groupNames},
|
||||
# RESULTAT = res_Bld,
|
||||
# NOM_CHAM = 'REAC_NODA',
|
||||
# RESULTANTE = ('DX','DY','DZ',),
|
||||
# MOMENT = ('DRX','DRY','DRZ',),
|
||||
# POINT = (0,0,0,),
|
||||
# OPERATION = 'EXTRACTION'
|
||||
# )
|
||||
# )
|
||||
# '''
|
||||
#
|
||||
# context = {
|
||||
# 'groupNames': point0DGroupNames,
|
||||
# }
|
||||
#
|
||||
# f.write(template.format(**context))
|
||||
#
|
||||
# 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 = ["test"]
|
||||
files = fileNames
|
||||
|
||||
for fileName in files:
|
||||
BASE_PATH = Path(
|
||||
"/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
|
||||
)
|
||||
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
||||
ASTERFILENAME = BASE_PATH / fileName / f"{fileName}.comm"
|
||||
COMMANDFILE(DATAFILENAME, ASTERFILENAME)
|
||||
@@ -0,0 +1,428 @@
|
||||
# Ifc2CA - IFC Code_Aster utility
|
||||
# Copyright (C) 2020, 2021 Ioannis P. Christovasilis <ipc@aethereng.com>
|
||||
#
|
||||
# This file is part of Ifc2CA.
|
||||
#
|
||||
# Ifc2CA is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ifc2CA 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 Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Ifc2CA. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import salome
|
||||
import salome_notebook
|
||||
import salome_version
|
||||
import numpy as np
|
||||
import itertools
|
||||
from pathlib import Path
|
||||
|
||||
flatten = itertools.chain.from_iterable
|
||||
|
||||
class MODEL:
|
||||
def __init__(self, dataFilename, medFilename, meshSize, zGround):
|
||||
self.dataFilename = dataFilename
|
||||
self.medFilename = medFilename
|
||||
self.meshSize = meshSize
|
||||
self.zGround = zGround
|
||||
self.tolLoc = 0
|
||||
self.mesh = None
|
||||
self.meshNodes = None
|
||||
self.create()
|
||||
|
||||
def getGroupName(self, name):
|
||||
if "|" in name:
|
||||
info = name.split("|")
|
||||
sortName = "".join(c for c in info[0] if c.isupper())
|
||||
return f"{sortName[2:]}_{info[1]}"
|
||||
else:
|
||||
return name
|
||||
|
||||
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 select(self, elements):
|
||||
zmin = -100
|
||||
zmax = 126300
|
||||
for el in elements:
|
||||
include = True
|
||||
for p in el["geometry"]:
|
||||
if p[2] < zmin or p[2] > zmax:
|
||||
include = False
|
||||
break
|
||||
el["include"] = include
|
||||
return [el for el in elements if el["include"]]
|
||||
|
||||
def create(self):
|
||||
# Read data from input file
|
||||
with open(self.dataFilename) as dataFile:
|
||||
data = json.load(dataFile)
|
||||
|
||||
# print(len(data['elements']))
|
||||
# elements = self.select(data['elements'])
|
||||
# print(len(elements))
|
||||
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
|
||||
zGround = self.zGround
|
||||
|
||||
dec = 5 # 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()
|
||||
print("Defining Object Geometry")
|
||||
init_time = start_time
|
||||
|
||||
# Loop 1
|
||||
for el in elements:
|
||||
el["elemObj"] = self.makeObject(el["geometry"], el["geometryType"])
|
||||
|
||||
el["linkObjs"] = [None for _ in el["connections"]]
|
||||
for j, rel in enumerate(el["connections"]):
|
||||
conn = [
|
||||
c for c in connections if c["referenceName"] == rel["relatedConnection"]
|
||||
][0]
|
||||
if rel["eccentricity"]:
|
||||
rel["index"] = len(conn["relatedElements"]) + 1
|
||||
|
||||
geometry = self.getLinkGeometry(
|
||||
rel["eccentricity"], el["orientation"], conn["geometry"]
|
||||
)
|
||||
el["linkObjs"][j] = self.makeObject(geometry, "line")
|
||||
conn["relatedElements"].append(rel)
|
||||
|
||||
# Make assemble of Building Object
|
||||
bldObjs = []
|
||||
bldObjs.extend([el["elemObj"] for el in elements])
|
||||
bldObjs.extend(
|
||||
flatten([[link for link in el["linkObjs"] if link] for el in elements])
|
||||
)
|
||||
|
||||
# bldComp = geompy.MakeCompound(bldObjs)
|
||||
bldComp = geompy.MakePartition(
|
||||
bldObjs, [], [], [], self.geompy.ShapeType[buildingShapeType], 0, [], 1
|
||||
)
|
||||
geompy.addToStudy(bldComp, "bldComp")
|
||||
|
||||
elapsed_time = time.time() - init_time
|
||||
init_time += elapsed_time
|
||||
print("Building Geometry Defined in %g sec" % (elapsed_time))
|
||||
|
||||
# Define and add groups for all curve, surface and rigid 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, True)
|
||||
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, True)
|
||||
geompy.addToStudyInFather(bldComp, surfaceCompound, "SurfaceMembers")
|
||||
|
||||
linkObjs = list(
|
||||
flatten([[obj for obj in el["linkObjs"] if obj] for el in elements])
|
||||
)
|
||||
if len(linkObjs) > 0:
|
||||
# Make compound of requested group
|
||||
compoundTemp = geompy.MakeCompound(linkObjs)
|
||||
# Define group object and add to study
|
||||
rigidCompound = geompy.GetInPlace(bldComp, compoundTemp, True)
|
||||
geompy.addToStudyInFather(bldComp, rigidCompound, "RigidMembers")
|
||||
|
||||
for el in elements:
|
||||
# el['partObj'] = geompy.RestoreGivenSubShapes(bldComp, [el['partObj']], GEOM.FSM_GetInPlace, False, False)[0]
|
||||
el["elemObj"] = geompy.GetInPlace(bldComp, el["elemObj"], True)
|
||||
geompy.addToStudyInFather(
|
||||
bldComp, el["elemObj"], self.getGroupName(el["referenceName"])
|
||||
)
|
||||
|
||||
for j, rel in enumerate(el["connections"]):
|
||||
if rel["eccentricity"]: # point geometry
|
||||
el["linkObjs"][j] = geompy.GetInPlace(
|
||||
bldComp, el["linkObjs"][j], True
|
||||
)
|
||||
geompy.addToStudyInFather(
|
||||
bldComp,
|
||||
el["linkObjs"][j],
|
||||
self.getGroupName(el["referenceName"])
|
||||
+ "_1DR_"
|
||||
+ self.getGroupName(rel["relatedConnection"]),
|
||||
)
|
||||
|
||||
elapsed_time = time.time() - init_time
|
||||
init_time += elapsed_time
|
||||
print("Building Geometry Groups Defined in %g sec" % (elapsed_time))
|
||||
|
||||
###
|
||||
### SMESH component
|
||||
###
|
||||
|
||||
import SMESH
|
||||
from salome.smesh import smeshBuilder
|
||||
|
||||
print("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()
|
||||
coincident_nodes_on_part = bldMesh.FindCoincidentNodesOnPart(
|
||||
[bldMesh], tolLoc, [], 0
|
||||
)
|
||||
if coincident_nodes_on_part:
|
||||
# bldMesh.MergeNodes(coincident_nodes_on_part, [], 0)
|
||||
# print(f'{len(coincident_nodes_on_part)} Sets of Coincident Nodes Found and Merged')
|
||||
print(f"{len(coincident_nodes_on_part)} Sets of Coincident Nodes Found")
|
||||
print(f"{coincident_nodes_on_part}")
|
||||
|
||||
## 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
|
||||
print("Meshing Operations Completed in %g sec" % (elapsed_time))
|
||||
|
||||
# Define and add groups for all curve, surface and rigid 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")
|
||||
|
||||
if len(linkObjs) > 0:
|
||||
tempgroup = bldMesh.GroupOnGeom(rigidCompound, "RigidMembers", SMESH.EDGE)
|
||||
smesh.SetName(tempgroup, "RigidMembers")
|
||||
|
||||
# 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["referenceName"]), shapeType
|
||||
)
|
||||
smesh.SetName(tempgroup, self.getGroupName(el["referenceName"]))
|
||||
|
||||
for j, rel in enumerate(el["connections"]):
|
||||
if rel["eccentricity"]:
|
||||
tempgroup = bldMesh.GroupOnGeom(
|
||||
el["linkObjs"][j],
|
||||
self.getGroupName(el["referenceName"])
|
||||
+ "_1DR_"
|
||||
+ self.getGroupName(rel["relatedConnection"]),
|
||||
SMESH.EDGE,
|
||||
)
|
||||
smesh.SetName(
|
||||
tempgroup,
|
||||
self.getGroupName(el["referenceName"])
|
||||
+ "_1DR_"
|
||||
+ self.getGroupName(rel["relatedConnection"]),
|
||||
)
|
||||
|
||||
self.mesh = bldMesh
|
||||
self.meshNodes = bldMesh.GetNodesId()
|
||||
|
||||
# Find ground supports and extract node coordinates
|
||||
grdSupps = bldMesh.CreateEmptyGroup(SMESH.NODE, "grdSupps")
|
||||
|
||||
for node in self.meshNodes:
|
||||
coords = bldMesh.GetNodeXYZ(node)
|
||||
if abs(coords[2] - self.zGround) < tolLoc:
|
||||
grdSupps.Add([node])
|
||||
|
||||
smesh.SetName(grdSupps, "grdSupps")
|
||||
|
||||
elapsed_time = time.time() - init_time
|
||||
init_time += elapsed_time
|
||||
print("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:
|
||||
print("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
|
||||
print("ALL Operations Completed in %g sec" % (elapsed_time))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fileNames = ["test"]
|
||||
files = fileNames
|
||||
|
||||
meshSize = 0.5
|
||||
zGround = 0
|
||||
|
||||
for fileName in files:
|
||||
BASE_PATH = Path(
|
||||
"/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
|
||||
)
|
||||
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
||||
MEDFILENAME = BASE_PATH / fileName / f"{fileName}.med"
|
||||
model = MODEL(DATAFILENAME, str(MEDFILENAME), meshSize, zGround)
|
||||
Reference in New Issue
Block a user