diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2025-11-23 12:28:02 +0100 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2025-11-23 12:28:02 +0100 |
| commit | e63c2a09a54c28dbcaaee48de2008fd5c3a7bf81 (patch) | |
| tree | fdfb26e79756e68676017f238adadce7f214c5dd /src | |
| parent | acfa01613f6e7fbeace88a15df61252156d39cf1 (diff) | |
Do some inline distance indicators
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.c | 100 | ||||
| -rw-r--r-- | src/svg.c | 109 |
2 files changed, 106 insertions, 103 deletions
@@ -50,19 +50,8 @@ 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_style(struct line l, enum LineStyle style) { - char *style_str; - switch(style) { - case LSTYLE_NORMAL: - style_str = "stroke=\"black\" stroke-width=\"0.2\""; - break; - case LSTYLE_CONSTRUCTION: - style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-dasharray=\"0.7,0.2\" stroke-opacity=\"0.3\""; - break; - case LSTYLE_INDICATOR: - abort(); - break; - } +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; @@ -79,23 +68,16 @@ void plot_line_style(struct line l, enum LineStyle style) { printf("<line %s x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n", style_str, minx, -miny, maxx, -maxy); } - if(style == LSTYLE_NORMAL) { - double d0 = glm_vec2_norm2(l.norm); + 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 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("%f %f\n", l.norm[0], l.norm[1]); + 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_line(struct line l) { - plot_line_style(l, LSTYLE_NORMAL); + 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) { @@ -198,10 +180,9 @@ struct mid init_mid() { } int main(int argc, char *argv[]) { - struct constraints constraints = {0}; - struct topology topo = {0}; + struct constraints constraints = {}; + struct topology topo = {}; - // Figure 4 struct component components[] = { {.type = COM_POINT}, {.type = COM_POINT}, @@ -339,7 +320,6 @@ int main(int argc, char *argv[]) { struct drawing drawing = {}; solve_constraints(&constraints, &drawing); - // line.start.e = components[5].e; double *params = malloc(sizeof(double) * (constraints.length)); for(size_t i = 0; i < constraints.length; i++) { @@ -365,53 +345,19 @@ int main(int argc, char *argv[]) { execute_drawing(&drawing, params); - printf("<svg version=\"1.1\" viewBox=\"-50 -50 100 100\" width=\"1200\" height=\"1200\" xmlns=\"http://www.w3.org/2000/svg\">\n"); + begin_drawing(); + // for(struct command *current = drawing.root; current != NULL && current != drawing.error; current = current->next) { + // if(current->hidden) continue; + // plot_generic(current->result); + // } - // 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"); + // if(drawing.error != NULL) { + // plot_generic(*drawing.error->arg1); + // plot_generic(*drawing.error->arg2); + // fprintf(stderr, "Solver error detected. Drawing will be incomplete\n"); + // } - 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"); - } - - struct component *head = NULL; - for(size_t i = 0; i < topo.length; i++) { - struct topology_elem *cur = &topo.elements[i]; - switch(cur->cmd.op) { - case TOPO_MOVETO: - cur++; - if(cur->arg.c->e != NULL) head = cur->arg.c; - break; - case TOPO_LINETO: - cur++; - if(cur->arg.c->e != NULL) { - plot_line_between(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); - head = (cur+1)->arg.c; - } - break; - case TOPO_END: - abort(); - } - } - - // printf("%f %f %f\n", components[3].e->line.norm[0], components[3].e->line.norm[1], components[3].e->line.C); - + draw_topology(&topo); draw_constraints(&constraints); - - printf("</svg>\n"); + end_drawing(); } @@ -14,9 +14,12 @@ void plot_line_between_style(struct point p1, struct point p2, enum LineStyle st case LSTYLE_INDICATOR: style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-opacity=\"0.3\""; break; + case LSTYLE_INDICATOR_INLINE: + style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-opacity=\"0.3\" marker-start=\"url(#triangle)\" marker-end=\"url(#triangle)\""; + 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]); + 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]); } void plot_line_between(struct point p1, struct point p2) { @@ -32,6 +35,7 @@ void plot_arc_between_style(struct point c, struct point p1, struct point p2, en case LSTYLE_CONSTRUCTION: abort(); break; + case LSTYLE_INDICATOR_INLINE: case LSTYLE_INDICATOR: style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-opacity=\"0.3\""; break; @@ -103,9 +107,6 @@ 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_line_style(l1, LSTYLE_CONSTRUCTION); - // plot_line_style(l2, LSTYLE_CONSTRUCTION); } double project_point_to_line_distance(struct point p, struct line l) { @@ -138,7 +139,7 @@ void extend_line_to(struct component* c, struct point *p) { } } -static void plot_distance_indicator(struct point p1, struct point p2, double distance) { +static void plot_distance_indicator(struct point p1, struct point p2, double distance, bool offset) { vec2 dir; glm_vec2_sub(p2.pos, p1.pos, dir); glm_vec2_normalize(dir); @@ -147,27 +148,34 @@ static void plot_distance_indicator(struct point p1, struct point p2, double dis struct point start; struct point end; { - glm_vec2_add(p1.pos, norm, start.pos); - glm_vec2_add(p2.pos, norm, end.pos); - plot_line_between_style(start, end, LSTYLE_INDICATOR); + if(offset) { + glm_vec2_add(p1.pos, norm, start.pos); + glm_vec2_add(p2.pos, norm, end.pos); + } else { + 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); } - // The little wings to highlight the ends - vec2 tip = {.3, .3}; - glm_vec2_mul(norm, tip, tip); - { - struct point p1; - 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); - } - { - 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); + if(offset) { + // The little wings to highlight the ends + vec2 tip = {.3, .3}; + glm_vec2_mul(norm, tip, tip); + { + struct point p1; + 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); + } + { + 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); + } } // The text @@ -219,7 +227,10 @@ void draw_constraints(struct constraints *constraints) { assert(constraint->c2->type == COM_POINT); if(constraint->v == 0.0) continue; - plot_distance_indicator(constraint->c1->e->point, constraint->c2->e->point, constraint->v); + // @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); } break; case CT_LINE_LINE_ANGLE: { assert(constraint->c1->type == COM_LINE); @@ -265,7 +276,10 @@ void draw_constraints(struct constraints *constraints) { struct point closest; line_distance_to_point(line->e->line, dist, &closest); - plot_distance_indicator(point->e->point, closest, constraint->v); + // @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); } extend_line_to(line, &point->e->point); @@ -309,4 +323,47 @@ void draw_constraints(struct constraints *constraints) { } void draw_topology(struct topology *topo) { + struct component *head = NULL; + for(size_t i = 0; i < topo->length; i++) { + struct topology_elem *cur = &topo->elements[i]; + switch(cur->cmd.op) { + case TOPO_MOVETO: + cur++; + if(cur->arg.c->e != NULL) head = cur->arg.c; + break; + case TOPO_LINETO: + cur++; + if(cur->arg.c->e != NULL) { + plot_line_between(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); + head = (cur+1)->arg.c; + } + break; + case TOPO_END: + abort(); + } + } +} + +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"); + + // 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"); +} + +void end_drawing() { + printf("</svg>\n"); } |
