A binary space partition of a sector map: the order to draw it in from any point, front to back, and the convex piece any point is in.
{segs, subsectors, nodes} = Cauldron2D.Sectors.Bsp.build(map)
Cauldron2D.Sectors.Bsp.locate(map, {x, y})The level is cut by lines into convex subsectors, each a run of segs — pieces of
the map's lines — in one sector. A node is a cutting line {x, y, dx, dy} with a
child on each side and the bounding box of each child; the last node is the root.
a seg is
%{from: {x, y}, to: {x, y}, line: index, side: 0 | 1, offset: distance}, wheresideis the side of its line it shows andoffsethow far along that side it starts- a subsector is
%{first: index, count: n, sector: index}, its segs beingfirst..first + count - 1 - a node is
%{x:, y:, dx:, dy:, boxes: {front_box, back_box}, children: {front, back}}, a box{top, bottom, left, right}and a child{:node, index}or{:leaf, index}; the front is the right of the cutting line, asCauldron2D.Sectors.Map.point_side/2reckons it
build/2 builds one from a map's lines. A level that carries its own BSP is read into
the same shapes and used as it is.
Summary
Functions
A BSP for map built from its lines: {segs, subsectors, nodes} as tuples.
The subsector point is in.
The root of the map's BSP.
Visit the subsectors front to back as seen from point.
Types
@type child() :: {:node, non_neg_integer()} | {:leaf, non_neg_integer()}
Functions
@spec build(Cauldron2D.Sectors.Map.t(), keyword()) :: {tuple(), tuple(), tuple()}
A BSP for map built from its lines: {segs, subsectors, nodes} as tuples.
Cutting lines are chosen among the segs' own lines, weighing how many segs a cut would
split against how unevenly it divides them. Options: :split_cost, the weight of one
split against one seg of imbalance, default 8; :candidates, how many cutting lines are
tried at each step, default 48.
@spec locate(Cauldron2D.Sectors.Map.t(), Cauldron2D.Sectors.Map.point()) :: non_neg_integer()
The subsector point is in.
@spec root(Cauldron2D.Sectors.Map.t()) :: child()
The root of the map's BSP.
@spec walk( Cauldron2D.Sectors.Map.t(), Cauldron2D.Sectors.Map.point(), acc, (non_neg_integer(), acc -> acc), (box(), acc -> boolean()) ) :: acc when acc: term()
Visit the subsectors front to back as seen from point.
leaf is called leaf.(subsector_index, acc) and returns the new acc. Before going
into the far side of a node, far?.(box, acc) is asked whether anything in that box can
still be seen; returning false skips it.