43#define BEZIERSUBDIVISION 10
55 double HeadHt, TailHt;
59static void vrml_begin_job(
GVJ_t *job) {
63static void vrml_end_job(
GVJ_t *job) {
71static strview_t gdirname(
const char *pathname){
73 size_t last = strlen(pathname);
75 while (
last > 0 && pathname[--
last] ==
'/');
83 else if (pathname[1] ==
'/')
89 if (
last == 0 && *pathname ==
'/' && pathname[1] ==
'/')
97static char *nodefilename(
const char *filename,
node_t *n,
agxbuf *buf) {
101 dir = gdirname(filename);
108static FILE *nodefile(
const char *filename,
node_t * n)
113 rv = fopen(nodefilename(filename, n, &buf),
"wb");
141 alpha = (255 -
color.u.rgba[3]) * gdAlphaMax / 255;
143 if(
alpha == gdAlphaMax)
144 return gdImageGetTransparent(im);
146 return gdImageColorResolveAlpha(im,
153static int set_penstyle(
GVJ_t * job, gdImagePtr im, gdImagePtr brush)
156 int i, pen, pencolor,
transparent, width, dashstyle[20];
158 pen = pencolor = color_index(im, obj->
pencolor);
161 for (i = 0; i < 10; i++)
162 dashstyle[i] = pencolor;
165 gdImageSetStyle(im, dashstyle, 20);
168 for (i = 0; i < 2; i++)
169 dashstyle[i] = pencolor;
172 gdImageSetStyle(im, dashstyle, 12);
178 gdImageSetThickness(im, width);
181 brush = gdImageCreate(width, width);
182 gdImagePaletteCopy(brush, im);
183 gdImageFilledRectangle(brush, 0, 0, width - 1, width - 1, pencolor);
184 gdImageSetBrush(im, brush);
186 pen = gdStyledBrushed;
195static void vrml_begin_page(
GVJ_t *job)
199 gvputs(job,
"#VRML V2.0 utf8\n");
201 state->Saw_skycolor =
false;
202 state->MinZ = DBL_MAX;
203 gvputs(job,
"Group { children [\n"
205 gvprintf(job,
" scale %.3f %.3f %.3f\n", .0278, .0278, .0278);
206 gvputs(job,
" children [\n");
209static void vrml_end_page(
GVJ_t *job)
219 z = (0.6667*d)/tan(
M_PI/8.0) + state->MinZ;
221 if (!state->Saw_skycolor)
222 gvputs(job,
" Background { skyColor 1 1 1 }\n");
224 gvprintf(job,
" Viewpoint {position %.3f %.3f %.3f}\n",
225 state->Scale * (bb.
UR.
x + bb.
LL.
x) / 72.,
226 state->Scale * (bb.
UR.
y + bb.
LL.
y) / 72.,
227 state->Scale * 2 *
z / 72.);
231static void vrml_begin_node(
GVJ_t *job)
245 if (state->PNGfile ==
NULL) {
246 agerrorf(
"failed to open file for writing PNG node image\n");
249 width = (
ND_lw(n) +
ND_rw(n)) * state->Scale + 2 * NODE_PAD;
250 height = (
ND_ht(n) ) * state->Scale + 2 * NODE_PAD;
251 state->im = gdImageCreate(width, height);
255 gdRedMax - 1, gdGreenMax,
256 gdBlueMax, gdAlphaTransparent);
261static void vrml_end_node(
GVJ_t *job)
265 if (state->PNGfile !=
NULL) {
266 gdImagePng(state->im, state->PNGfile);
267 fclose(state->PNGfile);
269 gdImageDestroy(state->im);
274static void vrml_begin_edge(
GVJ_t *job)
280 state->IsSegment = 0;
282 gvputs(job,
" Group { children [\n");
290 double o_x, o_y, o_z;
291 double x, y, y0,
z, theta;
294 o_x = ((double)(p0.
x + p1.
x))/2;
295 o_y = ((double)(p0.
y + p1.
y))/2;
296 o_z = (state->Fstz + state->Sndz) / 2;
314 theta = acos(2 * y / state->EdgeLen) +
M_PI;
316 theta = acos(2 * y / state->EdgeLen);
320 y0 = (state->HeadHt - state->TailHt) / 2.0;
322 gvprintf(job,
" center 0 %.3f 0\n", y0);
323 gvprintf(job,
" rotation %.3f 0 %.3f %.3f\n", -
z, x, -theta);
324 gvprintf(job,
" translation %.3f %.3f %.3f\n", o_x, o_y - y0, o_z);
328static void vrml_end_edge(
GVJ_t *job)
332 if (state->IsSegment)
333 finishSegment(job, job->
obj->
u.
e);
343 if (!obj->
u.
n || !state->im)
346 switch (span->
just) {
360 spf = vrml_node_point(job, obj->
u.
n, p);
361 epf = vrml_node_point(job, obj->
u.
n, q);
364 color_index(state->im, obj->
pencolor),
391 rv = (fstz + sndz) / 2.0;
393 rv = fstz + (sndz - fstz) * (p1.
y - fst.
y) / (snd.
y - fst.
y);
398 rv = fstz + d*(sndz - fstz);
419static int straight(
pointf *
A,
size_t n) {
420 if (n != 4)
return 0;
421 return collinear(
A) && collinear(
A + 1);
429 double delx, dely, delz;
435 state->EdgeLen = sqrt(delx*delx + dely*dely + delz*delz);
438 state->CylHt = state->EdgeLen - d0 - d1;
439 state->TailHt = state->HeadHt = 0;
441 state->IsSegment = 1;
442 gvputs(job,
"Transform {\n"
445 " geometry Cylinder {\n"
446 " bottom FALSE top FALSE\n");
448 gvputs(job,
" appearance Appearance {\n"
449 " material Material {\n"
450 " ambientIntensity 0.33\n");
451 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
474#define GETZ(jp,op,p,e) (nearTail(jp,p,e)?op->tail_z:op->head_z)
476static void vrml_bezier(
GVJ_t *job,
pointf *
A,
size_t n,
int filled) {
488 fstz = state->Fstz = obj->
tail_z;
489 sndz = state->Sndz = obj->
head_z;
490 if (straight(
A, n)) {
495 gvputs(job,
"Shape { geometry Extrusion {\n"
498 for (
size_t i = 0; i + 3 < n; i += 3) {
500 for (
size_t j = 1; j <= 3; j++)
505 interpolate_zcoord(job, p1,
A[0], fstz,
A[n - 1], sndz));
509 gvprintf(job,
" crossSection [ %.3f %.3f, %.3f %.3f, %.3f %.3f, %.3f %.3f ]\n",
514 gvprintf(job,
" appearance DEF E%d Appearance {\n",
AGSEQ(e));
515 gvputs(job,
" material Material {\n"
516 " ambientIntensity 0.33\n");
517 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
537 p0.
x = (
A[0].x +
A[2].x)/2.0;
538 p0.
y = (
A[0].y +
A[2].y)/2.0;
539 rad =
DIST(
A[0],
A[2])/2.0;
542 y = (state->CylHt + ht)/2.0;
544 gvputs(job,
"Transform {\n");
545 if (nearTail (job,
A[1], e)) {
547 gvprintf(job,
" translation 0 %.3f 0\n", -y);
552 gvprintf(job,
" translation 0 %.3f 0\n", y);
554 gvputs(job,
" children [\n"
556 gvprintf(job,
" geometry Cone {bottomRadius %.3f height %.3f }\n",
558 gvputs(job,
" appearance Appearance {\n"
559 " material Material {\n"
560 " ambientIntensity 0.33\n");
561 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
572static void vrml_polygon(
GVJ_t *job,
pointf *
A,
size_t np,
int filled) {
580 gdImagePtr brush =
NULL;
586 gvprintf(job,
" Background { skyColor %.3f %.3f %.3f }\n",
590 state->Saw_skycolor =
true;
596 pen = set_penstyle(job, state->im, brush);
598 for (
size_t i = 0; i < np; i++) {
599 mp = vrml_node_point(job, n,
A[i]);
603 assert(np <= INT_MAX);
605 gdImageFilledPolygon(state->im,
points, (
int)np, color_index(state->im, obj->
fillcolor));
606 gdImagePolygon(state->im,
points, (
int)np, pen);
609 gdImageDestroy(brush);
612 " appearance Appearance {\n"
613 " material Material {\n"
614 " ambientIntensity 0.33\n"
615 " diffuseColor 1 1 1\n"
617 gvprintf(job,
" texture ImageTexture { url \"node%d.png\" }\n",
AGSEQ(n));
619 " geometry Extrusion {\n"
621 for (
size_t i = 0; i < np; i++) {
629 gvprintf(job,
" spine [ %.5g %.5g %.5g, %.5g %.5g %.5g ]\n",
642 "vrml_polygon: non-triangle arrowheads not supported - ignoring\n");
645 if (state->IsSegment) {
646 doArrowhead (job,
A);
650 for (
size_t i = 0; i < np; i++) {
659 atan2((
A[0].y +
A[2].y) / 2.0 -
A[1].y,
660 (
A[0].x +
A[2].x) / 2.0 -
A[1].x) +
M_PI / 2.0;
662 z = GETZ(job,obj,p,e);
665 gvputs(job,
"Transform {\n");
666 gvprintf(job,
" translation %.3f %.3f %.3f\n", p.
x, p.
y,
z);
667 gvputs(job,
" children [\n"
669 gvprintf(job,
" rotation 0 0 1 %.3f\n", theta);
670 gvputs(job,
" children [\n"
672 gvprintf(job,
" geometry Cone {bottomRadius %.3f height %.3f }\n",
687static void doSphere(
GVJ_t *job,
pointf p,
double z,
double rx) {
690 gvputs(job,
"Transform {\n");
691 gvprintf(job,
" translation %.3f %.3f %.3f\n", p.
x, p.
y,
z);
692 gvprintf(job,
" scale %.3f %.3f %.3f\n", rx, rx, rx);
693 gvputs(job,
" children [\n"
697 " geometry Sphere { radius 1.0 }\n"
698 " appearance Appearance {\n"
699 " material Material {\n"
700 " ambientIntensity 0.33\n");
701 gvprintf(job,
" diffuseColor %.3f %.3f %.3f\n",
714static void vrml_ellipse(
GVJ_t * job,
pointf *
A,
int filled)
725 gdImagePtr brush =
NULL;
728 rx =
A[1].x -
A[0].x;
729 ry =
A[1].y -
A[0].y;
738 doSphere(job,
A[0],
z, rx);
741 pen = set_penstyle(job, state->im, brush);
743 npf = vrml_node_point(job, n,
A[0]);
744 nqf = vrml_node_point(job, n,
A[1]);
752 gdImageFilledEllipse(state->im, np.
x, np.
y,
dx,
dy, color_index(state->im, obj->
fillcolor));
753 gdImageArc(state->im, np.
x, np.
y,
dx,
dy, 0, 360, pen);
756 gdImageDestroy(brush);
758 gvputs(job,
"Transform {\n");
759 gvprintf(job,
" translation %.3f %.3f %.3f\n",
A[0].x,
A[0].y,
z);
760 gvprintf(job,
" scale %.3f %.3f 1\n", rx, ry);
761 gvputs(job,
" children [\n"
763 " rotation 1 0 0 1.57\n"
766 " geometry Cylinder { side FALSE }\n"
767 " appearance Appearance {\n"
768 " material Material {\n"
769 " ambientIntensity 0.33\n"
770 " diffuseColor 1 1 1\n"
772 gvprintf(job,
" texture ImageTexture { url \"node%d.png\" }\n",
AGSEQ(n));
782 z = GETZ(job,obj,
A[0],e);
784 gvputs(job,
"Transform {\n");
785 gvprintf(job,
" translation %.3f %.3f %.3f\n",
A[0].x,
A[0].y,
z);
786 gvputs(job,
" children [\n"
788 gvprintf(job,
" geometry Sphere {radius %.3f }\n", (
double) rx);
848 {FORMAT_VRML,
"vrml", 1, &vrml_engine, &render_features_vrml},
855 {FORMAT_VRML,
"vrml:vrml", 1,
NULL, &device_features_vrml},
static agxbuf last
last message
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
abstract graph C library, Cgraph API
pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right)
void gdgen_text(gdImagePtr im, pointf spf, pointf epf, int fontcolor, double fontsize, int fontdpi, double fontangle, char *fontname, char *str)
static double len(glCompPoint p)
void agwarningf(const char *fmt,...)
void agerrorf(const char *fmt,...)
char * agnameof(void *)
returns a string descriptor for the object.
#define GVDEVICE_NO_WRITER
#define GVDEVICE_BINARY_FORMAT
static void color(Agraph_t *g)
pointf gvrender_ptf(GVJ_t *job, pointf p)
int gvputs(GVJ_t *job, const char *s)
void gvprintf(GVJ_t *job, const char *format,...)
static const char transparent[]
gvplugin_installed_t gvrender_vrml_types[]
gvplugin_installed_t gvdevice_vrml_types[]
textitem scanner parser str
PATHUTIL_API int wind(Ppoint_t a, Ppoint_t b, Ppoint_t c)
shape_kind shapeOf(node_t *)
const char * output_filename
size_t size
number of characters in the buffer
information the ID allocator needs to do its job
a non-owning string reference
const char * data
start of the pointed to string
size_t size
extent of the string in bytes
Non-owning string references.
static strview_t strview(const char *referent, char terminator)
create a string reference
#define BEZIERSUBDIVISION