mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
ifccityjson conversion support for MultiLineString and MultiPoint
This commit is contained in:
@@ -19,8 +19,8 @@ The example file that could be used is example/3D_BAG_example.json
|
||||
python ifccityjson.py -i example/3DBAG_example.json -o example/3DBAG_example.ifc -n identificatie
|
||||
|
||||
## Implemented geometries
|
||||
- [ ] "MultiPoint"
|
||||
- [ ] "MultiLineString"
|
||||
- [x] "MultiPoint"
|
||||
- [x] "MultiLineString"
|
||||
- [x] "MultiSurface"
|
||||
- [x] "CompositeSurface"
|
||||
- [x] "Solid": exterior shell
|
||||
@@ -34,5 +34,5 @@ The example file that could be used is example/3D_BAG_example.json
|
||||
- [x] Implement georeferencing
|
||||
- [x] Do not use template IFC for new IFC file, but make IFC file from scratch
|
||||
- [x] Create mapping to IFC for all CityJSON object types & semantic surfaces
|
||||
- [ ] Implement conversion of all geometries
|
||||
- [ ] Implement conversion of all LODs instead of online the most detailed
|
||||
- [ ] Implement conversion of all CitYJSON geometries
|
||||
- [ ] Implement conversion of all LODs instead of only the most detailed
|
||||
|
||||
@@ -106,15 +106,14 @@ class Cityjson2ifc:
|
||||
def create_new_file(self):
|
||||
self.IFC_model = ifcopenshell.api.run("project.create_file")
|
||||
self.IFC_project = ifcopenshell.api.run("root.create_entity", self.IFC_model, **{"ifc_class": "IfcProject"})
|
||||
ifcopenshell.api.run("unit.assign_unit", self.IFC_model, length={"is_metric": True, "raw": "METERS"})
|
||||
self.properties["owner_history"] = self.create_owner_history()
|
||||
ifcopenshell.api.run("unit.assign_unit", self.IFC_model)
|
||||
self.IFC_representation_context = ifcopenshell.api.run("context.add_context", self.IFC_model,
|
||||
**{"context": "Model"})
|
||||
self.IFC_representation_sub_context = ifcopenshell.api.run("context.add_context", self.IFC_model,
|
||||
**{"context": "Model",
|
||||
"subcontext": "Body", # LODs as subcontext
|
||||
"target_view": "MODEL_VIEW"})
|
||||
|
||||
self.IFC_site = ifcopenshell.api.run("root.create_entity", self.IFC_model,
|
||||
**{"ifc_class": "IfcSite",
|
||||
"name": "My Site"})
|
||||
@@ -150,7 +149,7 @@ class Cityjson2ifc:
|
||||
data.update(mapping[1])
|
||||
|
||||
# attributes
|
||||
IFC_name = None
|
||||
IFC_name = obj_id
|
||||
if "name_attribute" in self.properties and self.properties["name_attribute"] in obj.attributes:
|
||||
IFC_name = obj.attributes[self.properties["name_attribute"]]
|
||||
|
||||
@@ -175,25 +174,26 @@ class Cityjson2ifc:
|
||||
child_data = {"GlobalId": ifcopenshell.guid.new(),
|
||||
"Name": IFC_child_class
|
||||
}
|
||||
|
||||
# CREATE ENTITY
|
||||
surface_geometry = self.geometry.create_IFC_surface(self.IFC_model, geometry, surface_id)
|
||||
if surface_geometry:
|
||||
child_data["Representation"] = self.create_IFC_representation(surface_geometry)
|
||||
child_data["Representation"] = self.create_IFC_representation(surface_geometry, 'brep')
|
||||
IFC_children.append(self.IFC_model.create_entity(IFC_child_class, **child_data))
|
||||
|
||||
else:
|
||||
IFC_geometry = self.geometry.create_IFC_geometry(self.IFC_model, geometry)
|
||||
IFC_geometry, shape_representation_type = self.geometry.create_IFC_geometry(self.IFC_model, geometry)
|
||||
if IFC_geometry:
|
||||
data["Representation"] = self.create_IFC_representation(IFC_geometry)
|
||||
data["Representation"] = self.create_IFC_representation(IFC_geometry, shape_representation_type)
|
||||
data["GlobalId"] = ifcopenshell.guid.new()
|
||||
data["Name"] = IFC_name
|
||||
|
||||
IFC_object = self.IFC_model.create_entity(IFC_class, **data)
|
||||
# Define aggregation
|
||||
self.IFC_model.create_entity("IfcRelAggregates",
|
||||
self.IFC_model.create_entity("IfcRelContainedInSpatialStructure",
|
||||
**{"GlobalId": ifcopenshell.guid.new(),
|
||||
"RelatedObjects": [IFC_object],
|
||||
"RelatingObject": self.IFC_site}
|
||||
"RelatedElements": [IFC_object],
|
||||
"RelatingStructure": self.IFC_site}
|
||||
)
|
||||
if IFC_children:
|
||||
self.IFC_model.create_entity("IfcRelAggregates",
|
||||
@@ -203,10 +203,13 @@ class Cityjson2ifc:
|
||||
|
||||
self.create_property_set(obj.attributes, IFC_object)
|
||||
|
||||
def create_IFC_representation(self, IFC_geometry):
|
||||
def create_IFC_representation(self, IFC_geometry, shape_representation_type):
|
||||
if not isinstance(IFC_geometry, list):
|
||||
IFC_geometry = [IFC_geometry]
|
||||
|
||||
shape_representation = self.IFC_model.create_entity("IfcShapeRepresentation",
|
||||
self.IFC_representation_sub_context, 'Body', 'Brep',
|
||||
[IFC_geometry])
|
||||
self.IFC_representation_sub_context, 'Body', shape_representation_type,
|
||||
IFC_geometry)
|
||||
product_representation = self.IFC_model.create_entity("IfcProductDefinitionShape",
|
||||
Representations=[shape_representation])
|
||||
return product_representation
|
||||
|
||||
@@ -0,0 +1,485 @@
|
||||
{
|
||||
"CityObjects": {
|
||||
"multipoint": {
|
||||
"geometry": [
|
||||
{
|
||||
"type": "MultiPoint",
|
||||
"lod": 1,
|
||||
"boundaries": [
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7
|
||||
]
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "Being a MultiPoint geometry"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"multiline": {
|
||||
"geometry": [
|
||||
{
|
||||
"type": "MultiLineString",
|
||||
"lod": 1,
|
||||
"boundaries": [
|
||||
[
|
||||
2,
|
||||
3,
|
||||
9
|
||||
],
|
||||
[
|
||||
10,
|
||||
8,
|
||||
10
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "Being a MultiLineString"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"multisurface": {
|
||||
"geometry": [
|
||||
{
|
||||
"type": "MultiSurface",
|
||||
"lod": 1,
|
||||
"boundaries": [
|
||||
[
|
||||
[
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
4
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "Being a MultiSurface without holes"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"CompositeSurface": {
|
||||
"geometry": [
|
||||
{
|
||||
"type": "CompositeSurface",
|
||||
"lod": 1,
|
||||
"boundaries": [
|
||||
[
|
||||
[
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
4
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "Being a CompositeSurface without holes"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"cube": {
|
||||
"geometry": [
|
||||
{
|
||||
"boundaries": [
|
||||
[
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
7
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"lod": 1,
|
||||
"type": "Solid"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "being a Solid geometry cube"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"multicube": {
|
||||
"geometry": [
|
||||
{
|
||||
"boundaries": [[
|
||||
[
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
7
|
||||
]
|
||||
]
|
||||
]
|
||||
],[
|
||||
[
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
7
|
||||
]
|
||||
]
|
||||
]
|
||||
]],
|
||||
"lod": 1,
|
||||
"type": "MultiSolid"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "being a MultiSolid geometry cube that is twice the same geometry"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
},
|
||||
"compositecube": {
|
||||
"geometry": [
|
||||
{
|
||||
"boundaries": [[
|
||||
[
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
7
|
||||
]
|
||||
]
|
||||
]
|
||||
],[
|
||||
[
|
||||
[
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
7
|
||||
]
|
||||
]
|
||||
]
|
||||
]],
|
||||
"lod": 1,
|
||||
"type": "CompositeSolid"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
"function": "being a CompositeSolid geometry cube that is twice the same geometry"
|
||||
},
|
||||
"type": "GenericCityObject"
|
||||
}
|
||||
},
|
||||
"type": "CityJSON",
|
||||
"version": "1.0",
|
||||
"vertices": [
|
||||
[
|
||||
1.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
-1.0,
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
-1.0,
|
||||
1.0
|
||||
],
|
||||
[
|
||||
1.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
1.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
-1.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
-1.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
5.0,
|
||||
30,
|
||||
2.0
|
||||
],
|
||||
[
|
||||
6.0,
|
||||
-1.0,
|
||||
2.0
|
||||
],
|
||||
[
|
||||
8.0,
|
||||
7.0,
|
||||
-1.0
|
||||
]
|
||||
],
|
||||
"metadata": {
|
||||
"geographicalExtent": [
|
||||
-1.0,
|
||||
-1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -35,16 +35,50 @@ class GeometryIO:
|
||||
IFC_cartesian_point = IFC_model.create_entity("IfcCartesianPoint", IFC_vertex)
|
||||
self.vertices[tuple(coord)] = IFC_cartesian_point
|
||||
|
||||
# See for CityJSON geometries:
|
||||
# https://www.cityjson.org/dev/geom-arrays/
|
||||
# https://www.cityjson.org/specs/1.0.3/#geometry-objects
|
||||
def create_IFC_geometry(self, IFC_model, geometry):
|
||||
if geometry.type == "Solid":
|
||||
return self.create_IFC_closed_shell(IFC_model, geometry)
|
||||
elif geometry.type in ["CompositeSolid", "MultiSolid"]:
|
||||
return self.create_IFC_composite_closed_shell(IFC_model, geometry)
|
||||
IFC_Geometry = None
|
||||
geometry_type = 'brep'
|
||||
if geometry.type in ["MultiPoint"]:
|
||||
IFC_geometry = self.create_IFC_cartesian_point_list3D(IFC_model, geometry)
|
||||
geometry_type = 'PointCloud'
|
||||
elif geometry.type in ["MultiLineString"]:
|
||||
IFC_geometry = self.create_IFC_composite_curve(IFC_model, geometry)
|
||||
geometry_type = 'Curve3D'
|
||||
elif geometry.type in ["CompositeSurface", "MultiSurface"]:
|
||||
return self.create_IFC_surface(IFC_model, geometry)
|
||||
IFC_geometry = self.create_IFC_surface(IFC_model, geometry)
|
||||
elif geometry.type == "Solid":
|
||||
IFC_geometry = self.create_IFC_closed_shell(IFC_model, geometry)
|
||||
elif geometry.type in ["CompositeSolid", "MultiSolid"]:
|
||||
IFC_geometry = self.create_IFC_composite_closed_shell(IFC_model, geometry)
|
||||
elif geometry.type in ["GeometryInstance"]:
|
||||
warnings.warn("GeometryInstance is not supported.")
|
||||
return None, None
|
||||
else:
|
||||
warnings.warn("Types other than solids are not yet supported")
|
||||
return
|
||||
warnings.warn("Custom CityJSON geometries are not supported.")
|
||||
return None, None
|
||||
return IFC_geometry, geometry_type
|
||||
|
||||
def create_IFC_cartesian_point_list3D(self, IFC_model, geometry):
|
||||
# https://www.cityjson.org/dev/geom-arrays/
|
||||
# https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/schema/ifcgeometricmodelresource/lexical/ifccartesianpointlist3d.htm
|
||||
IFC_geometry = IFC_model.create_entity("IfcCartesianPointList3D", geometry.boundaries)
|
||||
return IFC_geometry
|
||||
|
||||
def create_IFC_composite_curve(self, IFC_model, geometry):
|
||||
# https://www.cityjson.org/dev/geom-arrays/
|
||||
# https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/schema/ifcgeometryresource/lexical/ifccompositecurve.htm
|
||||
# https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/schema/ifcgeometryresource/lexical/ifccompositecurvesegment.htm
|
||||
IFC_geometry = []
|
||||
for line in geometry.boundaries:
|
||||
vertices = []
|
||||
for vertex in line:
|
||||
vertices.append(self.vertices[tuple(vertex)])
|
||||
polyline = IFC_model.create_entity("IfcPolyLine", vertices)
|
||||
IFC_geometry.append(polyline)
|
||||
return IFC_geometry
|
||||
|
||||
def create_IFC_composite_closed_shell(self, IFC_model, geometry):
|
||||
shells = []
|
||||
|
||||
@@ -25,6 +25,7 @@ from cityjson2ifc import Cityjson2ifc
|
||||
if __name__ == '__main__':
|
||||
# Example:
|
||||
# python ifccityjson.py -i example/3DBAG_example.json -o example/output.ifc -n identificatie
|
||||
# python ifccityjson.py -i example/geometries.json -o example/geometry_output.ifc
|
||||
parser = argparse.ArgumentParser(description="")
|
||||
parser.add_argument("-i", "--input", type=str, help="input CityJSON file", required=True)
|
||||
parser.add_argument("-o", "--output", type=str, help="output IFC file. Standard is output.ifc")
|
||||
|
||||
Reference in New Issue
Block a user