diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2025-12-07 23:11:22 +0100 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2025-12-07 23:11:22 +0100 |
| commit | 7a5e295029e8a2c176e4b75f06f52a43bca7ccbd (patch) | |
| tree | 8f7c812175acdcae0ea6a6e3b72c2d5b64ad388e /src | |
| parent | e22588e908a9a2b172a8965cfd8767305dcb3459 (diff) | |
A little bit of cleanup and renaming
Diffstat (limited to 'src')
| -rw-r--r-- | src/construction.c | 2 | ||||
| -rw-r--r-- | src/main.c | 143 | ||||
| -rw-r--r-- | src/solve.c | 49 | ||||
| -rw-r--r-- | src/svg.c | 99 | ||||
| -rw-r--r-- | src/topology.c | 3 |
5 files changed, 160 insertions, 136 deletions
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: { @@ -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) { @@ -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"); } } |
