close #1232 elevating grid in section views

This commit is contained in:
QwiglyDee
2021-01-12 07:48:18 +07:00
parent 6502b2c18d
commit d1a2a12e94
2 changed files with 88 additions and 39 deletions
+24 -4
View File
@@ -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):
"""
# LiangBarsky 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))]
+64 -35
View File
@@ -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"}