diff options
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 810 |
1 files changed, 31 insertions, 779 deletions
@@ -8,105 +8,12 @@ #include "cad/construction.h" #include "cad/solve.h" - -#define TEXT_OFFSET 0.4 +#include "cad/svg.h" #define SETSIGN(b, v) ((v) * ((2 * (b)) - 1)) -#define SIGNOF(x) ((typeof(x))((x)>0) - ((x)<0)) #define DEG(x) ((x) * M_PI / 180.0) -enum topology_op { - TOPO_MOVETO, - TOPO_LINETO, - TOPO_ARCTO, - - TOPO_END, -}; - -struct topology_cmd { - enum topology_op op; -}; - -struct topology_arg { - struct component *c; -}; - -struct topology_elem { - union { - struct topology_cmd cmd; - struct topology_arg arg; - }; -}; - -#define MOVETO(c) \ - { .cmd = {TOPO_MOVETO} }, \ - { .arg = {c} } \ - -#define LINETO(c) \ - { .cmd = {TOPO_LINETO} }, \ - { .arg = {c} } \ - -#define ARCTO(center, end) \ - { .cmd = {TOPO_ARCTO} }, \ - { .arg = {center} }, \ - { .arg = {end} } \ - -#define END() \ - { .cmd = {TOPO_END} } \ - -struct topology { - struct topology_elem *elements; - size_t length; - size_t capacity; -}; - -static void resize_buffer(void **buffer, size_t *capacity, size_t elems, size_t elemSize) { - assert(elems > 0); - uint64_t newpower = (sizeof(elems) * CHAR_BIT) - __builtin_clzl(elems-1); - elems = 1 << newpower; - - if(elems != *capacity) { - *capacity = elems; - *buffer = realloc(*buffer, *capacity * elemSize); - } -} - -static void topo_resize(struct topology *topo, uint64_t newcapacity) { - resize_buffer((void**)&topo->elements, &topo->capacity, newcapacity, sizeof(struct topology_elem)); -} - -size_t frag_len(struct topology_elem *elems) { - struct topology_elem *cur = elems; - while(cur->cmd.op != TOPO_END) { - switch(cur->cmd.op) { - case TOPO_MOVETO: - cur += 2; - break; - case TOPO_LINETO: - cur += 2; - break; - case TOPO_ARCTO: - cur += 3; - break; - case TOPO_END: - abort(); - } - } - - return cur - elems; -} - -void add_topo_fragment(struct topology *topo, struct topology_elem *new) { - size_t new_num = frag_len(new); - if(new_num + topo->length > topo->capacity) { - topo_resize(topo, new_num + topo->length); - } - - memcpy(topo->elements + topo->length, new, new_num * sizeof(struct topology_elem)); - topo->length += new_num; -} - #define PP_DISTANCE(C1, C2, D) \ { \ .type = CT_POINT_POINT_DISTANCE, \ @@ -139,86 +46,10 @@ void add_topo_fragment(struct topology *topo, struct topology_elem *new) { .type = CT_END, \ } -struct constraints { - struct constraint *elements; - size_t length; - size_t capacity; -}; - -void add_constraint(struct constraints *c, struct constraint *new) { - struct constraint *end = new; - while(end->type != CT_END) end++; - size_t new_num = end - new; - - if(c->length + new_num > c->capacity) { - resize_buffer((void**)&c->elements, &c->capacity, c->length + new_num, sizeof(struct constraint)); - } - - memcpy(c->elements + c->length, new, new_num * sizeof(struct constraint)); - c->length += new_num; -} - -double project_point_to_line_distance(struct point p, struct line l) { - vec2 offset = {-p.pos[0], -p.pos[1]}; - double c = glm_vec2_dot(l.norm, offset); - - double det = (l.norm[0] * p.pos[1]) - (l.norm[1] * p.pos[0]); - det = -det; - - // @HACK There's a rounding error here that can cause d1 to end up - // negative. Just take the abolute value of it to get around that. - double d1 = fabs(glm_vec2_norm2(p.pos) - pow(c, 2)/glm_vec2_norm2(l.norm)); - assert(d1 >= 0.0); - double m1 = sqrt(d1 / glm_vec2_norm2(l.norm)); - - return SIGNOF(det) * m1; -} - -void line_distance_to_point(struct line l, double d, struct point *p) { - glm_vec2_zero(p->pos); - glm_vec2_muladds(l.norm, l.C, p->pos); - glm_vec2_divs(p->pos, glm_vec2_norm2(l.norm), p->pos); - glm_vec2_negate(p->pos); - - vec2 perp = {l.norm[1], -l.norm[0]}; - glm_vec2_muladds(perp, d, p->pos); -} - void plot_point(struct point p) { printf("<circle cx=\"%f\" cy=\"%f\" r=\".4\" fill=\"black\" />\n", p.pos[0], -p.pos[1]); } -enum LineStyle { - LSTYLE_NORMAL, - LSTYLE_CONSTRUCTION, - LSTYLE_INDICATOR, -}; - -void plot_line_between_style(struct point p1, struct point p2, 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: - style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-opacity=\"0.3\""; - 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]); -} - -void plot_line_between(struct point p1, struct point p2) { - plot_line_between_style(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_line_style(struct line l, enum LineStyle style) { char *style_str; switch(style) { @@ -267,47 +98,6 @@ void plot_line(struct line l) { plot_line_style(l, LSTYLE_NORMAL); } -void plot_arc_between_style(struct point c, struct point p1, struct point p2, enum LineStyle style) { - char *style_str; - switch(style) { - case LSTYLE_NORMAL: - style_str = "stroke=\"black\" stroke-width=\"0.2\""; - break; - case LSTYLE_CONSTRUCTION: - abort(); - break; - case LSTYLE_INDICATOR: - style_str = "stroke=\"blue\" stroke-width=\"0.1\" stroke-opacity=\"0.3\""; - break; - } - - bool above_pi; - { - vec2 p1l; - glm_vec2_sub(p1.pos, c.pos, p1l); - glm_vec2_normalize(p1l); - vec2 p2l; - glm_vec2_sub(p2.pos, c.pos, p2l); - glm_vec2_normalize(p2l); - - glm_vec2_copy((vec2){-p2l[1], p2l[0]}, p2l); - - above_pi = glm_vec2_dot(p1l, p2l) < 0; - } - - // @COML: There's something missing here about which side of the arc we - // want. I think we can figure that out from the relation of the center and - // the points - 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]); -} - -void plot_arc_between(struct point c, struct point p1, struct point p2) { - plot_arc_between_style(c, p1, p2, LSTYLE_NORMAL); -} - 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); } @@ -328,415 +118,6 @@ void plot_generic(struct element e) { } } -void plot_distance_indicator(struct point p1, struct point p2, double distance) { - vec2 dir; - glm_vec2_sub(p2.pos, p1.pos, dir); - glm_vec2_normalize(dir); - vec2 norm = {-dir[1], dir[0]}; - - 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); - } - - // 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 - { - struct point p; - glm_vec2_lerp(start.pos, end.pos, 0.5, p.pos); - - glm_vec2_muladds(norm, TEXT_OFFSET, p.pos); - - double angle = atan2(dir[1], dir[0]); - - // Flip upside down labels - if(angle > M_PI/2) { - glm_vec2_muladds(norm, 0.1, p.pos); - angle -= M_PI; - } - if(angle < -M_PI/2) { - glm_vec2_muladds(norm, 0.1, p.pos); - angle += M_PI; - } - - assert(angle >= -M_PI); - assert(angle <= M_PI); - - char buf[512]; - snprintf(buf, sizeof(buf), "%.1f u", distance); - plot_text(p, angle, buf); - } -} - -void plot_angle(struct line l1, struct line l2, double theta, struct point *intersect, struct point *p1, struct point *p2) { - line_line_intersect(l1, l2, intersect); - - struct circle c = { .radius = 1.3 }; - glm_vec2_copy(intersect->pos, c.center); - - circle_line_intersect(c, l1, 0, p1); - circle_line_intersect(c, l2, 0, p2); - - plot_arc_between_style(*intersect, *p2, *p1, LSTYLE_INDICATOR); - - vec2 l1v; - vec2 l2v; - glm_vec2_normalize_to(l1.norm, l1v); - glm_vec2_normalize_to(l2.norm, l2v); - - // Label - glm_vec2_negate(l2v); - - vec2 x; - glm_vec2_add(l1v, l2v, x); - glm_vec2_normalize(x); - - struct point label_point; - glm_vec2_copy(intersect->pos, label_point.pos); - glm_vec2_muladds(x, c.radius + TEXT_OFFSET, label_point.pos); - - double dot = x[0]; - double det = x[1]; - - double angle = atan2(det, dot); - - 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); -} - -struct element *create_perp(struct drawing *cmds, struct element *l, struct element *p, bool hide) { - static struct element radius = { - .type = ETYPE_VALUE, - .value = 5, // Just an arbitrary number - }; - - struct element *c1 = insert_cmd(cmds, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .result.type = ETYPE_CIRCLE, - .hidden = true, - .arg1 = p, - .arg2 = &radius, - }); - struct element *p1 = insert_cmd(cmds, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .result.type = ETYPE_POINT, - .hidden = true, - .root = 0, - .arg1 = c1, - .arg2 = l, - }); - struct element *p2 = insert_cmd(cmds, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .result.type = ETYPE_POINT, - .hidden = true, - .root = 1, - .arg1 = c1, - .arg2 = l, - }); - - struct element *c2 = insert_cmd(cmds, (struct command){ - .op = CMD_CIRCLE_CENTER_POINT, - .result.type = ETYPE_CIRCLE, - .hidden = true, - .arg1 = p2, - .arg2 = p1, - }); - struct element *c3 = insert_cmd(cmds, (struct command){ - .op = CMD_CIRCLE_CENTER_POINT, - .result.type = ETYPE_CIRCLE, - .hidden = true, - .arg1 = p1, - .arg2 = p2, - }); - - struct element *perp1 = insert_cmd(cmds, (struct command){ - .op = CMD_POINT_CIRCLE_CIRCLE, - .result.type = ETYPE_POINT, - .hidden = true, - .arg1 = c2, - .arg2 = c3, - }); - struct element *perp2 = insert_cmd(cmds, (struct command){ - .op = CMD_POINT_CIRCLE_CIRCLE, - .result.type = ETYPE_POINT, - .hidden = true, - .root = 1, - .arg1 = c2, - .arg2 = c3, - }); - - return insert_cmd(cmds, (struct command){ - .op = CMD_LINE_POINT_POINT, - .result.type = ETYPE_LINE, - .hidden = hide, - .arg1 = perp1, - .arg2 = perp2, - }); -} - -void create_rounded_3line(struct drawing *next, struct element *r, struct element *p1, struct element *p2, struct element *p3, struct element **center, struct element **start, struct element **end) { - { - struct element *par1; - struct element *par2; - { - struct element *l = insert_cmd(next, (struct command){ - .op = CMD_LINE_POINT_POINT, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = p1, - .arg2 = p2, - }); - - struct element *perp = create_perp(next, l, p2, true); - - struct element *c = insert_cmd(next, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = p2, - .arg2 = r, - }); - - struct element *p = insert_cmd(next, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = perp, - }); - - par1 = create_perp(next, perp, p, true); - } - - { - struct element *l = insert_cmd(next, (struct command){ - .op = CMD_LINE_POINT_POINT, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = p2, - .arg2 = p3, - }); - - struct element *perp = create_perp(next, l, p2, true); - - struct element *c = insert_cmd(next, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = p2, - .arg2 = r, - }); - - struct element *p = insert_cmd(next, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = perp, - }); - - par2 = create_perp(next, perp, p, true); - } - - struct element *pc = insert_cmd(next, (struct command){ - .op = CMD_POINT_LINE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = par1, - .arg2 = par2, - }); - *center = pc; - - struct element *c = insert_cmd(next, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = pc, - .arg2 = r, - }); - - { - struct element *l = insert_cmd(next, (struct command){ - .op = CMD_LINE_POINT_POINT, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = p1, - .arg2 = p2, - }); - - struct element *p = insert_cmd(next, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = l, - }); - *start = p; - } - - { - struct element *l = insert_cmd(next, (struct command){ - .op = CMD_LINE_POINT_POINT, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = p2, - .arg2 = p3, - }); - - struct element *p = insert_cmd(next, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = l, - }); - *end = p; - } - - } -} - -void create_drawing(struct drawing* drawing, struct element **line_start, struct element **line_bend_start, struct element **line_ctr, struct element **line_bend_end, struct element **line_end) { - *line_start = insert_cmd(drawing, (struct command){ - .op = CMD_ORIGIN, - .hidden = true, - .result.type = ETYPE_POINT, - }); - - struct element *element_spacing = insert_cmd(drawing, (struct command){ - .op = CMD_VALUE_INPUT, - .result.type = ETYPE_VALUE, - }); - - struct element *line_corner; - { - struct element *xaxis = insert_cmd(drawing, (struct command){ - .op = CMD_LINE_X, - .hidden = true, - .result.type = ETYPE_LINE, - }); - - struct element *root_angle = insert_cmd(drawing, (struct command){ - .op = CMD_VALUE_INPUT, - .result.type = ETYPE_VALUE, - }); - - struct element *l = insert_cmd(drawing, (struct command){ - .op = CMD_LINE_POINT_LINE_ANGLE, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = *line_start, - .arg2 = xaxis, - .arg3 = root_angle, - }); - - struct element *c = insert_cmd(drawing, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = *line_start, - .arg2 = element_spacing, - }); - - struct element *p = insert_cmd(drawing, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = l, - }); - line_corner = p; - } - - { - struct element *li = insert_cmd(drawing, (struct command){ - .op = CMD_LINE_POINT_POINT, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = *line_start, - .arg2 = line_corner, - }); - - struct element *bend_angle = insert_cmd(drawing, (struct command){ - .op = CMD_VALUE_INPUT, - .hidden = true, - .result.type = ETYPE_VALUE, - }); - - struct element *l = insert_cmd(drawing, (struct command){ - .op = CMD_LINE_POINT_LINE_ANGLE, - .hidden = true, - .result.type = ETYPE_LINE, - .arg1 = line_corner, - .arg2 = li, - .arg3 = bend_angle, - }); - - struct element *c = insert_cmd(drawing, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = line_corner, - .arg2 = element_spacing, - }); - - struct element *p = insert_cmd(drawing, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = l, - }); - *line_end = p; - } - - - struct element *round_rad = insert_cmd(drawing, (struct command){ - .op = CMD_VALUE_INPUT, - .hidden = true, - .result.type = ETYPE_VALUE, - }); - create_rounded_3line(drawing, round_rad, *line_start, line_corner, *line_end, line_ctr, line_bend_start, line_bend_end); -} - -void extend_line_to(struct component* c, struct point *p) { - assert(c->type == COM_LINE); - - double val = project_point_to_line_distance(*p, c->e->line); - if(!c->min_max_init) { - c->min_max_init = true; - c->min = val; - c->max = val; - } else { - c->min = fmin(c->min, val - 0.1); - c->max = fmax(c->max, val + 0.1); - } -} - struct smooth_line { struct component l1; struct component l2; @@ -817,16 +198,6 @@ struct mid init_mid() { } int main(int argc, char *argv[]) { - // struct element *line_start; - // struct element *line_bend_start; - // struct element *line_ctr; - // struct element *line_bend_end; - // struct element *line_end; - - // struct drawing drawing = {}; - // create_drawing(&drawing, &line_start, &line_bend_start, &line_ctr, &line_bend_end, &line_end); - // execute_drawing(&drawing, (double[]){8, M_PI * 0.5, M_PI * 0.4, .3}); - struct constraints constraints = {0}; struct topology topo = {0}; @@ -840,14 +211,14 @@ int main(int argc, char *argv[]) { {.type = COM_POINT}, }; - add_topo_fragment(&topo, (struct topology_elem[]){ - MOVETO(&components[1]), - LINETO(&components[5]), - LINETO(&components[0]), - LINETO(&components[2]), - LINETO(&components[1]), + add_fragment(&topo, (struct topology_elem[]){ + TOPO_MOVETO(&components[1]), + TOPO_LINETO(&components[5]), + TOPO_LINETO(&components[0]), + TOPO_LINETO(&components[2]), + TOPO_LINETO(&components[1]), - END(), + TOPO_END(), }); add_constraint(&constraints, (struct constraint[]){ @@ -869,18 +240,21 @@ int main(int argc, char *argv[]) { struct smooth_line line = init_smooth_line(); - add_topo_fragment(&topo, (struct topology_elem[]){ - MOVETO(&components[5]), - LINETO(&line.corner_start), - ARCTO(&line.corner_center, &line.corner_end), - LINETO(&line.end), + add_fragment(&topo, (struct topology_elem[]){ + TOPO_MOVETO(&line.start), + TOPO_LINETO(&line.corner_start), + TOPO_ARCTO(&line.corner_center, &line.corner_end), + TOPO_LINETO(&line.end), - END(), + TOPO_END(), }); + alias_point(&constraints, &line.start, &components[5]); + add_constraint(&constraints, (struct constraint[]){ LL_ANGLE(&components[3], &line.l1, DEG(90)), - POINT_ON_LINE(&components[5], &line.l1), + + POINT_ON_LINE(&line.start, &line.l1), LL_ANGLE(&line.l2, &line.l1, DEG(90)), POINT_ON_LINE(&line.corner, &line.l1), @@ -888,7 +262,7 @@ int main(int argc, char *argv[]) { POINT_ON_LINE(&line.end, &line.l2), PL_DISTANCE(&line.end, &line.l1, 10), - PL_DISTANCE(&line.end, &components[3], 12), + PL_DISTANCE(&line.end, &components[4], 5), PL_DISTANCE(&line.corner_center, &line.l1, 2), PL_DISTANCE(&line.corner_center, &line.l2, -2), @@ -907,14 +281,14 @@ int main(int argc, char *argv[]) { }); struct box box = init_box(); - add_topo_fragment(&topo, (struct topology_elem[]){ - MOVETO(&box.corner[0]), - LINETO(&box.corner[1]), - LINETO(&box.corner[2]), - LINETO(&box.corner[3]), - LINETO(&box.corner[0]), - - END(), + add_fragment(&topo, (struct topology_elem[]){ + TOPO_MOVETO(&box.corner[0]), + TOPO_LINETO(&box.corner[1]), + TOPO_LINETO(&box.corner[2]), + TOPO_LINETO(&box.corner[3]), + TOPO_LINETO(&box.corner[0]), + + TOPO_END(), }); add_constraint(&constraints, (struct constraint[]){ @@ -964,11 +338,13 @@ int main(int argc, char *argv[]) { }); struct drawing drawing = {}; - solve_constraints(constraints.elements, constraints.length, &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++) { if(!constraints.elements[i].used) continue; + if(constraints.elements[i].order == 0) continue; params[constraints.elements[i].order-1] = SETSIGN(constraints.elements[i].forward, constraints.elements[i].v); @@ -1035,131 +411,7 @@ int main(int argc, char *argv[]) { // printf("%f %f %f\n", components[3].e->line.norm[0], components[3].e->line.norm[1], components[3].e->line.C); - if(true) { - for(size_t i = 0; i < constraints.length; i++) { - struct constraint *constraint = &constraints.elements[i]; - if(!constraint->used) continue; - - switch(constraint->type) { - case CT_POINT_POINT_DISTANCE: { - } break; - case CT_LINE_LINE_ANGLE: { - assert(constraint->c1->type == COM_LINE); - assert(constraint->c2->type == COM_LINE); - - struct point intersect; - line_line_intersect(constraint->c1->e->line, constraint->c2->e->line, &intersect); - } break; - case CT_POINT_LINE_DISTANCE: - break; - case CT_END: abort(); - } - } - - for(size_t i = 0; i < constraints.length; i++) { - struct constraint *constraint = &constraints.elements[i]; - if(!constraint->used) continue; - - switch(constraint->type) { - case CT_POINT_POINT_DISTANCE: { - assert(constraint->c1->type == COM_POINT); - assert(constraint->c2->type == COM_POINT); - plot_distance_indicator(constraint->c1->e->point, constraint->c2->e->point, constraint->v); - } break; - case CT_LINE_LINE_ANGLE: { - assert(constraint->c1->type == COM_LINE); - assert(constraint->c2->type == COM_LINE); - - // Check if it's more likely a "parallel" constraint - if(fabs(sin(constraint->v)) < 0.1) continue; - - struct component *l1 = constraint->c1; - struct component *l2 = constraint->c2; - // Negative angles are counterclockwise, we have to swap - // the arguments to get proper rendering. - if(constraint->v < 0) { - l1 = constraint->c2; - l2 = constraint->c1; - } - - struct point p1; - struct point p2; - struct point intersect; - plot_angle(l1->e->line, l2->e->line, constraint->v, &intersect, &p1, &p2); - - extend_line_to(constraint->c1, &intersect); - extend_line_to(constraint->c2, &intersect); - extend_line_to(l1, &p1); - extend_line_to(l2, &p2); - } break; - case CT_POINT_LINE_DISTANCE: { - struct component *line; - struct component *point; - if(constraint->c1->type == COM_LINE) { - line = constraint->c1; - point = constraint->c2; - } else { - line = constraint->c2; - point = constraint->c1; - } - assert(point->type == COM_POINT); - assert(line->type == COM_LINE); - - if(constraint->v > 0) { - double dist = project_point_to_line_distance(point->e->point, line->e->line); - struct point closest; - line_distance_to_point(line->e->line, dist, &closest); - - plot_distance_indicator(point->e->point, closest, constraint->v); - } - - extend_line_to(line, &point->e->point); - } break; - case CT_END: abort(); - } - } - - for(size_t i = 0; i < constraints.length; i++) { - struct constraint *constraint = &constraints.elements[i]; - if(!constraint->used) continue; - - switch(constraint->type) { - case CT_POINT_POINT_DISTANCE: { - } break; - case CT_LINE_LINE_ANGLE: { - assert(constraint->c1->type == COM_LINE); - assert(constraint->c2->type == COM_LINE); - - struct point p1; - struct point p2; - 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); - 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); - constraint->c2->drawn = true; - } - } break; - case CT_POINT_LINE_DISTANCE: - break; - case CT_END: abort(); - } - } - } - - // plot_line_between(components[0].e->point, components[3].e->point); - // plot_line_between(components[3].e->point, components[1].e->point); - // plot_line_between(line_bend_end->point, line_end->point); - // plot_arc_between(line_ctr->point, line_bend_start->point, line_bend_end->point); - // plot_line_between(detector_right->point, decomposer_left->point); - // plot_line_between(decomposer_right->point, solver_left->point); - // plot_line_between(solver_right->point, solutions_left->point); + draw_constraints(&constraints); printf("</svg>\n"); } |
