Они предназначены именно для этого - расширения сущностей базовой библиотеки внутри зависимой библиотеки, когда исходные сущности не могут быть изменены там, где они "живут".
Конечно, это работает только тогда, когда все операции рисования могут быть реализованы в терминах публичных атрибутов и публичных методов геометрических классов. Но для данного типа сценария использования это обычно так и есть или может быть легко организовано.
Подход №2: Общие функции рисования внутри геометрических сущностей
Такие функции будут получать некий абстрактный графический контекст или объект canvas и позволять сущности рисовать себя на этом холсте. Интерфейс canvas должен быть частью ядра, но конкретная реализация canvas будет находиться вне ядра, поэтому ядро не будет зависеть от конкретных компонентов пользовательского интерфейса.
Такой подход имеет смысл, когда графический контекстный интерфейс может предоставить некоторые базовые операции рисования, которые можно использовать для всех геометрических объектов, например, "DrawLineSegment" или "DrawPolylines", которые универсально используются для рисования линии, окружности или эллипса.
Конечно, ничто не мешает объединить оба подхода: общие функции рисования, работающие на абстрактном холсте, могут быть реализованы как методы расширения вне ядра. При этом логика "draw-to-canvas" полностью удалена от ядра, она может быть реализована, например, в каком-то промежуточном слое или непосредственно в слое приложения.
Рекомендую посмотреть эти видео для лучшего погружения в вопрос: