adds IFC export for structural slabs (StructuralSurfaceMemebers) with their thickness
This commit is contained in:
@@ -29,6 +29,7 @@ __url__ = "https://www.freecadweb.org"
|
||||
ALLOW_LINEAR_OBJECTS = True # allow non-solid objects (wires, etc) to become analytic objects?
|
||||
|
||||
structural_nodes = {} # this keeps track of nodes during this session
|
||||
structural_curves = {} # this keeps track of structural curves during this session
|
||||
scaling = 1.0 # this keeps track of scaling during this session
|
||||
|
||||
|
||||
@@ -103,6 +104,37 @@ def createStructuralNode(ifcfile, ifcbin, point):
|
||||
return structPntConn
|
||||
|
||||
|
||||
def createStructuralCurve(ifcfile, ifcbin, curve):
|
||||
|
||||
"""Creates a structural connection for a curve"""
|
||||
|
||||
import ifcopenshell
|
||||
uid = ifcopenshell.guid.new
|
||||
ownerHistory = ifcfile.by_type("IfcOwnerHistory")[0]
|
||||
structContext = getStructuralContext(ifcfile)
|
||||
|
||||
cartPnt1 = ifcbin.createIfcCartesianPoint(tuple(curve.Vertexes[ 0].Point.multiply(scaling)))
|
||||
cartPnt2 = ifcbin.createIfcCartesianPoint(tuple(curve.Vertexes[-1].Point.multiply(scaling)))
|
||||
vertPnt1 = ifcfile.createIfcVertexPoint(cartPnt1)
|
||||
vertPnt2 = ifcfile.createIfcVertexPoint(cartPnt2)
|
||||
edge = ifcfile.createIfcEdge(vertPnt1, vertPnt2)
|
||||
topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, "Analysis", "Edge", [edge])
|
||||
prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None , [topologyRep])
|
||||
|
||||
# boundary conditions serve for ex. to create fixed edges
|
||||
# for now we don't create any boundary condition
|
||||
appliedCondition = None
|
||||
localPlacement = ifcbin.createIfcLocalPlacement()
|
||||
origin = ifcfile.createIfcCartesianPoint((0.0, 0.0, 0.0))
|
||||
orientation = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
|
||||
xAxis = ifcfile.createIfcDirection(tuple(orientation[0]))
|
||||
zAxis = ifcfile.createIfcDirection(tuple(orientation[2]))
|
||||
localAxes = ifcfile.createIfcAxis2Placement3D(origin, zAxis, xAxis)
|
||||
structCrvConn = ifcfile.createIfcStructuralCurveConnection(
|
||||
uid(), ownerHistory, "Line", None, None, localPlacement, prodDefShape, appliedCondition, localAxes)
|
||||
return structCrvConn
|
||||
|
||||
|
||||
def createStructuralMember(ifcfile, ifcbin, obj):
|
||||
|
||||
"""Creates a structural member if possible. Returns the member"""
|
||||
@@ -112,6 +144,7 @@ def createStructuralMember(ifcfile, ifcbin, obj):
|
||||
import Draft
|
||||
import Part
|
||||
import ifcopenshell
|
||||
import FreeCAD
|
||||
uid = ifcopenshell.guid.new
|
||||
ownerHistory = ifcfile.by_type("IfcOwnerHistory")[0]
|
||||
structContext = getStructuralContext(ifcfile)
|
||||
@@ -140,42 +173,123 @@ def createStructuralMember(ifcfile, ifcbin, obj):
|
||||
edges = wire.Edges
|
||||
if not edges:
|
||||
return None
|
||||
for edge in edges:
|
||||
if len(edge.Vertexes) > 1:
|
||||
# we don't care about curved edges just now...
|
||||
vert0 = edge.Vertexes[ 0].Point.multiply(scaling)
|
||||
vert1 = edge.Vertexes[-1].Point.multiply(scaling)
|
||||
cartPoint1 = ifcbin.createIfcCartesianPoint(tuple(vert0))
|
||||
cartPoint2 = ifcbin.createIfcCartesianPoint(tuple(vert1))
|
||||
localPlacement = ifcbin.createIfcLocalPlacement()
|
||||
vertPoint1 = ifcfile.createIfcVertexPoint(cartPoint1)
|
||||
vertPoint2 = ifcfile.createIfcVertexPoint(cartPoint2)
|
||||
newEdge = ifcfile.createIfcEdge(vertPoint1, vertPoint2)
|
||||
topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, 'Analysis', 'Edge', [newEdge])
|
||||
prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None, [topologyRep])
|
||||
if ifcfile.wrapped_data.schema_name() == "IFC2X3":
|
||||
structuralMember = ifcfile.createIfcStructuralCurveMember(
|
||||
uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER")
|
||||
else:
|
||||
localZAxis = ifcbin.createIfcDirection((0, 0, 1))
|
||||
structuralMember = ifcfile.createIfcStructuralCurveMember(
|
||||
uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER", localZAxis)
|
||||
# check for existing connection nodes
|
||||
for vert in [vert0, vert1]:
|
||||
vertCoord = tuple(vert)
|
||||
if vertCoord in structural_nodes:
|
||||
if structural_nodes[vertCoord]:
|
||||
# there is already another member using this point
|
||||
structPntConn = structural_nodes[vertCoord]
|
||||
else:
|
||||
# there is another member with same point, create a new node
|
||||
structPntConn = createStructuralNode(ifcfile, ifcbin, vert)
|
||||
structural_nodes[vertCoord] = structPntConn
|
||||
ifcfile.createIfcRelConnectsStructuralMember(
|
||||
uid(), ownerHistory, None, None, structuralMember, structPntConn, None, None, None, None)
|
||||
|
||||
# OBJECT CLASSIFICATION by edge number
|
||||
# Linear elements for edge_number = 1, Surface elements for edge_number > 1
|
||||
# we don't care about curved edges just now...
|
||||
|
||||
if len(edges) == 1:
|
||||
# LINEAR OBJECTS: beams, columns
|
||||
# ATM limitations:
|
||||
# - no profile properties are taken into account
|
||||
# - no materials properties are takein into account
|
||||
# -
|
||||
# create geometry
|
||||
verts = [None for _ in range(len(edges)+1)]
|
||||
verts[0] = tuple(edges[0].Vertexes[ 0].Point.multiply(scaling))
|
||||
verts[1] = tuple(edges[0].Vertexes[-1].Point.multiply(scaling))
|
||||
cartPnt1 = ifcfile.createIfcCartesianPoint(verts[0])
|
||||
cartPnt2 = ifcfile.createIfcCartesianPoint(verts[1])
|
||||
vertPnt1 = ifcfile.createIfcVertexPoint(cartPnt1)
|
||||
vertPnt2 = ifcfile.createIfcVertexPoint(cartPnt2)
|
||||
newEdge = ifcfile.createIfcEdge(vertPnt1, vertPnt2)
|
||||
topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, "Analysis", "Edge", (newEdge,))
|
||||
prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None, (topologyRep,))
|
||||
# set local coordinate system
|
||||
localPlacement = ifcbin.createIfcLocalPlacement()
|
||||
localZAxis = ifcbin.createIfcDirection((0, 0, 1))
|
||||
# create structural member
|
||||
if ifcfile.wrapped_data.schema_name() == "IFC2X3":
|
||||
structuralMember = ifcfile.createIfcStructuralCurveMember(
|
||||
uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER")
|
||||
else:
|
||||
localZAxis = ifcbin.createIfcDirection((0, 0, 1))
|
||||
structuralMember = ifcfile.createIfcStructuralCurveMember(
|
||||
uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER", localZAxis)
|
||||
|
||||
elif len(edges) > 1:
|
||||
# SURFACE OBJECTS: slabs (horizontal, vertical, inclined)
|
||||
# ATM limitations:
|
||||
# - mo material properties are taken into account
|
||||
# - walls don't work because they miss a node system
|
||||
# -
|
||||
# creates geometry
|
||||
verts = [None for _ in range(len(edges))]
|
||||
for i, edge in enumerate(edges):
|
||||
verts[i] = tuple(edge.Vertexes[0].Point.multiply(scaling))
|
||||
cartPnt = ifcfile.createIfcCartesianPoint(verts[i])
|
||||
vertPnt = ifcfile.createIfcVertexPoint(cartPnt)
|
||||
orientedEdges = [None for _ in range(len(edges))]
|
||||
for i, vert in enumerate(verts):
|
||||
v2Index = (i + 1) if i < len(verts) - 1 else 0
|
||||
cartPnt1 = ifcfile.createIfcCartesianPoint(vert)
|
||||
cartPnt2 = ifcfile.createIfcCartesianPoint(verts[v2Index])
|
||||
vertPnt1 = ifcfile.createIfcVertexPoint(cartPnt1)
|
||||
vertPnt2 = ifcfile.createIfcVertexPoint(cartPnt2)
|
||||
edge = ifcfile.createIfcEdge(vertPnt1, vertPnt2)
|
||||
orientedEdges[i] = ifcfile.createIfcOrientedEdge(None, None, edge, True)
|
||||
edgeLoop = ifcfile.createIfcEdgeLoop(tuple(orientedEdges))
|
||||
# sets local coordinate system
|
||||
localPlacement = ifcbin.createIfcLocalPlacement()
|
||||
# sets face origin to the first vertex point of the planar surface
|
||||
origin = cartPnt2
|
||||
# find crossVect that is perpendicular to the planar surface
|
||||
vect0 = FreeCAD.Vector(verts[0])
|
||||
vect1 = FreeCAD.Vector(verts[1])
|
||||
vectn = FreeCAD.Vector(verts[-1])
|
||||
vect01 = vect1.sub(vect0)
|
||||
vect0n = vectn.sub(vect0)
|
||||
crossVect = vect01.cross(vect0n)
|
||||
# normalize crossVect
|
||||
normVect = crossVect.normalize()
|
||||
xAxis = ifcfile.createIfcDirection(tuple([vect01.x, vect01.y, vect01.z]))
|
||||
zAxis = ifcfile.createIfcDirection(tuple([normVect.x, normVect.y, normVect.z]))
|
||||
localAxes = ifcfile.createIfcAxis2Placement3D(origin, zAxis, xAxis)
|
||||
plane = ifcfile.createIfcPlane(localAxes)
|
||||
faceBound = ifcfile.createIfcFaceBound(edgeLoop, True)
|
||||
face = ifcfile.createIfcFaceSurface((faceBound,), plane, True)
|
||||
topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, "Analysis", "Face", (face,))
|
||||
prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None, (topologyRep,))
|
||||
# sets surface thickness
|
||||
# ATM limitations
|
||||
# - for verical slabs (walls) or inclined slabs (ramps) the thickness is taken from the Height property
|
||||
thickness = float(obj.Height)*scaling
|
||||
# creates structural member
|
||||
structuralMember = ifcfile.createIfcStructuralSurfaceMember(
|
||||
uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "SHELL", thickness)
|
||||
|
||||
# check for existing connection nodes
|
||||
for vert in verts:
|
||||
vertCoord = tuple(vert)
|
||||
if vertCoord in structural_nodes:
|
||||
if structural_nodes[vertCoord]:
|
||||
# there is already another member using this point
|
||||
structPntConn = structural_nodes[vertCoord]
|
||||
else:
|
||||
# just add the point, no other member using it yet
|
||||
structural_nodes[vertCoord] = None
|
||||
# there is another member with same point, create a new node connection
|
||||
structPntConn = createStructuralNode(ifcfile, ifcbin, vert)
|
||||
structural_nodes[vertCoord] = structPntConn
|
||||
ifcfile.createIfcRelConnectsStructuralMember(
|
||||
uid(), ownerHistory, None, None, structuralMember, structPntConn, None, None, None, None)
|
||||
else:
|
||||
# just add the point, no other member using it yet
|
||||
structural_nodes[vertCoord] = None
|
||||
|
||||
# check for existing connection curves
|
||||
for edge in edges:
|
||||
if edge in structural_curves:
|
||||
if structural_curves[edge]:
|
||||
# there is already another member using this curve
|
||||
strucCrvConn = structural_curves[edge]
|
||||
else:
|
||||
# there is another member with same edge, create a new curve connection
|
||||
strucCrvConn = createStructuralCurve(ifcfile, ifcbin, edge)
|
||||
structural_curves[edge] = strucCrvConn
|
||||
ifcfile.createIfcRelConnectsStructuralMember(
|
||||
uid(), None, None, None, structuralMember, strucCrvConn, None, None, None, None)
|
||||
else:
|
||||
# just add the curve, no other member using it yet
|
||||
structural_curves[edge] = None
|
||||
return structuralMember
|
||||
|
||||
|
||||
@@ -186,11 +300,13 @@ def createStructuralGroup(ifcfile):
|
||||
import ifcopenshell
|
||||
uid = ifcopenshell.guid.new
|
||||
ownerHistory = ifcfile.by_type("IfcOwnerHistory")[0]
|
||||
structCrvMember = ifcfile.by_type("IfcStructuralCurveMember")
|
||||
structSrfMember = ifcfile.by_type("IfcStructuralSurfaceMember")
|
||||
structCrvMember = ifcfile.by_type("IfcStructuralCurveMember")
|
||||
structPntConn = ifcfile.by_type("IfcStructuralPointConnection")
|
||||
structCrvConn = ifcfile.by_type("IfcStructuralCurveConnection")
|
||||
structModel = ifcfile.by_type("IfcStructuralAnalysisModel")[0]
|
||||
if structModel:
|
||||
members = structCrvMember + structPntConn
|
||||
members = structSrfMember + structCrvMember + structPntConn + structCrvConn
|
||||
if members:
|
||||
ifcfile.createIfcRelAssignsToGroup(uid(), ownerHistory, None, None, members, "PRODUCT", structModel)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user