Input data format:
obj_1 = [(x1, y1, z1, x2, y2, z2), (...),...]
obj_2 = [(x1, y1, z1, x2, y2, z2), (...),...]
etc.
The task is to find a way to create new objects under old ones according to the order in which the creation function is called. In this case, we start by creating a obj_1, then a obj_2, which will hide under the obj_1. Then the obj_3 is created, and consequently this object is hidden under the first and second objects.
Desired output data - coordinates of all lines for drawing the drawing
Maybe i need to use the shapely library, but I'm not sure.
The shape of an object can be absolutely any, so it is not quite correct to write code based only on circles, triangles and lines.
from itertools import chain
from matplotlib import pyplot as plt
from more_itertools import batched
from shapely import Point, LineString, Polygon, MultiPoint, MultiLineString
from shapely.plotting import plot_polygon, plot_line, plot_points
Declare objects like in file given by OP:
obj_1 = [(0.3931383333340818, 1.1771275460626884, 0.0,
Parsing data into shapely objects:
shapely_objects = []
for obj in chain(obj_3, obj_1, obj_2):
n = len(obj) / 3
if n == 0:
continue
elif n == 1:
geom = Point(obj[0])
else:
data = list(batched(obj, 3, strict=True))
geom = LineString(data)
if geom.is_ring:
geom = Polygon(data)
shapely_objects.append(geom)
Actual processing:
def overlay(geometries: Iterable[BaseGeometry]):
"""
Overlay shapely geometries: cut away the part of shapes that are underneath others.
First features in input will be underneath, last feature will not be cut.
"""
result = []
s = set()
tree = STRtree(geometries)
for idx, current_feature in enumerate(geometries):
s.add(idx)
overlapping_features = tree.geometries.take(list(set(tree.query(current_feature)) - s))
cut = current_feature.difference(unary_union(overlapping_features))
result.append(cut)
return result
shapes_overlain = overlay(shapely_objects)
Visualization:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharex=True, sharey=True)
for shape in shapely_objects:
if isinstance(shape, Polygon):
plot_polygon(shape, color="w", add_points=False, ax=ax1)
elif isinstance(shape, LineString):
plot_line(shape, color="w", add_points=False, ax=ax1)
else:
plot_points(shape, color="w", add_points=False, ax=ax1)
for shape in shapes_overlain:
if isinstance(shape, Polygon):
plot_polygon(shape, color="w", add_points=False, ax=ax2)
elif isinstance(shape, (MultiLineString, LineString)):
plot_line(shape, color="w", add_points=False, ax=ax2)
elif isinstance(shape, (Point, MultiPoint)):
plot_points(shape, color="w", add_points=False, ax=ax2)
else:
raise ValueError(f"shape: {shape}")
ax1.set(facecolor="#242c34", xticks=[], yticks=[])
ax2.set(facecolor="#242c34", xticks=[], yticks=[])
ax1.set_title("Normal")
ax2.set_title("Overlain")
plt.show()