This is possible in Processing with PGS shape boolean operations.
The approach is: for each shape, subtract the union of shapes visually above it.
l will include the algorithm given below as a method in the next version of the library (which has been WIP for some time now!).
Example
Input
[left] Circles shaded by layer (lighter = visually on top). [right] Translucent fill to reveal overlap.
Line culling
Note that some edges duplicated/overlap where shapes have been cut away from each other.
Line culling + dissolve remaining lines
Having removed any overlapping edges, we get pure linework for svg/plotting.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import micycle.pgs.PGS_Conversion;
import micycle.pgs.PGS_ShapeBoolean;
import org.locationtech.jts.dissolve.LineDissolver;
PShape cullLines(PShape shape) {
var layers = PGS_Conversion.getChildren(shape); // visual top last
Collections.reverse(layers); // visual top first
PShape union = layers.get(0); // cascading union
List<PShape> layersOut = new ArrayList<>();
layersOut.add(layers.get(0));
for (int i = 1; i < layers.size(); i++) {
// for each shape, subtract the union of shapes visually above it
var layer = PGS_ShapeBoolean.subtract(layers.get(i), union);
layersOut.add(layer);
union = PGS_ShapeBoolean.union(union, layers.get(i));
}
var culled = PGS_Conversion.fromChildren(layersOut);
var dissolved = toPShape(LineDissolver.dissolve(fromPShape(culled)));
return dissolved;
}