diff options
| author | Jesper Jensen <jesper@jnsn.dev> | 2026-04-25 10:14:15 +0200 |
|---|---|---|
| committer | Jesper Jensen <jesper@jnsn.dev> | 2026-04-25 10:14:15 +0200 |
| commit | acf794c8ce51a78fca9531852d61c6f4dc0b140c (patch) | |
| tree | bbb7dca04eac95c203770cda90fa0e33f0c285ec | |
| parent | 2dbf9aed304c69431038d3b37e614e5d45dbcc56 (diff) | |
Try to make main solve again, fail
| -rw-r--r-- | src/debug.c | 15 | ||||
| -rw-r--r-- | src/main.c | 2 | ||||
| -rw-r--r-- | src/solve.c | 35 | ||||
| -rw-r--r-- | src/svg.c | 4 | ||||
| -rw-r--r-- | test/solve.c | 123 |
5 files changed, 169 insertions, 10 deletions
diff --git a/src/debug.c b/src/debug.c index 92540fc..97f0b3c 100644 --- a/src/debug.c +++ b/src/debug.c @@ -30,6 +30,7 @@ void print_subassemblies(struct constraints *c, struct subassembly *assemblies, component_type_name[ct->c2->type], (void*)ct->c2); } } + fprintf(stderr, "Unused constraints:\n"); for(size_t j = 0; j < c->length; j++) { struct constraint *ct = &c->elements[j]; @@ -38,6 +39,20 @@ void print_subassemblies(struct constraints *c, struct subassembly *assemblies, j, constraint_type_name[ct->type], ct->v, component_type_name[ct->c1->type], (void*)ct->c1, component_type_name[ct->c2->type], (void*)ct->c2); + + for(size_t i = 0; i < assemblies_num; i++) { + struct subassembly *a = &assemblies[i]; + for(size_t k = 0; k < a->articulation_num; k++) { + if(a->articulation[k] == ct->c1) + goto articulation_found; + if(a->articulation[k] == ct->c2) + goto articulation_found; + } + // Constraint did not touch one of the articulations + continue; +articulation_found: + fprintf(stderr, " Connects to %zu\n", i); + } } fprintf(stderr, "=========================\n"); } @@ -237,7 +237,7 @@ int main(int argc, char *argv[]) { a_box(&box, &topo, &constraints); add_constraint(&constraints, (struct constraint[]){ - PL_DISTANCE(&box.side[1], &box.corner[0], 20), + PP_DISTANCE(&box.corner[2], &box.corner[3], 20), PP_DISTANCE(&line.corner_end, &box.corner[0], 9.5), PL_DISTANCE(&box.corner[0], &components[3], 20), diff --git a/src/solve.c b/src/solve.c index 491cb6f..51b08a0 100644 --- a/src/solve.c +++ b/src/solve.c @@ -207,8 +207,10 @@ struct solve_step { static bool fix_first(struct constraint *constraints, size_t constraints_num, size_t *c) { for(size_t i = 0; i < constraints_num; i++) { if(constraints[i].used) continue; - if(constraints[i].type != CT_POINT_POINT_DISTANCE) continue; - if(constraints[i].v == 0.0) continue; + + if(constraints[i].type != CT_POINT_POINT_DISTANCE && constraints[i].type != CT_POINT_LINE_DISTANCE) continue; + if(constraints[i].type == CT_POINT_POINT_DISTANCE && constraints[i].v == 0.0) continue; + if(constraints[i].c1->ein != NULL) continue; if(constraints[i].c2->ein != NULL) continue; @@ -354,7 +356,7 @@ static bool try_fix_component(struct constraints *constraints_in, struct compone if(c->ein == NULL) { if(dest != c) { - if(!find_angle(constraints, constraints_num, dest, c, constraints[i].path)) + if(true)//!find_angle(constraints, constraints_num, dest, c, constraints[i].path)) continue; } } else { @@ -363,10 +365,11 @@ static bool try_fix_component(struct constraints *constraints_in, struct compone } // Is this actually correct? - assert(!dest->fixed); + if(dest->fixed) continue; *possibly_angle = &constraints[i]; *f2 = f; + if(c == dest) break; } } @@ -425,8 +428,8 @@ static size_t build_triangles(struct constraints *constraints_in, struct compone if(constraints[i].v != 0.0) continue; // We'll handle this elsewhere? - if(constraints[i].c1->ein != NULL) continue; - if(constraints[i].c2->ein != NULL) continue; + if(!constraints[i].c1->fixed && constraints[i].c1->ein != NULL) continue; + if(!constraints[i].c2->fixed && constraints[i].c2->ein != NULL) continue; struct component *oppo; bool forward; @@ -446,7 +449,7 @@ static size_t build_triangles(struct constraints *constraints_in, struct compone constraints[i].order = 0; constraints[i].used = useid; - steps[steps_i].assembly = assembly; + steps[steps_i].assembly = NULL; steps[steps_i].i = i; steps[steps_i].j = i; steps[steps_i].i_forward = forward; @@ -658,6 +661,8 @@ static void draw_for_subassembly(struct constraint *constraints, size_t fix, str static void draw_solution(struct constraint *constraints, size_t fix, struct solve_step* steps, size_t steps_num, struct drawing *drawing, struct subassembly *assembly) { { + assert(constraints[fix].type == CT_POINT_POINT_DISTANCE || + constraints[fix].type == CT_POINT_LINE_DISTANCE); constraints[fix].c1->e = insert_cmd(drawing, (struct command){ .op = CMD_ORIGIN, .hidden = true, @@ -693,6 +698,22 @@ static void draw_solution(struct constraint *constraints, size_t fix, struct sol .arg1 = c, .arg2 = xaxis, }); + + if(constraints[fix].type == CT_POINT_LINE_DISTANCE) { + static struct element right_angle = { + .type = ETYPE_VALUE, + .value = DEG(90), + }; + + constraints[fix].c2->e = insert_cmd(drawing, (struct command){ + .op = CMD_LINE_POINT_LINE_ANGLE, + .hidden = true, + .result.type = ETYPE_LINE, + .arg1 = constraints[fix].c2->e, + .arg2 = xaxis, + .arg3 = &right_angle, + }); + } } // Build the solution steps @@ -127,7 +127,7 @@ double project_point_to_line_distance(struct point p, struct line l) { // @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); + // assert(d1 >= 0.0); double m1 = sqrt(d1 / glm_vec2_norm2(l.norm)); return SIGNOF(det) * m1; @@ -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=\"-100 -150 200 200\" width=\"1200\" height=\"1200\" xmlns=\"http://www.w3.org/2000/svg\">\n"); + 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, "<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 ae54597..6213540 100644 --- a/test/solve.c +++ b/test/solve.c @@ -1,7 +1,31 @@ #include "cad/solve.h" +#include "cad/debug.h" #include <assert.h> +#include <math.h> #include <string.h> +static double point_line_distance_abs(struct point p, struct line l) { + return fabs((glm_vec2_dot(l.norm, p.pos) + l.C) / glm_vec2_norm(l.norm)); +} + +static double point_point_distance(struct point p1, struct point p2) { + vec2 between; + glm_vec2_sub(p1.pos, p2.pos, between); + return glm_vec2_norm(between); +} + +static double line_line_angle_abs(struct line l1, struct line l2) { + double dot = glm_vec2_dot(l1.norm, l2.norm); + double mag = glm_vec2_norm(l1.norm) * glm_vec2_norm(l2.norm); + double c = fabs(dot / mag); + c = fmin(1.0, fmax(-1.0, c)); + return acos(c); +} + +static void assert_near(double actual, double expected) { + assert(fabs(actual - expected) < 1e-6); +} + int main(int argc, char *argv[]) { struct subassembly assemblies[16] = {}; size_t assemblies_num; @@ -69,6 +93,105 @@ int main(int argc, char *argv[]) { memset(assemblies, 0, sizeof(assemblies)); { + printf("Corner by point-on-line root\n"); + struct constraints constraints = {}; + + struct component base = {.type = COM_LINE}; + struct component side = {.type = COM_LINE}; + struct component corner = {.type = COM_POINT}; + struct component tip = {.type = COM_POINT}; + + add_constraint(&constraints, (struct constraint[]){ + POINT_ON_LINE(&corner, &base), + POINT_ON_LINE(&corner, &side), + LL_ANGLE(&base, &side, DEG(90)), + PL_DISTANCE(&tip, &base, 10), + PL_DISTANCE(&tip, &side, -20), + CEND(), + }); + + struct drawing drawing = {}; + bool solved = solve_constraints(&constraints, &drawing, assemblies, &assemblies_num); + + assert(solved); + assert(assemblies_num == 1); + assert(drawing.root != NULL); + + double *params = malloc(sizeof(double) * constraints.length); + for(size_t i = 0; i < constraints.length; i++) { + params[i] = constraints.elements[i].v; + } + place_points(&drawing, params); + free(params); + + assert(corner.e != NULL); + assert(tip.e != NULL); + assert(base.e != NULL); + assert(side.e != NULL); + + print_subassemblies(&constraints, assemblies, assemblies_num); + + assert_near(point_line_distance_abs(corner.e->point, base.e->line), 0.0); + assert_near(point_line_distance_abs(corner.e->point, side.e->line), 0.0); + assert_near(line_line_angle_abs(base.e->line, side.e->line), DEG(90)); + assert_near(point_line_distance_abs(tip.e->point, base.e->line), 10.0); + assert_near(point_line_distance_abs(tip.e->point, side.e->line), 20.0); + + free_drawing(&drawing); + free_constraints(&constraints); + } + + memset(assemblies, 0, sizeof(assemblies)); + { + printf("Corner by offset point-line root\n"); + struct constraints constraints = {}; + + struct component base = {.type = COM_LINE}; + struct component side = {.type = COM_LINE}; + struct component corner = {.type = COM_POINT}; + struct component tip = {.type = COM_POINT}; + + add_constraint(&constraints, (struct constraint[]){ + PL_DISTANCE(&corner, &base, 5), + POINT_ON_LINE(&corner, &side), + LL_ANGLE(&base, &side, DEG(90)), + PL_DISTANCE(&tip, &base, 10), + PL_DISTANCE(&tip, &side, -20), + CEND(), + }); + + struct drawing drawing = {}; + bool solved = solve_constraints(&constraints, &drawing, assemblies, &assemblies_num); + + assert(solved); + assert(assemblies_num == 1); + assert(drawing.root != NULL); + + double *params = malloc(sizeof(double) * constraints.length); + for(size_t i = 0; i < constraints.length; i++) { + params[i] = constraints.elements[i].v; + } + place_points(&drawing, params); + free(params); + + assert(corner.e != NULL); + assert(tip.e != NULL); + assert(base.e != NULL); + assert(side.e != NULL); + + assert_near(point_line_distance_abs(corner.e->point, base.e->line), 5.0); + assert_near(point_line_distance_abs(corner.e->point, side.e->line), 0.0); + assert_near(line_line_angle_abs(base.e->line, side.e->line), DEG(90)); + assert_near(point_line_distance_abs(tip.e->point, base.e->line), 10.0); + assert_near(point_line_distance_abs(tip.e->point, side.e->line), 20.0); + assert_near(point_point_distance(corner.e->point, tip.e->point), sqrt(425.0)); + + free_drawing(&drawing); + free_constraints(&constraints); + } + + memset(assemblies, 0, sizeof(assemblies)); + { printf("Two triangles sharing a point one defined by angles\n"); struct constraints constraints = {}; |
