def test_cache_usage_for_flat_multi_boxes(msp_solids, func): cache = bbox.Cache() for _ in range(10): list(func(msp_solids, cache=cache)) # This works because flat processing has not to yield bounding boxes for # sub entities, caching top level bounding boxes works well. assert cache.misses == 2 + 2 # first 2xINSERT, 2xSOLID in INSERT assert cache.hits == 9 * 2 # 9 x 2xINSERT
def test_cache_usage_for_recreation_on_the_fly(msp_solids): cache = bbox.Cache(uuid=True) for _ in range(10): list(bbox.multi_recursive(msp_solids, cache=cache)) # This does not work well, because recursive processing has to yield the # bounding boxes for all sub entities. These sub entities are created on the # fly for every call and do not have a handle and always gets a new UUID, # which is the meaning of an UUID. # The INSERT entity, which has a handle, gets no own bounding box and is # therefore not cached. assert cache.misses == 20 assert cache.hits == 0
def test_cache_usage_with_uuids_for_reused_virtual_entities(msp_solids, func): cache = bbox.Cache(uuid=True) # Create flat entity structure by yourself, so that virtual entities are # only created once: entities = list(disassemble.recursive_decompose(msp_solids)) for _ in range(10): list(func(entities, cache=cache)) # This works, because virtual entities are cached by UUID # multi_flat and extents, have a second access stage: 2x2 misses, but # triggers only 2 bounding box calculations. # multi_recursive is the lowest level and has only 2 cache misses. assert cache.misses in (2, 4) assert cache.hits == 18
def main(rows: int, cols: int): doc = ezdxf.new() msp = doc.modelspace() create_content(msp) # Detecting the drawing extents by ezdxf: # The bounding box cache can be reused for entity filtering. # This cache is a lightweight object, which is compatible to the pickle # module, DXF entities are referenced by handle strings. (multiprocessing!) cache = bbox.Cache() # The bounding box calculation can take along time for big DXF files! # If flatten=0 the bounding box calculation for curves (SPLINE, ELLIPSE, ...) # is based on the control points of the Path class, this is less precise but # can speed up the calculation and for this task is a precise bounding box # not required. # This has no impact on this example which uses only straight lines extents = bbox.extents(msp, cache=cache, flatten=0) ctx = RenderContext(doc) for tile, render_area in enumerate(render_areas(extents, (rows, cols))): # Setup drawing add-on: fig = plt.figure(dpi=DPI) ax = fig.add_axes([0, 0, 1, 1]) out = MatplotlibBackend(ax) ax.set_xlim(render_area.extmin.x, render_area.extmax.x) ax.set_ylim(render_area.extmin.y, render_area.extmax.y) # Disable rendering of entities outside of the render area: def is_intersecting_render_area(entity): """Returns True if entity should be rendered. """ entity_bbox = bbox.extents([entity], cache=cache, flatten=0) return render_area.has_intersection(entity_bbox) # Finalizing invokes auto-scaling! Frontend(ctx, out).draw_layout(msp, finalize=False, filter_func=is_intersecting_render_area) # Set output size in inches: # width = 6 inch x 300 dpi = 1800 px # height = 3 inch x 300 dpi = 900 px fig.set_size_inches(6, 3, forward=True) filename = f"tile-{tile:02d}.png" print(f'saving tile #{tile} to "{filename}"') fig.savefig(DIR / filename, dpi=DPI) plt.close(fig)
def test_cache_usage_for_reused_virtual_entities(msp_solids, func): cache = bbox.Cache() # Create flat entity structure by yourself, so that virtual entities are # only created once: entities = list(disassemble.recursive_decompose(msp_solids)) for _ in range(10): list(func(entities, cache=cache)) # This does not work well by "handle only" usage, because 'entities' contains # virtual entities which have no handle and therefore are not cached: # multi_flat and extents, have a second access stage and triggers 2x20 cache # misses but this is just a cache access issue, this does not trigger 40 # bounding box calculations! # multi_recursive is the lowest level and has only 20 cache misses. assert cache.misses in (20, 40) # virtual entities do not have handles assert cache.hits == 0 # parent INSERT bbox is not calculated and cached
def merge_dxfs(listname, seplayer=False, shifth=0, shiftv=0): n = -1 tx = 10 ty = 0 for filename in listname: n = n + 1 merge_dxf = ezdxf.readfile(filename) print("file : " + filename) #print("header : ", merge_dxf.header) #print("EXTMAX ", merge_dxf.header['$EXTMAX']) #print("EXTMIN ", merge_dxf.header['$EXTMIN']) #print("LIMMAX ", merge_dxf.header['$LIMMAX']) #print("LIMMIN ", merge_dxf.header['$LIMMIN']) if seplayer: nl = 'L' + chr(ord('A') + n) np = 'P' + chr(ord('A') + n) rename_layer(merge_dxf, '0', nl) rename_layer(merge_dxf, 'Defpoints', np) if shifth > 0 or shiftv > 0: msp = merge_dxf.modelspace() cache = bbox.Cache() bounds = bbox.extends(msp, cache) minpt = bounds.extmin s = bounds.size print("bbox : ", bounds) print(" min : ", minpt) print(" s : ", s) dx = tx - minpt[0] dy = ty - minpt[1] print("dx = ", dx, " dy = ", dy) #translation_x_y(merge_dxf, n*500, n*100) translation_x_y(merge_dxf, dx, dy) if shifth > 0: tx = tx + s[0] + shifth if shiftv > 0: ty = ty + s[1] + shiftv if n > 0: merge(merge_dxf, base_dxf) else: base_dxf = merge_dxf return base_dxf
def test_cache_usage_with_uuids(points1): # Entities in VirtualLayouts have no handles: cache = bbox.Cache(uuid=True) for _ in range(10): bbox.extents(points1, cache=cache) assert cache.hits == 18
def test_cache_usage_without_handles(points1): # Entities in VirtualLayouts have no handles: cache = bbox.Cache() for _ in range(10): bbox.extends(points1, cache) assert cache.hits == 0