summaryrefslogtreecommitdiff
path: root/src/intcgm/ellipse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/intcgm/ellipse.c')
-rw-r--r--src/intcgm/ellipse.c143
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);
+}