mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-23 01:01:45 +02:00
ptrude/: path extrusion, work in progress
This commit is contained in:
parent
4ae218c6dc
commit
d4c96f129d
13
ptrude/Makefile
Normal file
13
ptrude/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CFLAGS = -Wall -g
|
||||||
|
LDFLAGS = -lm
|
||||||
|
OBJS = ptrude.o path.o
|
||||||
|
|
||||||
|
.PHONY: clean try
|
||||||
|
|
||||||
|
ptrude: $(OBJS)
|
||||||
|
|
||||||
|
try: ptrude
|
||||||
|
./ptrude <try | tee out
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS)
|
24
ptrude/README
Normal file
24
ptrude/README
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
File format
|
||||||
|
-----------
|
||||||
|
|
||||||
|
#r=radius
|
||||||
|
minimum bend radius. Propagates to all subsequent points.
|
||||||
|
#delta=distance
|
||||||
|
maximum distance of line from curve. Propagates to all
|
||||||
|
subsequent points.
|
||||||
|
#tag=name
|
||||||
|
name point or shape. Gets passed through 2D->2D transform.
|
||||||
|
Affects only the next point.
|
||||||
|
x-coord y-coord
|
||||||
|
line endpoint
|
||||||
|
|
||||||
|
#r=, #delta=, and #tag= modify the next point, e.g.,
|
||||||
|
|
||||||
|
0 0
|
||||||
|
#r=2
|
||||||
|
#tag=foo
|
||||||
|
1 0
|
||||||
|
1 1
|
||||||
|
|
||||||
|
would set the bend radius at the corner (and the final point) to 2 mm
|
||||||
|
and the tag of the corner point to "foo".
|
68
ptrude/arc.fig
Normal file
68
ptrude/arc.fig
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#FIG 3.2 Produced by xfig version 3.2.5b
|
||||||
|
Landscape
|
||||||
|
Center
|
||||||
|
Metric
|
||||||
|
A4
|
||||||
|
100.00
|
||||||
|
Single
|
||||||
|
-2
|
||||||
|
1200 2
|
||||||
|
5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 3822.761 2922.761 3825 7425 7193 5908 8325 2925
|
||||||
|
5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 3821.168 2921.168 3825 7290 4883 7159 8190 2925
|
||||||
|
5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 3822.431 2923.366 3825 7560 4969 7416 8459 2948
|
||||||
|
5 1 0 1 0 0 50 -1 -1 4.000 0 1 0 0 8324.358 7425.641 8775 7425 8706 7186 8325 6975
|
||||||
|
5 1 0 1 0 0 50 -1 -1 4.000 0 0 0 0 3823.445 2923.445 5400 2925 5284 3517 3825 4500
|
||||||
|
1 3 0 0 0 0 50 -1 20 0.000 1 0.0000 4725 7065 45 45 4725 7065 4770 7065
|
||||||
|
1 3 0 0 0 0 50 -1 20 0.000 1 0.0000 7065 5625 45 45 7065 5625 7110 5625
|
||||||
|
1 3 0 0 0 0 50 -1 20 0.000 1 0.0000 4950 7020 45 45 4950 7020 4995 7020
|
||||||
|
1 3 0 0 0 0 50 -1 20 0.000 1 0.0000 7245 5400 45 45 7245 5400 7290 5400
|
||||||
|
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
900 7425 3825 7425
|
||||||
|
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
8325 2925 8325 1125
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
|
||||||
|
0 0 1.00 120.00 120.00
|
||||||
|
0 0 1.00 120.00 120.00
|
||||||
|
3870 2790 8235 2790
|
||||||
|
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
|
||||||
|
3825 7425 6390 6795 8235 4320
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3825 2925 8235 4320
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3825 2925 7290 5580
|
||||||
|
2 1 1 2 0 0 50 -1 -1 6.000 0 0 -1 0 0 2
|
||||||
|
8235 4320 8280 3690
|
||||||
|
2 1 0 1 0 0 50 -1 -1 4.000 0 0 -1 0 0 2
|
||||||
|
8325 2925 8325 7650
|
||||||
|
2 1 0 1 0 0 50 -1 -1 4.000 0 0 -1 0 0 2
|
||||||
|
3825 7425 9000 7425
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
9000 2925 3330 2925
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3825 2925 6390 6795
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3825 2475 3825 8100
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3825 2925 4860 7155
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 105 6075 2655 r\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 3690 7380 d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 3690 7695 d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 105 3645 5490 r\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 375 4365 6390 r-d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 450 5580 6300 r+d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 375 6210 5175 r-d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 450 6840 4230 r+d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 165 4545 7695 u\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 135 5625 7425 v\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 135 7290 6390 v\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 135 8055 5220 v\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 150 855 8640 3690 ...+v+u\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 195 240 8505 7380 2t\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 270 2085 9405 7200 (r-d)^2+u^2=r^2\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 270 2610 9405 7650 (r-d)^2+v^2=(r+d)^2\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 270 1530 9405 8100 2t = 2p+n*q\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 210 915 4410 3105 ...+q+p\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 4950 3555 q\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 4635 3870 q\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 4320 4050 q\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 3960 4185 p\001
|
68
ptrude/corner.fig
Normal file
68
ptrude/corner.fig
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#FIG 3.2 Produced by xfig version 3.2.5b
|
||||||
|
Landscape
|
||||||
|
Center
|
||||||
|
Metric
|
||||||
|
A4
|
||||||
|
100.00
|
||||||
|
Single
|
||||||
|
-2
|
||||||
|
1200 2
|
||||||
|
5 1 0 2 0 7 48 -1 -1 0.000 0 1 0 0 4494.036 1337.375 4500 9000 6203 8807 9909 6759
|
||||||
|
5 1 0 1 0 7 48 -1 -1 0.000 0 1 0 0 4499.660 1353.986 5220 3105 5552 2928 5818 2713
|
||||||
|
5 1 0 1 0 7 52 -1 -1 0.000 0 1 0 0 7651.482 8999.573 9000 9000 8926 8559 8604 8045
|
||||||
|
5 1 0 1 0 7 52 -1 -1 0.000 0 1 0 0 3374.893 7199.935 3915 7200 3838 6922 2993 6818
|
||||||
|
5 1 0 2 0 7 48 -1 -1 0.000 0 1 0 0 1798.655 6524.275 1800 7200 2162 7094 2277 6047
|
||||||
|
1 3 0 0 0 7 46 -1 0 0.000 1 0.0000 2250 6255 45 45 2250 6255 2295 6255
|
||||||
|
1 3 0 0 0 7 46 -1 0 0.000 1 0.0000 1935 7065 45 45 1935 7065 1980 7065
|
||||||
|
1 3 0 0 0 7 46 -1 0 0.000 1 0.0000 4680 8820 45 45 4680 8820 4725 8820
|
||||||
|
1 3 0 0 0 7 46 -1 0 0.000 1 0.0000 9630 6750 45 45 9630 6750 9675 6750
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
9900 6750 4050 900
|
||||||
|
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
|
||||||
|
1575 9000 7650 9000 13050 3600
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
7650 9000 4185 585
|
||||||
|
2 1 0 1 0 7 52 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
7650 9000 11025 9000
|
||||||
|
2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
|
||||||
|
675 7200 3375 7200 1125 4950
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
1800 7200 1800 5850
|
||||||
|
2 1 0 1 0 7 52 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3375 7200 4050 7200
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
2250 6075 1350 6975
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
3375 7200 1620 6435
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
|
||||||
|
0 0 1.00 120.00 120.00
|
||||||
|
0 0 1.00 120.00 120.00
|
||||||
|
4500 9135 7650 9135
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
1800 7335 3375 7335
|
||||||
|
2 1 0 0 0 7 46 -1 0 0.000 0 0 -1 1 1 2
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
4500 1350 4500 9000
|
||||||
|
2 1 0 0 0 7 46 -1 0 0.000 0 0 -1 1 1 2
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
0 0 1.00 90.00 90.00
|
||||||
|
7425 8415 7650 9000
|
||||||
|
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
|
||||||
|
4500 9000 4500 675
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 210 180 7650 8685 d\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 150 105 4320 5580 r\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 150 105 6030 5760 r\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 195 90 5130 2475 t\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 270 1830 7425 1125 cos t = r/(r+d)\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 165 5985 9405 s\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 210 1305 7425 1575 s = r*tan t\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 195 240 8325 8775 2t\001
|
||||||
|
4 0 0 48 -1 18 18 0.0000 4 195 240 3330 7020 2t\001
|
||||||
|
4 1 0 48 -1 18 18 0.0000 4 195 90 2115 6525 t\001
|
||||||
|
4 1 0 48 -1 18 18 0.0000 4 150 105 1665 7020 r\001
|
||||||
|
4 1 0 48 -1 18 18 0.0000 4 210 180 2520 7110 d\001
|
||||||
|
4 1 0 50 -1 18 18 0.0000 4 150 165 2610 7605 s\001
|
||||||
|
4 0 0 50 -1 18 18 0.0000 4 270 2310 7425 2025 r^2+s^2 = (r+d)^2\001
|
344
ptrude/path.c
Normal file
344
ptrude/path.c
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define alloc_type(t) ((t *) malloc(sizeof(t)))
|
||||||
|
#define stralloc(s) strdup(s)
|
||||||
|
|
||||||
|
|
||||||
|
static double deg(double rad)
|
||||||
|
{
|
||||||
|
return rad/M_PI*180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct path *alloc_path(void)
|
||||||
|
{
|
||||||
|
struct path *path;
|
||||||
|
|
||||||
|
path = alloc_type(struct path);
|
||||||
|
path->vertices = NULL;
|
||||||
|
path->last = &path->vertices;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct vertex *alloc_vertex(void)
|
||||||
|
{
|
||||||
|
struct vertex *v;
|
||||||
|
|
||||||
|
v = alloc_type(struct vertex);
|
||||||
|
v->r = 0;
|
||||||
|
v->d = 0;
|
||||||
|
v->tag = NULL;
|
||||||
|
v->next = NULL;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void free_vertex(struct vertex *v)
|
||||||
|
{
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void free_path(struct path *path)
|
||||||
|
{
|
||||||
|
struct vertex *v, *next;
|
||||||
|
|
||||||
|
for (v = path->vertices; v; v = next) {
|
||||||
|
next = v->next;
|
||||||
|
free_vertex(v);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct vertex *clone_vertex(const struct vertex *v)
|
||||||
|
{
|
||||||
|
struct vertex *new;
|
||||||
|
|
||||||
|
new = alloc_type(struct vertex);
|
||||||
|
*new = *v;
|
||||||
|
new->next = NULL;
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void append_vertex(struct path *path, struct vertex *v)
|
||||||
|
{
|
||||||
|
*path->last = v;
|
||||||
|
path->last = &v->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct vertex *add_vertex(struct path *path, double x, double y,
|
||||||
|
double r, double d, const char *tag)
|
||||||
|
{
|
||||||
|
struct vertex *v;
|
||||||
|
|
||||||
|
v = alloc_vertex();
|
||||||
|
v->x = x;
|
||||||
|
v->y = y;
|
||||||
|
v->r = r;
|
||||||
|
v->d = d;
|
||||||
|
v->tag = tag;
|
||||||
|
append_vertex(path, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct vertex *corner(struct path *path, const struct vertex *a,
|
||||||
|
const struct vertex *b, const struct vertex *c, double r, double d)
|
||||||
|
{
|
||||||
|
double ax = b->x-a->x;
|
||||||
|
double ay = b->y-a->y;
|
||||||
|
double bx = c->x-b->x;
|
||||||
|
double by = c->y-b->y;
|
||||||
|
double aa = hypot(ax, ay);
|
||||||
|
double bb = hypot(bx, by);
|
||||||
|
double dp = ax*bx+ay*by; /* a * b = a*b*cos 2t */
|
||||||
|
double cp = ax*by-ay*bx; /* |a x b| = a*b*sin 2t */
|
||||||
|
double dd; /* "d" of the given vectors */
|
||||||
|
double tt, s;
|
||||||
|
double t2, p, q, ang;
|
||||||
|
double u, v;
|
||||||
|
double f, x, y;
|
||||||
|
int n, i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* http://en.wikipedia.org/wiki/Dot_product
|
||||||
|
* dp = a*b*cos 2t
|
||||||
|
*
|
||||||
|
* http://en.wikipedia.org/wiki/Cross_product
|
||||||
|
* cp = a*b*sin 2t
|
||||||
|
*
|
||||||
|
* http://en.wikipedia.org/wiki/Tangent_half-angle_formula
|
||||||
|
* tan t = sin 2t/(1+cos 2t)
|
||||||
|
*/
|
||||||
|
tt = cp/(aa*bb+dp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From s = r*tan t
|
||||||
|
*/
|
||||||
|
s = fabs(r*tt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From r^2+s^2 = (r+d)^2
|
||||||
|
*/
|
||||||
|
dd = hypot(r, s)-r;
|
||||||
|
|
||||||
|
fprintf(stderr, "a = (%g, %g)-(%g, %g) = (%g, %g); |a| = %g\n",
|
||||||
|
b->x, b->y, a->x, a->y, ax, ay, aa);
|
||||||
|
fprintf(stderr, "b = (%g, %g)-(%g, %g) = (%g, %g); |b| = %g\n",
|
||||||
|
c->x, c->y, b->x, b->y, bx, by, bb);
|
||||||
|
fprintf(stderr, "sin 2t = %g, cos 2t = %g, tan t = %g\n",
|
||||||
|
cp/aa/bb, dp/aa/bb, tt);
|
||||||
|
fprintf(stderr, "r = %g, d = %g, s = %g, dd = %g\n", r, d, s, dd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only know how to make a rounded corner if two vectors are
|
||||||
|
* involved. They therefore have to be long enough to accommodate the
|
||||||
|
* entire arc, from beginning to end. Furthermore, we split the
|
||||||
|
* available length in half, one for the inbound arc, the other for the
|
||||||
|
* outbound arc.
|
||||||
|
*/
|
||||||
|
if (aa/2 < s) {
|
||||||
|
fprintf(stderr, "first vector is too short (%g/2 < %g)\n",
|
||||||
|
aa, s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (bb/2 < s) {
|
||||||
|
fprintf(stderr, "second vector is too short (%g/2 < %g)\n",
|
||||||
|
bb, s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the corner is already smooth enough, we just keep what we have.
|
||||||
|
*/
|
||||||
|
if (dd <= d) {
|
||||||
|
append_vertex(path, clone_vertex(b));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 1: determine the total angle (2*t) */
|
||||||
|
|
||||||
|
t2 = acos(dp/aa/bb);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 2: determine the maximum angle of the first and last segment.
|
||||||
|
*
|
||||||
|
* We use
|
||||||
|
* r*cos p = r-d
|
||||||
|
* cos p = 1-d/r
|
||||||
|
*/
|
||||||
|
|
||||||
|
p = acos(1-d/r);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 3: determine the maximum angle of intermediate segments (if
|
||||||
|
* there are any).
|
||||||
|
*
|
||||||
|
* We use
|
||||||
|
* (r+d)*cos q = r-d
|
||||||
|
* cos q = r-q/(r+d)
|
||||||
|
*/
|
||||||
|
|
||||||
|
q = acos((r-d)/(r+d));
|
||||||
|
|
||||||
|
fprintf(stderr, "t2 = %g, p(max) = %g, q(max) = %g\n",
|
||||||
|
deg(t2), deg(p), deg(q));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 4: emit the starting point of the arc
|
||||||
|
*/
|
||||||
|
|
||||||
|
f = s/aa;
|
||||||
|
x = b->x-f*ax;
|
||||||
|
y = b->y-f*ay;
|
||||||
|
add_vertex(path, x, y, b->r, b->d, b->tag);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 5: determine if we need intermediate points. If yes, how many,
|
||||||
|
* and then proceed to add them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (t2 > 2*p) {
|
||||||
|
n = (int) ceil((t2-2*(p+q))/(2*q));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @@@ We should evenly distribute the slack, but that seems
|
||||||
|
* difficult. For now, we just center the polygon.
|
||||||
|
*/
|
||||||
|
q = (t2/2-p)/(n+1);
|
||||||
|
|
||||||
|
double dir = copysign(1, cp);
|
||||||
|
#if 0
|
||||||
|
if (cp < 0) {
|
||||||
|
// t2 = -t2;
|
||||||
|
q = -q;
|
||||||
|
p = -p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (n)
|
||||||
|
ang = p+q;
|
||||||
|
else
|
||||||
|
ang = t2/2;
|
||||||
|
u = tan(p)*(r-d);
|
||||||
|
v = tan(q)*(r-d);
|
||||||
|
f = (u+v)/aa;
|
||||||
|
for (i = 0; i <= n; i++) {
|
||||||
|
x += f*ax*cos(ang-q)-dir*f*ay*sin(ang-q);
|
||||||
|
y += dir*f*ax*sin(ang-q)+f*ay*cos(ang-q);
|
||||||
|
fprintf(stderr, " %d/%d: %g %g @ %g\n", i, n,
|
||||||
|
x, y, deg(ang));
|
||||||
|
add_vertex(path, x, y, 0, 0, NULL);
|
||||||
|
ang += 2*q;
|
||||||
|
f = (2*v)/aa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Step 6: emit the finishing point of the arc
|
||||||
|
*/
|
||||||
|
|
||||||
|
f = s/bb;
|
||||||
|
return add_vertex(path, b->x+f*bx, b->y+f*by, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct path *round_path(const struct path *path, double r, double d)
|
||||||
|
{
|
||||||
|
struct path *new;
|
||||||
|
const struct vertex *prev, *v;
|
||||||
|
|
||||||
|
new = alloc_path();
|
||||||
|
prev = path->vertices;
|
||||||
|
if (!prev)
|
||||||
|
return new;
|
||||||
|
append_vertex(new, clone_vertex(prev));
|
||||||
|
if (!prev->next)
|
||||||
|
return new;
|
||||||
|
|
||||||
|
if (prev->r)
|
||||||
|
r = prev->r;
|
||||||
|
if (prev->d)
|
||||||
|
d = prev->d;
|
||||||
|
|
||||||
|
for (v = prev->next; v->next; v = v->next) {
|
||||||
|
if (v->r)
|
||||||
|
r = v->r;
|
||||||
|
if (v->d)
|
||||||
|
d = v->d;
|
||||||
|
prev = corner(new, prev, v, v->next, r, d);
|
||||||
|
}
|
||||||
|
append_vertex(new, clone_vertex(v));
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct path *load_path(FILE *file)
|
||||||
|
{
|
||||||
|
struct path *path;
|
||||||
|
char buf[1100]; /* plenty :) */
|
||||||
|
char buf2[sizeof(buf)];
|
||||||
|
char *s;
|
||||||
|
float x, y, tmp;
|
||||||
|
float r = 0, d = 0;
|
||||||
|
const char *tag = NULL;
|
||||||
|
|
||||||
|
path = alloc_path();
|
||||||
|
while (fgets(buf, sizeof(buf),file)) {
|
||||||
|
s = strchr(buf, '\n');
|
||||||
|
if (s)
|
||||||
|
*s = 0;
|
||||||
|
if (sscanf(buf, "#r=%f", &tmp) == 1) {
|
||||||
|
r = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sscanf(buf, "#delta=%f", &tmp) == 1) {
|
||||||
|
d = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sscanf(buf, "#tag=%s", buf2) == 1) {
|
||||||
|
tag = stralloc(buf2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*buf == '#')
|
||||||
|
continue;
|
||||||
|
if (sscanf(buf, "%f %f", &x, &y) != 2) {
|
||||||
|
fprintf(stderr, "can't parse \"%s\"\n", buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_vertex(path, x, y, r, d, tag);
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
d = 0;
|
||||||
|
tag = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void save_path(FILE *file, const struct path *path)
|
||||||
|
{
|
||||||
|
const struct vertex *v;
|
||||||
|
|
||||||
|
for (v = path->vertices; v; v = v->next) {
|
||||||
|
if (v->r)
|
||||||
|
fprintf(file, "#r=%f\n", v->r);
|
||||||
|
if (v->d)
|
||||||
|
fprintf(file, "#delta=%f\n", v->d);
|
||||||
|
if (v->tag)
|
||||||
|
fprintf(file, "#delta=%f\n", v->d);
|
||||||
|
fprintf(file, "%f %f\n", v->x, v->y);
|
||||||
|
}
|
||||||
|
}
|
28
ptrude/path.h
Normal file
28
ptrude/path.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef PATH_H
|
||||||
|
#define PATH_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct vertex {
|
||||||
|
double x, y;
|
||||||
|
double r; /* minimum bend radius; 0 = use previous value */
|
||||||
|
double d; /* max. distance of corner from ideal arc; 0 = prev */
|
||||||
|
const char *tag;
|
||||||
|
struct vertex *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct path {
|
||||||
|
struct vertex *vertices;
|
||||||
|
struct vertex **last;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void free_path(struct path *path);
|
||||||
|
|
||||||
|
struct path *round_path(const struct path *path, double r, double d);
|
||||||
|
|
||||||
|
struct path *load_path(FILE *file);
|
||||||
|
void save_path(FILE *file, const struct path *path);
|
||||||
|
|
||||||
|
#endif /* !PATH_H */
|
15
ptrude/ptrude.c
Normal file
15
ptrude/ptrude.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const struct path *path;
|
||||||
|
|
||||||
|
path = load_path(stdin);
|
||||||
|
path = round_path(path, 1, 0.1);
|
||||||
|
save_path(stdout, path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
14
ptrude/try
Normal file
14
ptrude/try
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
0 0
|
||||||
|
#r=10
|
||||||
|
#delta=0.01
|
||||||
|
100 0
|
||||||
|
100 100
|
||||||
|
200 100
|
||||||
|
100 200
|
||||||
|
0 200
|
||||||
|
100 100
|
||||||
|
0 100
|
||||||
|
0 50
|
||||||
|
100 50
|
||||||
|
150 0
|
||||||
|
100 0
|
Loading…
Reference in New Issue
Block a user