From 978c91a3d019c9c948ef2916c0084402cf03b84b Mon Sep 17 00:00:00 2001 From: Anurag Aggarwal Date: Thu, 25 Jun 2020 12:05:14 +0530 Subject: [PATCH] Add cartesian grid --- src/include/grlib.h | 2 + src/include/ui_helper.h | 2 + src/ui-hlp/menu.cpp | 61 +++++++++++++++++++++++++--- src/ui-hlp/ui_helper.cpp | 61 ++++++++++++++++++++++++++++ src/ui/image_qt.cpp | 88 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 209 insertions(+), 5 deletions(-) diff --git a/src/include/grlib.h b/src/include/grlib.h index 08da0f55..baf6225a 100644 --- a/src/include/grlib.h +++ b/src/include/grlib.h @@ -1,6 +1,7 @@ #ifndef _TEXT_H #define _TEXT_H #define TEXT_PRESSED 1 +#include "ui_helper.h" int xprint(struct image *image, void *font, int x, int y, const char *text, int fgcolor, int bgcolor, int mode); int xtextwidth(struct image *image, void *font, const char *text); @@ -15,5 +16,6 @@ void xrestoreline(struct image *img, char *data, int x1, int y1, int x2, int y2); void xline(struct image *img, int x1, int y1, int x2, int y2, int color); void xprepareimage(struct image *img); +void overlayGrid(uih_context *c, int fgcolor); #endif diff --git a/src/include/ui_helper.h b/src/include/ui_helper.h index fb4eb1d9..539cb2e7 100644 --- a/src/include/ui_helper.h +++ b/src/include/ui_helper.h @@ -547,6 +547,8 @@ void uih_status(uih_context *uih); int uih_statusenabled(uih_context *uih); int uih_ministatusenabled(uih_context *uih); void uih_ministatus(uih_context *uih); +int uih_cartesiangridenabled(uih_context *uih); +void uih_cartesiangrid(uih_context *uih); void uih_sffeset(uih_context *c, sffe *parser, const char *formula); #endif diff --git a/src/ui-hlp/menu.cpp b/src/ui-hlp/menu.cpp index 7610559d..e352c234 100644 --- a/src/ui-hlp/menu.cpp +++ b/src/ui-hlp/menu.cpp @@ -62,7 +62,7 @@ const char *const uih_colornames[] = {"white", "black", "red", NULL}; * Zoltan Kovacs , 2003-01-05 */ -#define MAX_MENUDIALOGS_I18N 103 +#define MAX_MENUDIALOGS_I18N 104 #define Register(variable) variable = &menudialogs_i18n[no_menudialogs_i18n] static menudialog menudialogs_i18n[MAX_MENUDIALOGS_I18N]; // static int no_menudialogs_i18n; @@ -76,7 +76,7 @@ static menudialog *uih_perturbationdialog, *uih_juliadialog, *uih_filterdialog, *uih_shiftdialog, *uih_speeddialog, *printdialog, *uih_bailoutdialog, *uih_threaddialog, *saveanimdialog, *uih_juliamodedialog, *uih_textposdialog, *uih_fastmodedialog, *uih_timedialog, *uih_numdialog, - *uih_fpdialog, *palettedialog, *uih_cyclingdialog, *loadimgdialog + *uih_fpdialog, *palettedialog, *uih_cyclingdialog, *loadimgdialog, *palettegradientdialog #ifdef USE_SFFE , *uih_sffedialog, *uih_sffeinitdialog @@ -266,6 +266,12 @@ void uih_registermenudialogs_i18n(void) NULL_I(); Register(palettedialog); + DIALOGINT_I(TR("Dialog", "Algorithm number:"), 0); + DIALOGINT_I(TR("Dialog", "Seed:"), 0); + DIALOGINT_I(TR("Dialog", "Shift:"), 0); + NULL_I(); + + Register(palettegradientdialog); DIALOGPALSLIDER_I(TR("Dialog", "Visualiser:"), 0); NULL_I(); @@ -552,11 +558,21 @@ static menudialog *uih_getsffeinitdialog(struct uih_context *c) static menudialog *uih_getpalettedialog(struct uih_context *uih) { if (uih != NULL) { - palettedialog[0].defint = 0; + palettedialog[0].defint = uih->palettetype; + palettedialog[1].defint = uih->paletteseed; + palettedialog[2].defint = uih->paletteshift + uih->manualpaletteshift; } return (palettedialog); } +static menudialog *uih_getpalettegradientdialog(struct uih_context *uih) +{ + if (uih != NULL) { + palettegradientdialog[0].defint = 0; + } + return (palettegradientdialog); +} + static menudialog *uih_getcyclingdialog(struct uih_context *uih) { if (uih != NULL) @@ -583,6 +599,35 @@ static void uih_setspeed(uih_context *c, number_t p) static void uih_palette(struct uih_context *uih, dialogparam *p) { + int n1 = p[0].dint; + int n2 = p[1].dint; + int shift = p[2].dint; + + if (!n1) { + uih_playdefpalette(uih, shift); + return; + } + if (n1 < 1 || n1 > PALGORITHMS) { + uih_error(uih, TR("Error", "Unknown palette type")); + } + if (uih->zengine->fractalc->palette == NULL) + return; + if (mkpalette(uih->zengine->fractalc->palette, n2, n1 - 1) != 0) { + uih_newimage(uih); + } + uih->manualpaletteshift = 0; + uih->palettetype = n1; + uih->palettechanged = 1; + uih->paletteseed = n2; + if (shiftpalette(uih->zengine->fractalc->palette, shift)) { + uih_newimage(uih); + } + uih->paletteshift = shift; +} + +static void uih_palettegradient(struct uih_context *uih, dialogparam *p) +{ + fflush(stdout); int n1 = uih->palettetype; int n2 = uih->paletteseed; int shift = uih->paletteshift; @@ -906,6 +951,8 @@ void uih_registermenus_i18n(void) MENUNOPCB_I("ui", "l", TR("Menu", "Ministatus"), "ministatus", MENUFLAG_INCALC, uih_ministatus, uih_ministatusenabled); + MENUNOPCB_I("ui", "g", TR("Menu", "Cartesian Grid"), "cartesiangrid", + MENUFLAG_INCALC, uih_cartesiangrid, uih_cartesiangridenabled); MENUSEPARATOR_I("ui"); MENUSEPARATOR_I("uia"); MENUNOPCB_I("uia", "/", TR("Menu", "Status"), "animstatus", @@ -914,6 +961,8 @@ void uih_registermenus_i18n(void) MENUNOPCB_I("uia", "l", TR("Menu", "Ministatus"), "animministatus", UI | MENUFLAG_INCALC, uih_ministatus, uih_ministatusenabled); + MENUNOPCB_I("uia", "g", TR("Menu", "Show Grid"), "animcartesiangrid", + MENUFLAG_INCALC, uih_cartesiangrid, uih_cartesiangridenabled); MENUSEPARATOR_I("uia"); SUBMENU_I("root", "s", TR("Menu", "File"), "file"); SUBMENU_I("root", NULL, TR("Menu", "Edit"), "edit"); @@ -1061,8 +1110,10 @@ void uih_registermenus_i18n(void) 0, uih_mkdefaultpalette); MENUNOP_I("palettemenu", "p", TR("Menu", "Random palette"), "randompalette", 0, uih_menumkpalette); - MENUCDIALOG_I("palettemenu", NULL, TR("Menu", "Custom palette"), "palette", - 0, uih_palette, uih_getpalettedialog); + MENUCDIALOG_I("", NULL, TR("Menu", "Custom palette"), "palette", + 0, uih_palette, uih_getpalettedialog); //This is a placeholder menu + MENUCDIALOG_I("palettemenu", NULL, TR("Menu", "Custom palette"), "palettegradient", + 0, uih_palettegradient, uih_getpalettegradientdialog); MENUSEPARATOR_I("palettemenu"); MENUNOPCB_I("palettemenu", "y", TR("Menu", "Color cycling"), "cycling", 0, uih_cyclingsw, uih_cyclingselected); diff --git a/src/ui-hlp/ui_helper.cpp b/src/ui-hlp/ui_helper.cpp index ddb18392..5dca6ced 100644 --- a/src/ui-hlp/ui_helper.cpp +++ b/src/ui-hlp/ui_helper.cpp @@ -2230,6 +2230,8 @@ static int statusstart; static struct uih_window *statuswindow = NULL; static int ministatusstart; static struct uih_window *ministatuswindow = NULL; +int cartesiangridstart; +static struct uih_window *cartesiangridwindow = NULL; void uih_updatestatus(uih_context *uih) { @@ -2265,6 +2267,9 @@ void uih_updatestarts(uih_context *uih) ministatusstart = y; if (ministatuswindow != NULL) y += xtextheight(uih->image, uih->font); + cartesiangridstart = y; + if (cartesiangridwindow != NULL) + y += xtextheight(uih->image, uih->font) * 2; statusstart = y; if (statuswindow != NULL) y += xtextheight(uih->image, uih->font) * STATUSLINES; @@ -2405,3 +2410,59 @@ int uih_ministatusenabled(uih_context * /*uih*/) { return (ministatuswindow != NULL); } + +static void uih_cartesiangridpos(uih_context *uih, int *x, int *y, int *w, int *h, + void * /*data*/) +{ + *x = 0; + *y = 0; + *w = uih->image->width; + *h = uih->image->height-30; // Leave some padding, FIXME + fflush(stdout); +} + +static void uih_drawcartesiangrid(uih_context *uih, void * /*data*/) +{ + char statustext[256]; + int h = xtextheight(uih->image, uih->font); + long double rr = uih->fcontext->s.rr/10.0; + long double counter=0; + while(rr < 1){ + rr *= 10; + counter++; + } + sprintf(statustext, "X-axis: 1 grid = %f", pow(10.0, -counter+1)); + xprint(uih->image, uih->font, 0, cartesiangridstart, statustext, FGCOLOR(uih), + BGCOLOR(uih), 0); + sprintf(statustext, "Y-axis: 1 grid = %f", pow(10.0, -counter+1)); + xprint(uih->image, uih->font, 0, cartesiangridstart + h, statustext, FGCOLOR(uih), + BGCOLOR(uih), 0); + overlayGrid(uih, FGCOLOR(uih)); +} + +void uih_cartesiangrid(uih_context *uih) +{ + double currzoom = + (uih->fcontext->currentformula->v.rr) / (uih->fcontext->s.rr); + + if (cartesiangridwindow == NULL and currzoom < 100000) { + cartesiangridwindow = + uih_registerw(uih, uih_cartesiangridpos, uih_drawcartesiangrid, NULL, 0); + } else { + if(cartesiangridwindow) { + uih_removew(uih, cartesiangridwindow); + cartesiangridwindow = NULL; + } else { + uih_error(uih, "Cartesian Grid not supported on zoom > 100000x"); + } + } + + uih_updatestarts(uih); + uih_updatemenus(uih, "cartesiangrid"); + uih_updatemenus(uih, "animcartesiangrid"); +} + +int uih_cartesiangridenabled(uih_context * /*uih*/) +{ + return (cartesiangridwindow != NULL); +} diff --git a/src/ui/image_qt.cpp b/src/ui/image_qt.cpp index 0d585242..d6b6ab69 100644 --- a/src/ui/image_qt.cpp +++ b/src/ui/image_qt.cpp @@ -131,3 +131,91 @@ struct image *create_image_qt(int width, int height, struct palette *palette, img->free = freeImage; return img; } + +void overlayGrid(uih_context *c, int fgcolor) +{ + struct image* image = c->image; + QImage *qimage = reinterpret_cast(image->data)[image->currimage]; + QPainter painter(qimage); + QPen pen; + pen.setColor(fgcolor); + pen.setWidth(2); + painter.setPen(pen); + + //Find fractal origin (0,0) + long long int x1 = (0 - c->fcontext->rs.nc) / + (c->fcontext->rs.mc - c->fcontext->rs.nc) * + c->zengine->image->width; + long long int y1 = (0 - c->fcontext->rs.ni) / + (c->fcontext->rs.mi - c->fcontext->rs.ni) * + c->zengine->image->height; + + /* FIXME Support greater zoom*/ + double currzoom = + (c->fcontext->currentformula->v.rr) / (c->fcontext->s.rr); + if(currzoom > 100000){ + uih_error(c, "Cartesian Grid not supported on zoom > 100000x"); + uih_message(c, "Re-enable after zooming out"); + uih_cartesiangrid(c); + } + + // Find next coordinate (1,1) + long long int x2 = (1 - c->fcontext->rs.nc) / + (c->fcontext->rs.mc - c->fcontext->rs.nc) * + c->zengine->image->width; + long long int y2 = (1 - c->fcontext->rs.ni) / + (c->fcontext->rs.mi - c->fcontext->rs.ni) * + c->zengine->image->height; + + // Find current zoom level + long double rr = c->fcontext->s.rr/10.0; + long double counter=0; + while(rr<1){ + rr*=10; + counter++; + } + + // Set step size + long double xinterval = x2-x1; + long double yinterval = y2-y1; + long double xstep = xinterval/pow(10.0, counter - 1); + long double ystep = yinterval/pow(10.0, counter - 1); + + // Do Not draw smaller coordinates if step size is too low + // Draw Boundary Boxes + if(xstep > 1 and ystep > 1){ + for(long double i=x1; i<=image->width; i+=xstep*10){ + painter.drawLine(i, 0, i, image->height); + } + for(long double i=x1; i>=0; i-=xstep*10){ + painter.drawLine(i, 0, i, image->height); + } + for(long double i=y1; i<=image->height; i+=ystep*10){ + painter.drawLine(0, i, image->width, i); + } + for(long double i=y1; i>=0; i-=ystep*10){ + painter.drawLine(0, i, image->width, i); + } + } + + pen.setWidth(1); + pen.setStyle(Qt::DashLine); + painter.setPen(pen); + + // Draw grid boxes + if(xstep > 1 and ystep > 1){ + for(long double i=x1; i<=image->width; i+=xstep){ + painter.drawLine(i, 0, i, image->height); + } + for(long double i=x1; i>=0; i-=xstep){ + painter.drawLine(i, 0, i, image->height); + } + for(long double i=y1; i<=image->height; i+=ystep){ + painter.drawLine(0, i, image->width, i); + } + for(long double i=y1; i>=0; i-=ystep){ + painter.drawLine(0, i, image->width, i); + } + } + return; +}