Skip to content

Collision Handling

One of the biggest contributors to the visual quality of a map is labeling, which includes choosing carefully what to label and also choosing good positions for those labels. Obviously, you don't want labels to collide with each other, but there's also a few more subtle things to consider when labeling points and areas on a map. Starplot has a CollisionHandler to control some of these things.

When you create a plot, you can specify the default collision handler for three different types of labels:

  • Points (point_label_handler) - stars, DSOs, etc
  • Areas (area_label_handler) - constellations
  • Paths (path_label_handler) - ecliptic, celestial equator, etc

You can also override these defaults on all functions that plot text. There are three distinct types of collision handlers because it's very common to want different rules for different types of labels. For example, the default area collision handler allows collisions with constellation lines, but the point handler does not.

See the Virgo Galaxy Cluster plot for an example of using a custom collision handler.

New Feature

The collision handler is a newer feature of Starplot (introduced in version 0.19.0), and will continue to evolve in future versions. As always, if you notice any unexpected behavior with it, please open an issue on GitHub.

Defaults

Below are the defaults for each type of collision handler. These are the defaults for all plot types.

Points

CollisionHandler(
    attempts=10,
    anchor_fallbacks=[
        AnchorPointEnum.BOTTOM_RIGHT,
        AnchorPointEnum.TOP_LEFT,
        AnchorPointEnum.TOP_RIGHT,
        AnchorPointEnum.BOTTOM_LEFT,
        AnchorPointEnum.BOTTOM_CENTER,
        AnchorPointEnum.TOP_CENTER,
        AnchorPointEnum.RIGHT_CENTER,
        AnchorPointEnum.LEFT_CENTER,
    ]
)

Areas

CollisionHandler(
    allow_constellation_line_collisions=True
)

Paths

CollisionHandler(
    allow_constellation_line_collisions=True
)

starplot.CollisionHandler dataclass

CollisionHandler(
    allow_clipped: bool = False,
    allow_label_collisions: bool = False,
    allow_marker_collisions: bool = False,
    allow_constellation_line_collisions: bool = False,
    plot_on_fail: bool = False,
    attempts: int = 500,
    seed: int = None,
    anchor_fallbacks: list[AnchorPointEnum] = None,
)

Dataclass that describes how to handle label collisions with other objects, like text, markers, constellation lines, etc.

allow_clipped class-attribute instance-attribute

allow_clipped: bool = False

If True, then labels will be plotted if they're clipped (i.e. part of the label is outside the plot area)

allow_label_collisions class-attribute instance-attribute

allow_label_collisions: bool = False

If True, then labels will be plotted if they collide with another label

allow_marker_collisions class-attribute instance-attribute

allow_marker_collisions: bool = False

If True, then labels will be plotted if they collide with another marker

allow_constellation_line_collisions class-attribute instance-attribute

allow_constellation_line_collisions: bool = False

If True, then labels will be plotted if they collide with a constellation line

plot_on_fail class-attribute instance-attribute

plot_on_fail: bool = False

If True, then labels will be plotted even if no allowed position is found. They will be plotted at their last attempted position.

attempts class-attribute instance-attribute

attempts: int = 500

Max attempts to find a good label position

seed class-attribute instance-attribute

seed: int = None

Random seed for randomly generating points

anchor_fallbacks class-attribute instance-attribute

anchor_fallbacks: list[AnchorPointEnum] = None

If a point-based label's preferred anchor point results in a collision, then these fallbacks will be tried in sequence until a collision-free position is found.

Default:

[
    AnchorPointEnum.BOTTOM_RIGHT,
    AnchorPointEnum.TOP_LEFT,
    AnchorPointEnum.TOP_RIGHT,
    AnchorPointEnum.BOTTOM_LEFT,
    AnchorPointEnum.BOTTOM_CENTER,
    AnchorPointEnum.TOP_CENTER,
    AnchorPointEnum.RIGHT_CENTER,
    AnchorPointEnum.LEFT_CENTER,
]