summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c634
1 files changed, 372 insertions, 262 deletions
diff --git a/src/main.c b/src/main.c
index 452ad0a..1751edb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,11 +6,13 @@
#include <string.h>
enum operation {
+ CMD_VALUE_INPUT,
CMD_ORIGIN,
+ CMD_LINE_X,
CMD_CIRCLE_CENTER_RADIUS,
CMD_CIRCLE_CENTER_POINT,
- CMD_LINE_POINT_ANGLE,
CMD_LINE_POINT_POINT,
+ CMD_LINE_POINT_LINE_ANGLE,
CMD_POINT_CIRCLE_LINE,
CMD_POINT_CIRCLE_CIRCLE,
CMD_POINT_LINE_LINE,
@@ -30,30 +32,43 @@ struct line {
double C;
};
-struct command {
- enum operation op;
- uint8_t root;
- bool hidden;
-
- union {
- struct command *as_cmd;
- double as_input;
- } arg1;
+enum EType {
+ ETYPE_VALUE,
+ ETYPE_CIRCLE,
+ ETYPE_POINT,
+ ETYPE_LINE,
+};
- union {
- struct command *as_cmd;
- double as_input;
- } arg2;
+struct element {
+ enum EType type;
union {
+ double value;
struct circle circle;
struct point point;
struct line line;
};
+};
+
+struct command {
+ enum operation op;
+ uint8_t root;
+ bool hidden;
+
+ struct element *arg1;
+ struct element *arg2;
+ struct element *arg3;
+
+ struct element result;
struct command *next;
};
+struct drawing {
+ struct command *root;
+ struct command *tail;
+};
+
void circle_line_intersect(struct circle circle, struct line line, uint8_t root, struct point *point) {
double a = line.norm[0];
double b = line.norm[1];
@@ -96,382 +111,477 @@ void plot_line_between(struct point p1, struct point p2) {
}
void plot_line(struct line l) {
- double minx = -50;
- double maxx = 50;
-
- double miny = -(l.norm[0] * minx + l.C) / l.norm[1];
- double maxy = -(l.norm[0] * maxx + l.C) / l.norm[1];
+ // @HACK I've just duplicated this for vertical lines. There's a more
+ // efficient solution
+ if(l.norm[1] != 0) {
+ double minx = -50;
+ double maxx = 50;
+
+ double miny = -(l.norm[0] * minx + l.C) / l.norm[1];
+ double maxy = -(l.norm[0] * maxx + l.C) / l.norm[1];
+ printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" stroke-width=\".2\" />\n", minx, -miny, maxx, -maxy);
+ } else {
+ double miny = -50;
+ double maxy = 50;
- printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" stroke-width=\".2\" />\n", minx, -miny, maxx, -maxy);
+ double minx = -(l.norm[1] * miny + l.C) / l.norm[0];
+ double maxx = -(l.norm[1] * maxy + l.C) / l.norm[0];
+ printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" stroke-width=\".2\" />\n", minx, -miny, maxx, -maxy);
+ }
}
-void plot_arc_between(double r, struct point p1, struct point p2) {
- printf("<path d=\"M %f %f A %f %f 0 0 0 %f %f\" stroke=\"black\" stroke-width=\".2\" fill=\"none\" />\n", p1.pos[0], -p1.pos[1], r, r, p2.pos[0], -p2.pos[1]);
+void plot_arc_between(struct point c, struct point p1, struct point p2) {
+ // @COML: There's something missing here about which side of the arc we
+ // want. I think we can figure that out from the relation of the center and
+ // the points
+ vec2 t;
+ glm_vec2_sub(c.pos, p1.pos, t);
+ double r = glm_vec2_norm(t);
+ printf("<path d=\"M %f %f A %f %f 0 0 0 %f %f\" stroke=\"black\" stroke-width=\".2\" fill=\"none\" />\n", p2.pos[0], -p2.pos[1], r, r, p1.pos[0], -p1.pos[1]);
}
void plot_circle(struct circle c) {
printf("<circle cx=\"%f\" cy=\"%f\" r=\"%f\" fill=\"none\" stroke=\"black\" stroke-width=\".1\" />\n", c.center[0], -c.center[1], c.radius);
}
-struct command* insert_cmd(struct command **cmds, struct command cmd) {
+struct element* insert_cmd(struct drawing *drawing, struct command cmd) {
struct command *new = calloc(sizeof(struct command), 1);
memcpy(new, &cmd, sizeof(struct command));
assert(new != NULL);
- if(*cmds != NULL) (*cmds)->next = new;
- *cmds = new;
+ if(drawing->tail != NULL) drawing->tail->next = new;
+ else drawing->root = new;
+ drawing->tail = new;
- return new;
+ return &new->result;
}
-struct command *create_perp(struct command **cmds, struct command *l, struct command *p) {
- struct command *c1 = insert_cmd(cmds, (struct command){
+struct element *create_perp(struct drawing *cmds, struct element *l, struct element *p, bool hide) {
+ static struct element radius = {
+ .type = ETYPE_VALUE,
+ .value = 5, // Just a random number
+ };
+
+ struct element *c1 = insert_cmd(cmds, (struct command){
.op = CMD_CIRCLE_CENTER_RADIUS,
- .hidden = true,
- .arg1.as_cmd = p,
- .arg2.as_input = 5, // Not actually input, just a random number
+ .result.type = ETYPE_CIRCLE,
+ .hidden = hide,
+ .arg1 = p,
+ .arg2 = &radius,
});
- struct command *p1 = insert_cmd(cmds, (struct command){
+ struct element *p1 = insert_cmd(cmds, (struct command){
.op = CMD_POINT_CIRCLE_LINE,
+ .result.type = ETYPE_POINT,
.hidden = true,
.root = 0,
- .arg1.as_cmd = c1,
- .arg2.as_cmd = l,
+ .arg1 = c1,
+ .arg2 = l,
});
- struct command *p2 = insert_cmd(cmds, (struct command){
+ struct element *p2 = insert_cmd(cmds, (struct command){
.op = CMD_POINT_CIRCLE_LINE,
+ .result.type = ETYPE_POINT,
.hidden = true,
.root = 1,
- .arg1.as_cmd = c1,
- .arg2.as_cmd = l,
+ .arg1 = c1,
+ .arg2 = l,
});
- struct command *c2 = insert_cmd(cmds, (struct command){
+ struct element *c2 = insert_cmd(cmds, (struct command){
.op = CMD_CIRCLE_CENTER_POINT,
+ .result.type = ETYPE_CIRCLE,
.hidden = true,
- .arg1.as_cmd = p2,
- .arg2.as_cmd = p1,
+ .arg1 = p2,
+ .arg2 = p1,
});
- struct command *c3 = insert_cmd(cmds, (struct command){
+ struct element *c3 = insert_cmd(cmds, (struct command){
.op = CMD_CIRCLE_CENTER_POINT,
+ .result.type = ETYPE_CIRCLE,
.hidden = true,
- .arg1.as_cmd = p1,
- .arg2.as_cmd = p2,
+ .arg1 = p1,
+ .arg2 = p2,
});
- struct command *perp1 = insert_cmd(cmds, (struct command){
+ struct element *perp1 = insert_cmd(cmds, (struct command){
.op = CMD_POINT_CIRCLE_CIRCLE,
+ .result.type = ETYPE_POINT,
.hidden = true,
- .arg1.as_cmd = c2,
- .arg2.as_cmd = c3,
+ .arg1 = c2,
+ .arg2 = c3,
});
- struct command *perp2 = insert_cmd(cmds, (struct command){
+ struct element *perp2 = insert_cmd(cmds, (struct command){
.op = CMD_POINT_CIRCLE_CIRCLE,
+ .result.type = ETYPE_POINT,
.hidden = true,
.root = 1,
- .arg1.as_cmd = c2,
- .arg2.as_cmd = c3,
+ .arg1 = c2,
+ .arg2 = c3,
});
return insert_cmd(cmds, (struct command){
.op = CMD_LINE_POINT_POINT,
- .hidden = true,
- .arg1.as_cmd = perp1,
- .arg2.as_cmd = perp2,
+ .result.type = ETYPE_LINE,
+ .hidden = hide,
+ .arg1 = perp1,
+ .arg2 = perp2,
});
}
-int main(int argc, char *argv[]) {
-
- struct command *root = NULL;
- struct command *next = NULL;
- root = insert_cmd(&next, (struct command){
- .op = CMD_ORIGIN,
- });
-
- struct command *p2;
- {
- struct command *circle = insert_cmd(&next, (struct command){
- .op = CMD_CIRCLE_CENTER_RADIUS,
- .hidden = true,
- .arg1.as_cmd = root,
- .arg2.as_input = 20,
- });
- struct command *line = insert_cmd(&next, (struct command){
- .op = CMD_LINE_POINT_ANGLE,
- .hidden = true,
- .arg1.as_cmd = root,
- .arg2.as_input = M_PI*0.66666,
- });
- p2 = insert_cmd(&next, (struct command){
- .op = CMD_POINT_CIRCLE_LINE,
- .arg1.as_cmd = circle,
- .arg2.as_cmd = line,
- });
- }
-
- struct command *p3;
+void create_rounded_3line(struct drawing *next, struct element *r, struct element *p1, struct element *p2, struct element *p3, struct element **center, struct element **start, struct element **end) {
{
- struct command *c1 = insert_cmd(&next, (struct command){
- .op = CMD_CIRCLE_CENTER_RADIUS,
- .hidden = true,
- .arg1.as_cmd = root,
- .arg2.as_input = 20,
- });
- struct command *c2 = insert_cmd(&next, (struct command){
- .op = CMD_CIRCLE_CENTER_RADIUS,
- .hidden = true,
- .arg1.as_cmd = p2,
- .arg2.as_input = 20,
- });
- p3 = insert_cmd(&next, (struct command){
- .op = CMD_POINT_CIRCLE_CIRCLE,
- .arg1.as_cmd = c1,
- .arg2.as_cmd = c2,
- });
- }
+ struct element *par1;
+ struct element *par2;
+ {
+ struct element *l = insert_cmd(next, (struct command){
+ .op = CMD_LINE_POINT_POINT,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = p1,
+ .arg2 = p2,
+ });
- struct command *round_start;
- struct command *round_end;
- {
- struct command *l1 = insert_cmd(&next, (struct command){
- .op = CMD_LINE_POINT_POINT,
- .hidden = true,
- .arg1.as_cmd = root,
- .arg2.as_cmd = p2,
- });
- struct command *l2 = insert_cmd(&next, (struct command){
- .op = CMD_LINE_POINT_POINT,
- .hidden = true,
- .arg1.as_cmd = p2,
- .arg2.as_cmd = p3,
- });
+ struct element *perp = create_perp(next, l, p2, true);
- struct command *l1_parallel;
- {
- struct command *perp = create_perp(&next, l1, p2);
- struct command *c = insert_cmd(&next, (struct command){
+ struct element *c = insert_cmd(next, (struct command){
.op = CMD_CIRCLE_CENTER_RADIUS,
.hidden = true,
- .arg1.as_cmd = p2,
- .arg2.as_input = 4,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = p2,
+ .arg2 = r,
});
- struct command *d = insert_cmd(&next, (struct command){
+ struct element *p = insert_cmd(next, (struct command){
.op = CMD_POINT_CIRCLE_LINE,
.hidden = true,
- .root = 1,
- .arg1.as_cmd = c,
- .arg2.as_cmd = perp,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = perp,
});
- l1_parallel = create_perp(&next, perp, d);
+ par1 = create_perp(next, perp, p, true);
}
- struct command *l2_parallel;
{
- struct command *perp = create_perp(&next, l2, p2);
- struct command *c = insert_cmd(&next, (struct command){
+ struct element *l = insert_cmd(next, (struct command){
+ .op = CMD_LINE_POINT_POINT,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = p2,
+ .arg2 = p3,
+ });
+
+ struct element *perp = create_perp(next, l, p2, true);
+
+ struct element *c = insert_cmd(next, (struct command){
.op = CMD_CIRCLE_CENTER_RADIUS,
.hidden = true,
- .arg1.as_cmd = p2,
- .arg2.as_input = 4,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = p2,
+ .arg2 = r,
});
- struct command *d = insert_cmd(&next, (struct command){
+ struct element *p = insert_cmd(next, (struct command){
.op = CMD_POINT_CIRCLE_LINE,
.hidden = true,
- .root = 1,
- .arg1.as_cmd = c,
- .arg2.as_cmd = perp,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = perp,
});
- l2_parallel = create_perp(&next, perp, d);
+ par2 = create_perp(next, perp, p, true);
}
- struct command *rounding_center = insert_cmd(&next, (struct command){
+ struct element *pc = insert_cmd(next, (struct command){
.op = CMD_POINT_LINE_LINE,
.hidden = true,
- .arg1.as_cmd = l1_parallel,
- .arg2.as_cmd = l2_parallel,
+ .result.type = ETYPE_POINT,
+ .arg1 = par1,
+ .arg2 = par2,
});
+ *center = pc;
- struct command *rounding_circle = insert_cmd(&next, (struct command){
+ struct element *c = insert_cmd(next, (struct command){
.op = CMD_CIRCLE_CENTER_RADIUS,
.hidden = true,
- .arg1.as_cmd = rounding_center,
- .arg2.as_input = 4,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = pc,
+ .arg2 = r,
});
- round_start = insert_cmd(&next, (struct command){
- .op = CMD_POINT_CIRCLE_LINE,
- .hidden = true,
- .arg1.as_cmd = rounding_circle,
- .arg2.as_cmd = l1,
- });
- round_end = insert_cmd(&next, (struct command){
- .op = CMD_POINT_CIRCLE_LINE,
- .hidden = true,
- .arg1.as_cmd = rounding_circle,
- .arg2.as_cmd = l2,
- });
+ {
+ struct element *l = insert_cmd(next, (struct command){
+ .op = CMD_LINE_POINT_POINT,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = p1,
+ .arg2 = p2,
+ });
+
+ struct element *p = insert_cmd(next, (struct command){
+ .op = CMD_POINT_CIRCLE_LINE,
+ .hidden = true,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = l,
+ });
+ *start = p;
+ }
+
+ {
+ struct element *l = insert_cmd(next, (struct command){
+ .op = CMD_LINE_POINT_POINT,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = p2,
+ .arg2 = p3,
+ });
+
+ struct element *p = insert_cmd(next, (struct command){
+ .op = CMD_POINT_CIRCLE_LINE,
+ .hidden = true,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = l,
+ });
+ *end = p;
+ }
- // insert_cmd(&next, (struct command){
- // .op = CMD_CIRCLE_CENTER_POINT,
- // .arg1.as_cmd = rounding_center,
- // .arg2.as_cmd = p2,
- // });
}
+}
- // {
- // .op = CMD_POINT_CIRCLE_LINE,
- // .root = 1,
- // .arg1.as_cmd = &cmd[7],
- // .arg2.as_cmd = &cmd[2],
- // },
- // {
- // .op = CMD_LINE_POINT_POINT,
- // .arg1.as_cmd = &cmd[3],
- // .arg2.as_cmd = &cmd[6],
- // },
- // {
- // .op = CMD_POINT_CIRCLE_LINE,
- // .hidden = true,
- // .root = 1,
- // .arg1.as_cmd = &cmd[7],
- // .arg2.as_cmd = &cmd[9],
- // },
- // {
- // .op = CMD_CIRCLE_CENTER_POINT,
- // .hidden = true,
- // .arg1.as_cmd = &cmd[8],
- // .arg2.as_cmd = &cmd[3],
- // },
- // {
- // .op = CMD_POINT_CIRCLE_LINE,
- // .hidden = true,
- // .root = 1,
- // .arg1.as_cmd = &cmd[11],
- // .arg2.as_cmd = &cmd[2],
- // },
- // {
- // .op = CMD_CIRCLE_CENTER_POINT,
- // .arg1.as_cmd = &cmd[12],
- // .arg2.as_cmd = &cmd[3],
- // },
- // {
- // .op = CMD_CIRCLE_CENTER_POINT,
- // .arg1.as_cmd = &cmd[3],
- // .arg2.as_cmd = &cmd[12],
- // },
- // {
- // .op = CMD_POINT_CIRCLE_CIRCLE,
- // .arg1.as_cmd = &cmd[13],
- // .arg2.as_cmd = &cmd[14],
- // },
- // {
- // .op = CMD_POINT_CIRCLE_CIRCLE,
- // .root = 1,
- // .arg1.as_cmd = &cmd[13],
- // .arg2.as_cmd = &cmd[14],
- // },
- // {
- // .op = CMD_LINE_POINT_POINT,
- // .root = 1,
- // .arg1.as_cmd = &cmd[15],
- // .arg2.as_cmd = &cmd[16],
- // },
- // };
-
- for(struct command *current = root; current != NULL; current = current->next) {
+void execute_drawing(struct drawing *drawing, double inputs[]) {
+ size_t input_i = 0;
+ for(struct command *current = drawing->root; current != NULL; current = current->next) {
switch(current->op) {
+ case CMD_VALUE_INPUT: {
+ assert(current->result.type == ETYPE_VALUE);
+ current->result.value = inputs[input_i++];
+ }break;
case CMD_ORIGIN: {
- glm_vec2_zero(current->point.pos);
+ assert(current->result.type == ETYPE_POINT);
+ glm_vec2_zero(current->result.point.pos);
}break;
- case CMD_CIRCLE_CENTER_RADIUS: {
- glm_vec2_copy(current->arg1.as_cmd->point.pos, current->circle.center);
- current->circle.radius = current->arg2.as_input;
+ case CMD_LINE_X: {
+ assert(current->result.type == ETYPE_LINE);
+ current->result.line.norm[0] = 0;
+ current->result.line.norm[1] = 1;
+ current->result.line.C = 0;
}break;
- case CMD_LINE_POINT_ANGLE: {
- double theta = current->arg2.as_input;
- current->line.norm[0] = -sin(theta);
- current->line.norm[1] = cos(theta);
- vec2 offset = {-current->arg1.as_cmd->point.pos[0], -current->arg1.as_cmd->point.pos[1]};
- current->line.C = glm_vec2_dot(current->line.norm, offset);
+ case CMD_CIRCLE_CENTER_RADIUS: {
+ assert(current->result.type == ETYPE_CIRCLE);
+ glm_vec2_copy(current->arg1->point.pos, current->result.circle.center);
+ current->result.circle.radius = current->arg2->value;
}break;
case CMD_LINE_POINT_POINT: {
- current->line.norm[0] = current->arg2.as_cmd->point.pos[1] - current->arg1.as_cmd->point.pos[1];
- current->line.norm[1] = current->arg1.as_cmd->point.pos[0] - current->arg2.as_cmd->point.pos[0];
- current->line.C = current->arg1.as_cmd->point.pos[1] * -current->line.norm[1] - current->line.norm[0] * current->arg1.as_cmd->point.pos[0];
+ assert(current->result.type == ETYPE_LINE);
+ current->result.line.norm[0] = current->arg2->point.pos[1] - current->arg1->point.pos[1];
+ current->result.line.norm[1] = current->arg1->point.pos[0] - current->arg2->point.pos[0];
+ current->result.line.C = current->arg1->point.pos[1] * -current->result.line.norm[1] - current->result.line.norm[0] * current->arg1->point.pos[0];
+ }break;
+ case CMD_LINE_POINT_LINE_ANGLE: {
+ assert(current->arg1->type == ETYPE_POINT);
+ assert(current->arg2->type == ETYPE_LINE);
+ assert(current->arg3->type == ETYPE_VALUE);
+ assert(current->result.type == ETYPE_LINE);
+
+ glm_vec2_rotate(current->arg2->line.norm, current->arg3->value, current->result.line.norm);
+
+ vec2 offset = {-current->arg1->point.pos[0], -current->arg1->point.pos[1]};
+ current->result.line.C = glm_vec2_dot(current->result.line.norm, offset);
}break;
case CMD_POINT_CIRCLE_LINE: {
- circle_line_intersect(current->arg1.as_cmd->circle, current->arg2.as_cmd->line, current->root, &current->point);
+ assert(current->result.type == ETYPE_POINT);
+ circle_line_intersect(current->arg1->circle, current->arg2->line, current->root, &current->result.point);
}break;
case CMD_POINT_CIRCLE_CIRCLE: {
+ assert(current->result.type == ETYPE_POINT);
vec2 between_centers;
- glm_vec2_sub(current->arg1.as_cmd->circle.center, current->arg2.as_cmd->circle.center, between_centers);
+ glm_vec2_sub(current->arg1->circle.center, current->arg2->circle.center, between_centers);
glm_vec2_mul(between_centers, (vec2){2, 2}, between_centers);
double a = between_centers[0];
double b = between_centers[1];
- double c = (pow(current->arg2.as_cmd->circle.center[0], 2) - pow(current->arg1.as_cmd->circle.center[0], 2)) + \
- (pow(current->arg2.as_cmd->circle.center[1], 2) - pow(current->arg1.as_cmd->circle.center[1], 2)) - \
- (pow(current->arg2.as_cmd->circle.radius, 2) - pow(current->arg1.as_cmd->circle.radius, 2));
+ double c = (pow(current->arg2->circle.center[0], 2) - pow(current->arg1->circle.center[0], 2)) + \
+ (pow(current->arg2->circle.center[1], 2) - pow(current->arg1->circle.center[1], 2)) - \
+ (pow(current->arg2->circle.radius, 2) - pow(current->arg1->circle.radius, 2));
struct line radical_axis = { {a, b}, c };
- circle_line_intersect(current->arg1.as_cmd->circle, radical_axis, current->root, &current->point);
+ circle_line_intersect(current->arg1->circle, radical_axis, current->root, &current->result.point);
}break;
case CMD_POINT_LINE_LINE: {
- double a1 = current->arg1.as_cmd->line.norm[0];
- double b1 = current->arg1.as_cmd->line.norm[1];
- double c1 = current->arg1.as_cmd->line.C;
+ assert(current->result.type == ETYPE_POINT);
+ double a1 = current->arg1->line.norm[0];
+ double b1 = current->arg1->line.norm[1];
+ double c1 = current->arg1->line.C;
- double a2 = current->arg2.as_cmd->line.norm[0];
- double b2 = current->arg2.as_cmd->line.norm[1];
- double c2 = current->arg2.as_cmd->line.C;
+ double a2 = current->arg2->line.norm[0];
+ double b2 = current->arg2->line.norm[1];
+ double c2 = current->arg2->line.C;
- current->point.pos[0] = -(c1*b2 - c2*b1) / (a1*b2 - a2*b1);
- current->point.pos[1] = -(a1*c2 - a2*c1) / (a1*b2 - a2*b1);
+ current->result.point.pos[0] = -(c1*b2 - c2*b1) / (a1*b2 - a2*b1);
+ current->result.point.pos[1] = -(a1*c2 - a2*c1) / (a1*b2 - a2*b1);
}break;
case CMD_CIRCLE_CENTER_POINT: {
- glm_vec2_copy(current->arg1.as_cmd->point.pos, current->circle.center);
+ assert(current->result.type == ETYPE_CIRCLE);
+ glm_vec2_copy(current->arg1->point.pos, current->result.circle.center);
vec2 imm;
- glm_vec2_sub(current->arg1.as_cmd->point.pos, current->arg2.as_cmd->point.pos, imm);
- current->circle.radius = glm_vec2_norm(imm);
+ glm_vec2_sub(current->arg1->point.pos, current->arg2->point.pos, imm);
+ current->result.circle.radius = glm_vec2_norm(imm);
}break;
}
// printf("%fx + %fy + %f = 0\n", cmd[2].line.norm[0], cmd[2].line.norm[1], cmd[2].line.C);
}
+}
+
+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 = {};
+ line_start = insert_cmd(&drawing, (struct command){
+ .op = CMD_ORIGIN,
+ .hidden = true,
+ .result.type = ETYPE_POINT,
+ });
+
+ struct element *element_spacing = insert_cmd(&drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .result.type = ETYPE_VALUE,
+ });
+
+ struct element *line_corner;
+ {
+ struct element *xaxis = insert_cmd(&drawing, (struct command){
+ .op = CMD_LINE_X,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ });
+
+ struct element *root_angle = insert_cmd(&drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .result.type = ETYPE_VALUE,
+ });
+
+ struct element *l = insert_cmd(&drawing, (struct command){
+ .op = CMD_LINE_POINT_LINE_ANGLE,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = line_start,
+ .arg2 = xaxis,
+ .arg3 = root_angle,
+ });
+
+ struct element *c = insert_cmd(&drawing, (struct command){
+ .op = CMD_CIRCLE_CENTER_RADIUS,
+ .hidden = true,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = line_start,
+ .arg2 = element_spacing,
+ });
+
+ struct element *p = insert_cmd(&drawing, (struct command){
+ .op = CMD_POINT_CIRCLE_LINE,
+ .hidden = true,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = l,
+ });
+ line_corner = p;
+ }
+
+ {
+ struct element *li = insert_cmd(&drawing, (struct command){
+ .op = CMD_LINE_POINT_POINT,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = line_start,
+ .arg2 = line_corner,
+ });
+
+ struct element *bend_angle = insert_cmd(&drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .hidden = true,
+ .result.type = ETYPE_VALUE,
+ });
+
+ struct element *l = insert_cmd(&drawing, (struct command){
+ .op = CMD_LINE_POINT_LINE_ANGLE,
+ .hidden = true,
+ .result.type = ETYPE_LINE,
+ .arg1 = line_corner,
+ .arg2 = li,
+ .arg3 = bend_angle,
+ });
+
+ struct element *c = insert_cmd(&drawing, (struct command){
+ .op = CMD_CIRCLE_CENTER_RADIUS,
+ .hidden = true,
+ .result.type = ETYPE_CIRCLE,
+ .arg1 = line_corner,
+ .arg2 = element_spacing,
+ });
+
+ struct element *p = insert_cmd(&drawing, (struct command){
+ .op = CMD_POINT_CIRCLE_LINE,
+ .hidden = true,
+ .result.type = ETYPE_POINT,
+ .arg1 = c,
+ .arg2 = l,
+ });
+ line_end = p;
+ }
+
+
+ struct element *round_rad = insert_cmd(&drawing, (struct command){
+ .op = CMD_VALUE_INPUT,
+ .hidden = true,
+ .result.type = ETYPE_VALUE,
+ });
+ create_rounded_3line(&drawing, round_rad, line_start, line_corner, line_end, &line_ctr, &line_bend_start, &line_bend_end);
+
+ execute_drawing(&drawing, (double[]){16, M_PI * 0.5, M_PI * 0.1, 1});
+
printf("<svg version=\"1.1\" viewBox=\"-50 -50 100 100\" width=\"1200\" height=\"1200\" xmlns=\"http://www.w3.org/2000/svg\">\n");
- printf("<line x1=\"-1000\" y1=\"0\" x2=\"1000\" y2=\"0\" stroke=\"black\" stroke-width=\".1\" />\n");
- printf("<line y1=\"-1000\" x1=\"0\" y2=\"1000\" x2=\"0\" stroke=\"black\" stroke-width=\".1\" />\n");
- for(struct command *current = root; current != NULL; current = current->next) {
+ // Axis lines
+ printf("<line x1=\"-1000\" y1=\"0\" x2=\"1000\" y2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
+ printf("<line y1=\"-1000\" x1=\"0\" y2=\"1000\" x2=\"0\" stroke=\"black\" stroke-width=\"0.1\" stroke-opacity=\"0.4\" />\n");
+
+ for(struct command *current = drawing.root; current != NULL; current = current->next) {
if(current->hidden) continue;
switch(current->op) {
+ case CMD_VALUE_INPUT:
+ break;
case CMD_ORIGIN:
case CMD_POINT_CIRCLE_LINE:
case CMD_POINT_CIRCLE_CIRCLE:
case CMD_POINT_LINE_LINE:
- plot_point(current->point);
+ assert(current->result.type == ETYPE_POINT);
+ plot_point(current->result.point);
break;
case CMD_CIRCLE_CENTER_RADIUS:
case CMD_CIRCLE_CENTER_POINT:
- plot_circle(current->circle);
+ assert(current->result.type == ETYPE_CIRCLE);
+ plot_circle(current->result.circle);
break;
- case CMD_LINE_POINT_ANGLE:
+ case CMD_LINE_X:
case CMD_LINE_POINT_POINT:
- plot_line(current->line);
+ case CMD_LINE_POINT_LINE_ANGLE:
+ assert(current->result.type == ETYPE_LINE);
+ plot_line(current->result.line);
break;
}
}
- plot_line_between(root->point, round_start->point);
- plot_line_between(round_end->point, p3->point);
- plot_line_between(p3->point, root->point);
-
- plot_arc_between(4, round_start->point, round_end->point);
+ plot_line_between(line_start->point, line_bend_start->point);
+ plot_line_between(line_bend_end->point, line_end->point);
+ plot_arc_between(line_ctr->point, line_bend_start->point, line_bend_end->point);
+ // plot_line_between(detector_right->point, decomposer_left->point);
+ // plot_line_between(decomposer_right->point, solver_left->point);
+ // plot_line_between(solver_right->point, solutions_left->point);
printf("</svg>\n");
}