def test_decompose_block_reference_level_1(doc, sx, sy, sz): msp = doc.modelspace() msp.delete_all_entities() msp.add_blockref("L1", (0, 0), dxfattribs=scale(sx, sy, sz)) types = [e.dxftype() for e in recursive_decompose(msp)] assert len(types) == count(doc, ["L0", "L1"]) assert set(types) == {"LINE"}, "expected only LINES"
def multi_recursive(entities: Iterable['DXFEntity'], cache: Cache = None) -> Iterable[BoundingBox]: """ Yields all bounding boxes for the given `entities` **or** all bounding boxes for their sub entities. If an entity (INSERT) has sub entities, only the bounding boxes of these sub entities will be yielded, **not** the bounding box of entity (INSERT) itself. """ flat_entities = disassemble.recursive_decompose(entities) primitives = disassemble.to_primitives(flat_entities) for primitive in primitives: if primitive.is_empty: continue entity = primitive.entity if cache is not None: box = cache.get(entity) if box is None: box = BoundingBox(primitive.vertices()) if box.has_data: cache.store(entity, box) else: box = BoundingBox(primitive.vertices()) if box.has_data: yield box
def explode(layout: 'BaseLayout'): if EXPLODE_CONTENT: entities = list(disassemble.recursive_decompose(layout)) for e in entities: if e.dxftype() in ('ATTRIB', 'ATTDEF'): if not EXPLODE_ATTRIBS: continue e = copy_attrib_as_text(cast('BaseAttrib', e)) e = cast('DXFGraphic', e) e.dxf.layer = EXPLODE e.dxf.color = 6 layout.add_entity(e)
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 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 test_decompose_minsert_level_1(doc): nrows = 2 ncols = 2 expected_count = count(doc, ['L0', 'L1']) * nrows * ncols msp = doc.modelspace() msp.delete_all_entities() msp.add_blockref('L1', (0, 0), dxfattribs={ 'row_count': nrows, 'row_spacing': 5, 'column_count': ncols, 'column_spacing': 5, }) types = [e.dxftype() for e in recursive_decompose(msp)] assert len(types) == expected_count assert set(types) == {'LINE'}, "expected only LINES"
def test_decompose_minsert_level_1(doc): nrows = 2 ncols = 2 expected_count = count(doc, ["L0", "L1"]) * nrows * ncols msp = doc.modelspace() msp.delete_all_entities() msp.add_blockref( "L1", (0, 0), dxfattribs={ "row_count": nrows, "row_spacing": 5, "column_count": ncols, "column_spacing": 5, }, ) types = [e.dxftype() for e in recursive_decompose(msp)] assert len(types) == expected_count assert set(types) == {"LINE"}, "expected only LINES"
def multi_recursive( entities: Iterable["DXFEntity"], *, flatten: float = MAX_FLATTENING_DISTANCE, cache: Cache = None, ) -> Iterable[BoundingBox]: """Yields all bounding boxes for the given `entities` **or** all bounding boxes for their sub entities. If an entity (INSERT) has sub entities, only the bounding boxes of these sub entities will be yielded, **not** the bounding box of entity (INSERT) itself. Calculate bounding boxes from flattened curves, if argument `flatten` is not 0 (max flattening distance), else from control points. """ def vertices(p: disassemble.Primitive) -> Iterable[Vec3]: if flatten: primitive.max_flattening_distance = abs(flatten) return primitive.vertices() else: return disassemble.to_control_vertices([p]) flat_entities = disassemble.recursive_decompose(entities) primitives = disassemble.to_primitives(flat_entities) for primitive in primitives: if primitive.is_empty: continue entity = primitive.entity if cache is not None: box = cache.get(entity) if box is None: box = BoundingBox(vertices(primitive)) if box.has_data: cache.store(entity, box) else: box = BoundingBox(vertices(primitive)) if box.has_data: yield box
def multi_recursive(entities: Iterable['DXFEntity'], *, flatten: bool = True, cache: Cache = None) -> Iterable[BoundingBox]: """ Yields all bounding boxes for the given `entities` **or** all bounding boxes for their sub entities. If an entity (INSERT) has sub entities, only the bounding boxes of these sub entities will be yielded, **not** the bounding box of entity (INSERT) itself. Calculate bounding boxes from flattened curves, if argument `flatten` is ``True``, else from control points. """ def vertices(p: disassemble.Primitive) -> Iterable[Vec3]: if not flatten: return disassemble.to_control_vertices([p]) return primitive.vertices() flat_entities = disassemble.recursive_decompose(entities) primitives = disassemble.to_primitives(flat_entities) for primitive in primitives: if primitive.is_empty: continue entity = primitive.entity if cache is not None: box = cache.get(entity) if box is None: box = BoundingBox(vertices(primitive)) if box.has_data: cache.store(entity, box) else: box = BoundingBox(vertices(primitive)) if box.has_data: yield box
def test_do_nothing(): assert list(disassemble.recursive_decompose([])) == [] assert list(disassemble.to_primitives([])) == [] assert list(disassemble.to_vertices([])) == []
def test_decompose_block_level_1(doc): l1 = doc.blocks.get("L1") types = [e.dxftype() for e in recursive_decompose(l1)] assert len(types) == count(doc, ["L0", "L1"]) assert set(types) == {"LINE"}, "expected only LINES"
def test_decompose_block_reference_level_0(doc, sx, sy, sz): msp = doc.modelspace() msp.delete_all_entities() msp.add_blockref("L0", (0, 0), dxfattribs=scale(sx, sy, sz)) result = list(recursive_decompose(msp)) assert len(result) == count(doc, ["L0"])
def test_decompose_block_level_0(doc): l0 = doc.blocks.get("L0") result = list(recursive_decompose(l0)) assert len(result) == count(doc, ["L0"])
def entities(self, doc): return list(recursive_decompose(doc.modelspace()))
def test_decompose_block_level_1(doc): l1 = doc.blocks.get('L1') types = [e.dxftype() for e in recursive_decompose(l1)] assert len(types) == count(doc, ['L0', 'L1']) assert set(types) == {'LINE'}, "expected only LINES"