diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2026-02-11 23:01:51 +0100 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2026-02-11 23:01:51 +0100 |
| commit | 96c91046d390b6d5c557ed0a574eacd407cce48c (patch) | |
| tree | b0f3289180aa229469618b08f8590af3a8e5215a | |
| parent | 679907d1b2023396b5f353b3390ca0879fc15e50 (diff) | |
Add another example
| -rw-r--r-- | examples/box_and_lines.c | 202 | ||||
| -rw-r--r-- | src/solve.c | 4 |
2 files changed, 204 insertions, 2 deletions
diff --git a/examples/box_and_lines.c b/examples/box_and_lines.c new file mode 100644 index 0000000..7026268 --- /dev/null +++ b/examples/box_and_lines.c @@ -0,0 +1,202 @@ +#include "cad.h" + +struct mid { + struct component p1; + struct component p2; + + struct component lb; + + struct component l1; + struct component l2; + + struct component x1; + + struct component p; + + struct component m; +}; + +void a_midpoint(struct mid *mid, struct topology *topo, struct constraints *constr) { + *mid = (struct mid){ + .p1 = {.type = COM_POINT}, + .p2 = {.type = COM_POINT}, + .lb = {.type = COM_LINE}, + + .l1 = {.type = COM_LINE}, + .l2 = {.type = COM_LINE}, + + .x1 = {.type = COM_POINT}, + + .p = {.type = COM_LINE}, + + .m = {.type = COM_POINT}, + }; + + if(constr != NULL) { + add_constraint(constr, (struct constraint[]){ + POINT_ON_LINE(&mid->p1, &mid->lb), + POINT_ON_LINE(&mid->p2, &mid->lb), + + LL_ANGLE(&mid->lb, &mid->l1, DEG(-30)), + POINT_ON_LINE(&mid->p1, &mid->l1), + LL_ANGLE(&mid->lb, &mid->l2, DEG(30)), + POINT_ON_LINE(&mid->p2, &mid->l2), + + POINT_ON_LINE(&mid->x1, &mid->l1), + POINT_ON_LINE(&mid->x1, &mid->l2), + + LL_ANGLE(&mid->lb, &mid->p, DEG(90)), + POINT_ON_LINE(&mid->x1, &mid->p), + + POINT_ON_LINE(&mid->m, &mid->lb), + POINT_ON_LINE(&mid->m, &mid->p), + + CEND(), + }); + } +} + +struct box { + struct component bottom_left; + struct component bottom_right; + struct component top_right; + struct component top_left; + + struct component bottom; + struct component right; + struct component top; + struct component left; + + struct mid left_mid; + struct mid right_mid; +}; + +void a_box(struct box *box, struct topology *topo, struct constraints *constr) { + assert(box != NULL); + + *box = (struct box){ + .bottom_left = {.type = COM_POINT}, + .bottom_right = {.type = COM_POINT}, + .top_right = {.type = COM_POINT}, + .top_left = {.type = COM_POINT}, + + .bottom = {.type = COM_LINE}, + .right = {.type = COM_LINE}, + .top = {.type = COM_LINE}, + .left = {.type = COM_LINE}, + }; + + a_midpoint(&box->left_mid, topo, constr); + a_midpoint(&box->right_mid, topo, constr); + + if(topo != NULL) { + add_fragment(topo, (struct topology_elem[]){ + TOPO_MOVETO(&box->bottom_left), + TOPO_LINETO(&box->bottom_right), + TOPO_LINETO(&box->top_right), + TOPO_LINETO(&box->top_left), + TOPO_LINETO(&box->bottom_left), + + TOPO_END(), + }); + } + + if(constr != NULL) { + add_constraint(constr, (struct constraint[]){ + POINT_ON_LINE(&box->bottom_left, &box->bottom), + POINT_ON_LINE(&box->bottom_right, &box->bottom), + + POINT_ON_LINE(&box->bottom_right, &box->right), + POINT_ON_LINE(&box->top_right, &box->right), + + POINT_ON_LINE(&box->top_right, &box->top), + POINT_ON_LINE(&box->top_left, &box->top), + + POINT_ON_LINE(&box->bottom_left, &box->left), + POINT_ON_LINE(&box->top_left, &box->left), + + LL_ANGLE(&box->left, &box->bottom, DEG(90)), + LL_ANGLE(&box->right, &box->top, DEG(90)), + LL_ANGLE(&box->top, &box->left, DEG(90)), + + PP_DISTANCE(&box->bottom_left, &box->bottom_right, 7), + PP_DISTANCE(&box->bottom_right, &box->top_right, 3), + + // Bind the mids + PP_SAME(&box->left_mid.p1, &box->top_left), + PP_SAME(&box->left_mid.p2, &box->bottom_left), + + PP_SAME(&box->right_mid.p1, &box->bottom_right), + PP_SAME(&box->right_mid.p2, &box->top_right), + CEND(), + }); + } +} + +void draw_from_constraints(struct constraints *c, struct topology *t, struct canvas *cv) { + struct drawing drawing = {}; + bool rc = solve_constraints(c, &drawing); + assert(rc); + + // 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); + free(params); + + begin_drawing(cv); + draw_topology(cv, t); + draw_constraints(cv, c); + end_drawing(cv); + + free_drawing(&drawing); +} + +int main(int argc, char *argv[]) { + struct constraints constraints = {}; + struct topology topo = {}; + + struct box box1; + a_box(&box1, &topo, &constraints); + + struct box box2; + a_box(&box2, &topo, &constraints); + + struct box box3; + a_box(&box3, &topo, &constraints); + + add_constraint(&constraints, (struct constraint[]){ + POINT_ON_LINE(&box2.bottom_left, &box1.bottom), + PP_DISTANCE(&box1.bottom_right, &box2.bottom_left, 3), + LL_ANGLE(&box2.bottom, &box1.bottom, 0), + + POINT_ON_LINE(&box3.bottom_left, &box1.bottom), + PP_DISTANCE(&box2.bottom_right, &box3.bottom_left, 3), + LL_ANGLE(&box3.bottom, &box2.bottom, 0), + CEND(), + }); + + add_fragment(&topo, (struct topology_elem[]){ + TOPO_MOVETO(&box1.right_mid.m), + TOPO_LINETO(&box2.left_mid.m), + + TOPO_MOVETO(&box2.right_mid.m), + TOPO_LINETO(&box3.left_mid.m), + + TOPO_END(), + }); + + struct canvas canvas = { + .state = CANVAS_INIT, + .f = stdout, + }; + + draw_from_constraints(&constraints, &topo, &canvas); + + free_constraints(&constraints); + free_topology(&topo); +} diff --git a/src/solve.c b/src/solve.c index 630a0a6..8ea65c1 100644 --- a/src/solve.c +++ b/src/solve.c @@ -51,7 +51,7 @@ void free_constraints(struct constraints *c) { // @COMPL: We should do something better than this. I don't really know what. struct frontier { - struct component *elems[64]; + struct component *elems[128]; size_t n; }; @@ -65,7 +65,7 @@ static bool frontier_scan(struct frontier *frontier, struct component *component static void add_frontier(struct frontier *frontier, struct component *component) { assert(!frontier_scan(frontier, component)); - assert(frontier->n < 64); + assert(frontier->n < 128); frontier->elems[frontier->n++] = component; } |
