mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +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
|
||||
:arg margin: margins, in scene units
|
||||
: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
|
||||
size = camera.ortho_scale
|
||||
@@ -338,7 +338,11 @@ def ortho_view_frame(camera, margin=0.015):
|
||||
scale = parse_diagram_scale(camera)
|
||||
xmarg = margin * scale
|
||||
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):
|
||||
@@ -350,11 +354,11 @@ def clip_segment(bounds, segm):
|
||||
"""
|
||||
# Liang–Barsky algorithm
|
||||
|
||||
xmin, xmax, ymin, ymax = bounds
|
||||
xmin, xmax, ymin, ymax, _, _ = bounds
|
||||
p1, p2 = segm
|
||||
|
||||
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:
|
||||
return None # outside
|
||||
else:
|
||||
@@ -389,3 +393,19 @@ def clip_segment(bounds, segm):
|
||||
p2c = p1 + dlt * t2
|
||||
|
||||
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):
|
||||
proj_coll = helper.get_project_collection(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")]
|
||||
for obj in existing:
|
||||
def grep(coll):
|
||||
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)
|
||||
|
||||
source = [
|
||||
obj
|
||||
for obj in proj_coll.all_objects
|
||||
if obj.name.startswith("IfcGridAxis")
|
||||
]
|
||||
grid = [localize(*disassemble(clone(obj))) for obj in grep(proj_coll)]
|
||||
|
||||
clipping = camera.data.type == "ORTHO"
|
||||
bounds = helper.ortho_view_frame(camera.data) if clipping else None
|
||||
if clipping:
|
||||
grid = [(obj, clip(mesh)) for obj, mesh in grid]
|
||||
elif elevating:
|
||||
grid = [(obj, elev(mesh)) for obj, mesh in grid]
|
||||
|
||||
for src in source:
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(src.data)
|
||||
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)
|
||||
for obj, mesh in grid:
|
||||
if mesh is not None:
|
||||
view_coll.objects.link(assemble(obj, mesh))
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
Reference in New Issue
Block a user