src/sn-tex.c: Make it possible to specify the absolute width of the graphic.
authorFlorian Forster <octo@leeloo.octo.it>
Mon, 20 Dec 2010 09:55:50 +0000 (10:55 +0100)
committerFlorian Forster <octo@leeloo.octo.it>
Mon, 20 Dec 2010 09:55:50 +0000 (10:55 +0100)
src/sn-svg.c
src/sn-tex.c

index ee60e80..47d7f93 100644 (file)
 
 #include "config.h"
 
+#ifndef _ISOC99_SOURCE
+# define _ISOC99_SOURCE
+#endif
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -70,7 +77,7 @@ static int read_options (int argc, char **argv) /* {{{ */
   return (0);
 } /* }}} int read_options */
 
-static double determine_stage_width (sn_stage_t *s)
+static double determine_stage_width (sn_stage_t *s) /* {{{ */
 {
   int lines[s->comparators_num];
   int right[s->comparators_num];
@@ -103,7 +110,7 @@ static double determine_stage_width (sn_stage_t *s)
   assert (lines_used >= 1);
 
   return (((double) (lines_used - 1)) * INNER_SPACING);
-}
+} /* }}} double determine_stage_width */
 
 static double determine_network_width (sn_network_t *n) /* {{{ */
 {
index a2c031d..95bf61d 100644 (file)
 
 #include <stdlib.h>
 #include <stdio.h>
-
-#define SCALE 0.7
-#define INNER_SPACING 0.35
-#define OUTER_SPACING 1.5
+#include <unistd.h>
+#include <assert.h>
 
 #include "sn_network.h"
 
-static double x_offset = OUTER_SPACING;
+/* 21cm (DIN-A4) - 2x3cm Rand = 15cm
+static double output_width = 15.0;
+static double scale = 1.0;
+static double inner_spacing = 0.3;
+static double outer_spacing = 1.0;
+static double vertical_spacing = 0.8;
+
+static double x_offset;
 static int next_vertex_number = 0;
 
-static int tex_show_stage (sn_stage_t *s)
+#define INPUT_TO_Y(i) (((double) (i)) * vertical_spacing)
+
+static void exit_usage (void) /* {{{ */
+{
+  printf ("Usage: sn-tex [options] [file]\n"
+      "\n"
+      "Valid options are:\n"
+      "  -w <width>   Specify the width of the graph (in TikZ default units).\n" 
+      "\n");
+  exit (EXIT_FAILURE);
+} /* }}} void exit_usage */
+
+static int read_options (int argc, char **argv) /* {{{ */
+{
+  int option;
+
+  while ((option = getopt (argc, argv, "w:h?")) != -1)
+  {
+    switch (option)
+    {
+      case 'w':
+      {
+       double width = atof (optarg);
+       if (width <= 0.0)
+       {
+         fprintf (stderr, "Invalid width argument: %s\n", optarg);
+         exit (EXIT_FAILURE);
+       }
+       output_width = width;
+       break;
+      }
+
+      case 'h':
+      case '?':
+      default:
+       exit_usage ();
+    }
+  }
+
+  return (0);
+} /* }}} int read_options */
+
+static double determine_stage_width (sn_stage_t *s) /* {{{ */
+{
+  int lines[s->comparators_num];
+  int right[s->comparators_num];
+  int lines_used = 0;
+  int i;
+
+  if (SN_STAGE_COMP_NUM (s) == 0)
+    return (0.0);
+
+  for (i = 0; i < SN_STAGE_COMP_NUM (s); i++)
+  {
+    lines[i] = -1;
+    right[i] = -1;
+  }
+
+  for (i = 0; i < SN_STAGE_COMP_NUM (s); i++)
+  {
+    int j;
+    sn_comparator_t *c = SN_STAGE_COMP_GET (s, i);
+
+    for (j = 0; j < lines_used; j++)
+      if (SN_COMP_LEFT (c) > right[j])
+       break;
+
+    lines[i] = j;
+    right[j] = SN_COMP_RIGHT (c);
+    if (j >= lines_used)
+      lines_used = j + 1;
+  }
+  assert (lines_used >= 1);
+
+  return (((double) (lines_used - 1)) * inner_spacing);
+} /* }}} double determine_stage_width */
+
+static double determine_network_width (sn_network_t *n) /* {{{ */
+{
+  double width;
+  int i;
+
+  /* Spacing between stages and at the beginning and end of the network */
+  width = (SN_NETWORK_STAGE_NUM (n) + 1) * outer_spacing;
+
+  /* Spacing required within a stage */
+  for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++)
+    width += determine_stage_width (SN_NETWORK_STAGE_GET (n, i));
+
+  return (width);
+} /* }}} double determine_network_width */
+
+static int tex_show_stage (sn_stage_t *s) /* {{{ */
 {
   int lines[s->comparators_num];
   int right[s->comparators_num];
@@ -74,57 +171,71 @@ static int tex_show_stage (sn_stage_t *s)
     if (j >= lines_used)
       lines_used = j + 1;
 
-    printf ("\\node[vertex] (v%i) at (%.2f,%i) {};\n"
-       "\\node[vertex] (v%i) at (%.2f,%i) {};\n"
+    printf ("\\node[vertex] (v%i) at (%.2f,%.2f) {};\n"
+       "\\node[vertex] (v%i) at (%.2f,%.2f) {};\n"
        "\\path[comp] (v%i) -- (v%i);\n"
        "\n",
-       min_num, x_offset + (j * INNER_SPACING), c->min,
-       max_num, x_offset + (j * INNER_SPACING), c->max,
+       min_num, x_offset + (j * inner_spacing), INPUT_TO_Y (c->min),
+       max_num, x_offset + (j * inner_spacing), INPUT_TO_Y (c->max),
        min_num, max_num);
   }
 
-  x_offset = x_offset + ((lines_used - 1) * INNER_SPACING) + OUTER_SPACING;
+  x_offset = x_offset + ((lines_used - 1) * inner_spacing) + outer_spacing;
 
   return (0);
-} /* int tex_show_stage */
+} /* }}} int tex_show_stage */
 
-int main (int argc, char **argv)
+int main (int argc, char **argv) /* {{{ */
 {
   sn_network_t *n;
   FILE *fh = NULL;
+  double orig_width;
   int i;
 
-  if (argc == 1)
+  read_options (argc, argv);
+
+  if ((argc - optind) == 0)
     fh = stdin;
-  else if (argc == 2)
-    fh = fopen (argv[1], "r");
+  else if ((argc - optind) == 1)
+    fh = fopen (argv[optind], "r");
 
   if (fh == NULL)
-  {
-    printf ("fh == NULL!\n");
-    return (1);
-  }
+    exit_usage ();
 
   n = sn_network_read (fh);
-
   if (n == NULL)
   {
-    printf ("n == NULL!\n");
-    return (1);
+    fprintf (stderr, "Unable to read network from file handle.\n");
+    exit (EXIT_FAILURE);
+  }
+
+  orig_width = determine_network_width (n);
+  if (orig_width <= 0.0)
+  {
+    fprintf (stderr, "determine_network_width returned invalid value %g.\n",
+       orig_width);
+    exit (EXIT_FAILURE);
   }
 
-  printf ("\\begin{tikzpicture}[scale=%.2f,auto]\n", SCALE);
+  scale = output_width / orig_width;
+  inner_spacing *= scale;
+  outer_spacing *= scale;
+  vertical_spacing *= scale;
+
+  x_offset = outer_spacing;
+
+  printf ("\\begin{tikzpicture}[auto]\n");
 
   for (i = 0; i < SN_NETWORK_STAGE_NUM (n); i++)
      tex_show_stage (SN_NETWORK_STAGE_GET (n, i));
 
   for (i = 0; i < SN_NETWORK_INPUT_NUM (n); i++)
-    printf ("\\path[edge] (0,%i) -- (%.2f,%i);\n",
-       i, x_offset, i);
+    printf ("\\path[edge] (0,%.2f) -- (%.2f,%.2f);\n",
+       INPUT_TO_Y (i), x_offset, INPUT_TO_Y (i));
 
   printf ("\\end{tikzpicture}\n");
 
   return (0);
-} /* int main */
+} /* }}} int main */
 
-/* vim: set shiftwidth=2 softtabstop=2 : */
+/* vim: set shiftwidth=2 softtabstop=2 fdm=marker : */