implement axis drawing

parent 4c8f9c01
coloritto: *.c argvs-commands.inc *.h Makefile
gcc *.c -o coloritto -lm `pkg-config mrg babl --cflags --libs` -Wall -Wno-unused-but-set-variable -g
ccache gcc *.c -o coloritto -lm `pkg-config mrg babl --cflags --libs` -Wall -Wno-unused-but-set-variable -g
clean:
rm -f coloritto argvs-commands.inc
......
......@@ -437,6 +437,7 @@ typedef struct
ColorLemma {
float sx;
float sy;
float d;
float radius;
Coloritto color;
......@@ -445,11 +446,19 @@ ColorLemma {
} ColorLemma;
MrgList *items = NULL;
char *commandline = NULL;
MrgList *items = NULL; /* list of color lemmas existing at all */
#define SCALEX 300.0
#define SCALEY 300.0
Coloritto *current = NULL;
static MrgList *palette = NULL;
int pal_no = 0;
static int projection_model = COLORITTO_xyY;
char *commandline = NULL; /* commandline being edited */
#define SCALEX 200.0
#define SCALEY 200.0
#define SRGB_SCALE 1.5
Coloritto *coloritto_new (void)
{
......@@ -473,7 +482,6 @@ void coloritto_set_key (Coloritto *color, const char *key,
color->kvs++;
}
const char *coloritto_get_key (Coloritto *color, const char *key)
{
for (int i = 0; i < color->kvs; i++)
......@@ -482,7 +490,6 @@ const char *coloritto_get_key (Coloritto *color, const char *key)
return NULL;
}
void coloritto_set_name (Coloritto *color, const char *name)
{
coloritto_set_key (color, "name", name);
......@@ -520,17 +527,18 @@ int cmd_locus (COMMAND_ARGS) /* "locus", 0, "[command]", "exit" */
const Spectrum *xs = luz_get_spectrum (luz, "observer_x");
const Spectrum *ys = luz_get_spectrum (luz, "observer_y");
const Spectrum *zs = luz_get_spectrum (luz, "observer_z");
int i;
for (i = 0; i < LUZ_SPECTRUM_BANDS; i ++)
for (float nm = 400; nm < 690; nm += 1)
{
char name[32];
xyz[0] = xs->bands[i];
xyz[1] = ys->bands[i];
xyz[2] = zs->bands[i];
Coloritto *color = add_item (luz, COLORITTO_XYZ, &xyz[0], 0.01);
sprintf (name, "%inm", LUZ_SPECTRUM_START + LUZ_SPECTRUM_GAP * i);
xyz[0] = luz_spectrum_interpolate_nm (xs, nm);
xyz[1] = luz_spectrum_interpolate_nm (ys, nm);
xyz[2] = luz_spectrum_interpolate_nm (zs, nm);
Coloritto *color = add_item (luz, COLORITTO_XYZ, &xyz[0], 0.005);
sprintf (name, "%.0fnm", nm);
coloritto_set_name (color, name);
}
mrg_queue_draw (mrg, NULL);
return 0;
}
......@@ -559,7 +567,7 @@ static void add_items ()
add_item (luz, COLORITTO_RGB, &rgb[0], 0.01);
}
#endif
#if 1
#if 0
{
float rgb[3]={1,0,0};
add_item (luz, COLORITTO_RGB, &rgb[0], 0.01);
......@@ -604,10 +612,6 @@ static void add_items ()
}
Coloritto *current = NULL;
static MrgList *palette = NULL;
static int projection_model = COLORITTO_xyY;
int cmd_lab (COMMAND_ARGS) /* "lab", 0, "[command]", "exit" */
{
......@@ -616,7 +620,6 @@ int cmd_lab (COMMAND_ARGS) /* "lab", 0, "[command]", "exit" */
return 0;
}
int cmd_xyY (COMMAND_ARGS) /* "xyY", 0, "[command]", "exit" */
{
projection_model = COLORITTO_xyY;
......@@ -638,7 +641,7 @@ int cmd_rgb (COMMAND_ARGS) /* "rgb", 0, "[command]", "exit" */
return 0;
}
static float angle = 0.0;
static float rotation_angle = 0.0;
int ortho = 1;
int spin = 0;
......@@ -649,6 +652,8 @@ int cmd_ortho (COMMAND_ARGS) /* "ortho", 0, "[command]", "exit" */
ortho = atoi(argv[1]);
if (!strcmp (argv[1], "on")) ortho = 1;
}
else
ortho = !ortho;
printf ("ortho is %s", ortho?"on":"off");
mrg_queue_draw (mrg, NULL);
return 0;
......@@ -661,6 +666,8 @@ int cmd_spin (COMMAND_ARGS) /* "spin", 0, "[command]", "exit" */
spin = atoi(argv[1]);
if (!strcmp (argv[1], "on")) spin = 1;
}
else
spin = !spin;
printf ("spin is %s", spin?"on":"off");
mrg_queue_draw (mrg, NULL);
return 0;
......@@ -670,20 +677,82 @@ int cmd_rotate (COMMAND_ARGS) /* "rotate", 0, "[command]", "exit" */
{
if (argv[1])
{
angle = strtod(argv[1], NULL);
rotation_angle = strtod(argv[1], NULL);
}
mrg_queue_draw (mrg, NULL);
return 0;
}
static float cos_rotation;
static float sin_rotation;
void xyz_to_xy (float x, float y, float z,
float *sx, float *sy, float *d)
{
{
float u,v,w;
u = x * cos_rotation - z * sin_rotation;
v = y;
w = x * sin_rotation + z * cos_rotation;
x=u; y = v; z = w;
}
if (ortho)
{
if (d) *d = z;
if (sx) *sx = x + 0.5;
if (sy) *sy = y + 0.5;
}
else
{
float eyed = 1.0;
float dist = 1.0;
/*
,`
/ ,` |
/| ,` |
/ |,` | y
/ ,`sy |
eye /,`_|_______|
\eyed+dist+z
\ |
\ |
\|
\
sy / eyed = y / ( eyed + dist + z );
sy = y * eyed / ( eyed + dist + z ) + 0.5;
*/
if (d) *d = dist + z;
if (sx) *sx = x * eyed / ( eyed + dist + z ) + 0.5;
if (sy) *sy = y * eyed / ( eyed + dist + z ) + 0.5;
}
}
static int compare_depths (const void *a, const void *b, void *userdata)
{
const ColorLemma *la = a;
const ColorLemma *lb = b;
return (la->d - lb->d) * 100;
}
static void update_projection ()
{
/* here 3d projection and rotation can be incorporated */
if (spin)
angle += 0.02;
float c = cos (angle);
float s = sin (angle);
{
rotation_angle += 0.02;
mrg_queue_draw (mrg, NULL);
}
cos_rotation = cos (rotation_angle);
sin_rotation = sin (rotation_angle);
for (MrgList *l = items; l; l = l->next)
{
......@@ -702,71 +771,27 @@ static void update_projection ()
z = item->color.xyY[2] - 0.5;
break;
case COLORITTO_LAB:
x = (item->color.lab[1]-50)/SCALEX;
y = item->color.lab[2]/SCALEY;
z = item->color.lab[0]/SCALEY;
x = (item->color.lab[1])/SCALEX;
y = item->color.lab[2]/SCALEX;
z = (item->color.lab[0]-50)/SCALEY;
break;
case COLORITTO_SRGB:
#define SRGB_SCALE 4.0
x = (item->color.srgb[0]-0.5) / SRGB_SCALE ;
y = (item->color.srgb[1]-0.5) / SRGB_SCALE ;
y = -(item->color.srgb[1]-0.5) / SRGB_SCALE ;
z = (item->color.srgb[2]-0.5) / SRGB_SCALE ;
break;
case COLORITTO_XYZ:
#define SRGB_SCALE 4.0
x = (item->color.xyz[0] - 0.5) / SRGB_SCALE;
y = (item->color.xyz[1] - 0.5) / SRGB_SCALE;
y = -(item->color.xyz[1] - 0.5) / SRGB_SCALE;
z = (item->color.xyz[2] - 0.5) / SRGB_SCALE;
break;
}
{
float u,v,w;
u = x * c - z * s;
v = y;
w = x * s + z * c;
x=u; y = v; z = w;
}
if (ortho)
{
item->sx = x + 0.5;
item->sy = y + 0.5;
}
else
{
float eyed = 1.0;
float dist = 1.0;
float sy = y * eyed / ( eyed + dist + z ) + 0.5;
float sx = x * eyed / ( eyed + dist + z ) + 0.5;
item->sx = sx;
item->sy = sy;
}
#if 0
,
/ ,`|
/| ,` |
/ |,` | y
/ ,`sy |
eye /,`_|______|
\eyed dist z
\ |
\ |
\|
\
sy / eyed = y / ( eyed + dist + z );
sy = y * eyed / ( eyed + dist + z ) + 0.5;
#endif
xyz_to_xy (x, y, z, &item->sx, &item->sy, &item->d);
}
mrg_list_sort (&items, compare_depths, NULL);
}
......@@ -807,6 +832,11 @@ static void up (MrgEvent *event, void *data1, void *data2) {
mrg_queue_draw (event->mrg, NULL);
}
static void drag_void (MrgEvent *event, void *data1, void *data2)
{
rotation_angle += event->delta_x / mrg_height (event->mrg) * 3.1415 * 2;
}
static void down (MrgEvent *event, void *data1, void *data2)
{
......@@ -843,10 +873,117 @@ void save_selection (void)
}
static void draw_axes (Mrg *mrg, float w, float h)
{
cairo_t *cr = mrg_cr (mrg);
const Spectrum *xs = luz_get_spectrum (luz, "observer_x");
const Spectrum *ys = luz_get_spectrum (luz, "observer_y");
const Spectrum *zs = luz_get_spectrum (luz, "observer_z");
switch (projection_model)
{
case COLORITTO_xyY:
{
float sx, sy;
#define C(x,y,z) \
xyz_to_xy ((x-0.5),1.0-y-0.5,(z-0.5), &sx, &sy, NULL); sx = sx * h + (w - h) / 2; sy *= h;
cairo_new_path (cr);
for (float nm = 400; nm < 690; nm += 2)
{
float xyz[3];
xyz[0] = luz_spectrum_interpolate_nm (xs, nm);
xyz[1] = luz_spectrum_interpolate_nm (ys, nm);
xyz[2] = luz_spectrum_interpolate_nm (zs, nm);
float sum = xyz[0] + xyz[1] + xyz[2];
C(xyz[0]/sum,xyz[1]/sum,xyz[1]); cairo_line_to (cr, sx, sy);
}
cairo_close_path (cr);
cairo_set_source_rgb (cr, 1,1,1);
cairo_set_line_width (cr, 1);
cairo_stroke (cr);
}
break;
#undef C
case COLORITTO_XYZ:
{
float sx, sy;
#define C(x,y,z) \
xyz_to_xy ((x-0.5)/SRGB_SCALE,-(y-0.5)/SRGB_SCALE,(z-0.5)/SRGB_SCALE, &sx, &sy, NULL); sx = sx * h + (w - h) / 2; sy *= h;
C(0,0,0); cairo_move_to (cr, sx, sy);
C(1,0,0); cairo_line_to (cr, sx, sy);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(0,1,0); cairo_line_to (cr, sx, sy);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(0,0,1); cairo_line_to (cr, sx, sy);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(1,1,1); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 1,1,1);
cairo_set_line_width (cr, 1);
cairo_stroke (cr);
}
break;
case COLORITTO_SRGB:
{
float sx, sy;
cairo_set_line_width (cr, 1);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(1,0,0); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 1,0,0);
cairo_stroke (cr);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(0,1,0); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 0,1,0);
cairo_stroke (cr);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(0,0,1); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 0,0,1);
cairo_stroke (cr);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(1,1,1); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 1,1,1);
cairo_stroke (cr);
}
break;
#undef C
case COLORITTO_LAB:
{
float sx, sy;
#define C(x,y,z) \
xyz_to_xy ((y)/SCALEX,z/SCALEX,(x-50)/SCALEY, &sx, &sy, NULL); sx = sx * h + (w - h) / 2; sy *= h;
cairo_set_line_width (cr, 1);
C(0,0,0); cairo_move_to (cr, sx, sy);
C(100,0,0); cairo_line_to (cr, sx, sy);
cairo_set_source_rgb (cr, 1,1,1);
cairo_stroke (cr);
}
break;
}
}
static void draw_items (Mrg *mrg, float w, float h)
{
cairo_t *cr = mrg_cr (mrg);
cairo_set_antialias (cr, CAIRO_ANTIALIAS_FAST);
cairo_new_path (cr);
cairo_rectangle (cr, 0, 0, w, h);
mrg_listen (mrg, MRG_DRAG, drag_void, NULL, NULL);
cairo_new_path (cr);
for (MrgList *l = items; l; l = l->next)
{
......@@ -854,6 +991,8 @@ static void draw_items (Mrg *mrg, float w, float h)
Coloritto *color = &lemma->color;
float rad_scale = 1.0;
if (lemma->d < 0.0 && !ortho) continue;
if (current == color) rad_scale = 1.5;
cairo_arc (cr, lemma->sx * h + (w - h) / 2, lemma->sy * h,
......@@ -895,22 +1034,8 @@ static void ui (Mrg *mrg, void *data)
cairo_set_source_rgb (cr, .5, .5, .5);
cairo_paint (cr); /* todo: use a form of structured noise here */
if (0) for (MrgList *l = items; l; l = l->next)
{
ColorLemma *lemma = l->data;
if (lemma->radius > 0.003)
{
if (&lemma->color == current)
mrg_printf (mrg, "[");
mrg_printf (mrg, "%s", coloritto_get_name (&lemma->color));
if (&lemma->color == current)
mrg_printf (mrg, "]");
mrg_printf (mrg, " ");
}
}
update_projection ();
draw_axes (mrg, w, h);
draw_items (mrg, w, h);
if (!draw_palette (mrg, w, h))
......
......@@ -152,7 +152,7 @@ static const char *config_internal =
"observer_y=observer_y_1931jv\n"
"observer_z=observer_z_1931jv\n"
"illuminant=D50\n"
"illuminant=D65\n"
......
......@@ -1046,7 +1046,7 @@ Spectrum luz_coats_to_spectrum (Luz *luz,
}
/* for now, linear interpolation */
float luz_spectrum_interpolate_nm (Spectrum *spectrum, float nm)
float luz_spectrum_interpolate_nm (const Spectrum *spectrum, float nm)
{
float offset = (nm - LUZ_SPECTRUM_START) / LUZ_SPECTRUM_GAP;
float delta;
......
......@@ -32,9 +32,10 @@
typedef struct _Luz Luz;
#define LUZ_MAX_COATS 16
#define LUZ_SPECTRUM_START 380 /* 380nm */
#define LUZ_SPECTRUM_START 360 /* 380nm */
#define LUZ_SPECTRUM_GAP 5
#define LUZ_SPECTRUM_BANDS 66 /* 380 + 10 * 31 = 790nm */
#define LUZ_SPECTRUM_BANDS 95
//#define LUZ_SPECTRUM_BANDS 68 /* 380 + 10 * 31 = 790nm */
// START + GAP * BANDS should be around 700 to cover visual range
Luz *luz_new (const char *config);
......@@ -79,7 +80,7 @@ void luz_spectrum_to_xyz (Luz *luz,
float *y,
float *z);
float luz_spectrum_interpolate_nm (Spectrum *spectrum, float nm);
float luz_spectrum_interpolate_nm (const Spectrum *spectrum, float nm);
struct _Spectrum {
float bands[LUZ_SPECTRUM_BANDS];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment