Add visually distinct color generator#3165
Conversation
|
"Clean" would be to use https://github.com/alan-turing-institute/distinctipy but that relies on numpy. |
There was a problem hiding this comment.
PR Summary:
- Adds
distinct_rgb_colors()(greedy max-distance algorithm) and companion formatters:distinct_hex_colors,distinct_rgb_strings,distinct_rgba_strings - Private helper
_color_distance()computes Euclidean RGB distance - Also includes minor style cleanups (pylint comment spacing, Black reformatting of existing code)
- Python 2.7 / IronPython compatible, no external dependencies
Review Summary:
The feature concept is solid and fits well alongside the existing random_* color helpers. Three issues were found: a logic bug where the first color always ignores 199 of its 200 candidate samples (the if not colors: break should sit outside the inner loop), a performance issue where math.sqrt is called unnecessarily on every comparison (squared distance is sufficient), and a design inconsistency where distinct_rgba_strings applies random alpha — breaking both the distinctness guarantee and seed-reproducibility that the PR explicitly advertises.
Follow-up suggestions:
@devloaifix the identified issues (early break bug, dropmath.sqrt, fixdistinct_rgba_stringsalpha default)@devloaiadd docstring examples (matching therandom_*pattern in this file) to the new public functions
Sorry, we don't do clean here 😄 |
Complete Test fileimport os
import webbrowser
from pyrevit.coreutils import distinct_rgb_colors
def preview_colors(colors, path="colors.html"):
"""Write an HTML preview of colors."""
path_in = path
if not os.path.isabs(path_in):
_base = os.environ.get("TEMP") or os.environ.get("TMP")
if not _base:
_base = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(_base, os.path.basename(path_in))
else:
path = path_in
f = open(path, "w")
f.write("<html><body style='font-family:sans-serif;'>")
for c in colors:
r, g, b = c
f.write(
"<div style='width:120px;height:40px;"
"background:rgb(%d,%d,%d);"
"display:inline-block;margin:4px;"
"color:white;text-align:center;'>"
"%d,%d,%d</div>"
% (r, g, b, r, g, b)
)
f.write("</body></html>")
f.close()
return path
if __name__ == "__main__":
cols = distinct_rgb_colors(40)
out_path = preview_colors(cols)
webbrowser.open(out_path) |
|
@Wurschdhaud why not make the sample test file into a button in the pyRevitDEv tools |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26083+2106-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26083+2130-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26086+2004-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26088+1318-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26089+1231-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+0549-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+1533-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+1536-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+1540-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+1540-wip |
|
📦 New work-in-progress (wip) builds are available for 6.1.0.26090+1556-wip |
|
📦 New public release are available for 6.2.0.26090+1754 |
Description
This PR adds a color generator that produces visually distinct colors using a greedy max-distance algorithm in RGB space.
The current helpers (random_*) generate purely random colors which often appear visually similar when many colors are needed (e.g. category visualization, element highlighting). The new implementation improves usability by ensuring each new color is maximally separated from previously generated colors.
Key properties:
Python 2.7 / IronPython compatible
No external dependencies
Deterministic behavior with random.seed
Suitable for generating 10–200 distinguishable colors
The implementation evaluates a set of random candidates and selects the color with the largest minimum distance to existing colors.
Checklist
Before submitting your pull request, ensure the following requirements are met:
pipenv run black {source_file_or_directory}Additional Notes
a simple test script: