К сожалению, я думаю, что будет трудно найти это решение легкодоступным в Javascript или PHP. Но я думаю, что ваша проблема может быть разбита на небольшие подзадачи (основанные на ваших правилах), чтобы помочь вам разработать свое решение.
Я бы определил, какие из ваших правил наиболее важны. Судя по представленному вами графику, я бы сказал, что правила № 1 и № 2 обеспечат максимальное улучшение читаемости.
Чтобы определить размещение по этим правилам, я бы вычислил граничные контейнеры с текстом и пузырьками и проверил на пересечение. На перекрестке переместитесь в место без пересечения. Если не удается найти, используйте пробел с минимальным перекрытием.
Это позволит вам также создать эвристику взвешенного размещения для верхнего левого, нижнего правого и т. Д., Чтобы помочь разместить метки в «предпочтительных» местах.
Я бы попытался написать небольшой фрагмент алгоритма размещения, используя два пузырька с двумя метками, которые обычно близки и потенциально могут перекрываться. Если вы можете обобщить алгоритм размещения для работы с этим небольшим подмножеством, вы должны хорошо продвигаться вперед с большим количеством пузырьков.
Кроме того, возможно, вы могли бы использовать что-то в порядке kd-дерева или другой структуры данных разделения пространства, чтобы найти ближайших соседей, которых следует избегать.