47 #define BEZIERSUBDIVISION 10
54 static int Saw_skycolor;
60 static double EdgeLen;
61 static double HeadHt, TailHt;
62 static double Fstz, Sndz;
68 static char *gdirname(
char *pathname)
73 for (last = pathname; *last; last++);
75 while (last > pathname && *--last ==
'/');
77 for (; last > pathname && *last !=
'/'; last--);
78 if (last == pathname) {
83 else if (pathname[1] ==
'/')
87 for (; *last ==
'/' && last > pathname; last--);
89 if (last == pathname && *pathname ==
'/' && pathname[1] ==
'/')
98 static char *nodefilename(
const char *filename,
node_t * n,
char *buf)
101 static char disposable[1024];
105 dir = gdirname(strcpy(disposable, filename));
109 sprintf(buf,
"%s/node%d.png", dir,
AGSEQ(n));
113 static FILE *nodefile(
const char *filename,
node_t * n)
118 rv = fopen(nodefilename(filename, n, buf),
"wb");
139 static int color_index(gdImagePtr im,
gvcolor_t color)
144 alpha = (255 - color.
u.
rgba[3]) * gdAlphaMax / 255;
146 if(alpha == gdAlphaMax)
147 return (gdImageGetTransparent(im));
149 return (gdImageColorResolveAlpha(im,
156 static int set_penstyle(
GVJ_t * job, gdImagePtr im, gdImagePtr brush)
159 int i, pen, pencolor, transparent, width, dashstyle[40];
161 pen = pencolor = color_index(im, obj->
pencolor);
162 transparent = gdImageGetTransparent(im);
164 for (i = 0; i < 20; i++)
165 dashstyle[i] = pencolor;
167 dashstyle[i] = transparent;
168 gdImageSetStyle(im, dashstyle, 20);
171 for (i = 0; i < 2; i++)
172 dashstyle[i] = pencolor;
174 dashstyle[i] = transparent;
175 gdImageSetStyle(im, dashstyle, 24);
181 gdImageSetThickness(im, width);
184 brush = gdImageCreate(width, width);
185 gdImagePaletteCopy(brush, im);
186 gdImageFilledRectangle(brush, 0, 0, width - 1, width - 1, pencolor);
187 gdImageSetBrush(im, brush);
189 pen = gdStyledBrushed;
198 static void vrml_begin_page(
GVJ_t *job)
201 gvputs(job,
"#VRML V2.0 utf8\n");
203 Saw_skycolor =
FALSE;
205 gvputs(job,
"Group { children [\n");
206 gvputs(job,
" Transform {\n");
207 gvprintf(job,
" scale %.3f %.3f %.3f\n", .0278, .0278, .0278);
208 gvputs(job,
" children [\n");
211 static void vrml_end_page(
GVJ_t *job)
220 z = (0.6667*d)/tan(
M_PI/8.0) + MinZ;
223 gvputs(job,
" Background { skyColor 1 1 1 }\n");
225 gvprintf(job,
" Viewpoint {position %.3f %.3f %.3f}\n",
226 Scale * (bb.
UR.
x + bb.
LL.
x) / 72.,
227 Scale * (bb.
UR.
y + bb.
LL.
y) / 72.,
228 Scale * 2 * z / 72.);
232 static void vrml_begin_node(
GVJ_t *job)
246 width = (
ND_lw(n) +
ND_rw(n)) * Scale + 2 * NODE_PAD;
247 height = (
ND_ht(n) ) * Scale + 2 * NODE_PAD;
248 im = gdImageCreate(width, height);
251 transparent = gdImageColorResolveAlpha(im,
252 gdRedMax - 1, gdGreenMax,
253 gdBlueMax, gdAlphaTransparent);
254 gdImageColorTransparent(im, transparent);
258 static void vrml_end_node(
GVJ_t *job)
261 gdImagePng(im, PNGfile);
268 static void vrml_begin_edge(
GVJ_t *job)
275 gvputs(job,
" Group { children [\n");
283 double o_x, o_y, o_z;
284 double x, y, y0, z, theta;
286 o_x = ((double)(p0.
x + p1.
x))/2;
287 o_y = ((double)(p0.
y + p1.
y))/2;
288 o_z = (Fstz + Sndz)/2;
306 theta = acos(2*y/EdgeLen) +
M_PI;
308 theta = acos(2*y/EdgeLen);
312 y0 = (HeadHt-TailHt)/2.0;
314 gvprintf(job,
" center 0 %.3f 0\n", y0);
315 gvprintf(job,
" rotation %.3f 0 %.3f %.3f\n", -z, x, -theta);
316 gvprintf(job,
" translation %.3f %.3f %.3f\n", o_x, o_y - y0, o_z);
320 static void vrml_end_edge(
GVJ_t *job)
323 finishSegment(job, job->
obj->
u.
e);
327 extern void gdgen_text(gdImagePtr im,
pointf spf,
pointf epf,
int fontcolor,
double fontsize,
int fontdpi,
double fontangle,
char *fontname,
char *
str);
334 if (! obj->
u.
n || ! im)
337 switch (span->
just) {
351 spf = vrml_node_point(job, obj->
u.
n, p);
352 epf = vrml_node_point(job, obj->
u.
n, q);
382 rv = (fstz + sndz) / 2.0;
384 rv = fstz + (sndz - fstz) * (p1.
y - fst.
y) / (snd.
y - fst.
y);
387 len =
DIST(fst, snd);
388 d =
DIST(p1, fst)/len;
389 rv = fstz + d*(sndz - fstz);
402 w =
wind(A[0],A[1],A[2]);
403 return (fabs(w) <= 1);
411 straight (
pointf * A,
int n)
413 if (n != 4)
return 0;
414 return (collinear(A) && collinear(A+1));
422 double delx, dely, delz;
427 EdgeLen = sqrt(delx*delx + dely*dely + delz*delz);
430 CylHt = EdgeLen - d0 - d1;
434 gvputs(job,
"Transform {\n");
435 gvputs(job,
" children [\n");
436 gvputs(job,
" Shape {\n");
437 gvputs(job,
" geometry Cylinder {\n");
438 gvputs(job,
" bottom FALSE top FALSE\n");
440 gvputs(job,
" appearance Appearance {\n");
441 gvputs(job,
" material Material {\n");
442 gvputs(job,
" ambientIntensity 0.33\n");
443 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
466 #define GETZ(jp,op,p,e) (nearTail(jp,p,e)?op->tail_z:op->head_z)
469 vrml_bezier(
GVJ_t *job,
pointf * A,
int n,
int arrow_at_start,
int arrow_at_end,
int filled)
479 fstz = Fstz = obj->
tail_z;
480 sndz = Sndz = obj->
head_z;
486 gvputs(job,
"Shape { geometry Extrusion {\n");
489 for (i = 0; i + 3 < n; i += 3) {
491 for (j = 1; j <= 3; j++)
496 interpolate_zcoord(job, p1, A[0], fstz, A[n - 1], sndz));
500 gvprintf(job,
" crossSection [ %.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f ]\n",
505 gvprintf(job,
" appearance DEF E%ld Appearance {\n",
AGSEQ(e));
506 gvputs(job,
" material Material {\n");
507 gvputs(job,
" ambientIntensity 0.33\n");
508 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
527 p0.
x = (A[0].
x + A[2].
x)/2.0;
528 p0.
y = (A[0].
y + A[2].
y)/2.0;
529 rad =
DIST(A[0],A[2])/2.0;
532 y = (CylHt + ht)/2.0;
534 gvputs(job,
"Transform {\n");
535 if (nearTail (job, A[1], e)) {
537 gvprintf(job,
" translation 0 %.3f 0\n", -y);
542 gvprintf(job,
" translation 0 %.3f 0\n", y);
544 gvputs(job,
" children [\n");
545 gvputs(job,
" Shape {\n");
546 gvprintf(job,
" geometry Cone {bottomRadius %.3f height %.3f }\n",
548 gvputs(job,
" appearance Appearance {\n");
549 gvputs(job,
" material Material {\n");
550 gvputs(job,
" ambientIntensity 0.33\n");
551 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
562 static void vrml_polygon(
GVJ_t *job,
pointf * A,
int np,
int filled)
571 gdImagePtr brush =
NULL;
576 gvprintf(job,
" Background { skyColor %.3f %.3f %.3f }\n",
586 pen = set_penstyle(job, im, brush);
588 for (i = 0; i < np; i++) {
589 mp = vrml_node_point(job, n, A[i]);
590 points[i].x =
ROUND(mp.
x);
591 points[i].y =
ROUND(mp.
y);
594 gdImageFilledPolygon(im, points, np, color_index(im, obj->
fillcolor));
595 gdImagePolygon(im, points, np, pen);
598 gdImageDestroy(brush);
601 gvputs(job,
" appearance Appearance {\n");
602 gvputs(job,
" material Material {\n");
603 gvputs(job,
" ambientIntensity 0.33\n");
604 gvputs(job,
" diffuseColor 1 1 1\n");
606 gvprintf(job,
" texture ImageTexture { url \"node%ld.png\" }\n",
AGSEQ(n));
608 gvputs(job,
" geometry Extrusion {\n");
609 gvputs(job,
" crossSection [");
610 for (i = 0; i < np; i++) {
618 gvprintf(job,
" spine [ %.5g %.5g %.5g, %.5g %.5g %.5g ]\n",
631 "vrml_polygon: non-triangle arrowheads not supported - ignoring\n");
635 doArrowhead (job, A);
639 for (i = 0; i < np; i++) {
648 atan2((A[0].y + A[2].y) / 2.0 - A[1].y,
649 (A[0].x + A[2].x) / 2.0 - A[1].x) +
M_PI / 2.0;
651 z = GETZ(job,obj,p,e);
654 gvputs(job,
"Transform {\n");
655 gvprintf(job,
" translation %.3f %.3f %.3f\n", p.
x, p.
y, z);
656 gvputs(job,
" children [\n");
657 gvputs(job,
" Transform {\n");
658 gvprintf(job,
" rotation 0 0 1 %.3f\n", theta);
659 gvputs(job,
" children [\n");
660 gvputs(job,
" Shape {\n");
661 gvprintf(job,
" geometry Cone {bottomRadius %.3f height %.3f }\n",
685 gvputs(job,
"Transform {\n");
686 gvprintf(job,
" translation %.3f %.3f %.3f\n", p.
x, p.
y, z);
687 gvprintf(job,
" scale %.3f %.3f %.3f\n", rx, rx, rx);
688 gvputs(job,
" children [\n");
689 gvputs(job,
" Transform {\n");
690 gvputs(job,
" children [\n");
691 gvputs(job,
" Shape {\n");
692 gvputs(job,
" geometry Sphere { radius 1.0 }\n");
693 gvputs(job,
" appearance Appearance {\n");
694 gvputs(job,
" material Material {\n");
695 gvputs(job,
" ambientIntensity 0.33\n");
696 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
709 static void vrml_ellipse(
GVJ_t * job,
pointf * A,
int filled)
720 gdImagePtr brush =
NULL;
722 rx = A[1].
x - A[0].
x;
723 ry = A[1].
y - A[0].
y;
732 doSphere (job, n, A[0], z, rx, ry);
735 pen = set_penstyle(job, im, brush);
737 npf = vrml_node_point(job, n, A[0]);
738 nqf = vrml_node_point(job, n, A[1]);
740 dx =
ROUND(2 * (nqf.
x - npf.
x));
741 dy =
ROUND(2 * (nqf.
y - npf.
y));
746 gdImageFilledEllipse(im, np.
x, np.
y, dx, dy, color_index(im, obj->
fillcolor));
747 gdImageArc(im, np.
x, np.
y, dx, dy, 0, 360, pen);
750 gdImageDestroy(brush);
752 gvputs(job,
"Transform {\n");
753 gvprintf(job,
" translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z);
754 gvprintf(job,
" scale %.3f %.3f 1\n", rx, ry);
755 gvputs(job,
" children [\n");
756 gvputs(job,
" Transform {\n");
757 gvputs(job,
" rotation 1 0 0 1.57\n");
758 gvputs(job,
" children [\n");
759 gvputs(job,
" Shape {\n");
760 gvputs(job,
" geometry Cylinder { side FALSE }\n");
761 gvputs(job,
" appearance Appearance {\n");
762 gvputs(job,
" material Material {\n");
763 gvputs(job,
" ambientIntensity 0.33\n");
764 gvputs(job,
" diffuseColor 1 1 1\n");
766 gvprintf(job,
" texture ImageTexture { url \"node%ld.png\" }\n",
AGSEQ(n));
776 z = GETZ(job,obj,A[0],e);
778 gvputs(job,
"Transform {\n");
779 gvprintf(job,
" translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z);
780 gvputs(job,
" children [\n");
781 gvputs(job,
" Shape {\n");
782 gvprintf(job,
" geometry Sphere {radius %.3f }\n", (
double) rx);
842 {FORMAT_VRML,
"vrml", 1, &vrml_engine, &render_features_vrml},
849 {FORMAT_VRML,
"vrml:vrml", 1,
NULL, &device_features_vrml},
void gdgen_text(gdImagePtr im, pointf spf, pointf epf, int fontcolor, double fontsize, int fontdpi, double fontangle, char *fontname, char *str)
#define GVDEVICE_BINARY_FORMAT
shape_kind shapeOf(node_t *)
const char * output_filename
int agerr(agerrlevel_t level, const char *fmt,...)
gvplugin_installed_t gvdevice_vrml_types[]
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
#define GVDEVICE_NO_WRITER
int gvputs(GVJ_t *job, const char *s)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
CGRAPH_API char * agnameof(void *)
pointf gvrender_ptf(GVJ_t *job, pointf p)
int wind(Ppoint_t a, Ppoint_t b, Ppoint_t c)
pointf Bezier(pointf *V, int degree, double t, pointf *Left, pointf *Right)
gvplugin_installed_t gvrender_vrml_types[]
#define BEZIERSUBDIVISION
void gvprintf(GVJ_t *job, const char *format,...)