def update_extents(doc: "Drawing") -> BoundingBox: """Calculate the extents of the model space, update the HEADER variables $EXTMIN and $EXTMAX and returns the result as :class:`ezdxf.math.BoundingBox`. Note that this function uses the :mod:`ezdxf.bbox` module to calculate the extent of the model space. This module is not very fast and not very accurate for text and ignores all :term:`ACIS` based entities. The function updates only the values in the HEADER section, to zoom the active viewport to this extents, use this recipe:: import ezdxf from ezdxf import zoom, appsettings doc = ezdxf.readfile("your.dxf") extents = appsettings.update_extents(doc) zoom.center(doc.modelspace(), extents.center, extents.size) .. seealso:: - the :mod:`ezdxf.bbox` module to understand the limitations of the extent calculation - the :mod:`ezdxf.zoom` module """ extents = bbox.extents(doc.modelspace(), flatten=0) doc.header[EXTMIN] = extents.extmin doc.header[EXTMAX] = extents.extmax return extents
def zoom_to_entities(layout: Layout, entities: Iterable[DXFEntity], factor): if layout.is_any_paperspace: # filter main viewport main_viewport = layout.main_viewport() if main_viewport is not None: entities = (e for e in entities if e is not main_viewport) extents = bbox.extents(entities, flatten=0) if extents.has_data: center(layout, extents.center, extents.size * factor)
def test_bbox_of_main_viewport(self, psp): psp.reset_main_viewport() vp = psp.main_viewport() box = bbox.extents([vp]) assert box.has_data is True assert box.center == vp.dxf.center assert box.size.x == pytest.approx(vp.dxf.width) assert box.size.y == pytest.approx(vp.dxf.height)
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_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_extend(points1): box = bbox.extents(points1) assert box.extmin == (-1, -2, -3) assert box.extmax == (4, 5, 6)
def test_bbox_from_precise_flattening(circle): box = bbox.extents(circle, flatten=0.0001) assert box.extmin.isclose((-100, -100), abs_tol=0.0001), "expected a very close result" assert box.extmax.isclose((+100, +100), abs_tol=0.0001), "expected a very_close result"
def test_bbox_from_rough_flattening(circle): box = bbox.extents(circle, flatten=5) assert box.extmin != (-100, -100), "did not expect a precise result" assert box.extmax != (+100, +100), "did not expect a precise result"
def test_bbox_from_control_points(circle): box = bbox.extents(circle, flatten=0) assert box.extmin == (-100, -100) assert box.extmax == (+100, +100)
def get_hatches_bbox(text): hatches = text2path.make_hatches_from_entity(text) return bbox.extents(hatches, flatten=0)
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)
except ezdxf.DXFStructureError: if args.verbose: print("Regular loading function failed, using recover mode.") t_start = time.perf_counter() doc, auditor = recover.readfile(name) t_read = time.perf_counter() t_audit = t_read if auditor.has_errors and args.verbose: print(f"Found {len(auditor.errors)} unrecoverable error(s).") if auditor.has_fixes and args.verbose: print(f"Fixed {len(auditor.fixes)} error(s).") ex_run = 0 if args.extends: ex_start = time.perf_counter() extends = bbox.extents(doc.modelspace()) ex_run = time.perf_counter() - t_start if args.verbose: extmin = doc.header.get("$EXTMIN") extmax = doc.header.get("$EXTMAX") if extmin is not None: e1 = Vec3(extmin).round(3) e2 = Vec3(extmax).round(3) print(f"Header var $EXTMIN/$EXTMAX: {e1}; {e2}") if extends.has_data: e1 = extends.extmin.round(3) e2 = extends.extmax.round(3) print(f"Calculated $EXTMIN/$EXTMAX: {e1}; {e2}") if args.verbose: print("Timing: ", end="")