diff options
Diffstat (limited to 'src/intcgm/ellipse.c')
-rw-r--r-- | src/intcgm/ellipse.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/intcgm/ellipse.c b/src/intcgm/ellipse.c new file mode 100644 index 0000000..8d6889c --- /dev/null +++ b/src/intcgm/ellipse.c @@ -0,0 +1,143 @@ +#include <stdio.h> +#include <math.h> + +#include <cd.h> + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm6.h" +#include "ellipse.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#define ANGMIN 0.00001 + +/* Adjust the circle parametrization for the elipsis parametrization */ +double cgm_AdjArc ( double arc, double w, double h ) +{ + double value; + + if ((fabs(w*sin(arc))<1e-99) && (fabs(h*cos(arc))<1e-99)) + value = 0.0; + else + value = atan2(w*sin(arc), h*cos(arc)); + + if ( arc > PI ) value += 2*PI; + if ( arc < -PI ) value -= 2*PI; + + return value; +} + + +/* Desenha um arco de Elipse */ + +void cgm_ElpArc ( double xc, double yc, double w, double h, double r, double a1, + double a2, int n, int tipo ) + +{ + + /* Onde: + + (xc,yc) Centro + (w,h) Largura e altura (diametro na direcao dos eixos principais) + r Inclinacao dos eixos principais com relacao x e y + a1,a2 Angulos incial e final do arco [-360,+360] + Note-se que o sentido e' dado pela diferenca a2-a1, + ou seja, 30 a 330 e' trigonometrico + 30 a -30 e' horario + n Numero de segmentos da poligonal equivalente + (64 parece ser um bom numero) + tipo 0=aberto 1=fechado(torta) 2=fechado(corda) */ + + double da, c, s, sx, sy, ang, xant, yant; + double px, py, tx, ty, txant, tyant, dx, dy; + int i, inicio; + +/* Reduz de diametro a raio */ + + w = w/2; + h = h/2; + +/* Transforma graus em radianos e ajusta a os angulos da parametrizacao */ + + a1 = cgm_AdjArc(a1,w,h); + + a2 = cgm_AdjArc(a2,w,h); + + if ( a2>a1 ) + ang = a2 - a1; + else + ang = 2*PI - ( a1 - a2 ); + +/* Gera os pontos do arco centrado na origem com os eixos em x e y */ + + da = ang/n; + c = cos(da); + s = sin(da); + sx = -w*s/h; + sy = h*s/w; + + if ( tipo==1 || tipo==2 ) + { + long int cor; + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + cdCanvasBegin(intcgm_canvas, cgm_setintstyle(intcgm_fill_att.int_style) ); + } + else + { + long int cor; + int size = (int)floor(intcgm_line_att.width+.5); + cdCanvasLineStyle (intcgm_canvas, intcgm_line_att.type ); + cdCanvasLineWidth (intcgm_canvas, size>0? size: 1 ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + } + + dx = (fabs(r)>ANGMIN) ? sin(r) : 0; + dy = (fabs(r)>ANGMIN) ? cos(r) : 1; + + xant = w*cos(a1); + yant = h*sin(a1); + + txant = xc+dy*xant-dx*yant; /* Inclina (se for o caso) e translada */ + tyant = yc+dx*xant+dy*yant; /* Inclina (se for o caso) e translada */ + + if ( tipo==1 ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) ); + inicio = 2; + } + else if ( tipo==2 ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) ); + inicio = 1; + } + + for ( i=inicio; i<=(n+inicio-1); i++ ) + { + px = c*xant+sx*yant; + py = sy*xant+c*yant; + + tx = xc+dy*px-dx*py; /* Inclina (se for o caso) e translada */ + ty = yc+dx*px+dy*py; /* Inclina (se for o caso) e translada */ + + if ( tipo==0 ) + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant), cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) ); + else + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) ); + + xant = px; + yant = py; + txant = tx; + tyant = ty; + } + +/* Desenha */ + + if ( tipo==1 || tipo==2 ) cdCanvasEnd(intcgm_canvas); +} |