mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
You can now specify a target view when creating a new drawing. See #1153.
This commit is contained in:
@@ -65,66 +65,14 @@ class Operator:
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class AddDrawing(bpy.types.Operator):
|
class AddDrawing(bpy.types.Operator, Operator):
|
||||||
bl_idname = "bim.add_drawing"
|
bl_idname = "bim.add_drawing"
|
||||||
bl_label = "Add Drawing"
|
bl_label = "Add Drawing"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return IfcStore.get_file()
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
return IfcStore.execute_ifc_operator(self, context)
|
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
self.file = IfcStore.get_file()
|
self.props = context.scene.DocProperties
|
||||||
drawing_name = tool.Drawing.ensure_unique_drawing_name("UNTITLED")
|
core.add_drawing(tool.Ifc, tool.Collector, tool.Drawing, target_view=self.props.target_view, location_hint=None)
|
||||||
if not bpy.data.collections.get("Views"):
|
|
||||||
context.scene.collection.children.link(bpy.data.collections.new("Views"))
|
|
||||||
views_collection = bpy.data.collections.get("Views")
|
|
||||||
view_collection = bpy.data.collections.new("IfcGroup/" + drawing_name)
|
|
||||||
views_collection.children.link(view_collection)
|
|
||||||
camera = bpy.data.objects.new(drawing_name, bpy.data.cameras.new(drawing_name))
|
|
||||||
camera.location = (0, 0, 1.5) # The view shall be 1.5m above the origin
|
|
||||||
camera.data.type = "ORTHO"
|
|
||||||
camera.data.ortho_scale = 50 # The default of 6m is too small
|
|
||||||
camera.data.clip_end = 10 # A slightly more reasonable default
|
|
||||||
if context.scene.unit_settings.system == "IMPERIAL":
|
|
||||||
camera.data.BIMCameraProperties.diagram_scale = '1/8"=1\'-0"|1/96'
|
|
||||||
else:
|
|
||||||
camera.data.BIMCameraProperties.diagram_scale = "1:100|1/100"
|
|
||||||
context.scene.camera = camera
|
|
||||||
view_collection.objects.link(camera)
|
|
||||||
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
|
|
||||||
area.spaces[0].region_3d.view_perspective = "CAMERA"
|
|
||||||
bpy.ops.bim.assign_class(obj=camera.name, ifc_class="IfcAnnotation", predefined_type="DRAWING")
|
|
||||||
bpy.ops.bim.activate_drawing_style()
|
|
||||||
|
|
||||||
bpy.ops.bim.add_group()
|
|
||||||
group = self.file.by_id(sorted(GroupData.groups.keys())[-1])
|
|
||||||
ifcopenshell.api.run("group.edit_group", self.file, **{"group": group, "attributes": {"Name": drawing_name}})
|
|
||||||
bpy.ops.bim.assign_group(product=camera.name, group=group.id())
|
|
||||||
pset = ifcopenshell.api.run(
|
|
||||||
"pset.add_pset",
|
|
||||||
self.file,
|
|
||||||
**{
|
|
||||||
"product": self.file.by_id(camera.BIMObjectProperties.ifc_definition_id),
|
|
||||||
"name": "EPset_Drawing",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
ifcopenshell.api.run(
|
|
||||||
"pset.edit_pset",
|
|
||||||
self.file,
|
|
||||||
**{
|
|
||||||
"pset": pset,
|
|
||||||
"properties": {"TargetView": "PLAN_VIEW", "Scale": "1/100"},
|
|
||||||
"pset_template": blenderbim.bim.schema.ifc.psetqto.get_by_name("EPset_Drawing"),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
PsetData.load(IfcStore.get_file(), camera.BIMObjectProperties.ifc_definition_id)
|
|
||||||
tool.Drawing.import_drawings()
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class CreateDrawing(bpy.types.Operator):
|
class CreateDrawing(bpy.types.Operator):
|
||||||
@@ -143,6 +91,7 @@ class CreateDrawing(bpy.types.Operator):
|
|||||||
camera = context.scene.camera
|
camera = context.scene.camera
|
||||||
return (
|
return (
|
||||||
IfcStore.get_file()
|
IfcStore.get_file()
|
||||||
|
and camera
|
||||||
and camera.type == "CAMERA"
|
and camera.type == "CAMERA"
|
||||||
and camera.data.type == "ORTHO"
|
and camera.data.type == "ORTHO"
|
||||||
and camera.BIMObjectProperties.ifc_definition_id
|
and camera.BIMObjectProperties.ifc_definition_id
|
||||||
|
|||||||
@@ -180,8 +180,11 @@ class BIM_PT_drawings(Panel):
|
|||||||
op.view = self.props.active_drawing.name
|
op.view = self.props.active_drawing.name
|
||||||
op = row.operator("bim.activate_view", icon="OUTLINER_OB_CAMERA", text="")
|
op = row.operator("bim.activate_view", icon="OUTLINER_OB_CAMERA", text="")
|
||||||
op.drawing = self.props.active_drawing.ifc_definition_id
|
op.drawing = self.props.active_drawing.ifc_definition_id
|
||||||
|
row.operator("bim.create_drawing", text="", icon="OUTPUT")
|
||||||
row.operator("bim.remove_drawing", icon="X", text="").index = self.props.active_drawing_index
|
row.operator("bim.remove_drawing", icon="X", text="").index = self.props.active_drawing_index
|
||||||
self.layout.template_list("BIM_UL_drawinglist", "", self.props, "drawings", self.props, "active_drawing_index")
|
self.layout.template_list(
|
||||||
|
"BIM_UL_drawinglist", "", self.props, "drawings", self.props, "active_drawing_index"
|
||||||
|
)
|
||||||
|
|
||||||
# Commented out until federated drawing generation is rebuilt
|
# Commented out until federated drawing generation is rebuilt
|
||||||
# row = self.layout.row()
|
# row = self.layout.row()
|
||||||
|
|||||||
@@ -96,3 +96,18 @@ def load_drawings(drawing):
|
|||||||
|
|
||||||
def disable_editing_drawings(drawing):
|
def disable_editing_drawings(drawing):
|
||||||
drawing.disable_editing_drawings()
|
drawing.disable_editing_drawings()
|
||||||
|
|
||||||
|
|
||||||
|
def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
|
||||||
|
drawing_name = drawing.ensure_unique_drawing_name("UNTITLED")
|
||||||
|
drawing_matrix = drawing.generate_drawing_matrix(target_view, location_hint)
|
||||||
|
camera = drawing.create_camera(drawing_name, drawing_matrix)
|
||||||
|
# Not yet refactored
|
||||||
|
element = drawing.run_assign_class_operator(obj=camera, ifc_class="IfcAnnotation", predefined_type="DRAWING")
|
||||||
|
group = ifc.run("group.add_group")
|
||||||
|
ifc.run("group.edit_group", group=group, attributes={"Name": drawing_name})
|
||||||
|
ifc.run("group.assign_group", group=group, product=element)
|
||||||
|
collector.assign(camera)
|
||||||
|
pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing")
|
||||||
|
ifc.run("pset.edit_pset", pset=pset, properties={"TargetView": target_view, "Scale": "1/100"})
|
||||||
|
drawing.import_drawings()
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ class Debug:
|
|||||||
|
|
||||||
@interface
|
@interface
|
||||||
class Drawing:
|
class Drawing:
|
||||||
|
def create_camera(cls, name, matrix): pass
|
||||||
def create_svg_sheet(cls, document, titleblock): pass
|
def create_svg_sheet(cls, document, titleblock): pass
|
||||||
def disable_editing_drawings(cls): pass
|
def disable_editing_drawings(cls): pass
|
||||||
def disable_editing_sheets(cls): pass
|
def disable_editing_sheets(cls): pass
|
||||||
@@ -144,8 +145,10 @@ class Drawing:
|
|||||||
def enable_editing_sheets(cls): pass
|
def enable_editing_sheets(cls): pass
|
||||||
def enable_editing_text(cls, obj): pass
|
def enable_editing_text(cls, obj): pass
|
||||||
def enable_editing_text_product(cls, obj): pass
|
def enable_editing_text_product(cls, obj): pass
|
||||||
|
def ensure_unique_drawing_name(cls, name): pass
|
||||||
def ensure_unique_identification(cls, identification): pass
|
def ensure_unique_identification(cls, identification): pass
|
||||||
def export_text_literal_attributes(cls, obj): pass
|
def export_text_literal_attributes(cls, obj): pass
|
||||||
|
def generate_drawing_matrix(cls, target_view, location_hint): pass
|
||||||
def generate_sheet_identification(cls): pass
|
def generate_sheet_identification(cls): pass
|
||||||
def get_sheet_filename(cls, document): pass
|
def get_sheet_filename(cls, document): pass
|
||||||
def get_text_literal(cls, obj): pass
|
def get_text_literal(cls, obj): pass
|
||||||
@@ -155,6 +158,7 @@ class Drawing:
|
|||||||
def import_text_attributes(cls, obj): pass
|
def import_text_attributes(cls, obj): pass
|
||||||
def import_text_product(cls, obj): pass
|
def import_text_product(cls, obj): pass
|
||||||
def open_svg(cls, filepath): pass
|
def open_svg(cls, filepath): pass
|
||||||
|
def run_assign_class_operator(cls, obj=None, ifc_class=None, predefined_type=None): pass
|
||||||
def update_text_value(cls, obj): pass
|
def update_text_value(cls, obj): pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import bpy
|
import bpy
|
||||||
|
import mathutils
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
@@ -27,6 +28,21 @@ import blenderbim.bim.module.drawing.sheeter as sheeter
|
|||||||
|
|
||||||
|
|
||||||
class Drawing(blenderbim.core.tool.Drawing):
|
class Drawing(blenderbim.core.tool.Drawing):
|
||||||
|
@classmethod
|
||||||
|
def create_camera(cls, name, matrix):
|
||||||
|
camera = bpy.data.objects.new(name, bpy.data.cameras.new(name))
|
||||||
|
camera.location = (0, 0, 1.5) # The view shall be 1.5m above the origin
|
||||||
|
camera.data.type = "ORTHO"
|
||||||
|
camera.data.ortho_scale = 50 # The default of 6m is too small
|
||||||
|
camera.data.clip_end = 10 # A slightly more reasonable default
|
||||||
|
if bpy.context.scene.unit_settings.system == "IMPERIAL":
|
||||||
|
camera.data.BIMCameraProperties.diagram_scale = '1/8"=1\'-0"|1/96'
|
||||||
|
else:
|
||||||
|
camera.data.BIMCameraProperties.diagram_scale = "1:100|1/100"
|
||||||
|
camera.matrix_world = matrix
|
||||||
|
bpy.context.scene.collection.objects.link(camera)
|
||||||
|
return camera
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_svg_sheet(cls, document, titleblock):
|
def create_svg_sheet(cls, document, titleblock):
|
||||||
sheet_builder = sheeter.SheetBuilder()
|
sheet_builder = sheeter.SheetBuilder()
|
||||||
@@ -97,6 +113,10 @@ class Drawing(blenderbim.core.tool.Drawing):
|
|||||||
name += " - " + document.Name or "Unnamed"
|
name += " - " + document.Name or "Unnamed"
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_drawing_matrix(cls, target_view, location_hint):
|
||||||
|
return mathutils.Matrix()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_sheet_identification(cls):
|
def generate_sheet_identification(cls):
|
||||||
number = len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "DOCUMENTATION"])
|
number = len([d for d in tool.Ifc.get().by_type("IfcDocumentInformation") if d.Scope == "DOCUMENTATION"])
|
||||||
@@ -174,6 +194,11 @@ class Drawing(blenderbim.core.tool.Drawing):
|
|||||||
os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", filename + ".svg"),
|
os.path.join(bpy.context.scene.BIMProperties.data_dir, "sheets", filename + ".svg"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run_assign_class_operator(cls, obj=None, ifc_class=None, predefined_type=None):
|
||||||
|
bpy.ops.bim.assign_class(obj=obj.name, ifc_class=ifc_class, predefined_type=predefined_type)
|
||||||
|
return tool.Ifc.get_entity(obj)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_text_value(cls, obj):
|
def update_text_value(cls, obj):
|
||||||
element = cls.get_text_literal(obj)
|
element = cls.get_text_literal(obj)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import blenderbim.core.drawing as subject
|
import blenderbim.core.drawing as subject
|
||||||
from test.core.bootstrap import ifc, drawing
|
from test.core.bootstrap import ifc, drawing, collector
|
||||||
|
|
||||||
|
|
||||||
class TestEnableEditingText:
|
class TestEnableEditingText:
|
||||||
@@ -137,3 +137,23 @@ class TestDisableEditingDrawings:
|
|||||||
def test_run(self, drawing):
|
def test_run(self, drawing):
|
||||||
drawing.disable_editing_drawings().should_be_called()
|
drawing.disable_editing_drawings().should_be_called()
|
||||||
subject.disable_editing_drawings(drawing)
|
subject.disable_editing_drawings(drawing)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddDrawing:
|
||||||
|
def test_run(self, ifc, collector, drawing):
|
||||||
|
drawing.ensure_unique_drawing_name("UNTITLED").should_be_called().will_return("name")
|
||||||
|
drawing.generate_drawing_matrix("target_view", "location_hint").should_be_called().will_return("matrix")
|
||||||
|
drawing.create_camera("name", "matrix").should_be_called().will_return("obj")
|
||||||
|
drawing.run_assign_class_operator(
|
||||||
|
obj="obj", ifc_class="IfcAnnotation", predefined_type="DRAWING"
|
||||||
|
).should_be_called().will_return("element")
|
||||||
|
ifc.run("group.add_group").should_be_called().will_return("group")
|
||||||
|
ifc.run("group.edit_group", group="group", attributes={"Name": "name"}).should_be_called()
|
||||||
|
ifc.run("group.assign_group", group="group", product="element").should_be_called()
|
||||||
|
collector.assign("obj").should_be_called()
|
||||||
|
ifc.run("pset.add_pset", product="element", name="EPset_Drawing").should_be_called().will_return("pset")
|
||||||
|
ifc.run(
|
||||||
|
"pset.edit_pset", pset="pset", properties={"TargetView": "target_view", "Scale": "1/100"}
|
||||||
|
).should_be_called()
|
||||||
|
drawing.import_drawings().should_be_called()
|
||||||
|
subject.add_drawing(ifc, collector, drawing, target_view="target_view", location_hint="location_hint")
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
|
import mathutils
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import blenderbim.core.tool
|
import blenderbim.core.tool
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
@@ -30,6 +31,17 @@ class TestImplementsTool(NewFile):
|
|||||||
assert isinstance(subject(), blenderbim.core.tool.Drawing)
|
assert isinstance(subject(), blenderbim.core.tool.Drawing)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateCamera(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
obj = subject.create_camera("Name", mathutils.Matrix())
|
||||||
|
assert obj.name == "Name"
|
||||||
|
assert obj.matrix_world == mathutils.Matrix()
|
||||||
|
assert obj.data.type == "ORTHO"
|
||||||
|
assert obj.data.ortho_scale == 50
|
||||||
|
assert obj.data.clip_end == 10
|
||||||
|
assert obj.users_collection[0] == bpy.context.scene.collection
|
||||||
|
|
||||||
|
|
||||||
class TestCreateSvgSheet(NewFile):
|
class TestCreateSvgSheet(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -149,6 +161,11 @@ class TestGetSheetFilename(NewFile):
|
|||||||
subject.get_sheet_filename(document) == "X - FOOBAR"
|
subject.get_sheet_filename(document) == "X - FOOBAR"
|
||||||
|
|
||||||
|
|
||||||
|
class TestGenerateDrawingMatrix(NewFile):
|
||||||
|
def test_returning_the_origin_as_a_fallback(self):
|
||||||
|
assert subject.generate_drawing_matrix("PLAN_VIEW", None) == mathutils.Matrix()
|
||||||
|
|
||||||
|
|
||||||
class TestGenerateSheetIdentification(NewFile):
|
class TestGenerateSheetIdentification(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
@@ -266,6 +283,11 @@ class TestOpenSvg(NewFile):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TestRunAssignClassOperator(NewFile):
|
||||||
|
def test_nothing(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestUpdateTextValue(NewFile):
|
class TestUpdateTextValue(NewFile):
|
||||||
def test_updating_arbitrary_strings(self):
|
def test_updating_arbitrary_strings(self):
|
||||||
TestGetTextLiteral().test_run()
|
TestGetTextLiteral().test_run()
|
||||||
|
|||||||
Reference in New Issue
Block a user