mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-31 17:06:29 +00:00
close #1232 elevating grid in section views
This commit is contained in:
@@ -329,7 +329,7 @@ def ortho_view_frame(camera, margin=0.015):
|
|||||||
:type camera: bpy.types.Camera + BIMCameraProperties
|
:type camera: bpy.types.Camera + BIMCameraProperties
|
||||||
:arg margin: margins, in scene units
|
:arg margin: margins, in scene units
|
||||||
:type margin: float
|
:type margin: float
|
||||||
:return: (xmin, xmax, ymin, ymax) in local camera coordinates
|
:return: (xmin, xmax, ymin, ymax, zmin, zmax) in local camera coordinates
|
||||||
"""
|
"""
|
||||||
aspect = camera.BIMCameraProperties.raster_y / camera.BIMCameraProperties.raster_x
|
aspect = camera.BIMCameraProperties.raster_y / camera.BIMCameraProperties.raster_x
|
||||||
size = camera.ortho_scale
|
size = camera.ortho_scale
|
||||||
@@ -338,7 +338,11 @@ def ortho_view_frame(camera, margin=0.015):
|
|||||||
scale = parse_diagram_scale(camera)
|
scale = parse_diagram_scale(camera)
|
||||||
xmarg = margin * scale
|
xmarg = margin * scale
|
||||||
ymarg = margin * scale * aspect
|
ymarg = margin * scale * aspect
|
||||||
return (-hwidth + xmarg, hwidth - xmarg, -hheight + ymarg, hheight - ymarg)
|
return (-hwidth + xmarg, hwidth - xmarg, -hheight + ymarg, hheight - ymarg, -camera.clip_start, -camera.clip_end)
|
||||||
|
|
||||||
|
|
||||||
|
def almost_zero(v):
|
||||||
|
return abs(v) < 1e-5
|
||||||
|
|
||||||
|
|
||||||
def clip_segment(bounds, segm):
|
def clip_segment(bounds, segm):
|
||||||
@@ -350,11 +354,11 @@ def clip_segment(bounds, segm):
|
|||||||
"""
|
"""
|
||||||
# Liang–Barsky algorithm
|
# Liang–Barsky algorithm
|
||||||
|
|
||||||
xmin, xmax, ymin, ymax = bounds
|
xmin, xmax, ymin, ymax, _, _ = bounds
|
||||||
p1, p2 = segm
|
p1, p2 = segm
|
||||||
|
|
||||||
def clip_side(p, q):
|
def clip_side(p, q):
|
||||||
if abs(p) < 1e-10: # ~= 0, parallel to the side
|
if almost_zero(p): # ~= 0, parallel to the side
|
||||||
if q < 0:
|
if q < 0:
|
||||||
return None # outside
|
return None # outside
|
||||||
else:
|
else:
|
||||||
@@ -389,3 +393,19 @@ def clip_segment(bounds, segm):
|
|||||||
p2c = p1 + dlt * t2
|
p2c = p1 + dlt * t2
|
||||||
|
|
||||||
return p1c, p2c
|
return p1c, p2c
|
||||||
|
|
||||||
|
|
||||||
|
def elevate_segment(bounds, segm):
|
||||||
|
"""Elevate line xy-perpendicular segment vertically
|
||||||
|
|
||||||
|
:arg bounds: (xmin, xmax, ymin, ymax)
|
||||||
|
:arg segm: 2 vertices of the segment
|
||||||
|
:return: 2 new vertices of segment or None if segment outside the bounding box
|
||||||
|
"""
|
||||||
|
_, _, ymin, ymax, zmin, _ = bounds
|
||||||
|
p1, p2 = segm
|
||||||
|
dlt = p2 - p1
|
||||||
|
if not (almost_zero(dlt.x) and almost_zero(dlt.y)):
|
||||||
|
return None
|
||||||
|
x = p1.x
|
||||||
|
return [Vector((x, ymin, zmin)), Vector((x, ymax, zmin))]
|
||||||
|
|||||||
@@ -3759,45 +3759,74 @@ class CopyGrid(bpy.types.Operator):
|
|||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
proj_coll = helper.get_project_collection(context.scene)
|
proj_coll = helper.get_project_collection(context.scene)
|
||||||
view_coll, camera = helper.get_active_drawing(context.scene)
|
view_coll, camera = helper.get_active_drawing(context.scene)
|
||||||
|
if view_coll is None:
|
||||||
|
return {'CANCELLED'}
|
||||||
|
is_ortho = camera.data.type == "ORTHO"
|
||||||
|
bounds = helper.ortho_view_frame(camera.data) if is_ortho else None
|
||||||
|
clipping = is_ortho and camera.data.BIMCameraProperties.target_view in ('PLAN_VIEW', 'REFLECTED_PLAN_VIEW')
|
||||||
|
elevating = is_ortho and camera.data.BIMCameraProperties.target_view in ('ELEVATION_VIEW', 'SECTION_VIEW')
|
||||||
|
|
||||||
existing = [obj for obj in view_coll.objects if obj.name.startswith("IfcGridAxis")]
|
def grep(coll):
|
||||||
for obj in existing:
|
return [obj for obj in coll.all_objects if obj.name.startswith("IfcGridAxis")]
|
||||||
|
|
||||||
|
def clone(src):
|
||||||
|
dst = src.copy()
|
||||||
|
dst.data = dst.data.copy()
|
||||||
|
return dst
|
||||||
|
|
||||||
|
def disassemble(obj):
|
||||||
|
mesh = bmesh.new()
|
||||||
|
mesh.verts.ensure_lookup_table()
|
||||||
|
mesh.from_mesh(obj.data)
|
||||||
|
return obj, mesh
|
||||||
|
|
||||||
|
def assemble(obj, mesh):
|
||||||
|
mesh.to_mesh(obj.data)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def localize(obj, mesh):
|
||||||
|
# convert to camera coords
|
||||||
|
mesh.transform(camera.matrix_world.inverted() @ obj.matrix_world)
|
||||||
|
obj.matrix_world = camera.matrix_world
|
||||||
|
return obj, mesh
|
||||||
|
|
||||||
|
def clip(mesh):
|
||||||
|
# clip segment against camera view bounds
|
||||||
|
mesh.verts.ensure_lookup_table()
|
||||||
|
points = [v.co for v in mesh.verts[0:2]]
|
||||||
|
points = helper.clip_segment(bounds, points)
|
||||||
|
if points is None:
|
||||||
|
return None
|
||||||
|
mesh.verts[0].co = points[0]
|
||||||
|
mesh.verts[1].co = points[1]
|
||||||
|
return mesh
|
||||||
|
|
||||||
|
def elev(mesh):
|
||||||
|
# put camera-perpendicular segments vertically
|
||||||
|
mesh.verts.ensure_lookup_table()
|
||||||
|
points = [v.co for v in mesh.verts[0:2]]
|
||||||
|
points = helper.elevate_segment(bounds, points)
|
||||||
|
if points is None:
|
||||||
|
return None
|
||||||
|
points = helper.clip_segment(bounds, points)
|
||||||
|
if points is None:
|
||||||
|
return None
|
||||||
|
mesh.verts[0].co = points[0]
|
||||||
|
mesh.verts[1].co = points[1]
|
||||||
|
return mesh
|
||||||
|
|
||||||
|
for obj in grep(view_coll):
|
||||||
view_coll.objects.unlink(obj)
|
view_coll.objects.unlink(obj)
|
||||||
|
|
||||||
source = [
|
grid = [localize(*disassemble(clone(obj))) for obj in grep(proj_coll)]
|
||||||
obj
|
|
||||||
for obj in proj_coll.all_objects
|
|
||||||
if obj.name.startswith("IfcGridAxis")
|
|
||||||
]
|
|
||||||
|
|
||||||
clipping = camera.data.type == "ORTHO"
|
if clipping:
|
||||||
bounds = helper.ortho_view_frame(camera.data) if clipping else None
|
grid = [(obj, clip(mesh)) for obj, mesh in grid]
|
||||||
|
elif elevating:
|
||||||
|
grid = [(obj, elev(mesh)) for obj, mesh in grid]
|
||||||
|
|
||||||
for src in source:
|
for obj, mesh in grid:
|
||||||
bm = bmesh.new()
|
if mesh is not None:
|
||||||
bm.from_mesh(src.data)
|
view_coll.objects.link(assemble(obj, mesh))
|
||||||
bm.verts.ensure_lookup_table()
|
|
||||||
|
|
||||||
if clipping:
|
|
||||||
proj = src.matrix_world @ camera.matrix_world.inverted()
|
|
||||||
unproj = src.matrix_world.inverted() @ camera.matrix_world
|
|
||||||
|
|
||||||
bm.transform(proj)
|
|
||||||
|
|
||||||
points_orig = [v.co for v in bm.verts[0:2]]
|
|
||||||
points_clip = helper.clip_segment(bounds, points_orig)
|
|
||||||
|
|
||||||
if points_clip is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
bm.verts[0].co = points_clip[0]
|
|
||||||
bm.verts[1].co = points_clip[1]
|
|
||||||
|
|
||||||
bm.transform(unproj)
|
|
||||||
|
|
||||||
dst = src.copy()
|
|
||||||
dst.data = bpy.data.meshes.new(dst.name)
|
|
||||||
bm.to_mesh(dst.data)
|
|
||||||
view_coll.objects.link(dst)
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|||||||
Reference in New Issue
Block a user