From 197fd727099d264cbf7c746f752f762dd3618814 Mon Sep 17 00:00:00 2001 From: Jesper Jensen Date: Sat, 18 Oct 2025 09:28:59 +0200 Subject: Extract solving into procedure --- src/main.c | 847 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 426 insertions(+), 421 deletions(-) diff --git a/src/main.c b/src/main.c index 6e4352c..90942ea 100644 --- a/src/main.c +++ b/src/main.c @@ -947,429 +947,101 @@ bool find_angle(struct constraint *constraints, size_t constraints_num, struct c return false; } -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; +void solve_constraints(struct constraint *constraints, size_t constraints_num, struct drawing *drawing) { + struct frontier frontier = {}; + uint64_t order = 1; - // 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}); + for(size_t i = 0; i < constraints_num; i++) { + constraints[i].path[0].i = -1; + constraints[i].forward = true; + } - // Figure 4 - struct component components[] = { - {.type = COM_POINT}, - {.type = COM_POINT}, - {.type = COM_POINT}, - {.type = COM_LINE}, - {.type = COM_LINE}, - {.type = COM_POINT}, - }; + // Step 1 Pick some point point distance constraint as the base + for(size_t i = 0; i < constraints_num; i++) { + assert(!constraints[i].used); - struct smooth_line line = { - .l1 = {.type = COM_LINE}, - .l2 = {.type = COM_LINE}, - .corner = {.type = COM_POINT}, - .corner_center = {.type = COM_POINT}, - .end = {.type = COM_POINT}, - .start = {.type = COM_POINT}, + if(constraints[i].type != CT_POINT_POINT_DISTANCE) continue; - .perp1 = {.type = COM_LINE}, - .perp2 = {.type = COM_LINE}, + constraints[i].c1->e = insert_cmd(drawing, (struct command){ + .op = CMD_ORIGIN, + .hidden = true, + .result.type = ETYPE_POINT, + }); - .corner_start = {.type = COM_POINT}, - .corner_end = {.type = COM_POINT}, - }; + struct element *xaxis = insert_cmd(drawing, (struct command){ + .op = CMD_LINE_X, + .hidden = true, + .result.type = ETYPE_LINE, + }); - struct box box = { - .corner = { - {.type = COM_POINT}, - {.type = COM_POINT}, - {.type = COM_POINT}, - {.type = COM_POINT}, - }, - .side = { - {.type = COM_LINE}, - {.type = COM_LINE}, - {.type = COM_LINE}, - {.type = COM_LINE}, - }, - }; + struct element *distance = insert_cmd(drawing, (struct command){ + .op = CMD_VALUE_INPUT, + .result.type = ETYPE_VALUE, + }); - struct constraint constraints[] = { - { - .type = CT_POINT_POINT_DISTANCE, - .v = 13, - .c1 = &components[0], - .c2 = &components[1], - }, - { - .type = CT_POINT_POINT_DISTANCE, - .v = 10, - .c1 = &components[1], - .c2 = &components[2], - }, - { - .type = CT_POINT_POINT_DISTANCE, - .v = 10, - .c1 = &components[2], - .c2 = &components[0], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &components[0], - .c2 = &components[3], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &components[1], - .c2 = &components[3], - }, - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/1.7, - .c1 = &components[3], - .c2 = &components[4], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &components[4], - .c2 = &components[1], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &components[4], - .c2 = &components[5], - }, - { - .type = CT_POINT_POINT_DISTANCE, - .v = 12.8, - .c1 = &components[0], - .c2 = &components[5], - }, + struct element *c = insert_cmd(drawing, (struct command){ + .op = CMD_CIRCLE_CENTER_RADIUS, + .hidden = true, + .result.type = ETYPE_CIRCLE, + .arg1 = constraints[i].c1->e, + .arg2 = distance, + }); - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &components[3], - .c2 = &line.l1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &components[5], - .c2 = &line.l1, - }, + constraints[i].c2->e = insert_cmd(drawing, (struct command){ + .op = CMD_POINT_CIRCLE_LINE, + .hidden = true, + .result.type = ETYPE_POINT, + .arg1 = c, + .arg2 = xaxis, + }); - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &line.l2, - .c2 = &line.l1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner, - .c2 = &line.l2, - }, + constraints[i].used = true; + constraints[i].order = order++; + add_frontier(&frontier, constraints[i].c1); + add_frontier(&frontier, constraints[i].c2); + break; + } - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner, - .c2 = &line.l1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.end, - .c2 = &line.l2, - }, + // Step 2 we iteratively expand the frontier from the selected base + while(true) { + for(size_t i = 0; i < constraints_num; i++) { + if(constraints[i].used) continue; - { - .type = CT_POINT_LINE_DISTANCE, - .v = 10, - .c1 = &line.end, - .c2 = &line.l1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 12, - .c1 = &line.end, - .c2 = &components[3], - }, + struct component *oppo_i; + struct component *local_i; - { - .type = CT_POINT_LINE_DISTANCE, - .v = 1, - .c1 = &line.corner_center, - .c2 = &line.l1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = -1, - .c1 = &line.corner_center, - .c2 = &line.l2, - }, + if(frontier_scan(&frontier, constraints[i].c1)) { + oppo_i = constraints[i].c2; + local_i = constraints[i].c1; + } else if(frontier_scan(&frontier, constraints[i].c2)) { + oppo_i = constraints[i].c1; + local_i = constraints[i].c2; + } else continue; - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &line.l1, - .c2 = &line.perp1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_center, - .c2 = &line.perp1, - }, + for(size_t j = i+1; j < constraints_num; j++) { + if(constraints[j].used) continue; - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_start, - .c2 = &line.perp1, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_start, - .c2 = &line.l1, - }, + struct component *oppo_j; + struct component *local_j; - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &line.l2, - .c2 = &line.perp2, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_center, - .c2 = &line.perp2, - }, - - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_end, - .c2 = &line.perp2, - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &line.corner_end, - .c2 = &line.l2, - }, - - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[0], - .c2 = &box.side[0], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[1], - .c2 = &box.side[0], - }, - - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[1], - .c2 = &box.side[1], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[2], - .c2 = &box.side[1], - }, - - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[2], - .c2 = &box.side[2], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[3], - .c2 = &box.side[2], - }, - - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[3], - .c2 = &box.side[3], - }, - { - .type = CT_POINT_LINE_DISTANCE, - .v = 0, - .c1 = &box.corner[0], - .c2 = &box.side[3], - }, - - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &box.side[3], - .c2 = &box.side[0], - }, - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &box.side[1], - .c2 = &box.side[2], - }, - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI/2, - .c1 = &box.side[2], - .c2 = &box.side[3], - }, - { - .type = CT_LINE_LINE_ANGLE, - .v = M_PI*1/2, - .c1 = &components[3], - .c2 = &box.side[1], - }, - - { - .type = CT_POINT_POINT_DISTANCE, - .v = 10, - .c1 = &line.corner_start, - .c2 = &box.corner[0], - }, - { - .type = CT_POINT_POINT_DISTANCE, - .v = 10, - .c1 = &line.corner_end, - .c2 = &box.corner[0], - }, - - { - .type = CT_POINT_POINT_DISTANCE, - .v = 20, - .c1 = &box.corner[0], - .c2 = &box.corner[1], - }, - { - .type = CT_POINT_POINT_DISTANCE, - .v = 10, - .c1 = &box.corner[1], - .c2 = &box.corner[2], - }, - }; - - struct frontier frontier = {}; - struct drawing drawing = {}; - uint64_t order = 1; - - for(size_t i = 0; i < sizeof(constraints)/sizeof(constraints[0]); i++) { - constraints[i].path[0].i = -1; - constraints[i].forward = true; - } - - // Step 1 Pick some point point distance constraint as the base - for(size_t i = 0; i < sizeof(constraints)/sizeof(constraints[0]); i++) { - assert(!constraints[i].used); - - if(constraints[i].type != CT_POINT_POINT_DISTANCE) continue; - - constraints[i].c1->e = insert_cmd(&drawing, (struct command){ - .op = CMD_ORIGIN, - .hidden = true, - .result.type = ETYPE_POINT, - }); - - struct element *xaxis = insert_cmd(&drawing, (struct command){ - .op = CMD_LINE_X, - .hidden = true, - .result.type = ETYPE_LINE, - }); - - struct element *distance = insert_cmd(&drawing, (struct command){ - .op = CMD_VALUE_INPUT, - .result.type = ETYPE_VALUE, - }); - - struct element *c = insert_cmd(&drawing, (struct command){ - .op = CMD_CIRCLE_CENTER_RADIUS, - .hidden = true, - .result.type = ETYPE_CIRCLE, - .arg1 = constraints[i].c1->e, - .arg2 = distance, - }); - - constraints[i].c2->e = insert_cmd(&drawing, (struct command){ - .op = CMD_POINT_CIRCLE_LINE, - .hidden = true, - .result.type = ETYPE_POINT, - .arg1 = c, - .arg2 = xaxis, - }); - - constraints[i].used = true; - constraints[i].order = order++; - add_frontier(&frontier, constraints[i].c1); - add_frontier(&frontier, constraints[i].c2); - break; - } - - // Step 2 we iteratively expand the frontier from the selected base - while(true) { - for(size_t i = 0; i < sizeof(constraints)/sizeof(constraints[0]); i++) { - if(constraints[i].used) continue; - - struct component *oppo_i; - struct component *local_i; - - if(frontier_scan(&frontier, constraints[i].c1)) { - oppo_i = constraints[i].c2; - local_i = constraints[i].c1; - } else if(frontier_scan(&frontier, constraints[i].c2)) { - oppo_i = constraints[i].c1; - local_i = constraints[i].c2; - } else continue; - - for(size_t j = i+1; j < sizeof(constraints)/sizeof(constraints[0]); j++) { - if(constraints[j].used) continue; - - struct component *oppo_j; - struct component *local_j; - - if(frontier_scan(&frontier, constraints[j].c1)) { - oppo_j = constraints[j].c2; - local_j = constraints[j].c1; - } else if(frontier_scan(&frontier, constraints[j].c2)) { - oppo_j = constraints[j].c1; - local_j = constraints[j].c2; - } else continue; + if(frontier_scan(&frontier, constraints[j].c1)) { + oppo_j = constraints[j].c2; + local_j = constraints[j].c1; + } else if(frontier_scan(&frontier, constraints[j].c2)) { + oppo_j = constraints[j].c1; + local_j = constraints[j].c2; + } else continue; // One of the constraints can't be an angle one if(constraints[i].type == CT_LINE_LINE_ANGLE && constraints[j].type == CT_LINE_LINE_ANGLE) continue; if(oppo_i != oppo_j) { if(constraints[i].type == CT_LINE_LINE_ANGLE) { - if(!find_angle(constraints, sizeof(constraints)/sizeof(constraints[0]), oppo_i, oppo_j, constraints[i].path)) continue; + if(!find_angle(constraints, constraints_num, oppo_i, oppo_j, constraints[i].path)) continue; oppo_i = oppo_j; } else if(constraints[j].type == CT_LINE_LINE_ANGLE) { - if(!find_angle(constraints, sizeof(constraints)/sizeof(constraints[0]), oppo_j, oppo_i, constraints[j].path)) continue; + if(!find_angle(constraints, constraints_num, oppo_j, oppo_i, constraints[j].path)) continue; oppo_j = oppo_i; } else continue; @@ -1384,17 +1056,17 @@ int main(int argc, char *argv[]) { && local_j->type == COM_POINT) { assert(oppo_i->type == COM_POINT); - struct element *d1 = insert_cmd(&drawing, (struct command){ + struct element *d1 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *d2 = insert_cmd(&drawing, (struct command){ + struct element *d2 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *c1 = insert_cmd(&drawing, (struct command){ + struct element *c1 = insert_cmd(drawing, (struct command){ .op = CMD_CIRCLE_CENTER_RADIUS, .hidden = true, .result.type = ETYPE_CIRCLE, @@ -1402,7 +1074,7 @@ int main(int argc, char *argv[]) { .arg2 = d1, }); - struct element *c2 = insert_cmd(&drawing, (struct command){ + struct element *c2 = insert_cmd(drawing, (struct command){ .op = CMD_CIRCLE_CENTER_RADIUS, .hidden = true, .result.type = ETYPE_CIRCLE, @@ -1410,7 +1082,7 @@ int main(int argc, char *argv[]) { .arg2 = d2, }); - oppo_i->e = insert_cmd(&drawing, (struct command){ + oppo_i->e = insert_cmd(drawing, (struct command){ .op = CMD_POINT_CIRCLE_CIRCLE, .hidden = true, .result.type = ETYPE_POINT, @@ -1423,16 +1095,16 @@ int main(int argc, char *argv[]) { && local_j->type == COM_POINT) { assert(oppo_i->type == COM_LINE); - struct element *d1 = insert_cmd(&drawing, (struct command){ + struct element *d1 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *d2 = insert_cmd(&drawing, (struct command){ + struct element *d2 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *c1 = insert_cmd(&drawing, (struct command){ + struct element *c1 = insert_cmd(drawing, (struct command){ .op = CMD_CIRCLE_CENTER_RADIUS, .hidden = true, .result.type = ETYPE_CIRCLE, @@ -1440,7 +1112,7 @@ int main(int argc, char *argv[]) { .arg2 = d1, }); - struct element *c2 = insert_cmd(&drawing, (struct command){ + struct element *c2 = insert_cmd(drawing, (struct command){ .op = CMD_CIRCLE_CENTER_RADIUS, .hidden = true, .result.type = ETYPE_CIRCLE, @@ -1448,7 +1120,7 @@ int main(int argc, char *argv[]) { .arg2 = d2, }); - oppo_i->e = insert_cmd(&drawing, (struct command){ + oppo_i->e = insert_cmd(drawing, (struct command){ .op = CMD_LINE_CIRCLE_CIRCLE_TANGENT, .hidden = true, .result.type = ETYPE_LINE, @@ -1461,16 +1133,16 @@ int main(int argc, char *argv[]) { && local_j->type == COM_LINE) { assert(oppo_i->type == COM_POINT); - struct element *d1 = insert_cmd(&drawing, (struct command){ + struct element *d1 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *d2 = insert_cmd(&drawing, (struct command){ + struct element *d2 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *l1 = insert_cmd(&drawing, (struct command){ + struct element *l1 = insert_cmd(drawing, (struct command){ .op = CMD_LINE_LINE_DISTANCE_PARALLEL, .hidden = true, .result.type = ETYPE_LINE, @@ -1478,7 +1150,7 @@ int main(int argc, char *argv[]) { .arg2 = d1, }); - struct element *l2 = insert_cmd(&drawing, (struct command){ + struct element *l2 = insert_cmd(drawing, (struct command){ .op = CMD_LINE_LINE_DISTANCE_PARALLEL, .hidden = true, .result.type = ETYPE_LINE, @@ -1486,7 +1158,7 @@ int main(int argc, char *argv[]) { .arg2 = d2, }); - oppo_i->e = insert_cmd(&drawing, (struct command){ + oppo_i->e = insert_cmd(drawing, (struct command){ .op = CMD_POINT_LINE_LINE, .hidden = true, .result.type = ETYPE_POINT, @@ -1500,7 +1172,7 @@ int main(int argc, char *argv[]) { assert(oppo_i->type == COM_LINE); constraints[i].forward = constraints[i].c1 == local_i; - build_angle_point_line(&drawing, local_i, local_j, oppo_i); + build_angle_point_line(drawing, local_i, local_j, oppo_i); } else if(constraints[i].type == CT_POINT_LINE_DISTANCE && local_i->type == COM_POINT && constraints[j].type == CT_LINE_LINE_ANGLE @@ -1519,23 +1191,23 @@ int main(int argc, char *argv[]) { j = j ^ i; i ^= j; - build_angle_point_line(&drawing, local_i, local_j, oppo_i); + build_angle_point_line(drawing, local_i, local_j, oppo_i); } else if(constraints[i].type == CT_POINT_LINE_DISTANCE && local_i->type == COM_LINE && constraints[j].type == CT_POINT_POINT_DISTANCE && local_j->type == COM_POINT) { assert(oppo_i->type == COM_POINT); - struct element *d1 = insert_cmd(&drawing, (struct command){ + struct element *d1 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *d2 = insert_cmd(&drawing, (struct command){ + struct element *d2 = insert_cmd(drawing, (struct command){ .op = CMD_VALUE_INPUT, .result.type = ETYPE_VALUE, }); - struct element *l = insert_cmd(&drawing, (struct command){ + struct element *l = insert_cmd(drawing, (struct command){ .op = CMD_LINE_LINE_DISTANCE_PARALLEL, .hidden = true, .result.type = ETYPE_LINE, @@ -1543,7 +1215,7 @@ int main(int argc, char *argv[]) { .arg2 = d1, }); - struct element *c = insert_cmd(&drawing, (struct command){ + struct element *c = insert_cmd(drawing, (struct command){ .op = CMD_CIRCLE_CENTER_RADIUS, .hidden = true, .result.type = ETYPE_CIRCLE, @@ -1551,7 +1223,7 @@ int main(int argc, char *argv[]) { .arg2 = d2, }); - oppo_i->e = insert_cmd(&drawing, (struct command){ + oppo_i->e = insert_cmd(drawing, (struct command){ .op = CMD_POINT_CIRCLE_LINE, .hidden = true, .result.type = ETYPE_POINT, @@ -1578,6 +1250,339 @@ candidate_found: ; } +} + +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}); + + // Figure 4 + struct component components[] = { + {.type = COM_POINT}, + {.type = COM_POINT}, + {.type = COM_POINT}, + {.type = COM_LINE}, + {.type = COM_LINE}, + {.type = COM_POINT}, + }; + + struct smooth_line line = { + .l1 = {.type = COM_LINE}, + .l2 = {.type = COM_LINE}, + .corner = {.type = COM_POINT}, + .corner_center = {.type = COM_POINT}, + .end = {.type = COM_POINT}, + .start = {.type = COM_POINT}, + + .perp1 = {.type = COM_LINE}, + .perp2 = {.type = COM_LINE}, + + .corner_start = {.type = COM_POINT}, + .corner_end = {.type = COM_POINT}, + }; + + struct box box = { + .corner = { + {.type = COM_POINT}, + {.type = COM_POINT}, + {.type = COM_POINT}, + {.type = COM_POINT}, + }, + .side = { + {.type = COM_LINE}, + {.type = COM_LINE}, + {.type = COM_LINE}, + {.type = COM_LINE}, + }, + }; + + struct constraint constraints[] = { + { + .type = CT_POINT_POINT_DISTANCE, + .v = 13, + .c1 = &components[0], + .c2 = &components[1], + }, + { + .type = CT_POINT_POINT_DISTANCE, + .v = 10, + .c1 = &components[1], + .c2 = &components[2], + }, + { + .type = CT_POINT_POINT_DISTANCE, + .v = 10, + .c1 = &components[2], + .c2 = &components[0], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &components[0], + .c2 = &components[3], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &components[1], + .c2 = &components[3], + }, + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/1.7, + .c1 = &components[3], + .c2 = &components[4], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &components[4], + .c2 = &components[1], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &components[4], + .c2 = &components[5], + }, + { + .type = CT_POINT_POINT_DISTANCE, + .v = 12.8, + .c1 = &components[0], + .c2 = &components[5], + }, + + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &components[3], + .c2 = &line.l1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &components[5], + .c2 = &line.l1, + }, + + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &line.l2, + .c2 = &line.l1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner, + .c2 = &line.l2, + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner, + .c2 = &line.l1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.end, + .c2 = &line.l2, + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 10, + .c1 = &line.end, + .c2 = &line.l1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 12, + .c1 = &line.end, + .c2 = &components[3], + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 1, + .c1 = &line.corner_center, + .c2 = &line.l1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = -1, + .c1 = &line.corner_center, + .c2 = &line.l2, + }, + + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &line.l1, + .c2 = &line.perp1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_center, + .c2 = &line.perp1, + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_start, + .c2 = &line.perp1, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_start, + .c2 = &line.l1, + }, + + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &line.l2, + .c2 = &line.perp2, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_center, + .c2 = &line.perp2, + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_end, + .c2 = &line.perp2, + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &line.corner_end, + .c2 = &line.l2, + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[0], + .c2 = &box.side[0], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[1], + .c2 = &box.side[0], + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[1], + .c2 = &box.side[1], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[2], + .c2 = &box.side[1], + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[2], + .c2 = &box.side[2], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[3], + .c2 = &box.side[2], + }, + + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[3], + .c2 = &box.side[3], + }, + { + .type = CT_POINT_LINE_DISTANCE, + .v = 0, + .c1 = &box.corner[0], + .c2 = &box.side[3], + }, + + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &box.side[3], + .c2 = &box.side[0], + }, + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &box.side[1], + .c2 = &box.side[2], + }, + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI/2, + .c1 = &box.side[2], + .c2 = &box.side[3], + }, + { + .type = CT_LINE_LINE_ANGLE, + .v = M_PI*1/2, + .c1 = &components[3], + .c2 = &box.side[1], + }, + + { + .type = CT_POINT_POINT_DISTANCE, + .v = 10, + .c1 = &line.corner_start, + .c2 = &box.corner[0], + }, + { + .type = CT_POINT_POINT_DISTANCE, + .v = 10, + .c1 = &line.corner_end, + .c2 = &box.corner[0], + }, + + { + .type = CT_POINT_POINT_DISTANCE, + .v = 20, + .c1 = &box.corner[0], + .c2 = &box.corner[1], + }, + { + .type = CT_POINT_POINT_DISTANCE, + .v = 10, + .c1 = &box.corner[1], + .c2 = &box.corner[2], + }, + }; + + struct drawing drawing = {}; + solve_constraints(constraints, sizeof(constraints)/sizeof(constraints[0]), &drawing); + double *params = malloc(sizeof(double) * (sizeof(constraints)/sizeof(constraints[0]))); for(size_t i = 0; i < sizeof(constraints)/sizeof(constraints[0]); i++) { if(constraints[i].order == 0) continue; -- cgit v1.2.3