0

给定一个 DXF 文件(2D CAD 绘图),是否有可能只光栅化其中的一部分?最好在 Python 的ezdxf. 它的一部分,我的意思是选定的矩形区域,而不是单层。

背景:我正在努力在合理的时间内对相当大的 DXF 文件进行光栅化,并且 DPI 不错,所以我认为也许有一种方法可以通过并行光栅化绘图的不同部分来加快处理速度。我正在使用ezdxf后端matplotlib

4

1 回答 1

1

此解决方案在 4 个图块中渲染 DXF 文件,包括过滤渲染区域外的 DXF 实体。但是边界框的计算成本也很高,重叠区域的实体会被多次渲染,这意味着这种解决方案作为单次渲染需要更长的时间。但它显示了这个概念。这些图像完美地融合在一起,留下的空间显示这是 4 张图像:

4个瓷砖并排

import matplotlib.pyplot as plt
import random

import ezdxf
from ezdxf.addons.drawing import RenderContext, Frontend
from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
from ezdxf import bbox
from ezdxf.math import BoundingBox2d

COLORS = list(range(1, 7))
DPI = 300
WIDTH = 400
HEIGHT = 200
LEFT = 0
BOTTOM = 0

doc = ezdxf.new()
msp = doc.modelspace()


def random_points(count):
    for _ in range(count):
        yield WIDTH * random.random(), HEIGHT * random.random()


for s, e in zip(random_points(100), random_points(100)):
    msp.add_line(s, e, dxfattribs={"color": random.choice(COLORS)})

# detecting the drawing extents by ezdxf can take along time for big files!
cache = bbox.Cache()  # reuse bounding boxes for entity filtering
rect = bbox.extents(msp, cache=cache)
WIDTH = rect.size.x
HEIGHT = rect.size.y
LEFT = rect.extmin.x
BOTTOM = rect.extmin.y


VIEWPORT_X = [LEFT, LEFT + WIDTH / 2, LEFT, LEFT + WIDTH / 2]
VIEWPORT_Y = [BOTTOM, BOTTOM, BOTTOM + HEIGHT / 2, BOTTOM + HEIGHT / 2]

ctx = RenderContext(doc)
for quarter in [0, 1, 2, 3]:
    # setup drawing add-on:
    fig = plt.figure(dpi=300)
    ax = fig.add_axes([0, 0, 1, 1])
    out = MatplotlibBackend(ax)

    # calculate and set render borders:
    left = VIEWPORT_X[quarter]
    bottom = VIEWPORT_Y[quarter]
    ax.set_xlim(left, left + WIDTH / 2)
    ax.set_ylim(bottom, bottom + HEIGHT / 2)

    # set entities outside of the rendering area invisible:
    # Bounding box calculation can be very costly, especially for deep nested
    # block references! If you did the extents calculation and reuse the cache
    # you already have paid the price:
    render_area = BoundingBox2d(
        [(left, bottom), (left + WIDTH / 2, bottom + HEIGHT / 2)])

    for entity in msp:
        entity_bbox = bbox.extents([entity], cache=cache)
        if render_area.intersect(entity_bbox):
            entity.dxf.invisible = 0
        else:
            entity.dxf.invisible = 1

    # finalizing invokes auto-scaling!
    Frontend(ctx, out).draw_layout(msp, finalize=False)

    # set output size in inches
    # width = 6 in x 300 dpi = 1800 px
    # height = 3 in x 300 dpi = 900 px
    fig.set_size_inches(6, 3, forward=True)

    filename = f"lines{quarter}.png"
    print(f'saving to "{filename}"')
    fig.savefig(filename, dpi=300)
    plt.close(fig)

draw_layout()方法有一个参数filter_func来指定一个函数,该函数接受一个 DXF 实体作为参数并返回TrueFalse呈现或忽略该实体。这将是在不改变 DXF 内容的情况下过滤渲染区域之外的实体的替代方法。

更新:可以在github上找到一个精致的示例

于 2022-02-02T15:49:05.290 回答