summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/debug.c15
-rw-r--r--src/main.c2
-rw-r--r--src/solve.c35
-rw-r--r--src/svg.c4
-rw-r--r--test/solve.c123
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");
}
diff --git a/src/main.c b/src/main.c
index cd356cc..1ad2369 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/svg.c b/src/svg.c
index 23a62c8..7144482 100644
--- a/src/svg.c
+++ b/src/svg.c
@@ -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 = {};