Table of Contents

Class CollisionGeometryUtils

Namespace
GridPlacement.GDScript
Assembly
MoonBark.GridPlacement.GDScript.dll

Pure, stateless helpers used by the placement/collision mapping pipeline. These functions are extracted from the runtime mapper to allow focused unit tests and reuse from multiple contexts without side-effects.\n\n[b]Default Overlap Thresholds[/b] - Edge epsilon: [code]0.01[/code] (1% tolerance for edge detection) - Minimum area fraction: [code]0.05[/code] (5% of tile area required for overlap) - Very small polygons (< 5% of tile area) are filtered out to avoid spurious detections - For 16×16 tiles, minimum overlap area is 12.8 square units - For 32×32 tiles, minimum overlap area is 51.2 square units\n\n[b]Testing Notes[/b] - Micro polygons smaller than 5% threshold return zero tiles (by design) - Use larger polygons (≥25% tile area) for reliable collision detection in tests - Production mapper may use different thresholds for specific shape types\n\n[i]Documentation style[/i]: Comments use BBCode to render nicely in the Godot editor's help panel.\n\nCross‑references - Center‑based tile semantics: Indicator and mapper math assume tile centers; e.g., 16×16 → center offset (+8,+8). - Iteration range epsilon: compute_tile_iteration_range applies symmetric epsilons to min/max to avoid fencepost tiles when world bounds align exactly to tile borders (bottom‑inclusive, top‑exclusive in practice).

class CollisionGeometryUtils extends RefCounted
CollisionGeometryUtils

Properties

shape_transform

var shape_transform = Transform2D()

shape_local_offset

var shape_local_offset = shape_owner.position

world_points

var world_points: PackedVector2Array = PackedVector2Array()

global_xform

var global_xform = polygon_node.get_global_transform()

result

var result = {}

epsilon

var epsilon = 0.0001

adjusted_min_corner

var adjusted_min_corner = bounds.position + Vector2(epsilon, epsilon)

start_tile

var start_tile = map.local_to_map(map.to_local(adjusted_min_corner))

adjusted_max_corner

var adjusted_max_corner = bounds.position + bounds.size - Vector2(epsilon, epsilon)

end_tile_inclusive

var end_tile_inclusive = map.local_to_map(map.to_local(adjusted_max_corner))

end_exclusive

var end_exclusive = Vector2i(end_tile_inclusive.x + 1, end_tile_inclusive.y + 1)

offsets

var offsets: Array[Vector2i] = []

overlapped_tiles

var overlapped_tiles: Array[Vector2i] = CollisionGeometryCalculator.calculate_tile_overlap(world_points, tile_size, tile_shape, tile_map_layer, 0.01, 0.05)

n

var n = points.size()

sign

var sign = 0

a

var a = points[i]

b

var b = points[(i+1) % n]

c

var c = points[(i+2) % n]

cross

var cross = (b - a).cross(c - b)

curr_sign

var curr_sign = signi(cross)

Methods

build_shape_transform

static func build_shape_transform(col_obj: Node2D, shape_owner: Node2D) -> Transform2D:

Parameters

col_obj
shape_owner

Returns

to_world_polygon

static func to_world_polygon(polygon_node: CollisionPolygon2D) -> PackedVector2Array:

Parameters

polygon_node

Returns

compute_tile_iteration_range

static func compute_tile_iteration_range(bounds: Rect2, map: TileMapLayer) -> Dictionary:

Parameters

bounds
map

Returns

center_tile_for_polygon_positioner

static func center_tile_for_polygon_positioner(map: TileMapLayer, positioner: Node2D) -> Vector2i:

Parameters

map
positioner

Returns

center_tile_for_shape_object

static func center_tile_for_shape_object(map: TileMapLayer, col_obj: Node2D) -> Vector2i:

Parameters

map
col_obj

Returns

compute_polygon_tile_offsets

static func compute_polygon_tile_offsets(world_points: PackedVector2Array, tile_size: Vector2, center_tile: Vector2i, tile_shape: TileSet.TileShape = TileSet.TILE_SHAPE_SQUARE, tile_map_layer: TileMapLayer = null) -> Array[Vector2i]:

Parameters

world_points
tile_size
center_tile
tile_shape
tile_map_layer

Returns

is_polygon_convex

static func is_polygon_convex(points: PackedVector2Array) -> bool:

Parameters

points

Returns