diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2026-03-29 12:07:19 +0200 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2026-03-29 12:07:19 +0200 |
| commit | e49c0ac340da53f3460a2aa02b514340ab0866e0 (patch) | |
| tree | f96fd5ec9fb085e0f4a55554bebcd8e5fc7e626c | |
| parent | 770216abb4bde565f824eb9010ae641ae118bb2d (diff) | |
Start testing as a cad tool
| -rw-r--r-- | examples/mount.c | 119 | ||||
| -rw-r--r-- | examples/triangle_tip.c | 2 | ||||
| -rw-r--r-- | src/solve.c | 18 | ||||
| -rw-r--r-- | src/svg.c | 2 | ||||
| -rw-r--r-- | test/solve.c | 19 |
5 files changed, 141 insertions, 19 deletions
diff --git a/examples/mount.c b/examples/mount.c new file mode 100644 index 0000000..7ffdc34 --- /dev/null +++ b/examples/mount.c @@ -0,0 +1,119 @@ +#include "cad.h" + +void draw_from_constraints(struct constraints *c, struct topology *t, struct canvas *cv) { + struct drawing drawing = {}; + struct subassembly assemblies[16] = {}; + size_t assemblies_num; + bool rc = solve_constraints(c, &drawing, assemblies, &assemblies_num); + 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); + + reconstruct_drawing(c, assemblies, &assemblies_num); + + 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 component mid_bot = {.type = COM_POINT}; + struct component pseudo = {.type = COM_POINT}; + struct component bot = {.type = COM_LINE}; + + struct component symmetry = {.type = COM_LINE}; + + struct component right_lower = {.type = COM_LINE}; + struct component left_lower = {.type = COM_LINE}; + + struct component right_under_hole_mid = {.type = COM_POINT}; + + struct component right_hole_bot_tan = {.type = COM_LINE}; + struct component left_hole_bot_tan = {.type = COM_LINE}; + struct component right_hole_top_tan = {.type = COM_LINE}; + struct component left_hole_top_tan = {.type = COM_LINE}; + + struct component right_hole_mid = {.type = COM_POINT}; + struct component left_hole_mid = {.type = COM_POINT}; + + struct component swoop_mid = {.type = COM_POINT}; + struct component swoop_top_tan = {.type = COM_POINT}; + + struct component left_bend = {.type = COM_POINT}; + struct component lb2 = {.type = COM_POINT}; + + struct component l1 = {.type = COM_LINE}; + + add_constraint(&constraints, (struct constraint[]){ + PP_DISTANCE(&mid_bot, &pseudo, 10), + POINT_ON_LINE(&mid_bot, &bot), + POINT_ON_LINE(&pseudo, &bot), + + LL_ANGLE(&bot, &symmetry, DEG(90)), + POINT_ON_LINE(&mid_bot, &symmetry), + + // @HACK This is going in the wrong direction? + PL_DISTANCE(&mid_bot, &right_lower, 35), + LL_ANGLE(&bot, &right_lower, DEG(-90)), + PL_DISTANCE(&left_lower, &mid_bot, 35), + LL_ANGLE(&bot, &left_lower, DEG(90)), + + PL_DISTANCE(&right_hole_mid, &bot, 80), + PL_DISTANCE(&left_hole_mid, &bot, 80), + PL_DISTANCE(&right_hole_mid, &symmetry, -60), + PL_DISTANCE(&left_hole_mid, &symmetry, 60), + + PL_DISTANCE(&right_under_hole_mid, &right_lower, 20), + PL_DISTANCE(&right_under_hole_mid, &right_hole_bot_tan, 20), + + LL_ANGLE(&right_hole_bot_tan, &symmetry, DEG(270)), + + PL_DISTANCE(&right_hole_mid, &right_hole_bot_tan, -28), + // PL_DISTANCE(&left_hole_mid, &left_hole_bot_tan, 56), + PL_DISTANCE(&right_hole_mid, &right_hole_top_tan, 28), + // PL_DISTANCE(&left_hole_mid, &left_hole_top_tan, 56), + + POINT_ON_LINE(&swoop_mid, &symmetry), + PP_DISTANCE(&swoop_mid, &right_hole_mid, 120 - 28), + // PL_DISTANCE(&swoop_mid, &swoop_top_tan, 120), + PL_DISTANCE(&swoop_mid, &right_hole_top_tan, 120), + + + // Make a triangle + CEND(), + }); + + add_fragment(&topo, (struct topology_elem[]){ + TOPO_MOVETO(&mid_bot), + TOPO_LINETO(&right_hole_mid), + + TOPO_MOVETO(&mid_bot), + // TOPO_LINETO(&p2), + // TOPO_LINETO(&p3), + TOPO_END(), + }); + + struct canvas canvas = { + .state = CANVAS_INIT, + .f = stdout, + }; + + draw_from_constraints(&constraints, &topo, &canvas); + + free_constraints(&constraints); + return 0; +} diff --git a/examples/triangle_tip.c b/examples/triangle_tip.c index b6fcf99..4da57da 100644 --- a/examples/triangle_tip.c +++ b/examples/triangle_tip.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { POINT_ON_LINE(&p2, &t1base), POINT_ON_LINE(&p1, &t1bas2), - LL_ANGLE(&t1base, &t1bas2, DEG(-10)), + LL_ANGLE(&t1base, &t1bas2, DEG(-5)), // With another triangle sharing a point PP_DISTANCE(&p4, &p5, 30), diff --git a/src/solve.c b/src/solve.c index 5b3cdce..66cbb7f 100644 --- a/src/solve.c +++ b/src/solve.c @@ -810,8 +810,8 @@ constraint_matches_j: // Here we have two assemblies, one fixed and the other not, // that share a single point and each one other point that - // share a constraint. We can hopefully place the rest of the - // assembly from that information + // share a constraint. Try place the rigid body based on that + // information float theta = atan2(constraint->c1->e->line.norm[1], constraint->c1->e->line.norm[0]) - atan2(constraint->c2->e->line.norm[1], constraint->c2->e->line.norm[0]); theta = forward ? -theta : theta; @@ -865,22 +865,22 @@ constraint_matches_j: // Find a point on the line, what point doesn't matter // since the whole line is moving struct line line = c->e->line; - double a = line.norm[0]; - double b = line.norm[1]; - double rec = pow(a, 2) + pow(b, 2); - double x0 = -a*line.C / rec; - double y0 = -b*line.C / rec; - vec2 p = {x0, y0}; + vec2 p; + glm_vec2_zero(p); + + glm_vec2_muladds(line.norm, line.C, p); + double rec = glm_vec2_norm2(line.norm); + glm_vec2_divs(p, rec, p); // Rotate the line to the new orientation glm_vec2_rotate(line.norm, theta, line.norm); // Transform the fixed point affine_transform_vec2(transform, p, p); - glm_vec2_negate(p); // Calculate a C to follow the new point + glm_vec2_negate(p); line.C = glm_vec2_dot(line.norm, p); c->e->line = line; @@ -369,7 +369,7 @@ 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, "<svg version=\"1.1\" viewBox=\"-100 -100 200 200\" 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"); diff --git a/test/solve.c b/test/solve.c index e1729ff..65b51d6 100644 --- a/test/solve.c +++ b/test/solve.c @@ -1,5 +1,6 @@ #include "cad/solve.h" #include <assert.h> +#include <string.h> int main(int argc, char *argv[]) { struct subassembly assemblies[16] = {}; @@ -146,7 +147,7 @@ int main(int argc, char *argv[]) { POINT_ON_LINE(&p5, &t2base), // The edge they don't share is constrained - LL_ANGLE(&t1base, &t2base, DEG(40)), + LL_ANGLE(&t1base, &t2base, DEG(70)), CEND(), }); @@ -159,17 +160,19 @@ int main(int argc, char *argv[]) { for(size_t i = 0; i < constraints.length; i++) { params[i] = constraints.elements[i].v; } - place_points(&drawing, params); + free(params); reconstruct_drawing(&constraints, assemblies, &assemblies_num); - // @COMPL: We don't currently know how to derive an angle constraint - // from the rigid triangle. We'd probably need to do some sort of - // recursive solving, and even then you can't construct it without some - // sort of math in the construction phase. - // assert(!solved); - // assert(solved); + assert(solved); + + assert(glm_vec2_eqv_eps(p1.e->point.pos, (vec2){ 0.0 , 0.0 })); + assert(glm_vec2_eqv_eps(p2.e->point.pos, (vec2){30.0 , 0.0 })); + assert(glm_vec2_eqv_eps(p3.e->point.pos, (vec2){15.0 , 25.980762})); + + assert(glm_vec2_eqv_eps(p4.e->point.pos, (vec2){34.283630, 2.999428})); + assert(glm_vec2_eqv_eps(p5.e->point.pos, (vec2){44.544235, 31.190207})); free_drawing(&drawing); free_constraints(&constraints); |
