def occult( document: vpype.Document, tolerance: float, layer: Optional[Union[int, List[int]]], keep_occulted: bool = False, ) -> vpype.Document: """ Remove lines occulted by polygons. The 'keep_occulted' option (-k, --keep-occulted) saves removed geometries in a new layer. The order of the geometries in 'lines' matters, see basic example below. Occlusion is performed layer by layer. This means that if one geometry is occulting another, and these geometries are not in the same layer, occult won't remove occulted paths. Args: document: the vpype.Document to work on. tolerance: controls the distance tolerance between the first and last points of a geometry to consider it closed. layer: specify which layer(s) to work on. Default: all. keep_occulted: If set, this flag allows to save removed lines in a separate layer. Examples: - Basic usage: $ vpype line 0 0 5cm 5cm rect 2cm 2cm 1cm 1cm occult show # line is occulted by rect $ vpype rect 2cm 2cm 1cm 1cm line 0 0 5cm 5cm occult show # line is NOT occulted by rect, as the line is drawn after the rectangle. - Keep occulted lines in a separate layer: $ vpype line -- -3cm 0 8cm 0 circle 0 0 3cm circle -l 2 5cm 0 3cm occult -k show # 'occult -k' will remove the path inside the first circle, and put it in a third layer. # both the first circle and the line are not affected by the second circle, as it is # in a different layer. """ new_document = document.empty_copy() layer_ids = multiple_to_layer_ids(layer, document) removed_layer_id = document.free_id() for lines, l_id in zip(document.layers_from_ids(layer_ids), layer_ids): lines, removed_lines = _occult_layer(lines, tolerance, keep_occulted) new_document.add(lines, layer_id=l_id) if keep_occulted and not removed_lines.is_empty(): new_document.add(removed_lines, layer_id=removed_layer_id) return new_document
def occult( document: vpype.Document, tolerance: float, layer: Optional[Union[int, List[int]]], keep_occulted: bool = False, ignore_layers: bool = False, reverse: bool = False, ) -> vpype.Document: """ Remove lines occulted by polygons. The 'keep_occulted' option (-k, --keep-occulted) saves removed geometries in a new layer. The order of the geometries in 'lines' matters, see basic example below. Occlusion is performed layer by layer. This means that if one geometry is occulting another, and these geometries are not in the same layer, occult won't remove occulted paths. With the 'ignore_layers' option, occlusion is performed on all geometry regardless of layers, with higher-numbered layers occluding lower-numbered layers. Args: document: the vpype.Document to work on. tolerance: controls the distance tolerance between the first and last points of a geometry to consider it closed. layer: specify which layer(s) to work on. Default: all. keep_occulted: If set, this flag allows to save removed lines in a separate layer. ignore_layers: If set, this flag causes occult to treat all geometries as if they exist on the same layer. However, all geometries in the final result remain on their original layer. Examples: - Basic usage: $ vpype line 0 0 5cm 5cm rect 2cm 2cm 1cm 1cm occult show # line is occulted by rect $ vpype rect 2cm 2cm 1cm 1cm line 0 0 5cm 5cm occult show # line is NOT occulted by rect, as the line is drawn after the rectangle. - Keep occulted lines in a separate layer: $ vpype line -- -3cm 0 8cm 0 circle 0 0 3cm circle -l 2 5cm 0 3cm occult -k show # 'occult -k' will remove the path inside the first circle, and put it in a third layer. # both the first circle and the line are not affected by the second circle, as it is # in a different layer. """ new_document = document.empty_copy() layer_ids = multiple_to_layer_ids(layer, document) removed_layer_id = document.free_id() if ignore_layers: layers = [{ l_id: list(document.layers_from_ids([l_id]))[0] for l_id in layer_ids }] else: layers = [{ l_id: list(document.layers_from_ids([l_id]))[0] } for l_id in layer_ids] if reverse: for layer in layers: for key in layer: layer[key].reverse() for layer in layers: lines, removed_lines = _occult_layer(layer, tolerance, keep_occulted) for l_id, occulted_lines in lines.items(): new_document.add(occulted_lines, layer_id=l_id) if keep_occulted and not removed_lines.is_empty(): new_document.add(removed_lines, layer_id=removed_layer_id) return new_document