mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-11 02:02:22 +00:00
7cd40bf8cb
ifcquery is a new command-line tool for querying and inspecting IFC models. All output is JSON.
Subcommands:
summary — schema version, entity counts, project metadata
tree — full spatial hierarchy (Project → Site → Building → Storeys → Spaces → Elements)
info <id> — deep inspection of any entity by step ID (attributes, psets, placement matrix, type, material)
select <query> — filter elements using ifcopenshell selector syntax
relations <id> — relationships for an element; --traverse up walks to IfcProject
clash <id> — geometric intersection and clearance detection
validate — schema/constraint validation; --rules adds EXPRESS checks
schedule — work schedules with nested task trees
cost — cost schedules with nested cost item trees
schema <class> — IFC class documentation from the model's schema version
plot — SVG plan drawing
render — 3D geometry rendering
contexts — geometric representation contexts
materials — material assignments
Usage:
python3 -m ifcquery <file.ifc> <subcommand> [args]
Generated with the assistance of an AI coding tool.
113 lines
4.4 KiB
Python
113 lines
4.4 KiB
Python
# This file was generated with the assistance of an AI coding tool.
|
|
import ifcopenshell
|
|
import ifcopenshell.api.context
|
|
import ifcopenshell.api.geometry
|
|
import ifcopenshell.api.project
|
|
import ifcopenshell.api.root
|
|
import ifcopenshell.api.unit
|
|
import ifcopenshell.util.representation
|
|
import ifcopenshell.util.shape_builder
|
|
|
|
from ifcquery.info import info
|
|
|
|
|
|
class TestInfo:
|
|
def test_basic_attributes(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = info(model, wall)
|
|
assert result["id"] == wall.id()
|
|
assert result["type"] == "IfcWall"
|
|
assert result["attributes"]["Name"] == "Wall001"
|
|
|
|
def test_container(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = info(model, wall)
|
|
assert result["container"]["type"] == "IfcBuildingStorey"
|
|
assert result["container"]["name"] == "Ground Floor"
|
|
|
|
def test_project_info(self, model):
|
|
project = model.by_type("IfcProject")[0]
|
|
result = info(model, project)
|
|
assert result["type"] == "IfcProject"
|
|
assert result["attributes"]["Name"] == "TestProject"
|
|
|
|
def test_all_attributes_serializable(self, model):
|
|
"""All attribute values should be JSON-serializable (no entity instances)."""
|
|
import json
|
|
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = info(model, wall)
|
|
# Should not raise
|
|
json.dumps(result)
|
|
|
|
def test_no_geometry_summary_without_representation(self, model):
|
|
wall = model.by_type("IfcWall")[0]
|
|
result = info(model, wall)
|
|
assert "geometry_summary" not in result
|
|
|
|
|
|
class TestGeometrySummary:
|
|
def _make_model_with_wall(self):
|
|
f = ifcopenshell.api.project.create_file()
|
|
ifcopenshell.api.root.create_entity(f, ifc_class="IfcProject")
|
|
ifcopenshell.api.unit.assign_unit(f)
|
|
model_ctx = ifcopenshell.api.context.add_context(f, context_type="Model")
|
|
ifcopenshell.api.context.add_context(
|
|
f,
|
|
context_type="Model",
|
|
context_identifier="Body",
|
|
target_view="MODEL_VIEW",
|
|
parent=model_ctx,
|
|
)
|
|
wall = ifcopenshell.api.root.create_entity(f, ifc_class="IfcWall", name="W1")
|
|
ifcopenshell.api.geometry.edit_object_placement(f, product=wall)
|
|
return f, wall
|
|
|
|
def _body_context(self, f):
|
|
return ifcopenshell.util.representation.get_context(f, "Model", "Body", "MODEL_VIEW")
|
|
|
|
def test_swept_solid_summary(self):
|
|
f, wall = self._make_model_with_wall()
|
|
body = self._body_context(f)
|
|
rep = ifcopenshell.api.geometry.add_wall_representation(f, context=body, length=5.0, height=3.0, thickness=0.2)
|
|
ifcopenshell.api.geometry.assign_representation(f, product=wall, representation=rep)
|
|
result = info(f, wall)
|
|
gs = result["geometry_summary"]
|
|
assert gs["representation_type"] == "SweptSolid"
|
|
assert len(gs["solids"]) == 1
|
|
solid = gs["solids"][0]
|
|
assert solid["depth"] == 3000.0 # stored in project units (mm)
|
|
assert solid["profile"]["type"] == "IfcArbitraryClosedProfileDef"
|
|
assert len(solid["profile"]["points"]) == 5 # closed polyline
|
|
|
|
def test_clipping_summary(self):
|
|
f, wall = self._make_model_with_wall()
|
|
body = self._body_context(f)
|
|
rep = ifcopenshell.api.geometry.add_wall_representation(
|
|
f,
|
|
context=body,
|
|
length=5.0,
|
|
height=4.0,
|
|
thickness=0.2,
|
|
clippings=[{"location": (0.0, 0.0, 3.0), "normal": (0.0, 0.0, 1.0)}],
|
|
)
|
|
ifcopenshell.api.geometry.assign_representation(f, product=wall, representation=rep)
|
|
result = info(f, wall)
|
|
gs = result["geometry_summary"]
|
|
assert gs["representation_type"] == "Clipping"
|
|
solid = gs["solids"][0]
|
|
assert len(solid["clipping_planes"]) == 1
|
|
plane = solid["clipping_planes"][0]
|
|
assert plane["location"][2] == 3000.0 # stored in project units (mm)
|
|
assert plane["normal"] == [0.0, 0.0, 1.0]
|
|
|
|
def test_geometry_summary_json_serializable(self):
|
|
import json
|
|
|
|
f, wall = self._make_model_with_wall()
|
|
body = self._body_context(f)
|
|
rep = ifcopenshell.api.geometry.add_wall_representation(f, context=body, length=5.0, height=3.0, thickness=0.2)
|
|
ifcopenshell.api.geometry.assign_representation(f, product=wall, representation=rep)
|
|
result = info(f, wall)
|
|
json.dumps(result)
|