########################## ## ## Title : writeoogl, a package for converting maple PLOT3D ## objects to Geomview data objects. ## gvplot, interactive pipe to Geomview from Maple ## ## Created : Dec 5 1993 ## ## Authors : Frederick Wicklin and ## Stuart Levy ## The Geometry Center ## ## ## ## ## Documentation : currently ?gvplot or ?writeoogl or ?geomview ## ## History ## fjw 9/21/93 initial maple->geomview for Maple VR2 ## slevy 11/27/93 interactive geomview pipe; ## backwards compatable to Maple V ## fjw 11/29/93 debugging; added color options ## ## lr (renggli@math.fsu.edu) 03/28/97 ## modifications for Maple VR4 (replaced gc() calls) ## ## ## Usage: readlib(gvplot); ## (optional) gvcommand := `geomview initial-options ...`; ## (optional) gvdirectories := `/some/dir/ectory:/other/dir...`; ## 3dplot_struct := plot3d( ... ): ## writeoogl(`filename`, 3dplot_struct); ## gvplot(3dplot_struct); # To search for "geomview" and "togeomview" in directories which might not # be on the default UNIX search path, list those director(ies) here, as in # default_gvdirectories := `/u/geom/bin:/usr/local/bin:` # or, set the "gvdirectories" variable before invoking gvplot(). default_gvdirectories := ``: # To start geomview with non-default options, or to start another program # via gvplot, put its name and initial arguments here in place of `geomview`, # or set the variable "gvcommand" before invoking gvplot(). # Changing default_gvcommand, then resaving gvplot.m, alters the default for # all users; setting the gvcommand variable changes it for just your session. default_gvcommand := `geomview`: ### Upon invoking the geomview package, maple creates a global ### variable UsEr_ID__ which is assigned a "random" number. ### This variable is used to create user-specific files in /tmp. ################################################################## # There doesn't seem to be any explicit test for Maple V1 vs. V2, # but all V1 plot objects seem to begin with FUNCTION, so use that fact # to detect that we must be careful not to print invalid float constants. ################################################################## `oogl/lprn` := `oogl/lprnV2`: writeoogl := proc() global `oogl/lprn`; local header, item, ps, zlist, plist, llist, ppoint, pcolor, appear, i, j, totl, xrange, yrange, nx, ny, savedprintbytes, coloron,colorlist,ccnt, totalverts; options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`; if nargs > 2 or nargs = 0 then ERROR(`Usage:writeoogl(``filename``,3dplot_struct); OR writeoogl(3dplot_struct);`) fi; ps := args[nargs]; if not type(ps, PLOT3D) then ERROR(`Invalid plot structure`,ps, `; must be of type PLOT3D, as from plot3d(), tubeplot(), spacecurve(), etc.`) fi; if nargs = 2 and not type(args[1], string) then ERROR(`Invalid file name (not string)`, args[1]) fi; if nops(ps) < 1 then ERROR(`Empty 3D plot structure!`) fi; ################################################################## # When run in command-line mode, Garbage Collection (GC) # # messages printed to terminal can interfere with the data flow. # # Therefore suppress GC during writing of GeomView data # ################################################################## if nargs = 2 then savedprintbytes:=kernelopts( printbytes): kernelopts( printbytes=false): print(`Saving Maple 3D structs to Geomview file`, args[1]); writeto(args[1]); fi; xrange := 'xrange'; # nullify this local variable appear := find_appearance(1, ps); lprint( appear, `{LIST` ); ################################################################## ### BEGIN main loop over all 3D plots (may be a list of plots) ### ################################################################## for item in ps do coloron := FALSE; # default is no color info header := op(0,item); if header = FUNCTION then # Maple V1 only: FUNCTION( f(x,y), xrange, yrange ) # or FUNCTION( x(u,v), y(u,v), z(u,v), u = u0..u1, v = v0..v1 ) xrange := op(nops(item)-1, item); if type(xrange, `=`) then xrange := op(2, xrange) fi; yrange := op(nops(item), item); if type(yrange, `=`) then yrange := op(2, yrange) fi; # Maple V1 -- don't trust lprint() `oogl/lprn` := `oogl/lprnV1`; ########################### GRID ############################ # EX: plot3d( f(x,y), x=xmin..xmax, y=ymin..ymax] # Saving Maple GRID struct to geomview ZMESH struct # Maple V1: FUNCTION( f(x,y), xrange,yrange ) followed by GRID( zlist ) # In Maple V1, we might see either ZMESH-style data (only Z per vertex) # or a full 3-D mesh (x,y,z per vertex). Just check the first # vertex to see. # Maple V2: GRID( xrange, yrange, zlist ) # Maple V2 uses GRID only for ZMESH-style data, # and uses a MESH header for meshes with general 3-D verts. ############################################################### elif header = GRID then if type(xrange, `..`) then zlist := item else # this is typical VR2 route xrange := op(1, item); yrange := op(2, item); zlist := op(3, item); ####################################################### # if color, then there are 4 possibilities: # colorlist = COLOR(HUE, h[1],...,h[nops[colorlist]) # colorlist = COLOR(HUE, h) # colorlist = COLOR(RGB, r[1],g[1],b[1],...) # colorlist = COLOR(RGB, r,g,b) # Convert HUES to an RGB value using HSV2RGB and # (assume that Maple uses s=v=1). Add a 1 at the end of # the list for geomview's "alpha": 0<=>transparent, 1<=>opaque ####################################################### if( nops(item)>3 ) then colorlist := find_colorlist(4, item); coloron := op(1,colorlist); # either RGB, HUE, or FALSE fi; fi; nx := nops(zlist); ny := nops(op(1,zlist)); if type(op(1, op(1,zlist)), list) then lprint(`{ { MESH`, ny, nx) else # scale this data by wrapping it in transformation matrix lprint(`{ INST transform { `); `oogl/lprn`( [0, (op(2,yrange)-op(1,yrange)) / (ny-1), 0, 0] ); `oogl/lprn`( [(op(2,xrange)-op(1,xrange)) / (nx-1), 0, 0, 0] ); lprint(0, 0, 1, 0); `oogl/lprn`( [op(1,xrange), op(1,yrange), 0, 1] ); if(coloron = FALSE) then lprint(` } geom { ZMESH`, ny, nx); # gv type else lprint(` } geom { CZMESH`, ny, nx); # color gv type fi; fi; ccnt := 2; # set color counter to 2 for plist in zlist do for ppoint in plist do `oogl/lprn`(ppoint); if (coloron = HUE) and nops(colorlist)>2 then lprint(HSV2RGB(op(ccnt,colorlist), 1,1), 1); ccnt := ccnt + 1; elif (coloron = HUE) and nops(colorlist)=2 then lprint(HSV2RGB(op(2,colorlist), 1,1), 1); elif (coloron = RGB) and nops(colorlist)>4 then lprint(op(ccnt,colorlist),op(ccnt+1,colorlist),op(ccnt+2,colorlist),1); ccnt := ccnt + 3; elif (coloron = RGB) and nops(colorlist)=4 then lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist), 1); fi; od; od; lprint( `} }`); ########################### MESH ########################### # EX: plot3d( [x(s,t), y(s,t), z(s,t)], s=smin..smax, t=tmin..tmax] # Saving Maple MESH struct to geomview MESH struct ############################################################### elif header = MESH then llist := op(1, item): if( nops(item)>1 ) then colorlist := find_colorlist(2, item); coloron := op(1,colorlist); # either RGB, HUE, or FALSE fi; if(coloron=FALSE) then lprint(`{ MESH ` ); # gv type else lprint(`{ CMESH ` ); # color gv type fi; lprint( nops(llist)); # num x elements lprint( nops(op(1,llist)) ); # num y elements # Maple store points in row-dominant manner # But geomview want column-dominant, so need to # print out the transpose of the matrix in the plot3d struct nx := nops(llist); # maple rows ny := nops(op(1,llist)); # maple cols for j from 1 to ny do for i from 1 to nx do ppoint := op(j, op(i,llist)); `oogl/lprn`(ppoint); if (coloron = HUE) and nops(colorlist)>2 then lprint(HSV2RGB(op((i-1)*ny+j +1,colorlist), 1,1), 1); elif (coloron = HUE) and nops(colorlist)=2 then lprint(HSV2RGB(op(2,colorlist), 1,1), 1); elif (coloron = RGB) and nops(colorlist)>4 then lprint(op(3*((i-1)*ny+j-1)+2,colorlist),op(3*((i-1)*ny+j-1)+3,colorlist),op(3*((i-1)*ny+j-1)+4,colorlist),1); elif (coloron = RGB) and nops(colorlist)=4 then lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist), 1); fi; od; od; lprint( `}`); ########################### CURVES ########################## # EX: spacecurve( [x(t), y(t), z(t)], t=tmin..tmax] # Saving Maple CURVES struct to geomview VECT struct ############################################################### elif header = CURVES then llist := select(type, item, list); if( nops(item)>1 ) then colorlist := find_colorlist(2, item); coloron := op(1,colorlist); # either RGB, HUE, or FALSE fi; lprint(`{ VECT `); # gv type # Number of polylines, total vertices. totalverts := sum('nops(op(i,llist))', 'i'=1..nops(llist)); lprint(nops(llist), totalverts); if coloron=FALSE then lprint(1); # One color in all lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # Vertex counts lprint(1, 0 $ 'i'=2..nops(llist)); # Color counts. else lprint(totalverts); # Total number of colors, 1 per vert lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # Vertex counts lprint(seq(nops(op(i,llist)), i=1..nops(llist))); # color per vert fi; for plist in llist do for ppoint in plist do # print all vertices `oogl/lprn`(ppoint); od od; if coloron=FALSE then lprint(1,1,1,1); # color RGBA = white and opaque elif (coloron = HUE) and nops(colorlist)>2 then for ccnt from 2 to nops(colorlist) do lprint(HSV2RGB(op(ccnt,colorlist), 1,1), 1); od; elif (coloron = HUE) and nops(colorlist)=2 then for ccnt from 1 to nops(llist) do lprint(HSV2RGB(op(2,colorlist), 1,1), 1); od; elif (coloron = RGB) and nops(colorlist)>4 then for ccnt from 2 by 3 to nops(colorlist) do lprint(op(ccnt,colorlist),op(ccnt+1,colorlist),op(ccnt+2,color\list),1); od; elif (coloron = RGB) and nops(colorlist)=4 then for ccnt from 1 to nops(llist) do lprint(op(2,colorlist),op(3,colorlist),op(4,colorlist),1); od; fi; lprint( `}`); ######################### POLYGONS ########################## #EX:polygonplot3d([seq([seq([x(s,t),y(s,t),z(s,t)],s=smin..smax],tmin..tmax])): # Polygons are handled differently than the other objects w/r/t # color. Leave color alone and let user change color using geomview. ############################################################### elif header = POLYGONS then pcolor := i $ i=1..0; # Empty sequence totl := 0: nx := 0: # use nx to count number of polygons for llist in item do # sequence of lists POLY(),COLOR(), if type(llist,list) then nx := nx + 1; # number of polygons totl := totl + nops(llist); # compute total number of vertices fi od; lprint(find_appearance(1, item)); # if coloron=FALSE then lprint(`{ OFF `); # gv type # else # lprint(`{ COFF `); # color # fi; lprint(totl, nx, 0); # total verts,polygons,"edges"(not used!) for llist in item do if type(llist,list) then for ppoint in llist do `oogl/lprn`(ppoint); # List of vertices od; fi; od; lprint(``); totl := 0; for llist in item do if type(llist,function) and (op(0,llist)=COLOR or op(0,llist)=COLOUR) then colorlist := llist; if op(1,llist)=HUE and nops(colorlist)=2 then pcolor := HSV2RGB(op(2,colorlist),1,1); # use ppoint for RGB elif op(1,llist)=RGB and nops(colorlist)=4 then pcolor := op(2..4,colorlist); fi; elif type(llist,list) then ## There are only two possibilities for POLYGONS ## ## In both cases, it means entire polygon is same color ## lprint( nops(llist), i $ i=totl..totl+nops(llist)-1, ` `, pcolor); totl := totl + nops(llist); fi; od; lprint( `}`); ######################### POINTS ########################## #EX:PLOT3D(POINTS([0,0,1],[1,0,0],[0,1,0])); ############################################################### elif header = POINTS then lprint(`{ VECT`, nops(item), nops(item), 0); for plist in item do lprint(`1`) od; lprint(``); for plist in item do lprint(`0`) od; lprint(``); for ppoint in item do `oogl/lprn`(ppoint) od; lprint(`}`); ########################### TEXT ############################ # 3D plots using the "plots" package may include TEXT # This is not supported ############################################################### elif header = TEXT then print(` `); fi; od; # END main for loop lprint( `}`); if nargs = 2 then writeto(terminal); kernelopts( printbytes=savedprintbytes): fi; NULL; end: gvplot := proc() global UsEr_ID__, gvcommand, default_gvcommand, gvdirectories, default_gvdirectories; local gvname, gvcmd, gvdirs, ps, savedprintbytes, tmp_fname; options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`; ### Set up filename to use as temporary site for data. ### ### Take file in /tmp and postfix number which is (hopefully) ### ### independent of users. Eg, if user1 and user2 are both ### ### using writeoogl, then they will be writing to different ### ### files. This is UNIX specific (but so is Geomview). ### if UsEr_ID__ = 'UsEr_ID__' then UsEr_ID__ := (round( rand() * (time()+1) ) mod 9999) + 1; fi; tmp_fname := `Maple`.(UsEr_ID__); ### Let user specify, via "gvcommand" and "gvdirectories" global vars, ### which program/args to run when invoking geomview, ### and how to set the search path to find it and togeomview. if gvcommand <> 'gvcommand' then gvcmd := gvcommand else gvcmd := default_gvcommand fi; if gvdirectories <> 'gvdirectories' then gvdirs := gvdirectories else gvdirs := default_gvdirectories fi; ps := args[nargs]; gvname := `Maple`; if nargs < 1 or nargs > 2 then ERROR(`Usage: gvplot(3dplot_structure) -or- gvplot(``name``, 3dplot_structure)`); fi; if nargs > 1 then gvname := args[1] fi; if not type( ps, PLOT3D) then ERROR(`Invalid plot structure`,ps, `; must be of type PLOT3D, as from plot3d(), tubeplot(), spacecurve(), etc.`) fi; # start geomview reading from stdin if system( `PATH=` . gvdirs . `:$PATH togeomview -Mcp `.tmp_fname.` `.gvcmd.` 0 then ERROR(`gvplot: togeomview: Can't start a copy of geomview. `. `If "togeomview" or "geomview" were not found `. `try setting the variable "gvdirectories" to the name of the directory where `. `they're installed (or to a colon-separated list of directories).`); fi; savedprintbytes:=kernelopts( printbytes): kernelopts( printbytes=false): writeto(`/tmp/geomview/`.tmp_fname); lprint(`(geometry`, gvname); writeoogl( ps ); lprint(`)`); writeto(terminal); kernelopts( printbytes=savedprintbytes): NULL; end: gvcommand := proc() global UsEr_ID__, gvcommand, default_gvcommand, gvdirectories, default_gvdirectories; local gvname, gvcmd, gvdirs, ps, savedprintbytes, tmp_fname; options `Copyright 1993 by Frederick Wicklin and Stuart Levy, Geometry Center`; ### Set up filename to use as temporary site for data. ### ### Take file in /tmp and postfix number which is (hopefully) ### ### independent of users. Eg, if user1 and user2 are both ### ### using writeoogl, then they will be writing to different ### ### files. This is UNIX specific (but so is Geomview). ### if UsEr_ID__ = 'UsEr_ID__' then UsEr_ID__ := (round( rand() * (time()+1) ) mod 9999) + 1; fi; tmp_fname := `Maple`.(UsEr_ID__); ### Let user specify, via "gvcommand" and "gvdirectories" global vars, ### which program/args to run when invoking geomview, ### and how to set the search path to find it and togeomview. if gvcommand <> 'gvcommand' then gvcmd := gvcommand else gvcmd := default_gvcommand fi; if gvdirectories <> 'gvdirectories' then gvdirs := gvdirectories else gvdirs := default_gvdirectories fi; # start geomview reading from stdin if system( `PATH=` . gvdirs . `:$PATH togeomview -Mcp `.tmp_fname.` `.gvcmd.` 0 then ERROR(`gvplot: togeomview: Can't start a copy of geomview. `. `If "togeomview" or "geomview" were not found `. `try setting the variable "gvdirectories" to the name of the directory where `. `they're installed (or to a colon-separated list of directories).`); fi; savedprintbytes:=kernelopts( printbytes): kernelopts( printbytes=false): writeto(`/tmp/geomview/`.tmp_fname); lprint(args); writeto(terminal); kernelopts( printbytes=savedprintbytes): NULL; end: # possible gvplot enhancements: # allow remote display? # Maybe use a two-step Rube Goldberg hookup with an external converter # that directly reads lprint() format. Likely to be faster for large objects. # Then gvplot would read # gvplot := proc() # ... # if system(`togeomview -Mcp Maple.raw maple2oogl -togeomview -Mcp Maple`)<>0 # then ERROR(...) fi; # writeto(`/tmp/geomview/Maple.raw`); # lprint(`(geometry`, gvname, `<<`); # lprint(3dplot_struct); # lprint(`>>)`); # writeto(terminal); # end: # and writeoogl would read # writeoogl := proc() # ... # if system(cat(`togeomview -Mcp Maple.rawdata maple2oogl -o `, fname)) <> 0 # then ERROR(...) fi; # writeto(`/tmp/geomview/Maple.rawdata`); # lprint(`<<', 3dplot_string, `>>'); # writeto(terminal); # end: # # Here 'togeomview' is actually being used to start 'maple2oogl' rather # than geomview itself. In the first case, maple2oogl -togeomview would # invoke code to start a copy of geomview. # Help information for writeoogl `help/text/writeoogl` := TEXT( ` `, `HELP FOR: writeoogl, gvplot `, ` `, `CALLING SEQUENCE: `, ` readlib(gvplot): `, ` writeoogl( ``filename``, 3dplot_struct ); `, ` writeoogl( 3dplot_struct ); `, ` gvplot( 3dplot_struct ); `, ` gvplot( ``geomview_name``, 3dplot_struct ) `, ` `, `PARAMETERS: `, ` filename the file which will contain the Geomview data `, ` 3dplot_struct a Maple PLOT3D data structure `, ` geomview_name name of the object in the Geomview browser `, ` `, `SYNOPSIS: `, ` writeoogl() accepts Maple PLOT3D structures and writes files `, ` readable by Geomview. gvplot() converts Maple PLOT3D structures`, ` and displays them immediately using Geomview, starting a copy of`, ` Geomview if necessary.`, ``, ` Supported data types include the Maple structures MESH, GRID, `, ` CURVES, POINTS, and POLYGONS. `, ` See ?plot3d[structure] for more information on Maple PLOT3D types.`, ` `, ` The Maple MESH and GRID structures are translated into Geomview's`, ` MESH and ZMESH objects, respectively, Maple CURVES and POINTS`, ` become VECT objects, and Maple POLYGONS becomes an OFF object.`, ` `, ` The Maple TEXT structure is not supported. Color information is`, ` supported for all objects.`, ``, ` The form writeoogl(filename, plot_struct) writes data in OOGL`, ` (Geomview) form to the given file; writeoogl(plot) writes to the`, ` current output stream as selected by writeto().`, ``, ` gvplot() normally starts the program "geomview", with no options;`, ` to specify something else, set the variable "gvcommand", as in:`, ` gvcommand := ``/usr/local/bin/gv -wpos 200x200 -c startup.gv``;`, ` before invoking gvplot(). Also, if the programs "geomview" or`, ` "togeomview" are not on your UNIX search path, set the variable`, ` gvdirectories := ``/some/dir/ectory:/some/other/directory``;`, ` to the appropriate directory (or directories separated by colons).`, ` `, `EXAMPLES: `, ` readlib(gvplot): `, ` my_plot := plot3d(sin(x+y), x=-Pi..Pi, y=-Pi..Pi): `, ` writeoogl( ``sinxy.mesh``, my_plot ); `, ` Saving Maple 3D structs to Geomview file, sinxy.mesh `, ` steiner := plot3d([ sin(2*x)*(cos(y))^2, sin(x)*sin(2*y), `, ` cos(x)*sin(2*y)], x=-Pi..Pi, y=-Pi..Pi): `, ` writeoogl( ``steiner.mesh``, steiner); `, ` Saving Maple 3D structs to Geomview file, steiner.mesh`, ` # Display it in geomview directly `, ` gvplot( steiner ); `, ` # load in the plots package `, ` with(plots): `, ` trefoil := spacecurve([ -2*cos(t)- 1/2*cos(5*t)+ 3*sin(2*t), `, ` -3*cos(2*t)+ 2*sin(t)- 1/2*sin(5*t), 2*cos(3*t), t=0..2*Pi]):`, ` writeoogl( ``trefoil.vect``, trefoil); `, ` Saving Maple 3D structs to Geomview file, trefoil.vect`, ` tetrahedra := [[1,0,0],[-1,0,0],[0,0,1]], [[1,0,0],[0,0,1],[0,1,0]], `, ` [[0,1,0],[-1,0,0],[0,0,1]], [[1,0,0],[0,1,0],[-1,0,0]]:`, ` Tplot :=polygonplot3d([tetrahedra]): `, ` writeoogl( ``tetrahedra.off``, Tplot); `, ` Saving Maple 3D structs to Geomview file, tetrahedra.off`, ` # you can even create a single file with multiple objects `, ` all_objs := display3d( {my_plot, steiner, trefoil, Tplot} ): `, ` writeoogl( ``all.list``, all_objs ); `, ` Saving Maple 3D structs to Geomview file, all.list `, ` `, `SEE ALSO: plot3d[structure] ` ): `help/text/gvplot` := `help/text/writeoogl`: `help/text/geomview` := `help/text/writeoogl`: # Convert number to string, avoiding excess digits and avoiding Maple V1's # propensity to emit Float(mantissa,exponent) rather than ordinary exponential # notation! `oogl/cvs` := proc(v) local sign, absmant; options `Copyright 1993 by Stuart Levy, Geometry Center`; if type(v, float) then absmant := cat(abs(op(1,v))); sign := substring(`-`, 1..1-signum(v)); if abs(v) >= 1 then if(op(2,v) >= 0) then cat(op(1,v), '0' $ op(2,v)) else cat( sign, substring(absmant, 1..length(absmant)+op(2,v)), `.`, substring(absmant, length(absmant)+op(2,v)+1..8) ) fi elif abs(v) > .000001 then cat( sign, substring( `.0000000`, 1 .. 1-length(absmant)-op(2,v) ), substring(absmant, 1..7) ) else cat( sign, `.`, substring( absmant, 1..7), `e`, op(2,v) + length(absmant) ) fi elif type(v, realcons) then cat(v) fi; end: # # lprint a number, or a list of numbers. # `oogl/lprnV1` := proc (v) local i; options `Copyright 1993 by Stuart Levy, Geometry Center`; if type(v, list) then lprint( ' `oogl/cvs`(v[i]) ' $ i=1..nops(v) ); elif type(v,float) and abs(v) <= .1 then lprint(`oogl/cvs`(v)); elif type(v, realcons) then lprint(v); else lprint(`0 #`); fi; end: # Ditto, but assume we're Maple V2, which prints floating constants # in acceptable form. Don't bother to reformat them. `oogl/lprnV2` := proc(v) local i; options `Copyright 1993 by Stuart Levy, Geometry Center`; if type(v, list) then lprint( 'v[i]' $ i = 1..nops(v) ); # Print on one line elif type(v, realcons) then lprint(v); else lprint(`0 #`); fi end: ############################################################### ## HSV2RGB converts Maple Hues to RGB colors. ## The HUEs used are in [0,1] so assume that S=V=1 (this is close) ## The following algorithm is from Computer Graphics ## By Foley, vanDam, Feiner, Hughes, 2nd Ed. Addison-Wesley ## p 593 ## ## Adapted by fjw 11/29/93 ## Input: (h,s,v) in [0,1]^3 ## Output: sequence r,b,g each in [0,1] ############################################################### HSV2RGB := proc( h,s,v ) local hh,ip,fp,p,q,t; options `Copyright 1990 by Foley, vanDam, Feiner, Hughes`; if (s = 0) then # color on B/W center line if (h<0) then # There is no hue,ie, hue undefined RETURN( v,v,v ); else ERROR(`Undefined color`); fi; else if (h>1) then hh:=1 fi; hh := 6*h; # hh now in [0,6] ip := floor(hh); # ip is integer part of h fp := hh - ip; # fp is fractional part of h p := v*(1-s); q := v*(1-(s*fp)); t := v*(1-(s*(1-fp))); if (ip=0) then RETURN( v,t,p ); elif (ip=1) then RETURN( q,v,p ); elif (ip=2) then RETURN( p,v,t ); elif (ip=3) then RETURN( p,q,v ); elif (ip=4) then RETURN( t,p,v ); else RETURN( v,p,q ); fi; fi; end: ######################################################## # find_colorlist # input: n where to start looking for color data # item what list to search # output: list of color information or NULL list ######################################################## find_colorlist := proc(n,item) local i; options `Copyright 1993 by Frederick Wicklin, Geometry Center`; for i from n to nops(item) do if type(op(i,item),function) and (op(0,op(i,item))=COLOR or op(0,op(i,item))=COLOUR) then RETURN(op(i,item)) fi; od; RETURN([FALSE]); # no color info found end: ######################################################## # find_appearance # input: n index to start seeking color data # list list to search # output: argument of STYLE option (e.g. `PATCH`) or [] list. ######################################################## find_appearance := proc(n, list) local i, part, ap, color, colortype; ap := ``; color := ``; for i from n to nops(list) do part := op(i,list); if type(part,function) and (op(0,part)=COLOR or op(0,part)=COLOUR) then colortype := op(1,part); if colortype = HUE and nops(part) = 2 then color := [HSV2RGB(op(2,part), 1, 1)] elif colortype = RGB and nops(part) = 4 then color := [op(2..4,part)] fi # Otherwise, this "color" tag isn't for us elif type(part,function) and op(0,part) = STYLE then if op(1,part) = PATCH then ap := cat(ap, ` +face -edge`) elif op(1,part) = LINE or op(1,part) = WIREFRAME then ap := cat(ap, ` -face +edge`) fi elif type(part,function) and op(0,part) = THICKNESS and type(op(1,part),integer) then ap := cat(ap, ` linewidth `, op(1,part)); fi od; if color <> `` then color := cat( op(1..3, map(v -> cat(convert(v,string),` `), color) ) ); ap := cat(ap, `\n material { edgecolor `, color, `\n diffuse `, color, `}\n`); fi; if ap <> `` then ap := cat(` appearance { `, ap, `}`) fi; RETURN(ap); end: [`writeoogl`, `gvplot`];