mirror of
git://projects.qi-hardware.com/cae-tools.git
synced 2024-12-23 12:26:28 +02:00
124 lines
2.7 KiB
C
124 lines
2.7 KiB
C
|
/*
|
||
|
* extrude.c - Perform the extrusion
|
||
|
*
|
||
|
* Written 2011 by Werner Almesberger
|
||
|
* Copyright 2011 by Werner Almesberger
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Known bugs:
|
||
|
*
|
||
|
* - negative x coordinates in shape produce overlapping faces
|
||
|
* - the rounding is only accurate for x = 0. For x > 0, we need to add
|
||
|
* more points. Tricky.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "path.h"
|
||
|
#include "extrude.h"
|
||
|
|
||
|
|
||
|
#define alloc_tn(t, n) ((t *) malloc(sizeof(t)*(n)))
|
||
|
|
||
|
|
||
|
static void slice(double x, double y, double nx, double ny,
|
||
|
const struct path *shape, struct point *p)
|
||
|
{
|
||
|
const struct vertex *v;
|
||
|
|
||
|
for (v = shape->vertices; v; v = v->next) {
|
||
|
p->x = x+nx*v->x;
|
||
|
p->y = y+ny*v->x;
|
||
|
p->z = v->y;
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void mesh(const struct point *a, const struct point *b, int n,
|
||
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
||
|
void *data)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i != n-1; i++) {
|
||
|
face(data, a[i], b[i], a[i+1]);
|
||
|
face(data, a[i+1], b[i], b[i+1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void extrude(const struct path *path, const struct path *shape,
|
||
|
void (*face)(void *data, struct point a, struct point b, struct point c),
|
||
|
void *data)
|
||
|
{
|
||
|
const struct vertex *v; /* current vertex (for iteration) */
|
||
|
const struct vertex *a, *b, *c; /* previous, current, next vertex */
|
||
|
struct point *prev, *this; /* previous and current slice */
|
||
|
double nx, ny; /* 2D normals */
|
||
|
double f; /* factor for normalization */
|
||
|
double tx, ty; /* temporary 2D normals */
|
||
|
int n = 0; /* number of vertices in shape */
|
||
|
|
||
|
if (!path->vertices || !path->vertices->next || !shape->vertices)
|
||
|
return;
|
||
|
|
||
|
for (v = shape->vertices; v; v = v->next)
|
||
|
n++;
|
||
|
|
||
|
prev = alloc_tn(struct point, n);
|
||
|
this = alloc_tn(struct point, n);
|
||
|
|
||
|
a = path->vertices;
|
||
|
b = a->next;
|
||
|
nx = b->y-a->y;
|
||
|
ny = a->x-b->x;
|
||
|
f = hypot(nx, ny);
|
||
|
slice(a->x, a->y, nx/f, ny/f, shape, prev);
|
||
|
|
||
|
for (v = path->vertices->next; v->next; v = v->next) {
|
||
|
b = v;
|
||
|
c = v->next;
|
||
|
|
||
|
tx = b->y-a->y;
|
||
|
ty = a->x-b->x;
|
||
|
f = hypot(tx, ty);
|
||
|
nx = tx/f;
|
||
|
ny = ty/f;
|
||
|
|
||
|
tx = c->y-b->y;
|
||
|
ty = b->x-c->x;
|
||
|
f = hypot(tx, ty);
|
||
|
nx += tx/f;
|
||
|
ny += ty/f;
|
||
|
|
||
|
slice(b->x, b->y, nx/2, ny/2, shape, this);
|
||
|
mesh(prev, this, n, face, data);
|
||
|
|
||
|
memcpy(prev, this, sizeof(*prev)*n);
|
||
|
|
||
|
a = v;
|
||
|
}
|
||
|
|
||
|
nx = v->y-a->y;
|
||
|
ny = a->x-v->x;
|
||
|
f = hypot(nx, ny);
|
||
|
|
||
|
slice(v->x, v->y, nx/f, ny/f, shape, this);
|
||
|
mesh(prev, this, n, face, data);
|
||
|
|
||
|
/* @@@ To do: close shape and close top and bottom */
|
||
|
|
||
|
free(prev);
|
||
|
free(this);
|
||
|
}
|