Code

AXONOMETRIC (3D) GRID! OK, still alot of work to be done. Snapping, diagonal guides...
authorjohanengelen <johanengelen@users.sourceforge.net>
Thu, 21 Sep 2006 22:25:16 +0000 (22:25 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Thu, 21 Sep 2006 22:25:16 +0000 (22:25 +0000)
src/attributes-test.h
src/attributes.cpp
src/attributes.h
src/display/Makefile_insert
src/display/canvas-axonomgrid.cpp [new file with mode: 0644]
src/display/canvas-axonomgrid.h [new file with mode: 0644]
src/sp-namedview.cpp
src/sp-namedview.h
src/ui/dialog/document-properties.cpp
src/ui/dialog/document-properties.h

index f0db48ad0d846eee0f90464abbb001974b796e8f..1e413c90f4245229d9a5d065b0784b6ed662ae8c 100644 (file)
@@ -402,6 +402,7 @@ struct {char const *attr; bool supported;} const all_attrs[] = {
     /* SPNamedView */
     {"viewonly", true},
     {"showgrid", true},
+    {"gridtype", true},
     {"showguides", true},
     {"gridtolerance", true},
     {"guidetolerance", true},
@@ -411,6 +412,8 @@ struct {char const *attr; bool supported;} const all_attrs[] = {
     {"gridoriginy", true},
     {"gridspacingx", true},
     {"gridspacingy", true},
+    {"gridanglex", true},
+    {"gridanglez", true},
     {"gridcolor", true},
     {"gridopacity", true},
     {"gridempcolor", true},
index 867e5989c73128be532974de96c62f14760d454f..f02e9b28fd779436bde77f4d25bd53e393c0b2f5 100644 (file)
@@ -7,6 +7,7 @@
  * Author:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
  * Copyright (C) 2002 Lauris Kaplinski
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
@@ -59,6 +60,7 @@ static SPStyleProp const props[] = {
     /* SPNamedView */
     {SP_ATTR_VIEWONLY, "viewonly"},
     {SP_ATTR_SHOWGRID, "showgrid"},
+    {SP_ATTR_GRIDTYPE, "gridtype"},
     {SP_ATTR_SHOWGUIDES, "showguides"},
     {SP_ATTR_GRIDTOLERANCE, "gridtolerance"},
     {SP_ATTR_GUIDETOLERANCE, "guidetolerance"},
@@ -68,6 +70,8 @@ static SPStyleProp const props[] = {
     {SP_ATTR_GRIDORIGINY, "gridoriginy"},
     {SP_ATTR_GRIDSPACINGX, "gridspacingx"},
     {SP_ATTR_GRIDSPACINGY, "gridspacingy"},
+    {SP_ATTR_GRIDANGLEX, "gridanglex"},
+    {SP_ATTR_GRIDANGLEZ, "gridanglez"},
     {SP_ATTR_GRIDCOLOR, "gridcolor"},
     {SP_ATTR_GRIDOPACITY, "gridopacity"},
     {SP_ATTR_GRIDEMPCOLOR, "gridempcolor"},
index 5ef817e49ca6a3dfd330c27e2bf30bffbd8c9451..242c5c24691f763c40745a9683b201a2432ed51c 100644 (file)
@@ -8,6 +8,7 @@
  * Author:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
  * Copyright (C) 2002 Lauris Kaplinski
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
@@ -60,6 +61,7 @@ enum SPAttributeEnum {
     /* SPNamedView */
     SP_ATTR_VIEWONLY,
     SP_ATTR_SHOWGRID,
+    SP_ATTR_GRIDTYPE,
     SP_ATTR_SHOWGUIDES,
     SP_ATTR_GRIDTOLERANCE,
     SP_ATTR_GUIDETOLERANCE,
@@ -69,6 +71,8 @@ enum SPAttributeEnum {
     SP_ATTR_GRIDORIGINY,
     SP_ATTR_GRIDSPACINGX,
     SP_ATTR_GRIDSPACINGY,
+    SP_ATTR_GRIDANGLEX,
+    SP_ATTR_GRIDANGLEZ,
     SP_ATTR_GRIDCOLOR,
     SP_ATTR_GRIDOPACITY,
     SP_ATTR_GRIDEMPCOLOR,
index 6d38c15934d44ac4438f969a3fe3ab9c88f1fe18..a6cecaffbdc1cf790054347628b197cca599635e 100644 (file)
@@ -36,6 +36,8 @@ display_libspdisplay_a_SOURCES = \
        display/canvas-bpath.h  \
        display/canvas-grid.cpp \
        display/canvas-grid.h   \
+       display/canvas-axonomgrid.cpp   \
+       display/canvas-axonomgrid.h     \
        display/curve.cpp       \
        display/curve.h \
        display/display-forward.h       \
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
new file mode 100644 (file)
index 0000000..909ebdc
--- /dev/null
@@ -0,0 +1,469 @@
+#define SP_CANVAS_AXONOMGRID_C\r
+\r
+/*\r
+ * SPCAxonomGrid\r
+ *\r
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>\r
+ * Copyright (C) 2000 Lauris Kaplinski\r
+ *\r
+ */                         \r
\r
+ /* \r
+  * Current limits are: one axis (y-axis) is always vertical. The other two\r
+  * axes are bound to a certain range of angles. The z-axis always has an angle \r
+  * smaller than 90 degrees (measured from horizontal, 0 degrees being a line extending\r
+  * to the right). The x-axis will always have an angle between 0 and 90 degrees.\r
+  * When I quickly think about it: all possibilities are probably covered this way. Eg.\r
+  * a z-axis with negative angle can be replaced with an x-axis, etc.\r
+  */              \r
+  \r
+ /*\r
+  *  TODO:  LOTS LOTS LOTS. Optimization etc.\r
+  *\r
+  */\r
+\r
+#include "sp-canvas-util.h"\r
+#include "canvas-axonomgrid.h"\r
+#include "display-forward.h"\r
+#include <libnr/nr-pixops.h>\r
+\r
+#define SAFE_SETPIXEL   //undefine this when it is certain that setpixel is never called with invalid params\r
+\r
+enum {\r
+    ARG_0,\r
+    ARG_ORIGINX,\r
+    ARG_ORIGINY,\r
+    ARG_ANGLEX,\r
+    ARG_SPACINGY,\r
+    ARG_ANGLEZ,\r
+    ARG_COLOR,\r
+    ARG_EMPCOLOR,\r
+    ARG_EMPSPACING\r
+};\r
+\r
+enum Dim3 { X=0, Y, Z };\r
+\r
+#ifndef M_PI\r
+#define M_PI 3.14159265358979323846\r
+#endif\r
+\r
+static double deg_to_rad(double deg) { return deg*M_PI/180.0;}\r
+\r
+\r
+static void sp_caxonomgrid_class_init (SPCAxonomGridClass *klass);\r
+static void sp_caxonomgrid_init (SPCAxonomGrid *grid);\r
+static void sp_caxonomgrid_destroy (GtkObject *object);\r
+static void sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);\r
+\r
+static void sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);\r
+static void sp_caxonomgrid_render (SPCanvasItem *item, SPCanvasBuf *buf);\r
+\r
+static SPCanvasItemClass * parent_class;\r
+\r
+GtkType\r
+sp_caxonomgrid_get_type (void)\r
+{\r
+    static GtkType caxonomgrid_type = 0;\r
+\r
+    if (!caxonomgrid_type) {\r
+        GtkTypeInfo caxonomgrid_info = {\r
+            "SPCAxonomGrid",\r
+            sizeof (SPCAxonomGrid),\r
+            sizeof (SPCAxonomGridClass),\r
+            (GtkClassInitFunc) sp_caxonomgrid_class_init,\r
+            (GtkObjectInitFunc) sp_caxonomgrid_init,\r
+            NULL, NULL,\r
+            (GtkClassInitFunc) NULL\r
+        };\r
+        caxonomgrid_type = gtk_type_unique (sp_canvas_item_get_type (), &caxonomgrid_info);\r
+    }\r
+    return caxonomgrid_type;\r
+}\r
+\r
+static void\r
+sp_caxonomgrid_class_init (SPCAxonomGridClass *klass)\r
+{\r
+\r
+    GtkObjectClass *object_class;\r
+    SPCanvasItemClass *item_class;\r
+\r
+    object_class = (GtkObjectClass *) klass;\r
+    item_class = (SPCanvasItemClass *) klass;\r
+\r
+    parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());\r
+\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::originx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINX);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::originy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINY);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::anglex", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEX);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::spacingy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGY);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::anglez", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ANGLEZ);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::color", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COLOR);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::empcolor", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPCOLOR);\r
+    gtk_object_add_arg_type ("SPCAxonomGrid::empspacing", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPSPACING);\r
+\r
+    object_class->destroy = sp_caxonomgrid_destroy;\r
+    object_class->set_arg = sp_caxonomgrid_set_arg;\r
+\r
+    item_class->update = sp_caxonomgrid_update;\r
+    item_class->render = sp_caxonomgrid_render;\r
+  \r
+}\r
+\r
+static void\r
+sp_caxonomgrid_init (SPCAxonomGrid *grid)\r
+{\r
+    grid->origin[NR::X] = grid->origin[NR::Y] = 0.0;\r
+//    grid->spacing[X] = grid->spacing[Y] = grid->spacing[Z] = 8.0;\r
+    grid->color = 0x0000ff7f;\r
+    grid->empcolor = 0x3F3FFF40;\r
+    grid->empspacing = 5;\r
+}\r
+\r
+static void\r
+sp_caxonomgrid_destroy (GtkObject *object)\r
+{\r
+    g_return_if_fail (object != NULL);\r
+    g_return_if_fail (SP_IS_CAXONOMGRID (object));\r
+\r
+    if (GTK_OBJECT_CLASS (parent_class)->destroy)\r
+        (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);\r
+}\r
+\r
+static void\r
+sp_caxonomgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)\r
+{\r
+    SPCanvasItem *item = SP_CANVAS_ITEM (object);\r
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (object);\r
+    \r
+    g_message("arg");\r
+    \r
+    switch (arg_id) {\r
+    case ARG_ORIGINX:\r
+        grid->origin[NR::X] = GTK_VALUE_DOUBLE (* arg);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_ORIGINY:\r
+        grid->origin[NR::Y] = GTK_VALUE_DOUBLE (* arg);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_ANGLEX:\r
+        grid->angle_deg[X] = GTK_VALUE_DOUBLE (* arg);\r
+        if (grid->angle_deg[X] < 0.0) grid->angle_deg[X] = 0.0;\r
+        grid->angle_rad[X] = deg_to_rad(grid->angle_deg[X]);\r
+        grid->tan_angle[X] = tan(grid->angle_rad[X]);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_SPACINGY:\r
+        grid->lengthy = GTK_VALUE_DOUBLE (* arg);\r
+        if (grid->lengthy < 0.01) grid->lengthy = 0.01;\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_ANGLEZ:\r
+        grid->angle_deg[Z] = GTK_VALUE_DOUBLE (* arg);\r
+        if (grid->angle_deg[Z] < 0.0) grid->angle_deg[Z] = 0.0;\r
+        grid->angle_rad[Z] = deg_to_rad(grid->angle_deg[Z]);\r
+        grid->tan_angle[Z] = tan(grid->angle_rad[Z]);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_COLOR:\r
+        grid->color = GTK_VALUE_INT (* arg);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_EMPCOLOR:\r
+        grid->empcolor = GTK_VALUE_INT (* arg);\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    case ARG_EMPSPACING:\r
+        grid->empspacing = GTK_VALUE_INT (* arg);\r
+        // std::cout << "Emphasis Spacing: " << grid->empspacing << std::endl;\r
+        sp_canvas_item_request_update (item);\r
+        break;\r
+    default:\r
+        break;\r
+    }\r
+}\r
+\r
+\r
+\r
+/**\r
+    \brief  This function renders a pixel on a particular buffer.\r
+                \r
+    The topleft of the buffer equals\r
+                        ( rect.x0 , rect.y0 )  in screen coordinates\r
+                        ( 0 , 0 )  in setpixel coordinates\r
+    The bottomright of the buffer equals\r
+                        ( rect.x1 , rect,y1 )  in screen coordinates\r
+                        ( rect.x1 - rect.x0 , rect.y1 - rect.y0 )  in setpixel coordinates\r
+*/\r
+static void \r
+sp_caxonomgrid_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba) {\r
+#ifdef SAFE_SETPIXEL\r
+    if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {\r
+#endif        \r
+        guint r, g, b, a;          \r
+        r = NR_RGBA32_R (rgba);\r
+        g = NR_RGBA32_G (rgba);\r
+        b = NR_RGBA32_B (rgba);\r
+        a = NR_RGBA32_A (rgba);  \r
+        guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;\r
+        p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);\r
+        p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);\r
+        p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);\r
+#ifdef SAFE_SETPIXEL\r
+    }\r
+#endif    \r
+}\r
+\r
+/**\r
+    \brief  This function renders a line on a particular canvas buffer,\r
+            using Bresenham's line drawing function.\r
+            http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html \r
+            Coordinates are interpreted as SCREENcoordinates\r
+*/\r
+static void \r
+sp_caxonomgrid_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba) {\r
+    int dy = y1 - y0;\r
+    int dx = x1 - x0;\r
+    int stepx, stepy;\r
+\r
+    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }\r
+    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }\r
+    dy <<= 1;                                                  // dy is now 2*dy\r
+    dx <<= 1;                                                  // dx is now 2*dx\r
+\r
+    sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
+    if (dx > dy) {\r
+        int fraction = dy - (dx >> 1);                         // same as 2*dy - dx\r
+        while (x0 != x1) {\r
+            if (fraction >= 0) {\r
+                y0 += stepy;\r
+                fraction -= dx;                                // same as fraction -= 2*dx\r
+            }\r
+            x0 += stepx;\r
+            fraction += dy;                                    // same as fraction -= 2*dy\r
+            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
+        }\r
+    } else {\r
+        int fraction = dx - (dy >> 1);\r
+        while (y0 != y1) {\r
+            if (fraction >= 0) {\r
+                x0 += stepx;\r
+                fraction -= dy;\r
+            }\r
+            y0 += stepy;\r
+            fraction += dx;\r
+            sp_caxonomgrid_setpixel(buf, x0, y0, rgba);\r
+        }\r
+    }\r
+    \r
+}\r
+\r
+static void\r
+sp_grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)\r
+{\r
+    if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {\r
+        guint r, g, b, a;\r
+        gint y0, y1, y;\r
+        guchar *p;\r
+        r = NR_RGBA32_R(rgba);\r
+        g = NR_RGBA32_G (rgba);\r
+        b = NR_RGBA32_B (rgba);\r
+        a = NR_RGBA32_A (rgba);\r
+        y0 = MAX (buf->rect.y0, ys);\r
+        y1 = MIN (buf->rect.y1, ye + 1);\r
+        p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;\r
+        for (y = y0; y < y1; y++) {\r
+            p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);\r
+            p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);\r
+            p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);\r
+            p += buf->buf_rowstride;\r
+        }\r
+    }\r
+}\r
+\r
+/**\r
+    \brief  This function renders the grid on a particular canvas buffer\r
+    \param  item  The grid to render on the buffer\r
+    \param  buf   The buffer to render the grid on\r
+    \r
+    This function gets called a touch more than you might believe,\r
+    about once per tile.  This means that it could probably be optimized\r
+    and help things out.\r
+\r
+    Basically this function has to determine where in the canvas it is,\r
+    and how that associates with the grid.  It does this first by looking\r
+    at the bounding box of the buffer, and then calculates where the grid\r
+    starts in that buffer.  It will then step through grid lines until\r
+    it is outside of the buffer.\r
+\r
+    For each grid line it is drawn using the function \c sp_grid_hline\r
+    or \c sp_grid_vline.  These are convience functions for the sake\r
+    of making the function easier to read.\r
+\r
+    Also, there are emphasized lines on the grid.  While the \c syg and\r
+    \c sxg variable track grid positioning, the \c xlinestart and \c\r
+    ylinestart variables track the 'count' of what lines they are.  If\r
+    that count is a multiple of the line seperation between emphasis\r
+    lines, then that line is drawn in the emphasis color.\r
+*/\r
+static void\r
+sp_caxonomgrid_render (SPCanvasItem * item, SPCanvasBuf * buf)\r
+{\r
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);\r
+\r
+    sp_canvas_prepare_buffer (buf);\r
+              \r
+     // gc = gridcoordinates (the coordinates calculated from the grids origin 'grid->ow'.\r
+     // sc = screencoordinates ( for example "buf->rect.x0" is in screencoordinates )\r
+     // bc = buffer patch coordinates \r
+     \r
+     // tl = topleft ; br = bottomright\r
+    NR::Point buf_tl_gc;\r
+    NR::Point buf_br_gc;\r
+    buf_tl_gc[NR::X] = buf->rect.x0 - grid->ow[NR::X];\r
+    buf_tl_gc[NR::Y] = buf->rect.y0 - grid->ow[NR::Y];\r
+    buf_br_gc[NR::X] = buf->rect.x1 - grid->ow[NR::X];\r
+    buf_br_gc[NR::Y] = buf->rect.y1 - grid->ow[NR::Y];\r
+\r
+\r
+    gdouble x;\r
+    gdouble y;\r
+\r
+    // render the three separate line groups representing the main-axes:\r
+    // x-axis always goes from topleft to bottomright. (0,0) - (1,1)  \r
+    const gdouble xintercept_y_bc = (buf_tl_gc[NR::X] * grid->tan_angle[X]) - buf_tl_gc[NR::Y] ;\r
+    const gdouble xstart_y_sc = ( xintercept_y_bc - floor(xintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;\r
+    const gint  xlinestart = (gint) Inkscape::round( (xstart_y_sc - grid->ow[NR::Y]) / grid->lyw );\r
+    gint xlinenum;\r
+    // lijnen vanaf linker zijkant.\r
+    for (y = xstart_y_sc, xlinenum = xlinestart; y < buf->rect.y1; y += grid->lyw, xlinenum++) {\r
+        const gint x0 = buf->rect.x0;\r
+        const gint y0 = (gint) Inkscape::round(y);\r
+        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - y) / grid->tan_angle[X] );\r
+        const gint y1 = buf->rect.y1;\r
+            \r
+        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
+        } else {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
+        }\r
+    }\r
+    // lijnen vanaf bovenkant.\r
+    const gdouble xstart_x_sc = buf->rect.x0 + (grid->lxw_x - (xstart_y_sc - buf->rect.y0) / grid->tan_angle[X]) ;\r
+    for (x = xstart_x_sc, xlinenum = xlinestart; x < buf->rect.x1; x += grid->lxw_x, xlinenum--) {\r
+        const gint y0 = buf->rect.y0;\r
+        const gint y1 = buf->rect.y1;\r
+        const gint x0 = (gint) Inkscape::round(x);\r
+        const gint x1 = x0 + (gint) Inkscape::round( (y1 - y0) / grid->tan_angle[X] );\r
+            \r
+        if (!grid->scaled && (xlinenum % grid->empspacing) == 0) {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
+        } else {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
+        }\r
+    }\r
+    \r
+\r
+    // y-axis lines (vertical)\r
+    const gdouble ystart_x_sc = floor (buf_tl_gc[NR::X] / grid->spacing_ylines) * grid->spacing_ylines + grid->ow[NR::X];\r
+    const gint  ylinestart = (gint) Inkscape::round((ystart_x_sc - grid->ow[NR::X]) / grid->spacing_ylines);\r
+    gint ylinenum;\r
+    for (x = ystart_x_sc, ylinenum = ylinestart; x < buf->rect.x1; x += grid->spacing_ylines, ylinenum++) {\r
+        const gint x0 = (gint) Inkscape::round(x);\r
+\r
+        if (!grid->scaled && (ylinenum % grid->empspacing) == 0) {\r
+            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->empcolor);\r
+        } else {\r
+            sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, grid->color);\r
+        }\r
+    }\r
+\r
+    // z-axis always goes from bottomleft to topright. (0,1) - (1,0)  \r
+    const gdouble zintercept_y_bc = (buf_tl_gc[NR::X] * -grid->tan_angle[Z]) - buf_tl_gc[NR::Y] ;\r
+    const gdouble zstart_y_sc = ( zintercept_y_bc - floor(zintercept_y_bc/grid->lyw)*grid->lyw ) + buf->rect.y0;\r
+    const gint  zlinestart = (gint) Inkscape::round( (zstart_y_sc - grid->ow[NR::Y]) / grid->lyw );\r
+    gint zlinenum;\r
+    // lijnen vanaf linker zijkant.\r
+    for (y = zstart_y_sc, zlinenum = zlinestart; y < buf->rect.y1; y += grid->lyw, zlinenum++) {\r
+        const gint x0 = buf->rect.x0;\r
+        const gint y0 = (gint) Inkscape::round(y);\r
+        const gint x1 = x0 + (gint) Inkscape::round( (y - buf->rect.y0 ) / grid->tan_angle[Z] );\r
+        const gint y1 = buf->rect.y0;\r
+            \r
+        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
+        } else {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
+        }\r
+    }\r
+    // lijnen vanaf onderkant.\r
+    const gdouble zstart_x_sc = buf->rect.x0 + (y - buf->rect.y1) / grid->tan_angle[Z] ;\r
+    for (x = zstart_x_sc; x < buf->rect.x1; x += grid->lxw_z, zlinenum--) {\r
+        const gint y0 = buf->rect.y1;\r
+        const gint y1 = buf->rect.y0;\r
+        const gint x0 = (gint) Inkscape::round(x);\r
+        const gint x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - buf->rect.y0) / grid->tan_angle[Z] );\r
+            \r
+        if (!grid->scaled && (zlinenum % grid->empspacing) == 0) {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->empcolor);\r
+        } else {\r
+            sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, grid->color);\r
+        }\r
+    }\r
+    \r
+}\r
+\r
+static void\r
+sp_caxonomgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)\r
+{\r
+    SPCAxonomGrid *grid = SP_CAXONOMGRID (item);\r
+\r
+    if (parent_class->update)\r
+        (* parent_class->update) (item, affine, flags);\r
+\r
+    grid->ow = grid->origin * affine;\r
+    grid->sw = NR::Point(fabs(affine[0]),fabs(affine[3]));\r
+    \r
+    for(int dim = 0; dim < 2; dim++) {\r
+        gint scaling_factor = grid->empspacing;\r
+\r
+        if (scaling_factor <= 1)\r
+            scaling_factor = 5;\r
+\r
+        grid->scaled = FALSE;\r
+        while (grid->sw[dim] < 8.0) {\r
+            grid->scaled = TRUE;\r
+            grid->sw[dim] *= scaling_factor;\r
+            // First pass, go up to the major line spacing, then\r
+            // keep increasing by two.\r
+            scaling_factor = 2;\r
+        }\r
+    }\r
+\r
+    grid->spacing_ylines = grid->sw[NR::X] * grid->lengthy  /(grid->tan_angle[X] + grid->tan_angle[Z]);\r
+    grid->lyw            = grid->lengthy * grid->sw[NR::Y];\r
+    grid->lxw_x          = (grid->lengthy / grid->tan_angle[X]) * grid->sw[NR::X];\r
+    grid->lxw_z          = (grid->lengthy / grid->tan_angle[Z]) * grid->sw[NR::X];\r
+\r
+    if (grid->empspacing == 0) {\r
+        grid->scaled = TRUE;\r
+    }\r
+\r
+    sp_canvas_request_redraw (item->canvas,\r
+                     -1000000, -1000000,\r
+                     1000000, 1000000);\r
+                     \r
+    item->x1 = item->y1 = -1000000;\r
+    item->x2 = item->y2 = 1000000;\r
+}\r
+\r
+/*\r
+  Local Variables:\r
+  mode:c++\r
+  c-file-style:"stroustrup"\r
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+  indent-tabs-mode:nil\r
+  fill-column:99\r
+  End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h
new file mode 100644 (file)
index 0000000..22fceed
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef SP_CANVAS_AXONOMGRID_H\r
+#define SP_CANVAS_AXONOMGRID_H\r
+\r
+/*\r
+ * SPCAxonomGrid\r
+ *\r
+ * Generic (and quite unintelligent) modified copy of the grid item for gnome canvas\r
+ *\r
+ * Copyright (C) 2006 Johan Engelen  <johan@shouraizou.nl>\r
+ * Copyright (C) 2000 Lauris Kaplinski 2000\r
+ *\r
+ */\r
+\r
+#include <display/sp-canvas.h>\r
+#include <libnr/nr-coord.h>\r
+\r
+\r
+#define SP_TYPE_CAXONOMGRID            (sp_caxonomgrid_get_type ())\r
+#define SP_CAXONOMGRID(obj)            (GTK_CHECK_CAST ((obj), SP_TYPE_CAXONOMGRID, SPCAxonomGrid))\r
+#define SP_CAXONOMGRID_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_CAXONOMGRID, SPCAxonomGridClass))\r
+#define SP_IS_CAXONOMGRID(obj)         (GTK_CHECK_TYPE ((obj), SP_TYPE_CAXONOMGRID))\r
+#define SP_IS_CAXONOMGRID_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_CAXONOMGRID))\r
+\r
+\r
+/** \brief  All the variables that are tracked for a axonometric grid specific\r
+            canvas item. */\r
+struct SPCAxonomGrid : public SPCanvasItem{\r
+       NR::Point origin;     /**< Origin of the grid */\r
+       double lengthy;       /**< The lengths of the primary y-axis */\r
+       double angle_deg[3];  /**< Angle of each axis (note that angle[2] == 0) */\r
+       double angle_rad[3];  /**< Angle of each axis (note that angle[2] == 0) */\r
+       double tan_angle[3];  /**< tan(angle[.]) */\r
+       guint32 color;        /**< Color for normal lines */\r
+       guint32 empcolor;     /**< Color for emphasis lines */\r
+       gint empspacing;      /**< Spacing between emphasis lines */\r
+       bool scaled;          /**< Whether the grid is in scaled mode */\r
+       \r
+       NR::Point ow;         /**< Transformed origin by the affine for the zoom */\r
+       double lyw;           /**< Transformed length y by the affine for the zoom */\r
+       double lxw_x;\r
+       double lxw_z;\r
+       double spacing_ylines;\r
+                          \r
+    NR::Point sw;          /**< the scaling factors of the affine transform */\r
+};\r
+\r
+struct SPCAxonomGridClass {\r
+       SPCanvasItemClass parent_class;\r
+};\r
+\r
+\r
+/* Standard Gtk function */\r
+GtkType sp_caxonomgrid_get_type (void);\r
+\r
+\r
+\r
+#endif    \r
+\r
+\r
index 9c36b5057aa4df5f978a88e120914971b43816eb..54805f8725944cfd1de6d23a3691384da1124979 100644 (file)
@@ -7,6 +7,7 @@
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   bulia byak <buliabyak@users.sf.net>
  *
+ * Copyright (C) 2006      Johan Engelen <johan@shouraizou.nl>
  * Copyright (C) 1999-2005 Authors
  * Copyright (C) 2000-2001 Ximian, Inc.
  *
@@ -16,6 +17,7 @@
 #include "config.h"
 
 #include "display/canvas-grid.h"
+#include "display/canvas-axonomgrid.h"
 #include "helper/units.h"
 #include "svg/svg-color.h"
 #include "xml/repr.h"
@@ -107,6 +109,7 @@ static void sp_namedview_init(SPNamedView *nv)
 {
     nv->editable = TRUE;
     nv->showgrid = FALSE;
+    nv->gridtype = 0;
     nv->showguides = TRUE;
     nv->showborder = TRUE;
     nv->showpageshadow = TRUE;
@@ -133,6 +136,7 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape:
     sp_object_read_attr(object, "inkscape:document-units");
     sp_object_read_attr(object, "viewonly");
     sp_object_read_attr(object, "showgrid");
+    sp_object_read_attr(object, "gridtype");
     sp_object_read_attr(object, "showguides");
     sp_object_read_attr(object, "gridtolerance");
     sp_object_read_attr(object, "guidetolerance");
@@ -142,6 +146,8 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape:
     sp_object_read_attr(object, "gridoriginy");
     sp_object_read_attr(object, "gridspacingx");
     sp_object_read_attr(object, "gridspacingy");
+    sp_object_read_attr(object, "gridanglex");
+    sp_object_read_attr(object, "gridanglez");
     sp_object_read_attr(object, "gridempspacing");
     sp_object_read_attr(object, "gridcolor");
     sp_object_read_attr(object, "gridempcolor");
@@ -226,6 +232,11 @@ static void sp_namedview_set(SPObject *object, unsigned int key, const gchar *va
             nv->snap_manager.grid.setEnabled(nv->showgrid);
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
+       case SP_ATTR_GRIDTYPE:
+            nv->gridtype = sp_str_to_bool(value);
+            sp_namedview_setup_grid(nv);
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
        case SP_ATTR_SHOWGUIDES:
             if (!value) { // show guides if not specified, for backwards compatibility
                 nv->showguides = TRUE;
@@ -294,6 +305,18 @@ static void sp_namedview_set(SPObject *object, unsigned int key, const gchar *va
             object->requestModified(SP_OBJECT_MODIFIED_FLAG);
             break;
        }
+       case SP_ATTR_GRIDANGLEX:
+       case SP_ATTR_GRIDANGLEZ:
+       {
+            unsigned const d = (key == SP_ATTR_GRIDANGLEZ); // 0=X  1=Z
+            nv->gridangle[d] = 30; // 30 deg default
+            if (value) {
+                nv->gridangle[d] = g_ascii_strtod(value, NULL);
+            }
+            sp_namedview_setup_grid(nv);
+            object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+       }
        case SP_ATTR_GRIDCOLOR:
             nv->gridcolor = (nv->gridcolor & 0xff) | (DEFAULTGRIDCOLOR & 0xffffff00);
             if (value) {
@@ -616,11 +639,17 @@ void SPNamedView::show(SPDesktop *desktop)
 
     views = g_slist_prepend(views, desktop);
 
-    SPCanvasItem *item = sp_canvas_item_new(sp_desktop_grid(desktop), SP_TYPE_CGRID, NULL);
+    SPCanvasItem * item = sp_canvas_item_new(sp_desktop_grid(desktop), SP_TYPE_CGRID, NULL);
+    // since we're keeping a copy, we need to bump up the ref count
+    gtk_object_ref(GTK_OBJECT(item));
+    gridviews = g_slist_prepend(gridviews, item);
+
+    item = sp_canvas_item_new(sp_desktop_grid(desktop), SP_TYPE_CAXONOMGRID, NULL);
     // since we're keeping a copy, we need to bump up the ref count
     gtk_object_ref(GTK_OBJECT(item));
     gridviews = g_slist_prepend(gridviews, item);
-    sp_namedview_setup_grid_item(this, item);
+
+    sp_namedview_setup_grid(this);
 }
 
 /*
@@ -723,15 +752,11 @@ void SPNamedView::hide(SPDesktop const *desktop)
     GSList *l;
     for (l = gridviews; l != NULL; l = l->next) {
         if (SP_CANVAS_ITEM(l->data)->canvas == sp_desktop_canvas(desktop)) {
-            break;
+            sp_canvas_item_hide(SP_CANVAS_ITEM(l->data));
+            gtk_object_unref(GTK_OBJECT(l->data));
+            gridviews = g_slist_remove(gridviews, l->data);
         }
     }
-
-    g_assert(l);
-
-    sp_canvas_item_hide(SP_CANVAS_ITEM(l->data));
-    gtk_object_unref(GTK_OBJECT(l->data));
-    gridviews = g_slist_remove(gridviews, l->data);
 }
 
 void SPNamedView::activateGuides(gpointer desktop, gboolean active)
@@ -795,6 +820,17 @@ void sp_namedview_toggle_grid(SPDocument *doc, Inkscape::XML::Node *repr)
     sp_document_set_undo_sensitive(doc, saved);
 }
 
+void sp_namedview_set_gridtype(bool type, SPDocument *doc, Inkscape::XML::Node *repr)
+{
+    bool saved = sp_document_get_undo_sensitive(doc);
+    sp_document_set_undo_sensitive(doc, false);
+
+    sp_repr_set_boolean(repr, "showgrid", type);
+
+    doc->rroot->setAttribute("sodipodi:modified", "true");
+    sp_document_set_undo_sensitive(doc, saved);
+}
+
 static void sp_namedview_setup_grid(SPNamedView *nv)
 {
     for (GSList *l = nv->gridviews; l != NULL; l = l->next) {
@@ -804,23 +840,41 @@ static void sp_namedview_setup_grid(SPNamedView *nv)
 
 static void sp_namedview_setup_grid_item(SPNamedView *nv, SPCanvasItem *item)
 {
-    if (nv->showgrid) {
+    bool btype = SP_IS_CAXONOMGRID(GTK_OBJECT(item));
+
+    if ( nv->showgrid && (nv->gridtype == btype) ) {
         sp_canvas_item_show(item);
     } else {
         sp_canvas_item_hide(item);
     }
-
-    sp_canvas_item_set((GtkObject *) item,
-                       "color", nv->gridcolor,
-                       "originx", nv->gridorigin[NR::X],
-                       "originy", nv->gridorigin[NR::Y],
-                       "spacingx", nv->gridspacing[NR::X],
-                       "spacingy", nv->gridspacing[NR::Y],
-                       "empcolor", nv->gridempcolor,
-                       "empspacing", nv->gridempspacing,
-                       NULL);
+    
+    if (!btype){
+        // CGRID
+        sp_canvas_item_set((GtkObject *) item,
+                           "color", nv->gridcolor,
+                           "originx", nv->gridorigin[NR::X],
+                           "originy", nv->gridorigin[NR::Y],
+                           "spacingx", nv->gridspacing[NR::X],
+                           "spacingy", nv->gridspacing[NR::Y],
+                           "empcolor", nv->gridempcolor,
+                           "empspacing", nv->gridempspacing,
+                           NULL);
+    } else {
+        // CAXONOMGRID
+        sp_canvas_item_set((GtkObject *) item,
+                           "color", nv->gridcolor,
+                           "originx", nv->gridorigin[NR::X],
+                           "originy", nv->gridorigin[NR::Y],
+                           "spacingy", nv->gridspacing[NR::Y],
+                           "anglex", nv->gridangle[0],
+                           "anglez", nv->gridangle[1],
+                           "empcolor", nv->gridempcolor,
+                           "empspacing", nv->gridempspacing,
+                           NULL);
+    }
 }
 
+
 gchar const *SPNamedView::getName() const
 {
     SPException ex;
index 54291413e078d05a561a99a31dd01992880e53f7..6625fd027f8f50d1791e71ff3349e44ae5f6cc2d 100644 (file)
@@ -7,6 +7,7 @@
  * Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
  * Copyright (C) Lauris Kaplinski 2000-2002
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
@@ -32,6 +33,7 @@ enum {
 struct SPNamedView : public SPObjectGroup {
     unsigned int editable : 1;
     unsigned int showgrid : 1;
+    unsigned int gridtype : 1; // 0=normal 1=axonometric
     unsigned int showguides : 1;
     unsigned int showborder : 1;
     unsigned int showpageshadow : 1;
@@ -51,6 +53,7 @@ struct SPNamedView : public SPObjectGroup {
     /* Grid data is in points regardless of unit */
     NR::Point gridorigin;
     gdouble gridspacing[2];
+    gdouble gridangle[2];   // for axonometric grid
     gint gridempspacing;
 
     SPUnit const *doc_units;
@@ -81,6 +84,7 @@ struct SPNamedView : public SPObjectGroup {
     GSList *guides;
     GSList *views;
     GSList *gridviews;
+    
     gint viewcount;
 
     void show(SPDesktop *desktop);
@@ -105,6 +109,7 @@ void sp_namedview_document_from_window(SPDesktop *desktop);
 
 void sp_namedview_toggle_guides(SPDocument *doc, Inkscape::XML::Node *repr);
 void sp_namedview_toggle_grid(SPDocument *doc, Inkscape::XML::Node *repr);
+void sp_namedview_set_gridtype(bool type, SPDocument *doc, Inkscape::XML::Node *repr);
 
 #endif /* !INKSCAPE_SP_NAMEDVIEW_H */
 
index 726c0ad948f866a3f99a3033c7b4917cb7475b57..c32ac9f1f46eaee3fc18768c4bcd651b6fa30550 100644 (file)
@@ -9,6 +9,7 @@
  *   Jon Phillips <jon@rejon.org>
  *   Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm)
  *
+ * Copyright (C) 2006 Johan Engelen  <johan@shouraizou.nl>
  * Copyright (C) 2000 - 2005 Authors
  *
  * Released under GNU GPL.  Read the file 'COPYING' for more information
@@ -231,6 +232,11 @@ DocumentProperties::build_grid()
     /// Dissenting view: you want snapping without grid.
     
     _rcbgrid.init (_("_Show grid"), _("Show or hide grid"), "showgrid", _wr);
+    _rrb_gridtype.init (_("Grid type:"), _("Normal (2D)"), _("Axonometric (3D)"),
+                _("The normal grid with vertical and horizontal lines."),
+                _("A grid with vertical lines and two diagonal line groups, each representing the projection of a primary axis."),
+                _("gridtype"), _wr);
+    
     _rumg.init (_("Grid _units:"), "grid_units", _wr);
     _rsu_ox.init (_("_Origin X:"), _("X coordinate of grid origin"), 
                   "gridoriginx", _rumg, _wr);
@@ -240,6 +246,10 @@ DocumentProperties::build_grid()
                   "gridspacingx", _rumg, _wr);
     _rsu_sy.init (_("Spacing _Y:"), _("Distance of horizontal grid lines"), 
                   "gridspacingy", _rumg, _wr);
+    _rsu_ax.init (_("Angle X:"), _("Angle of x-axis of axonometric grid"), 
+                  "gridanglex", _rumg, _wr);
+    _rsu_az.init (_("Angle Z:"), _("Angle of z-axis of axonometric grid"), 
+                  "gridanglez", _rumg, _wr);
     _rcp_gcol.init (_("Grid line _color:"), _("Grid line color"), 
                     _("Color of grid lines"), "gridcolor", "gridopacity", _wr);
     _rcp_gmcol.init (_("Ma_jor grid line color:"), _("Major grid line color"), 
@@ -261,11 +271,14 @@ DocumentProperties::build_grid()
     {
         label_grid,         0,
         0,                  _rcbgrid._button,
+        _rrb_gridtype._hbox,      0,
         _rumg._label,       _rumg._sel,
         0,                  _rsu_ox.getSU(),
         0,                  _rsu_oy.getSU(),
         0,                  _rsu_sx.getSU(),
         0,                  _rsu_sy.getSU(),
+        0,                  _rsu_ax.getSU(),
+        0,                  _rsu_az.getSU(),
         _rcp_gcol._label,   _rcp_gcol._cp, 
         0,                  0,
         _rcp_gmcol._label,  _rcp_gmcol._cp,
@@ -386,6 +399,7 @@ DocumentProperties::update()
 
     //-----------------------------------------------------------grid page
     _rcbgrid.setActive (nv->showgrid);
+    _rrb_gridtype.setValue (nv->gridtype);
     _rumg.setUnit (nv->gridunit);
     
     gdouble val;
@@ -402,6 +416,11 @@ DocumentProperties::update()
     double gridy = sp_pixels_get_units (val, *(nv->gridunit));
     _rsu_sy.setValue (gridy);
 
+    val = nv->gridangle[0];
+    _rsu_ax.setValue (val);
+    val = nv->gridangle[1];
+    _rsu_az.setValue (val);
+
     _rcp_gcol.setRgba32 (nv->gridcolor);
     _rcp_gmcol.setRgba32 (nv->gridempcolor);
     _rsi.setValue (nv->gridempspacing);
index ae2c30cbf8c10907460a99492a6075a0a37eaba2..0f67508f2d4e47cedd560a0b48c7cf58a6b52bc5 100644 (file)
@@ -5,6 +5,7 @@
  *   Ralf Stephan <ralf@ark.in-berlin.de>
  *   Bryce W. Harrington <bryce@bryceharrington.org>
  *
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
  * Copyright (C) 2004, 2005 Authors
  *
  * Released under GNU GPL.  Read the file 'COPYING' for more information.
@@ -61,8 +62,9 @@ protected:
     PageSizer             _page_sizer;
     //---------------------------------------------------------------
     RegisteredCheckButton _rcbgrid, _rcbsnbb, _rcbsnnod;
+    RegisteredRadioButtonPair _rrb_gridtype;
     RegisteredUnitMenu    _rumg, _rums;
-    RegisteredScalarUnit  _rsu_ox, _rsu_oy, _rsu_sx, _rsu_sy;
+    RegisteredScalarUnit  _rsu_ox, _rsu_oy, _rsu_sx, _rsu_sy, _rsu_ax, _rsu_az;
     RegisteredColorPicker _rcp_gcol, _rcp_gmcol;
     RegisteredSuffixedInteger _rsi;
     //---------------------------------------------------------------