SVG output for cad3d - 2nd attempt
John Pybus
john@pybus.org
Wed, 05 May 2004 00:25:13 +0100
This is a multi-part message in MIME format.
--------------090707080105060605060601
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
...and this time, as a special bonus, it even creates maps that're the
right way up!
It also sets the initial viewport to match the scale specified.
Yours,
John
--------------090707080105060605060601
Content-Type: text/plain;
name="cad3d.patch2"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="cad3d.patch2"
--- src/cad3d.c.orig 2004-05-03 23:45:21.000000000 +0100
+++ src/cad3d.c 2004-05-05 00:15:31.000000000 +0100
@@ -49,6 +49,12 @@
#define POINTS_PER_INCH 72.0
#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
+#define SQRT_2 1.41421356237309504880168872420969
+
+#define LEGS 1
+#define STNS 2
+#define LABELS 4
+
/* default to DXF */
#define FMT_DEFAULT FMT_DXF
@@ -62,6 +68,7 @@
static double grid; /* grid spacing (or 0 for no grid) */
static double scale = 500.0;
static double factor;
+static const char *unit = "mm";
static img *pimg;
static const char *survey = NULL;
@@ -333,26 +340,6 @@
static point **htab;
static void
-plt_header(void)
-{
- size_t i;
- htab = osmalloc(HTAB_SIZE * ossizeof(point *));
- for (i = 0; i < HTAB_SIZE; ++i) htab[i] = NULL;
- /* Survex is E, N, Alt - PLT file is N, E, Alt */
- fprintf(fh, "Z %.3f %.3f %.3f %.3f %.3f %.3f\r\n",
- min_y / METRES_PER_FOOT, max_y / METRES_PER_FOOT,
- min_x / METRES_PER_FOOT, max_x / METRES_PER_FOOT,
- min_z / METRES_PER_FOOT, max_z / METRES_PER_FOOT);
- fprintf(fh, "N%s D 1 1 1 C%s\r\n", survey ? survey : "X", pimg->title);
-}
-
-static void
-plt_start_pass(int layer)
-{
- layer = layer;
-}
-
-static void
set_name(const img_point *p, const char *s)
{
int hash;
@@ -368,9 +355,9 @@
hash = (hash_data(u.data, sizeof(int) * 3) & (HTAB_SIZE - 1));
for (pt = htab[hash]; pt; pt = pt->next) {
if (pt->p.x == p->x && pt->p.y == p->y && pt->p.z == p->z) {
- /* already got name for these coordinates */
- /* FIXME: what about multiple names for the same station? */
- return;
+ /* already got name for these coordinates */
+ /* FIXME: what about multiple names for the same station? */
+ return;
}
}
@@ -406,6 +393,122 @@
}
static void
+svg_header(void)
+{
+ size_t i;
+ htab = osmalloc(HTAB_SIZE * ossizeof(point *));
+ for (i = 0; i < HTAB_SIZE; ++i) htab[i] = NULL;
+ fprintf(fh, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
+ fprintf(fh, "<svg width=\"%.3f%s\" height=\"%.3f%s\""
+ " viewBox=\"0 0 %0.3f %0.3f\">\n",
+ (max_x - min_x) * factor, unit, (max_y - min_y) * factor, unit,
+ (max_x - min_x) * factor, (max_y - min_y) * factor );
+ fprintf(fh, "<g transform=\"translate(%.3f %.3f)\">\n",
+ min_x * -factor, max_y * factor);
+}
+
+static bool to_close = 0;
+static bool close_g = 0;
+
+static void
+svg_start_pass(int layer)
+{
+ if (to_close) {
+ fprintf(fh, "\"/>\n");
+ to_close = 0;
+ }
+ if (close_g) {
+ fprintf(fh, "</g>\n");
+ }
+ close_g = 1;
+
+ fprintf(fh, "<g id=\"%s\"", layer_names[layer]);
+ if (layer & LEGS)
+ fprintf(fh, " style=\"stroke:black;fill:none;stroke-width:0.4\"");
+ else if (layer & STNS)
+ fprintf(fh, " style=\"stroke:black;fill:none;stroke-width:0.05\"");
+ else if (layer & LABELS)
+ fprintf(fh, " style=\"font-size:%.3f\"", text_height);
+ fprintf(fh, ">\n");
+}
+
+static void
+svg_move(const img_point *p)
+{
+ if (to_close) {
+ fprintf(fh, "\"/>\n");
+ }
+ fprintf(fh, "<path d=\"M %.3f %.3f",
+ p->x * factor, p->y * -factor);
+ to_close = 1;
+}
+
+static void
+svg_line(const img_point *p1, const img_point *p, bool fSurface)
+{
+ fSurface = fSurface; /* unused */
+ p1 = p1; /* unused */
+ fprintf(fh, "L%.3f %.3f", p->x * factor, p->y * -factor);
+ to_close = 1;
+}
+
+static void
+svg_label(const img_point *p, const char *s, bool fSurface)
+{
+ fSurface = fSurface; /* unused */
+ fprintf(fh, "<text transform=\"translate(%.3f %.3f)\">",
+ p->x * factor, p->y * -factor);
+ fprintf(fh, s);
+ fprintf(fh, "</text>\n");
+ set_name(p, s);
+}
+
+static void
+svg_cross(const img_point *p, bool fSurface)
+{
+ fSurface = fSurface; /* unused */
+ fprintf(fh, "<circle id=\"%s\" cx=\"%.3f\" cy=\"%.3f\" r=\"%.3f\"/>\n",
+ find_name(p), p->x * factor,
+ p->y * -factor, MARKER_SIZE * SQRT_2);
+ fprintf(fh, "<path d=\"M%.3f %.3fL%.3f %.3fM%.3f %.3fL%.3f %.3f\"/>\n",
+ p->x * factor - MARKER_SIZE, p->y * -factor - MARKER_SIZE,
+ p->x * factor + MARKER_SIZE, p->y * -factor + MARKER_SIZE,
+ p->x * factor + MARKER_SIZE, p->y * -factor - MARKER_SIZE,
+ p->x * factor - MARKER_SIZE, p->y * -factor + MARKER_SIZE );
+}
+
+static void
+svg_footer(void) ////
+{
+ if (to_close) {
+ fprintf(fh, "\"/>\n");
+ to_close = 0;
+ }
+ fprintf(fh, "</g>\n");
+ fprintf(fh, "</g>\n</svg>");
+}
+
+static void
+plt_header(void)
+{
+ size_t i;
+ htab = osmalloc(HTAB_SIZE * ossizeof(point *));
+ for (i = 0; i < HTAB_SIZE; ++i) htab[i] = NULL;
+ /* Survex is E, N, Alt - PLT file is N, E, Alt */
+ fprintf(fh, "Z %.3f %.3f %.3f %.3f %.3f %.3f\r\n",
+ min_y / METRES_PER_FOOT, max_y / METRES_PER_FOOT,
+ min_x / METRES_PER_FOOT, max_x / METRES_PER_FOOT,
+ min_z / METRES_PER_FOOT, max_z / METRES_PER_FOOT);
+ fprintf(fh, "N%s D 1 1 1 C%s\r\n", survey ? survey : "X", pimg->title);
+}
+
+static void
+plt_start_pass(int layer)
+{
+ layer = layer;
+}
+
+static void
plt_move(const img_point *p)
{
/* Survex is E, N, Alt - PLT file is N, E, Alt */
@@ -458,12 +561,10 @@
putc('\x1a', fh);
}
-#define LEGS 1
-#define STNS 2
-#define LABELS 4
static int dxf_passes[] = { LEGS|STNS|LABELS, 0 };
static int sketch_passes[] = { LEGS, STNS, LABELS, 0 };
static int plt_passes[] = { LABELS, LEGS, 0 };
+static int svg_passes[] = { LEGS, LABELS, STNS, 0 };
int
main(int argc, char **argv)
@@ -476,8 +577,8 @@
int elevation = 0;
double elev_angle = 0;
double s = 0, c = 0;
- enum { FMT_DXF = 0, FMT_SKETCH, FMT_PLT, FMT_AUTO } format;
- static const char *extensions[] = { "dxf", "sk", "plt" };
+ enum { FMT_DXF = 0, FMT_SKETCH, FMT_PLT, FMT_SVG, FMT_AUTO } format;
+ static const char *extensions[] = { "dxf", "sk", "plt", "svg" };
int *pass;
void (*header)(void);
@@ -504,12 +605,13 @@
{"dxf", no_argument, 0, 'D'},
{"sketch", no_argument, 0, 'S'},
{"plt", no_argument, 0, 'P'},
+ {"svg", no_argument, 0, 'V'},
{"help", no_argument, 0, HLP_HELP},
{"version", no_argument, 0, HLP_VERSION},
{0,0,0,0}
};
-#define short_opts "s:cnlg::t:m:e:r:DSP"
+#define short_opts "s:cnlg::t:m:e:r:DSPV"
/* TRANSLATE */
static struct help_msg help[] = {
@@ -525,6 +627,7 @@
{HLP_ENCODELONG(9), "produce DXF output"},
{HLP_ENCODELONG(10), "produce Sketch output"},
{HLP_ENCODELONG(11), "produce Compass PLT output for Carto"},
+ {HLP_ENCODELONG(12), "produce SVG output"},
{0,0}
};
@@ -588,6 +691,9 @@
case 'P':
format = FMT_PLT;
break;
+ case 'V':
+ format = FMT_SVG;
+ break;
case 's':
survey = optarg;
break;
@@ -656,6 +762,18 @@
pass = plt_passes;
mode = "wb"; /* Binary file output */
break;
+ case FMT_SVG:
+ header = svg_header;
+ start_pass = svg_start_pass;
+ move = svg_move;
+ line = svg_line;
+ label = svg_label;
+ cross = svg_cross;
+ footer = svg_footer;
+ pass = svg_passes;
+ factor = 1000.0 / scale;
+ mode = "wb"; /* Binary file output */
+ break;
default:
exit(1);
}
--------------090707080105060605060601--