Hi,

I looked for some existing code in Geomery to cut my polygon with the player's tail in a Qix / Gals panic like game I'm working on:

But as far I understand there's no such method exposed.

So I coded my own:

`start_edge` and `end_edge` are index of the point in the polygon representing the playground (white square on the screenshot above). In this case `start_edge` = 2, `end_edge` = 1

`PolygonIterator` is a class with a little magic for looping on the edge in the polygon array of point, which on a given size known when to go through the end of the Array and restart at the beginning.

``````func cut(tail, start_edge, end_edge):
var pol1 : Array = tail.points

# process of linking the 2 polygons:
# pol1
# 1. all the tail points
# 2. the area points from where the tail ends in clockwise order throught
#    where the tail starts

if is_on_corner(pol1[0], start_edge):
start_edge = prev_corner(start_edge)

if is_on_corner(pol1[-1], end_edge):
end_edge = next_corner(end_edge)

var iter = PolygonIterator.new(pol.polygon.size(), end_edge, start_edge)
print(iter)

for i in iter:
print("cut: add point %d" % i)
pol1.append(pol.polygon[i])

var polys = Geometry.clip_polygons_2d(pol.polygon, pol1)
print("cliped: %d" % len(polys))
return [ pol1, polys[0] ]
``````

ThePolygonIterator class code:

``````class_name PolygonIterator
# this iterator loop over start to the end to cover all points
# excluding  start, including  end

var start
var current
var end
var count = 0
var size
var counter = 0

func _init(size, start, stop):
self.size = size
self.start = start
self.current = start
if stop < size:
self.end = stop
else:
self.end = size - 1

if start < end:
count = end - start
elif start == end:
count = 0
else:
count = end + (size - start)

func should_continue():
return counter > 0

func init_count():
counter = count

func _iter_init(arg):
init_count()
current = next_val(start)
return should_continue()

func next_val(val):
return (val + 1 + size) % size

func _iter_next(arg):
counter -= 1
current = next_val(current)
return should_continue()

func _iter_get(arg):
return current

func _to_string():
return "iter: (%d) start %d end %d count %d" % [ size, start, end, count ]
``````

So I first complete my Polyline (`tail`) with some polygon's point in order to have a polygon, and then I subtract it to the playground's polygon with `clip_polygons_2d()`.

Is there better way to perform it?

Regards,
Sylvain.

in Engine

There's no such method exposed because the underlying library for polygon clipping in Godot (Clipper) doesn't support such operation.

You can in theory simulate this by using `Geometry.offset_polyline_2d` with a very small `delta`, which will grow your polyline into a thin polygon, and then do the clipping between polygons. Or, you can generate two rectangles along with a polyline (if it's a straight line), and do `Geometry.intersect_polygons_2d` two times against your subject polygon on the both side of the polyline.

by (1,378 points)