summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesper Jensen <jesper@jnsn.dev>2025-12-07 23:11:22 +0100
committerJesper Jensen <jesper@jnsn.dev>2025-12-07 23:11:22 +0100
commit7a5e295029e8a2c176e4b75f06f52a43bca7ccbd (patch)
tree8f7c812175acdcae0ea6a6e3b72c2d5b64ad388e
parente22588e908a9a2b172a8965cfd8767305dcb3459 (diff)
A little bit of cleanup and renaming
-rw-r--r--inc/cad/construction.h2
-rw-r--r--inc/cad/log.h8
-rw-r--r--inc/cad/svg.h26
-rw-r--r--src/construction.c2
-rw-r--r--src/main.c143
-rw-r--r--src/solve.c49
-rw-r--r--src/svg.c99
-rw-r--r--src/topology.c3
8 files changed, 187 insertions, 145 deletions
diff --git a/inc/cad/construction.h b/inc/cad/construction.h
index 71bc432..e4b0428 100644
--- a/inc/cad/construction.h
+++ b/inc/cad/construction.h
@@ -78,7 +78,7 @@ struct drawing {
};
struct element* insert_cmd(struct drawing *drawing, struct command cmd);
-void execute_drawing(struct drawing *drawing, double inputs[]);
+void place_points(struct drawing *drawing, double inputs[]);
bool circle_line_intersect(struct circle circle, struct line line, uint8_t root, struct point *point);
void line_through_points(struct point p1, struct point p2, struct line* l);
diff --git a/inc/cad/log.h b/inc/cad/log.h
new file mode 100644
index 0000000..dd46479
--- /dev/null
+++ b/inc/cad/log.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#define LOG(fmt, ...) \
+ fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__);
+
+#define CRASH(fmt, ...) \
+ fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
+ abort();
diff --git a/inc/cad/svg.h b/inc/cad/svg.h
index 7a7e799..e44cf3a 100644
--- a/inc/cad/svg.h
+++ b/inc/cad/svg.h
@@ -11,12 +11,22 @@ enum LineStyle {
};
#define TEXT_OFFSET 0.4
-void plot_line_between(struct point p1, struct point p2);
-void plot_arc_between_style(struct point c, struct point p1, struct point p2, enum LineStyle style);
-void plot_arc_between(struct point c, struct point p1, struct point p2);
-void plot_text(struct point p, double angle, char* str);
+enum CanvasState {
+ CANVAS_INIT,
+ CANVAS_DRAWING,
+};
+
+struct canvas {
+ enum CanvasState state;
+ FILE *f;
+};
+
+void plot_line_between(struct canvas *canvas, struct point p1, struct point p2);
+void plot_arc_between_style(struct canvas *canvas, struct point c, struct point p1, struct point p2, enum LineStyle style);
+void plot_arc_between(struct canvas *canvas, struct point c, struct point p1, struct point p2);
+void plot_text(struct canvas *canvas, struct point p, double angle, char* str);
-void begin_drawing();
-void draw_constraints(struct constraints *constraints);
-void draw_topology(struct topology *topo);
-void end_drawing();
+void begin_drawing(struct canvas *canvas);
+void draw_constraints(struct canvas *canvas, struct constraints *constraints);
+void draw_topology(struct canvas *canvas, struct topology *topo);
+void end_drawing(struct canvas *canvas);
diff --git a/src/construction.c b/src/construction.c
index 209b167..23f02a7 100644
--- a/src/construction.c
+++ b/src/construction.c
@@ -68,7 +68,7 @@ struct element* insert_cmd(struct drawing *drawing, struct command cmd) {
#define SETSIGN(b, v) ((v) * ((2 * (b)) - 1))
-void execute_drawing(struct drawing *drawing, double inputs[]) {
+void place_points(struct drawing *drawing, double inputs[]) {
for(struct command *current = drawing->root; current != NULL; current = current->next) {
switch(current->op) {
case CMD_VALUE_INPUT: {
diff --git a/src/main.c b/src/main.c
index 6fc50c0..fa0f66a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,60 +10,6 @@
#include "cad/solve.h"
#include "cad/svg.h"
-void plot_point(struct point p) {
- printf("<circle cx=\"%f\" cy=\"%f\" r=\".4\" fill=\"black\" />\n", p.pos[0], -p.pos[1]);
-}
-
-void plot_line(struct line l) {
- char *style_str = "stroke=\"black\" stroke-width=\"0.2\"";
- if(fabs(l.norm[0]) < fabs(l.norm[1])) {
- double minx = -50;
- double maxx = 50;
-
- double miny = -(l.norm[0] * minx + l.C) / l.norm[1];
- double maxy = -(l.norm[0] * maxx + l.C) / l.norm[1];
- printf("<line %s x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n", style_str, minx, -miny, maxx, -maxy);
- } else {
- double miny = -50;
- double maxy = 50;
-
- double minx = -(l.norm[1] * miny + l.C) / l.norm[0];
- double maxx = -(l.norm[1] * maxy + l.C) / l.norm[0];
- printf("<line %s x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n", style_str, minx, -miny, maxx, -maxy);
- }
-
- double d0 = glm_vec2_norm2(l.norm);
-
- vec2 p0 = {0, 0};
- glm_vec2_mulsubs(l.norm, l.C, p0);
- glm_vec2_divs(p0, d0, p0);
-
- vec2 p1;
- glm_vec2_add(p0, l.norm, p1);
-
- printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" stroke-width=\".2\" />\n", p0[0], -p0[1], p1[0], -p1[1]);
-}
-
-void plot_circle(struct circle c) {
- printf("<circle cx=\"%f\" cy=\"%f\" r=\"%f\" fill=\"none\" stroke=\"black\" stroke-width=\".1\" />\n", c.center[0], -c.center[1], c.radius);
-}
-
-void plot_generic(struct element e) {
- switch(e.type) {
- case ETYPE_VALUE:
- break;
- case ETYPE_CIRCLE:
- plot_circle(e.circle);
- break;
- case ETYPE_POINT:
- plot_point(e.point);
- break;
- case ETYPE_LINE:
- plot_line(e.line);
- break;
- }
-}
-
struct smooth_line {
struct component l1;
struct component l2;
@@ -80,7 +26,7 @@ struct smooth_line {
struct component corner_end;
};
-struct smooth_line init_smooth_line() {
+struct smooth_line a_smooth_line() {
return (struct smooth_line){
.l1 = {.type = COM_LINE},
.l2 = {.type = COM_LINE},
@@ -102,7 +48,7 @@ struct box {
struct component side[4];
};
-struct box init_box() {
+struct box a_box() {
return (struct box){
.corner = {
{.type = COM_POINT},
@@ -130,7 +76,7 @@ struct mid {
struct component p;
};
-struct mid init_mid() {
+struct mid a_midpoint() {
return (struct mid) {
.l1 = {.type = COM_LINE},
.l2 = {.type = COM_LINE},
@@ -143,6 +89,36 @@ struct mid init_mid() {
};
}
+void draw_from_constraints(struct constraints *c, struct topology *t, struct canvas *cv) {
+ struct drawing drawing = {};
+ solve_constraints(c, &drawing);
+
+ // Copy over all the parameter values to a new array
+ // @PERF: Maybe we should just store them in a separate array to start with
+ double *params = malloc(sizeof(double) * (c->length));
+ for(size_t i = 0; i < c->length; i++) {
+ params[i] = c->elements[i].v;
+ }
+
+ place_points(&drawing, params);
+
+ begin_drawing(cv);
+ // for(struct command *current = drawing.root; current != NULL && current != drawing.error; current = current->next) {
+ // if(current->hidden) continue;
+ // plot_generic(current->result);
+ // }
+
+ // if(drawing.error != NULL) {
+ // plot_generic(*drawing.error->arg1);
+ // plot_generic(*drawing.error->arg2);
+ // fprintf(stderr, "Solver error detected. Drawing will be incomplete\n");
+ // }
+
+ draw_topology(cv, t);
+ draw_constraints(cv, c);
+ end_drawing(cv);
+}
+
int main(int argc, char *argv[]) {
struct constraints constraints = {};
struct topology topo = {};
@@ -183,7 +159,7 @@ int main(int argc, char *argv[]) {
CEND(),
});
- struct smooth_line line = init_smooth_line();
+ struct smooth_line line = a_smooth_line();
add_fragment(&topo, (struct topology_elem[]){
TOPO_MOVETO(&line.start),
@@ -225,7 +201,7 @@ int main(int argc, char *argv[]) {
CEND(),
});
- struct box box = init_box();
+ struct box box = a_box();
add_fragment(&topo, (struct topology_elem[]){
TOPO_MOVETO(&box.corner[0]),
TOPO_LINETO(&box.corner[1]),
@@ -249,19 +225,23 @@ int main(int argc, char *argv[]) {
POINT_ON_LINE(&box.corner[0], &box.side[3]),
POINT_ON_LINE(&box.corner[3], &box.side[3]),
- LL_ANGLE(&box.side[3], &box.side[0], DEG(80)),
- LL_ANGLE(&box.side[1], &box.side[2], DEG(100)),
- LL_ANGLE(&box.side[1], &box.side[3], DEG(180)),
- LL_ANGLE(&components[3], &box.side[1], DEG(90)),
+ LL_ANGLE(&box.side[3], &box.side[0], DEG(90)),
+ LL_ANGLE(&box.side[1], &box.side[2], DEG(90)),
+ LL_ANGLE(&box.side[2], &box.side[3], DEG(90)),
PL_DISTANCE(&box.side[1], &box.corner[0], 20),
PP_DISTANCE(&line.corner_end, &box.corner[0], 9.5),
- PP_DISTANCE(&line.corner_start, &box.corner[0], 10),
+ PL_DISTANCE(&box.corner[0], &components[3], 20),
CEND(),
});
- struct mid box_enter = init_mid();
+ add_constraint(&constraints, (struct constraint[]){
+ LL_ANGLE(&components[3], &box.side[1], DEG(90)),
+ CEND(),
+ });
+
+ struct mid box_enter = a_midpoint();
add_constraint(&constraints, (struct constraint[]){
LL_ANGLE(&box.side[3], &box_enter.l1, DEG(-30)),
@@ -282,31 +262,10 @@ int main(int argc, char *argv[]) {
CEND(),
});
- struct drawing drawing = {};
- solve_constraints(&constraints, &drawing);
-
- // Copy over all the parameter values to a new array
- // @PERF: Maybe we should just store them in a separate array to start with
- double *params = malloc(sizeof(double) * (constraints.length));
- for(size_t i = 0; i < constraints.length; i++) {
- params[i] = constraints.elements[i].v;
- }
-
- execute_drawing(&drawing, params);
-
- begin_drawing();
- // for(struct command *current = drawing.root; current != NULL && current != drawing.error; current = current->next) {
- // if(current->hidden) continue;
- // plot_generic(current->result);
- // }
-
- // if(drawing.error != NULL) {
- // plot_generic(*drawing.error->arg1);
- // plot_generic(*drawing.error->arg2);
- // fprintf(stderr, "Solver error detected. Drawing will be incomplete\n");
- // }
-
- draw_topology(&topo);
- draw_constraints(&constraints);
- end_drawing();
+ struct canvas canvas = {
+ .state = CANVAS_INIT,
+ .f = stdout,
+ };
+
+ draw_from_constraints(&constraints, &topo, &canvas);
}
diff --git a/src/solve.c b/src/solve.c
index b82d8e8..31c7947 100644
--- a/src/solve.c
+++ b/src/solve.c
@@ -1,5 +1,6 @@
#include "cad/solve.h"
+#include "cad/log.h"
#include "cad/util.h"
#include <string.h>
@@ -595,13 +596,55 @@ static void draw_solution(struct constraint *constraints, size_t fix, struct sol
.arg1 = c,
.arg2 = l,
});
+ } else if(constraints[step->i].type == CT_POINT_POINT_DISTANCE
+ && local_i->type == COM_POINT
+ && constraints[step->j].type == CT_POINT_LINE_DISTANCE
+ && local_j->type == COM_LINE) {
+ // @COPYPASTA: Taken from rigth above but swapped
+ assert(oppo_i->type == COM_POINT);
+
+ struct element *d1 = insert_cmd(drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .index = step->i,
+ .dir = constraints[step->i].forward,
+ .result.type = ETYPE_VALUE,
+ });
+ struct element *d2 = insert_cmd(drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .index = step->j,
+ .dir = constraints[step->j].forward,
+ .result.type = ETYPE_VALUE,
+ });
+
+ struct element *l = insert_cmd(drawing, (struct command){
+ .op = CMD_LINE_LINE_DISTANCE_PARALLEL,
+ .hidden = !shown,
+ .result.type = ETYPE_LINE,
+ .arg1 = local_j->e,
+ .arg2 = d2,
+ });
+
+ struct element *c = insert_cmd(drawing, (struct command){
+ .op = CMD_CIRCLE_CENTER_RADIUS,
+ .hidden = !shown,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = local_i->e,
+ .arg2 = d1,
+ });
+
+ oppo_i->e = insert_cmd(drawing, (struct command){
+ .op = CMD_POINT_CIRCLE_LINE,
+ .hidden = !shown,
+ .root = constraints[step->j].c2 == local_i,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = l,
+ });
} else {
- printf("Unknown constraint combination %s and %s\n", constraint_type_name[constraints[step->i].type], constraint_type_name[constraints[step->j].type]);
- abort();
+ CRASH("Unknown constraint combination %s and %s\n", constraint_type_name[constraints[step->i].type], constraint_type_name[constraints[step->j].type]);
}
}
-
}
bool solve_constraints(struct constraints *constraints, struct drawing *drawing) {
diff --git a/src/svg.c b/src/svg.c
index 20a8262..7480e4f 100644
--- a/src/svg.c
+++ b/src/svg.c
@@ -2,7 +2,9 @@
#define SIGNOF(x) ((typeof(x))((x)>0) - ((x)<0))
-void plot_line_between_style(struct point p1, struct point p2, enum LineStyle style) {
+void plot_line_between_style(struct canvas *canvas, struct point p1, struct point p2, enum LineStyle style) {
+ assert(canvas->state == CANVAS_DRAWING);
+
char *style_str;
switch(style) {
case LSTYLE_NORMAL:
@@ -19,14 +21,16 @@ void plot_line_between_style(struct point p1, struct point p2, enum LineStyle st
break;
}
- printf("<line %s x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n", style_str, p1.pos[0], -p1.pos[1], p2.pos[0], -p2.pos[1]);
+ fprintf(canvas->f, "<line %s x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n", style_str, p1.pos[0], -p1.pos[1], p2.pos[0], -p2.pos[1]);
}
-void plot_line_between(struct point p1, struct point p2) {
- plot_line_between_style(p1, p2, LSTYLE_NORMAL);
+void plot_line_between(struct canvas *canvas, struct point p1, struct point p2) {
+ plot_line_between_style(canvas, p1, p2, LSTYLE_NORMAL);
}
-void plot_arc_between_style(struct point c, struct point p1, struct point p2, enum LineStyle style) {
+void plot_arc_between_style(struct canvas *canvas, struct point c, struct point p1, struct point p2, enum LineStyle style) {
+ assert(canvas->state == CANVAS_DRAWING);
+
char *style_str;
switch(style) {
case LSTYLE_NORMAL:
@@ -61,18 +65,22 @@ void plot_arc_between_style(struct point c, struct point p1, struct point p2, en
vec2 t;
glm_vec2_sub(c.pos, p1.pos, t);
double r = glm_vec2_norm(t);
- printf("<path %s d=\"M %f %f A %f %f 0 %d 0 %f %f\" fill=\"none\" />\n", style_str, p2.pos[0], -p2.pos[1], r, r, above_pi, p1.pos[0], -p1.pos[1]);
+ fprintf(canvas->f, "<path %s d=\"M %f %f A %f %f 0 %d 0 %f %f\" fill=\"none\" />\n", style_str, p2.pos[0], -p2.pos[1], r, r, above_pi, p1.pos[0], -p1.pos[1]);
}
-void plot_arc_between(struct point c, struct point p1, struct point p2) {
- plot_arc_between_style(c, p1, p2, LSTYLE_NORMAL);
+void plot_arc_between(struct canvas *canvas, struct point c, struct point p1, struct point p2) {
+ plot_arc_between_style(canvas, c, p1, p2, LSTYLE_NORMAL);
}
-void plot_text(struct point p, double angle, char* str) {
- printf("<text text-anchor=\"middle\" dominant-baseline=\"central\" transform=\"translate(%f, %f) scale(1, -1) rotate(%f) scale(1, -1)\" font-size=\"0.75\">%s</text>\n", p.pos[0], -p.pos[1], angle * (180.0/M_PI), str);
+void plot_text(struct canvas *canvas, struct point p, double angle, char* str) {
+ assert(canvas->state == CANVAS_DRAWING);
+
+ fprintf(canvas->f, "<text text-anchor=\"middle\" dominant-baseline=\"central\" transform=\"translate(%f, %f) scale(1, -1) rotate(%f) scale(1, -1)\" font-size=\"0.75\">%s</text>\n", p.pos[0], -p.pos[1], angle * (180.0/M_PI), str);
}
-void plot_angle(struct line l1, struct line l2, double theta, struct point *intersect, struct point *p1, struct point *p2) {
+void plot_angle(struct canvas *canvas, struct line l1, struct line l2, double theta, struct point *intersect, struct point *p1, struct point *p2) {
+ assert(canvas->state == CANVAS_DRAWING);
+
line_line_intersect(l1, l2, intersect);
struct circle c = { .radius = 1.3 };
@@ -81,7 +89,7 @@ void plot_angle(struct line l1, struct line l2, double theta, struct point *inte
circle_line_intersect(c, l1, 0, p1);
circle_line_intersect(c, l2, 0, p2);
- plot_arc_between_style(*intersect, *p2, *p1, LSTYLE_INDICATOR);
+ plot_arc_between_style(canvas, *intersect, *p2, *p1, LSTYLE_INDICATOR);
vec2 l1v;
vec2 l2v;
@@ -106,7 +114,7 @@ void plot_angle(struct line l1, struct line l2, double theta, struct point *inte
char buf[512];
snprintf(buf, sizeof(buf), "%.1f°", theta);
- plot_text(label_point, angle - M_PI/2, buf);
+ plot_text(canvas, label_point, angle - M_PI/2, buf);
}
double project_point_to_line_distance(struct point p, struct line l) {
@@ -139,7 +147,9 @@ void extend_line_to(struct component* c, struct point *p) {
}
}
-static void plot_distance_indicator(struct point p1, struct point p2, double distance, bool offset) {
+static void plot_distance_indicator(struct canvas *canvas, struct point p1, struct point p2, double distance, bool offset) {
+ assert(canvas->state == CANVAS_DRAWING);
+
vec2 dir;
glm_vec2_sub(p2.pos, p1.pos, dir);
glm_vec2_normalize(dir);
@@ -155,7 +165,7 @@ static void plot_distance_indicator(struct point p1, struct point p2, double dis
glm_vec2_copy(p1.pos, start.pos);
glm_vec2_copy(p2.pos, end.pos);
}
- plot_line_between_style(start, end, offset ? LSTYLE_INDICATOR : LSTYLE_INDICATOR_INLINE);
+ plot_line_between_style(canvas, start, end, offset ? LSTYLE_INDICATOR : LSTYLE_INDICATOR_INLINE);
}
if(offset) {
@@ -167,14 +177,14 @@ static void plot_distance_indicator(struct point p1, struct point p2, double dis
struct point p2;
glm_vec2_add(start.pos, tip, p1.pos);
glm_vec2_sub(start.pos, tip, p2.pos);
- plot_line_between_style(p1, p2, LSTYLE_INDICATOR);
+ plot_line_between_style(canvas, p1, p2, LSTYLE_INDICATOR);
}
{
struct point p1;
struct point p2;
glm_vec2_add(end.pos, tip, p1.pos);
glm_vec2_sub(end.pos, tip, p2.pos);
- plot_line_between_style(p1, p2, LSTYLE_INDICATOR);
+ plot_line_between_style(canvas, p1, p2, LSTYLE_INDICATOR);
}
}
@@ -202,7 +212,7 @@ static void plot_distance_indicator(struct point p1, struct point p2, double dis
char buf[512];
snprintf(buf, sizeof(buf), "%.1f u", distance);
- plot_text(p, angle, buf);
+ plot_text(canvas, p, angle, buf);
}
}
@@ -216,7 +226,9 @@ void line_distance_to_point(struct line l, double d, struct point *p) {
glm_vec2_muladds(perp, d, p->pos);
}
-void draw_constraints(struct constraints *constraints) {
+void draw_constraints(struct canvas *canvas, struct constraints *constraints) {
+ assert(canvas->state == CANVAS_DRAWING);
+
for(size_t i = 0; i < constraints->length; i++) {
struct constraint *constraint = &constraints->elements[i];
if(!constraint->used) continue;
@@ -229,8 +241,8 @@ void draw_constraints(struct constraints *constraints) {
// @COMPL: It would be nice to combine the indicator and
// construction line if there's no topology line there
- plot_line_between_style(constraint->c1->e->point, constraint->c2->e->point, LSTYLE_CONSTRUCTION);
- plot_distance_indicator(constraint->c1->e->point, constraint->c2->e->point, constraint->v, true);
+ plot_line_between_style(canvas, constraint->c1->e->point, constraint->c2->e->point, LSTYLE_CONSTRUCTION);
+ plot_distance_indicator(canvas, constraint->c1->e->point, constraint->c2->e->point, constraint->v, true);
} break;
case CT_LINE_LINE_ANGLE: {
assert(constraint->c1->type == COM_LINE);
@@ -251,7 +263,7 @@ void draw_constraints(struct constraints *constraints) {
struct point p1;
struct point p2;
struct point intersect;
- plot_angle(l1->e->line, l2->e->line, constraint->v, &intersect, &p1, &p2);
+ plot_angle(canvas, l1->e->line, l2->e->line, constraint->v, &intersect, &p1, &p2);
extend_line_to(constraint->c1, &intersect);
extend_line_to(constraint->c2, &intersect);
@@ -279,7 +291,7 @@ void draw_constraints(struct constraints *constraints) {
// @COMPL: It would be nice to combine the indicator and
// construction line if there's no topology line there
// plot_line_between_style(closest, point->e->point, LSTYLE_CONSTRUCTION);
- plot_distance_indicator(point->e->point, closest, constraint->v, false);
+ plot_distance_indicator(canvas, point->e->point, closest, constraint->v, false);
}
extend_line_to(line, &point->e->point);
@@ -304,14 +316,14 @@ void draw_constraints(struct constraints *constraints) {
if(!constraint->c1->drawn) {
line_distance_to_point(constraint->c1->e->line, constraint->c1->min, &p1);
line_distance_to_point(constraint->c1->e->line, constraint->c1->max, &p2);
- plot_line_between_style(p1, p2, LSTYLE_CONSTRUCTION);
+ plot_line_between_style(canvas, p1, p2, LSTYLE_CONSTRUCTION);
constraint->c1->drawn = true;
}
if(!constraint->c2->drawn) {
line_distance_to_point(constraint->c2->e->line, constraint->c2->min, &p1);
line_distance_to_point(constraint->c2->e->line, constraint->c2->max, &p2);
- plot_line_between_style(p1, p2, LSTYLE_CONSTRUCTION);
+ plot_line_between_style(canvas, p1, p2, LSTYLE_CONSTRUCTION);
constraint->c2->drawn = true;
}
} break;
@@ -322,7 +334,9 @@ void draw_constraints(struct constraints *constraints) {
}
}
-void draw_topology(struct topology *topo) {
+void draw_topology(struct canvas *canvas, struct topology *topo) {
+ assert(canvas->state == CANVAS_DRAWING);
+
struct component *head = NULL;
for(size_t i = 0; i < topo->length; i++) {
struct topology_elem *cur = &topo->elements[i];
@@ -334,14 +348,14 @@ void draw_topology(struct topology *topo) {
case TOPO_LINETO:
cur++;
if(cur->arg.c->e != NULL) {
- plot_line_between(head->e->point, cur->arg.c->e->point);
+ plot_line_between(canvas, head->e->point, cur->arg.c->e->point);
head = cur->arg.c;
}
break;
case TOPO_ARCTO:
cur++;
if(cur->arg.c->e != NULL && (cur+1)->arg.c->e != NULL) {
- plot_arc_between(cur->arg.c->e->point, (cur+1)->arg.c->e->point, head->e->point);
+ plot_arc_between(canvas, cur->arg.c->e->point, (cur+1)->arg.c->e->point, head->e->point);
head = (cur+1)->arg.c;
}
break;
@@ -351,19 +365,26 @@ void draw_topology(struct topology *topo) {
}
}
-void begin_drawing() {
- printf("<svg version=\"1.1\" viewBox=\"-50 -50 100 100\" width=\"1200\" height=\"1200\" xmlns=\"http://www.w3.org/2000/svg\">\n");
- printf("<defs>\n");
- printf("\t<marker id=\"triangle\" viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" markerUnits=\"strokeWidth\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">\n");
- printf("\t\t<path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"blue\" opacity=\"0.3\" />\n");
- printf("\t</marker>\n");
- printf("</defs>\n");
+void begin_drawing(struct canvas *canvas) {
+ assert(canvas->f != NULL);
+ assert(canvas->state == CANVAS_INIT);
+
+ fprintf(canvas->f, "<svg version=\"1.1\" viewBox=\"-50 -50 100 100\" width=\"1200\" height=\"1200\" xmlns=\"http://www.w3.org/2000/svg\">\n");
+ fprintf(canvas->f, "<defs>\n");
+ fprintf(canvas->f, "\t<marker id=\"triangle\" viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" markerUnits=\"strokeWidth\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">\n");
+ fprintf(canvas->f, "\t\t<path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"blue\" opacity=\"0.3\" />\n");
+ fprintf(canvas->f, "\t</marker>\n");
+ fprintf(canvas->f, "</defs>\n");
// Axis lines
- printf("<line x1=\"-1000\" y1=\"0\" x2=\"1000\" y2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
- printf("<line y1=\"-1000\" x1=\"0\" y2=\"1000\" x2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
+ fprintf(canvas->f, "<line x1=\"-1000\" y1=\"0\" x2=\"1000\" y2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
+ fprintf(canvas->f, "<line y1=\"-1000\" x1=\"0\" y2=\"1000\" x2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
+ canvas->state = CANVAS_DRAWING;
}
-void end_drawing() {
- printf("</svg>\n");
+void end_drawing(struct canvas *canvas) {
+ assert(canvas->state == CANVAS_DRAWING);
+
+ fprintf(canvas->f, "</svg>\n");
+ canvas->state = CANVAS_INIT;
}
diff --git a/src/topology.c b/src/topology.c
index 10fc53f..e12057d 100644
--- a/src/topology.c
+++ b/src/topology.c
@@ -1,4 +1,5 @@
#include "cad/topology.h"
+#include "cad/log.h"
#include "cad/util.h"
#include <string.h>
@@ -21,7 +22,7 @@ size_t frag_len(struct topology_elem *elems) {
cur += 3;
break;
case TOPO_END:
- abort();
+ CRASH("We should never get to here");
}
}