Root/ptrude/extrude.c

1/*
2 * extrude.c - Perform the extrusion
3 *
4 * Written 2011 by Werner Almesberger
5 * Copyright 2011 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13/*
14 * Known bugs:
15 *
16 * - negative x coordinates in shape produce overlapping faces
17 */
18
19
20#include <stdlib.h>
21#include <math.h>
22#include <assert.h>
23
24#include "ptrude.h"
25#include "path.h"
26#include "extrude.h"
27
28
29static void cvt_3d(struct point *p, const struct vertex *v, double z)
30{
31    p->x = v->x;
32    p->y = v->y;
33    p->z = z;
34}
35
36
37static void size(const struct path *p)
38{
39    const struct vertex *v, *next;
40    double s = 0, sl = 0;
41    int n = 0;
42
43    if (!debug)
44        return;
45    for (v = p->vertices; v; v = next) {
46        next = v->next;
47        if (next)
48            s += hypot(v->x-next->x, v->y-next->y);
49        sl += v->len;
50        n++;
51    }
52    fprintf(stderr, "%d virt %g real %g\n", n, sl, s);
53    
54}
55
56
57static void mesh(const struct path *pa, double za,
58    const struct path *pb, double zb,
59    void (*face)(void *data, struct point a, struct point b, struct point c),
60    void *data)
61{
62    const struct vertex *a = pa->vertices;
63    const struct vertex *b = pb->vertices;
64    double sa = 0, sb = 0; /* total distance traveled on path */
65    double da, db;
66    struct point a3, b3, n;
67
68    cvt_3d(&a3, a, za);
69    cvt_3d(&b3, b, zb);
70
71    while (a->next || b->next) {
72        da = fabs(sa+a->len-sb);
73        db = fabs(sb+b->len-sa);
74        if ((a->next && da < db) || !b->next) {
75            cvt_3d(&n, a->next, za);
76            face(data, a3, n, b3);
77            a3 = n;
78            sa += a->len;
79            a = a->next;
80        } else {
81            cvt_3d(&n, b->next, zb);
82            face(data, b3, a3, n);
83            b3 = n;
84            sb += b->len;
85            b = b->next;
86        }
87    }
88}
89
90
91void extrude(const struct path *path, const struct path *shape,
92    double r, double d,
93    void (*face)(void *data, struct point a, struct point b, struct point c),
94    void *data)
95{
96    const struct vertex *v, *next; /* current and next vertex */
97    struct path *prev, *curr; /* previous and current path */
98    struct path *tmp;
99
100    if (!path->vertices || !path->vertices->next)
101        return;
102
103    v = shape->vertices;
104    if (!v || !v->next)
105        return;
106
107    tmp = stretch_path(path, v->x, r);
108    size(tmp);
109    prev = round_path(tmp, r, d);
110    free_path(tmp);
111    size(prev);
112
113    while (v->next) {
114        next = v->next;
115        tmp = stretch_path(path, next->x, r);
116        size(tmp);
117        curr = round_path(tmp, r, d);
118        size(curr);
119        free_path(tmp);
120
121        mesh(prev, v->y, curr, next->y, face, data);
122
123        free_path(prev);
124        prev = curr;
125        v = next;
126    }
127
128    free_path(prev);
129}
130

Archive Download this file

Branches:
master



interactive