Rev 18608 | Rev 18615 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
15111 | schaersvoo | 1 | /*27/7/2013 version 0.01 |
7614 | schaersvoo | 2 | "Inspired" by FLY program: http://martin.gleeson.com/fly |
3 | ********************************************************************************* |
||
18552 | bpr | 4 | * J.M. Evers 7/2013 * |
5 | * This is all just amateur scriblings... So no copyrights. * |
||
6 | * This source code file, and compiled objects derived from it, * |
||
7 | * can be used and distributed without restriction, including for commercial use * |
||
8 | * No warrenty whatsoever * |
||
7614 | schaersvoo | 9 | ********************************************************************************* |
10 | */ |
||
18552 | bpr | 11 | #define VERSION "0.5" |
18104 | georgesk | 12 | |
13 | #define _GNU_SOURCE |
||
14 | #include <string.h> |
||
15 | |||
7848 | bpr | 16 | #include "canvasdraw.h" |
15348 | bpr | 17 | void *tmp_buffer; |
18552 | bpr | 18 | FILE *js_include_file; |
7614 | schaersvoo | 19 | /****************************************************************************** |
20 | ** Internal Functions |
||
21 | ******************************************************************************/ |
||
18552 | bpr | 22 | void add_to_buffer(char *tmp); /* add tmp_buffer to the buffer */ |
23 | void sync_input(FILE *infile);/* proceed with inputfile */ |
||
24 | void reset();/* reset some global variables like "use_filled", "use_dashed" */ |
||
25 | int get_token(FILE *infile); /* read next char until EOL*/ |
||
18606 | bpr | 26 | |
18552 | bpr | 27 | int x2px(double x); |
28 | int y2px(double y); |
||
18606 | bpr | 29 | |
18552 | bpr | 30 | double px2x(int x); |
31 | double px2y(int y); |
||
32 | double get_real(FILE *infile,int last); /* read a value; calculation and symbols allowed */ |
||
33 | char *str_replace ( const char *word, const char *sub_word, const char *rep_word ); |
||
34 | char *get_color(FILE *infile,int last); /* read hex-color or colorname -> hex */ |
||
35 | char *get_string(FILE *infile,int last); /* get the string at the end of a command */ |
||
36 | char *get_string_argument(FILE *infile,int last); /* the same, but with "comma" as separator */ |
||
18558 | bpr | 37 | int hypgeodaux(double *q, double* res, int full); |
18552 | bpr | 38 | char *convert_hex2rgb(char *hexcolor); |
39 | void make_js_include(int canvas_root_id); |
||
40 | void check_string_length(int length);/* checks if the length of string argument of command is correct */ |
||
41 | FILE *js_include_file; |
||
42 | FILE *get_file(int *line_number, char **filename); |
||
43 | FILE *infile; /* will be stdin */ |
||
7614 | schaersvoo | 44 | /****************************************************************************** |
45 | ** global |
||
46 | ******************************************************************************/ |
||
47 | int finished = FALSE;/* main variable for signalling the end of the fly-script ; if finished = 1 ; write to stdout or canvasz */ |
||
48 | int line_number = 1;/* used in canvas_error() ; keep track of line number in canvasdraw/fly - script */ |
||
49 | /* set some variables to avoid trouble (NaN) in case of syntax and other usage errors */ |
||
50 | int xsize = 320; |
||
51 | int ysize = 320; |
||
52 | double xmin = 0.0; |
||
53 | double xmax = 320.0; |
||
54 | double ymin = 0.0; |
||
55 | double ymax = 320.0; |
||
11893 | schaersvoo | 56 | double tmax = 0; |
57 | double tmin = 0; |
||
7614 | schaersvoo | 58 | /* flag to indicate parsing of line status */ |
8224 | bpr | 59 | int done = FALSE; |
7614 | schaersvoo | 60 | int type; /* eg command number */ |
15111 | schaersvoo | 61 | int onclick = 0; |
62 | /* |
||
15116 | bpr | 63 | |
64 | 1 = onclick ; |
||
65 | 2 = draggable ; |
||
66 | 3 = click+slideable ; |
||
67 | 4 = slideable without click |
||
15111 | schaersvoo | 68 | 5 = draggable + slideable |
69 | */ |
||
14208 | schaersvoo | 70 | char *slider_type="0"; |
15111 | schaersvoo | 71 | char *my_sliders = "[-1]"; |
72 | int use_slider = -1; |
||
73 | int last_slider = 0; |
||
74 | double double_data[MAX_INT+1]; |
||
75 | int int_data[MAX_INT+1]; |
||
76 | int dragstuff[MAX_DRAGSTUFF]; |
||
77 | int js_function[MAX_JS_FUNCTIONS]; /* javascript functions include objects on demand basis: only once per object type */ |
||
78 | double affine_matrix[] = {1,0,0,1,0,0}; |
||
7785 | schaersvoo | 79 | int use_affine = FALSE; |
7614 | schaersvoo | 80 | int use_rotate = FALSE; |
14078 | bpr | 81 | int use_filled = 0; /* 0:no fill, 1:fill,2=grid?,3=hatch?,4=diamond?,5=dot?,6=image? */ |
82 | int use_dashed = FALSE; /* dashing not natively supported in firefox, for now... */ |
||
15111 | schaersvoo | 83 | double angle = 0.0; |
7614 | schaersvoo | 84 | char buffer[MAX_BUFFER];/* contains js-functions with arguments ... all other basic code is directly printed into js-include file */ |
9329 | schaersvoo | 85 | char *getfile_cmd = ""; |
15111 | schaersvoo | 86 | int reply_format = 0; |
87 | unsigned int canvas_root_id; |
||
88 | char *css_class; |
||
89 | int font_size; |
||
90 | char *draw_type; |
||
91 | int jsplot_cnt = -1; /* keepint track on the curve identity */ |
||
92 | int input_cnt = 0; |
||
93 | int dashtype[2] = { 4 , 4 }; /* just line_px and space_px: may have more arguments...if needed in future */ |
||
94 | char *function_label = "[\"f(x)=\",\"g(x)=\",\"h(x)=\"]"; |
||
95 | int drag_type = -1;/* 0,1,2: xy,x,y */ |
||
96 | int use_offset = 0;/* use_offset only for text shape objects... 0=none;1=yoffset;2=xoffset;3=xyoffset;4=centered*/ |
||
97 | int linegraph_cnt = 0; /* identifier for command 'linegraph' ; multiple line graphs may be plotted in a single plot*/ |
||
98 | int barchart_cnt = 0; /* identifier for command 'barchart' ; multiple charts may be plotted in a single plot*/ |
||
99 | int legend_cnt = -1; /* to allow multiple legends to be used, for multiple piecharts etc */ |
||
100 | int use_axis = FALSE; |
||
101 | int use_axis_numbering = -1; |
||
102 | int no_reset = FALSE; |
||
103 | |||
7614 | schaersvoo | 104 | /****************************************************************************** |
105 | ** Main Program |
||
106 | ******************************************************************************/ |
||
107 | int main(int argc, char *argv[]){ |
||
18552 | bpr | 108 | /* need unique id for every call to canvasdraw: rand(); is too slow...will result in many identical id's */ |
109 | struct timeval tv;struct timezone tz;gettimeofday(&tv, &tz); |
||
110 | canvas_root_id = (unsigned int) tv.tv_usec; |
||
111 | infile = stdin;/* read flyscript via stdin */ |
||
112 | int i,c; |
||
113 | for(i=0;i<MAX_DRAGSTUFF;i++){dragstuff[i] = 0;} |
||
114 | for(i=0;i<MAX_INT;i++){int_data[i]=0;double_data[i]=0;} |
||
115 | int use_snap = 0; /* 0 = none 1=grid: 2=x-grid: 3=y-grid: 4=snap to points */ |
||
116 | int print_drag_params_only_once = FALSE;/* avoid multiple useless identical lines about javascript precision and use_dragdrop */ |
||
18589 | bpr | 117 | int line_width = 2; |
18552 | bpr | 118 | int decimals = 2; |
119 | int use_dragstuff = 0; |
||
120 | int precision = 100; /* 10 = 1;100=2;1000=3 decimal display for mouse coordinates or grid coordinate.May be redefined before every object */ |
||
121 | int use_userdraw = 0; /* 0=none,1=userdraw,2=multidraw flag to indicate user interaction */ |
||
122 | int use_tooltip = -1; /* 1= tooltip 2= popup window*/ |
||
123 | int use_parametric = FALSE;/* will be reset after parametric plotting */ |
||
124 | char *tooltip_text = "Click here"; |
||
125 | char *temp = ""; /* */ |
||
126 | char *bgcolor = "";/* used for background of canvas_div ; default is tranparent */ |
||
127 | char *stroke_color = "255,0,0"; |
||
128 | char *fill_color = "255,255,255"; |
||
129 | char *font_family = "12px Arial"; /* commands xaxistext,yaxistext,legend,text/textup/string/stringup may us this */ |
||
130 | char *font_color = "#00000"; |
||
131 | draw_type = "points"; |
||
132 | char *fly_font = "normal"; |
||
133 | css_class = "none"; |
||
134 | char *flytext = ""; |
||
135 | int canvas_type = DRAG_CANVAS; /* to use a specific canvas for filling etc */ |
||
136 | int pixelsize = 1; |
||
137 | int fill_cnt = 0; |
||
138 | int use_zoom = 0; |
||
139 | font_size = 12;/* this may lead to problems when using something like <code>fontfamily Italic 24px Arial</code> the ''fontsize`` value is not substituted into fontfamily !! */ |
||
140 | int fly_font_size = 12; /*fly_font_size is relative to this... */ |
||
141 | for(i=0;i<MAX_JS_FUNCTIONS;i++){js_function[i]=0;} |
||
142 | int arrow_head = 8; /* size in px needed for arrow based userdraw: "userdraw arrow,color" */ |
||
143 | int crosshair_size = 5; /* size in px*/ |
||
144 | int plot_steps = 250;/* the js-arrays with x_data_points and y_data_points will have size 250 each: use with care !!! use jscurve when precise plots are required */ |
||
145 | int found_size_command = 0; /* 1 = found size ; 2 = found xrange; 3 = found yrange: just to flag an error message */ |
||
146 | int object_cnt = 0; /*counter to identify the "onclick" ojects ; 0 is first object set onclick: reply[object_cnt]=1 when clicked ; otherwise reply[object_cnt]=0 ; object_cnt is only increased when another object is set again */ |
||
147 | int clock_cnt = 0; /* counts the amount of clocks used -> unique object clock%d */ |
||
148 | int boxplot_cnt = 0; |
||
149 | int drawxml_cnt = 0; |
||
150 | int numberline_cnt = 0; |
||
151 | int snap_to_points_cnt = 0; |
||
152 | int reply_precision = 100; /* used for precision of student answers / drawings */ |
||
153 | char *rotation_center = "null";/* needs to be removed... but is used for canvas CTX based rotation*/ |
||
154 | double rotationcenter[] = {0,0}; /* use for recalculating x/y values on rotation() */ |
||
155 | int use_animate = 0; /* used for jscurve / js parametric */ |
||
156 | int use_input_xy = 0; /* 1= input fields 2= textarea 3=calc y value*/ |
||
157 | size_t string_length = 0; /* measure the size of the user input fly-string */ |
||
18609 | bpr | 158 | double stroke_opacity = 0.95; /* use some opacity as default */ |
18552 | bpr | 159 | double fill_opacity = 0.5;/* use some opacity as default */ |
160 | char *URL = "http://localhost/images"; |
||
161 | memset(buffer,'\0',MAX_BUFFER); |
||
162 | void *tmp_buffer = ""; |
||
18555 | bpr | 163 | double res[7]; |
18552 | bpr | 164 | /* default writing a unzipped js-include file into wims getfile directory */ |
165 | char *w_wims_session = getenv("w_wims_session"); |
||
166 | if( w_wims_session == NULL || *w_wims_session == 0 ){canvas_error("Hmmm, your wims environment does not exist...\nCanvasdraw should be used within wims.");} |
||
167 | int L0=strlen(w_wims_session) + 21; |
||
168 | char *getfile_dir = my_newmem(L0); /* create memory to fit string precisely */ |
||
169 | snprintf(getfile_dir,L0, "../sessions/%s/getfile",w_wims_session);/* string will fit precisely */ |
||
170 | mode_t process_mask = umask(0); /* check if file exists */ |
||
171 | int result = mkdir(getfile_dir, S_IRWXU | S_IRWXG | S_IRWXO); |
||
172 | if( result == 0 || errno == EEXIST ){ |
||
173 | umask(process_mask); /* be sure to set correct permission */ |
||
174 | char *w_session = getenv("w_session"); |
||
175 | int L1 = (int) (strlen(w_session)) + find_number_of_digits(canvas_root_id) + 48; |
||
176 | getfile_cmd = my_newmem(L1); /* create memory to fit string precisely */ |
||
177 | snprintf(getfile_cmd,L1,"wims.cgi?session=%s&cmd=getfile&special_parm=%d.js",w_session,canvas_root_id);/* extension ".gz" is MANDATORY for webserver */ |
||
13306 | obado | 178 | /* write the include tag to html page:<script src="wims.cgi?session=%s&cmd=getfile&special_parm=11223344_js"></script> */ |
7614 | schaersvoo | 179 | /* now write file into getfile dir*/ |
14066 | bpr | 180 | char *w_wims_home = getenv("w_wims_home"); /* "/home/users/wims": we need absolute path for location */ |
7614 | schaersvoo | 181 | int L2 = (int) (strlen(w_wims_home)) + (int) (strlen(w_wims_session)) + find_number_of_digits(canvas_root_id) + 23; |
182 | char *location = my_newmem(L2); /* create memory to fit string precisely */ |
||
183 | snprintf(location,L2,"%s/sessions/%s/getfile/%d.js",w_wims_home,w_wims_session,canvas_root_id);/*absolute path */ |
||
184 | js_include_file = fopen(location,"w");/* open the file location for writing */ |
||
14066 | bpr | 185 | /* check on opening...if nogood: mount readonly? disk full? permissions not set correctly? */ |
186 | if(js_include_file == NULL){ canvas_error("SHOULD NOT HAPPEN: could not write to javascript include file...check your system logfiles !" );} |
||
7614 | schaersvoo | 187 | |
188 | /* ----------------------------------------------------- */ |
||
11997 | schaersvoo | 189 | |
18552 | bpr | 190 | /* while more lines to process */ |
7614 | schaersvoo | 191 | |
192 | while(!finished){ |
||
18552 | bpr | 193 | if(line_number>1 && found_size_command == 0 && use_tooltip != 2 ){canvas_error("command \"size xsize,ysize\" needs to come first ! ");} |
194 | type = get_token(infile); |
||
195 | done = FALSE; |
||
196 | /* |
||
197 | @ canvasdraw |
||
198 | @ Canvasdraw will try use the same basic syntax structure as flydraw |
||
18572 | bpr | 199 | @ General syntax <ul><li>The transparency of all objects can be controlled by command <a href="#opacity">opacity [0-255],[0,255]</a></li><li>line width of any object can be controlled by command <a href="#linewidth">linewidth int</a></li><li>any may be dashed by using keyword <a href="#dashed">dashed</a> before the object command.<br> the dashing type can be controled by command <a href="#dashtype">dashtype int,int</a>please note: dashing may have different spacing depending on the angle of the line<br>see https://wimsedu.info/?topic=dashed-arrows-not-dashed-in-canvasdraw</li><li>a fillable object can be set fillable by starting the object command with an ''f`` (like ''frect``,''fcircle``,''ftriangle`` ...) or by using the keyword <a href="#filled">filled</a> before the object command.<br>The fill colour of ''non_userdraw`` objects will be the stroke colour...(flydraw harmonization 19/10/2013)<br> non-solid filling (grid,hatch,diamond,dot,text) is provided using command <a href="#fillpattern">fillpattern a_pattern</a><br>note: do not use a <b>f</b> with this non-solid pattern filling !<br>for <a href="#filltoborder">filltoborder x0,y0,color</a> or <a href="#filltoborder">fill x0,y0,color</a> type filling (eg fill a region around x0,y0 with color until a border is encountered),<br>there are non-solid pattern fill analogues:<ul><li><a href="#gridfill">gridfill x,y,dx,dy,color</a></li><li><a href="#hatchfill">hatchfill x,y,dx,dy,color</a></li><li><a href="#diamondfill">diamondfill x,y,dx,dy,color</a></li><li><a href="#dotfill">dotfill x,y,dx,dy,color</a></li><li><a href="#textfill">textfill x,y,color,sometext_or_char</a></li></ul></li><li>all draggable objects may have a <a href="#slider">slider</a> for translation / rotation; several objects may be translated / rotated by a single slider</li> <li> a draggable object can be set draggable by a preceding command <a href="#drag">drag x/y/xy</a><br>The translation can be read by javascript:read_dragdrop();The replyformat is: object_number : x-orig : y-orig : x-drag : y-drag<br>The x-orig/y-orig will be returned in maximum precision (javascript float)...<br>the x-drag/y-drag will be returned in defined ''precision`` number of decimals<br>Multiple objects may be set draggable / clickable (no limit)<br>not all flydraw objects may be dragged / clicked<br>Only draggable / clickable objects will be scaled on <a href="#zoom">zoom</a> and will be translated in case of panning.</li><li> a ''onclick object`` can be set ''clickable`` by the preceding keyword <a href="#onclick">onclick</a><br>not all flydraw objects can be set clickable</li><li><b>remarks using a '';`` as command separator</b>. Commands with only numeric or colour arguments may be using a '';`` as command separator (instead of a new line). Commands with a string argument may not use a '';`` as command separator !<br>these exceptions are not really straight forward... so keep this in mind.</li><li>almost every <a href="#userdraw">userdraw object,color</a> or <a href="#multidraw">multidraw</a> command ''family`` may be combined with keywords <a href="#snaptogrid">"snaptogrid | xsnaptogrid | ysnaptogrid | snaptofunction</a> or command <code>snaptopoints x1,y1,x2,y2,...</code></li><li>every draggable | onclick object may be combined with keywords <a href="#snaptogrid">snaptogrid | xsnaptogrid | ysnaptogrid | snaptofunction</a> or command <code>snaptopoints x1,y1,x2,y2,...</code></li><li>almost every command for a single object has a multiple objects counterpart:<br><ul>general syntax rule:<li><code>object x1,y1,...,color</code></li><li><code>objects color,x1,y1,...</code></li></ul><li>All inputfields or textareas generated, can be styled individually using command <a href="#css">css some_css</a><br>the fontsize used for labeling these elements can be controlled by command <a href="#fontsize">fontsize int</a> <br>command <code>fontfamily</code> is <b>not</b> active for these elements</li></ul> |
18552 | bpr | 200 | @ If needed multiple interactive scripts (*) may be used in a single webpage.<br>A function <code>read_canvas()</code> and / or <code>read_dragdrop()</code> can read all interactive userdata from these images.<br>The global array <code>canvas_scripts</code>will contain all unique random "canvas_root_id" of the included scripts.<br>The included local javascript "read" functions ''read_canvas%d()`` and ''read_dragdrop%d()`` will have this ''%d = canvas_root_id``<br>e.g. canvas_scripts[0] will be the random id of the first script in the page and will thus provide a function<br><code>fun = eval("read_canvas"+canvas_scripts[0])</code> to read user based drawings / inputfield in this first image.<br>The read_dragdrop is analogue.<br>If the default reply formatting is not suitable, use command <a href='#replyformat'>replyformat</a> to format the replies for an individual canvas script,<br>To read all user interactions from all included canvas scripts, use something like:<br><code>function read_all_canvas_images(){<br> var script_len = canvas_scripts.length;<br> var draw_reply = "";<br> var found_result = false;<br> for(var p = 0 ; p < script_len ; p++){<br> var fun = eval("read_canvas"+canvas_scripts[p]);<br> if( typeof fun === 'function'){<br> var result = fun();<br> if( result && result.length != 0){<br> if(script_len == 1 ){.return result;};<br> found_result = true;<br> draw_reply = draw_reply + result + "newline";<br> };<br> };<br> };<br> if( found_result ){return draw_reply;}else{return null;};<br>};</code> <br>(*) Note: the speed advantage over <em>canvas-do-it-all</em> libraries is reduced to zero, when multiple canvasdraw scripts are present in a single page...<br>For example a typical canvasdraw script is between 5 and 40 kB...a large library like JSXgraph is approx 600 kB<br>In these cases it would be much faster to load a static general HTML5 canvas javascript draw library and parse it multiple raw fly instructions !<br> |
17351 | bpr | 201 | @ Canvasdraw can be used to paint a html5 bitmap image<br>by generating a tailor-made javascript include file: providing only the js-functionality needed to perform the job.<br>thus ensuring a minimal strain on the client browser <br>(unlike some popular ''canvas-do-it-all`` libraries, who have proven to be not suitable for low-end computers found in schools...) |
18552 | bpr | 202 | @ You can check the javascript reply format in the wims tool <a href="http://localhost/wims/wims.cgi?lang=en&module=tool/directexec">direct exec</a> |
203 | @ For usage within OEF (without anstype ''draw``), something like this (a popup function plotter) will work:<br><code>\\text{popup_grapher=wims(exec canvasdraw <br>popup<br>size 400,400<br>xrange -10,10<br>yrange -10,10<br>axis<br>axisnumbering<br>opacity 100,100<br>grid 2,2,grey,2,2,6,black<br>snaptogrid<br>linewidth 2<br>jsplot red,5*sin(1/x)<br>strokecolor green<br>functionlabel f(x)=<br>userinput function<br>mouse blue,22<br>)<br>}<br>\\statement{<br>\\popup_grapher<br>}</code>. |
||
204 | @ Be aware that older browsers will probably not work correctly<br>no effort has been undertaken to add glue code for older browsers !! <br>in any case it is not wise to use older browsers...not just for canvasdraw. |
||
205 | @ Be aware that combining several different objects and interactivity may lead to problems. |
||
206 | @ If you find flaws, errors or other incompatibilities -not those mentioned in this document- send <a href='mailto:jm.evers-at-schaersvoorde.nl'>me</a> an email with screenshots and the generated javascript include file. |
||
207 | @ There is limited support for touch devices: touchstart, touchmove and touchend in commands <a href="#userdraw">userdraw primitives </a>, <a href="#multidraw">multidraw primitives </a>, <a href="#protractor">protractor</a>, <a href="#ruler">ruler</a> and probably a few others... <br>Only single finger gestures are supported (for now).<br>The use of a special pen is advised for interactive drawing on touch devices.<br>For more accurate user-interaction (numeric, eg keyboard driven drawings) with canvasdraw on touch devices: use the command family <a href="#userinput_xy">userinput</a>. |
||
208 | */ |
||
209 | switch(type){ |
||
210 | case END:finished = 1;done = TRUE;break; |
||
211 | case 0:sync_input(infile);break; |
||
212 | case AFFINE: |
||
213 | /* |
||
18556 | bpr | 214 | @ affine a,b,c,d,tx,ty |
215 | @ defines a transformation matrix for subsequent objects |
||
216 | @ use keyword <a href='#killaffine'>killaffine</a> to end the transformation...the next objects will be drawn in the original x/y-range |
||
217 | @ a: Scales the drawings horizontally |
||
218 | @ b: Skews the drawings horizontally |
||
219 | @ c: Skews the drawings vertically |
||
220 | @ d: Scales the drawings vertically |
||
221 | @ tx: Moves the drawings horizontally in xrange coordinate system |
||
222 | @ ty: Moves the drawings vertically in yrange coordinate system |
||
223 | @ the data precision may be set by preceding command ''precision int`` |
||
224 | @ <b>note</b>: not all affine operations on canvasdraw objects will be identical to flydraw's behaviour. Make sure to check ! |
||
225 | @%affine%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%#use larger linewith to improve selecting a draggable object !%linewidth 4%drag xy%frect 0,5,3,3,red%affine cos(pi/4),sin(pi/4),-cos(pi/2),sin(pi/2),-5,-5%drag xy%frect 0,5,3,3,red |
||
226 | @%affine+latex%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%strokecolor blue%fontfamily 42px Arial%centered%drag xy%latex 5,5,\\frac{123}{\\pi^{234}}%affine cos(pi/4),sin(pi/4),-cos(pi/2),sin(pi/2),-5,-5%drag xy%latex 5,5,\\frac{123}{\\pi^{234}} |
||
18552 | bpr | 227 | */ |
228 | for(i = 0 ; i<6;i++){ |
||
229 | switch(i){ |
||
230 | case 0: affine_matrix[0] = get_real(infile,0);break; |
||
231 | case 1: affine_matrix[1] = get_real(infile,0);break; |
||
232 | case 2: affine_matrix[2] = get_real(infile,0);break; |
||
233 | case 3: affine_matrix[3] = get_real(infile,0);break; |
||
234 | case 4: affine_matrix[4] = get_real(infile,0);break; |
||
235 | case 5: affine_matrix[5] = get_real(infile,1); |
||
236 | use_affine = TRUE; |
||
237 | break; |
||
238 | default: break; |
||
239 | } |
||
240 | } |
||
241 | break; |
||
14394 | schaersvoo | 242 | case ALLOW_DUPLICATES: |
18556 | bpr | 243 | /* |
244 | @ duplicates || allowdups |
||
245 | @ keyword (no arguments) |
||
246 | @ only useful in case of a <a href="#multidraw">multidraw</a> student reply. |
||
247 | @ only useful in default <a href="#replyformat">replyformat</a> (eg in case of a not specified replyformat). |
||
248 | @ if set, duplicate (x:y) coordinates will not be removed from the student reply. |
||
249 | @ technical: a javascript variable "allow_duplicate_answer = 1;" is declared. |
||
250 | @ default for command multidraw is: removal of duplicates. |
||
251 | */ |
||
18552 | bpr | 252 | fprintf(js_include_file,"var allow_duplicate_answers = 1;"); |
253 | break; |
||
254 | case ANGLE: |
||
18556 | bpr | 255 | /* |
256 | @ angle xc,yc,width,start_angle,end_angle,color |
||
257 | @ width is in x-range |
||
258 | @ angles are in degrees |
||
259 | @ not compatible with ''flydraw`` |
||
260 | @ will zoom in/out |
||
261 | @ may be set onclick or drag&drop |
||
262 | @ if angle size is controlled by command <a href='#slider'>slider</a>, use radians to set limits of slider |
||
263 | @ ''angle`` and <a href="#arc">arc</a> are exceptions in case of sliders...they are always active (e.g. not click-activated) |
||
264 | @%angle%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%angle 0,0,4,10,135,blue |
||
265 | @%angle_slider%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%strokecolor blue%slider -2*pi,2*pi,260,28,angle active degree,blue arrow%arrow 0,0,8,0,8,blue%fillpattern diamond%angle 0,0,2,0,0,blue%killslider%strokecolor red%slider -2*pi,2*pi,260,28,angle active radian,red arrow%arrow 0,1,8,1,8,red%fillpattern dot%angle 0,1,2,0,0,red |
||
266 | */ |
||
18552 | bpr | 267 | for(i=0;i<7;i++){ |
268 | switch(i){ |
||
269 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
270 | case 1:double_data[1] = get_real(infile,0); |
||
271 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
272 | if(use_affine == TRUE ){ transform(2,2);} |
||
273 | break; /* y-values */ |
||
274 | case 2:double_data[2] = get_real(infile,0);break; /* width x-range ! */ |
||
275 | case 3:double_data[3] = 0.0174532925*(get_real(infile,0) - angle);break; /* start angle in degrees -> radians */ |
||
276 | case 4:double_data[4] = 0.0174532925*(get_real(infile,0) - angle);break; /* end angle in degrees -> radians */ |
||
277 | case 5:stroke_color = get_color(infile,1);/* name or hex color */ |
||
278 | if( use_slider != -1 ){ onclick = 3; }/* always active in case of slider */ |
||
279 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 280 | tmp_buffer=my_newmem(MAX_BUFFER); |
281 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,17,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 282 | add_to_buffer(tmp_buffer); |
283 | dragstuff[17] = 1; |
||
284 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
285 | if(onclick != 0){object_cnt++;}/* object_cnt++;*/ |
||
286 | break; |
||
287 | } |
||
288 | } |
||
289 | break; |
||
290 | case ANIMATE: |
||
291 | /* |
||
18556 | bpr | 292 | @ animate |
293 | @ keyword |
||
294 | @ if set, it will animate a point on a curve |
||
295 | @ all other canvas object or group of objects (like lines,circles,rects,points...images,svg,latex,mathml etc)<br>may be animated using command <a href='#slider'>slider</a> with keyword 'anim' |
||
296 | @ the animated point is a filled rectangle ; adjust colour with command <code>fillcolor colorname/hexnumber</code> |
||
297 | @ use linewidth to adjust size of the points |
||
298 | @ will animate a point on -only- the next <a href='#jsplot'>jsplot/jscurve command</a>. Only a single call to <code>animate</code> is allowed...in case of multiple <code>animate</code> keywords, only the last one is valid |
||
299 | @ only usable in combination with command <a href='#jsplot'>jsplot</a> (normal functions or parametric) |
||
300 | @ moves repeatedly from <a href='#xrange'>xmin to xmax</a> or in case of a parametric function from <a href='#trange'>tmin to tmax</a> |
||
301 | @ use commands <a href='#multilinewidth'>multilinewidth</a>, <a href='#multistrokecolor'>multistrokecolor</a> etc in case of multiple animated functions.<br>use multiple functions as argument in a single call to <a href='#jsplot'>jsplot color,fun1,fun2,fun3...fun_n</a> |
||
302 | @%animate_1%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%fillcolor red%animate%trange -2*pi,2*pi%linewidth 1%opacity 255,50%canvastype 100%fill 1.2,1.2,red%canvastype 101%fill -1.2,-1.2,blue%jsplot blue,7*cos(x),5*sin(2*x) |
||
303 | @%animate_2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%fillcolor red%animate%trange -2*pi,2*pi%linewidth 1%opacity 255,50%canvastype 100%fill 1.2,1.2,red%canvastype 101%fill -1.2,-1.2,blue%multistrokecolors blue,blue,green,green,orange,orange%multilinewidth 2,2,3,3,1,1%jsplot blue,7*cos(x),5*sin(2*x),9*sin(x),5*cos(x),x^2,x |
||
18552 | bpr | 304 | */ |
305 | use_animate++; |
||
306 | if( use_animate == 1 ){ |
||
307 | fprintf(js_include_file,"\nvar trace_canvas = create_canvas%d(%d,xsize,ysize);\ |
||
308 | var trace_ctx = trace_canvas.getContext('2d');\ |
||
309 | trace_ctx.fillStyle = 'rgba(%s,%f)';\ |
||
310 | trace_ctx.strokeStyle = 'rgba(%s,%f)';\ |
||
311 | trace_ctx.lineWidth = %d;var anim_pos = 0;\n\ |
||
312 | function animate_this(){\ |
||
313 | var sync;\ |
||
314 | var synchrone = Math.floor(animation_steps/animation_funs);\ |
||
315 | trace_ctx.clearRect(0,0,xsize,ysize);\ |
||
316 | for(var p=0; p<animation_funs;p++){\ |
||
317 | sync = p*synchrone;\ |
||
318 | trace_ctx.fillRect(x_anim_points[sync+anim_pos]-%d, y_anim_points[sync+anim_pos]-%d,%d,%d);\ |
||
319 | };\ |
||
320 | setTimeout(function(){\ |
||
321 | requestAnimationFrame(animate_this); anim_pos++;}, 50\ |
||
322 | );\ |
||
323 | if(anim_pos >= animation_steps){anim_pos = 0;};\ |
||
324 | };",canvas_root_id,ANIMATE_CANVAS,fill_color,fill_opacity,stroke_color,stroke_opacity,line_width,line_width,line_width,2*line_width,2*line_width); |
||
325 | } else { |
||
326 | canvas_error("animate can only be used once<br>multiple curves may be animated using something like:<br>jsplot red,sin(x),cos(x),x^2,sin(2*x)"); |
||
327 | } |
||
328 | break; |
||
329 | case ARC: |
||
330 | /* |
||
18556 | bpr | 331 | @ arc xc,yc,x-width,y-height,start_angle,end_angle,color |
332 | @ may be set ''onclick`` or ''drag xy`` |
||
333 | @ compatible with ''flydraw`` |
||
334 | @ attention: width & height in x/y-range |
||
335 | @ for arrow hats on an arc, see command <a href='#arcarrow'>arcarrow or arrowarc</a> |
||
336 | @ better use command <a href='#angle'>angle</a> for use with a <a href='#slider'>slider</a> |
||
337 | @%arc%size 400,400%xrange -10,10%yrange -10,10%arc 0,0,4,4,10,135,red |
||
338 | @%arc_filled%size 400,400%xrange -10,10%yrange -10,10%opacity 255,60%filled%fillcolor green%arc 0,0,4,4,10,135,red |
||
18552 | bpr | 339 | */ |
340 | for(i=0;i<7;i++){ |
||
341 | switch(i){ |
||
342 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
343 | case 1:double_data[1] = get_real(infile,0); |
||
344 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
345 | if(use_affine == TRUE ){ transform(4,2);} |
||
346 | break; /* y-values */ |
||
347 | case 2:double_data[2] = get_real(infile,0);break; /* width x-range no pixels ! */ |
||
348 | case 3:double_data[3] = get_real(infile,0); |
||
349 | break; /* height y-range no pixels ! */ |
||
350 | case 4:double_data[4] = get_real(infile,0) - angle ;break; /* start angle in degrees */ |
||
351 | case 5:double_data[5] = get_real(infile,0) - angle;break; /* end angle in degrees */ |
||
352 | case 6:stroke_color = get_color(infile,1);/* name or hex color */ |
||
353 | /* in Shape library: |
||
354 | x[0] = x[1] = xc = double_data[0] |
||
355 | y[0] = y[1] = yc = double_data[1] |
||
356 | w[0] = width = double_data[2] |
||
357 | w[1] = height = double_data[3] |
||
358 | h[0] = start_angle = double_data[4] |
||
359 | h[1] = end_angle = double_data[5] |
||
360 | */ |
||
18555 | bpr | 361 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
362 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 363 | |
364 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
365 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18555 | bpr | 366 | add_to_buffer(tmp_buffer);reset(); |
367 | dragstuff[12] = 1; |
||
368 | if(onclick != 0){object_cnt++;} |
||
369 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
18552 | bpr | 370 | break; |
371 | } |
||
372 | } |
||
373 | break; |
||
374 | case ARCARROW: |
||
375 | /* |
||
18556 | bpr | 376 | @ arrowarc xc,yc,x-width,y-height,start_angle,end_angle,color,type |
377 | @ alternative: arcarrow |
||
378 | @ uses same syntax as <a href='#arc'>arc</a> |
||
379 | @ for arrow hat: type = 1 : right<br>type = 2 : left<br>type = 3 : left&right |
||
380 | @ if the default arrow hat/head is not satisfactory , the size of the arrow may be set with command <a href='#arrowhead'>arrowhead</a> |
||
381 | @ no other arrow types are implemented...yet |
||
382 | @ may be set draggable or onclick |
||
383 | @ attention: when width ad height are very different, the arrow hat is not drawn correctly. This is a flaw and not a feature...(for now: too much calculations to correct) |
||
384 | @%arcarrow%size 400,400%xrange -10,10%yrange -10,10%noreset%onclick%arcarrow 0,0,7,7,50,275,blue,3%arcarrow 0,0,8,8,50,275,red,2%arcarrow 0,0,9,9,50,275,green,1 |
||
18552 | bpr | 385 | */ |
386 | for(i=0;i<8;i++){ |
||
387 | switch(i){ |
||
388 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
389 | case 1:double_data[1] = get_real(infile,0); |
||
390 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
391 | if(use_affine == TRUE ){ transform(4,2);} |
||
392 | break; /* y-values */ |
||
393 | case 2:double_data[2] = get_real(infile,0);break; /* width x-range no pixels ! */ |
||
394 | case 3:double_data[3] = get_real(infile,0); |
||
395 | break; /* height y-range no pixels ! */ |
||
396 | case 4:double_data[4] = get_real(infile,0) - angle ;break; /* start angle in degrees */ |
||
397 | case 5:double_data[5] = get_real(infile,0) - angle;break; /* end angle in degrees */ |
||
398 | case 6:stroke_color = get_color(infile,0);/* name or hex color */ |
||
399 | break; |
||
400 | case 7:int_data[0] = (int) get_real(infile,1); |
||
401 | switch(int_data[0]){ |
||
402 | case 1: int_data[1] = 24;break; /* right */ |
||
403 | case 2: int_data[1] = 25;break; /* left */ |
||
404 | case 3: int_data[1] = 26;break; /* left&right */ |
||
405 | default:int_data[1] = 24;break; |
||
406 | } |
||
407 | if(int_data[0] == 1 ){int_data[1] = 24;} |
||
408 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
409 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 410 | |
411 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
412 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"var arrow_head = %d;dragstuff.addShape(new Shape(%d,%d,%d,%d,%d,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",arrow_head,drag_type,object_cnt,onclick,use_snap,int_data[1],decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 413 | add_to_buffer(tmp_buffer); |
414 | dragstuff[int_data[1]] = 1; |
||
415 | if(onclick != 0){object_cnt++;} |
||
416 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
417 | js_function[JS_ARROWHEAD] = 1; |
||
418 | reset(); |
||
419 | } |
||
420 | } |
||
421 | break; |
||
422 | case ARROW: |
||
423 | /* |
||
424 | @ arrow x1,y1,x2,y2,h,color |
||
425 | @ alternative: vector |
||
426 | @ draw a single headed arrow / vector from (x1:y1) to (x2:y2)<br>with arrowhead size h in px and in color ''color`` |
||
427 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
428 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
429 | @%arrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%arrow 0,0,4,3,8,blue%drag xy%arrow 0,0,-4,3,8,green%drag xy%arrow 0,0,4,-3,8,orange%drag xy%arrow 0,0,-4,-3,8,cyan |
||
430 | @%arrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%arrow 0,0,4,4,8,blue%onclick%arrow 0,0,-4,5,8,green%onclick%arrow 0,0,4,-6,8,orange%onclick%arrow 0,0,-4,-2,8,cyan |
||
431 | */ |
||
432 | for(i=0;i<6;i++){ |
||
433 | switch(i){ |
||
434 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
435 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
436 | case 2: double_data[2] = get_real(infile,0);break; /* x */ |
||
437 | case 3: double_data[3] = get_real(infile,0);break; /* y */ |
||
438 | case 4: arrow_head = (int) get_real(infile,0);break;/* h */ |
||
439 | case 5: stroke_color = get_color(infile,1);/* name or hex color */ |
||
440 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
441 | if(use_affine == TRUE ){ transform(4,2);} |
||
442 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
443 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 444 | |
445 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
446 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,8,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 447 | if(onclick != 0){object_cnt++;} |
448 | /* object_cnt++;*/ |
||
449 | add_to_buffer(tmp_buffer);reset(); |
||
450 | dragstuff[8] = 1; |
||
451 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
452 | break; |
||
453 | } |
||
454 | } |
||
455 | break; |
||
456 | case ARROWS: |
||
457 | /* |
||
458 | @ arrows color,head (px),x1,y1,x2,y2...x_n,y_n |
||
459 | @ alternative: vectors |
||
460 | @ draw single headed arrows / vectors from (x1:y1) to (x2:y2) ... (x3:y3) to (x4:y4) etc ... in color 'color' |
||
461 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
462 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
463 | @%arrows_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2% |
||
464 | @%arrows_drag%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2% |
||
465 | @%arrows_drag_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%# Click arrow(s) to activate %slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2% |
||
466 | */ |
||
467 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
468 | fill_color = stroke_color; |
||
469 | arrow_head = (int) get_real(infile,0);/* h */ |
||
470 | i=0; |
||
471 | while( ! done ){ /* get next item until EOL*/ |
||
472 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
473 | if(i%2 == 0 ){ |
||
474 | double_data[i] = get_real(infile,0); /* x */ |
||
475 | } else { |
||
476 | double_data[i] = get_real(infile,1); /* y */ |
||
477 | } |
||
478 | i++; |
||
479 | } |
||
480 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
481 | if( use_affine == TRUE ){ transform(i-1,2);} |
||
482 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
483 | decimals = find_number_of_digits(precision); |
||
484 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18557 | bpr | 485 | tmp_buffer=my_newmem(MAX_BUFFER); |
486 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,8,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 487 | add_to_buffer(tmp_buffer); |
488 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
489 | } |
||
490 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
491 | dragstuff[8] = 1; |
||
492 | reset(); |
||
493 | break; |
||
494 | case ARROW2: |
||
495 | /* |
||
496 | @ arrow2 x1,y1,x2,y2,h,color |
||
497 | @ draw a double headed arrow/vector from (x1:y1) to (x2:y2)<br>with arrowhead size h in px and in color ''color`` |
||
498 | @ use command <code>arrowhead int</code> to adjust the arrow head size |
||
499 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
500 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
501 | @%arrow2%size 400,400%xrange -10,10%yrange -10,10%drag xy%arrow2 0,0,4,3,8,blue% |
||
502 | */ |
||
503 | for(i=0;i<6;i++){ |
||
504 | switch(i){ |
||
505 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
506 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
507 | case 2: double_data[2] = get_real(infile,0);break; /* x */ |
||
508 | case 3: double_data[3] = get_real(infile,0);break; /* y */ |
||
509 | case 4: arrow_head = (int) get_real(infile,0);break;/* h */ |
||
510 | case 5: stroke_color = get_color(infile,1);/* name or hex color */ |
||
511 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
512 | if( use_affine == 1 ){ transform(4,2);} |
||
513 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
514 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 515 | tmp_buffer=my_newmem(MAX_BUFFER); |
516 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,10,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 517 | add_to_buffer(tmp_buffer); |
518 | if(onclick != 0){object_cnt++;}/* object_cnt++;*/ |
||
519 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
520 | dragstuff[10] = 1; |
||
521 | reset(); |
||
522 | break; |
||
523 | } |
||
524 | } |
||
525 | break; |
||
526 | case ARROWS2: |
||
527 | /* |
||
528 | @ arrows2 color,head (px),x1,y1,x2,y2...x_n,y_n |
||
529 | @ draw double headed arrows / vectors from (x1:y1) to (x2:y2) ... (x3:y3) to (x4:y4) etc ... in color ''color`` |
||
530 | @ use command <code>linewidth int</code> to adjust thickness of the arrows |
||
531 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
532 | @%arrows2%size 400,400%xrange -10,10%yrange -10,10%onclick%arrows2 red,8,0,0,4,3,1,1,2,4,2,2,-2,4,3,3,-3,-4,0,0,3,-2% |
||
533 | */ |
||
534 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
535 | fill_color = stroke_color; |
||
536 | arrow_head = (int) get_real(infile,0);/* h */ |
||
537 | i=0; |
||
538 | while( ! done ){ /* get next item until EOL*/ |
||
539 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
540 | if(i%2 == 0 ){ |
||
541 | double_data[i] = get_real(infile,0); /* x */ |
||
542 | } else { |
||
543 | double_data[i] = get_real(infile,1); /* y */ |
||
544 | } |
||
545 | i++; |
||
546 | } |
||
547 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
548 | if( use_affine == 1 ){ transform(i-1,2);} |
||
549 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
8386 | schaersvoo | 550 | |
18552 | bpr | 551 | decimals = find_number_of_digits(precision); |
552 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18557 | bpr | 553 | tmp_buffer=my_newmem(MAX_BUFFER); |
554 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,10,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 555 | add_to_buffer(tmp_buffer); |
556 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
557 | } |
||
558 | dragstuff[10] = 1; |
||
559 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
560 | reset(); |
||
561 | break; |
||
562 | case ARROWHEAD: |
||
563 | /* |
||
564 | @ arrowhead int |
||
565 | @ default 8 (pixels) |
||
566 | */ |
||
567 | arrow_head = (int) (get_real(infile,1)); |
||
568 | break; |
||
569 | case AUDIO: |
||
570 | /* |
||
571 | @ audio x,y,w,h,loop,visible,audiofile location |
||
572 | @ x,y: left top corner of audio element (in xrange / yrange) |
||
573 | @ w,y: width and height in pixels |
||
574 | @ loop: 0 or 1 ( 1 = loop audio fragment) |
||
575 | @ visible: 0 or 1 (1 = show controls) |
||
576 | @ audio format may be in *.mp3 or *.ogg |
||
577 | @ If you are using *.mp3: be aware that FireFox will not (never) play this ! (Pattented format) |
||
578 | @ if you are using *.ogg: be aware that Microsoft based systems not support it natively |
||
579 | @ To avoid problems supply both types (mp3 and ogg) of audiofiles.<br>the program will use both as source tag |
||
580 | */ |
||
581 | js_function[DRAW_AUDIO] = 1; |
||
582 | for(i=0;i<7;i++){ |
||
583 | switch(i){ |
||
584 | case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x in x/y-range coord system -> pixel */ |
||
585 | case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y in x/y-range coord system -> pixel */ |
||
586 | case 2: int_data[2] = (int) (get_real(infile,0)); break; /* pixel width */ |
||
587 | case 3: int_data[3] = (int) (get_real(infile,0)); break; /* height pixel height */ |
||
588 | case 4: int_data[4] = (int) (get_real(infile,0)); if(int_data[4] != TRUE){int_data[4] = FALSE;} break; /* loop boolean */ |
||
589 | case 5: int_data[5] = (int) (get_real(infile,0)); if(int_data[5] != TRUE){int_data[5] = FALSE;} break; /* visible boolean */ |
||
590 | case 6: |
||
591 | temp = get_string(infile,1); |
||
592 | if( strstr(temp,".mp3") != 0 ){ temp = str_replace(temp,".mp3","");} |
||
593 | if( strstr(temp,".ogg") != 0 ){ temp = str_replace(temp,".ogg","");} |
||
18557 | bpr | 594 | tmp_buffer=my_newmem(MAX_BUFFER); |
595 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_audio(%d,%d,%d,%d,%d,%d,%d,\"%s.ogg\",\"%s.mp3\");\n", canvas_root_id, int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],temp,temp)); |
||
18552 | bpr | 596 | add_to_buffer(tmp_buffer); |
597 | break; |
||
598 | default:break; |
||
599 | } |
||
600 | } |
||
601 | reset(); |
||
602 | break; |
||
603 | case AXIS_NUMBERING: |
||
604 | /* |
||
18556 | bpr | 605 | @ axisnumbering |
606 | @ keyword (no arguments required) |
||
607 | @ for special numbering of x-axis or y-axis see grid related commands <a href="#axis">axis</a> <a href="#xaxis">xaxis</a>, <a href="#xaxisup">xaxisup</a>, <a href="#noxaxis">noxaxis</a>, <a href="#yaxis">yaxis</a>, <a href="#yaxisup">yaxisup</a>, <a href="#noyaxis">noyaxis</a> |
||
608 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
18552 | bpr | 609 | */ |
610 | use_axis_numbering++; |
||
611 | break; |
||
612 | case AXIS: |
||
613 | /* |
||
18556 | bpr | 614 | @ axis |
615 | @ keyword (no arguments required) |
||
616 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
8386 | schaersvoo | 617 | |
18552 | bpr | 618 | */ |
619 | use_axis = TRUE; |
||
620 | break; |
||
621 | case BARCHART: |
||
622 | /* |
||
623 | @ barchart x_1:y_1:color_1:x_2:y_2:color_2:...x_n:y_n:color_n |
||
624 | @ may <b>only</b> to be used together with command <a href='#grid'>grid</a> |
||
625 | @ can be used together with freestyle x-axis/y-axis texts: see commands <a href='#xaxis'>xaxis</a>,<a href='#xaxisup'>xaxisup</a> and <a href='#yaxis'>yaxis</a> |
||
626 | @ use command <a href='#legend'>legend</a> to provide an optional legend in right-top-corner |
||
627 | @ multiple barchart command may be used in a single script |
||
628 | @ also see command <a href='#piechart'>piechart</a> |
||
629 | @ note: your arguments are not checked by canvasdraw: use your javascript console in case of trouble... |
||
630 | @%barchart%size 400,400%xrange -1,10%yrange -2,14%legend legend Z:legend A:this is B:C:D:E:F:G:H:X%legendcolors green:red:orange:lightblue:cyan:gold:purple:darkred:yellow:lightgreen%xaxis 0:Z:1:A:2:B:3:C:4:D:5:E:6:F:7:G:8:H:9:X%noyaxis%precision 1%fontfamily bold 15px Arial%grid 1,1,white%barchart 0:5.5:green:2:5.5:red:4:6.5:orange:6:8:lightblue:8:11:cyan:1:5.5:gold:3:9:purple:5:4:darkred:7:7:yellow:9:1:lightgreen%mouse red,14 |
||
631 | */ |
||
632 | temp = get_string(infile,1); |
||
633 | if( strstr( temp,":" ) != 0 ){ temp = str_replace(temp,":","\",\""); } |
||
634 | fprintf(js_include_file,"var barchart_%d = [\"%s\"];",barchart_cnt,temp); |
||
635 | barchart_cnt++; |
||
636 | reset(); |
||
637 | break; |
||
638 | case BEZIER: |
||
639 | /* |
||
640 | @ bezier color,x_start,y_start,x_first,y_first,x_second,y_second,x_end,y_end |
||
641 | @ draw a bezier curve between points, starting from (x_start:y_start) |
||
642 | @ can <b>not</b> be dragged or set onclick |
||
643 | */ |
||
644 | js_function[DRAW_BEZIER] = 1; |
||
645 | decimals = find_number_of_digits(precision); |
||
646 | for(i = 0 ; i < 9; i++){ |
||
647 | switch(i){ |
||
648 | case 0: stroke_color = get_color(infile,0);break; |
||
649 | case 1: double_data[0] = get_real(infile,0);break;/* start x */ |
||
650 | case 2: double_data[1] = get_real(infile,0);break;/* start y */ |
||
651 | case 3: double_data[2] = get_real(infile,0);break;/*The x-coordinate of the first Bézier control point */ |
||
652 | case 4: double_data[3] = get_real(infile,0);break;/*The y-coordinate of the first Bézier control point */ |
||
653 | case 5: double_data[4] = get_real(infile,0);break;/*The x-coordinate of the second Bézier control point */ |
||
654 | case 6: double_data[5] = get_real(infile,0);break;/*The y-coordinate of the second Bézier control point */ |
||
655 | case 7: double_data[6] = get_real(infile,0);break;/*The x-coordinate of the Bézier end point */ |
||
656 | case 8: double_data[7] = get_real(infile,1);/*The y-coordinate of the Bézier end point */ |
||
657 | if(use_rotate == TRUE ){rotate(8,angle,rotationcenter,2);} |
||
658 | if(use_affine == TRUE ){ transform(2,5);} |
||
18557 | bpr | 659 | tmp_buffer=my_newmem(MAX_BUFFER); |
660 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"draw_bezier(%d,%d,[%f,%f,%f,%f,%f,%f,%f,%f],\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.2f);",STATIC_CANVAS,line_width,double_data[0],double_data[1],double_data[2],double_data[3],double_data[4],double_data[5],double_data[6],double_data[7],fill_color,fill_opacity,stroke_color,stroke_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle)); |
||
18552 | bpr | 661 | add_to_buffer(tmp_buffer); |
662 | break; |
||
663 | default: break; |
||
664 | } |
||
665 | } |
||
666 | reset(); |
||
667 | break; |
||
668 | case BGCOLOR: |
||
669 | /* |
||
18556 | bpr | 670 | @ bgcolor colorname or #hex |
671 | @ use this color as background of the "div" containing the canvas(es) |
||
672 | @%bgcolor%size 400,400%xrange -10,10%yrange -10,10%bgcolor lightblue |
||
18552 | bpr | 673 | */ |
674 | /* [255,255,255]*/ |
||
675 | bgcolor = get_string(infile,1); |
||
676 | if(strstr(bgcolor,"#") == NULL){ /* convert colorname -> #ff00ff */ |
||
677 | int found = 0; |
||
678 | for( i = 0; i < NUMBER_OF_COLORNAMES ; i++ ){ |
||
679 | if( strcmp( colors[i].name , bgcolor ) == 0 ){ |
||
680 | bgcolor = colors[i].hex; |
||
681 | found = 1; |
||
682 | break; |
||
683 | } |
||
684 | } |
||
685 | if(found == 0){canvas_error("your bgcolor is not in my rgb.txt data list: use hexcolor...something like #a0ffc4");} |
||
686 | } |
||
687 | fprintf(js_include_file,"/* set background color of canvas div */\ncanvas_div.style.backgroundColor = \"%s\";canvas_div.style.opacity = %f;\n",bgcolor,fill_opacity); |
||
688 | break; |
||
689 | case BGIMAGE: |
||
690 | /* |
||
18556 | bpr | 691 | @ bgimage image_location |
692 | @ use an image as background; technical: we use the background of ''canvas_div`` |
||
693 | @ the background image will be resized to match "width = xsize" and "height = ysize" |
||
694 | @%bgimage%size 400,400%xrange -10,10%yrange -10,10%bgimage https://wims.unice.fr/wims/gifs/en.gif |
||
18552 | bpr | 695 | */ |
696 | URL = get_string(infile,1); |
||
697 | fprintf(js_include_file,"/* set background image to canvas div */\ncanvas_div.style.backgroundImage = \"url(%s)\";canvas_div.style.backgroundSize = \"%dpx %dpx\";\n",URL,xsize,ysize); |
||
698 | break; |
||
699 | case BLINK: |
||
700 | /* |
||
18556 | bpr | 701 | @ blink time(seconds) |
702 | @ NOT IMPLEMETED -YET |
||
18552 | bpr | 703 | */ |
704 | break; |
||
705 | case BOXPLOT: |
||
706 | /* |
||
707 | @ boxplot x_or_y,box-height_or_box-width,position,min,Q1,median,Q3,max |
||
708 | @ example:<br><code>xrange 0,300<br>yrange 0,10<br>boxplot x,4,8,120,160,170,220,245</code><br>meaning: create a boxplot in x-direction, with height 4 (in yrange) and centered around line y=8 |
||
709 | @ example:<br><code>xrange 0,10<br>yrange 0,300<br>boxplot y,4,8,120,160,170,220,245</code><br>meaning: create a boxplot in y-direction, with width 4 (in xrange) and centered around line x=8 |
||
710 | @ use command <a href='#filled'>filled</a> to fill the box<br><b>note:</b> the strokecolor is used for filling Q1, the fillcolor is used for filling Q3 |
||
711 | @ use command <a href='#fillpattern'>fillpattern some_pattern</a> to use a (diamond for Q1, hatch for Q3) pattern. |
||
712 | @ use command <a href='#opacity'>opacity</a> to adjust fill_opacity of stroke and fill colours |
||
713 | @ use command <a href='#legend'>legend</a> to automatically create a legend <br>unicode allowed in legend<br>use command <a href='#fontfamily'>fontfamily</a> to set the font of the legend. |
||
714 | @ there is no limit to the number of boxplots used. |
||
715 | @ can <b>not</b> be set draggable and <a href='#onclick'>onclick</a> is not ready yet |
||
716 | @ use keyword <a href="#userboxplot">userboxplot</a> before command boxplot, if a pupil must draw a boxplot (using his own min,Q1,median,Q3,max data) |
||
717 | @ use keyword <a href="#userboxplotdata">userboxplotdata</a> before command boxplot, if a pupil must generate the data by some means. |
||
718 | @ use command <a href="#boxplotdata">boxplotdata</a> when the boxplot should be drawn from wims-generated raw statistical date |
||
719 | @%boxplot_1%size 400,400%xrange 0,300%yrange 0,10%opacity 120,50%filled%fillcolor orange%strokecolor blue%linewidth 2%boxplot x,4,8,120,160,170,220,245 |
||
720 | @%boxplot_2%size 400,400%xrange 0,10%yrange 0,300%opacity 120,50%filled%fillcolor orange%strokecolor blue%linewidth 2%boxplot y,4,8,120,160,170,220,245 |
||
721 | @%boxplot_3%size 400,400%xrange 0,100%yrange 0,10%fillpattern hatch%linewidth 3%fillcolor red%strokecolor green%boxplot x,1,2,4,14,27,39,66%strokecolor blue%boxplot x,1,4,15,45,50,66,87%strokecolor red%boxplot x,1,6,45,70,80,90,100%strokecolor orange%boxplot x,1,8,28,38,48,56,77%mouse red,16 |
||
722 | */ |
||
723 | js_function[DRAW_BOXPLOT] = 1; |
||
724 | for(i=0;i<8;i++){ |
||
725 | switch(i){ |
||
726 | case 0: temp = get_string_argument(infile,0); |
||
727 | if( strstr(temp,"x") != 0){int_data[0] = 1;}else{int_data[0] = 0;} break; /* x or y */ |
||
728 | case 1: double_data[0] = get_real(infile,0);break;/* height | width */ |
||
729 | case 2: |
||
730 | if( js_function[DRAW_JSBOXPLOT] == 0 ){ |
||
731 | double_data[1] = get_real(infile,0); |
||
732 | fprintf(js_include_file,"var boxplot_source = 0;\n");/* we use given min,Q1,median,Q3,max */ |
||
733 | } |
||
734 | else { |
||
735 | double_data[1] = get_real(infile,1); |
||
736 | double_data[2] = 1; |
||
737 | double_data[3] = 1; |
||
738 | double_data[4] = 1; |
||
739 | double_data[5] = 1; |
||
740 | double_data[6] = 1; |
||
741 | double_data[7] = 1; |
||
742 | i=8; |
||
743 | } |
||
744 | break;/* center value x or y */ |
||
745 | case 3: double_data[2] = get_real(infile,0); break;/* min */ |
||
746 | case 4: double_data[3] = get_real(infile,0); break;/* Q1 */ |
||
747 | case 5: double_data[4] = get_real(infile,0); break;/* median */ |
||
748 | case 6: double_data[5] = get_real(infile,0); break;/* Q3 */ |
||
749 | case 7: double_data[6] = get_real(infile,1); break;/* max */ |
||
750 | default:break; |
||
751 | } |
||
752 | } |
||
753 | decimals = find_number_of_digits(precision); |
||
754 | /*function draw_boxplot(canvas_type,xy,hw,cxy,data,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1)*/ |
||
18557 | bpr | 755 | tmp_buffer=my_newmem(MAX_BUFFER); |
756 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"draw_boxplot(%d,%d,%.*f,%.*f,[%.*f,%.*f,%.*f,%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d);\n",BOXPLOT_CANVAS+boxplot_cnt,int_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],decimals,double_data[6],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1])); |
||
18552 | bpr | 757 | add_to_buffer(tmp_buffer); |
758 | boxplot_cnt++; |
||
759 | reset(); |
||
760 | break; |
||
761 | case BOXPLOTDATA: |
||
762 | /* |
||
763 | @ boxplotdata some_data |
||
764 | @ 'some_data' are a list of numbers separated by a comma "," (items) |
||
765 | @ only be used before command <code>boxplot</code>: the command <a href="#boxplot">boxplot</a> will provide the boxplot drawing of the data. |
||
766 | @ xrange 0,100<br>yrange 0,10<br>boxplotdata 11,22,13,15,23,43,12,12,14,2,45,32,44,13,21,24,13,19,35,21,24,23<br>boxplot x,4,5 |
||
767 | @ note: wims will not check your data input | format. use js-error console to debug any problems. |
||
768 | @ a javascript function <code>statistics()</code> will parse the data and calculate the values [min,Q1,median,Q3,max] and hand them to the boxplot draw function. |
||
769 | @ only a single call to <code>boxplotdata</code> can be made. If multiple boxplots should be present in a single canvas, then use multiple calls to command <a href='#boxplot'>boxplot</a> |
||
770 | @%boxplotdata%size 400,400%xrange 0,100%yrange 0,10%strokecolor orange%fillpattern hatch%linewidth 3%strokecolor green%boxplotdata 11,22,13,15,23,43,12,12,14,2,45,32,44,13,21,24,13,19,35,21,24,23%boxplot x,2,2%mouse red,16 |
||
771 | */ |
||
772 | js_function[DRAW_JSBOXPLOT] = 1; |
||
773 | js_function[DRAW_BOXPLOT] = 1; |
||
774 | fprintf(js_include_file,"var boxplot_source = 1;var jsboxplot_data = [%s];\n",get_string(infile,1)); |
||
775 | break; |
||
776 | case CANVASTYPE: |
||
777 | canvas_type = (int) (get_real(infile,1)); |
||
778 | /* |
||
779 | @ canvastype TYPE |
||
780 | @ for now only useful before commands filltoborder / floodfill / clickfill etc operations<br>Only the images of this TYPE will be scanned and filled |
||
781 | @ default value of TYPE is DRAG_CANVAS e.g. 5 (all clickable / draggable object are in this canvas) |
||
782 | @ use another TYPE, if you know what you are doing... |
||
783 | @ other possible canvasses (e.g. transparent PNG pictures, xsize × ysize on top of each other)<ul><li> EXTERNAL_IMAGE_CANVAS 0</li><li> BG_CANVAS 1</li><li> STATIC_CANVAS 2</li><li> MOUSE_CANVAS 3</li><li> GRID_CANVAS 4</li><li> DRAG_CANVAS 5</li><li> DRAW_CANVAS 6</li><li> TEXT_CANVAS 7</li><li> CLOCK_CANVAS 8</li><li> ANIMATE_CANVAS 9</li><li> TRACE_CANVAS 10</li><li>BOXPLOT_CANVAS 11</li><li> JSPLOT_CANVAS 100, will increase with every call</li><li> FILL_CANVAS 200, will increase with every call</li><li> USERDRAW_JSPLOT 300, will increase with every call</li><li>CLICKFILL_CANVAS 400, will increase with every call/click</li><li>BOXPLOT_CANVAS 500, will increase with every call</li></ul> |
||
784 | */ |
||
785 | break; |
||
786 | case CENTERED: |
||
787 | use_offset = 4; |
||
788 | /* |
||
18556 | bpr | 789 | @ centered |
790 | @ keyword ; to place the text centered (in width and height) on the text coordinates(x:y) |
||
791 | @ may be used for text exactly centered on its (x;y) |
||
792 | @ use <a href="#fontfamily">fontfamily</a> for setting the font |
||
793 | @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the ''drag/drop/onclick-library``) |
||
794 | @%centered%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red |
||
18552 | bpr | 795 | */ |
18556 | bpr | 796 | break; |
18552 | bpr | 797 | case CENTERSTRING: |
798 | /* |
||
18556 | bpr | 799 | @ centerstring color,y-value,the text string |
800 | @ title color,y-value,the text string |
||
801 | @ draw a string centered on the canvas at y = y-value |
||
802 | @ can not be set ''onclick`` or ''drag xy`` (...) |
||
803 | @ unicode supported: <code>centerstring red,5,\\u2232</code> |
||
804 | @ use a command like <code>fontfamily italic 24pt Arial</code> to set fonts on browser that support font change |
||
805 | @%centerstring%size 400,400%xrange -10,10%yrange -10,10%bgcolor lightblue%fontfamily italic 22pt Courier%centerstring blue,7,the center |
||
18552 | bpr | 806 | */ |
807 | js_function[DRAW_CENTERSTRING] = 1; |
||
808 | for(i=0;i<3;i++){ |
||
809 | switch(i){ |
||
810 | case 0: stroke_color = get_color(infile,0);break;/* name or hex color */ |
||
811 | case 1: double_data[0] = get_real(infile,0);break; /* y in xrange*/ |
||
812 | case 2: temp = get_string_argument(infile,1); |
||
813 | /* draw_text = function(canvas_type,y,font_family,stroke_color,stroke_opacity,text) */ |
||
814 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 815 | tmp_buffer=my_newmem(MAX_BUFFER); |
816 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_centerstring(%d,%.*f,\"%s\",\"%s\",%.2f,\"%s\");\n",canvas_root_id,decimals,double_data[0],font_family,stroke_color,stroke_opacity,temp)); |
||
18552 | bpr | 817 | add_to_buffer(tmp_buffer); |
818 | break; |
||
819 | default:break; |
||
820 | } |
||
821 | } |
||
822 | break; |
||
823 | case CHEMTEX: |
||
824 | /* |
||
825 | chemtex |
||
826 | keyword...needs to be the first command in the script (even before the ''size`` command) |
||
827 | only for KaTeX enabled typesetting ! |
||
828 | will include 80kB large js-library for chemisty typesetting |
||
829 | using <a href="http://85.148.206.56/wims/download/katex.for.wims.tar.gz">KaTeX</a> : <code>katex x,y,\\ce{ chemistry tex code} like : \\ce{ Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2- }</code> |
||
830 | using MathJaX : <code>latex x,y,\\ce{ chemistry tex code} like : \\ce{ Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2- }</code> |
||
831 | see https://mhchem.github.io/MathJax-mhchem/ |
||
832 | %chemtex_katex_mathjax%chemtex%size 400,400%xrange -10,10%yrange -10,10%snaptogrid%fontfamily 22px Arial%strokecolor red%drag xy%centered%latex 0,8,\\ce{Hg^2+}%drag xy%centered%latex 0,4,\\ce{\\xrightarrow{\\text{I}^{-}}}%drag xy%centered%latex 0,0,\\ce{HgI2}%centered%drag xy%latex 0,-4,\\ce{\\xrightarrow{\\text{I}^{-}}}%drag xy%centered%latex 0,-8,\\ce{[Hg^{II}I4]^2-} |
||
833 | */ |
||
834 | found_size_command = 1; |
||
835 | fprintf(stdout,"\n<script src=\"scripts/js/KaTeX/mhchem.js\" defer></script>\n"); |
||
836 | break; |
||
8386 | schaersvoo | 837 | |
18552 | bpr | 838 | case CIRCLE: |
839 | /* |
||
840 | @ circle xc,yc,width (2*r in pixels),color |
||
841 | @ use command <code>fcircle xc,yc,d,color</code> |
||
842 | @ alternative: disk |
||
843 | @ use command <code>fillcolor color</code> to set the fillcolor |
||
844 | @ may be set <a href='#drag'>draggable</a> / <a href='#onclick'>onclick</a> |
||
845 | @ will shrink / expand on zoom out / zoom in |
||
846 | @%circle%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%drag xy%circle 0,0,60,red%zoom red |
||
847 | */ |
||
848 | for(i=0;i<4;i++){ |
||
849 | switch(i){ |
||
850 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
851 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
852 | case 2: double_data[2] = px2x((get_real(infile,0))/2) - px2x(0);break; /* for zoom in/out: radius in 'dx' xrange*/ |
||
853 | case 3: stroke_color = get_color(infile,1);/* name or hex color */ |
||
854 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
855 | if(use_affine == TRUE ){ transform(2,2);} |
||
856 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
857 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 858 | tmp_buffer=my_newmem(MAX_BUFFER); |
859 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],double_data[2],double_data[2],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 860 | add_to_buffer(tmp_buffer); |
861 | if(onclick != 0){object_cnt++;}/* object_cnt++;*/ |
||
862 | dragstuff[13] = 1; |
||
863 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
864 | reset(); |
||
865 | break; |
||
866 | default : break; |
||
867 | } |
||
868 | } |
||
869 | break; |
||
870 | case CIRCLES: |
||
871 | /* |
||
872 | @ circles color,xc1,yc1,r1,xc2,yc2,r2...xc_n,yc_n,r_n |
||
873 | @ <b>attention</b> r = radius in x-range (!) |
||
874 | @ use keyword <code>filled</code> or command <code>fcircles</code> to produce solid circles |
||
875 | @ alternative: disks |
||
876 | @ use command <code>fillcolor color</code> to set the fillcolor |
||
877 | @ may be set <a href='#drag'>draggable</a> / <a href='#onclick'>onclick</a> (individually) |
||
878 | @ will shrink / expand on zoom out / zoom in |
||
879 | @%circles_drag%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%drag xy%circles blue,0,0,2,2,2,3,-3,-3,3,3,3,4,3,-4,2%zoom red |
||
880 | @%circles_onclick%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%onclick%circles blue,0,0,2,2,2,3,-3,-3,3,3,3,4,3,-4,2%zoom red |
||
881 | @%circles_drag_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%# Click circles(s) to activate%opacity 200,50%fillcolor orange%rotationcenter 2,3%slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%fcircles blue,0,0,0.5,2,2,1,-3,-3,1.5,3,3,0.5,3,-4,0.5 |
||
882 | */ |
||
883 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
884 | fill_color = stroke_color; |
||
885 | i=1; |
||
886 | while( ! done ){ /* get next item until EOL*/ |
||
887 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
888 | switch (i%3){ |
||
889 | case 1:double_data[i-1] = get_real(infile,0);break; /* x */ |
||
890 | case 2:double_data[i-1] = get_real(infile,0);break; /* y */ |
||
891 | case 0:double_data[i-1] = get_real(infile,1);break; /* r */ |
||
892 | } |
||
893 | i++; |
||
894 | } |
||
895 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,3);} |
||
896 | if(use_affine == TRUE ){ transform(i-1,3);} |
||
897 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
8386 | schaersvoo | 898 | |
18552 | bpr | 899 | decimals = find_number_of_digits(precision); |
900 | for(c = 0 ; c < i-1 ; c = c+3){ |
||
18557 | bpr | 901 | tmp_buffer=my_newmem(MAX_BUFFER); |
902 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[c+2],double_data[c+2],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 903 | add_to_buffer(tmp_buffer); |
904 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
905 | } |
||
906 | reset(); |
||
907 | dragstuff[13] = 1; |
||
908 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
909 | break; |
||
910 | case CLEARBUTTON: |
||
911 | /* |
||
18556 | bpr | 912 | @ clearbutton value |
913 | @ alternative: delete |
||
914 | @ alternative: erase |
||
915 | @ adds a button to clear the <a href="#userdraw">userdraw</a> canvas with text ''value`` |
||
18572 | bpr | 916 | @ <b>attention</b> command <code>clearbutton</code> is incompatible with <a href="#multidraw">multidraw</a> based drawings<br>(in <code>multidraw</code> there is always a remove_object_button for every draw primitive) |
18556 | bpr | 917 | @ normally <a href="#userdraw">userdraw</a> primitives have the option to use middle/right mouse button on<br> a point of the object to remove this specific object...this clear button will remove all drawings |
918 | @ uses the tooltip placeholder div element: may not be used with command <code>intooltip</code> |
||
919 | @ use command <a href="#css">css</a> to style the button... |
||
920 | @ the clearbutton will have id="canvas_scripts[%d]" ; starting with %d=0 for the first script<br>to change the style of all ''clearbutton`` of all included canvasdraw scripts, use something like<br><code>if(document.getElementById("clearbutton"+canvas_scripts[0])){<br> var p = 0;<br> while(document.getElementById("clearbutton"+canvas_scripts[p])){<br> document.getElementById("clearbutton"+canvas_scripts[p]).className="some_class_name";<br> <!−−</code> or <code>document.getElementById("clearbutton"+canvas_scripts[p]).setAttribute("style","some_style"); −−><br> p++;<br> };<br>};</code> |
||
921 | @%clearbutton%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%userdraw circles,red%clearbutton Remove All |
||
18552 | bpr | 922 | */ |
923 | if(reply_format == 29){/* eg multidraw is selected */ |
||
924 | // canvas_error("command clearbutton incompatible with multidraw...only suitable for userdraw"); |
||
925 | } |
||
926 | add_clear_button(css_class,get_string(infile,1)); |
||
927 | break; |
||
928 | case CLOCK: |
||
929 | /* |
||
930 | @ clock x,y,r(px),H,M,S,type hourglass,interactive [ ,H_color,M_color,S_color,background_color,foreground_color ] |
||
931 | @ use command <code>opacity stroke-opacity,fill-opacity</code> to adjust foreground (stroke) and background (fill) transparency |
||
932 | @ type hourglass:<br>type = 0: only segments<br>type = 1: only numbers<br>type = 2: numbers and segments |
||
933 | @ colors are optional: if not defined, default values will be used<br>default colours: clock 0,0,60,4,35,45,1,2<br>custom colours: clock 0,0,60,4,35,45,1,2,,,,yellow,red<br>custom colours: clock 0,0,60,4,35,45,1,2,white,green,blue,black,yellow |
||
934 | @ if you don't want a seconds hand (or minutes...), just make it invisible by using the background color of the hourglass... |
||
935 | @ interactive <ul><li>0: not interactive, just clock(s)</li><li>1: function read_canvas() will read all active clocks in H:M:S format<br>The active clock(s) can be adjusted by pupils</li><li>2: function read_canvas() will return the clicked clock <br>(like multiplechoice; first clock in script in nr. 0 )</li><li>3: no prefab buttons...create your own buttons (or other means) to make the clock(s) adjustable by javascript function set_clock(num,type,diff)<br>wherein: num = clock id (starts with 0) ; type = 1 (hours) ; type = 2 (minutes) ; type = 3 (seconds) <br>and diff = the increment of 'type' (positive or negative)</li></ul> |
||
936 | @ canvasdraw will not check validity of colornames...the javascript console is your best friend |
||
937 | @ no combinations with other reply_types allowed, for now |
||
938 | @ if interactive is set to ''1``, 6 buttons per clock will be displayed for adjusting a clock (H+ M+ S+ H- M- S-)<br> set_clock(clock_id,type,incr) <br>first clock has clock_id=0 ; type: H=1,M=2,S=3 ; incr: increment integer |
||
939 | @ note: if you need multiple -interactive- clocks on a webpage, use multiple ''clock`` commands in a single script !<br>and <i>not multiple canvas scripts</i> in a single page |
||
940 | @ note: clocks will not zoom or pan, when using command <a href='#zoom'>zoom</a> |
||
941 | @%clock_1%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,0,0,red,green,blue,lightgrey,black |
||
942 | @%clock_2%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,1,1,red,green,blue,lightgrey,black |
||
943 | @%clock_3%size 400,400%xrange -10,10%yrange -10,10%clock -5,0,80,4,35,45,2,2,red,green,blue,lightgrey,black%clock 5,0,80,3,15,65,2,2,red,green,blue,lightgrey,black |
||
944 | @%clock_4%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,0,0,red,green,blue,lightgrey,black |
||
945 | @%clock_5%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,1,1,red,green,blue,lightgrey,black |
||
946 | @%clock_6%size 400,400%xrange -10,10%yrange -10,10%clock -5,0,80,4,35,45,2,2,red,green,blue,lightgrey,black%clock 5,0,80,8,55,15,2,2,red,green,blue,lightgrey,black |
||
947 | @%clock_7%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,2,0,red,green,blue,lightgrey,black |
||
948 | */ |
||
949 | js_function[DRAW_CLOCK] = 1; |
||
950 | js_function[INTERACTIVE] = 1; |
||
8386 | schaersvoo | 951 | |
18552 | bpr | 952 | /* var clock = function(xc,yc,radius,H,M,S,h_color,m_color,s_color,bg_color,fg_color) */ |
953 | for(i=0;i<9;i++){ |
||
954 | switch(i){ |
||
955 | case 0: int_data[0] = x2px(get_real(infile,0)); break; /* xc */ |
||
956 | case 1: int_data[1] = y2px(get_real(infile,0)); break; /* yc */ |
||
957 | case 2: int_data[2] = get_real(infile,0);break;/* radius in px */ |
||
958 | case 3: int_data[3] = get_real(infile,0);break;/* hours */ |
||
959 | case 4: int_data[4] = get_real(infile,0);break;/* minutes */ |
||
960 | case 5: int_data[5] = get_real(infile,0);break;/* seconds */ |
||
961 | case 6: int_data[6] = get_real(infile,0);if(int_data[6] < 0 || int_data[6] > 2){canvas_error("hourglass can be 0,1 or 2");}break;/* type hourglass */ |
||
962 | case 7: int_data[7] = (int)(get_real(infile,1));/* interactive 0,1,2*/ |
||
963 | switch(int_data[7]){ |
||
964 | case 0:break; |
||
965 | case 1: |
||
966 | if(clock_cnt == 0){ |
||
967 | if( reply_format == 0 ){ |
||
968 | reply_format = 18; /* user sets clock */ |
||
18557 | bpr | 969 | /* |
970 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
971 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "set_clock = function(num,type,diff){var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n")); |
||
18552 | bpr | 972 | add_to_buffer(tmp_buffer); |
973 | */ |
||
974 | fprintf(js_include_file,"set_clock = function(num,type,diff){if(wims_status == \"done\"){return;};var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n"); |
||
975 | } |
||
976 | else { |
||
977 | canvas_error("interactive clock may not be used together with other reply_types..."); |
||
978 | } |
||
979 | } |
||
980 | fprintf(stdout,"<p style=\"text-align:center\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,1)\" value=\"H+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,1)\" value=\"M+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,1)\" value=\"S+\"><br><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,-1)\" value=\"H−\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,-1)\" value=\"M−\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,-1)\" value=\"S−\"></p>",css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt); |
||
981 | break; |
||
982 | case 3: |
||
983 | if(clock_cnt == 0){ |
||
984 | if( reply_format == 0 ){ |
||
985 | reply_format = 18; /* user sets clock */ |
||
986 | fprintf(js_include_file,"set_clock = function(num,type,diff){if(wims_status == \"done\"){return;};var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,1,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n"); |
||
987 | } |
||
988 | else { |
||
989 | canvas_error("interactive clock may not be used together with other reply_types..."); |
||
990 | } |
||
991 | } |
||
992 | /* |
||
993 | fprintf(stdout,"<p style=\"text-align:center\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,1)\" value=\"H+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,1)\" value=\"M+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,1)\" value=\"S+\"><br><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,-1)\" value=\"H−\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,-1)\" value=\"M−\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,-1)\" value=\"S−\"></p>",css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt); |
||
994 | */ |
||
995 | break; |
||
996 | case 2: |
||
997 | if( reply_format == 0 ){ |
||
998 | reply_format = 19; /* "onclick */ |
||
999 | js_function[INTERACTIVE] = 1; |
||
1000 | fprintf(js_include_file,"\n/* begin onclick handler for clocks */\nvar reply = new Array();canvas_div.addEventListener( 'mousedown', user_click,false);\n\nfunction user_click(evt){if(evt.button == 1){var canvas_rect = clock_canvas.getBoundingClientRect();var x = evt.clientX - canvas_rect.left;var y = evt.clientY - canvas_rect.top;var p = 0;var name;var t = true;while(t){try{name = eval('clocks'+p);if( x < name.xc + name.radius && x > name.xc - name.radius ){if( y < name.yc + name.radius && y > name.yc - name.radius ){reply[0] = p;name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,\"lightblue\",name.fg_color);};}else{clock_ctx.clearRect(name.xc-name.radius,name.yc-name.radius,name.xc+name.radius,name.yc+name.radius);name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};p++;}catch(e){t=false;};};};};\n"); |
||
1001 | } |
||
1002 | else { |
||
1003 | if( reply_format != 19){ |
||
1004 | canvas_error("clickable clock(s) may not be used together with other reply_types..."); |
||
1005 | } |
||
1006 | } |
||
1007 | break; |
||
1008 | default: canvas_error("interactive must be set 0,1 or 2");break; |
||
1009 | } |
||
1010 | break; |
||
1011 | case 8: |
||
1012 | if(clock_cnt == 0 ){ /* set opacity's just once .... it should be a argument to clock(), for now it's OK */ |
||
1013 | fprintf(js_include_file,"var clock_bg_opacity = %.2f;var clock_fg_opacity = %.2f;",fill_opacity,stroke_opacity); |
||
1014 | } |
||
1015 | temp = get_string(infile,3);/* optional colors, like: ,,red,,blue*/ |
||
1016 | if( strstr( temp,",") != 0 ){ temp = str_replace(temp,",","\",\""); } |
||
1017 | else{ |
||
1018 | /* h_color,m_color,s_color,bg_color,fg_color */ |
||
1019 | temp = ",black\",\"black\",\"black\",\"white\",\"black";} |
||
18557 | bpr | 1020 | tmp_buffer=my_newmem(MAX_BUFFER); |
1021 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "clocks%d = new clock(%d,%d,%d,%d,%d,%d,%d,%d,\"%s\");\n",clock_cnt,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],temp)); |
||
18552 | bpr | 1022 | add_to_buffer(tmp_buffer); |
1023 | fprintf(js_include_file,"var clocks%d;",clock_cnt); |
||
1024 | clock_cnt++; |
||
1025 | break; |
||
1026 | default:break; |
||
1027 | } |
||
1028 | } |
||
1029 | break; |
||
1030 | case COLORPALETTE: |
||
1031 | /* |
||
18556 | bpr | 1032 | @ colorpalette color_name_1,color_name_2,...,color_name_8 |
1033 | @ opacity will be the same for all colors and is set by command <a href="#opacity">opacity [0-255],[0-255]</a> |
||
1034 | @ can be used with command <a href='#userdraw'>userdraw clickfill,color</a> when more than one fillcolor is wanted.<br>in that case use for example <a href='#replyformat'>replyformat 10</a> ... reply=x1:y1:color1,x2:y2:color2...<br>the pupil can choose from the given colors by clicking small coloured buttons.<br> the click coordinates and corresponding fillcolor will be stored in read_canvas()...when using the appropriate replyformat.<br>the first color of the palette is color=0 |
||
1035 | @ make sure to include the ''remove button`` by using command <a href='#clearbutton'>clearbutton some_text</a> |
||
18552 | bpr | 1036 | */ |
1037 | if( use_tooltip == 1 ){canvas_error("command 'colorpalette' is incompatible with command 'intooltip tip_text'");} |
||
1038 | fprintf(js_include_file,"var multifillcolors = [];var palettecolors = ["); |
||
1039 | while( ! done ){ |
||
1040 | temp = get_color(infile,1); |
||
1041 | fprintf(js_include_file,"\"%s\",",temp); |
||
1042 | } |
||
1043 | fprintf(js_include_file,"];");/* add black to avoid trouble with dangling comma... */ |
||
1044 | add_color_palette(css_class); |
||
1045 | break; |
||
15111 | schaersvoo | 1046 | |
18552 | bpr | 1047 | case COMMENT: |
1048 | sync_input(infile); |
||
1049 | break; |
||
11806 | schaersvoo | 1050 | |
18552 | bpr | 1051 | case COPY: |
1052 | /* |
||
1053 | @ copy x,y,x1,y1,x2,y2,[filename URL] |
||
1054 | @ The image may be "bitmap" or "SVG" |
||
1055 | @ Insert the region from (x1,y1) to (x2,y2) (in pixels) of [filename] to (x,y) in x/y-range |
||
1056 | @ If x1=y1=x2=y2=-1, the whole [filename URL] is copied. |
||
1057 | @ [filename] is the URL of the image |
||
1058 | @ <em>TODO:move special image functions to generic 'dragstuff' library</em> |
||
1059 | @ URL is normal URL of network reachable image file location |
||
1060 | @ if command <a href="#drag">drag x/y/xy</a> is set before command ''copy``, the images will be draggable<br>javascript function read_canvas(); will return the x/y coordinate data in xrange/yrange of all -including non draggable- images<br>the command drag is only valid for the next image<br>draggable / non-draggable images may be mixed<br>may be used together with preceding keywords ''snaptogrid``, ''xsnaptogrid``, ''ysnaptogrid`` or <code>snaptopoints x1,y1,x2,y2...</code>. |
||
1061 | @ if keyword <a href="#onclick">onclick</a> is set before command ''copy`` the image(s) is clickable (marked with a green rectangle around the image)<br>use 'read_dragdrop' to get the number of the clicked image(s)<br>use command 'clearbutton some_text' to reset the reply/click array.<br>example: 4 images; student clicked on image 2 and 3: reply = 0,1,1,0<br>after clicking the clear button: reply = 0,0,0,0<br>May be mixed with commands ''drag x|y|xy`` (use javascript read_canvas to get the new coordinates |
||
1062 | @ ''onclick`` for external images may be mixed with canvas generated stuff (like lines,curves, embeded XML etc) |
||
1063 | @ you may draw / userdraw / drag other stuff on top of an "imported" image |
||
1064 | @ the use of a slider is not possible: if needed, use command <a href='#html'>html x,y,<img src=my_image.svg /> </a> |
||
1065 | @ use keyword <a href='#centered'>centered</a> before command ''copy`` to place image center at given coordinates. |
||
1066 | @%copy_onclick%size 400,400%xrange -10,10%yrange -10,10%onclick%copy -5,5,-1,-1,-1,-1,gifs/fr.gif%onclick%copy 5,5,-1,-1,-1,-1,gifs/en.gif%onclick%copy 5,-5,-1,-1,-1,-1,gifs/it.gif%onclick%copy -5,-5,-1,-1,-1,-1,gifs/cn.gif |
||
1067 | @%copy_drag_xy%size 400,400%xrange -10,10%yrange -10,10%# attention: left mouse click on the image will activate dragging...%# keep left mouse button pressed while moving the image !%drag xy%copy -5,5,-1,-1,-1,-1,gifs/fr.gif%drag xy%copy 5,5,-1,-1,-1,-1,gifs/en.gif%drag xy%copy 5,-5,-1,-1,-1,-1,gifs/it.gif%drag xy%copy -5,-5,-1,-1,-1,-1,gifs/cn.gif |
||
1068 | @%copy_drag_xy_snaptogrid%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%# attention: left mouse click on the image will activate dragging...%# keep left mouse button pressed while moving the image !%drag xy%# a function read_canvas_images() %copy -6,6,-1,-1,-1,-1,gifs/fr.gif%snaptogrid%drag xy%copy 6,6,-1,-1,-1,-1,gifs/en.gif%snaptogrid%drag xy%copy 6,-6,-1,-1,-1,-1,gifs/it.gif%snaptogrid%drag xy%copy -6,-6,-1,-1,-1,-1,gifs/cn.gif |
||
1069 | */ |
||
1070 | for(i = 0 ; i<7;i++){ |
||
1071 | switch(i){ |
||
1072 | case 0: double_data[0]=get_real(infile,0);break; /* x left top corner in x/y range */ |
||
1073 | case 1: double_data[1]=get_real(infile,0);break; /* y left top corner in x/y range */ |
||
1074 | case 2: int_data[2]=(int)(get_real(infile,0));break;/* x1 in px of external image */ |
||
1075 | case 3: int_data[3]=(int)(get_real(infile,0));break;/* y1 in px of external image */ |
||
1076 | case 4: int_data[4]=(int)(get_real(infile,0));break;/* x2 --> width */ |
||
1077 | case 5: int_data[5]=(int)(get_real(infile,0)) ;break;/* y2 --> height */ |
||
1078 | case 6: URL = get_string(infile,1); |
||
1079 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
1080 | if(use_affine == TRUE ){transform(2,2);} |
||
1081 | int_data[0] = x2px(double_data[0]); |
||
1082 | int_data[1] = y2px(double_data[1]); |
||
1083 | int_data[6] = int_data[4] - int_data[2];/* swidth & width (if not scaling )*/ |
||
1084 | int_data[7] = int_data[5] - int_data[3];/* sheight & height (if not scaling )*/ |
||
1085 | if( onclick == 0 ){ /* no mouse needed static image copy */ |
||
1086 | if(js_function[DRAW_EXTERNAL_IMAGE] == 0){/* create canvas just once */ |
||
1087 | fprintf(js_include_file,"var image_copy_canvas = create_canvas%d(%d,xsize,ysize);",canvas_root_id,STATIC_IMAGE_CANVAS); |
||
1088 | js_function[DRAW_EXTERNAL_IMAGE] = 1; |
||
1089 | } |
||
18557 | bpr | 1090 | tmp_buffer=my_newmem(MAX_BUFFER); |
1091 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[2],int_data[3],int_data[6],int_data[7],int_data[0],int_data[1],int_data[6],int_data[7],use_offset,int_data[10])); |
||
18552 | bpr | 1092 | } |
1093 | else /* onclick or drag & drop external copy images */ |
||
1094 | { |
||
1095 | js_function[DRAG_EXTERNAL_IMAGE] = 1; |
||
18557 | bpr | 1096 | tmp_buffer=my_newmem(MAX_BUFFER); |
1097 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "drag_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[2],int_data[3],int_data[6],int_data[7],int_data[0],int_data[1],int_data[6],int_data[7],onclick,object_cnt,use_offset,use_snap,int_data[10])); |
||
18552 | bpr | 1098 | } |
1099 | add_to_buffer(tmp_buffer); |
||
1100 | object_cnt++; |
||
1101 | break; |
||
1102 | default: break; |
||
1103 | } |
||
1104 | } |
||
1105 | reset(); |
||
1106 | break; |
||
11806 | schaersvoo | 1107 | /* |
1108 | HTML5 specs: |
||
1109 | context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height); |
||
18552 | bpr | 1110 | img Specifies the image, canvas, or video element to use |
1111 | sx The x coordinate where to start clipping: x1 = int_data[0] |
||
1112 | sy The y coordinate where to start clipping: x2 = int_data[1] |
||
1113 | swidth The width of the clipped image: int_data[2] - int_data[0] |
||
14066 | bpr | 1114 | sheight The height of the clipped image: int_data[3] - int_data[1] |
18552 | bpr | 1115 | x The x coordinate where to place the image on the canvas: dx1 = int_data[4] |
1116 | y The y coordinate where to place the image on the canvas: dy1 = int_data[5] |
||
1117 | width The width of the image to use (stretch or reduce the image): dx2 - dx1 = int_data[6] |
||
1118 | height The height of the image to use (stretch or reduce the image): dy2 - dy1 = int_data[7] |
||
11806 | schaersvoo | 1119 | */ |
18552 | bpr | 1120 | case COPYRESIZED: |
1121 | /* |
||
1122 | @ copyresized x1,y2,x2,y2,dx1,dy1,dx2,dy2,image_file_url |
||
1123 | @ The image may be any "bitmap" or "SVG" |
||
1124 | @ Insert the region from (x1,y1) to (x2,y2) (in pixels) of [ filename], <br>possibly resized,<br>to the region of (dx1,dy1) to (dx2,dy2) in x/y-range |
||
1125 | @ (dx1:dy1) must be left top corner; (dx2:dy2) must be right bottom corner of inserted image |
||
1126 | @ If x1=y1=x2=y2=-1, the whole [filename / URL ] is copied and resized. |
||
1127 | @ URL is normal URL of network reachable image file location<br>(as seen from public_html-root or network reachable 'http://some_server/my_images/test.gif'<br>(eg no special wims paths are searched !!) |
||
1128 | @ if command <a href="#drag">drag x/y/xy</a> is set before command ''copy``, the images will be draggable<br>javascript function read_canvas(); will return the x/y coordinate data in xrange/yrange of all -including non draggable- images<br>the command drag is only valid for the next image<br>draggable / non-draggable images may be mixed<br>may be used together with preceding keywords ''snaptogrid``,''xsnaptogrid``,''ysnaptogrid`` or <code>snaptopoints x1,y1,x2,y2...</code> |
||
1129 | @ if keyword <a href="#onclick">onclick</a> is set before command ''copy`` the image(s) is clickable (marked with a green rectangle around the image)<br>use ''read_dragdrop`` to get the number of the clicked image(s)<br>use command 'clearbutton some_text' to reset the reply/click array.<br>example: 4 images; student clicked on image 2 and 3: reply = 0,1,1,0<br>after clicking the clear button: reply = 0,0,0,0<br>May be mixed with commands ''drag x|y|xy`` (use javascript read_canvas to get the new coordinates |
||
1130 | @ ''onclick`` for external images may be mixed with canvas generated stuff (like lines,curves etc) |
||
1131 | @ you may draw / userdraw / drag stuff on top of an "imported" image |
||
1132 | @ when set draggable, there will be special function 'read_canvas_images()'<br>now dragging external images may be combined with 'read_canvas()' from <a href='#userdraw'>userdraw</a> or <a href='#multidraw'>multidraw</a><br>set command <a href='#precision'>precision</a> before command ''copy`` |
||
1133 | @ use keyword <a href='#centered'>centered</a> before command 'copyresized' to place image center at given coordinates. |
||
1134 | @ <em>TODO:move special image functions to generic 'dragstuff' library</em> |
||
1135 | */ |
||
1136 | for(i = 0 ; i<9;i++){ |
||
1137 | switch(i){ |
||
1138 | case 0: int_data[0] = (int)(get_real(infile,0));break; /* x1 */ |
||
1139 | case 1: int_data[1] = (int)(get_real(infile,0));break; /* y1 */ |
||
1140 | case 2: int_data[2] = (int)(get_real(infile,0));break;/* x2 */ |
||
1141 | case 3: int_data[3] = (int)(get_real(infile,0));break;/* y2 */ |
||
1142 | case 4: int_data[4] = x2px(get_real(infile,0));break;/* dx1 */ |
||
1143 | case 5: int_data[5] = y2px(get_real(infile,0));break;/* dy1 */ |
||
1144 | case 6: int_data[6] = x2px(get_real(infile,0));break;/* dx2 */ |
||
1145 | case 7: int_data[7] = y2px(get_real(infile,0));break;/* dy2 */ |
||
1146 | case 8: URL = get_string(infile,1); |
||
1147 | if( int_data[1] == -1 ){ int_data[10] = 1; }else{int_data[10] = 0; }/* resized / not resized */ |
||
1148 | /* flag error when wrong diagonal: copyresized -1,-1,-1,-1,0,0,7,7,testfig.gif */ |
||
1149 | if( int_data[7] < int_data[5] || int_data[6] < int_data[4]){ |
||
1150 | canvas_error("in copyresized, use:<br>left top corner (dx1:dy1) and right bottom corner (dx2:dy2) ! "); |
||
1151 | } |
||
1152 | int_data[2] = abs(int_data[2] - int_data[0]);/* swidth */ |
||
1153 | int_data[3] = abs(int_data[3] - int_data[1]);/* sheight */ |
||
1154 | int_data[6] = abs(int_data[6] - int_data[4]);/* width */ |
||
1155 | int_data[7] = abs(int_data[7] - int_data[5]);/* height */ |
||
1156 | if( onclick == 0 ){ /* no mouse needed static image copy */ |
||
1157 | if(js_function[DRAW_EXTERNAL_IMAGE] == 0){ |
||
1158 | fprintf(js_include_file,"var image_copy_canvas = create_canvas%d(%d,xsize,ysize);",canvas_root_id,STATIC_IMAGE_CANVAS); |
||
1159 | js_function[DRAW_EXTERNAL_IMAGE] = 1; |
||
1160 | } |
||
18557 | bpr | 1161 | tmp_buffer=my_newmem(MAX_BUFFER); |
1162 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],use_offset,int_data[10])); |
||
18552 | bpr | 1163 | } |
1164 | else /* onclick or drag & drop external copy images */ |
||
1165 | { |
||
1166 | js_function[DRAG_EXTERNAL_IMAGE] = 1; |
||
18557 | bpr | 1167 | tmp_buffer=my_newmem(MAX_BUFFER); |
1168 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "drag_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],onclick,object_cnt,use_offset,use_snap,int_data[10])); |
||
18552 | bpr | 1169 | object_cnt++; |
1170 | } |
||
1171 | add_to_buffer(tmp_buffer); |
||
1172 | break; |
||
1173 | default: break; |
||
1174 | } |
||
1175 | } |
||
1176 | reset(); |
||
1177 | break; |
||
8386 | schaersvoo | 1178 | |
18552 | bpr | 1179 | case CROSSHAIR: |
1180 | /* |
||
1181 | @ crosshair x,y,color |
||
1182 | @ draw a single crosshair point at (x;y) in color ''color`` |
||
1183 | @ use command <code>crosshairsize int</code> and / or <code>linewidth int</code> to adjust |
||
1184 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1185 | @%crosshair%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 2%onclick%crosshair 0,0,red%linewidth 1%onclick%crosshair 1,1,blue%linewidth 3%onclick%crosshair 3,3,green%linewidth 4%xrosshair 4,4,orange |
||
1186 | */ |
||
1187 | for(i=0;i<3;i++){ |
||
1188 | switch(i){ |
||
1189 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
1190 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
1191 | case 2: stroke_color = get_color(infile,1);/* name or hex color */ |
||
1192 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
1193 | if(use_affine == TRUE ){ transform(2,2);} |
||
1194 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1195 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 1196 | tmp_buffer=my_newmem(MAX_BUFFER); |
1197 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,7,[%.*f],[%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],crosshair_size,crosshair_size,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1198 | add_to_buffer(tmp_buffer); |
1199 | if(onclick != 0){object_cnt++;} |
||
1200 | /* object_cnt++ */ |
||
1201 | reset(); |
||
1202 | dragstuff[7] = 1; |
||
1203 | break; |
||
1204 | default:break; |
||
1205 | } |
||
1206 | } |
||
1207 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1208 | break; |
||
11806 | schaersvoo | 1209 | |
18552 | bpr | 1210 | case CROSSHAIRS: |
1211 | /* |
||
1212 | @ crosshairs color,x1,y1,x2,y2,...,x_n,y_n |
||
1213 | @ draw multiple crosshair points at given coordinates in color ''color`` |
||
1214 | @ use command <code>crosshairsize int</code> and / or <code>linewidth int</code> to adjust |
||
1215 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
1216 | @%crosshairs_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%snaptogrid%linewidth 2%drag xy%crosshairs red,0,0,1,1,2,2,3,3%drag x%crosshairs blue,0,1,1,2,2,3,3,4 |
||
1217 | @%crosshairs_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 2%onclick%crosshairs red,0,0,1,1,2,2,3,3%onclick%crosshairs blue,0,1,1,2,2,3,3,4 |
||
12107 | schaersvoo | 1218 | */ |
18552 | bpr | 1219 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
1220 | fill_color = stroke_color; |
||
1221 | i=0; |
||
1222 | while( ! done ){ /* get next item until EOL*/ |
||
1223 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
1224 | if(i%2 == 0 ){ |
||
1225 | double_data[i] = get_real(infile,0); /* x */ |
||
1226 | } |
||
1227 | else { |
||
1228 | double_data[i] = get_real(infile,1); /* y */ |
||
1229 | } |
||
1230 | i++; |
||
1231 | } |
||
1232 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
1233 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
1234 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1235 | decimals = find_number_of_digits(precision); |
||
1236 | for(c=0 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 1237 | tmp_buffer=my_newmem(MAX_BUFFER); |
1238 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,7,[%.*f],[%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],crosshair_size,crosshair_size,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1239 | add_to_buffer(tmp_buffer); |
1240 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
1241 | } |
||
1242 | dragstuff[7] = 1; |
||
1243 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1244 | reset(); |
||
1245 | break; |
||
1246 | case CROSSHAIRSIZE: |
||
1247 | /* |
||
1248 | @ crosshairsize int |
||
1249 | @ default 8 (px) |
||
1250 | */ |
||
1251 | crosshair_size = (int) (get_real(infile,1)); |
||
1252 | break; |
||
1253 | case CSS: |
||
1254 | /* |
||
1255 | @ css css_class |
||
1256 | @ may be used before any ''style-able`` html object (like inputfields or buttons) or some html objects that are generated by some canvasdraw commands |
||
1257 | @ in case of <a href="#multidraw">multidraw</a> this command must be a table css class, for example "wimstable" |
||
1258 | @%css%size 400,400%xrange -10,10%yrange -10,10%css wims_button_help%input 0,0,10,1,Hello |
||
1259 | */ |
||
1260 | css_class = get_string(infile,1); |
||
1261 | break; |
||
1262 | case CURSOR: |
||
1263 | /* |
||
1264 | @ cursor some CSS cursor_style |
||
1265 | @ alternative: pointer |
||
1266 | @ style can be any valid CSS property value |
||
1267 | @ choose from these types:<br>alias,all-scroll,auto,cell,context-menu,col-resize,copy,crosshair,default,e-resize,<br>ew-resize,grab,grabbing,help,move,n-resize,ne-resize,nesw-resize,ns-resize,nw-resize,<br>nwse-resize,no-drop,none,not-allowed,pointer,progress,row-resize,s-resize,se-resize,<br>sw-resize,text,url(myBall.cur),auto,vertical-text,w-resize,wait,zoom-in,zoom-out,initial |
||
1268 | @ note: wims will not check the validity of your cursor declaration |
||
1269 | @%cursor_css%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 3%drag xy%opacity 200,75%fcircles blue,-5,5,3,-4,-2,6,0,0,5,3,4,2,4,-5,4 |
||
1270 | */ |
||
1271 | fprintf(js_include_file,"canvas_div%d.style.cursor = \"%s\";",canvas_root_id,get_string(infile,1)); |
||
1272 | break; |
||
1273 | case CURVE: |
||
1274 | /* |
||
18556 | bpr | 1275 | @ curve color,formula(x) |
1276 | @ alternative: plot |
||
18572 | bpr | 1277 | @ use command <a href="#trange">trange</a> in parametric functions before <b>every</b> command curve / plot <code>trange -pi,pi<br>curve color,formula1(t),formula2(t)</code><br>A next parametric curve will only be correctly plot when trange is set again !<br>this is a design flaw and not a feature... |
18556 | bpr | 1278 | @ use command <a href="#precision">precision</a> to increase the number of digits of the plotted points |
1279 | @ use command <a href="#plotsteps">plotsteps</a> to increase / decrease the amount of plotted points (default 150) |
||
1280 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1281 | @ if you need a plot beyond xrange / yrange, use <a href="#jsplot">jsplot</a> (command ''curve`` will only calculate points within the xrange) |
||
18569 | bpr | 1282 | @%curve%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 1%grid 2,2,grey,2,2,6,grey%precision 1000%curve red,4*sqrt(x)%curve green,2*sqrt(abs(x))%curve blue,3*1/sqrt(x)%curve orange,4*sin(4/x)%dashed%curve red,4*cos(x) |
18552 | bpr | 1283 | */ |
1284 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
11806 | schaersvoo | 1285 | |
18552 | bpr | 1286 | if( use_parametric == TRUE ){ /* parametric color,fun1(t),fun2(t)*/ |
1287 | use_parametric = FALSE; |
||
1288 | stroke_color = get_color(infile,0); |
||
1289 | char *fun1 = get_string_argument(infile,0); |
||
1290 | char *fun2 = get_string_argument(infile,1); |
||
1291 | if( strlen(fun1) == 0 || strlen(fun2) == 0 ){canvas_error("parametric functions are NOT OK !");} |
||
18557 | bpr | 1292 | tmp_buffer=my_newmem(MAX_BUFFER); |
1293 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,9,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval_parametric(xsize,ysize,fun1,fun2,xmin,xmax,ymin,ymax,tmin,tmax,plot_steps,precision,rotationcenter),2*line_width,2*line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1294 | add_to_buffer(tmp_buffer); |
1295 | } |
||
1296 | else{ |
||
1297 | stroke_color = get_color(infile,0); |
||
1298 | char *fun1 = get_string_argument(infile,1); |
||
1299 | if( strlen(fun1) == 0 ){canvas_error("function is NOT OK !");} |
||
18557 | bpr | 1300 | tmp_buffer=my_newmem(MAX_BUFFER); |
1301 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,9,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval(xsize,ysize,fun1,xmin,xmax,ymin,ymax,plot_steps,precision,rotationcenter),line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1302 | add_to_buffer(tmp_buffer); |
1303 | } |
||
1304 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
1305 | dragstuff[9] = 1; |
||
1306 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1307 | reset(); |
||
1308 | break; |
||
1309 | case CURVEDARROW: |
||
14038 | schaersvoo | 1310 | /* |
18556 | bpr | 1311 | @ curvedarrow x1,y1,xc,yc,x2,y2,color |
1312 | @ draw a single headed curved arrow from (x1:y1) in direction of (xc:yc) to point (x2:y2)<br> note: the curve will <b>not go through</b> point (xc:yc) |
||
1313 | @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head. |
||
1314 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
1315 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1316 | @%curvedarrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrow -5,0,0,10,5,0,blue |
||
1317 | @%curvedarrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow -5,0,0,-10,5,0,blue%onclick%curvedarrow -8,0,0,5,8,3,green |
||
11806 | schaersvoo | 1318 | |
14029 | schaersvoo | 1319 | h[0] = arrowhead |
14066 | bpr | 1320 | h[1] = type: 1 = single 2=double arrow |
15111 | schaersvoo | 1321 | function Shape(object_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_slider,rotation_center,use_offset) |
14038 | schaersvoo | 1322 | */ |
18552 | bpr | 1323 | for(i=0;i<7;i++){ |
1324 | switch(i){ |
||
1325 | case 0: double_data[0] = get_real(infile,0);break; /* x1 */ |
||
1326 | case 1: double_data[1] = get_real(infile,0);break; /* y1 */ |
||
1327 | case 2: double_data[2] = get_real(infile,0);break; /* xc */ |
||
1328 | case 3: double_data[3] = get_real(infile,0);break; /* yc */ |
||
1329 | case 4: double_data[4] = get_real(infile,0);break; /* y3 */ |
||
1330 | case 5: double_data[5] = get_real(infile,0);break; /* y3 */ |
||
1331 | case 6: stroke_color = get_color(infile,1);/* name or hex color */ |
||
1332 | if(use_rotate == TRUE ){rotate(6,angle,rotationcenter,2);} |
||
1333 | if(use_affine == TRUE ){ transform(6,2);} |
||
1334 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1335 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 1336 | tmp_buffer=my_newmem(MAX_BUFFER); |
1337 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,1,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1338 | add_to_buffer(tmp_buffer); |
1339 | if(onclick != 0){object_cnt++;}/* object_cnt++;*/ |
||
1340 | reset(); |
||
1341 | break; |
||
1342 | } |
||
1343 | } |
||
1344 | dragstuff[21] = 1; |
||
1345 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1346 | break; |
||
1347 | case CURVEDARROW2: |
||
14038 | schaersvoo | 1348 | /* |
18556 | bpr | 1349 | @ curvedarrow2 x1,y1,xc,yc,x2,y2,color |
1350 | @ draw a double headed curved arrow from (x1:y1) in direction of (xc:yc) to point (x2:y2)<br> note: the curve will <b>not go through</b> point (xc:yc) |
||
1351 | @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head. |
||
1352 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
1353 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1354 | @%curvedarrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrow2 -5,0,0,10,5,0,blue |
||
18569 | bpr | 1355 | @%curvedarrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow2 -5,0,0,-10,5,0,blue%onclick%curvedarrow -8,0,0,5,8,3,green |
14029 | schaersvoo | 1356 | |
1357 | h[0] = arrowhead |
||
14066 | bpr | 1358 | h[1] = type: 1 = single 2=double arrow |
15111 | schaersvoo | 1359 | function Shape(object_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_slider,rotation_center,use_offset) |
14038 | schaersvoo | 1360 | */ |
18552 | bpr | 1361 | for(i=0;i<7;i++){ |
1362 | switch(i){ |
||
1363 | case 0: double_data[0] = get_real(infile,0);break; /* x1 */ |
||
1364 | case 1: double_data[1] = get_real(infile,0);break; /* y1 */ |
||
1365 | case 2: double_data[2] = get_real(infile,0);break; /* xc */ |
||
1366 | case 3: double_data[3] = get_real(infile,0);break; /* yc */ |
||
1367 | case 4: double_data[4] = get_real(infile,0);break; /* y3 */ |
||
1368 | case 5: double_data[5] = get_real(infile,0);break; /* y3 */ |
||
1369 | case 6: stroke_color = get_color(infile,1);/* name or hex color */ |
||
1370 | if(use_rotate == TRUE ){rotate(6,angle,rotationcenter,2);} |
||
1371 | if(use_affine == TRUE ){ transform(6,2);} |
||
1372 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1373 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 1374 | tmp_buffer=my_newmem(MAX_BUFFER); |
1375 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,2,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1376 | add_to_buffer(tmp_buffer); |
1377 | if(onclick != 0){object_cnt++;}/* object_cnt++;*/ |
||
1378 | dragstuff[21] = 1; |
||
1379 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1380 | reset(); |
||
1381 | break; |
||
1382 | } |
||
1383 | } |
||
1384 | break; |
||
1385 | case CURVEDARROWS: |
||
14038 | schaersvoo | 1386 | /* |
18556 | bpr | 1387 | @ curvedarrows color,x1,y1,xc,yc,x2,y2,...,x_(n-1),y_(n-1),xc,yc,x_n,y_n |
1388 | @ draw curved arrows from (x1:y1) in direction of (xc:yc) to point (x2:y2), etc<br> note: the curve will <b>not go through</b> point (xc:yc) |
||
1389 | @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head. |
||
1390 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
1391 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1392 | @%curvedarrows_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrows red,-8,0,0,8,8,0,-5,5,0,-10,6,3 |
||
1393 | @%curvedarrows_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrows red,-8,0,0,8,8,0,-5,5,0,-10,6,3 |
||
14029 | schaersvoo | 1394 | |
14030 | schaersvoo | 1395 | h[0] = arrowhead |
14066 | bpr | 1396 | h[1] = type: 1 = single 2=double arrow |
15111 | schaersvoo | 1397 | function Shape(object_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_slider,rotation_center,use_offset) |
14038 | schaersvoo | 1398 | */ |
18552 | bpr | 1399 | stroke_color = get_color(infile,0);/* name or hex color */ |
1400 | i = 0; |
||
1401 | decimals = find_number_of_digits(precision); |
||
1402 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1403 | while( ! done ){ |
||
1404 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
1405 | double_data[0] = get_real(infile,0); /* x1 */ |
||
1406 | double_data[1] = get_real(infile,0); /* y1 */ |
||
1407 | double_data[2] = get_real(infile,0); /* xc */ |
||
1408 | double_data[3] = get_real(infile,0); /* yc */ |
||
1409 | double_data[4] = get_real(infile,0); /* x3 */ |
||
1410 | double_data[5] = get_real(infile,1); /* y3 */ |
||
18557 | bpr | 1411 | tmp_buffer=my_newmem(MAX_BUFFER); |
1412 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,1,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1413 | add_to_buffer(tmp_buffer); |
1414 | if(onclick != 0){object_cnt++;} |
||
1415 | i = i + 6; |
||
1416 | } |
||
1417 | if(use_rotate == TRUE ){rotate(i-6,angle,rotationcenter,2);} |
||
1418 | if(use_affine == TRUE ){ transform(i-6,2);} |
||
1419 | dragstuff[21] = 1; |
||
1420 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1421 | reset(); |
||
1422 | break; |
||
1423 | case CURVEDARROWS2: |
||
14038 | schaersvoo | 1424 | /* |
18556 | bpr | 1425 | @ curvedarrows2 color,x1,y1,xc,yc,x2,y2,...x_(n-1),y_(n-1),xc,yc,x_n,y_n |
1426 | @ draw double headed curved arrows from (x1:y1) in direction of (xc:yc) to point (x2:y2), etc. <br> note: the curve will <b>not go through</b> point (xc:yc) |
||
1427 | @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head. |
||
1428 | @ use command <code>linewidth int</code> to adjust thickness of the arrow |
||
1429 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1430 | @%curvedarrows2_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrows2 red,-8,0,0,8,8,0,-5,5,0,-10,6,3 |
||
1431 | @%curvedarrows2_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow -5,0,0,-10,5,0,blue%onclick%curvedarrows2 red,-8,0,0,8,8,0,-5,5,0,-10,6,3 |
||
14030 | schaersvoo | 1432 | |
1433 | h[0] = arrowhead |
||
14066 | bpr | 1434 | h[1] = type: 1 = single 2=double arrow |
15111 | schaersvoo | 1435 | function Shape(object_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_slider,rotation_center,use_offset) |
14038 | schaersvoo | 1436 | */ |
18552 | bpr | 1437 | stroke_color = get_color(infile,0);/* name or hex color */ |
1438 | i = 0; |
||
1439 | decimals = find_number_of_digits(precision); |
||
1440 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1441 | while( ! done ){ |
||
1442 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
1443 | double_data[0] = get_real(infile,0); /* x1 */ |
||
1444 | double_data[1] = get_real(infile,0); /* y1 */ |
||
1445 | double_data[2] = get_real(infile,0); /* xc */ |
||
1446 | double_data[3] = get_real(infile,0); /* yc */ |
||
1447 | double_data[4] = get_real(infile,0); /* x3 */ |
||
1448 | double_data[5] = get_real(infile,1); /* y3 */ |
||
18557 | bpr | 1449 | tmp_buffer=my_newmem(MAX_BUFFER); |
1450 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,2,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1451 | add_to_buffer(tmp_buffer); |
1452 | if(onclick != 0){object_cnt++;} |
||
1453 | i = i + 6; |
||
1454 | } |
||
1455 | if(use_rotate == TRUE ){rotate(i-6,angle,rotationcenter,2);} |
||
1456 | if(use_affine == TRUE ){ transform(i-6,2);} |
||
1457 | dragstuff[21] = 1; |
||
1458 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1459 | reset(); |
||
1460 | break; |
||
1461 | case DASHED: |
||
1462 | /* |
||
1463 | @ dashed |
||
1464 | @ keyword (no arguments required) |
||
1465 | @ next object will be drawn with a dashed line |
||
1466 | @ change dashing scheme by using command <a href="#dashtype">dashtype</a> |
||
1467 | @%dashed%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%line -5,-5,-5,5,red%dashtype 1,1%dline -4,-5,-4,5,green%dashtype 2,2%dline -3,-5,-3,5,blue%dashtype 3,3%dline 0,-5,0,5,orange%dashtype 4,4%dline 3,-5,3,5,brown |
||
1468 | */ |
||
1469 | use_dashed = TRUE; |
||
1470 | break; |
||
1471 | case DASHTYPE: |
||
1472 | /* |
||
1473 | @ dashtype line_width_px,space_width_px |
||
1474 | @ every indiviual object may have its own dashtype, if needed... |
||
1475 | @ When keyword <a href='#dashed'>dashed</a> is set, the objects will be drawn with this dashtype |
||
1476 | @ default value <code>dashtype 2,2</code> e.g. 2px line and 2px space |
||
1477 | @ HTML5 canvas specification supports more arguments (dashing schemes) ... but not all modern browsers are yet capable |
||
1478 | @%dashtype%size 400,400%xrange -10,10%yrange -10,10%dashtype 1,1%dhline 0,9,red%dashtype 2,2%dhline 0,8,red%dashtype 4,4%dhline 0,7,red%dashtype 6,6%dhline 0,6,red%dashtype 8,8%dhline 0,5,red%dashtype 10,10%dhline 0,4,red%dashtype 1,2%dhline 0,3,red%dashtype 2,4%dhline 0,2,red%dashtype 3,6%dhline 0,1,red%dashtype 4,8%dhline 0,0,red%linewidth 2%dashtype 1,1%dhline 0,-9,red%dashtype 2,2%dhline 0,-8,red%dashtype 4,4%dhline 0,-7,red%dashtype 6,6%dhline 0,-6,red%dashtype 8,8%dhline 0,-5,red%dashtype 10,10%dhline 0,-4,red%dashtype 1,2%dhline 0,-3,red%dashtype 2,4%dhline 0,-2,red%dashtype 4,8%dhline 0,-1,red |
||
1479 | */ |
||
1480 | for(i=0;i<2;i++){ |
||
1481 | switch(i){ |
||
1482 | case 0 : dashtype[0] = (int) line_width*( get_real(infile,0)) ; break; |
||
1483 | case 1 : dashtype[1] = (int) line_width*( get_real(infile,1)) ; break; |
||
1484 | } |
||
1485 | } |
||
1486 | break; |
||
1487 | case DIAMONDFILL: |
||
1488 | /* |
||
1489 | @ diamondfill x0,y0,dx,dy,color |
||
1490 | @ x0,y0 in xrange / yrange |
||
1491 | @ distances dx,dy in pixels |
||
1492 | @ there is also a command <a href="#userdraw">userdraw diamondfill,color</a> |
||
1493 | @%diamondfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%circles red,-4,0,6,4,0,6%linewidth 1%diamondfill 0,0,5,8,blue%diamondfill 0,7,8,8,lightgreen |
||
1494 | */ |
||
1495 | js_function[DRAW_DIAMONDFILL] = 1; |
||
1496 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
1497 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1498 | add_js_filltoborder(canvas_type); |
||
1499 | } |
||
1500 | decimals = find_number_of_digits(precision); |
||
1501 | for(i=0;i<5;i++){ |
||
1502 | switch(i){ |
||
1503 | case 0: double_data[0] = get_real(infile,0); break; /* x */ |
||
1504 | case 1: double_data[1] = get_real(infile,0); break; /* y */ |
||
1505 | case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */ |
||
1506 | case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/ |
||
1507 | case 4: stroke_color = get_color(infile,1); |
||
1508 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
1509 | if(use_affine == TRUE ){ transform(2,2);} |
||
18573 | bpr | 1510 | /* draw_diamondfill(ctx,x0,y0,dx,dy,linewidth,color,opacity,xsize,ysize) */ |
18557 | bpr | 1511 | tmp_buffer=my_newmem(MAX_BUFFER); |
1512 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_diamondfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize)); |
||
18552 | bpr | 1513 | add_to_buffer(tmp_buffer); |
1514 | fill_cnt++; |
||
1515 | reset(); |
||
1516 | break; |
||
1517 | default:break; |
||
1518 | } |
||
1519 | } |
||
1520 | break; |
||
1521 | case DOTFILL: |
||
1522 | /* |
||
1523 | @ dotfill x0,y0,dx,dy,color |
||
1524 | @ x0,y0 in xrange / yrange |
||
1525 | @ distances dx,dy in pixels |
||
1526 | @ radius of dots is linewidth |
||
1527 | @ there is also a command <a href="#userdraw">userdraw dotfill,color</a> |
||
1528 | @%dotfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%circles red,-4,0,6,4,0,6%dotfill 0,0,5,8,blue%dotfill 0,7,8,8,lightgreen |
||
1529 | */ |
||
1530 | js_function[DRAW_DOTFILL] = 1; |
||
1531 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
1532 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1533 | add_js_filltoborder(canvas_type); |
||
1534 | } |
||
1535 | decimals = find_number_of_digits(precision); |
||
1536 | for(i=0;i<5;i++){ |
||
1537 | switch(i){ |
||
1538 | case 0: double_data[0] = get_real(infile,0); break; /* x in px */ |
||
1539 | case 1: double_data[1] = get_real(infile,0); break; /* y in py */ |
||
1540 | case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */ |
||
1541 | case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/ |
||
1542 | case 4: stroke_color = get_color(infile,1); |
||
1543 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
1544 | if(use_affine == TRUE ){ transform(2,2);} |
||
1545 | /* draw_dotfill(ctx,x0,y0,dx,dy,radius,color,opacity,xsize,ysize) */ |
||
18557 | bpr | 1546 | tmp_buffer=my_newmem(MAX_BUFFER); |
1547 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_dotfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",FILL_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize)); |
||
18552 | bpr | 1548 | add_to_buffer(tmp_buffer); |
1549 | fill_cnt++; |
||
1550 | reset(); |
||
1551 | break; |
||
1552 | default:break; |
||
1553 | } |
||
1554 | } |
||
1555 | break; |
||
1556 | case DRAG: |
||
1557 | /* |
||
18556 | bpr | 1558 | @ drag [x][y][xy] |
1559 | @ the next object will be draggable in x / y / xy direction |
||
1560 | @ the displacement can be read by <code>javascript:read_dragdrop();</code> |
||
1561 | @ the precision (default 2 decimals) in the student reply may be set with command <a href="#precision">precision</a>.<br>Use this 'precision' command before this command 'drag x|y|xy' ! |
||
1562 | @ <a href='#onclick'>onclick</a> and ''drag x|y|xy`` may be combined (for different objects: a single object can either be onclick or drag, not both ) |
||
1563 | @ ''multi_objects`` will be numbered in the given x/y-sequence (example: points red,0,0,1,1,2,2,3,3: point (0:0) is object_number 1) |
||
1564 | @ <b>attention</b>: static objects and ''onclick/drag`` objects of the same type (like point,circle,etc) with the same coordinates (e.g. objects that overlap) will give problems in the ''recognition algorithm``) in this example<br> <code>linewidth 4<br>point 0,0,red<br>drag xy<br>point 0,0,blue</code><br>the red point will not be recognised as draggable ! in the example<br><code>linewidth 4<br>drag xy<br>point 0,0,red<br>drag xy<br>point 0,0,blue</code><br>both points will be recognised |
||
1565 | @ the answer is: drag_or_onclick_object_number : Xorg : Yorg : Xnew : Ynew<br>wherein object_number is the sequence number of the draggable & onclick objects in your script.<br>Only draggable & onclick objects will have an object_number (e.g things like point,crosshair,line,segment,circle,rect,triangle...etc) |
||
1566 | @ use keyword <a href='#snaptogrid'>snaptogrid</a>, <a href='#xsnaptogrid'>xsnaptogrid</a>, <a href='#ysnaptogrid'>ysnaptogrid</a> or command <a href='#snaptopoints'>snaptopoints x1,y1,x2,y2,...</a> to switch from free to discrete movement |
||
1567 | @ in case of external images (commands copy / copyresized) the external image can be set draggable ; always xy. <br>The function javascript;read_canvas() will return the xy-coordinates of all images. |
||
1568 | @%drag_x%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag x%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4 |
||
1569 | @%drag_y%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag y%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4 |
||
1570 | @%drag_xy%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag xy%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4 |
||
18552 | bpr | 1571 | */ |
1572 | temp = get_string(infile,1); |
||
1573 | if(strstr(temp,"xy") != NULL ){ |
||
1574 | drag_type = 0; |
||
1575 | } else { |
||
1576 | if(strstr(temp,"x") != NULL ){ |
||
1577 | drag_type = 1; |
||
1578 | } |
||
1579 | else { drag_type = 2;} |
||
1580 | } |
||
1581 | /* assuming all drag&drop coordinates the same precision: so set only once */ |
||
1582 | if( print_drag_params_only_once == FALSE ){ |
||
1583 | fprintf(js_include_file,"dragdrop_precision = %d;use_dragdrop_reply = true;",precision); |
||
1584 | print_drag_params_only_once = TRUE; |
||
1585 | } |
||
1586 | onclick = 2; |
||
1587 | /* if(use_userdraw == TRUE ){canvas_error("\"drag & drop\" may not be combined with \"userdraw\" or \"pan and zoom\" \n");} */ |
||
1588 | use_dragstuff = 2; |
||
1589 | js_function[INTERACTIVE] = 1; |
||
1590 | break; |
||
1591 | case ELLIPSE: |
||
1592 | /* |
||
1593 | @ ellipse xc,yc,width_x,height_y,color |
||
1594 | @ ellipses with center xc/yc and width/height in x/y-range etc (this differs from flydraw syntax!) |
||
1595 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1596 | @ will shrink / expand on zoom out / zoom in |
||
1597 | @%ellipse%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%opacity 200,40%linewidth 3%drag xy%ellipse 0,0,6,4,green%zoom blue |
||
1598 | */ |
||
1599 | for(i=0;i<5;i++){ |
||
1600 | switch(i){ |
||
1601 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
1602 | case 1:double_data[1] = get_real(infile,0);break; /* y-values */ |
||
1603 | case 2:double_data[2] = get_real(infile,0);break; /* rx -> px */ |
||
1604 | case 3:double_data[3] = get_real(infile,0);break; /* ry -> px */ |
||
1605 | case 4:stroke_color = get_color(infile,1);/* name or hex color */ |
||
1606 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,4);} |
||
1607 | if(use_affine == TRUE ){ transform(2,4);} |
||
1608 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
1609 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 1610 | tmp_buffer=my_newmem(MAX_BUFFER); |
1611 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,3,[%.*f],[%.*f],[%.*f],[%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1612 | add_to_buffer(tmp_buffer); |
1613 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
1614 | dragstuff[3] = 1; |
||
1615 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1616 | reset(); |
||
1617 | break; |
||
1618 | } |
||
1619 | } |
||
1620 | break; |
||
1621 | case ELLIPSES: |
||
1622 | /* |
||
1623 | @ ellipses color,xc1,yc1,width_x1,height_y1,xc2,yc2,width_x2,height_y2,xc3,yc3,width_x3,height_y3,... |
||
1624 | @ ellipses with center and height in x/y-range etc (this differs from flydraw syntax!) |
||
1625 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1626 | @ will shrink / expand on zoom out / zoom in |
||
1627 | @%ellipses%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%opacity 200,40%linewidth 3%onclick%ellipses red,-3,0,2,4,0,0,4,2,3,0,6,2 |
||
1628 | */ |
||
8224 | bpr | 1629 | |
18552 | bpr | 1630 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
1631 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
1632 | fill_color = stroke_color; |
||
1633 | i=1; |
||
1634 | while( ! done ){ /* get next item until EOL*/ |
||
1635 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
1636 | switch (i%4){ |
||
1637 | case 1:double_data[i-1] = get_real(infile,0);break; /* x */ |
||
1638 | case 2:double_data[i-1] = get_real(infile,0);break; /* y */ |
||
1639 | case 3:double_data[i-1] = get_real(infile,0);break; /* rx */ |
||
1640 | case 0:double_data[i-1] = get_real(infile,1);break; /* ry */ |
||
1641 | default: break; |
||
1642 | } |
||
1643 | i++; |
||
1644 | } |
||
1645 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,4);} |
||
1646 | if(use_affine == TRUE ){ transform(i-1,4);} |
||
1647 | decimals = find_number_of_digits(precision); |
||
1648 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18557 | bpr | 1649 | check_string_length(string_length) |
1650 | ;tmp_buffer=my_newmem(MAX_BUFFER); |
||
1651 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,3,[%.*f],[%.*f],[%.*f],[%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],decimals,double_data[c+2],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 1652 | add_to_buffer(tmp_buffer); |
1653 | if(onclick != 0){object_cnt++;} /* object_cnt++; */ |
||
1654 | } |
||
1655 | reset(); |
||
1656 | dragstuff[3] = 1; |
||
1657 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
1658 | break; |
||
1659 | case FILLALL: |
||
1660 | /* |
||
1661 | @ fillall color,x1,y1,x2,y2...x_n,y_n |
||
1662 | @ fill all region containing points (x1:y1),(x2:y2)...(x_n:y_n) with color 'color' |
||
1663 | @ any other colors (objects) in the <a href="#canvastype">canvastype</a> will act as border to the bucket fill |
||
1664 | @ use this command after all boundary objects are declared. |
||
1665 | @ Use command 'userdraw clickfill,color' for user click driven flood fill. |
||
1666 | @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5) |
||
1667 | @ note: the fill-family of commands are very (client) cpu intensive operations!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU.. |
||
1668 | @%fillall%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%vlines black,-5,0,-5,0,-4,0,-4,0,3,0,3,0%hlines black,-5,0,-5,0,-5,4,-5,4,-5,-2,-5,-2%circles green,0,0,2,3,3,5,-5,-5,3%opacity 240,50%fillall blue,1,1,8,8,-8,-8 |
||
1669 | */ |
||
1670 | decimals = find_number_of_digits(precision); |
||
1671 | fill_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
1672 | i=0; |
||
1673 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
1674 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1675 | add_js_filltoborder(canvas_type); |
||
1676 | } |
||
1677 | while( ! done ){ /* get next item until EOL*/ |
||
1678 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
1679 | if(i%2 == 0 ){ |
||
1680 | double_data[i] = get_real(infile,0); /* x */ |
||
1681 | } |
||
1682 | else { |
||
1683 | double_data[i] = get_real(infile,1); /* y */ |
||
18557 | bpr | 1684 | tmp_buffer=my_newmem(MAX_BUFFER); |
18609 | bpr | 1685 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "setTimeout(function(){filltoborder(%.*f,%.*f,false,[%s,%d],%d,false,null);},1000);\n",decimals,double_data[i-1],decimals,double_data[i],fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt)); |
18552 | bpr | 1686 | add_to_buffer(tmp_buffer); |
1687 | fill_cnt++; |
||
1688 | } |
||
1689 | i++; |
||
1690 | } |
||
1691 | break; |
||
1692 | case FILLED: |
||
1693 | /* |
||
1694 | @ filled |
||
1695 | @ keyword (no arguments required) |
||
1696 | @ the next ''fillable`` object (only the next !) will be filled |
||
1697 | @ use command <a href="#fillcolor">fillcolor color</a> to set fillcolor |
||
1698 | @ use <a href="#fillpattern">fillpattern</a> for non-solid color filling. |
||
1699 | @ use command <code>opacity 0-255,0-255</code> to set stroke and fill-opacity |
||
1700 | @ use command <a href='#fill'>fill x,y,color</a> or <a href="#floodfill">floodfill x,y,color</a> to fill the space around (x;y) with color <br>pixel operation implemented in javascript: use with care ! |
||
1701 | */ |
||
1702 | use_filled = 1; |
||
1703 | break; |
||
1704 | case FILLCOLOR: |
||
1705 | /* |
||
1706 | @ fillcolor colorname or #hex |
||
1707 | @ set the color: mainly used for command 'userdraw obj,stroke_color' |
||
1708 | @ all fillable massive objects will have a fillcolor == strokecolor (just to be compatible with flydraw...) |
||
1709 | @ see <a href="#fillpattern">fillpattern</a> for non-solid color filling. |
||
1710 | */ |
||
1711 | fill_color = get_color(infile,1); |
||
1712 | break; |
||
1713 | case FILLPATTERN: |
||
1714 | /* |
||
1715 | @ fillpattern grid | hatch | diamond | dot | image_url |
||
1716 | @ alternative: settile image_url |
||
1717 | @ use a pattern as fillstyle |
||
1718 | @ suitable for all fillable object including the <a href="#userdraw">userdraw objects' family</a> |
||
1719 | @ note: do not use the ''f`` for a fillable object : this is used exclusively for solid colour filling. |
||
18569 | bpr | 1720 | @ the fillcolor is set by the object command, for example:<br><code>size 370,370<br>xrange -5,5<br>yrange -5,5<br>opacity 165,150<br>fillpattern grid<br>circle -6,3,160,blue<br>fillpattern dot<br>circle -3,-3,160,red<br>fillpattern hatch<br>circle 0,3,160,green<br>fillpattern diamond<br>circle 3,-3,160,cyan<br>userdraw dotfill,blue<br>zoom red</code> |
18552 | bpr | 1721 | @ the pattern dimensions are hardcoded (linewidth, radius,dx,dy are fixed) |
1722 | @ the pattern color is set by command <a href='#fillcolor'>fillcolor</a> and <a href='#opacity'>opacity</a> |
||
1723 | @ see <a href="#fillcolor">fillcolor</a> for solid color filling. |
||
18569 | bpr | 1724 | @ when using an image-url, make sure it contains an ''/`` in the filename...''fillpattern $module_dir/gifs/test.jpg`` will fill the next fillable object with this image.|<br>the argument to html5 canvas routine 'createPattern(img,argument)' is set to ''repeat`` e.g. if the image is smaller then the canvas, multiple copies will be used to fill the area ( e.g. ctx.fillStyle() = pattern)<br>for example:<br><code>size 150,150<br>xrange -5,5<br>yrange -5,5<br>drag xy<br>fillpattern gifs/en.gif<br>circle 0,0,100,red<br>fillpattern gifs/nl.gif<br>drag xy<br>circle -3,2,100,green<br>fillpattern gifs/cn.gif<br>drag xy<br>circle 3,2,100,green</code> |
18552 | bpr | 1725 | @ fillpattern is also active for <a href="#userdraw">userdraw object,color</a>...<br>the userdraw family a has also ''clickfill type`` (e.g. an object gets filled between boundaries, when clicked) commands like:<br>'userdraw dotfill,color'<br>'userdraw hatchfill,color' etc |
18569 | bpr | 1726 | @%fillpattern_1%size 400,400%xrange -5,5%yrange -5,5%opacity 165,150%fillpattern grid%circle -6,3,160,blue%fillpattern dot%circle -3,-3,160,red%fillpattern hatch%circle 0,3,160,green%fillpattern diamond%circle 3,-3,160,cyan%zoom red |
18552 | bpr | 1727 | @%fillpattern_2%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%fillcolor green%fillpattern hatch%#fillpattern dot,diamond,grid,imageurl%userdraw circle,red |
1728 | */ |
||
1729 | temp = get_string(infile,1); |
||
1730 | use_filled = 0; |
||
1731 | js_function[DRAW_FILL_PATTERN] = 1; |
||
1732 | if( strstr(temp,"grid") != 0 ){ use_filled = 2;} |
||
1733 | else{ |
||
1734 | if( strstr(temp,"hatch") != 0 ){ use_filled = 3;} |
||
1735 | else{ |
||
1736 | if( strstr(temp,"diamond") != 0 ){ use_filled = 4;} |
||
1737 | else{ |
||
1738 | if( strstr(temp,"dot") != 0 ){ use_filled = 5;} |
||
1739 | else{ |
||
1740 | if( strstr(temp,"/") != 0 ){ /* get_image_from_url() needs to be called after function definition...*/ |
||
1741 | use_filled = 6;js_function[JS_LOAD_IMAGE] = 1; |
||
18557 | bpr | 1742 | tmp_buffer=my_newmem(MAX_BUFFER); |
1743 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "get_image_from_url(\"%s\");",temp)); |
||
18552 | bpr | 1744 | add_to_buffer(tmp_buffer); |
1745 | } |
||
1746 | } |
||
1747 | } |
||
1748 | } |
||
1749 | } |
||
1750 | if( use_filled == 0 ){canvas_error("fillpattern unknown or typo...choose grid,hatch,diamond of dot...");} |
||
1751 | break; |
||
1752 | case FILLTOBORDER: |
||
1753 | /* |
||
1754 | @ filltoborder x,y,bordercolor,color |
||
1755 | @ fill the region of point (x:y) with color 'color' |
||
1756 | @ any other color will not act as border to the bucket fill |
||
1757 | @ use this command after all boundary objects are declared. |
||
1758 | @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5) |
||
1759 | @ note: filltoborder is a very (client) cpu intensive operation!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU.. |
||
1760 | @ maybe used together with command <a href="#userdraw">userdraw clickfill,color</a> |
||
1761 | @%filltoborder%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%filltoborder 6,6,blue,blue%filltoborder 6,-6,blue,red |
||
1762 | */ |
||
1763 | for(i=0 ;i < 4 ; i++){ |
||
1764 | switch(i){ |
||
1765 | case 0:double_data[0] = get_real(infile,0);break; |
||
1766 | case 1:double_data[1] = get_real(infile,0);break; |
||
1767 | case 2:bgcolor = get_color(infile,0);break; |
||
1768 | case 3:fill_color = get_color(infile,1); |
||
18569 | bpr | 1769 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
1770 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1771 | add_js_filltoborder(canvas_type); |
||
1772 | } |
||
1773 | decimals = find_number_of_digits(precision); |
||
18552 | bpr | 1774 | /* we need to set a timeout: the canvas is not yet draw in memory? when floodfill is called directly... */ |
18569 | bpr | 1775 | tmp_buffer=my_newmem(MAX_BUFFER); |
18609 | bpr | 1776 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "filltoborder(%.*f,%.*f,[%s,%d],[%s,%d],%d,false,null);\n",decimals,double_data[0],decimals,double_data[1],bgcolor,(int) (fill_opacity/0.0039215),fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt)); |
18569 | bpr | 1777 | add_to_buffer(tmp_buffer); |
1778 | fill_cnt++; |
||
1779 | reset(); |
||
1780 | break; |
||
18552 | bpr | 1781 | default:break; |
1782 | } |
||
1783 | } |
||
1784 | break; |
||
1785 | case FLOODFILL: |
||
1786 | /* |
||
1787 | @ floodfill x,y,color |
||
1788 | @ alternative: fill |
||
1789 | @ fill the region of point (x:y) with color 'color' |
||
1790 | @ any other color or size of picture (borders of picture) will act as border to the bucket fill |
||
1791 | @ use this command after all boundary objects are declared. |
||
1792 | @ Use command <code>userdraw clickfill,color</code> for user click driven flood fill. |
||
1793 | @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5) |
||
1794 | @ note: floodfill is a very (client) cpu intensive operation!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU.. |
||
1795 | @%floodfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%floodfill 6,6,blue%floodfill 6,-6,red |
||
1796 | */ |
||
1797 | for(i=0 ;i < 4 ; i++){ |
||
1798 | switch(i){ |
||
1799 | case 0:double_data[0] = get_real(infile,0);break; |
||
1800 | case 1:double_data[1] = get_real(infile,0);break; |
||
1801 | case 2:fill_color = get_color(infile,1); |
||
1802 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
1803 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1804 | add_js_filltoborder(canvas_type); |
||
1805 | } |
||
1806 | decimals = find_number_of_digits(precision); |
||
1807 | /* we need to set a timeout: the canvas is not yet draw in memory? when floodfill is called directly... */ |
||
18557 | bpr | 1808 | tmp_buffer=my_newmem(MAX_BUFFER); |
18609 | bpr | 1809 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "setTimeout(function(){filltoborder(%.*f,%.*f,false,[%s,%d],%d,false,null);},1000);\n",decimals,double_data[0],decimals,double_data[1],fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt)); |
18552 | bpr | 1810 | add_to_buffer(tmp_buffer); |
1811 | fill_cnt++; |
||
1812 | break; |
||
1813 | default:break; |
||
1814 | } |
||
1815 | } |
||
1816 | reset(); |
||
1817 | break; |
||
1818 | case FONTCOLOR: |
||
1819 | /* |
||
18556 | bpr | 1820 | @ fontcolor color |
1821 | @ color: hexcolor or colorname |
||
1822 | @ default: black |
||
1823 | @ use command <a href="#fontfamily">fontfamily</a> to deviate from default font type |
||
1824 | @%fontcolor%size 400,400%xrange -10,10%yrange -10,10%fontcolor red%#note: use command fontfamily to change size and shape%axis%axisnumbering%grid 2,2,grey,2,2,4,grey |
||
18552 | bpr | 1825 | */ |
1826 | font_color = get_color(infile,1); |
||
1827 | break; |
||
1828 | case FONTFAMILY: |
||
1829 | /* |
||
18556 | bpr | 1830 | @ fontfamily font_description |
1831 | @ set the font family; for browsers that support it |
||
1832 | @ font_description: Arial, Courier, Helvetica etc |
||
1833 | @ in case commands <code>string color,x,y,the string</code>, <code>stringup color,x,y,rotation,the string</code>, ''fontfamily`` can be something like:<code>fontfamily italic 34pt Arial</code>. Use correct syntax: ''font style``, ''font size pt``, ''fontfamily`` |
||
1834 | @%fontfamily%size 400,400%xrange -10,10%yrange -10,10 %fontfamily Bold 10pt Arial%string blue,-9,9,10 pt Arial%fontfamily Italic 20pt Arial%string blue,0,9,20 pt Arial%fontfamily Bold 10pt Helvetica%string blue,-9,5,10 pt Helvetica%fontfamily Italic 20pt Helvetica%string blue,0,5,20 pt Helvetica %fontfamily Bold 10pt Courier%string blue,-9,0,10 pt Courier%fontfamily Italic 20pt Courier%string blue,0,0,20 pt Courier%fontfamily Bold 10pt Fixed%string blue,-9,-5,10 pt Fixed%fontfamily Italic 20pt Fixed%string blue,0,-5,20 pt Fixed %fontfamily Bold 10pt Times%string blue,-9,-9,10 pt Times%fontfamily Italic 20pt Times%string blue,0,-9,20 pt Times |
||
12110 | schaersvoo | 1835 | |
18552 | bpr | 1836 | */ |
1837 | font_family = get_string(infile,1); |
||
1838 | break; |
||
1839 | case FONTSIZE: |
||
1840 | /* |
||
18556 | bpr | 1841 | @ fontsize font_size |
1842 | @ default value 12 |
||
1843 | @ note: for some macros (like ''grid | legend | xaxistext | xlabel`` etc) sometimes command <a href="#fontfamily">fontfamily</a> can be used for some specific font-setting<br>this is however not always very straight forward... so just try and see what happens |
||
18552 | bpr | 1844 | */ |
1845 | font_size = (int) (get_real(infile,1)); |
||
1846 | break; |
||
1847 | case FUNCTION_LABEL: |
||
1848 | /* |
||
18556 | bpr | 1849 | @ functionlabel label_1:label_2:label_3... |
1850 | @ alternative: functionlabels |
||
1851 | @ default value ''f(x)=:g(x)=:h(x)=:i(x)=:j(x)=:k(x)=:m(x)=:n(x)=`` |
||
1852 | @ no mathml allowed (just ascii string) |
||
1853 | @ use command <a href='#fontsize'>fontsize int</a> to adjust the size |
||
1854 | @ use command <a href='#strokecolor'>strokecolor colorname</a> to adjust the labels (individually, if needed) |
||
1855 | @ if needed, use before every command <a href='#userinput'>userinput function | inputfield | textarea</a> |
||
1856 | @ no limit in amount of inputfields for userbased function plotting |
||
1857 | @%function_label%size 400,400%xrange -5,5%yrange -5,5%precision 0%axis%axisnumbering%opacity 100,190%grid 1,1,grey,2,2,5,black%linewidth 3%linewidth 1%precision 1000%functionlabels F(x)=:H(x)=:Yield(x)=%strokecolor green%userinput function%strokecolor red%userinput function%strokecolor blue%userinput function |
||
18552 | bpr | 1858 | */ |
1859 | temp = get_string_argument(infile,1); |
||
1860 | function_label = list2js_array(temp,":"); |
||
1861 | break; |
||
1862 | case GRID:/* xmajor,ymajor,gridcolor [,xminor,yminor,tick length (px), axis/tickscolor]*/ |
||
1863 | /* |
||
18556 | bpr | 1864 | @ grid step_x,step_y,gridcolor |
1865 | @ if keywords <a href="#axis">axis</a> or <a href="#axisnumbering">axisnumbering</a> are set, use: <code>grid step_x,step_y,major_color,minor_x,minor_y,tics height in px,axis_color</code> minor x step = step_x / minor_x |
||
1866 | @ in that case, use command <a href="#fontcolor">fontcolor</a>, <a href="#fontsize">fontsize</a> and / or <a href="#fontfamily">fontfamily</a> to adjust font; defaults: black,12,Arial |
||
1867 | @ if xmin > 0 and/or ymin > 0 and zooming / panning is not active: be aware that the x/y-axis numbering and x/y major/minor tic marks will not be visual as they are placed under the x-axis and left to the y-axis (in Quadrant II and IV) |
||
1868 | @ can <b>not</b> be set <a href="#onclick">onclick</a> or <a href="#drag">drag xy</a> |
||
1869 | @ use commands <a href="#xlabel">xlabel some_string</a> and/or <a href="#ylabel">ylabel some_string</a> to label axis; use command ''fontsize`` to adjust size: the font family is non-configurable 'italic your_fontsize px Arial' ! |
||
1870 | @ see commands <a href="#xaxis">xaxis or xaxistext</a>, <a href="#yaxis">yaxis or yaxistext</a> to set tailormade values on axis (the used font is set by command <a href="#fontfamily">fontfamily</a>; default '12px Arial') |
||
1871 | @ see command <a href="#legend">legend</a> to set a legend for the graph; use command <a href="#fontsize">fontsize</a> to adjust size (the font family is non-configurable 'bold your_fontsize px Arial') |
||
1872 | @%grid%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%zoom red |
||
1873 | @%grid_axis%size 400,400%xrange -10,10%yrange -10,10%axis%grid 1,1,grey,2,2,6,black%zoom red |
||
1874 | @%grid_axis_axisnumbering%size 400,400%xrange -10,10%yrange -10,10%fontfamily Italic 14px Courier%axis%axisnumbering%precision 0%grid 1,1,grey,2,2,6,black%zoom red |
||
18552 | bpr | 1875 | */ |
1876 | if( js_function[DRAW_YLOGSCALE] == 1 ){canvas_error("only one grid type is allowed...");} |
||
1877 | js_function[DRAW_GRID] = 1; |
||
1878 | for(i=0;i<4;i++){ |
||
1879 | switch(i){ |
||
1880 | case 0:double_data[0] = get_real(infile,0);break;/* xmajor */ |
||
1881 | case 1:double_data[1] = get_real(infile,0);break;/* ymajor */ |
||
1882 | case 2: |
||
1883 | if( use_axis == TRUE ){ |
||
1884 | stroke_color = get_color(infile,0); |
||
1885 | done = FALSE; |
||
1886 | int_data[0] = (int) (get_real(infile,0));/* xminor */ |
||
1887 | int_data[1] = (int) (get_real(infile,0));/* yminor */ |
||
1888 | int_data[2] = (int) (get_real(infile,0));/* tic_length */ |
||
1889 | fill_color = get_color(infile,1); /* used as axis_color*/ |
||
1890 | } |
||
1891 | else { |
||
1892 | int_data[0] = 1; |
||
1893 | int_data[1] = 1; |
||
1894 | stroke_color = get_color(infile,1); |
||
1895 | fill_color = stroke_color; |
||
1896 | } |
||
1897 | if( double_data[0] <= 0 || double_data[1] <= 0 || int_data[0] <= 0 || int_data[1] <= 0 ){canvas_error("major or minor ticks must be positive !");} |
||
1898 | /* set snap_x snap_y values in pixels */ |
||
1899 | fprintf(js_include_file,"snap_x = %f;snap_y = %f;",double_data[0] / int_data[0],double_data[1] / int_data[1]); |
||
1900 | fprintf(js_include_file,"\n/* add grid */function redraw_grid(){draw_grid%d(%d,%d,%.2f,%.*f,%.*f,%d,%d,%d,%d,\"%s\",\"%s\",%d,\"%s\",%d,%d,%d,%d,%d,\"%s\",%.2f);return;};",canvas_root_id,GRID_CANVAS,precision,stroke_opacity,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],int_data[2],line_width,stroke_color,fill_color,font_size,font_family,use_axis,use_axis_numbering,use_dashed,dashtype[0],dashtype[1],font_color,fill_opacity); |
||
18557 | bpr | 1901 | tmp_buffer=my_newmem(MAX_BUFFER); |
1902 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "redraw_grid();\n")); |
||
18552 | bpr | 1903 | add_to_buffer(tmp_buffer); |
1904 | break; |
||
1905 | } |
||
1906 | } |
||
1907 | reset(); |
||
1908 | break; |
||
1909 | case GRIDFILL: |
||
1910 | /* |
||
1911 | @ gridfill x0,y0,dx,dy,color |
||
1912 | @ x0,y0 in xrange / yrange |
||
1913 | @ distances dx,dy in pixels |
||
1914 | @ there is also a command <a href="#userdraw">userdraw gridfill,color</a> |
||
1915 | @%gridfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%gridfill 6,6,10,10,blue%gridfill 6,-6,6,6,red |
||
11806 | schaersvoo | 1916 | |
18552 | bpr | 1917 | */ |
1918 | js_function[DRAW_GRIDFILL] = 1; |
||
1919 | decimals = find_number_of_digits(precision); |
||
1920 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
1921 | js_function[DRAW_FILLTOBORDER] = 1; |
||
1922 | add_js_filltoborder(canvas_type); |
||
1923 | } |
||
1924 | for(i=0;i<5;i++){ |
||
1925 | switch(i){ |
||
1926 | case 0: double_data[0] = get_real(infile,0); break; /* x */ |
||
1927 | case 1: double_data[1] = get_real(infile,0); break; /* y */ |
||
1928 | case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */ |
||
1929 | case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/ |
||
1930 | case 4: stroke_color = get_color(infile,1); |
||
18557 | bpr | 1931 | |
1932 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
1933 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_gridfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize)); |
||
18552 | bpr | 1934 | add_to_buffer(tmp_buffer); |
1935 | fill_cnt++; |
||
1936 | reset(); |
||
1937 | break; |
||
1938 | default:break; |
||
1939 | } |
||
1940 | } |
||
1941 | break; |
||
1942 | case GROUP: |
||
1943 | /* |
||
18556 | bpr | 1944 | @ group |
1945 | @ keyword |
||
1946 | @ work in 'progress' |
||
1947 | @ all objects(*) after the command and until <a href="#kill">kill group</a> or <a href="#killslider">killslider</a> may be moved together with mouse moverments<br> (*) for now all real canvas objects and latex / xml ; but no images (work in progress) |
||
1948 | @ may be combined with slider driven movements or drag & drop |
||
1949 | @%group%%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%rotationcenter 0,0%slider -2*pi,2*pi,300,40,angle active,rotate%snaptogrid%ftriangle 0,-4,-2,-2,4,--5,blue%fillcolor red%fcircle -4.4,4.4,40,blue%kill slider%slider -20,20,300,40,x active,x-slide%ftriangle -2,0,0,4,2,0,green%fcircle 4.4,4.5,40,red%kill slider%slider -20,20,300,40,y active,y-slide%fcircle 4,-4,40,green%linewidth 4%fcircle -4,-4,40,orange%kill slider%group%fcircle -4.4,4.5,10,blue%fcircle -5.4,4.5,10,blue%fcircle -6.4,4.5,10,blue%fcircle -4.4,8,16,green%fcircle -5.4,8,16,green%fcircle -6.4,8,16,green%mouse red,22%zoom red |
||
18552 | bpr | 1950 | */ |
1951 | use_slider++; |
||
1952 | add_slider(2); |
||
1953 | no_reset = TRUE; |
||
1954 | int c = 0; |
||
1955 | for(i=last_slider;i<=use_slider;i++){ int_data[c] = i; c++; } |
||
1956 | my_sliders = data2js_array(int_data,use_slider - last_slider+1); |
||
1957 | if( precision == 0 ){precision = 100;} |
||
1958 | onclick = 5; |
||
1959 | use_dragstuff = 2; |
||
1960 | drag_type = 0; |
||
1961 | js_function[INTERACTIVE] = 1; |
||
1962 | fprintf(js_include_file,"var slider%d;dragdrop_precision = %d;use_dragdrop_reply = true;",use_slider,precision); |
||
18557 | bpr | 1963 | tmp_buffer=my_newmem(MAX_BUFFER); |
1964 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "slider%d = new move_group(%d);\n",use_slider,use_slider)); |
||
18552 | bpr | 1965 | add_to_buffer(tmp_buffer); |
1966 | break; |
||
1967 | case HALFLINE: |
||
1968 | /* |
||
1969 | @ demiline x1,y1,x2,y2,color |
||
1970 | @ alternative: halfline |
||
1971 | @ draws a halfline starting in (x1:y1) and through (x2:y2) in color 'color' (colorname or hex) |
||
1972 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
1973 | @%halfline%size 400,400%xrange -10,10%yrange -10,10%halfline -5,5,0,0,red%halfline -5,-5,0,0,blue |
||
1974 | */ |
||
1975 | for(i=0; i<13;i++){double_data[i]=0;} |
||
1976 | for(i=0;i<5;i++){ |
||
1977 | switch(i){ |
||
1978 | case 0: double_data[0]= get_real(infile,0);break; /* x-values */ |
||
1979 | case 1: double_data[1]= get_real(infile,0);break; /* y-values */ |
||
1980 | case 2: double_data[10]= get_real(infile,0);break; /* x-values */ |
||
1981 | case 3: double_data[11]= get_real(infile,0);break; /* y-values */ |
||
1982 | case 4: stroke_color=get_color(infile,1);/* name or hex color */ |
||
1983 | if(double_data[0] == double_data[10]){ /* vertical halfline */ |
||
1984 | if(double_data[1] < double_data[11]){ |
||
1985 | double_data[3] = ymax + 1000; |
||
1986 | } |
||
1987 | else { |
||
1988 | double_data[3] = ymin - 1000; |
||
1989 | } |
||
1990 | double_data[2] = double_data[0]; |
||
1991 | } else { /* horizontal halfline*/ |
||
1992 | if( double_data[1] == double_data[11] ){ |
||
1993 | if( double_data[0] < double_data[10] ){ |
||
1994 | double_data[2] = xmax + 1000; /* halfline to the right */ |
||
1995 | } |
||
1996 | else { |
||
1997 | double_data[2] = xmin - 1000; /* halfline to the left */ |
||
1998 | } |
||
1999 | double_data[3] = double_data[1]; |
||
2000 | } |
||
2001 | else { |
||
2002 | /* any other halfline */ |
||
2003 | /* slope */ |
||
2004 | double_data[12] = (double_data[11] - double_data[1])/(double_data[10] - double_data[0]); |
||
2005 | /* const */ |
||
2006 | double_data[13] = double_data[1] - double_data[12]*double_data[0]; |
||
2007 | if( double_data[0] < double_data[10] ){ |
||
2008 | double_data[2] = double_data[2] + 1000; |
||
2009 | } |
||
2010 | else { |
||
2011 | double_data[2] = double_data[2] - 1000; |
||
2012 | } |
||
2013 | double_data[3] = double_data[12]*double_data[2] + double_data[13]; |
||
2014 | } |
||
2015 | } |
||
2016 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2017 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
2018 | if(use_affine == TRUE ){ transform(4,2);} |
||
18557 | bpr | 2019 | tmp_buffer=my_newmem(MAX_BUFFER); |
2020 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,18,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2021 | add_to_buffer(tmp_buffer); |
2022 | if(onclick != 0){object_cnt++;} |
||
2023 | /* object_cnt++; */ |
||
2024 | reset(); |
||
2025 | break; |
||
2026 | } |
||
2027 | } |
||
2028 | dragstuff[18] = 1; |
||
2029 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2030 | break; |
||
2031 | case HALFLINES: |
||
2032 | /* |
||
2033 | @ demilines color,x1,y1,x2,y2,.... |
||
2034 | @ alternative: halflines |
||
2035 | @ draws halflines starting in (x1:y1) and through (x2:y2) in color 'color' (colorname or hex) etc |
||
2036 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> indiviually |
||
2037 | @%halflines%size 400,400%xrange -10,10%yrange -10,10%halflines red,-5,5,0,0,-5,-5,0,0 |
||
2038 | */ |
||
2039 | stroke_color=get_color(infile,0); |
||
2040 | fill_color = stroke_color; |
||
2041 | i=0; |
||
2042 | while( ! done ){ /* get next item until EOL*/ |
||
2043 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
2044 | if(i%2 == 0 ){ |
||
2045 | double_data[i] = get_real(infile,0); /* x */ |
||
2046 | } else { |
||
2047 | double_data[i] = get_real(infile,1); /* y */ |
||
2048 | } |
||
2049 | i++; |
||
2050 | } |
||
2051 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2052 | decimals = find_number_of_digits(precision); |
||
2053 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
2054 | if( double_data[c] == double_data[c+2] ){ /* vertical line*/ |
||
2055 | if(double_data[c+1] < double_data[c+3]){ /* upright halfline */ |
||
2056 | double_data[c+3] = ymax + 1000; |
||
2057 | } |
||
2058 | else { |
||
2059 | double_data[c+3] = ymin - 1000;/* descending halfline */ |
||
2060 | } |
||
2061 | } |
||
2062 | else { |
||
2063 | if( double_data[c+1] == double_data[c+3] ){ /* horizontal line */ |
||
2064 | if(double_data[c] < double_data[c+2] ){ /* halfline to the right */ |
||
2065 | double_data[c+2] = xmax+100; |
||
2066 | } |
||
2067 | else { |
||
2068 | double_data[c+2] = xmin-1000; /* halfline to the right */ |
||
2069 | } |
||
2070 | } |
||
2071 | else { |
||
2072 | /* m */ |
||
2073 | double m = (double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]); |
||
2074 | /* q */ |
||
2075 | double q = double_data[c+1] - ((double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]))*double_data[c]; |
||
2076 | if(double_data[c] < double_data[c+2]){ /* to the right */ |
||
2077 | double_data[c+2] = xmax+1000; /* 1000 is needed for dragging...otherwise it is just segment */ |
||
2078 | double_data[c+3] = (m)*(double_data[c+2])+(q); |
||
2079 | } |
||
2080 | else { /* to the left */ |
||
2081 | double_data[c+2] = xmin - 1000; |
||
2082 | double_data[c+3] = (m)*(double_data[c+2])+(q); |
||
2083 | } |
||
2084 | } |
||
2085 | } |
||
2086 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
2087 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
18557 | bpr | 2088 | tmp_buffer=my_newmem(MAX_BUFFER); |
2089 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,18,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2090 | add_to_buffer(tmp_buffer); |
2091 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
2092 | } |
||
2093 | reset(); |
||
2094 | dragstuff[18] = 1; |
||
2095 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2096 | break; |
||
2097 | case HATCHFILL: |
||
2098 | /* |
||
2099 | @ hatchfill x0,y0,dx,dy,color |
||
2100 | @ x0,y0 in xrange / yrange |
||
2101 | @ distances dx,dy in pixels |
||
2102 | @ there is also a command <a href="#userdraw">userdraw hatchfill,color</a> |
||
2103 | @%hatchfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%hatchfill 6,6,10,10,blue%hatchfill 6,-6,6,6,red |
||
2104 | */ |
||
2105 | js_function[DRAW_HATCHFILL] = 1; |
||
2106 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
2107 | js_function[DRAW_FILLTOBORDER] = 1; |
||
2108 | add_js_filltoborder(canvas_type); |
||
2109 | } |
||
2110 | decimals = find_number_of_digits(precision); |
||
2111 | for(i=0;i<5;i++){ |
||
2112 | switch(i){ |
||
2113 | case 0: double_data[0] = get_real(infile,0); break; /* x */ |
||
2114 | case 1: double_data[1] = get_real(infile,0); break; /* y */ |
||
2115 | case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */ |
||
2116 | case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/ |
||
2117 | case 4: stroke_color = get_color(infile,1); |
||
2118 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
2119 | if(use_affine == TRUE ){ transform(2,2);} |
||
2120 | /* draw_hatchfill(ctx,x0,y0,dx,dy,linewidth,color,opacity,xsize,ysize) */ |
||
18557 | bpr | 2121 | tmp_buffer=my_newmem(MAX_BUFFER); |
2122 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_hatchfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize)); |
||
18552 | bpr | 2123 | add_to_buffer(tmp_buffer); |
2124 | fill_cnt++; |
||
2125 | reset(); |
||
2126 | break; |
||
2127 | default:break; |
||
2128 | } |
||
2129 | } |
||
2130 | break; |
||
2131 | case HLINE: |
||
2132 | /* |
||
2133 | @ hline x,y,color |
||
2134 | @ alternative: horizontalline |
||
2135 | @ draw a horizontal line through point (x:y) in color 'color' |
||
2136 | @ or use command <a href='#curve'>curve color,formula</a> to draw the line (uses more points to draw the line; is however better draggable) |
||
2137 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
2138 | @%hline%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%hline 0,0,red%dhline 0,5,blue |
||
2139 | */ |
||
2140 | for(i=0;i<3;i++) { |
||
2141 | switch(i){ |
||
2142 | case 0: double_data[0] = get_real(infile,0);break; /* x-values */ |
||
2143 | case 1: double_data[1] = get_real(infile,0);break; /* y-values */ |
||
2144 | case 2: stroke_color = get_color(infile,1);/* name or hex color */ |
||
2145 | double_data[3] = double_data[1]; |
||
2146 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
2147 | if(use_affine == TRUE ){ transform(2,2);} |
||
2148 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2149 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 2150 | tmp_buffer=my_newmem(MAX_BUFFER); |
2151 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,100*xmin,decimals,100*xmax,decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2152 | add_to_buffer(tmp_buffer); |
2153 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
2154 | dragstuff[4] = 1; |
||
2155 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2156 | reset(); |
||
2157 | break; |
||
2158 | } |
||
2159 | } |
||
2160 | break; |
||
2161 | case HLINES: |
||
2162 | /* |
||
2163 | @ hlines color,x1,y1,x2,y2,... |
||
2164 | @ alternative: horizontallines |
||
2165 | @ draw horizontal lines through points (x1:y1)...(xn:yn) in color 'color' |
||
2166 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
2167 | @%hlines%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%hlines red,0,0,0,5,0,-5 |
||
2168 | */ |
||
2169 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
2170 | fill_color = stroke_color; |
||
2171 | i=0; |
||
2172 | while( ! done ){ /* get next item until EOL*/ |
||
2173 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
2174 | if(i%2 == 0 ){ |
||
2175 | double_data[i] = get_real(infile,0); /* x */ |
||
2176 | } |
||
2177 | else { |
||
2178 | double_data[i] = get_real(infile,1); /* y */ |
||
2179 | } |
||
2180 | i++; |
||
2181 | } |
||
2182 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
2183 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
2184 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
11806 | schaersvoo | 2185 | |
18552 | bpr | 2186 | decimals = find_number_of_digits(precision); |
2187 | for(c = 0 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 2188 | tmp_buffer=my_newmem(MAX_BUFFER); |
18607 | bpr | 2189 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,100*xmin,decimals,100*xmax,decimals,double_data[c+1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
18552 | bpr | 2190 | add_to_buffer(tmp_buffer); |
2191 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
2192 | } |
||
2193 | reset(); |
||
2194 | dragstuff[4] = 1; |
||
2195 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2196 | break; |
||
2197 | case HTTP: |
||
2198 | /* |
||
18556 | bpr | 2199 | @ http x1,y1,x2,y2,http://some_adress.com |
2200 | @ an active html-page will be displayed in an "iframe" rectangle left top (x1:y1), right bottom (x2:y2) |
||
2201 | @ do not use interactivity (or mouse) if the mouse needs to be active in the iframe |
||
2202 | @ can <b>not</b> be ''set onclick`` or ''drag xy`` |
||
2203 | @%http%size 400,400%xrange -10,10%yrange -10,10%http 0,10,10,0,http://wims.unice.fr%opacity 200,50%drag xy%fcircle 0,0,100,green |
||
18552 | bpr | 2204 | */ |
2205 | js_function[DRAW_HTTP] = 1; |
||
2206 | for(i=0;i<5;i++){ |
||
2207 | switch(i){ |
||
2208 | case 0: int_data[0]=x2px(get_real(infile,0));break; /* x in x/y-range coord system -> pixel width */ |
||
2209 | case 1: int_data[1]=y2px(get_real(infile,0));break; /* y in x/y-range coord system -> pixel height */ |
||
2210 | case 2: int_data[2]=x2px(get_real(infile,0)) - int_data[0];break; /* width in x/y-range coord system -> pixel width */ |
||
2211 | case 3: int_data[3]=y2px(get_real(infile,0)) - int_data[1];break; /* height in x/y-range coord system -> pixel height */ |
||
2212 | case 4: decimals = find_number_of_digits(precision); |
||
2213 | temp = get_string(infile,1); |
||
2214 | if(strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'");} |
||
18557 | bpr | 2215 | tmp_buffer = my_newmem(string_length+2); |
2216 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_http(%d,%d,%d,%d,%d,\"%s\");\n",canvas_root_id,int_data[0],int_data[1],int_data[2],int_data[3],temp)); |
||
18552 | bpr | 2217 | add_to_buffer(tmp_buffer); |
2218 | break; |
||
2219 | } |
||
2220 | } |
||
2221 | reset(); |
||
2222 | break; |
||
2223 | case HTML: |
||
2224 | /* |
||
18556 | bpr | 2225 | @ html x1,y1,html_string |
2226 | @ all tags are allowed, html code using inputfields could be read using your own javascript code. Do not use ids like 'canvas_input0' etc. |
||
2227 | @ can be set <a href='#onclick'>onclick</a> and <a href='#drag'>drag&drop</a> |
||
2228 | @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations |
||
2229 | @ command <a href='#rotate'>rotate</a> will rotate the object |
||
2230 | @ use keyword <a href='#centered'>centered</a> to center the html object on (x1:y1) |
||
2231 | @ note: using drag&drop for all external P,SPAN,DIV,IMG,SVG-images onto a canvasdraw element, use ''onclick=javascript:place_image_on_canvas(this.id)`` |
||
2232 | @ note: sub & sup are supported in command family <a href='#string'>string</a>, e.g. real internal canvas objects ! |
||
2233 | @%html-text%size 500,500%xrange -10,10%yrange -10,10%drag xy%centered%fillcolor lightblue%html 2,2,<h1 style='color:red'>DRAG ME</h1> %opacity 200,50%drag xy%fcircle 0,0,100,green |
||
2234 | @%html-image-slider%size 500,500%xrange -10,10%yrange -10,10%fontsize 42%rotationcenter 0,0%centered%html 0,0,<img src="http://85.148.206.56/gifs/can1.gif">%slider 0,pi,400,40,angle active degree, %centered%html 0,0,<img src="http://85.148.206.56/gifs/can2.gif"> |
||
18552 | bpr | 2235 | */ |
2236 | js_function[DRAW_XML] = 1; |
||
2237 | for(i=0;i<5;i++){ |
||
2238 | switch(i){ |
||
2239 | case 0: double_data[0] = get_real(infile,0);break; |
||
2240 | case 1: double_data[1] = get_real(infile,0);break; |
||
2241 | case 4: decimals = find_number_of_digits(precision); |
||
2242 | if(use_affine == TRUE ){ transform(2,2);}/* needs double_data[] */ |
||
2243 | if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */ |
||
2244 | int_data[0] = x2px(double_data[0]);/* needs px */ |
||
2245 | int_data[1] = y2px(double_data[1]); |
||
2246 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2247 | if( use_slider != -1 && drag_type != -1){ onclick = 5; } |
||
2248 | temp = get_string(infile,1); |
||
2249 | if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","\\\""); } |
||
2250 | if( strstr(temp,"<img ")!= 0){URL="image";}else{URL="html";} |
||
18557 | bpr | 2251 | tmp_buffer=my_newmem(MAX_BUFFER); |
2252 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'%s',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};slidergroup[%d] = null;draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,URL,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,object_cnt,drawxml_cnt)); |
||
18552 | bpr | 2253 | add_to_buffer(tmp_buffer); |
2254 | if(onclick != 0 ){object_cnt++;} |
||
2255 | drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */ |
||
2256 | break; |
||
2257 | default:break; |
||
2258 | } |
||
2259 | } |
||
2260 | reset(); |
||
2261 | break; |
||
2262 | case IMAGEFILL: |
||
2263 | /* |
||
2264 | @ imagefill x,y,scaling to xsize × ysize?,image_url |
||
2265 | @ The next suitable <b>filled object</b> will be filled with "image_url" tiled |
||
2266 | @ scaling to xsize × ysize ? ... 1 = yes 0 = no |
||
2267 | @ After pattern filling, the fill-color should be reset ! |
||
2268 | @ wims getins / image from class directory: imagefill 80,80,my_image.gif |
||
2269 | @ normal url: imagefill 80,80,0,$module_dir/gifs/my_image.gif |
||
2270 | @ normal url: imagefill 80,80,1,http://adres/a/b/c/my_image.jpg |
||
2271 | @ if dx,dy is larger than the image, the whole image will be background to the next object. |
||
2272 | @%imagefill_tile%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,5,3,2,5%imagefill 1.5,1.5,0,gifs/en.gif%imagefill -5,5,0,gifs/logo/wimsedu.png |
||
2273 | @%imagefill_scale%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,5,3,2,5%imagefill 1.5,1.5,1,gifs/en.gif%imagefill -5,5,1,gifs/logo/wimsedu.png |
||
2274 | */ |
||
2275 | js_function[DRAW_IMAGEFILL] = 1; |
||
2276 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
2277 | js_function[DRAW_FILLTOBORDER] = 1; |
||
2278 | add_js_filltoborder(canvas_type); |
||
2279 | } |
||
2280 | for(i=0 ;i < 4 ; i++){ |
||
2281 | switch(i){ |
||
2282 | case 0:int_data[0] = (int) (get_real(infile,0));break; |
||
2283 | case 1:int_data[1] = (int) (get_real(infile,0));break; |
||
2284 | case 2:int_data[2] = (int) (get_real(infile,0));break; /* 0 | 1 */ |
||
2285 | case 3: URL = get_string_argument(infile,1); |
||
18557 | bpr | 2286 | tmp_buffer=my_newmem(MAX_BUFFER); |
2287 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_imagefill(%d,%d,%d,\"%s\",%d,%d,%d,%d);\n",STATIC_CANVAS+fill_cnt,int_data[0],int_data[1],URL,xsize,ysize,use_userdraw,int_data[2])); |
||
18552 | bpr | 2288 | add_to_buffer(tmp_buffer); |
2289 | fill_cnt++; |
||
2290 | break; |
||
2291 | } |
||
2292 | } |
||
2293 | reset(); |
||
2294 | break; |
||
2295 | case IMAGEPALETTE: |
||
2296 | /* |
||
18556 | bpr | 2297 | @ imagepalette image1,image2,image3,... |
2298 | @ if used before and together with command <a href='#multidraw'>multidraw images,..,..., etc</a> the image will be presented in a small table in the ''control panel``. |
||
2299 | @%imagepalette%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%copy 0,0,-1,-1,-1,-1,gifs/images/skull_and_crossbones50.png%fontcolor green%fontfamily Bold 42pt Arial%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multiuserinput 0,0,1%css color:blue;%multisnaptogrid 1,1,1%multilinewidth 0,4,0%# attention: use unicode text input without the slash %# \u222D ---> u222D at least will sometimes work%# otherwise cut&past unicode symbols into inputfield...%multilabel TEXT,REACTION ARROW,FLAGS,STOP DRAWING%multidraw text,arrow,images |
||
18552 | bpr | 2300 | */ |
2301 | temp = get_string(infile,1); |
||
2302 | temp = str_replace(temp,",","\",\""); |
||
2303 | if( use_tooltip == 1 ){canvas_error("command 'imagepalette' is incompatible with command 'intooltip tip_text',as they use the same div-element ");} |
||
2304 | fprintf(js_include_file,"\nvar current_id;var imagepalette = [\" %s \"];\n",temp); |
||
2305 | break; |
||
2306 | case INPUT: |
||
2307 | /* |
||
18556 | bpr | 2308 | @ input x,y,size,editable,value |
2309 | @ to set inputfield "readonly", use editable = 0 |
||
2310 | @ if no preset 'value' is needed...use a 'space' as last item argument |
||
2311 | @ only active inputfields (editable = 1) will be read with read_canvas(); |
||
2312 | @ if ''$status=done`` (e.g. in answer.phtml) the inputfield will be cleared and set readonly<br>override this by keyword <a href="#status">status</a> |
||
2313 | @ may be further controlled by <a href="#css">css</a> |
||
2314 | @ if mathml inputfields are present and / or some userdraw is performed, these data will <b>not</b> be send as well (javascript:read_canvas();) |
||
2315 | @ use keyword <a href='#xoffset'>xoffset | centered</a> if the inputfield should be centered on (x:y)<br> default is the left top corner is (x:y) |
||
2316 | @ if the student must place an inputfield(s) somewhere on the canvas, use command <a href="#userdraw">userdraw input,color</a> or make use of a command like <a href="#userdraw">userdraw text,color</a> |
||
2317 | @%input%size 400,400%xrange -10,10%yrange -10,10%linewidth 6%point 1,2,red%input 1,2,5,1, ?%point -5,5,red%input -5,5,5,1, ?%point 6,-5,red%input 6,-5,5,1, ?%point -5,-8,red%input -5,-8,5,1, ? |
||
18552 | bpr | 2318 | */ |
2319 | js_function[DRAW_INPUTS] = 1; |
||
2320 | for(i = 0 ; i<5;i++){ |
||
2321 | switch(i){ |
||
2322 | case 0: int_data[0]=x2px(get_real(infile,0));break;/* x in px */ |
||
2323 | case 1: int_data[1]=y2px(get_real(infile,0));break;/* y in px */ |
||
2324 | case 2: int_data[2]=abs( (int)(get_real(infile,0)));break; /* size */ |
||
2325 | case 3: if( get_real(infile,1) >0){int_data[3] = 1;}else{int_data[3] = 0;};break; /* readonly */ |
||
2326 | case 4: temp = get_string(infile,3); |
||
18557 | bpr | 2327 | tmp_buffer=my_newmem(MAX_BUFFER); |
2328 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_static_inputs(%d,%d,%d,%d,%d,%d,\"%s\",\"%s\",%d);\n",canvas_root_id,input_cnt,int_data[0],int_data[1],int_data[2],int_data[3],css_class,temp,use_offset)); |
||
18552 | bpr | 2329 | add_to_buffer(tmp_buffer); |
2330 | input_cnt++;break; |
||
2331 | default: break; |
||
2332 | } |
||
2333 | } |
||
2334 | if(reply_format == 0 ){reply_format = 15;} |
||
2335 | reset(); |
||
2336 | break; |
||
2337 | case INTOOLTIP: |
||
18556 | bpr | 2338 | /* |
2339 | @ intooltip link_text |
||
2340 | @ link_text is a single line (span-element) |
||
2341 | @ link_text may also be an image URL ''http://some_server/images/my_image.png`` or ''$module_dir/gifs/my_image.jpg`` |
||
2342 | @ link_text may contain HTML markup |
||
2343 | @ the canvas will be displayed in a tooltip on ''link_text`` |
||
2344 | @ the canvas is default transparent: use command <a href="#bgcolor">bgcolor color</a> to adjust background-color, the link text will also be shown with this 'bgcolor'. |
||
2345 | @ many ''userinput stuff`` will use the tooltip_placeholder_div element...only one is defined in the wims-page<br>and are therefore these commands are mutually exclusive.<br>keep this in mind... |
||
2346 | @%intooltip%size 400,400%xrange -10,10%yrange -10,10%fontfamily Bold 42pt Courier%string black,0,0,Hello World%intooltip <span style="background-color:black;color:white;font-style:bold;font-size:48pt;">CLICK <br>HERE</span> |
||
2347 | */ |
||
18552 | bpr | 2348 | if(use_input_xy != FALSE ){canvas_error("intooltip can not be combined with userinput_xy or other commands using the tooltip-div...see documentation");} |
2349 | if( use_tooltip == 1 ){ canvas_error("command 'intooltip' cannot be combined with command 'popup'...");} |
||
2350 | tooltip_text = get_string(infile,1); |
||
2351 | if(strstr(tooltip_text,"\"") != 0 ){ tooltip_text = str_replace(tooltip_text,"\"","'"); } |
||
2352 | use_tooltip = 1; |
||
2353 | break; |
||
2354 | case JSCURVE: |
||
2355 | /* |
||
18556 | bpr | 2356 | @ jscurve color,formula1(x),formula2(x),formula3(x),... |
2357 | @ alternative: jsplot |
||
2358 | @ your function will be plotted by the javascript engine of the client browser |
||
2359 | @ if <a href='trange'>trange</a> is defined, the two functions will be plotted parametric<br><b>note</b>: use <i>x</i> as variable...and not <i>t</i>. Use keyword <a href='#animate'>animate</a> to animate a point on the curve |
||
2360 | @ use only basic math in your curve: <code>sqrt,^,asin,acos,atan,log,pi,abs,sin,cos,tan,e</code> |
||
2361 | @ use parenthesis and rawmath: use 2*x instead of 2x ; use 2^(sin(x))...etc etc (use error console to debug any errors...) |
||
2362 | @ <b>attention</b>: last ''precision`` command in the canvasdraw script determines the calculation precision of the javascript curve plot ! |
||
2363 | @ no validity check is done by wims. |
||
2364 | @ zooming & panning are implemented:<br>use command ''zoom color`` for mouse driven zooming<br>or use keyword 'setlimits' for inputfields setting xmin/xmax, ymin/ymax |
||
2365 | @ zooming & panning is better than for curves produced by command <a href="#curve">curve color,formula</a> because for avery change in x/y-range the curve is recalculated in javascript |
||
2366 | @ zooming & panning in case of userbased functionplot: reclick the OK button to re-plot curve onto the resized grid |
||
2367 | @ use keyword <a href='animate'>animate</a> for animating a point on the curve |
||
2368 | @ use command ''trace_jscurve formula(x)`` for tracing |
||
2369 | @ use command ''jsmath formula(x)`` for calculating and displaying indiviual points on the curve |
||
2370 | @ can <b>not</b> be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> (yet) |
||
2371 | @ commands plotjump / plotstep are not active for ''jscurve`` |
||
2372 | @ every command jscurve will produce a new canvas (canvastype 111,112,113...) for this one curve. |
||
18572 | bpr | 2373 | @ plotting multiple js-curves on the same canvas (for example if you want to use 'userdraw clickfill,color' on <a href="#canvastype">canvastype</a> number 111, use:<br> <code>jscurve red,fun1(x),fun2(x)...fun_n(x)</code>, you must specify individual multistrokecolors & multistrokeopacity & multilinewidth for these multiple js-curves to use different colors. Otherwise all curves will be the same color... Use commands like: <a href="#multistrokecolors">multistrokecolors</a>, <a href="#multilinewidth">multilinewidth</a>, <a href="#multidash">multidash</a>, <a href="#multistrokeopacity">multistroke</a>, <b>color</b> given for the command <code>jscurve color,formulas(x)</code> will not be used in that case... but the color argument must still be given in any case (otherwise syntax error...) |
18556 | bpr | 2374 | @%jscurve%size 400,400%xrange -10,10%yrange -10,10%multistrokecolors red,green,blue,orange%multilinewidth 1,2,3%multistrokeopacity 0.5,0.8,1.0%jscurve red,sin(x),1/sin(x),sin(x^2) |
18552 | bpr | 2375 | */ |
2376 | jsplot_cnt++;/* -1 --> 0 */ |
||
2377 | stroke_color = get_color(infile,0); |
||
2378 | js_function[JS_MATH] = 1; |
||
2379 | js_function[JS_PLOT] = 1; |
||
2380 | if( tmin != 0 && tmax !=0){use_parametric = TRUE;} |
||
2381 | temp = get_string(infile,1); |
||
2382 | temp = str_replace(temp,",","\",\""); |
||
18557 | bpr | 2383 | tmp_buffer=my_newmem(MAX_BUFFER); |
2384 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var js_plot%d = function(){jsplot(%d,[\"%s\"],[%d],[\"%s\"],[%.2f],[%d],%d,%d,[%f,%f],%d,%d,%d,0);};js_plot%d();",jsplot_cnt,JSPLOT_CANVAS+jsplot_cnt,temp,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],tmin,tmax,plot_steps,use_parametric,use_animate,jsplot_cnt)); |
||
18552 | bpr | 2385 | add_to_buffer(tmp_buffer); |
2386 | fprintf(js_include_file,"if(typeof(all_jsplots) !== 'number'){var all_jsplots;};all_jsplots = %d;",jsplot_cnt); |
||
11806 | schaersvoo | 2387 | |
18552 | bpr | 2388 | /* we need to create multiple canvasses, so we may zoom and pan ?? */ |
2389 | break; |
||
2390 | case JSMATH: |
||
2391 | /* |
||
18556 | bpr | 2392 | @ jsmath some_math_function |
2393 | @ will calculate an y-value from a userinput x-value and draws a crosshair on these coordinates. |
||
2394 | @ default labels ''x`` and ''y``; the commands ''xlabel some_x_axis_name`` and ''ylabel some_y_axis_name`` will set the label for the input fields |
||
2395 | @ use command 'css some_css' for styling the display fields. Use command 'fontsize int' to size the labels ''x`` and ''y`` |
||
2396 | @ the client browser will convert your math function to javascript math.<br>use parenthesis and rawmath: use 2*x instead of 2x etc etc<br>no check is done on the validity of your function and/or syntax<br>use error console to debug any errors... |
||
2397 | @ be aware that the formula's of the plotted function(s) can be found in the page javascript source |
||
2398 | @%jsmath%size 400,400%xrange -10,10%yrange -10,10%jsplot blue,sin(x^2)%jsmath sin(x^2) |
||
18552 | bpr | 2399 | */ |
2400 | js_function[DRAW_CROSSHAIRS] = 1; |
||
2401 | js_function[JS_MATH] = 1; |
||
2402 | add_calc_y(get_string(infile,1),font_size,css_class); |
||
2403 | break; |
||
2404 | case KILL: |
||
2405 | /* |
||
2406 | @ kill arguments |
||
2407 | @ arguments may be: affine linear translation rotation slider offset reset |
||
2408 | @ for documentation see: killaffine,killlinear,killtranslation... |
||
2409 | @ multiple arguments are allowed (although not checked for validity...) |
||
2410 | */ |
||
2411 | temp = get_string(infile,1); |
||
2412 | if(strstr(temp,"affine") != 0 ){use_affine = FALSE;affine_matrix[0] = 1.0;affine_matrix[1] = 0.0;affine_matrix[2] = 0.0;affine_matrix[3] = 1.0;affine_matrix[4] = 0.0;affine_matrix[5] = 0.0;} |
||
2413 | if(strstr(temp,"linear") != 0 ){affine_matrix[0] = 1.0;affine_matrix[1] = 0.0;affine_matrix[2] = 0.0;affine_matrix[3] = 1.0;} |
||
2414 | if(strstr(temp,"translation") != 0 || strstr(temp,"translate") != 0 ){affine_matrix[4] = 0.0;affine_matrix[5] = 0.0;} |
||
2415 | if(strstr(temp,"rotation") != 0 || strstr(temp,"rotate") != 0 ){use_rotate = FALSE;angle = 0.0;rotation_center="null";} |
||
2416 | if(strstr(temp,"slider") != 0 ){slider_type = "0";my_sliders = "[-1]";last_slider = use_slider+1;} |
||
2417 | if(strstr(temp,"group") != 0 ){onclick = 0;drag_type = -1;slider_type = "0";my_sliders = "[-1]";last_slider = use_slider+1;use_slider = -1;reset();} |
||
2418 | if(strstr(temp,"reset") != 0 ){if(no_reset == FALSE){no_reset = TRUE;}else{no_reset = FALSE;reset();}} |
||
2419 | if(strstr(temp,"offset") != 0 ){use_offset = 0;} |
||
2420 | break; |
||
2421 | case KILLAFFINE: |
||
2422 | /* |
||
2423 | @ killaffine |
||
2424 | @ keyword: resets the transformation matrix to 1,0,0,1,0,0 |
||
2425 | @ note: any active linear transformation will also be reset: tx=0, ty=0 |
||
2426 | */ |
||
2427 | use_affine = FALSE; |
||
2428 | affine_matrix[0] = 1.0; |
||
2429 | affine_matrix[1] = 0.0; |
||
2430 | affine_matrix[2] = 0.0; |
||
2431 | affine_matrix[3] = 1.0; |
||
2432 | affine_matrix[4] = 0.0; |
||
2433 | affine_matrix[5] = 0.0; |
||
2434 | break; |
||
2435 | case KILLLINEAR: |
||
2436 | /* |
||
2437 | @ killlinear |
||
2438 | @ keyword: resets the transformation matrix to 1,0,0,1,tx,ty |
||
2439 | @ note:any active transformation or rotation will not be killed (tx,ty remain active) |
||
2440 | */ |
||
2441 | affine_matrix[0] = 1.0; |
||
2442 | affine_matrix[1] = 0.0; |
||
2443 | affine_matrix[2] = 0.0; |
||
2444 | affine_matrix[3] = 1.0; |
||
2445 | break; |
||
2446 | case KILLROTATE: |
||
2447 | /* |
||
18556 | bpr | 2448 | @ killrotate |
2449 | @ will set the rotation angle to 0. |
||
18572 | bpr | 2450 | @ will also reset the command <a href="#rotationcenter">rotationcenter</a> to the first (x;y) of the next rotatable/slidable object(s) <br>eg a following rotate command will have the first object point as rotation center |
18556 | bpr | 2451 | @ if not set, the rotation center will remain unchanged |
2452 | @ note:any active transformation or linear will not be killed (e.g an active transformation matrix remains active) |
||
2453 | @%killrotate%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%rotationcenter 0,0%# slider is active for all following objects until 'killslider'%slider -10,10,300,40,angle degree,Rotate%drag xy%# after dragging the object must be clicked to re-activate the slider%linewidth 4%arrow 0,0,6,0,9,blue%%# reset rotation center to the first (x,y) of the next object/arrow...%killrotate%drag xy%# after dragging the object must be clicked to re-activate the slider%arrow 0,0,6,1,9,red |
||
18552 | bpr | 2454 | */ |
2455 | use_rotate = FALSE; |
||
2456 | angle = 0.0; |
||
2457 | rotation_center="null"; |
||
2458 | break; |
||
2459 | case KILLSLIDER: |
||
2460 | /* |
||
18556 | bpr | 2461 | @ killslider |
2462 | @ keyword (no arguments required) |
||
2463 | @ ends grouping of object under a previously defined slider |
||
18552 | bpr | 2464 | */ |
2465 | slider_type = "0"; |
||
2466 | my_sliders = "[-1]"; |
||
2467 | last_slider = use_slider+1; |
||
2468 | break; |
||
2469 | case KILLTRANSLATION: |
||
2470 | /* |
||
18556 | bpr | 2471 | @ killtranslation |
2472 | @ alternative: killtranslate |
||
2473 | @ note: a active linear or affine transformation will not be 100% reset...only tx=0,ty=0 |
||
2474 | @ resets the translation matrix a,b,c,d,tx,ty to a,b,c,d,0,0 |
||
18552 | bpr | 2475 | */ |
2476 | affine_matrix[4] = 0.0; |
||
2477 | affine_matrix[5] = 0.0; |
||
2478 | break; |
||
2479 | case LATEX: |
||
2480 | /* |
||
18556 | bpr | 2481 | @ latex x,y,tex string |
2482 | @ alternative: math |
||
18572 | bpr | 2483 | @ note: <b>for a single greek letter</b> ,please be smart and use a command like <a href='#string'>string</a> along with <b>unicode</b> !! <br>possibly together with command <a href="#xyoffset">xoffset, yoffset or xyoffset</a><br> See <a target='new' href='https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode'>https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode</a><br> See <a target='new' href='https://en.wikipedia.org/wiki/Greek_script_in_Unicode'>https://en.wikipedia.org/wiki/Greek_script_in_Unicode</a> |
18556 | bpr | 2484 | @ you may also use command <a href="#mathml">mathml</a> for xml strings generated with wims commmand ''mathmlmath`` (will not work on KaTeX enabled WIMS) |
2485 | @ transformation commands <a href='#affine'>affine</a>, <a href='#translation'>translation</a> and <a href='#rotate'>rotate</a> are supported.(onclick and drag will work) |
||
2486 | @ can be set onclick: <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects<br>if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object |
||
2487 | @ can be set draggable:<code>javascript:read_dragdrop();</code> will return all coordinates in the same order as the canvas script: unmoved object will have their original coordinates... |
||
2488 | @ can be moved/rotated with command <a href='#slider'>slider</a> |
||
2489 | @ snaptogrid is supported |
||
2490 | @ when clicked, the colour of the 'div background' of the 'mathobject' will be determined by the <a href="#fillcolor">fillcolor</a> and <a href="#opacity">opacity</a> settings |
||
2491 | @ userdraw may be combined with 'latex' ; the js-function 'read_canvas()' will contain the coordinates of the drawing. |
||
2492 | @ userdraw may be combined; the read_canvas() will contain the drawing. |
||
2493 | @ draggable or onclick 'external images' from command <a href='#copyresized'>copy or copyresized</a> and all objects from commands <a href='#html'>html</a> or <a href='#obabel'>obabel</a> can be combined with drag and/or onclick mathml |
||
2494 | @ other drag objects (circles/rects etc) are supported, but read_dragdrop() will probably be difficult to interpret... |
||
2495 | @ if inputfields are incorporated in mathml (with id's: id='mathml0',id='mathml1',...id='mathml_n')<br>the user_input values will be read by <code>javascript:read_mathml();</code>. <b>attention</b>: if after this mathml-input object other user-interactions are included, these will read mathml too using "read_canvas();" |
||
2496 | @ If other inputfields (command input / command textarea) or userdraw are performed, the function read_canvas() will not read mathml. Use some generic function to read it.... |
||
2497 | @ use keyword <a href='#centered'>centered</a> to center the katex div object on (x1:y1) <br>this may not work as expected for MathJaX [TO BE TESTED] |
||
2498 | @ note: if you want to include external TeX via drag&drop onto a canvasdraw element, use \\mmlid{integer} in the tex-command:''!insmath \\mmlid{1}\\frac{1}{\pi}``<br> (if your wims_mathml does not support it...use <a href="http://85.148.206.56/wims/download/Mathml.tar.gz">this version...</a>) |
||
2499 | @ note: the same is true for all external P,SPAN,DIV,IMG,SVG-images via drag&drop onto a canvasdraw element, use ''onclick=javascript:place_image_on_canvas(this.id)`` |
||
2500 | @%latex_drag%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%strokecolor red%drag xy%centered%latex -6,5,\\frac{1}{2}+ \\frac{\\pi}{2}%strokecolor blue%drag xy%centered%latex -3,5,\\frac{1}{3}+ \\frac{\\pi}{3}%strokecolor green%drag xy%centered%latex 0,5,\\frac{1}{4}+ \\frac{\\pi}{4}%strokecolor orange%drag xy%fontfamily 26px Times%centered%latex 3,5,\\frac{1}{5}+ \\frac{\\pi}{6} |
||
2501 | @%latex%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%vline 0,0,green%hline 0,0,green%fontfamily 16px Arial%fillcolor orange%strokecolor blue%linewidth 2%slider 0,4*pi,400,40,angle degree active, %centered%latex 0,0,\\frac{12345}{23456} \\times \\frac{12345}{23456}%translate 4,4%centered%rotate 180%drag xy%html 0,0,<table><tr><th>HTML TABLE</th></tr><tr><th><a href="https://wimsedu.info/">WIMS EDU </a> </th></tr><tr><td><img src="gifs/en.gif"></tr><tr><td><img src="gifs/nl.gif"></tr><tr><td><img src="gifs/fr.gif"></tr><tr><td><img src="gifs/cn.gif"></tr><tr><td><img src="gifs/it.gif"></tr></table>%userdraw arrow2,red |
||
18552 | bpr | 2502 | */ |
2503 | js_function[DRAW_XML] = 1; |
||
2504 | for(i=0;i<3;i++){ |
||
2505 | switch(i){ |
||
2506 | case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */ |
||
2507 | case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system -> pixel height */ |
||
2508 | case 2: decimals = find_number_of_digits(precision); |
||
2509 | temp = get_string(infile,1); |
||
2510 | if(use_affine == TRUE ){ transform(2,2);}/* slider will use css-rotate transformation */ |
||
2511 | if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */ |
||
2512 | int_data[0] = x2px(double_data[0]); |
||
2513 | int_data[1] = y2px(double_data[1]); |
||
2514 | if( use_slider != -1 && onclick == 0 ){ onclick = 5;} |
||
2515 | if( use_slider != -1 && drag_type != -1){ onclick = 5; } |
||
15757 | schaersvoo | 2516 | #ifdef KATEX_INSTALLED |
18552 | bpr | 2517 | if( strstr(temp,"\\") != 0 ){ temp = str_replace(temp,"\\","\\\\"); } |
2518 | if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); } |
||
18557 | bpr | 2519 | tmp_buffer=my_newmem(MAX_BUFFER); |
2520 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'katex',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,drawxml_cnt)); |
||
15757 | schaersvoo | 2521 | #else |
18552 | bpr | 2522 | temp = getMML(temp);/* generate MathML for Firefox or MathJaX */ |
2523 | if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); } |
||
18557 | bpr | 2524 | tmp_buffer=my_newmem(MAX_BUFFER); |
2525 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'mathml',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,drawxml_cnt)); |
||
15757 | schaersvoo | 2526 | #endif |
18552 | bpr | 2527 | add_to_buffer(tmp_buffer); |
2528 | if(onclick != 0 ){object_cnt++;} |
||
2529 | drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */ |
||
2530 | break; |
||
2531 | default:break; |
||
2532 | } |
||
2533 | } |
||
2534 | reset(); |
||
2535 | break; |
||
2536 | case LATTICE: |
||
2537 | /* |
||
18556 | bpr | 2538 | @ lattice x0,y0,xv1,yv1,xv2,yv2,n1,n2,color |
2539 | @ can <b>not</b> be set ''onclick`` or ''drag xy`` |
||
2540 | @%lattice%size 400,400%xrange -10,10%yrange -10,10%fillcolor red%linewidth 2%lattice -10,-10,0,1,1,1,10,10,red%fillcolor blue%lattice 10,-10,0,1,-1,1,10,10,blue |
||
18552 | bpr | 2541 | */ |
2542 | js_function[DRAW_LATTICE] = 1; |
||
2543 | for( i = 0; i<9; i++){ |
||
2544 | switch(i){ |
||
2545 | case 0: int_data[0] = x2px(get_real(infile,0));break; /* x0-values -> x-pixels*/ |
||
2546 | case 1: int_data[1] = y2px(get_real(infile,0));break; /* y0-values -> y-pixels*/ |
||
2547 | case 2: int_data[2] = (int) (get_real(infile,0));break; /* x1-values -> x-pixels*/ |
||
2548 | case 3: int_data[3] = (int) -1*(get_real(infile,0));break; /* y1-values -> y-pixels*/ |
||
2549 | case 4: int_data[4] = (int) (get_real(infile,0));break; /* x2-values -> x-pixels*/ |
||
2550 | case 5: int_data[5] = (int) -1*(get_real(infile,0));break; /* y2-values -> y-pixels*/ |
||
2551 | case 6: int_data[6] = (int) (get_real(infile,0));break; /* n1-values */ |
||
2552 | case 7: int_data[7] = (int) (get_real(infile,0));break; /* n2-values */ |
||
2553 | case 8: stroke_color=get_color(infile,1); |
||
2554 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 2555 | tmp_buffer=my_newmem(MAX_BUFFER); |
2556 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_lattice(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\"%s\",%.2f,\"%s\",%.2f,%d,%.2f,%d); ",STATIC_CANVAS,line_width,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],fill_color,fill_opacity,stroke_color,stroke_opacity,use_rotate,angle,use_filled)); |
||
18552 | bpr | 2557 | add_to_buffer(tmp_buffer);break; |
2558 | default:break; |
||
2559 | } |
||
2560 | } |
||
2561 | reset(); |
||
2562 | break; |
||
2563 | case LINEAR: |
||
2564 | /* |
||
18556 | bpr | 2565 | @ linear a,b,c,d |
2566 | @ defines a transformation matrix for subsequent objects |
||
2567 | @ use keyword <a href='#killlinear'>killlinear</a> to end the transformation...the next objects will be drawn in the original x/y-range |
||
2568 | @ a: Scales the drawings horizontally |
||
2569 | @ b: Skews the drawings horizontally |
||
2570 | @ c: Skews the drawings vertically |
||
2571 | @ d: Scales the drawings vertically |
||
2572 | @ the data precision may be set by preceding command ''precision int`` |
||
2573 | @ note: any active translation (tx,ty) is not changed |
||
2574 | @%linear%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%fcircle 5,5,40,blue%linear 0.2,0,0,0.2%fcircle 5,5,40,green |
||
18552 | bpr | 2575 | */ |
2576 | for(i = 0 ; i<4;i++){ |
||
2577 | switch(i){ |
||
2578 | case 0: affine_matrix[0] = get_real(infile,0);break; |
||
2579 | case 1: affine_matrix[1] = get_real(infile,0);break; |
||
2580 | case 2: affine_matrix[2] = get_real(infile,0);break; |
||
2581 | case 3: affine_matrix[3] = get_real(infile,1); |
||
2582 | affine_matrix[4] = 0;affine_matrix[5] = 0; |
||
2583 | use_affine = TRUE; |
||
2584 | break; |
||
2585 | default: break; |
||
2586 | } |
||
2587 | } |
||
2588 | reset(); |
||
2589 | break; |
||
2590 | case LINE: |
||
2591 | /* |
||
2592 | @ line x1,y1,x2,y2,color |
||
2593 | @ draw a line through points (x1:y1)--(x2:y2) in color ''color`` |
||
2594 | @ or use command ''curve color,formula`` to draw the line (uses more points to draw the line; is however better draggable) |
||
2595 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
2596 | @%line%size 400,400%xrange -10,10%yrange -10,10%line 0,1,2,-1,green |
||
2597 | */ |
||
2598 | for(i=0;i<5;i++){ |
||
2599 | switch(i){ |
||
2600 | case 0: double_data[10]= get_real(infile,0);break; /* x-values */ |
||
2601 | case 1: double_data[11]= get_real(infile,0);break; /* y-values */ |
||
2602 | case 2: double_data[12]= get_real(infile,0);break; /* x-values */ |
||
2603 | case 3: double_data[13]= get_real(infile,0);break; /* y-values */ |
||
2604 | case 4: stroke_color=get_color(infile,1);/* name or hex color */ |
||
2605 | if( double_data[10] == double_data[12] ){ /* vertical line*/ |
||
2606 | double_data[1] = xmin; |
||
2607 | double_data[3] = ymax; |
||
2608 | double_data[0] = double_data[10]; |
||
2609 | double_data[2] = double_data[10]; |
||
2610 | } |
||
2611 | else{ |
||
2612 | if( double_data[11] == double_data[13] ){ /* horizontal line */ |
||
2613 | double_data[1] = double_data[11]; |
||
2614 | double_data[3] = double_data[11]; |
||
2615 | double_data[0] = ymin; |
||
2616 | double_data[2] = xmax; |
||
2617 | } |
||
2618 | else { |
||
2619 | /* m */ |
||
2620 | double_data[5] = (double_data[13] - double_data[11]) /(double_data[12] - double_data[10]); |
||
2621 | /* q */ |
||
2622 | double_data[6] = double_data[11] - ((double_data[13] - double_data[11]) /(double_data[12] - double_data[10]))*double_data[10]; |
||
2623 | /*xmin,m*xmin+q,xmax,m*xmax+q*/ |
||
2624 | double_data[1] = (double_data[5])*(xmin)+(double_data[6]); |
||
2625 | double_data[3] = (double_data[5])*(xmax)+(double_data[6]); |
||
2626 | double_data[0] = xmin; |
||
2627 | double_data[2] = xmax; |
||
2628 | } |
||
2629 | } |
||
2630 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
2631 | if(use_affine == TRUE ){ transform(4,2);} |
||
2632 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2633 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 2634 | tmp_buffer=my_newmem(MAX_BUFFER); |
2635 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2636 | add_to_buffer(tmp_buffer); |
2637 | if(onclick != 0){object_cnt++;} |
||
2638 | /* object_cnt++;*/ |
||
2639 | reset(); |
||
2640 | break; |
||
2641 | } |
||
2642 | } |
||
2643 | dragstuff[4] = 1; |
||
2644 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2645 | break; |
||
2646 | case LINES: |
||
2647 | /* |
||
2648 | @ lines color,x1,y1,x2,y2...x_n-1,y_n-1,x_n,y_n |
||
2649 | @ draw multiple lines through points (x1:y1)--(x2:y2) ...(x_n-1:y_n-1)--(x_n:y_n) in color 'color' |
||
2650 | @ or use multiple commands ''curve color,formula`` or ''jscurve color,formule`` to draw the line <br>(uses more points to draw the line; is however better draggable) |
||
2651 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
2652 | @%lines%size 400,400%xrange -10,10%yrange -10,10%lines green,0,1,1,3,0,0,1,3,0,0,-2,1 |
||
2653 | */ |
||
2654 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
2655 | fill_color = stroke_color; |
||
2656 | i=0; |
||
2657 | while( ! done ){ /* get next item until EOL*/ |
||
2658 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
2659 | if(i%2 == 0 ){ |
||
2660 | double_data[i] = get_real(infile,0); /* x */ |
||
2661 | } |
||
2662 | else { |
||
2663 | double_data[i] = get_real(infile,1); /* y */ |
||
2664 | } |
||
2665 | i++; |
||
2666 | } |
||
2667 | decimals = find_number_of_digits(precision); |
||
2668 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2669 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
2670 | if(double_data[c] == double_data[c+2] ){ /* vertical line*/ |
||
2671 | double_data[c+1] = xmin; |
||
2672 | double_data[c+3] = ymax; |
||
2673 | double_data[c+2] = double_data[c]; |
||
2674 | } |
||
2675 | else { |
||
2676 | if( double_data[c+1] == double_data[c+3] ){ /* horizontal line */ |
||
2677 | double_data[c+3] = double_data[c+1]; |
||
2678 | double_data[c] = ymin; |
||
2679 | double_data[c+2] = xmax; |
||
2680 | } |
||
2681 | else { |
||
2682 | /* m */ |
||
2683 | double m = (double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]); |
||
2684 | /* q */ |
||
2685 | double q = double_data[c+1] - ((double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]))*double_data[c]; |
||
2686 | /*xmin,m*xmin+q,xmax,m*xmax+q*/ |
||
2687 | double_data[c+1] = (m)*(xmin)+(q); |
||
2688 | double_data[c+3] = (m)*(xmax)+(q); |
||
2689 | double_data[c] = xmin; |
||
2690 | double_data[c+2] = xmax; |
||
2691 | } |
||
2692 | } |
||
2693 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
2694 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
18557 | bpr | 2695 | tmp_buffer=my_newmem(MAX_BUFFER); |
2696 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2697 | add_to_buffer(tmp_buffer); |
2698 | if(onclick != 0){object_cnt++;} |
||
2699 | /* object_cnt++; */ |
||
2700 | } |
||
2701 | dragstuff[4] = 1; |
||
2702 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2703 | reset(); |
||
2704 | break; |
||
2705 | case LINEWIDTH: |
||
2706 | /* |
||
2707 | @ linewidth int |
||
2708 | @ default 1 |
||
2709 | @%linewidth%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%line -5,-5,-5,5,red%linewidth 2%line -4,-5,-4,5,green%linewidth 3%line -3,-5,-3,5,blue%linewidth 4%line -2,-5,-2,5,orange%linewidth 1%line -1,-5,-1,5,brown%linewidth 5%line 1,-5,1,5,cyan%linewidth 6%line 3,-5,3,5,purple%linewidth 7%line 5,-5,5,5,black |
||
2710 | */ |
||
2711 | line_width = (int) (get_real(infile,1)); |
||
2712 | break; |
||
2713 | case LEVELCURVE: |
||
2714 | /* |
||
2715 | @ levelcurve color,expression in x/y,l1,l2,... |
||
2716 | @ draws very primitive level curves for expression, with levels l1,l2,l3,...,l_n |
||
2717 | @ the quality is <b>not to be compared</b> with the Flydraw levelcurve. <br>(choose flydraw if you want quality...) |
||
2718 | @ every individual level curve may be set 'onclick / drag xy' <br>e.g. every single level curve (l1,l2,l3...l_n) has a unique identifier |
||
2719 | @ note: the arrays for holding the javascript data are limited in size |
||
2720 | @ note: reduce image size if javascript data arrays get overloaded<br>(command 'plotsteps int' will not control the data size of the plot...) |
||
2721 | @%levelcurve%size 400,400%xrange -10,10%yrange -10,10%levelcurve red,x*y,1,2,3,4 |
||
2722 | */ |
||
2723 | fill_color = get_color(infile,0); |
||
2724 | char *fun1 = get_string_argument(infile,0); |
||
2725 | if( strlen(fun1) == 0 ){canvas_error("function is NOT OK !");} |
||
2726 | i = 0; |
||
2727 | done = FALSE; |
||
2728 | while( !done ){ |
||
2729 | double_data[i] = get_real(infile,1); |
||
2730 | i++; |
||
2731 | } |
||
2732 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2733 | for(c = 0 ; c < i; c++){ |
||
18557 | bpr | 2734 | tmp_buffer=my_newmem(MAX_BUFFER); |
2735 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,16,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval_levelcurve(xsize,ysize,fun1,xmin,xmax,ymin,ymax,plot_steps,precision,double_data[c]),line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 2736 | add_to_buffer(tmp_buffer); |
2737 | if(onclick != 0){object_cnt++;} |
||
2738 | /* object_cnt++; */ |
||
2739 | } |
||
2740 | dragstuff[16] = 1; |
||
2741 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
2742 | reset(); |
||
2743 | break; |
||
2744 | case LEGEND: |
||
2745 | /* |
||
2746 | @ legend string1:string2:string3....string_n |
||
2747 | @ will be used to create a legend for a graph |
||
2748 | @ also see command <a href='#piechart'>piechart</a> |
||
2749 | @ will use the same colors per default as used in the graphs; use command <a href='#legendcolors'>legendcolors</a> to override the default |
||
2750 | @ use command <a href="#fontsize">fontsize</a> to adjust. (command ''fontfamily`` is not active for command ''legend``) |
||
2751 | @%legend%size 400,400%xrange -10,10%yrange -10,10%bgcolor white%fontsize 16%legend legend 1:legend 2:legend 3:legend 4:this is legend 5:legend 6:another legend abc%legendcolors red:green:blue%grid 1,1,white%# note: command "grid" is mandatory%# just set grid invisible if not wanted |
||
2752 | */ |
||
2753 | temp = get_string(infile,1); |
||
2754 | if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); } |
||
2755 | legend_cnt++; /* attention: starts with -1: it will be used in piechart etc */ |
||
2756 | fprintf(js_include_file,"var legend%d = [\"%s\"];",legend_cnt,temp); |
||
2757 | break; |
||
2758 | case LEGENDCOLORS: |
||
2759 | /* |
||
2760 | @ legendcolors color1:color2:color3:...:color_n |
||
2761 | @ will be used to color a legend: use this command after the legend command ! e.g. <code>legend test1:test2:test3<br>legendcolors blue:red:orange</code>. |
||
2762 | @ make sure the number of colors match the number of legend items |
||
2763 | @ command ''legend`` in case of ''piechart`` and ''barchart`` will use these colours per default (no need to specify ''legendcolors``) |
||
2764 | @%legendcolors%size 400,400%xrange -10,10%yrange -10,10%fontsize 18%legend legend 1:legend 2:legend 3%legendcolors red:green:blue%grid 1,1,grey |
||
2765 | */ |
||
2766 | if(legend_cnt == -1){canvas_error("use command \"legend\" before command \"legendcolors\" ! ");} |
||
2767 | temp = get_string(infile,1); |
||
2768 | if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); } |
||
2769 | fprintf(js_include_file,"var legendcolors%d = [\"%s\"];",legend_cnt,temp); |
||
2770 | break; |
||
2771 | case LINEGRAPH: /* scheme: var linegraph_0 = [ 'stroke_color','line_width','use_dashed', 'dashtype0','dashtype1','x1','y1',...,'x_n','y_n'];*/ |
||
2772 | /* |
||
2773 | @ linegraph x1:y1:x2:y2...x_n:y_n |
||
2774 | @ will plot your data in a graph |
||
2775 | @ may <b>only</b> to be used together with command <a href='#grid'>grid</a> |
||
2776 | @ can be used together with freestyle x-axis/y-axis texts: see commands <a href='#xaxis'>xaxis</a>,<a href='#xaxisup'>xaxisup</a> and <a href='#yaxis'>yaxis</a> |
||
2777 | @ use command <a href='#legend'>legend</a> to provide an optional legend in right-top-corner |
||
2778 | @ also see command <a href='#piechart'>piechart</a> |
||
2779 | @ multiple linegraphs may be used in a single plot |
||
2780 | @ note: your arguments are not checked by canvasdraw: use your javascript console in case of trouble... |
||
2781 | @ <ul><li>use command <a href='#strokecolor'>strokecolor</a> before a command ''linegraph`` to set the color of this graph</li><li>use command <a href='#linewidth'>linewidth</a> before command ''linegraph`` to set linewidth of this graph</li><li>use keyword <a href='#dashed'>dashed</a> before command ''linegraph`` to set dashing of the graph</li><li>if dashing is set, use command <a href='#dashtype'>dashtype</a> before command ''linegraph`` to set the type of dashing of the (individual) graph</li></ul> |
||
2782 | @%linegraph%size 400,400%xrange -10,10%yrange -10,10%strokecolor red%linegraph -10:1:-5:-1:3:3:10:-5%strokecolor blue%linegraph -10:-1:-5:1:3:-3:10:5%dashed%strokecolor green%linegraph -10:2:-5:-2:3:4:10:2%grid 1,1,grey |
||
2783 | */ |
||
2784 | temp = get_string(infile,1); |
||
2785 | if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); } |
||
2786 | fprintf(js_include_file,"var linegraph_%d = [\"%s\",\"%d\",\"%d\",\"%d\",\"%d\",\"%s\"];",linegraph_cnt,stroke_color,line_width,use_dashed,dashtype[0],dashtype[1],temp); |
||
2787 | linegraph_cnt++; |
||
2788 | reset(); |
||
2789 | break; |
||
2790 | case MATHML: |
||
2791 | /* |
||
2792 | @ mathml x1,y1,mathml_string |
||
2793 | @ this command is special for GECKO browsers, and it makes use of Native Mathml |
||
2794 | @ For general use with all browsers, use command <a href='#latex'>latex</a> |
||
2795 | @ can be set <a href='onclick'>onclick</a> and <a href='drag'>drag&drop</a> <br>Note: dragging is fairly primitive dragging of the div-element, and is not done using the <em>dragstuff library</em> |
||
2796 | @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations |
||
2797 | @ command <a href='#rotate'>rotate</a> will rotate the object |
||
2798 | @ the mathml object is centered at (x1:y1) |
||
2799 | @ the ''mathml_string`` can be produced using WIMS commands like ''texmath`` followed by ''mathmlmath``... or write correct TeX and use only ''mathmlmath`` |
||
2800 | @ mathml will be displayed in a rectangle left top (x1:y1) |
||
2801 | @ can be set onclick <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects; if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object |
||
2802 | @ can be set draggable: <code>javascript:read_dragdrop()</code> will return all coordinates in same order as the canvas script: unmoved objects will have their original coordinates... |
||
2803 | @ snaptogrid is supported...snaptopoints will work, but use with care... due to the primitive dragging. Technically: the dragstuff library is not used... the mathml is embedded in a new div element and not in the html5-canvas. |
||
2804 | @ when clicked, the mathml object will be drawn in red color; the div background color will be determined by the <a href="#fillcolor">fillcolor</a> and <a href="#opacity">opacity</a> settings. |
||
2805 | @ userdraw may be combined with 'mathml' ; the read_canvas() will contain the drawing. |
||
2806 | @ draggable or onclick 'external images' from command <a href='#copyresized'>copy or copyresized</a> can be combined with drag and/or onclick mathml |
||
2807 | @ other drag objects (circles/rects etc) are supported, but read_dragdrop() will probably be difficult to interpret... |
||
2808 | @ if inputfields are incorporated in mathml (with id's: id='mathml0',id='mathml1',...id='mathml_n')<br>the user_input values will be read by javascript:read_mathml();<br><b>attention</b>: if after this mathml-input object other user-interactions are included, these will read mathml too using "read_canvas();" |
||
2809 | @ If other inputfields (command input / command textarea) or userdraw is performed, the function read_canvas() will not read mathml. Use some generic function to read it.... |
||
2810 | @ use keyword <a href='#centered'>centered</a> to center the mathml/xml object on (x1:y1) |
||
2811 | @%mathml_onclick%size 400,400%xrange -10,10%yrange -10,10%onclick%strokecolor red%mathml -5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml366290"><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none " ><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><mo>⋅</mo><msup><mi>x</mi> <mn>2</mn></msup></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><msup><mi>x</mi> <mn>2</mn></msup></mrow></mfrac></mstyle></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%onclick%strokecolor blue%mathml 5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml580175" ><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines="none"><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></mfrac></mstyle></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span> |
||
2812 | @%mathml_drag%size 400,400%xrange -10,10%yrange -10,10%drag xy%strokecolor red%mathml -5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml366290"><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none "><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><mo>⋅</mo><msup><mi>x</mi> <mn>2</mn></msup></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><msup><mi>x</mi> <mn>2</mn></msup></mrow></mfrac></mstyle></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%drag xy%strokecolor blue%mathml 5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml580175" ><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none "><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></mfrac></mstyle></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%#click left top corner...then drag... |
||
2813 | */ |
||
2814 | js_function[DRAW_XML] = 1; |
||
2815 | for(i=0;i<3;i++){ |
||
2816 | switch(i){ |
||
2817 | case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */ |
||
2818 | case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system -> pixel height */ |
||
2819 | case 2: decimals = find_number_of_digits(precision); |
||
2820 | if(use_affine == TRUE ){ transform(2,2);}/* needs double_data[] */ |
||
2821 | if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */ |
||
2822 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
2823 | int_data[0] = x2px(double_data[0]);/* needs px */ |
||
2824 | int_data[1] = y2px(double_data[1]); |
||
2825 | if( use_slider != -1 && onclick == 0 ){ onclick = 3;}/* no drag&onclick but slideable */ |
||
2826 | if( use_slider != -1 && drag_type != -1){ onclick = 5; } |
||
2827 | temp = get_string(infile,1); |
||
2828 | if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); } |
||
18557 | bpr | 2829 | tmp_buffer=my_newmem(MAX_BUFFER); |
2830 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'mathml',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%d,rotation_center:%s,once:true};draw_xml(draw_xml%d);slidergroup[%d] = null;\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,use_slider,rotation_center,drawxml_cnt,object_cnt)); |
||
18552 | bpr | 2831 | add_to_buffer(tmp_buffer); |
2832 | if(onclick != 0 ){object_cnt++;} |
||
2833 | drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */ |
||
2834 | /* |
||
2835 | in case inputs are present, trigger adding the read_mathml() |
||
2836 | if no other reply_format is defined |
||
2837 | note: all other reply types will include a reading of elements with id='mathml'+p) |
||
2838 | */ |
||
2839 | if(strstr(temp,"mathml0") != NULL){ if(reply_format == 0 ){reply_format = 16;}} /* no other reply type is defined */ |
||
2840 | break; |
||
2841 | default:break; |
||
2842 | } |
||
2843 | } |
||
2844 | reset(); |
||
2845 | break; |
||
2846 | case MOUSE: |
||
2847 | /* |
||
18556 | bpr | 2848 | @ mouse color,fontsize |
2849 | @ will display the cursor (x:y) coordinates in ''color`` and ''fontsize`` using default fontfamily Arial |
||
2850 | @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``) |
||
2851 | @%mouse%size 400,400%xrange -10,10%yrange -10,10%mouse red,22 |
||
18552 | bpr | 2852 | */ |
2853 | stroke_color = get_color(infile,0); |
||
2854 | font_size = (int) (get_real(infile,1)); |
||
2855 | tmp_buffer = my_newmem(26); |
||
2856 | snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer); |
||
2857 | add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,2); |
||
2858 | js_function[INTERACTIVE] = 1; |
||
2859 | break; |
||
2860 | case MOUSE_DEGREE: |
||
2861 | /* |
||
18556 | bpr | 2862 | @ mouse_degree color,fontsize |
2863 | @ will display the angle in degrees between x-axis, (0:0) and the cursor (x:y) in 'color' and 'font size'<br> using a fontfamily Arial |
||
2864 | @ The angle is positive in QI and QIII and the angle value is negative in QII and QIV |
||
2865 | @ note: use command 'mouse' at the end of your script code (the same is true for command 'zoom') |
||
2866 | @%mouse_degree%size 400,400%xrange -10,10%yrange -10,10%userdraw arc,blue%precision 100000%mouse_degree red,22 |
||
18552 | bpr | 2867 | */ |
2868 | stroke_color = get_color(infile,0); |
||
2869 | font_size = (int) (get_real(infile,1)); |
||
2870 | tmp_buffer = my_newmem(26); |
||
2871 | snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer); |
||
2872 | add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,3); |
||
2873 | js_function[JS_FIND_ANGLE] = 1; |
||
2874 | js_function[INTERACTIVE] = 1; |
||
2875 | break; |
||
2876 | case MOUSE_DISPLAY: |
||
2877 | /* |
||
18556 | bpr | 2878 | @ display TYPE,color,fontsize |
2879 | @ TYPE may be x | y | xy | degree | radian | radius |
||
2880 | @ will display the mouse cursor coordinates as x-only,y-only,(x:y), the radius of a circle (this only in case 'userdraw circle(s),color') or the angle in degrees or radians for commands <code>userdraw arc,color</code> or protractor, ruler (if set dynamic). |
||
2881 | @ use commands ''xunit`` and / or ''yunit`` to add the units to the mouse values. The ''degree | radian`` will always have the appropriate symbol). |
||
2882 | @ just like commands ''mouse``, ''mousex``, ''mousey``, ''mouse_degree``... only other name |
||
2883 | @%display_x%size 400,400%xrange -10,10%yrange -10,10%xunit \\u212B%display x,red,22 |
||
2884 | @%display_y%size 400,400%xrange -10,10%yrange -10,10%yunit seconds%display y,red,22 |
||
2885 | @%display_xy%size 400,400%xrange -10,10%yrange -10,10%xunit centimetre%yunit seconds%display xy,red,22%userdraw segments,blue |
||
2886 | @%display_deg%size 400,400%xrange -10,10%yrange -10,10%display degree,red,22%fillcolor orange%opacity 200,50%userdraw arc,blue |
||
2887 | @%display_rad%size 400,400%xrange -10,10%yrange -10,10%display radian,red,22%fillcolor orange%opacity 200,50%userdraw arc,blue |
||
2888 | @%display_radius%size 400,400%xrange -10,10%yrange -10,10%xunit cm%xunit \\u212b%display radius,red,22%userdraw circle,blue |
||
18552 | bpr | 2889 | */ |
2890 | temp = get_string_argument(infile,0); |
||
2891 | if( strstr(temp,"xy") != NULL ){ |
||
2892 | int_data[0] = 2; |
||
2893 | } else { |
||
2894 | if( strstr(temp,"y") != NULL ){ |
||
2895 | int_data[0] = 1; |
||
2896 | }else{ |
||
2897 | if( strstr(temp,"x") != NULL ){ |
||
2898 | int_data[0] = 0; |
||
2899 | }else{ |
||
2900 | if(strstr(temp,"degree") != NULL){ |
||
2901 | int_data[0] = 3; |
||
2902 | js_function[JS_FIND_ANGLE] = 1; |
||
2903 | }else{ |
||
2904 | if(strstr(temp,"radian") != NULL){ |
||
2905 | int_data[0] = 4; |
||
2906 | js_function[JS_FIND_ANGLE] = 1; |
||
2907 | }else{ |
||
2908 | if(strstr(temp,"radius") != NULL){ |
||
2909 | int_data[0] = 5; |
||
2910 | }else{ |
||
2911 | int_data[0] = 2; |
||
2912 | } |
||
2913 | } |
||
2914 | } |
||
2915 | } |
||
2916 | } |
||
2917 | } |
||
2918 | stroke_color = get_color(infile,0); |
||
2919 | font_size = (int) (get_real(infile,1)); |
||
2920 | tmp_buffer = my_newmem(26); |
||
2921 | snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer); |
||
2922 | add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,int_data[0]); |
||
2923 | js_function[INTERACTIVE] = 1; |
||
2924 | break; |
||
2925 | case MOUSE_PRECISION: |
||
2926 | /* |
||
18556 | bpr | 2927 | @ precision int |
2928 | @ 1 = no decimals ; 10 = 1 decimal ; 100 = 2 decimals etc |
||
2929 | @ may be used / changed before every object |
||
2930 | @ In case of user interaction (like ''userdraw`` or ''multidraw``), this value will be used to determine the amount of decimals in the reply / answer |
||
2931 | @%precision%size 400,400%xrange -10,10%yrange -10,10%precision 1%userdraw segment,red |
||
18552 | bpr | 2932 | */ |
2933 | precision = (int) (get_real(infile,1)); |
||
2934 | if(precision < 1 ){precision = 1;}; |
||
2935 | break; |
||
2936 | case MOUSEX: |
||
2937 | /* |
||
18556 | bpr | 2938 | @ mousex color,fontsize |
2939 | @ will display the cursor x-coordinate in ''color`` and ''font size`` using the fontfamily Arial. |
||
2940 | @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``). |
||
18552 | bpr | 2941 | */ |
2942 | stroke_color = get_color(infile,0); |
||
2943 | font_size = (int) (get_real(infile,1)); |
||
2944 | tmp_buffer = my_newmem(26); |
||
2945 | snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer); |
||
2946 | add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,0); |
||
2947 | js_function[INTERACTIVE] = 1; |
||
2948 | break; |
||
2949 | case MOUSEY: |
||
2950 | /* |
||
18556 | bpr | 2951 | @ mousey color,fontsize |
2952 | @ will display the cursor y-coordinate in ''color`` and ''font size`` using default fontfamily Arial. |
||
2953 | @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``). |
||
8386 | schaersvoo | 2954 | |
18552 | bpr | 2955 | */ |
2956 | stroke_color = get_color(infile,0); |
||
2957 | font_size = (int) (get_real(infile,1)); |
||
2958 | tmp_buffer = my_newmem(26); |
||
2959 | snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer); |
||
2960 | add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,1); |
||
2961 | js_function[INTERACTIVE] = 1; |
||
2962 | break; |
||
2963 | case MULTIDASH: |
||
2964 | /* |
||
18556 | bpr | 2965 | @ multidash 0,1,1 |
2966 | @ meaning draw objects no. 2 (circle) and 3 (segments), in the list of command like <code>multifill points,circle,segments</code>, are dashed |
||
2967 | @ use before command <a href='#multidraw'>multidraw</a> |
||
2968 | @ if not set all objects will be set ''not dashed``... unless a generic keyword ''dashed`` was given before command ''multidraw`` |
||
2969 | @ the dash-type is not -yet- adjustable <br>(e.g. command <code>dashtype line_px,space_px</code> will give no control over multidraw objects) |
||
2970 | @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives... |
||
2971 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 2972 | */ |
2973 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
2974 | temp = get_string(infile,1); |
||
2975 | temp = str_replace(temp,",","\",\""); |
||
2976 | fprintf(js_include_file,"var multidash = [\"%s\"];",temp); |
||
2977 | reset();/* if command 'dashed' was given...reset to not-dashed */ |
||
2978 | break; |
||
2979 | case MULTIDRAW: |
||
2980 | /* |
||
18556 | bpr | 2981 | @ multidraw obj_type_1,obj_type_2...obj_type_11 |
2982 | @ for simple single object user drawings you could also use command <a href="#userdraw">userdraw</a> |
||
18572 | bpr | 2983 | @ implemented obj_types:<ul><li>point | points</li><li>circle | circles</li><li>line | lines</li><li>segment | segments</li><li>arrow | arrows (use command 'arrowhead int' for size (default value 8 pixels))</li><li>curvedarrow | curvedarrows</li><li>rect | rects</li><li>closedpoly<br><b>only one</b> closedpolygon may be drawn.The number of ''corner points`` is not preset (e.g. not limited, freestyle), the polygon is closed when clicking on the first point again..(+/- 10px)</li><li>triangle | triangles</li><li>parallelogram | parallelograms</li><li>poly[3-9] | polys[3-9] draw 3...9 point polygone(s): polys3 is of course triangles</li><li>images</li><li>crosshair | crosshairs</li><li>function <br>for more function user input fields, use it multiple times<br>for 4 inputfields use : multidraw function,function,function,function</li></ul> |
18556 | bpr | 2984 | @ additionally objects may be user labelled, using obj_type ''text``...<br>in this case allways a text input field and if <a href='#multiuserinput'> multiuserinput=1 </a> also (x:y) inputfields will be added to the page.<br>use commands ''fontfamily`` and ''fontcolor`` to adjust (command ''multistrokeopacity`` may be set to adjust text opacity)<br>note: text is always centered on the mouse-click or user-input coordinates !<br>note: no keyboard listeners are used |
2985 | @ it makes no sense using something like ''multidraw point,points`` ... <br>something like "multidraw polys4,polys7" will only result in drawing a ''4 point polygone`` and not a ''7 point polygone``: this is a design flaw and not a feature... |
||
2986 | @ note: mouselisteners are only active if "$status != done " (eg only drawing in an active/non-finished exercise) <br> to overrule use command/keyword "status" (no arguments required) |
||
2987 | @ buttons for changing the obj_type (and in case of ''multiuserinput``, some inputfields and buttons) <br>will be present in the reserved div ''tooltip_div`` and can be styled using command 'css some_css' |
||
2988 | @ the button label will be default the ''object primitive name`` (like ''point``, ''circles``).<br>If you want a different label (e.g. an other language), use command ''multilabel``<br>for example in dutch: <br><code>multilabel cirkel,lijnstuk,punten,STOP<br>multidraw circle,segment,points</code><br>(see command <a href='#multilabel'>multilabel</a> for more details) |
||
2989 | @ a right mouse button click will remove the last drawn object of the selected drawing type. All other type of objects are not removed |
||
2990 | @ multidraw is incompatible with command ''tooltip`` (the reserved div_area is used for the multidraw control buttons) |
||
2991 | @ all ''multidraw`` drawings will scale on zooming.<br>this in contrast to the command <a href="#userdraw">userdraw</a>. |
||
2992 | @ wims will <b>not</b> check the amount or validity of your command arguments ! <br>( use javascript console to debug any typo's ) |
||
18572 | bpr | 2993 | @ a local function <code>read_canvas%d</code> will read all userbased drawings.<br>The output is always a 16 lines string with fixed sequence.<br>line 1 = points_x+";"+points_y+"\\n"<br>line 2 = circles_x+";"+circles_y+";"+multi_radius+"\\n"<br>line 3 = segments_x+";"+segments_y+"\\n"<br>line 4 = arrows_x+";"+arrows_y+"\\n"<br>line 5 = lines_x+";"+lines_y+"\\n"<br>line 6 = triangles_x+";"+triangles_y+"\\n"<br>line 7 = polys[3-9]_x+";"+polys[3-9]_y+"\\n"<br>line 8 = rects_x +";"+rects_y+"\\n"<br>line 9 = closedpoly_x+";"+closedpoly_y+"\\n"<br>line 10 = parallelogram_x+";"+parallelogram_y"\\n"<br>line 11 = text_x+";"+text_y+";"+text"\\n"<br>line 12 = image_x+";"+image_y+";"+image_id<br>line 13 = curvedarrows_x +";"+ curvedarrows_y +"\\n"<br>line 14 = curvedarrows2_x +";"+ curvedarrows2_y +"\\n"<br>line 15 = crosshairs_x +";"+ crosshairs_y +"\\n"<br>line 16 = userdraw_x +";"+userdraw_y + "\\n" note: this is for single ''userdraw object,color`` and ''replyformat 29``<br>line 17 = userdraw_x +";"+userdraw_y +";"+userdraw_radius + "\\n" note: this is for single ''userdraw object,color`` and ''replyformat 29``<br>The x/y-data are in x/y-coordinate system and display precision may be set by a previous command ''precision 0 | 10 | 100 | 1000...``<br>In case of circles the radius is -for the time being- rounded to pixels<br><b>use the wims "direct exec" tool to see the format of the reply</b> |
18556 | bpr | 2994 | @ It is best to prepare / format the student reply in clientside javascript.<br>However in ''wims`` language you could use something like this<br>for example you are interested in the polys5 drawings of a pupil (the pupil may draw multiple poly5 objects...)<br>note: the reply for 2 poly5's is: x11,x12,x13,x14,x15,x21,x22,x23,x24,x25 ; y11,y12,y13,y14,y15,y21,y22,y23,y24,y25<br>rep = !line 7 of reply <br>rep = !translate ';' to '\\n' in $rep <br>pts = 5 # 5 points for polygon <br>x_rep = !line 1 of $rep <br>y_rep = !line 2 of $rep <br>tot = !itemcnt $x_rep <br>num_poly = $[$tot/$pts] <br>idx = 0 <br>!for p=1 to $num_poly <br> !for s=1 to $pts <br> !increase idx <br> X = !item $idx of $x_rep <br> Y = !item $idx of $y_rep <br> # do some checking <br> !next s <br>!next p <br> |
2995 | @ <b>attention</b>: for command argument ''closedpoly``, only one polygone can be drawn. The last point (e.g. the point clicked near the first point) of the array is removed. |
||
2996 | @ technical: all 10 ''draw primitives`` + ''text`` will have their own -transparent- PNG bitmap canvas. <br>So for example there can be a points_canvas entirely separated from a line_canvas.<br>This to avoid the need for a complete redraw when something is drawn to the canvas...(eg only the object_type_canvas is redrawn), this in contrast too many very slow do-it-all HTML5 canvas javascript libraries.<br>The mouselisteners are attached to the canvas-div element. |
||
2997 | @ a special object type is ''images``.<br>if used together with <a href='#imagepalette'>imagepalette</a> a image table will be integrated in the 'control section' of multidraw (set <code>multiuserinput 1</code> for ''images``) if not used with <a href='#imagepalette'>imagepalette</a>, provide the images or div's (<img> tag with bitmap or SVG or anything in a div element) somewhere on the html exercise page, with an onclick handler like:<br><code><img src='gifs/images/dog.svg' onclick='javascript:place_image_on_canvas(this.id);' id="ext_image_1" /><br><img src='gifs/fish.png' onclick='javascript:place_image_on_canvas(this.id);' id="another" /></code><br>etc ... when activating the multidraw ''image`` button, the images can be selected<br> (left mouse button/onclick) and placed on the canvas...left mouse click.<br>using div's will enable you -amongst other content- to add math typesetting from the exercise page onto the canvas. |
||
18572 | bpr | 2998 | @ When you are not content with the default ''multidraw control panel``, you can create your own interface, using a few javascript functions to call the drawprimitives, delete things and ''stop drawing`` in case you also want to drag&drop stuff...</br>To activate this feature, use <a href='#multilabel'>multilabel NOCONTROLS</a><br>The object types are internally represented by the following numbers (making typos will render your exercise null and void)<br>point = 0<br>points =1<br>circle = 2<br>circles = 3<br>line = 4<br>lines = 5<br>segment = 6<br>segments = 7<br>arrow = 8<br>arrows = 9<br>triangle = 10<br>triangles = 11<br>closedspoly = 12<br>text = 13<br>rect = 14<br>rects = 15<br>poly[3-9] = 16<br>polys[3-9] = 17<br>parallelogram = 18<br>parallelograms = 19<br>images = 20<br>curvedarrow = 21<br>curvedarrows = 22<br>curvedarrow2 = 23<br>curvedarrows2 = 24<br>crosshair = 25<br>crosshairs = 26 <br>controls for example:<br><code><input type='button' onclick='javascript:userdraw_primitive=null' value='STOP DRAWING' /><br><input type='button' onclick='javascript:userdraw_primitive=24;multidraw_object_cnt = 0;' value='start drawing curvedarrows2' /> <br><input type='button' onclick='javascript:var fun=eval("clear_draw_area"+canvas_scripts[0]);fun(24,0);' value='REMOVE LAST CURVEDARROW ' /> </code><br> If using multiple canvas scripts in a single page, loop through the canvas_scripts[n] <br>note: if using NOCONTROLS and just a single draw primitive (for example, just: 'multidraw circles'), the object may be drawn directly. (analogue to 'userdraw circles,color')<br>And since a right mouse button click will always remove the last drawn object of the current object type, there is no need for a special "remove button" |
18556 | bpr | 2999 | @%multidraw_function%size 400,400%xrange -10,10%yrange -10,10%fontfamily Italic 22px Helvetica%axis%axisnumbering%precision 0%grid 2,2,grey,1,1,5,black%multicolors red,green,blue%fontcolor orange%multilinewidth 1,2,3%multidraw text,function,function,function,line |
3000 | @%multidraw%size 400,400%xrange -10,10%yrange -10,10%multidash 1,0%multilinewidth 1,2%multistrokecolors red,blue%multisnaptogrid 1,1%multilabel LINES,CIRCLES,STOP DRAWING%multidraw lines,circles |
||
3001 | @%multidraw_images%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%drag xy%# use special function to read the drag coordinates%copy 0,0,-1,-1,-1,-1,gifs/images/skull_and_crossbones50.png%fontcolor green%fontfamily Bold 42pt Arial%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multiuserinput 0,0,1%css color:blue;%multisnaptogrid 1,1,1%multilinewidth 0,4,0%# attention: use unicode text input without the slash %# \u222D ---> u222D at least will sometimes work%# otherwise cut&past unicode symbols into inputfield...%multilabel TEXT,REACTION ARROW,FLAGS,STOP DRAWING%multidraw text,arrow,images |
||
3002 | @%multidraw_demo%size 800,800%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%css color:blue;%fontfamily Italic 42pt Arial%precision 1%opacity 200,50%snaptogrid%linewidth 3%filled%multistrokecolors red,green,blue,orange,yellow,purple,black,cyan,red,green,blue,orange,green,purple,black,cyan%multifillcolors red,green,blue,orange,yellow,purple,black,cyan,red,green,blue,orange,brown,purple%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multidraw closedpoly,segments,rect,parallelogram,triangles,poly5,points,lines,arrows,circles,text,curvedarrows,curvedarrows2,images |
||
3003 | @%multidraw_NOCONTROLS%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%linewidth 3%strokecolor green%fillcolor blue%filled%opacity 255,60%multilabel NOCONTROLS%multidraw circles%# RIGHT MOUSE CLICK REMOVES LAST OBJECT |
||
18552 | bpr | 3004 | */ |
3005 | js_function[INTERACTIVE] = 1; |
||
3006 | if(js_function[JS_ZOOM] == 1){use_zoom = 1;} /* use noisy zoom_code, when command zoom is given before command 'multidraw' */ |
||
3007 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3008 | if( use_userdraw == 1 ){canvas_error("Only one userdraw primitive may be used in command 'userdraw' use command 'multidraw' for this...");} |
||
3009 | use_userdraw = 2; |
||
3010 | temp = get_string(infile,1); |
||
3011 | fprintf(js_include_file,"\ |
||
3012 | var MMP = %d;\ |
||
3013 | if( typeof(multisnaptogrid) == 'undefined' && multisnaptogrid == null){var multisnaptogrid = new Array(MMP);for(var i=0;i<MMP;i++){multisnaptogrid[i] = %d;};};\ |
||
3014 | if( typeof(multistrokecolors) === 'undefined' && multistrokecolors == null){ var multistrokecolors = new Array(MMP);for(var i=0;i<MMP;i++){multistrokecolors[i] = '%s';};};\ |
||
3015 | if( typeof(multifillcolors) === 'undefined' && multifillcolors == null ){var multifillcolors = new Array(MMP);for(var i=0;i<MMP;i++){multifillcolors[i] = '%s';};};\ |
||
3016 | if( typeof(multistrokeopacity) === 'undefined' && multistrokeopacity == null){var multistrokeopacity = new Array(MMP);for(var i=0;i<MMP;i++){multistrokeopacity[i] = %.2f;};};\ |
||
3017 | if( typeof(multifillopacity) === 'undefined' && multifillopacity == null){var multifillopacity = new Array(MMP);for(var i=0;i<MMP;i++){multifillopacity[i] = %.2f;};};\ |
||
3018 | if( typeof(multilinewidth) === 'undefined' && multilinewidth == null){var multilinewidth = new Array(MMP);for(var i=0;i<MMP;i++){multilinewidth[i] = %d;};};\ |
||
3019 | if( typeof(multifill) === 'undefined' && multifill == null){var multifill = new Array(MMP);for(var i=0;i<MMP;i++){multifill[i] = %d;};};\ |
||
3020 | if( typeof(multidash) === 'undefined' && multidash == null){var multidash = new Array(MMP);for(var i=0;i<MMP;i++){multidash[i] = %d;};};\ |
||
3021 | if( typeof(multilabel) === 'undefined' && multilabel == null){var multilabel = [\"%s\",\"stop drawing\"];};\ |
||
3022 | if( typeof(multiuserinput) === 'undefined' && multiuserinput == null){var multiuserinput = new Array(MMP);for(var i=0;i<MMP;i++){multiuserinput[i] = '0';};};\ |
||
3023 | var arrow_head = %d;var multifont_color = '%s';var multifont_family = '%s';var forbidden_zone = [xsize+2,ysize+2];", |
||
3024 | MAX_MULTI_PRIMITIVES, |
||
3025 | use_snap, |
||
3026 | stroke_color, |
||
3027 | fill_color, |
||
3028 | stroke_opacity, |
||
3029 | fill_opacity, |
||
3030 | line_width, |
||
3031 | use_filled, |
||
3032 | use_dashed, |
||
3033 | str_replace(temp,",","\",\""), |
||
3034 | arrow_head,font_color,font_family); |
||
3035 | add_js_multidraw(temp,css_class,use_offset,int_data[MAX_MULTI_PRIMITIVES+1],crosshair_size,use_zoom); |
||
3036 | /* no_controls == int_data[MAX_MULTI_PRIMITIVES+1] */ |
||
3037 | reply_precision = precision; |
||
3038 | if(strstr(temp,"text") != NULL){ |
||
3039 | js_function[JS_SAFE_EVAL] = 1; |
||
3040 | js_function[DRAW_SUBSUP] = 1; |
||
3041 | } |
||
3042 | if(strstr(temp,"function") != NULL){ |
||
3043 | int pp, funs = count_substring(temp, "function"); |
||
3044 | js_function[JS_SAFE_EVAL] = 1; |
||
3045 | js_function[JS_RAWMATH] = 1; |
||
3046 | js_function[DRAW_JSFUNCTION] = 1; |
||
3047 | js_function[JS_MATH] = 1; |
||
3048 | js_function[JS_PLOT] = 1; |
||
3049 | for(pp = 0 ; pp< funs ;pp++){ |
||
3050 | add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size); |
||
3051 | input_cnt++; |
||
3052 | jsplot_cnt++; |
||
3053 | } |
||
3054 | fprintf(js_include_file,"if(typeof(all_jsplots) !== 'number'){var all_jsplots;};all_jsplots = %d;function redraw_userdraw(){redraw_jsplot();return;};",jsplot_cnt); |
||
3055 | } |
||
3056 | /* the canvasses range from 1000 ... 1008 */ |
||
3057 | if( reply_format == 0){reply_format = 29;} |
||
3058 | reset();/* if command 'filled' / 'dashed' was given...reset all */ |
||
3059 | break; |
||
3060 | case MULTILABEL: |
||
3061 | /* |
||
18556 | bpr | 3062 | @ multilabel button_label_1,button_label_2,...,button_label_8,'stop drawing text' |
3063 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3064 | @ if not set all labels (e.g. the value of input type 'button') will be set by the english names for the draw_primitives (like 'point','circle'...) |
||
3065 | @ the ''stop drawing`` button text <b>must</b> be the last item on the ''multilabel`` -list <br>for example:<br><code>multilabel punten,lijnen,Stop met Tekenen<br>multidraw points,lines</code> |
||
3066 | @ all buttons can be ''styled`` by using command <code>css</code><br><b>note:</b>If you want to add some CSS style to the buttons...<br>the id's of the ''draw buttons`` are their english command argument<br>(e.g. id="canvasdraw_points" for the draw points button).<br>the id of the ''stop drawing`` button is "canvasdraw_stop_drawing".<br>the id of the "OK" button is ''canvasdraw_ok_button`` |
||
3067 | @ wims will not check the amount or validity of your input |
||
3068 | @ always use the same sequence as is used for ''multidraw`` |
||
3069 | @ if you don't want the controls, and want to write your own interface, set <code>multilabel NOCONTROLS</code> |
||
18552 | bpr | 3070 | */ |
3071 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3072 | temp = get_string(infile,1); |
||
3073 | if( strcasestr(temp,"NOCONTROLS") ){ |
||
3074 | int_data[MAX_MULTI_PRIMITIVES+1] = 1; /*int_data[25] = 1 --> 'no_controls = 1' in canvasmacro.c */ |
||
3075 | fprintf(js_include_file,"var multilabel = null;"); |
||
3076 | } |
||
3077 | else { |
||
3078 | int_data[MAX_MULTI_PRIMITIVES+1] = 0; /* so DO use control buttons etc */ |
||
3079 | temp = str_replace(temp,",","\",\""); |
||
3080 | fprintf(js_include_file,"var multilabel = [\"%s\"];",temp); |
||
3081 | } |
||
3082 | break; |
||
3083 | case MULTILINEWIDTH: |
||
3084 | /* |
||
18556 | bpr | 3085 | @ multilinewidth linewidth_1,linewidth_2,...,linewidth_8 |
3086 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3087 | @ if not set all line widths will be set by a previous command ''linewidth int`` |
||
3088 | @ use these up to 7 different line widths for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code> |
||
3089 | @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives... |
||
3090 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 3091 | */ |
3092 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3093 | temp = get_string(infile,1); |
||
3094 | temp = str_replace(temp,",","\",\""); |
||
3095 | fprintf(js_include_file,"var multilinewidth = [\"%s\"];",temp); |
||
3096 | break; |
||
3097 | case MULTIFILL: |
||
3098 | /* |
||
18556 | bpr | 3099 | @ multifill 0,0,1,0,1,0,0 |
3100 | @ meaning draw objects no. 3 and 5, in the list of command ''multifill``, are filled (if the object is fillable...and not a line,segment,arrow or point...) |
||
3101 | @ using a fillpattern: multifill 0,1,2,5,3,4<br>meaning: first object is not filled...second object is solid color filled...2=grid | 3=hatch | 4=diamond | 5=dot |
||
3102 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3103 | @ if not set all objects -except point|points- will be set ''not filled``... unless a command <code>filled</code> was given before command <code>multifill</code> |
||
3104 | @ only suitable for draw_primitives like ''circle | circles``, ''triangle | triangles``, ''rect | rects``, ''poly[3-9] | polys[3-9]`` and ''polygon`` |
||
3105 | @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives... |
||
3106 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 3107 | */ |
3108 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3109 | i=0; |
||
3110 | while( ! done ){ /* get next item until EOL*/ |
||
3111 | if(i > MAX_MULTI_PRIMITIVES){canvas_error("too many multidraw primitives...read the documentation...");} |
||
3112 | int_data[i] = (int)(get_real(infile,1)); /* 0,1,2,3,4,5 */ |
||
3113 | if(int_data[i] < 0 || int_data[i] > 5 ){canvas_error("the only possible multifill arguments are: 0,1,2,3,4,5 ");} |
||
3114 | if(int_data[i] > 1 ){use_filled = 2;js_function[DRAW_FILL_PATTERN] = 1;}/* switch to trigger pattern filling */ |
||
3115 | i++; |
||
3116 | } |
||
3117 | fprintf(js_include_file,"var multifill = %s ;",data2js_array(int_data,i-1)); |
||
3118 | break; |
||
3119 | case MULTIFILLCOLORS: |
||
3120 | /* |
||
18556 | bpr | 3121 | @ multifillcolors color_name_1,color_name_2,...,color_name_8 |
3122 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3123 | @ if not set all fillcolors (for circle | triangle | poly[3-9] | closedpoly ) will be ''stroke_color``, ''fill_opacity`` |
||
3124 | @ use these up to 6 colors for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_n</code> |
||
3125 | @ wims will <b>not</b> check if the number of colours matches the amount of draw primitives... |
||
3126 | @ always use the same sequence as is used for ''multidraw`` |
||
3127 | @ can also be used with command <a href='#userdraw'>userdraw clickfill,color</a> when more than one fillcolor is wanted.<br>in that case use for example <a href='#replyformat'>replyformat 10</a> ... reply=x1:y1:color1,x2:y2:color2...<br>the colors will restart at the first color, when there are more fill-clicks than multi-fill-colors<br>if more control over the used colours is wanted, see command <a href='#colorpalette'>colorpalette color1,color2...</a> |
||
18552 | bpr | 3128 | */ |
3129 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3130 | fprintf(js_include_file,"var multifillcolors = ["); |
||
3131 | while( ! done ){ |
||
3132 | temp = get_color(infile,1); |
||
3133 | fprintf(js_include_file,"\"%s\",",temp); |
||
3134 | } |
||
3135 | fprintf(js_include_file,"\"0,0,0\"];");/* add black to avoid trouble with dangling comma... */ |
||
3136 | break; |
||
3137 | case MULTIFILLOPACITY: |
||
3138 | /* |
||
18556 | bpr | 3139 | @ multifillopacity fill_opacity_1,fill_opacity_2,...,fill_opacity_8 |
3140 | @ float values 0 - 1 or integer values 0 - 255 |
||
3141 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3142 | @ if not set all fill opacity_ will be set by previous command <code>opacity int,int</code> and keyword ''filled`` |
||
3143 | @ use these up to 7 different stroke opacities for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_y</code> |
||
3144 | @ wims will not check the amount or validity of your input |
||
3145 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 3146 | */ |
3147 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3148 | temp = get_string(infile,1); |
||
3149 | temp = str_replace(temp,",","\",\""); |
||
3150 | fprintf(js_include_file,"var multifillopacity = [\"%s\"];",temp); |
||
3151 | break; |
||
3152 | case MULTISNAPTOGRID: |
||
3153 | /* |
||
18556 | bpr | 3154 | @ multisnaptogrid 0,1,1 |
3155 | @ alternative: multisnap |
||
3156 | @ meaning draw objects no. 2 (circle) and 3 (segments), in the list of command like <code>multifill points,circle,segments</code>, will snap to the xy-grid (default 1 in x/y-coordinate system: see command <a href='#snaptogrid'>snaptogrid</a>) |
||
3157 | @ freehand drawing...specify precision for reply: all objects snap to grid <code>multisnaptogrid 1,1,1,...</code> |
||
3158 | @ only the xy-values snap_to_grid: all objects snap to grid <code>multisnaptogrid 1,1,1,...</code> |
||
3159 | @ only the x-values snap_to_grid: all objects snap to x-grid <code>multisnaptogrid 2,2,2,...</code> |
||
3160 | @ only the y-values snap_to_grid: all objects snap to y-grid <code>multisnaptogrid 3,3,3,...</code> |
||
3161 | @ if <a href='#snaptopoints'>snaptopoints</a> is defined: all objects snap to points <code>multisnaptogrid 4,4,4,...</code> <br><b>make sure to define the points to snap on...</b> use command <a href='#snaptopoints'>snaptopoints</a> |
||
3162 | @ <code>multisnaptogrid 0,1,2,3,4<br>multidraw text,arrow,line,circle,image</code><br>''text`` is free hand, ''arrow`` is snap to grid, ''line`` is snap to x-grid, ''circle`` is snap to y-grid, ''image`` is snap to points defined by command <a href='#snaptopoints'>snaptopoints</a> |
||
3163 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3164 | @ attention: if not set all objects will be set ''no snap``... unless a generic command ''snaptogrid`` was given before command ''multidraw`` |
||
3165 | @ commands <a href='#xsnaptogrid'>xsnaptogrid</a>, <a href='#ysnaptogrid'>ysnaptogrid</a>, <a href='#snaptofunction'>snaptofunction</a> are <b>not</b> supported amd only functional for command <a href='#userdraw'>userdraw</a> |
||
3166 | @ always use the same sequence as is used for ''multidraw`` |
||
3167 | @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives... |
||
18552 | bpr | 3168 | */ |
3169 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3170 | temp = get_string(infile,1); |
||
3171 | fprintf(js_include_file,"var multisnaptogrid = [%s];",temp); |
||
3172 | reset();/* if command 'dashed' was given...reset to not-dashed */ |
||
3173 | break; |
||
3174 | case MULTISTROKECOLORS: |
||
3175 | /* |
||
18556 | bpr | 3176 | @ multistrokecolors color_name_1,color_name_2,...,color_name_8 |
3177 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3178 | @ if not set all colors will be ''stroke_color``, ''stroke_opacity`` |
||
3179 | @ use these up to 6 colors for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code> |
||
3180 | @ wims will <b>not</b> check if the number of colours matches the amount of draw primitives... |
||
3181 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 3182 | */ |
3183 | if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3184 | fprintf(js_include_file,"var multistrokecolors = ["); |
||
3185 | while( ! done ){ |
||
3186 | temp = get_color(infile,1); |
||
3187 | fprintf(js_include_file,"\"%s\",",temp); |
||
3188 | } |
||
3189 | fprintf(js_include_file,"\"0,0,0\"];");/* add black to avoid trouble with dangling comma... */ |
||
3190 | break; |
||
3191 | case MULTISTROKEOPACITY: |
||
3192 | /* |
||
18556 | bpr | 3193 | @ multistrokeopacity stroke_opacity_1,stroke_opacity_2,...,stroke_opacity_7 |
3194 | @ float values 0 - 1 or integer values 0 - 255 |
||
3195 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3196 | @ if not set all stroke opacity_ will be set by previous command <code>opacity int,int</code> |
||
3197 | @ use these up to 7 different stroke opacities for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code> |
||
3198 | @ wims will not check the amount or validity of your input |
||
3199 | @ always use the same sequence as is used for ''multidraw`` |
||
18552 | bpr | 3200 | */ |
3201 | if( use_tooltip == 1){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");} |
||
3202 | temp = get_string(infile,1); |
||
3203 | temp = str_replace(temp,",","\",\""); |
||
3204 | fprintf(js_include_file,"var multistrokeopacity = [\"%s\"];",temp); |
||
3205 | break; |
||
3206 | case MULTIUSERINPUT: |
||
3207 | /* |
||
3208 | @ multiuserinput 0,1,1,0 |
||
3209 | @ alternative: multiinput |
||
18572 | bpr | 3210 | @ meaning, when the command ''multidraw`` is used <code>multidraw circles,points,lines,triangles</code><br>objects ''points`` and ''lines`` may additionally be ''drawn`` by direct input (inputfields)<br>all other objects must be drawn with a mouse |
18552 | bpr | 3211 | @ in case of circle | circles a third inputfield for Radius (R) is added. The radius must be in the x/y coordinate system (x-range) and <b>not</b> in pixels...students don't think in pixels.<br>note: R-values will not snap-to-grid |
3212 | @ in case of line(s) | segment(s) | arrow(s) the user should write <b>x1:y1</b> in the first inputfield and <b>x2:y2</b> in the second.<br>These ''hints`` are pre-filled into the input field.<br>Other coordinate delimiters are '';`` and '',`` e.g. <b>x1;y1</b> or <b>x1,y1</b>.<br>An error message (alert box) will popup when things are not correctly... |
||
3213 | @ in case of a triangle | poly3, three inputfields are provided. |
||
3214 | @ in case of ''text`` and ''multiuserinput=1, 3`` inputfields will be shown: ''x,y,text`` |
||
3215 | @ in case of ''text`` and ''multiuserinput=0, 1`` inputfield will be shown: text ... a mouse click will place the text on the canvas. |
||
3216 | @ may be styled using command <a href="#css">css</a> |
||
3217 | @ an additional button ''stop drawing`` may be used to combine userbased drawings with ''drag∧drop`` or ''onclick`` elements |
||
3218 | @ when exercise if finished (status=done) the buttons will not be shown.<br>To override this default behaviour use command / keyword ''status`` |
||
3219 | @ use before command <a href='#multidraw'>multidraw</a> |
||
3220 | @ always use the same sequence as is used for ''multidraw`` |
||
3221 | */ |
||
3222 | /* simple rawmath and input check */ |
||
3223 | js_function[JS_SAFE_EVAL] = 1; |
||
3224 | temp = get_string(infile,1); |
||
3225 | temp = str_replace(temp,",","\",\""); |
||
3226 | fprintf(js_include_file,"var multiuserinput = [\"%s\"];",temp); |
||
3227 | break; |
||
3228 | case NORESET: |
||
3229 | /* |
||
3230 | @ noreset |
||
3231 | @ alternative: killreset |
||
3232 | @ keyword |
||
3233 | @ may come in handy if canvas script code is generated using loops |
||
3234 | @ if used the following properties will remain to be valid<br><ul><li>filled</li><li>dash settings</li><li>onclick or drag settings</li><li>centering or offset</li></ul> |
||
3235 | @ if used again, these properies will be reset to the default values and normal behaviour is continued (e.g. the above properties will be reset after 'use' on a canvas object) |
||
3236 | @ etc etc |
||
3237 | @ commands <a href='#slider'>slider</a>, <a href='#linear'>linear</a>, <a href='#rotate'>rotate</a>, <a href='#translate'>translate</a>, <a href='#affine'>affine</a> are always active until the 'kill' commands are given: <br><a href='#killlinear'>killlinear</a>, <a href='#killrotate'>killrotate</a>, <a href='#killtranslate'>killtranslate</a> and <a href='#killaffine'>killaffine</a> |
||
3238 | @ commands like 'opacity', 'linewidth', 'fontsize', 'fontfamily' are only changed when redefined again |
||
3239 | @%noreset%size 400,400%xrange -10,10%yrange -10,10%noreset%drag xy%linewidth 4%filled%rect -4,4,-2,2,blue%triangle -3,-3,0,0,1,-5,green%circle 0,0,50,orange%noreset%rect 2,4,4,2,blue |
||
3240 | @%noreset_oefgraduation%size 800,100%xrange 0,11%yrange -1,1%hline 0,0,black%parallel 0,0,0,0.5,1,0,11,blue%noreset%onclick%centered%text black,1,0.6,large,20%text black,2,0.6,large,30%text black,3,0.6,large,40%text black,4,0.6,large,50%text black,5,0.6,large,60%text black,6,0.6,large,70%text black,7,0.6,large,80%text black,8,0.6,large,90%text black,9,0.6,large,100%text black,10,0.6,large,110 |
||
3241 | */ |
||
3242 | if(no_reset == FALSE){no_reset = TRUE;}else{no_reset = FALSE;reset();} |
||
3243 | break; |
||
3244 | case NOXAXIS: |
||
3245 | /* |
||
3246 | @ noxaxis |
||
3247 | @ keyword |
||
3248 | @ if set, the automatic x-axis numbering will be ignored |
||
3249 | @ use command <a href="#axis">axis</a> to have a visual x/y-axis lines (see command <a href="#grid">grid</a>) |
||
3250 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
3251 | */ |
||
3252 | fprintf(js_include_file,"x_strings = {};x_strings_up = [];\n"); |
||
3253 | use_axis_numbering = -1; |
||
3254 | break; |
||
3255 | case NOYAXIS: |
||
3256 | /* |
||
3257 | @ noyaxis |
||
3258 | @ keyword |
||
3259 | @ if set, the automatic y-axis numbering will be ignored |
||
3260 | @ use command <a href="#axis">axis</a> to have a visual x/y-axis lines (see command <a href="#grid">grid</a>) |
||
3261 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
3262 | */ |
||
3263 | fprintf(js_include_file,"y_strings = {};\n"); |
||
3264 | break; |
||
3265 | case NUMBERLINE: |
||
3266 | /* |
||
3267 | @ numberline x0,x1,xmajor,xminor,y0,y1 |
||
3268 | @ numberline is using xrange/yrange system for all dimensions |
||
3269 | @ multiple numberlines are allowed ; combinations with command <a href='#grid'>grid</a> is allowed; multiple commands <a href='#xaxis'>xaxis numbering</a> are allowed |
||
3270 | @ x0 is start x-value in xrange |
||
3271 | @ x1 is end x-value in xrange |
||
3272 | @ xmajor is step for major division |
||
3273 | @ xminor is divisor of xmajor; using small (30% of major tick) tick marks: this behaviour is ''hardcoded`` |
||
3274 | @ is xminor is an even divisor, an extra tickmark (60% of major tick) is added to the numberline: this behaviour is ''hardcoded`` |
||
3275 | @ y0 is bottom of numberline; y1 endpoint of major tics |
||
3276 | @ use command <a href="#linewidth">linewidth</a> to control appearance |
||
3277 | @ use <a href="#strokecolor">strokecolor</a> and <a href="#opacity">opacity</a> to controle measure line |
||
3278 | @ for all ticks linewidth and color / opacity are identical. |
||
3279 | @ if command <a href="#xaxis">xaxis</a> or <a href="#xaxisup">xaxisup</a> is not defined, the labeling will be on major ticks: x0...x1 |
||
3280 | @ use <a href="#fontfamily">fontfamily</a> and <a href="#fontcolor">fontcolor</a> to control fonts settings |
||
3281 | @ may be used together with <a href="#userdraw">userdraw</a>, <a href="#multidraw">multidraw</a> and <a href="#drag">user drag</a> command family for the extra object drawn onto the numberline |
||
3282 | @ <a href="#snaptogrid">snaptogrid, snaptopoints etc</a> and <a href="#zoom">zooming and panning</a> is supported |
||
3283 | @ onclick and dragging of the numberline are not -yet- supported |
||
3284 | @ note: in case of multiple numberlines, make sure the numberline without special x-axis numbering (e.g. ranging from xmin to xmax) comes first ! |
||
3285 | @%numberline%size 400,400%xrange -10,10%yrange -10,10%precision 1%strokecolor black%numberline -8,8,1,6,-4,-3.5%strokecolor red%xaxis -4:AA:-2:BB:2:CC:4:DD%numberline -8,8,1,2,4,4.5%strokecolor green%xaxisup -4:AAA:-2:BBB:2:CCC:4:DDD%numberline -8,8,1,3,2,2.5%strokecolor blue%xaxis -4:AAAA:-2:BBBB:2:CCCC:4:DDDD%numberline -8,8,1,4,0,0.5%strokecolor brown%xaxis -4:AAAAA:-2:BBBBB:2:CCCCC:4:DDDDD%numberline -8,8,1,5,-2,-1.5%zoom red |
||
3286 | */ |
||
3287 | js_function[DRAW_NUMBERLINE] = 1; |
||
3288 | for(i=0;i<6;i++){ |
||
3289 | switch(i){ |
||
3290 | case 0: double_data[0] = get_real(infile,0);break;/* xmin */ |
||
3291 | case 1: double_data[1] = get_real(infile,0);break;/* xmax */ |
||
3292 | case 2: double_data[2] = get_real(infile,0);break;/* xmajor */ |
||
3293 | case 3: double_data[3] = get_real(infile,0);break;/* xminor */ |
||
3294 | case 4: double_data[4] = get_real(infile,0);break;/* ymin */ |
||
3295 | case 5: double_data[5] = get_real(infile,1);/* ymax */ |
||
3296 | /* |
||
3297 | var draw_numberline%d = function(canvas_type,xmin,xmax,xmajor,xminor,ymin,ymax,linewidth,strokecolor,strokeopacity,fontfamily,fontcolor); |
||
3298 | */ |
||
3299 | fprintf(js_include_file,"snap_x = %f;snap_y = %f;",double_data[2] / double_data[3],double_data[5] - double_data[4] ); |
||
18557 | bpr | 3300 | tmp_buffer=my_newmem(MAX_BUFFER); |
3301 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "\ndraw_numberline(%d,%d,%f,%f,%f,%f,%f,%f,%d,\"%s\",%f,\"%s\",\"%s\",%d); ",NUMBERLINE_CANVAS+numberline_cnt,use_axis_numbering,double_data[0],double_data[1],double_data[2],double_data[3],double_data[4],double_data[5],line_width,stroke_color,stroke_opacity,font_family,font_color,precision)); |
||
18552 | bpr | 3302 | add_to_buffer(tmp_buffer); |
3303 | numberline_cnt++; |
||
3304 | break; |
||
3305 | default:break; |
||
3306 | } |
||
3307 | } |
||
3308 | reset(); |
||
3309 | break; |
||
3310 | case OBABEL: |
||
3311 | /* |
||
3312 | @ obabel x,y,type input,molecule smiles-code or file location, extra arguments,extra arguments,... |
||
3313 | @ will call the ''obabel`` program, if installed. |
||
3314 | @ output will be an svg file |
||
3315 | @ see documentation of obabel for special keys |
||
3316 | @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations |
||
3317 | @ command <a href='#rotate'>rotate</a> will rotate the object |
||
3318 | @ can be set onclick: <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects<br>if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object |
||
3319 | @ can be set draggable: <code>javascript:read_dragdrop();</code> will return all coordinates in the same order as the canvas script: unmoved object will have their original coordinates... |
||
3320 | @ snaptogrid is supported...snaptopoints will work, but use with care...due to the primitive dragging<br>technically: the dragstuff library is not used...the mathml is embedded in a new div element and not in the html5-canvas |
||
3321 | @ external files may be loaded if they are present on the server or in the modules <br>for example:<br> obabel 0,0,mol,$module_dir/caffeine.mol,-P100,-xb none |
||
3322 | @%obabel_smi%size 400,400%xrange -10,10%yrange -10,10%fillcolor green%drag xy%centered%obabel 0,0,smi,-:c1cFccc1cc,-xb none,-xB blue,-xi,-xt,-xa,-xX,-xP180,-h |
||
3323 | */ |
||
3324 | js_function[DRAW_XML] = 1; |
||
3325 | for(i=0;i<4;i++){ |
||
3326 | switch(i){ |
||
3327 | case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */ |
||
3328 | case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system -> pixel height */ |
||
3329 | case 2: URL = get_string_argument(infile,0);break; |
||
3330 | case 3: |
||
3331 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3332 | temp = getSVGMOL(URL,get_string(infile,1)); |
||
3333 | decimals = find_number_of_digits(precision); |
||
3334 | if(use_affine == TRUE ){ transform(2,2);} |
||
3335 | if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */ |
||
3336 | int_data[0] = x2px(double_data[0]); |
||
3337 | int_data[1] = y2px(double_data[1]); |
||
3338 | if( use_slider != -1 && onclick == 0 ){ onclick = 3;}/* no drag&onclick but slideable */ |
||
3339 | if( use_slider != -1 && drag_type > 0 ){ onclick = 5;}/* slider+drag*/ |
||
3340 | if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); } |
||
18557 | bpr | 3341 | tmp_buffer=my_newmem(MAX_BUFFER); |
3342 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'svg',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};slidergroup[%d] = null;draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,object_cnt,drawxml_cnt)); |
||
18552 | bpr | 3343 | add_to_buffer(tmp_buffer); |
3344 | if(onclick != 0 ){object_cnt++;} |
||
3345 | drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */ |
||
3346 | break; |
||
3347 | default:break; |
||
3348 | } |
||
3349 | } |
||
3350 | reset(); |
||
3351 | break; |
||
3352 | case OPACITY: |
||
3353 | /* |
||
3354 | @ opacity [0-255],[0-255] |
||
3355 | @ opacity [0.0 - 1.0],[0.0 - 1.0] |
||
3356 | @ alternative: transparent |
||
3357 | @ first item is stroke opacity, second is fill opacity |
||
3358 | @%opacity%size 400,400%xrange -10,10%yrange -10,10%opacity 255,0%fcircle -10,0,100,blue%opacity 250,50%fcircle -5,0,100,blue%opacity 200,100%fcircle 0,0,100,blue%opacity 150,150%fcircle 5,0,100,blue%opacity 100,200%fcircle 10,0,100,blue |
||
3359 | */ |
||
3360 | for(i = 0 ; i<2;i++){ |
||
3361 | switch(i){ |
||
3362 | case 0: double_data[0]= get_real(infile,0);break; |
||
3363 | case 1: double_data[1]= get_real(infile,1);break; |
||
3364 | default: break; |
||
3365 | } |
||
3366 | } |
||
3367 | if( double_data[0] > 255 || double_data[1] > 255 || double_data[0] < 0 || double_data[1] < 0 ){ canvas_error("opacity [0 - 255], [0 - 255] ");}/* typo or non-RGB ? */ |
||
18608 | bpr | 3368 | if( double_data[0] > 1 ){ stroke_opacity = (double) (0.0039215*double_data[0]); }else{ stroke_opacity = double_data[0];} /* 0.0 - 1.0 */ |
3369 | if( double_data[1] > 1 ){ fill_opacity = (double) (0.0039215*double_data[1]); }else{ fill_opacity = double_data[1];} /* 0.0 - 1.0 */ |
||
18552 | bpr | 3370 | break; |
18608 | bpr | 3371 | case STROKEOPACITY: |
3372 | /* |
||
3373 | @ strokeopacity [0-255] |
||
3374 | @ strokeopacity [0.0 - 1.0] |
||
3375 | @%strokeopacity%size 400,400%xrange -10,10%yrange -10,10%fillopacity 120%strokeopacity 255%circle -10,0,100,blue%strokeopacity 100%circle -5,0,100,blue%strokeopacity 50%circle 0,0,100,blue |
||
3376 | */ |
||
3377 | double_data[0]= get_real(infile,1); |
||
3378 | if( double_data[0] > 255 || double_data[0] < 0 ){ canvas_error("opacity [0 - 255] ");}/* typo or non-RGB ? */ |
||
3379 | if( double_data[0] > 1 ){ stroke_opacity = (double) (0.0039215*double_data[0]); }else{ stroke_opacity = double_data[0];} /* 0.0 - 1.0 */ |
||
3380 | break; |
||
3381 | case FILLOPACITY: |
||
3382 | /* |
||
3383 | @ fillopacity [0-255] |
||
3384 | @ fillopacity [0.0 - 1.0] |
||
3385 | @%fillopacity%size 400,400%xrange -10,10%yrange -10,10%strokeopacity 100%%fillopacity 0%fcircle -10,0,100,blue%fillopacity 50%fcircle -5,0,100,blue%fillopacity 100%fcircle 0,0,100,blue%fillopacity 150%fcircle 5,0,100,blue%fillopacity 200%fcircle 10,0,100,blue |
||
3386 | */ |
||
3387 | double_data[0]= get_real(infile,1); |
||
3388 | if( double_data[0] > 255 || double_data[0] < 0 ){ canvas_error("fillopacity [0 - 255] ");}/* typo or non-RGB ? */ |
||
3389 | if( double_data[0] > 1 ){ fill_opacity = (double) (0.0039215*double_data[0]); }else{ fill_opacity = double_data[0];} /* 0.0 - 1.0 */ |
||
3390 | break; |
||
18552 | bpr | 3391 | case ONCLICK: |
3392 | /* |
||
18556 | bpr | 3393 | @ onclick |
3394 | @ keyword (no arguments required) |
||
3395 | @ if the next object is clicked, its ''object onclick_or_drag sequence number`` in fly script is returned by <code>javascript:read_canvas();</code> |
||
3396 | @ onclick seqeuence numbering starts at ''0``, e.g. if there are 6 objects set onclick, the first onclick object will have id-number ''0``, the last id-number ''5`` |
||
3397 | @ line based objects will show an increase in line width<br>font based objects will show the text in ''bold`` when clicked. |
||
3398 | @ the click zone (accuracy) is determined by 2× the line width of the object |
||
3399 | @ onclick and <a href="#drag">drag x|y|xy</a> may be combined in a single flyscript (although a single object can <b>not</b> be onclick and draggable at the same time...) |
||
3400 | @ note: not all objects may be set onclick |
||
3401 | @%onclick%size 400,400%xrange -10,10%yrange -10,10%opacity 255,60%linewidth 3%onclick%fcircles blue,-3,3,1,1,2,2,3,1,1%onclick%ftriangles red,-4,-4,-4,0,-3,-2,0,0,4,0,2,-4%onclick%frects green,-4,4,-2,2,1,-1,3,-4 |
||
18552 | bpr | 3402 | */ |
3403 | fprintf(js_include_file,"use_dragdrop_reply = true;"); |
||
3404 | onclick = 1; |
||
3405 | use_dragstuff=2; |
||
3406 | js_function[INTERACTIVE] = 1; |
||
3407 | break; |
||
3408 | case PARALLEL: |
||
3409 | /* |
||
18556 | bpr | 3410 | @ parallel x1,y1,x2,y2,dx,dy,n,[colorname or #hexcolor] |
3411 | @ affine transformations should be identical to flydraw |
||
3412 | @ in case of <a href='#rotate'>rotation</a> or <a href='#affine'>affine transformation </a>, command parallel will produce <em>n</em> individual segments, and these may be set ''onclick`` or ''drag xy`` individually. |
||
3413 | @ in case of <em>no rotation or transformations</em> the lines can not be set ''onclick`` or ''drag xy``. |
||
3414 | @ note: a large number of parallel lines (large <em>n</em>) may result in a canvasdraw error (...simplify your script...it produces too many lines...) |
||
3415 | @%parallel_click%size 400,400%xrange -10,10%yrange -10,10%parallel -5,5,-4,-5,0.25,0,40,red%rotate 45%onclick%parallel -5,5,-4,-5,0.25,0,40,blue |
||
3416 | @%parallel%size 400,400%xrange -10,10%yrange -10,10%parallel -5,5,-4,-5,0.25,0,40,red |
||
18552 | bpr | 3417 | */ |
3418 | decimals = find_number_of_digits(precision); |
||
3419 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3420 | if( use_rotate == TRUE || use_affine == TRUE ){ |
||
3421 | for( i = 0;i < 8; i++ ){ |
||
3422 | switch(i){ |
||
3423 | case 0: double_data[0] = get_real(infile,0);break; /* x1-values */ |
||
3424 | case 1: double_data[1] = get_real(infile,0);break; /* y1-values */ |
||
3425 | case 2: double_data[2] = get_real(infile,0);break; /* x2-values */ |
||
3426 | case 3: double_data[3] = get_real(infile,0);break; /* y2-values */ |
||
3427 | case 4: double_data[4] = get_real(infile,0);break; /* xv */ |
||
3428 | case 5: double_data[5] = get_real(infile,0);break; /* yv */ |
||
3429 | case 6: int_data[0] = (int) (get_real(infile,0));break; /* n */ |
||
3430 | case 7: stroke_color=get_color(infile,1);break;/* name or hex color */ |
||
3431 | default: break; |
||
3432 | } |
||
3433 | } |
||
3434 | double_data[6] = double_data[0]; /* x1 */ |
||
3435 | double_data[7] = double_data[1]; /* y1 */ |
||
3436 | double_data[8] = double_data[2]; /* x2 */ |
||
3437 | double_data[9] = double_data[3]; /* y2 */ |
||
3438 | for(i = 0 ; i < int_data[0] ; i++){ |
||
3439 | double_data[0] = double_data[6] + i*double_data[4]; |
||
3440 | double_data[1] = double_data[7] + i*double_data[5]; |
||
3441 | double_data[2] = double_data[8] + i*double_data[4]; |
||
3442 | double_data[3] = double_data[9] + i*double_data[5]; |
||
3443 | if(use_rotate == TRUE ){ rotate(4,angle,rotationcenter,2);} |
||
3444 | if(use_affine == TRUE ){ transform(4,2);} |
||
18557 | bpr | 3445 | tmp_buffer=my_newmem(MAX_BUFFER); |
3446 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3447 | add_to_buffer(tmp_buffer); |
3448 | if(onclick != 0){object_cnt++;} |
||
3449 | } |
||
3450 | dragstuff[4] = 1; |
||
3451 | } |
||
3452 | else /* use the old parallel version: calculations in javascript */ |
||
3453 | { |
||
3454 | for( i = 0;i < 8; i++ ){ |
||
3455 | switch(i){ |
||
3456 | case 0: double_data[0] = get_real(infile,0);break; /* x1-values */ |
||
3457 | case 1: double_data[1] = get_real(infile,0);break; /* y1-values */ |
||
3458 | case 2: double_data[2] = get_real(infile,0);break; /* x2-values */ |
||
3459 | case 3: double_data[3] = get_real(infile,0);break; /* y2-values */ |
||
3460 | case 4: double_data[4] = xmin + get_real(infile,0);break; /* xv */ |
||
3461 | case 5: double_data[5] = ymax + get_real(infile,0);break; /* yv */ |
||
3462 | case 6: int_data[0] = (int) (get_real(infile,0));break; /* n */ |
||
3463 | case 7: stroke_color=get_color(infile,1);/* name or hex color */ |
||
18557 | bpr | 3464 | tmp_buffer=my_newmem(MAX_BUFFER); |
3465 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,11,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d,%d],[%d,%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],int_data[0],int_data[0],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3466 | add_to_buffer(tmp_buffer); |
3467 | if(onclick != 0){object_cnt++;} |
||
3468 | break; |
||
3469 | default: break; |
||
3470 | } |
||
3471 | dragstuff[11] = 1; |
||
3472 | } |
||
3473 | } |
||
3474 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3475 | reset(); |
||
3476 | break; |
||
3477 | case PLOTSTEPS: |
||
3478 | /* |
||
18556 | bpr | 3479 | @ plotsteps a_number |
3480 | @ default 150 |
||
3481 | @ only used for commands <a href="#curve">curve / plot</a> and <a href="#levelcurve">levelcurve</a> |
||
3482 | @ use with care ! |
||
18552 | bpr | 3483 | */ |
3484 | plot_steps = (int) (get_real(infile,1)); |
||
3485 | break; |
||
3486 | case POINT: |
||
3487 | /* |
||
3488 | @ point x,y,color |
||
3489 | @ draw a single point at (x;y) in color 'color' |
||
3490 | @ use command <code>linewidth int</code> to adjust size |
||
3491 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
3492 | @ will not resize on zooming (command <code>circle x,y,r,color</code> will resize on zooming) |
||
3493 | @ attention: in case of command <a href="#rotate">rotate angle</a> a point has rotation center (0:0) in x/y-range |
||
3494 | @%point%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 1%onclick%point 0,0,red%linewidth 2%onclick%point 1,1,blue%linewidth 3%onclick%point 3,3,green%linewidth 4%point 4,4,orange |
||
3495 | */ |
||
3496 | for(i=0;i<3;i++){ |
||
3497 | switch(i){ |
||
3498 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
3499 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
3500 | case 2: stroke_color = get_color(infile,1);/* name or hex color */ |
||
3501 | if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);} |
||
3502 | if(use_affine == TRUE ){ transform(2,2);} |
||
3503 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3504 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 3505 | tmp_buffer=my_newmem(MAX_BUFFER); |
3506 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,2,[%.*f],[%.*f],[%.2f],[%d],%.2f,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],1.5*line_width,line_width,1.5*line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3507 | add_to_buffer(tmp_buffer); |
3508 | /* object_cnt++; */ |
||
3509 | if(onclick != 0){object_cnt++;} |
||
3510 | break; |
||
3511 | default: break; |
||
3512 | } |
||
3513 | } |
||
3514 | dragstuff[2] = 1; |
||
3515 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3516 | reset(); |
||
3517 | break; |
||
3518 | case POINTS: |
||
3519 | /* |
||
3520 | @ points color,x1,y1,x2,y2,...,x_n,y_n |
||
3521 | @ draw multiple points at given coordinates in color 'color' |
||
3522 | @ use command <code>linewidth int</code> to adjust size |
||
3523 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
3524 | @ attention: in case of command <a href="#rotate">rotate angle</a> the points have rotation center (0:0) in x/y-range |
||
3525 | @%points_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%snaptogrid%linewidth 1%drag xy%points red,0,0,1,1,2,2,3,3%drag x%points blue,0,1,1,2,2,3,3,4 |
||
3526 | @%points_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 1%onclick%points red,0,0,1,1,2,2,3,3%onclick%points blue,0,1,1,2,2,3,3,4 |
||
3527 | */ |
||
3528 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
3529 | fill_color = stroke_color; |
||
3530 | i=0; |
||
3531 | while( ! done ){ /* get next item until EOL*/ |
||
3532 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3533 | if(i%2 == 0 ){ |
||
3534 | double_data[i] = get_real(infile,0); /* x */ |
||
3535 | } |
||
3536 | else { |
||
3537 | double_data[i] = get_real(infile,1); /* y */ |
||
3538 | } |
||
3539 | i++; |
||
3540 | } |
||
3541 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3542 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3543 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3544 | decimals = find_number_of_digits(precision); |
||
3545 | for(c = 0 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 3546 | tmp_buffer=my_newmem(MAX_BUFFER); |
3547 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,2,[%.*f],[%.*f],[%.2f],[%d],%.2f,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],1.5*line_width,line_width,1.5*line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3548 | add_to_buffer(tmp_buffer); |
3549 | /* object_cnt++; */ |
||
3550 | if(onclick != 0){object_cnt++;} |
||
3551 | } |
||
3552 | dragstuff[2] = 1; |
||
3553 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3554 | reset(); |
||
3555 | break; |
||
3556 | case POLY: |
||
3557 | /* |
||
3558 | @ poly color,x1,y1,x2,y2...x_n,y_n |
||
3559 | @ polygon color,x1,y1,x2,y2...x_n,y_n |
||
3560 | @ draw closed polygon |
||
3561 | @ use command ''fpoly`` to fill it or use keyword <a href='#filled'>filled</a> |
||
3562 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
3563 | @%polygon_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,25%fillcolor orange%filled%linewidth 2%drag xy%snaptogrid%poly blue,0,0,1,3,3,1,2,4,-1,3 |
||
3564 | @%polygon_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,25%fillcolor orange%filled%linewidth 1%onclick%poly green,0,0,1,3,3,1,2,4,-1,3 |
||
3565 | */ |
||
3566 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
3567 | i=0; |
||
3568 | c=0; |
||
3569 | while( ! done ){ /* get next item until EOL*/ |
||
3570 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3571 | for( c = 0 ; c < 2; c++){ |
||
3572 | if(c == 0 ){ |
||
3573 | double_data[i] = get_real(infile,0); |
||
3574 | i++; |
||
3575 | } |
||
3576 | else { |
||
3577 | double_data[i] = get_real(infile,1); |
||
3578 | i++; |
||
3579 | } |
||
3580 | } |
||
3581 | } |
||
3582 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3583 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3584 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
8386 | schaersvoo | 3585 | |
18552 | bpr | 3586 | /* draw path: closed & optional filled */ |
3587 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 3588 | tmp_buffer=my_newmem(MAX_BUFFER); |
3589 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,i,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3590 | add_to_buffer(tmp_buffer); |
3591 | if(onclick != 0){object_cnt++;} |
||
3592 | reset(); |
||
3593 | dragstuff[5] = 1; |
||
3594 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3595 | break; |
||
3596 | case POLYLINE: |
||
3597 | /* |
||
3598 | @ polyline color,x1,y1,x2,y2...x_n,y_n |
||
3599 | @ brokenline color,x1,y1,x2,y2...x_n,y_n |
||
3600 | @ path color,x1,y1,x2,y2...x_n,y_n |
||
3601 | @ remark: there is <b>no</b> command polylines | brokenlines | paths ... just use multiple commands <code>polyline, x1,y1,x2,y2...x_n,y_n</code> |
||
3602 | @ remark: there are commands <code>userdraw path(s),color</code> and <code>userdraw polyline,color</code>... these are two entirely different things ! the path(s) userdraw commands may be used for freehand drawing(s)<br>the polyline userdraw command is analogue to this polyline|brokenline command |
||
3603 | @ the command interconnects the points in the given order with a line (canvasdraw will not close the drawing: use command <a href="#poly">polygon</a> for this) |
||
3604 | @ use command <a href='#segments'>segments</a> for a series of segments. These may be clicked/dragged individually |
||
3605 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
3606 | @%polyline_1%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%snaptogrid%polyline blue,0,0,1,3,3,1,2,4,-1,3 |
||
3607 | @%polyline_2%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%onclick%polyline green,0,0,1,3,3,1,2,4,-1,3 |
||
3608 | */ |
||
11806 | schaersvoo | 3609 | |
18552 | bpr | 3610 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
3611 | i=0; |
||
3612 | c=0; |
||
3613 | while( ! done ){ /* get next item until EOL*/ |
||
3614 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3615 | for( c = 0 ; c < 2; c++){ |
||
3616 | if(c == 0 ){ |
||
3617 | double_data[i] = get_real(infile,0); |
||
3618 | i++; |
||
3619 | } |
||
3620 | else { |
||
3621 | double_data[i] = get_real(infile,1); |
||
3622 | i++; |
||
3623 | } |
||
3624 | } |
||
3625 | } |
||
11806 | schaersvoo | 3626 | |
18552 | bpr | 3627 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
3628 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3629 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
11806 | schaersvoo | 3630 | |
18552 | bpr | 3631 | /* draw path: not closed & not filled */ |
3632 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 3633 | tmp_buffer=my_newmem(MAX_BUFFER); |
3634 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,i,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3635 | add_to_buffer(tmp_buffer); |
3636 | if(onclick != 0){object_cnt++;} |
||
3637 | /* object_cnt++;*/ |
||
3638 | reset(); |
||
3639 | dragstuff[4] = 1; |
||
3640 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3641 | break; |
||
3642 | case POPUP: |
||
3643 | /* |
||
18556 | bpr | 3644 | @ popup |
3645 | @ keyword (no arguments) |
||
3646 | @ if fly-script starts with keyword ''popup``, the canvas image will be exclusively in a popup window (xsize px × ysize px) |
||
3647 | @ if keyword ''popup`` is used after command <code>size xsize,ysize</code> the canvas will also be displayed in a popup window with size ''xsize × ysize`` |
||
3648 | @ the popup window will be embedded into the page as a normal image, when ''status=done``; override with keyword <a href="#status">nostatus</a> |
||
3649 | @ to access the read_canvas and read_dragdrop functions in a popup window, use:<br> <code> function read_all(){<br> if( typeof popup !== 'undefined' ){<br> var fun1 = popup['read_dragdrop'+canvas_scripts[0]];<br>var fun2 = popup['read_canvas'+canvas_scripts[0]];<br> popup.close();<br> return "dragdrop="+fun1()+"\\ncanvas="+fun2();<br> };</code> |
||
3650 | @ to set a canvasdraw produced <a href="#clock">clock</a> or multiple clocks...use something like: <code>popup.set_clock(clock_id,type,diff);</code> as js-function for a button (or something else) in your document page.<br>where in <b>clock_id</b> starts with 0 for the first clock<br><b>type</b> is 1 for Hours,2 for Minutes and 3 for Seconds<br><b>diff</b> is the increment (positive or negative) per click |
||
3651 | @%popup%popup%size 400,400%xrange -2*pi,2*pi%yrange -5,5%precision 0%axis%axisnumbering%opacity 100,190%grid 1,1,grey,2,2,5,black%linewidth 4%fillcolor blue%trange -pi,pi%animate%linewidth 1%precision 1000%jsplot red,4*cos(2*x),2*sin(3*x-pi/6)%strokecolor green%functionlabel H(x)=%userinput function |
||
18552 | bpr | 3652 | */ |
3653 | use_tooltip = 2; |
||
3654 | break; |
||
3655 | case PROTRACTOR: |
||
3656 | /* |
||
18556 | bpr | 3657 | @ protractor x,y,x_width,type,mode,use_a_scale |
3658 | @ x,y are the initial location |
||
3659 | @ x_width: give the width in x-coordinate system (e.g. not in pixels !) |
||
3660 | @ type = 1: a triangle range 0 - 180<br>type = 2: a circle shape 0 - 360 |
||
3661 | @ mode: use -1 to set the protractor interactive (mouse movement of protractor)<br>use mode = '0° - 360°' to set the protractor with a static angle of some value |
||
3662 | @ if the value of the user_rotation angle is to be shown...use command <a href='#display'>display degree,color,fontsize</a><a href='#display'>display radian,color,fontsize</a> |
||
3663 | @ use_scale = 1: the protractor will have some scale values printed; use_scale=0 to disable |
||
3664 | @ the rotating direction of the mouse around the protractor determines the clockwise/ counter clockwise rotation of the protractor... |
||
3665 | @ commands ''stroke_color | fill_color | linewidth | opacity | font_family`` will determine the looks of the protractor. |
||
3666 | @ default replyformat: reply[0] = x;reply[1] = y;reply[2] = angle_in_radians<br>use command ''precision`` to set the reply precision. |
||
3667 | @ if combined with a ruler, use replyformat = 32 |
||
3668 | @ command <code>snap_to_grid</code> may be used to assist the pupil at placing the protractor |
||
3669 | @ when using command ''zoom``, pay <b>attention</b> to the size and symmetry of your canvas<br>...to avoid a partial image, locate the start position near the center of the visual canvas<br>technical: the actual ''protractor`` is just a static generated image in a new canvas-memory<br>This image is only generated once, and a copy of its bitmap is translated & rotated onto the visible canvas.<br>That is the reason for the ''high-speed dragging and rotating``.<br>I've limited its size to xsize × ysize e.g. the same size as the visual canvas... |
||
3670 | @ only one protractor allowed (for the time being) |
||
3671 | @ usage: first left click on the protractor will activate dragging;<br>a second left click will activate rotating (just move mouse around)<br>a third click will freeze this position and the x/y-coordinate and angle in radians will be stored in reply(3)<br>a next click will restart this sequence... |
||
3672 | @%protractor%size 400,400%xrange -5,10%yrange -5,10%hline 0,0,black%vline 0,0,black%fillcolor orange%opacity 255,40%protractor 2,-2,6,0,-1,1,1%mouse red,22 |
||
18552 | bpr | 3673 | */ |
3674 | for( i = 0;i < 6; i++ ){ |
||
3675 | switch(i){ |
||
3676 | case 0: double_data[0] = get_real(infile,0);break; /* x-center */ |
||
3677 | case 1: double_data[1] = get_real(infile,0);break; /* y-center */ |
||
3678 | case 2: double_data[2] = get_real(infile,0);break; /* x-width */ |
||
3679 | case 3: int_data[0] = (int)(get_real(infile,0));break; /* type: 1==triangle 2 == circle */ |
||
3680 | case 4: int_data[1] = (int)(get_real(infile,0));break; /* passive mode == 0; active mode == -1 */ |
||
3681 | case 5: int_data[2] = (int)(get_real(infile,1)); /* use scale */ |
||
3682 | decimals = find_number_of_digits(precision); |
||
3683 | if( int_data[1] < 0 ){ js_function[JS_FIND_ANGLE] = 1;} |
||
18557 | bpr | 3684 | add_js_protractor(int_data[0],double_data[0], double_data[1], double_data[2],font_family,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,int_data[2],int_data[1],use_snap); |
3685 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
3686 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, ";protractor%d(); ",canvas_root_id)); |
||
18552 | bpr | 3687 | add_to_buffer(tmp_buffer); |
3688 | reply_precision = precision; |
||
3689 | /* no reply from protractor if non-interactive */ |
||
3690 | if( reply_format == 0 && int_data[1] == -1 ){reply_format = 30;} |
||
3691 | js_function[INTERACTIVE] = 1; |
||
3692 | break; |
||
3693 | default: break; |
||
3694 | } |
||
3695 | } |
||
3696 | break; |
||
3697 | case PIXELS: |
||
3698 | /* |
||
3699 | @ pixels color,x1,y1,x2,y2,x3,y3... |
||
3700 | @ draw rectangular "points" with diameter 1 pixel |
||
3701 | @ pixels can <b>not</b> be dragged or clicked |
||
3702 | @ "pixelsize = 1" may be changed by command <code>pixelsize int</code> |
||
3703 | @%pixels%size 400,400%opacity 255,255%pixelsize 5%pixels red,1,1,2,2,3,3,4,4,5,5,10,10,20,20,30,30,40,40,50,50,60,60,70,70,80,80,90,90,100,100,120,120,140,140,160,160,180,180,200,200,240,240,280,280,320,320,360,360,400,400%#NOTE pixelsize=5...otherwise you will not see them clearly... |
||
3704 | */ |
||
3705 | js_function[DRAW_PIXELS] = 1; |
||
3706 | stroke_color=get_color(infile,0); |
||
3707 | i=0; |
||
3708 | c=0; |
||
3709 | while( ! done ){ /* get next item until EOL*/ |
||
3710 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3711 | for( c = 0 ; c < 2; c++){ |
||
3712 | if(c == 0 ){ |
||
3713 | double_data[i] = get_real(infile,0); |
||
3714 | i++; |
||
3715 | } |
||
3716 | else { |
||
3717 | double_data[i] = get_real(infile,1); |
||
3718 | } |
||
3719 | } |
||
3720 | } |
||
3721 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3722 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3723 | decimals = find_number_of_digits(precision); |
||
3724 | /* *double_xy2js_array(double xy[],int len,int decimals) */ |
||
18557 | bpr | 3725 | tmp_buffer=my_newmem(MAX_BUFFER); |
3726 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_setpixel(%s,\"%s\",%.2f,%d);\n",double_xy2js_array(double_data,i,decimals),stroke_color,stroke_opacity,pixelsize)); |
||
18552 | bpr | 3727 | add_to_buffer(tmp_buffer); |
3728 | reset(); |
||
3729 | break; |
||
3730 | case PIXELSIZE: |
||
3731 | /* |
||
3732 | @ pixelsize int |
||
3733 | @ in case you want to deviate from default pixelsize = 1(...) |
||
3734 | @ pixelsize 100 is of course a filled rectangle 100px × 100px |
||
3735 | */ |
||
3736 | pixelsize = (int) get_real(infile,1); |
||
3737 | break; |
||
15111 | schaersvoo | 3738 | |
18552 | bpr | 3739 | case PIECHART: |
3740 | /* |
||
3741 | @ piechart xc,yc,radius,'data+colorlist' |
||
3742 | @ (xc: yc) center of circle diagram in xrange/yrange |
||
3743 | @ radius in pixels |
||
3744 | @ data+color list: a colon separated list of raw data and corresponding colours<br>canvasdraw will not check validity of colornames...<br>in case of trouble look into javascript debugging of your browser |
||
3745 | @ example data+colorlist: 32:red:65:green:23:black:43:orange:43:yellow:14:white |
||
3746 | @ the number of colors must match the number of data. |
||
3747 | @ if defined <a href='#fillpattern'>fillpattern some_pattern</a> then the pie pieces will be filled with the respective color and a fill pattern...<br>the pattern is cycled from the 4 pattern primitives: grid,hatch,diamond,dot,grid,hatch,diamond,dot,... |
||
3748 | @ use command <a href='#opacity'>opacity</a> to adjust fill_opacity of colours |
||
3749 | @ use command <a href='#legend'>legend</a> to automatically create a legend using the same colours as pie segments; unicode allowed in legend; expect javascript trouble if the amount of ''pie-slices``, ''pie-colors``, ''pie-legend-titles`` do not match, a javascript console is your best friend...<br>use command ''fontfamily`` to set the font of the legend. |
||
3750 | @ use command <a href='centered'>centered</a> to place <a href='#legend'>legend</a> text inside the piechart. The text is using the same color as the pie segment: use (fill) opacity to enhance visibility. |
||
3751 | @%piechart_1%size 300,200%xrange -10,10%yrange -10,10%legend cars:motorcycles:bicycles:trikes%opacity 255,120%piechart -5,0,75,22:red:8:blue:63:green:7:purple% |
||
3752 | @%piechart_2%size 200,200%xrange -10,10%yrange -10,10%fontfamily 16px Arial%centered%legend cars:motorcycles:bicycles:trikes%opacity 255,60%piechart 0,0,100,22:red:8:blue:63:green:7:purple |
||
3753 | */ |
||
3754 | js_function[DRAW_PIECHART] = 1; |
||
3755 | for(i=0;i<5;i++){ |
||
3756 | switch(i){ |
||
3757 | case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x */ |
||
3758 | case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y */ |
||
3759 | case 2: int_data[2] = (int)(get_real(infile,1));break;/* radius*/ |
||
3760 | case 3: temp = get_string(infile,1); |
||
3761 | if( strstr( temp, ":" ) != 0 ){ temp = str_replace(temp,":","\",\"");} |
||
18557 | bpr | 3762 | tmp_buffer=my_newmem(MAX_BUFFER); |
3763 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_piechart(%d,%d,%d,%d,[\"%s\"],%.2f,%d,\"%s\",%d,%d);\n",PIECHART,int_data[0],int_data[1],int_data[2],temp,fill_opacity,legend_cnt,font_family,use_filled,use_offset)); |
||
18552 | bpr | 3764 | add_to_buffer(tmp_buffer); |
3765 | break; |
||
3766 | default:break; |
||
3767 | } |
||
3768 | } |
||
3769 | reset(); |
||
3770 | break; |
||
3771 | case RANGE: |
||
3772 | /* |
||
3773 | @ range xmin,xmax,ymin,ymax |
||
3774 | @ if not given: 0,xsize,0,ysize (eg in pixels) |
||
3775 | */ |
||
3776 | for(i = 0 ; i<4; i++){ |
||
3777 | switch(i){ |
||
3778 | case 0: xmin = get_real(infile,0);break; |
||
3779 | case 1: xmax = get_real(infile,1);break; |
||
3780 | case 2: ymin = get_real(infile,0);break; |
||
3781 | case 3: ymax = get_real(infile,1);break; |
||
3782 | default: break; |
||
3783 | } |
||
3784 | } |
||
3785 | if(xmin >= xmax){canvas_error(" xrange is not OK: xmin < xmax !");} |
||
3786 | if(ymin >= ymax){canvas_error(" yrange is not OK: ymin < ymax !");} |
||
3787 | fprintf(js_include_file,"var xmin = %f;var xmax = %f;var ymin = %f;var ymax = %f;",xmin,xmax,ymin,ymax); |
||
3788 | found_size_command = found_size_command+2; |
||
3789 | break; |
||
3790 | case RAYS: |
||
3791 | /* |
||
18556 | bpr | 3792 | @ rays color,xc,yc,x1,y1,x2,y2,x3,y3...x_n,y_n |
3793 | @ draw rays in color 'color' and center (xc:yc) |
||
3794 | @ may be set draggable or onclick (every individual ray) |
||
3795 | @%rays_onclick%size 400,400%xrange -10,10%yrange -10,10%onclick%rays blue,0,0,3,9,-3,5,-4,0,4,-9,7,9,-8,1,-1,-9 |
||
3796 | @%rays_drag_xy%size 400,400%xrange -10,10%yrange -10,10%drag xy%rays blue,0,0,3,9,-3,5,-4,0,4,-9,7,9,-8,1,-1,-9 |
||
18552 | bpr | 3797 | */ |
3798 | stroke_color=get_color(infile,0); |
||
3799 | fill_color = stroke_color; |
||
3800 | double_data[0] = get_real(infile,0);/* xc */ |
||
3801 | double_data[1] = get_real(infile,0);/* yc */ |
||
3802 | i=2; |
||
3803 | while( ! done ){ /* get next item until EOL*/ |
||
3804 | if(i > MAX_INT - 1){canvas_error("in command rays too many points / rays in argument: repeat command multiple times to fit");} |
||
3805 | if(i%2 == 0 ){ |
||
3806 | double_data[i] = get_real(infile,0); /* x */ |
||
3807 | } |
||
3808 | else { |
||
3809 | double_data[i] = get_real(infile,1); /* y */ |
||
3810 | } |
||
3811 | fprintf(js_include_file,"/* double_data[%d] = %f */\n",i,double_data[i]); |
||
3812 | i++; |
||
3813 | } |
||
3814 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3815 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3816 | if( i%2 != 0 ){canvas_error("in command rays: unpaired x or y value");} |
||
3817 | decimals = find_number_of_digits(precision); |
||
3818 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3819 | for(c=2; c<i;c = c+2){ |
||
18557 | bpr | 3820 | tmp_buffer=my_newmem(MAX_BUFFER); |
3821 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[c],decimals,double_data[1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3822 | add_to_buffer(tmp_buffer); |
3823 | /* object_cnt++; */ |
||
3824 | if(onclick != 0){object_cnt++;} |
||
3825 | } |
||
3826 | reset(); |
||
3827 | dragstuff[4] = 1; |
||
3828 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3829 | break; |
||
3830 | case RECT: |
||
3831 | /* |
||
3832 | @ rect x1,y1,x2,y2,color |
||
3833 | @ use command <code>frect x1,y1,x2,y2,color</code> for a filled rectangle |
||
3834 | @ use command/keyword <a href='#filled'>filled</a> before command <code>rect x1,y1,x2,y2,color</code> |
||
3835 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
18572 | bpr | 3836 | @ note: internally a rect is defined with 4 points. So when performing some affine transformation, other than translation, it will result in some morphing of the rectangle !<br>this is a deviation of flydraw's rect&affine |
18552 | bpr | 3837 | @%rect%size 400,400%xrange -10,10%yrange -10,10%rect 0,0,4,-4,green%rect 0,5,4,1,red |
3838 | */ |
||
3839 | for(i=0;i<5;i++){ |
||
3840 | switch(i){ |
||
3841 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
3842 | case 1:double_data[1] = get_real(infile,0);break; /* y-values */ |
||
3843 | case 2:double_data[4] = get_real(infile,0);break; /* x-values */ |
||
3844 | case 3:double_data[5] = get_real(infile,0);break; /* y-values */ |
||
3845 | case 4:stroke_color = get_color(infile,1);/* name or hex color */ |
||
3846 | decimals = find_number_of_digits(precision); |
||
3847 | double_data[2] = double_data[4]; |
||
3848 | double_data[3] = double_data[1]; |
||
3849 | double_data[6] = double_data[0]; |
||
3850 | double_data[7] = double_data[5]; |
||
3851 | /* using closed PATH (type=5) instead of ctx.rect (type=1)!!! |
||
3852 | 0,1 2,3 |
||
3853 | 6,7 4,5 |
||
3854 | x = [0,2,4,6] |
||
3855 | y = [1,3,5,7] |
||
3856 | */ |
||
3857 | if(use_rotate == TRUE ){rotate(8,angle,rotationcenter,2);} |
||
3858 | if(use_affine == TRUE ){ transform(8,2);} |
||
3859 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 3860 | tmp_buffer=my_newmem(MAX_BUFFER); |
3861 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[6],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],decimals,double_data[7],line_width,line_width,line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3862 | add_to_buffer(tmp_buffer); |
3863 | if(onclick != 0){object_cnt++;} |
||
18555 | bpr | 3864 | /* object_cnt++; */ |
18552 | bpr | 3865 | reset(); |
3866 | break; |
||
3867 | } |
||
3868 | } |
||
3869 | dragstuff[5] = 1; |
||
3870 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3871 | break; |
||
3872 | case RECTS: |
||
3873 | /* |
||
3874 | @ rects color,x1,y1,x2,y2,..... |
||
3875 | @ use command <code>frect color,x1,y1,x2,y2,.....</code> for a filled rectangle |
||
3876 | @ use command/keyword <a href='#filled'>filled</a> before command <code>rects color,x1,y1,x2,y2,....</code> |
||
3877 | @ use command <code>fillcolor color</code> before ''frects`` to set the fill colour. |
||
3878 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
3879 | @%rects%size 400,400%xrange -10,10%yrange -10,10%rects red,0,0,4,-4,0,5,4,1 |
||
3880 | */ |
||
3881 | /* using closed PATH (type=5) in stead of ctx.rect (type=1)!!! |
||
3882 | 0,1 2,3 .....8,9 10,11..... |
||
3883 | 6,7 4,5 .....14,15 12,13..... |
||
3884 | x = [0,2,4,6,8,10,12,14...] |
||
3885 | y = [1,3,5,7,9,11,13,15...] |
||
3886 | */ |
||
3887 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
3888 | fill_color = stroke_color; |
||
3889 | i=0; |
||
3890 | while( ! done ){ /* get next item until EOL*/ |
||
3891 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3892 | if(i%2 == 0 ){ |
||
3893 | double_data[i] = get_real(infile,0); /* x */ |
||
3894 | } |
||
3895 | else { |
||
3896 | double_data[i] = get_real(infile,1); /* y */ |
||
3897 | } |
||
3898 | i++; |
||
3899 | } |
||
3900 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3901 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3902 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
11806 | schaersvoo | 3903 | |
18552 | bpr | 3904 | decimals = find_number_of_digits(precision); |
3905 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18557 | bpr | 3906 | tmp_buffer=my_newmem(MAX_BUFFER); |
3907 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+2],decimals,double_data[c],decimals,double_data[c+1],decimals,double_data[c+1],decimals,double_data[c+3],decimals,double_data[c+3],line_width,line_width,line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3908 | add_to_buffer(tmp_buffer); |
3909 | if(onclick != 0){object_cnt++;} |
||
3910 | /* object_cnt++; */ |
||
3911 | } |
||
3912 | dragstuff[5] = 1; |
||
3913 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3914 | if(use_rotate == TRUE ){ |
||
3915 | rotate(i-1,angle,rotationcenter,2); |
||
3916 | } |
||
3917 | reset(); |
||
3918 | break; |
||
3919 | case REPLYFORMAT: |
||
3920 | /* |
||
3921 | @ replyformat number |
||
3922 | @ use number=-1 to deactivate the js-functions read_canvas() and read_dragdrop() |
||
3923 | @ default values should be fine ! |
||
3924 | @ use command <code>precision [0,1,10,100,1000,10000...]</code> before command ''replyformat`` to set the desired number of decimals in the student reply / drawing |
||
3925 | @ the last value for ''precision int`` will be used to calculate the reply coordinates, if needed (read_canvas();) |
||
3926 | @ choose<ul><li>replyformat 1: <code>x1,x2,x3,x4....x_n<br>y1,y2,y3,y4....y_n</code> x/y in pixels</li><li>replyformat 2: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 3: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n<br> r1,r2,r3,r4....r_n</code> x/y in pixels, r in pixels</li><li>replyformat 4: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n<br> r1,r2,r3,r4....r_n</code> x/y in xrange / yrange coordinate system, r in pixels</li><li>replyformat 5: <code> Ax1,Ax2,Ax3,Ax4....Ax_n<br> Ay1,Ay2,Ay3,Ay4....Ay_n<br> Bx1,Bx2,Bx3,Bx4....Bx_n<br> By1,By2,By3,By4....By_n<br> Cx1,Cx2,Cx3,Cx4....Cx_n<br> Cy1,Cy2,Cy3,Cy4....Cy_n<br> ....<br> Zx1,Zx2,Zx3,Zx4....Zx_n<br> Zy1,Zy2,Zy3,Zy4....Zy_n</code> x/y in pixels</li><li>replyformat 6: <code> Ax1,Ax2,Ax3,Ax4....Ax_n<br> Ay1,Ay2,Ay3,Ay4....Ay_n<br> Bx1,Bx2,Bx3,Bx4....Bx_n<br> By1,By2,By3,By4....By_n<br> Cx1,Cx2,Cx3,Cx4....Cx_n<br> Cy1,Cy2,Cy3,Cy4....Cy_n<br> ....<br> Zx1,Zx2,Zx3,Zx4....Zx_n<br> Zy1,Zy2,Zy3,Zy4....Zy_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 7: <code> x1:y1,x2:y2,x3:y3,x4:y4...x_n:y_n</code> x/y in pixels</li><li>replyformat 8: <code> x1:y1,x2:y2,x3:y3,x4:y4...x_n:y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 9: <code> x1:y1:r1,x2:y2:r2,x3:y3:r3,x4:y4:r3...x_n:y_n:r_n</code> x/y in pixels</li><li>replyformat 10: <code> x1:y1:r1,x2:y2:r2,x3:y3:r3,x4:y4:r3...x_n:y_n:r_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 11: <code> Ax1,Ay1,Ax2,Ay2<br>Bx1,By1,Bx2,By2<br> Cx1,Cy1,Cx2,Cy2<br> Dx1,Dy1,Dx2,Dy2<br> ......<br> Zx1,Zy1,Zx2,Zy2</code> x/y in xrange / yrange coordinate system</li><li>replyformat 12: <code> Ax1,Ay1,Ax2,Ay2<br> Bx1,By1,Bx2,By2<br>Cx1,Cy1,Cx2,Cy2<br> Dx1,Dy1,Dx2,Dy2<br> ......<br> Zx1,Zy1,Zx2,Zy2</code> x/y in pixels</li><li>replyformat 13: <code> Ax1:Ay1:Ax2:Ay2,Bx1:By1:Bx2:By2,Cx1:Cy1:Cx2:Cy2,Dx1:Dy1:Dx2:Dy2, ... ,Zx1:Zy1:Zx2:Zy2</code> x/y in xrange / yrange coordinate system</li><li>replyformat 14: <code> Ax1:Ay1:Ax2:Ay2,Bx1:By1:Bx2:By2....Zx1:Zy1:Zx2:Zy2</code> x/y in pixels</li><li>replyformat 15: reply from inputfields,textareas <code>reply1,reply2,reply3,...,reply_n</code></li><li>replyformat 16: mathml input fields</li><li>replyformat 17: read ''userdraw text,color`` only <code>x1,y1,text1 \\n x2,y2,text2...\\n...x_n,y_n,text_n </code> x/y-values are in xrange/yrange</li><li>replyformat 18: read_canvas() will read all interactive clocks in <code>H1:M1:S1,H2:M2:S2...Hn:Mn:Sn</code></li><li>replyformat 19: read_canvas() will return the object number of marked / clicked object (clock), analogue to (shape library) onclick command</li><li>replyformat 20: read_canvas() will reply "object_number:x:y" of external images: object_number of the first draggable external image in the fly-script starts with 0, e.g. expect something like 0:-5:4,1:6:2,2:-2:-5, the first image position is (-5:4), the second image position is (6:2) and the third image position is (-2:-5) <li>replyformat 21: <code> (x1:y1) (x2:y2) ... (x_n:y_n)</code> verbatim coordinate return</li><li>replyformat 22: returns an array .... <code>reply[0]=x1 reply[1]=y1 reply[2]=x2 reply[3]=y2 ... reply[n-1]=x_n reply[n]=y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 23: can only be used for drawtype ''polyline``. A typical click sequence in drawtype polyline is x1,y1,x2,y2,x2,y2,x3,y3,x3,y3.....,x(n-1),y(n-1),x(n-1),y(n-1),xn,yn --replyformat 23 gives <code>x1,y1,x2,y2,x3,y3,.....x(n-1),y(n-1),xn,yn</code>; multiple occurences will be filtered out. The reply will be in x-y-range (xreply \\n yreply)</li><li>replyformat 24: read all inputfield values: even those set ''readonly``</li><li>replyformat 25: <code> angle1,angle2;...;angle_n</code> will return the radius (one or many) of the user drawn circle segment in degrees</li><li>replyformat 26: <code> rad1,rad2,...rad_n</code> will return the radius (one or many) of the user drawn circle segment in radians</li><li>replyformat 27: return (only) userdraw inputfields <code>x1,y1,text1<br> x2,y2,text2...<br>...x_n,y_n,textn</code></li><li>replyformat 28: <code> x1,y1,r1,x2,y2,r2...x_n,y_n,r_n</code> x / y / r in xrange / yrange coordinate system: may be used to reinput into command <code>circles color,x1,y1,r1,x2,y2,r2...x_n,y_n,r_n</code> will not return anything else (e.g. no inputfields, text etc)</li><li>replyformat 34: a special for OEF and dragging external images -included via commands <a href='#copy'>copy</a> or <a href='#copyresized'>copyresized</a> there will be an extra function <code>read_canvas_images()</code> for reading the coordinates of the images.<br>for now this is a unique function, e.g. there is no ''canvas id`` linked to it. (TO DO !!! 18/5/2019)</li></ul> |
||
3927 | @ special replyformat = 100 ; will access to the raw javascript object data...use: read_dragdrop([property,property,...])<br>for example properies like 'clicked','text', 'angle' , 'x' |
||
3928 | */ |
||
3929 | reply_format = (int) get_real(infile,1); |
||
3930 | reply_precision = precision; |
||
3931 | break; |
||
3932 | case ROUNDRECT: |
||
3933 | /* |
||
3934 | @ roundrect x1,y1,x2,y2,radius in px,color |
||
3935 | @ use command <code>froundrect x1,y1,x2,y2,radius,color</code> for a filled rectangle |
||
3936 | @ use command/keyword <a href='#filled'>filled</a> before command <code>roundrect x1,y1,x2,y2,radius,color</code> |
||
3937 | @ fillcolor will be identical to ''color`` |
||
3938 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
3939 | @%roundrect%size 400,400%xrange -10,10%yrange -10,10%roundrect 0,0,4,-4,20,green%roundrect 0,5,4,1,10,red |
||
3940 | */ |
||
3941 | for(i=0;i<6;i++){ |
||
3942 | switch(i){ |
||
3943 | case 0:double_data[0] = get_real(infile,0);break; /* x-values */ |
||
3944 | case 1:double_data[1] = get_real(infile,0);break; /* y-values */ |
||
3945 | case 2:double_data[2] = get_real(infile,0);break; /* x-values */ |
||
3946 | case 3:double_data[3] = get_real(infile,0);break; /* y-values */ |
||
3947 | case 4:int_data[0] = (int) (get_real(infile,0));break; /* radius value in pixels */ |
||
3948 | case 5:stroke_color = get_color(infile,1);/* name or hex color */ |
||
3949 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
3950 | if(use_affine == TRUE ){ transform(2,4);} |
||
3951 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3952 | /* ensure no inverted roundrect is produced... */ |
||
3953 | if( double_data[0] > double_data[2] ){double_data[4] = double_data[0];double_data[0] = double_data[2];double_data[2] = double_data[4];} |
||
3954 | if( double_data[3] > double_data[1] ){double_data[4] = double_data[1];double_data[1] = double_data[3];double_data[3] = double_data[4];} |
||
3955 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 3956 | tmp_buffer=my_newmem(MAX_BUFFER); |
3957 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,6,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 3958 | add_to_buffer(tmp_buffer); |
3959 | if(onclick != 0){object_cnt++;} |
||
3960 | /* object_cnt++;*/ |
||
3961 | reset(); |
||
3962 | break; |
||
3963 | } |
||
3964 | } |
||
3965 | dragstuff[6] = 1; |
||
3966 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
3967 | break; |
||
3968 | case ROUNDRECTS: |
||
3969 | /* |
||
3970 | @ roundrects color,radius in px,x1,y1,x2,y2,x3,y3,x4,y4,.... |
||
3971 | @ for filled roundrects use command/keyword <a href='#filled'>filled</a> before command |
||
3972 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
3973 | @%roundrects%size 400,400%xrange -10,10%yrange -10,10%roundrects blue,5,0,0,4,-4,5,4,1,2 |
||
3974 | */ |
||
11806 | schaersvoo | 3975 | |
18552 | bpr | 3976 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
3977 | int_data[0] = (int) (get_real(infile,0)); /* radius value in pixels */ |
||
3978 | fill_color = stroke_color; |
||
3979 | i=0; |
||
3980 | while( ! done ){ /* get next item until EOL*/ |
||
3981 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
3982 | if(i%2 == 0 ){ |
||
3983 | double_data[i] = get_real(infile,0); /* x */ |
||
3984 | } |
||
3985 | else { |
||
3986 | double_data[i] = get_real(infile,1); /* y */ |
||
3987 | } |
||
3988 | i++; |
||
3989 | } |
||
3990 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
3991 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
3992 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
3993 | decimals = find_number_of_digits(precision); |
||
3994 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
3995 | /* ensure no inverted roundrect is produced... */ |
||
3996 | if( double_data[c] > double_data[c+2] ){double_data[c+4] = double_data[c];double_data[c] = double_data[c+2];double_data[c+2] = double_data[c+4];} |
||
3997 | if( double_data[c+3] > double_data[c+1] ){double_data[c+4] = double_data[c+1];double_data[c+1] = double_data[c+3];double_data[c+3] = double_data[c+4];} |
||
18557 | bpr | 3998 | tmp_buffer=my_newmem(MAX_BUFFER); |
3999 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,6,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4000 | add_to_buffer(tmp_buffer); |
4001 | if(onclick != 0){object_cnt++;} |
||
4002 | /* object_cnt++; */ |
||
4003 | } |
||
4004 | dragstuff[6] = 1; |
||
4005 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4006 | reset(); |
||
4007 | break; |
||
4008 | case RULER: |
||
4009 | /* |
||
4010 | @ ruler x,y,x-width,y-height,mode |
||
4011 | @ x,y are the initial location |
||
4012 | @ x-width, y-height are the ruler dimensions width & height in xy-coordinate system |
||
4013 | @ the ruler scale is by definition the x-scale, set by command ''xrange``. For example: a ruler x-width of 6 will have a scale ranging from 0 to 6 |
||
4014 | @ mode: use -1 to set the ruler interactive (eg mouse movement of ruler; drag & rotate)<br>use mode = '0° - 360°' to set the ruler with a static angle of some value |
||
4015 | @ if combined with a protractor, use replyformat = 32 |
||
4016 | @ only one ruler allowed (for the time being) |
||
4017 | @ when using command ''zoom``, pay <b>attention</b> to the size and symmetry of your canvas to avoid a partial image, locate the start position near the center of the visual canvas; technical: the actual ''ruler`` is just a static generated image in a new canvas-memory. This image is only generated once, and a copy of its bitmap is translated & rotated onto the visible canvas. That is the reason for the ''high-speed dragging and rotating``. I have limited its size to xsize × ysize e.g. the same size as the visual canvas... |
||
4018 | @ usage: first left click on the ruler will activate dragging; a second left click will activate rotating (just move mouse around), a third click will freeze this position and the x/y-coordinate and angle in radians will be stored in reply(3), a next click will restart this sequence... |
||
4019 | @%ruler_interactive%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler -9,0,10,2,-1%display degree,blue,22 |
||
4020 | @%ruler_set_degree_45%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler 0,0,10,2,45 |
||
4021 | @%ruler_set_degree_125%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler 0,0,10,2,125 |
||
4022 | */ |
||
4023 | for( i = 0;i < 5; i++ ){ |
||
4024 | switch(i){ |
||
4025 | case 0: double_data[0] = get_real(infile,0);break; /* x-center */ |
||
4026 | case 1: double_data[1] = get_real(infile,0);break; /* y-center */ |
||
4027 | case 2: double_data[2] = get_real(infile,0);break; /* x-width */ |
||
4028 | case 3: double_data[3] = get_real(infile,0);break; /* y-width */ |
||
4029 | case 4: int_data[0] = (int)(get_real(infile,1)); /* passive mode */ |
||
4030 | decimals = find_number_of_digits(precision); |
||
4031 | if( int_data[0] < 0 ){ |
||
4032 | js_function[JS_FIND_ANGLE] = 1; |
||
4033 | } |
||
18557 | bpr | 4034 | add_js_ruler(double_data[0],double_data[1],double_data[2],double_data[3], font_family,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,int_data[0],use_snap); |
4035 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
4036 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, ";ruler%d(); ",canvas_root_id)); |
||
18552 | bpr | 4037 | add_to_buffer(tmp_buffer); |
4038 | reply_precision = precision; |
||
4039 | /* no reply from ruler if non-interactive */ |
||
4040 | if( reply_format == 0 && int_data[0] == -1 ){reply_format = 31;} |
||
4041 | break; |
||
4042 | default: break; |
||
4043 | } |
||
4044 | } |
||
4045 | break; |
||
4046 | case RESET: |
||
4047 | /* |
||
4048 | @ reset |
||
4049 | @ keyword |
||
4050 | @ disables the effects of the <a href="noreset">noreset</a> command |
||
4051 | @ so the next objects will not be <a href="#filled">filled</a> and <a href="#dashed">dashed</a> |
||
4052 | */ |
||
4053 | no_reset = FALSE; reset(); |
||
4054 | break; |
||
4055 | case RESETOFFSET: |
||
4056 | /* |
||
18556 | bpr | 4057 | @ resetoffset |
4058 | @ keyword ; use to restore text placement on the canvas to the real (x;y) coordinates of the left bottom corner of the text |
||
4059 | @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-librariy |
||
18552 | bpr | 4060 | */ |
4061 | use_offset = 0; |
||
4062 | break; |
||
4063 | case ROTATE: |
||
4064 | /* |
||
18556 | bpr | 4065 | @ rotate rotation_angle |
4066 | @ angle in degrees |
||
4067 | @ (only) the next object will be rotated is given angle |
||
4068 | @ positive values rotate counter clockwise |
||
4069 | @ attention: all objects will be rotated around their first point...<br><code>rotate 45<br>triangle 1,1,5,1,3,4,red</code><br>will rotate 45 degrees around point (1:1) |
||
4070 | @ if another rotation center is needed, use command <a href="#rotationcenter">rotationcenter xc,yc</a>.<br>to reset this rotationcenter, use keyword <a href="#killrotate">killrotate</a> |
||
4071 | @ attention: rotate will mess up the interactivity of the rotated object <br>e.g. if combined with command <a href="#drag">drag xy</a> or keyword <a href="#onclick">onclick</a>: the mouse recognises the original -unrotated- coordinates of the object |
||
4072 | @%rotate_1%size 400,400%xrange -10,10%yrange -10,10%fpoly yellow,0,0,4,3,2,5%rotate 45%fpoly violet,0,0,4,3,2,5%killrotate%rotate 90%fpoly violet,0,0,4,3,2,5% |
||
18552 | bpr | 4073 | */ |
4074 | use_rotate = TRUE; |
||
4075 | angle = -1*(get_real(infile,1));/* -1: to be compatible with Flydraw... */ |
||
4076 | break; |
||
4077 | case ROTATION_CENTER: |
||
4078 | /* |
||
4079 | @ rotationcenter x_center,y_center |
||
4080 | @ define an rotation center in your x/y-coordinate system |
||
4081 | @ wims will not check the validity of your input; use javascript console to debug any erors |
||
4082 | @ if not defined a rotation will be around the first point of an object |
||
4083 | @ to be used before command <a href="#rotate">rotate</a> |
||
18572 | bpr | 4084 | @ use <a href="#killrotate">killrotate</a> to reset to 'null' <br>(eg. the rotationcenter of the next object(s) will be the first (x;y) coordinate of the object(s)) |
18552 | bpr | 4085 | @ all other commands will use this rotation center, unless a <a href="#killrotation">killrotation</a> is given |
4086 | @%rotationcenter%size 400,400%xrange -5,10%yrange -5,10%circles green,3,3,4.25%rotationcenter 3,3%opacity 255,80%fpoly yellow,0,0,4,3,2,5%rotate 45%fpoly violet,0,0,4,3,2,5%rotate 90%fpoly lightblue,0,0,4,3,2,5%rotate 135%fpoly blue,0,0,4,3,2,5%rotate 180%fpoly orange,0,0,4,3,2,5%rotate 225%fpoly green,0,0,4,3,2,5%rotate 270%fpoly cyan,0,0,4,3,2,5%rotate 315%fpoly purple,0,0,4,3,2,5%linewidth 3%point 3,3,red%mouse red,22 |
||
4087 | @%rotationcenter_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%fillcolor black%strokecolor yellow%rotationcenter 0,0%fontsize 28%slider 0,2*pi,400,30,angle degrees active, rotate...%plot red,5*sin(x)%filled%linewidth 1%opacity 150,50%fillcolor orange%angle 0,0,pi,0,0,blue |
||
4088 | */ |
||
4089 | for( i = 0;i < 2; i++ ){ |
||
4090 | switch(i){ |
||
4091 | case 0: rotationcenter[0] = get_real(infile,0);break; /* x-center */ |
||
4092 | case 1: rotationcenter[1] = get_real(infile,1);break; /* y-center */ |
||
4093 | } |
||
4094 | string_length = 1 + snprintf(NULL,0,"[%f,%f ]",rotationcenter[0],rotationcenter[1]); |
||
18557 | bpr | 4095 | |
18552 | bpr | 4096 | rotation_center = my_newmem(string_length); |
4097 | snprintf(rotation_center,string_length,"[%f,%f]",rotationcenter[0],rotationcenter[1]); |
||
4098 | } |
||
4099 | break; |
||
4100 | case SIZE: |
||
4101 | /* |
||
18556 | bpr | 4102 | @ size width,height |
4103 | @ set canvas size in pixels |
||
4104 | @ mandatory first command (can only be preceded by keyword <a href="#popup">popup</a>) |
||
4105 | @ if xrange and/or yrange is not given the range will be set to pixels:<br>xrange 0,xsize yrange 0,ysize<br>note: lower left corner is origin (0:0) !!! this in contrast to flydraw |
||
18552 | bpr | 4106 | */ |
4107 | found_size_command = 1; |
||
4108 | /* using fabs: however "xsize == int": so "xsize = abs( (int) get_real(infile,0))" would be the idea... */ |
||
4109 | xsize = (int)(fabs(round(get_real(infile,0)))); /* just to be sure that sizes > 0 */ |
||
4110 | ysize = (int)(fabs(round(get_real(infile,1)))); |
||
4111 | /* sometimes we want xrange / yrange to be in pixels...without telling x/y-range */ |
||
4112 | xmin = 0;xmax = xsize; |
||
4113 | ymin = 0;ymax = ysize; |
||
11806 | schaersvoo | 4114 | |
4115 | /* |
||
4116 | The sequence in which stuff is finally printed is important !! |
||
4117 | */ |
||
18552 | bpr | 4118 | fprintf(stdout,"\n\ |
4119 | <script>\n\ |
||
4120 | /*<![CDATA[*/\n\ |
||
4121 | if( typeof(wims_status) === 'undefined' ){ var wims_status = \"$status\";};\ |
||
4122 | if( typeof(use_dragdrop_reply) === 'undefined' ){ var use_dragdrop_reply = false;};\ |
||
4123 | if( typeof(canvas_scripts) === 'undefined' ){ var canvas_scripts = new Array();};\ |
||
4124 | canvas_scripts.push(\"%d\");\n/*]]>*/\n</script>\n\ |
||
4125 | ",canvas_root_id); |
||
11806 | schaersvoo | 4126 | |
18552 | bpr | 4127 | /* style=\"display:block;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;\" */ |
4128 | if( use_tooltip != 2){ |
||
4129 | fprintf(stdout,"<!-- canvasdraw div -->\n\ |
||
4130 | <div tabindex=\"0\" id=\"canvas_div%d\" style=\"max-width:%dpx;width:%dpx;height:%dpx\" class=\"canvas_wrapper\" oncontextmenu=\"return false;\">\ |
||
4131 | <canvas class=\"canvas_placeholder\" width=\"%d\" height=\"%d\"></canvas>\ |
||
4132 | </div>\n\ |
||
4133 | <!-- tooltip and input placeholder -->\n\ |
||
4134 | <div id=\"tooltip_placeholder_div%d\" style=\"text-align:center\">\ |
||
4135 | <span id=\"tooltip_placeholder%d\" class=\"tooltip_placeholder\"></span></div>\ |
||
4136 | <!-- include actual object code via include file -->\n\ |
||
4137 | <script id=\"canvas_script%d\" src=\"%s\" defer></script>\n",canvas_root_id,xsize,xsize,ysize,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,getfile_cmd); |
||
4138 | } else { |
||
11806 | schaersvoo | 4139 | /* |
14066 | bpr | 4140 | set canvas_div invisible and do not include placeholder in main html page: |
15111 | schaersvoo | 4141 | the js-include will also be in a popup window...to be shown when wims $status = done |
11806 | schaersvoo | 4142 | */ |
18552 | bpr | 4143 | fprintf(stdout,"<!-- canvasdraw div invisible -->\n\ |
4144 | <div tabindex=\"0\" id=\"canvas_div%d\" class=\"canvas_wrapper\" style=\"display:none;max-width:%dpx;width:%dpx;height:%dpx;\">\ |
||
4145 | <canvas class=\"canvas_placeholder\" width=\"%d\" height=\"%d\"></canvas>\ |
||
4146 | </div>\n\ |
||
4147 | <div id=\"tooltip_placeholder_div%d\" style=\"display:none;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;\">\ |
||
4148 | <span id=\"tooltip_placeholder%d\" class=\"tooltip_placeholder\"></span></div>\ |
||
4149 | <!-- include actual object code via include file -->\n\ |
||
4150 | <script id=\"canvas_script%d\" src=\"%s\"></script>\n",canvas_root_id,xsize,xsize,ysize,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,getfile_cmd); |
||
4151 | } |
||
11806 | schaersvoo | 4152 | |
14071 | bpr | 4153 | /* these must be global...it is all really very poor javascript:( */ |
15734 | schaersvoo | 4154 | fprintf(js_include_file,"\n/* begin generated javascript include for canvasdraw version %s */\n\ |
11806 | schaersvoo | 4155 | \"use strict\";\n\ |
15111 | schaersvoo | 4156 | /* these variables and functions must be global */\ |
11806 | schaersvoo | 4157 | var read_dragdrop%d;\ |
14038 | schaersvoo | 4158 | var read_canvas_images;\ |
11806 | schaersvoo | 4159 | var read_canvas%d;\ |
4160 | var set_clock;\ |
||
4161 | var clear_draw_area%d;\ |
||
4162 | var update_draw_area%d;\ |
||
14038 | schaersvoo | 4163 | var place_image_on_canvas;\ |
11806 | schaersvoo | 4164 | var draw_boxplot;\ |
4165 | var redraw_all%d;\ |
||
15111 | schaersvoo | 4166 | var userdraw_primitive;\ |
4167 | var wims_canvas_function%d = function(){\n/* common used stuff */\ |
||
4168 | var userdraw_x = [];var userdraw_y = [];var userdraw_radius = [];\ |
||
11806 | schaersvoo | 4169 | var xsize = %d;\ |
4170 | var ysize = %d;\ |
||
4171 | var precision = 100;\ |
||
4172 | var canvas_div = document.getElementById(\"canvas_div%d\");\ |
||
4173 | var create_canvas%d = function(canvas_type,size_x,size_y){var cnv;if(document.getElementById(\"wims_canvas%d\"+canvas_type)){ cnv = document.getElementById(\"wims_canvas%d\"+canvas_type);}else{try{ cnv = document.createElement(\"canvas\"); }catch(e){alert(\"Your browser does not support HTML5 CANVAS:GET FIREFOX !\");return;};canvas_div.appendChild(cnv);};cnv.width = size_x;cnv.height = size_y;cnv.style.top = 0;cnv.style.left = 0;cnv.style.position = \"absolute\";cnv.id = \"wims_canvas%d\"+canvas_type;return cnv;};\ |
||
4174 | function findPosX(i){ var obj = i;var curleft = 0;if(obj.offsetParent){while(1){curleft += obj.offsetLeft;if(!obj.offsetParent){break;};obj = obj.offsetParent;};}else{if(obj.x){curleft += obj.x;};};return curleft;};function findPosY(i){var obj = i;var curtop = 0;if(obj.offsetParent){while(1){curtop += obj.offsetTop;if(!obj.offsetParent){break;};obj = obj.offsetParent;};}else{if(obj.y){curtop += obj.y;};};return curtop;};\ |
||
18606 | bpr | 4175 | function x2px(x){if(use_xlogscale == 0 ){let res=Math.trunc((x-xmin)/(xmax - xmin)*xsize);return (res==xsize)?xsize-1:res;}else{let x_max = Math.log(xmax)/Math.log(xlogbase);let x_min = Math.log(xmin)/Math.log(xlogbase);let x_in = Math.log(x)/Math.log(xlogbase);let res=(x_in-x_min)/(x_max - x_min)*xsize; return (res==xsize)?xsize-1:res;};};\ |
4176 | function px2x(px){if(use_xlogscale == 0 ){return px*(xmax - xmin)/xsize + xmin;}else{let x_max = Math.log(xmax)/Math.log(xlogbase);let x_min = Math.log(xmin)/Math.log(xlogbase);let x_out = x_min +px*(x_max - x_min)/xsize;return Math.pow(xlogbase,x_out);};};\ |
||
4177 | function px2y(py){if(use_ylogscale == 0 ){return ymax - py*(ymax - ymin)/ysize;}else{let y_max = Math.log(ymax)/Math.log(ylogbase);let y_min = Math.log(ymin)/Math.log(ylogbase);let y_out = y_max +py*(y_min - y_max)/ysize;return Math.pow(ylogbase,y_out);};};\ |
||
4178 | function y2px(y){if(use_ylogscale == 0){let res= Math.trunc((ymax-y)/(ymax - ymin)*ysize);return (res==ysize)?ysize-1:res;}else{var y_max = Math.log(ymax)/Math.log(ylogbase);var y_min = Math.log(ymin)/Math.log(ylogbase);var y_in = Math.log(y)/Math.log(ylogbase);return (y_max - y_in)*ysize/(y_max - y_min);};};\ |
||
11806 | schaersvoo | 4179 | function scale_x_radius(rx){return rx*xsize/(xmax - xmin);};\ |
4180 | function scale_y_radius(ry){return ry*ysize/(ymax - ymin);};\ |
||
4181 | function distance(x1,y1,x2,y2){return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );};\ |
||
4182 | function distance_to_line (r,q,x,y){var c = (y) - (-1/r)*(x);var xs = r*(c - q)/(r*r+1);var ys = (r)*(xs)+(q);return parseInt(Math.sqrt( (xs-x)*(xs-x) + (ys-y)*(ys-y) ));};\ |
||
4183 | function move(obj,dx,dy){for(var p = 0 ; p < obj.x.length; p++){obj.x[p] = obj.x[p] + dx;obj.y[p] = obj.y[p] + dy;};return obj;};\ |
||
15111 | schaersvoo | 4184 | var snap_x = 1;var snap_y = 1;\ |
11806 | schaersvoo | 4185 | function snap_to_x(x){return x2px(snap_x*(Math.round((px2x(x))/snap_x)));};\ |
11890 | schaersvoo | 4186 | function snap_to_y(y){return y2px(snap_y*(Math.round((px2y(y))/snap_y)));};\ |
15111 | schaersvoo | 4187 | function multisnap_check(x,y,snap){switch(snap){case 1:return [snap_to_x(x),snap_to_y(y)];break;case 2:return [snap_to_x(x),y];break;case 3:return [x,snap_to_y(y)];break;case 4:return snap_to_points(x,y);break;case 5: return snap_to_fun(x,y);break;default: return [x,y];break;};};\ |
11806 | schaersvoo | 4188 | var xlogbase = 10;\ |
4189 | var ylogbase = 10;\ |
||
4190 | var use_xlogscale = 0;\ |
||
4191 | var use_ylogscale = 0;\ |
||
11891 | schaersvoo | 4192 | var x_strings = {};var x_strings_up = [];\ |
11806 | schaersvoo | 4193 | var y_strings = null;\ |
4194 | var use_jsmath = 0;\ |
||
4195 | var xstart = 0;\ |
||
4196 | var ystart = 0;\ |
||
4197 | var unit_x=\" \";\ |
||
4198 | var unit_y=\" \";\ |
||
15111 | schaersvoo | 4199 | var dragdrop_reply = [];\ |
15734 | schaersvoo | 4200 | var external_canvas = create_canvas%d(%d,xsize,ysize);",VERSION,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,EXTERNAL_IMAGE_CANVAS); |
15111 | schaersvoo | 4201 | /* var xstart,ystart are normally 0 : in case of sgraph they have the 'jump' in the graph */ |
18552 | bpr | 4202 | break; |
4203 | case SEGMENT: |
||
4204 | /* |
||
4205 | @ segment x1,y1,x2,y2,color |
||
4206 | @ alternative: seg |
||
4207 | @ draw a line segment between points (x1:y1)--(x2:y2) in color ''color`` |
||
4208 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
4209 | @%segment_onclick%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%segment 1,1,-9,3,green |
||
4210 | @%segment_drag_y%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag y%segment 1,1,-9,3,green |
||
4211 | */ |
||
4212 | for(i=0;i<5;i++) { |
||
4213 | switch(i){ |
||
4214 | case 0: double_data[0]= get_real(infile,0);break; /* x1-values */ |
||
4215 | case 1: double_data[1]= get_real(infile,0);break; /* y1-values */ |
||
4216 | case 2: double_data[2]= get_real(infile,0);break; /* x2-values */ |
||
4217 | case 3: double_data[3]= get_real(infile,0);break; /* y2-values */ |
||
4218 | case 4: stroke_color=get_color(infile,1);/* name or hex color */ |
||
4219 | if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);} |
||
4220 | if(use_affine == TRUE ){ transform(4,2);} |
||
4221 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
4222 | decimals = find_number_of_digits(precision); |
||
18557 | bpr | 4223 | tmp_buffer=my_newmem(MAX_BUFFER); |
4224 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4225 | add_to_buffer(tmp_buffer); |
4226 | if(onclick != 0){object_cnt++;} |
||
4227 | /* object_cnt++; */ |
||
4228 | reset(); |
||
4229 | break; |
||
4230 | default: break; |
||
4231 | } |
||
4232 | } |
||
4233 | dragstuff[4] = 1; |
||
4234 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4235 | break; |
||
4236 | case SEGMENTS: |
||
4237 | /* |
||
4238 | @ segments color,x1,y1,x2,y2,...,x_n,y_n |
||
4239 | @ alternative: segs |
||
4240 | @ draw multiple segments between points (x1:y1)--(x2:y2).....and... (x_n-1:y_n-1)--(x_n:y_n) in color ''color`` |
||
4241 | @ use command ''linewidth int`` to adjust size |
||
4242 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
4243 | @%segments_onclick%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1 |
||
4244 | @%segments_drag_y%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag y%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1 |
||
4245 | */ |
||
4246 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
4247 | fill_color = stroke_color; |
||
4248 | i=0; |
||
4249 | while( ! done ){ /* get next item until EOL*/ |
||
4250 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
4251 | if(i%2 == 0 ){ |
||
4252 | double_data[i] = get_real(infile,0); /* x */ |
||
4253 | } |
||
4254 | else { |
||
4255 | double_data[i] = get_real(infile,1); /* y */ |
||
4256 | } |
||
4257 | i++; |
||
4258 | } |
||
4259 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
4260 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
4261 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
4262 | decimals = find_number_of_digits(precision); |
||
4263 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18557 | bpr | 4264 | tmp_buffer=my_newmem(MAX_BUFFER); |
4265 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4266 | add_to_buffer(tmp_buffer); |
4267 | if(onclick != 0){object_cnt++;} |
||
4268 | /* object_cnt++;*/ |
||
4269 | } |
||
4270 | reset(); |
||
4271 | dragstuff[4] = 1; |
||
4272 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4273 | break; |
||
4274 | case SETLIMITS: |
||
4275 | /* |
||
18556 | bpr | 4276 | @ setlimits |
4277 | @ keyword: if set, it will produce 4 inputfields for ''xmin,xmax,ymin,ymax`` and an ''ok`` button |
||
4278 | @ may be used for inputfield based zooming / panning |
||
4279 | @ may be styled using command <a href="#css">css</a> |
||
4280 | @ use commands <a href="#xlabel">xlabel / ylabel</a> to change text from xmin to ''xlabel`` etc |
||
4281 | @ note: the input value will not be checked on validity |
||
4282 | @%setlimits%size 400,400%xrange -10,10%yrange -10,10%precision 1%xlabel T%ylabel H%axis%axisnumbering%grid 2,2,grey,2,2,5,grey%precision 100%multistrokecolors red,green,blue,orange%multilinewidth 1,1,2,2%multistrokeopacity 0.6,0.7,0.8,0.9%jsplot red,1/x,-1,x,1/(x-3),1/(x+3)%setlimits |
||
18552 | bpr | 4283 | */ |
4284 | js_function[JS_SAFE_EVAL] = 1; |
||
4285 | js_function[JSPLOT_AND_ZOOM] = 1; |
||
4286 | add_setlimits(font_size,css_class); |
||
4287 | done = TRUE; |
||
4288 | break; |
||
4289 | case SETPIXEL: |
||
4290 | /* |
||
4291 | @ setpixel x,y,color |
||
4292 | @ A rectangular "point" with diameter 1 pixel centered at (x:y) in xrange / yrange |
||
4293 | @ pixels can <b>not</b> be dragged or clicked |
||
4294 | @ "pixelsize = 1" may be changed by command <code>pixelsize int</code> |
||
4295 | @%setpixel%size 400,400%xrange -10,10%yrange -10,10%setpixel 1,1,red%pixelsize 2%setpixel 2,2,green%pixelsize 3%setpixel 3,3,blue% |
||
4296 | */ |
||
4297 | js_function[DRAW_PIXELS] = 1; |
||
4298 | for(i=0;i<3;i++){ |
||
4299 | switch(i){ |
||
4300 | case 0: double_data[0] = get_real(infile,0); break; /* x */ |
||
4301 | case 1: double_data[1] = get_real(infile,0); break; /* y */ |
||
4302 | case 2: stroke_color = get_color(infile,1); |
||
18557 | bpr | 4303 | tmp_buffer=my_newmem(MAX_BUFFER); |
4304 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_setpixel([%f],[%f],\"%s\",%.2f,%d);\n",double_data[0],double_data[1],stroke_color,stroke_opacity,pixelsize)); |
||
18552 | bpr | 4305 | add_to_buffer(tmp_buffer); |
4306 | break; |
||
4307 | default:break; |
||
4308 | } |
||
4309 | } |
||
4310 | reset(); |
||
4311 | break; |
||
4312 | case SLIDER: |
||
4313 | /* |
||
4314 | @ slider start_value,end_value,width px,height px,type,label |
||
4315 | @ type may be: ''x,y,angle`` |
||
4316 | @ if a slider value display is desired, use for argument ''type``: ''x display``, ''y display``, ''angle radian``, ''angle degree`` |
||
4317 | @ is the slider is used for animation, add keyword ''anim`` or ''animate`` to ''type``; for now only one animated slider may be used... |
||
18572 | bpr | 4318 | @ default behaviour is: click on an object to use its slider(s)<br>to use sliders without clicking on an object, use for ''type`` keyword ''active``<br>eg: <code>slider -2*pi,2*pi,300,30,angle degree active,Rotate</code> |
18552 | bpr | 4319 | @ if a unit (or something like that...) for x/y-value display is needed, use commands ''xunit`` and / or ''yunit`` |
4320 | @ if the translation should be performed using a function, use for type: ''x function``, ''y function``<br>use commands ''sliderfunction_x`` and/or ''sliderfunction_y`` before the slider command to define the functions. Example:<code>sliderfunction_x x^2<br>sliderfunction_y y^2<br>slider -5,5,100,100,xy function,Some_Text<br>...some stuff to slide<br>killslider<br>sliderfunction_x x^2-2<br>slider -15,15,100,10,x function,Some_Other_Text<br>...more stuff to slide<br>killslider... etc</code> |
||
4321 | @ use command ''slider`` before draggable/clickable objects. |
||
4322 | @ drag and drop may be combined with rotation slider<br>for example an arrow rotated by a slider may be placed anywhere (drag&drop)<br><code>size 300,300<br>xrange -5,5<br>yrange -5,5<br>grid 1,1,grey<br>linewidth 3<br>drag xy<br>fillcolor orange<br>strokecolor blue<br>slider 0,2*pi,250,30,angle degrees,Rotate arrow<br>arrow 2,2,5,5,8,red</code><br>note: except a combination 'drag' and 'slider' for command 'latex, katex, mathml, html, obabel' |
||
4323 | @ no slider for a math function, these can be traced using command ''trace_jscurve some_function_in_x`` |
||
4324 | @ a slider will affect all draggable objects after the ''slider`` command...<br>and can be used to group translate / rotate several objects...<br>until a next ''slider`` or keyword ''killslider`` |
||
4325 | @ amount of sliders is not limited. |
||
4326 | @ a slider can not be set ''snaptogrid`` or other ''snapto*`` : you may always use 'drag xy' in combination with the slider objects |
||
4327 | @ <code>javascript:read_dragdrop();</code> will return an array with ''object_number:slider_value`` |
||
4328 | @ every draggable object may have its own slider (no limit in amount of sliders) |
||
4329 | @ label: some slider text. <br>Note: on <a target='new' href='https://katex.org'>KaTeX</a> enabled wims, TeX produced by wims command ''mathmlmath``, is allowed. |
||
4330 | @ use fillcolor for slider controlkey |
||
4331 | @ use strokecolor for slider bar |
||
4332 | @ use fontfamily / fontcolor to set used fonts |
||
4333 | @ use opacity (only fill opacity will be used) to set transparency |
||
4334 | @ the slider canvas will be added to the ''tooltip div``: so incompatible with command tooltip ; setlimits etc |
||
4335 | @%slider_x_y_angle%%size 300,300%xrange -5,5%yrange -5,5%grid 1,1,grey%linewidth 3%fillcolor orange%strokecolor blue%slider 0,2*pi,300,30,angle active degrees,Rotate arrow%arrow 0,0,4.5,0,8,red%killslider%opacity 200,100%slider -2,2,300,30,x active,move blue rectangle%frect -4,4,1,-1,blue%killslider%linewidth 2%slider -2,2,300,30,y,move green rectangle%frect -4,4,1,-1,green |
||
4336 | @%slider_click%%size 300,300%xrange -6,6%yrange -6,6%grid 1,1,grey%linewidth 2%slider 0,2*pi,300,28,angle degree, name%fillcolor lightgreen%#CLICK ON THE OBJECTS TO ACTIVATE%opacity 255,30%ftriangle 2,2,-2,2,0,0,red%ftriangle -2,2,-2,-2,0,0,blue%ftriangle -2,-2,2,-2,0,0,green%ftriangle 2,-2,2,2,0,0,orange%rotationcenter 0,0%frect -2,2,2,-2,black |
||
4337 | @%slider_active%%size 300,300%xrange -6,6%yrange -6,6%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle degree active, name%fillcolor lightgreen%opacity 255,30%ftriangle 2,2,-2,2,0,0,red%ftriangle -2,2,-2,-2,0,0,blue%ftriangle -2,-2,2,-2,0,0,green%ftriangle 2,-2,2,2,0,0,orange%rotationcenter 0,0%frect -2,2,2,-2,black |
||
4338 | @%slider_animate%%size 300,300%xrange -6,6%yrange -6,6%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle anim active, name%fillcolor lightgreen%opacity 255,30%ftriangle 2,2,-2,2,0,0,red%ftriangle -2,2,-2,-2,0,0,blue%ftriangle -2,-2,2,-2,0,0,green%ftriangle 2,-2,2,2,0,0,orange%rotationcenter 0,0%frect -2,2,2,-2,black |
||
4339 | @%slider_html_image%%size 400,400%xrange -6,6%yrange -6,6%bgcolor white%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle active degree,%centered%html 0,0,<img src="gifs/domains/sciences/flasks.svg" width="100px" height="100px"> |
||
4340 | */ |
||
4341 | js_function[INTERACTIVE] = 1; |
||
4342 | int_data[2] = 0; /* --> show_display = 0; */ |
||
4343 | for(i=0; i<6 ; i++){ |
||
4344 | switch(i){ |
||
4345 | case 0: double_data[0] = get_real(infile,0);break; /* start value */ |
||
4346 | case 1: double_data[1] = get_real(infile,0);break; /* end value */ |
||
4347 | case 2: int_data[0] = (int)(get_real(infile,0));break; /* width */ |
||
4348 | case 3: int_data[1] = (int)(get_real(infile,0));break; /* height */ |
||
4349 | case 4: temp = get_string_argument(infile,0); /* type: x,y,angle */ |
||
4350 | if( strstr(temp,"displ")!=0 || strstr(temp,"deg")!=0 || strstr(temp,"rad")!=0 ){int_data[5] = 1; }else{int_data[5] = 0;} |
||
4351 | if(strstr(temp,"anim")!= 0){int_data[3] = 1;}else{int_data[3] = 0;} |
||
4352 | if(strstr(temp,"active")!= 0){onclick = 4;}else{onclick=0;} |
||
4353 | if(strstr(temp,"angle")!= 0){slider_type="R";if( strstr(temp,"rad")!= 0){int_data[2] = 3;}if( strstr(temp,"deg")!= 0){int_data[2] = 4;}} |
||
4354 | else |
||
4355 | if(strstr(temp,"xy") != 0){slider_type = "XY";if( strstr(temp,"disp")!= 0){int_data[2] = 5;}} |
||
4356 | else |
||
4357 | if(strstr(temp,"x") != 0){slider_type = "X";if( strstr(temp,"disp")!= 0){int_data[2] = 1;}} |
||
4358 | else |
||
4359 | if(strstr(temp,"y") != 0){slider_type = "Y";if( strstr(temp,"disp")!= 0){int_data[2] = 2;}} |
||
4360 | else |
||
4361 | canvas_error("slider can be of type: x,y,angle,fun_x:fun_y"); |
||
4362 | break; |
||
4363 | case 5: temp = get_string_argument(infile,1); if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\""," ");} |
||
4364 | /* slider label : in case of latex/mathmlmath we need to remove the extra " */ |
||
4365 | break; |
||
4366 | } |
||
4367 | } |
||
4368 | if(use_slider == -1 ){ /* add once */ |
||
4369 | add_slider(int_data[3]); |
||
4370 | if(int_data[5] == 1 ){add_slider_display(precision,font_size,font_color,stroke_opacity);} |
||
4371 | } |
||
4372 | use_slider++; |
||
4373 | if(int_data[3] == 0){\ |
||
18557 | bpr | 4374 | |
4375 | tmp_buffer=my_newmem(MAX_BUFFER); |
||
18570 | bpr | 4376 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"slider%d = new slider(\"%s\",\"%s\",%d,%d,%d,%d,\"%s\",\"%s\",[%f,%f],%f,%f,'%s',%d);\n",use_slider,slider_type,temp,use_slider,int_data[0],int_data[1],line_width,fill_color,stroke_color,fill_opacity,stroke_opacity,double_data[0],double_data[1],font_family,int_data[2])); |
18552 | bpr | 4377 | }else{ |
18557 | bpr | 4378 | |
18552 | bpr | 4379 | add_slider(int_data[3]);/* use only once !! */ |
18557 | bpr | 4380 | tmp_buffer=my_newmem(MAX_BUFFER); |
18570 | bpr | 4381 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"slider%d = new animslider(\"%s\",\"%s\",%d,%d,%d,%d,\"%s\",\"%s\",[%f,%f],%f,%f,'%s',%d);\n",use_slider,slider_type,temp,use_slider,int_data[0],int_data[1],line_width,fill_color,stroke_color,fill_opacity,stroke_opacity,double_data[0],double_data[1],font_family,int_data[2])); |
18552 | bpr | 4382 | } |
4383 | add_to_buffer(tmp_buffer); |
||
4384 | fprintf(js_include_file,"var slider%d;",use_slider); |
||
4385 | use_dragstuff = 2; |
||
4386 | // dragstuff[22] = 1; /* dragstuff switch no 22 is a slider...*/ |
||
4387 | if(onclick != 4 ){ js_function[INTERACTIVE] = 1; }/* no need to click on object to use slider... */ |
||
4388 | //js_function[JS_ROTATE_MOUSE] = 1; |
||
4389 | c = 0; |
||
4390 | for(i=last_slider;i<=use_slider;i++){ |
||
4391 | int_data[c] = i; c++; |
||
4392 | } |
||
4393 | my_sliders = data2js_array(int_data,use_slider - last_slider+1); |
||
4394 | break; |
||
4395 | case SGRAPH: |
||
4396 | /* |
||
18556 | bpr | 4397 | @ sgraph xstart,ystart,xmajor,ymajor,xminor,yminor,majorgrid_color,minorgrid_color |
4398 | @ primitive implementation of a ''broken scale`` graph... |
||
4399 | @ not very versatile: only usable in combination with userdraw <br>eg no other objects will obey this "coordinate system"<br>if you want to place an object into this coordinate system, be aware that 10% or 20% of xsize and/or ysize is ''lost``.<br>Use these "formulas" to recalculate the virtual coordinates:<br>factor=0.8 in case xstart != xmin (or ystart != ymin)<br>factor=0.9 in case xstart = xmin (or ystart = ymin)<br>px_x_point = ((factor*xsize)/(xmax - xstart))*(x_point - xmax)+xsize<br>x_recalculated = px*(xmax - xmin)/xsize + $xmin<br>px_y_point = -1*factor*y_point*ysize/(ymax - ystart) + ymax*factor*ysize/(ymax - ystart)<br>y_recalculated = ymax - py*(ymax - ymin)/ysize<br> |
||
4400 | @%sgraph%size 400,400%xrange 0,10000%yrange 0,100%sgraph 9000,50,100,10,4,4,grey,blue%userinput_xy%linewidth 2%userdraw segments,red%precision 0%mouse blue,22 |
||
18552 | bpr | 4401 | */ |
4402 | js_function[DRAW_SGRAPH] = 1; |
||
4403 | for(i = 0 ; i < 8 ;i++){ |
||
4404 | switch(i){ |
||
4405 | case 0:double_data[0] = get_real(infile,0);break; |
||
4406 | case 1:double_data[1] = get_real(infile,0);break; |
||
4407 | case 2:double_data[2] = get_real(infile,0);break; |
||
4408 | case 3:double_data[3] = get_real(infile,0);break; |
||
4409 | case 4:int_data[0] = (int)(get_real(infile,0));break; |
||
4410 | case 5:int_data[1] = (int)(get_real(infile,0));break; |
||
4411 | case 6:stroke_color = get_color(infile,0);break; |
||
4412 | case 7:font_color = get_color(infile,1); |
||
18557 | bpr | 4413 | tmp_buffer=my_newmem(MAX_BUFFER); |
4414 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "xstart = %f;\n ystart = %f;\ndraw_sgraph(%d,%d,%f,%f,%d,%d,\"%s\",\"%s\",\"%s\",%f,%d);\n", double_data[0],double_data[1],GRID_CANVAS,precision,double_data[2],double_data[3],int_data[0],int_data[1],stroke_color,font_color,font_family,stroke_opacity,font_size)); |
||
18552 | bpr | 4415 | add_to_buffer(tmp_buffer); |
4416 | break; |
||
4417 | default:break; |
||
4418 | } |
||
4419 | } |
||
4420 | /* sgraph(canvas_type,precision,xmajor,ymajor,xminor,yminor,majorcolor,minorcolor,fontfamily,opacity)*/ |
||
4421 | break; |
||
4422 | case SNAPTOFUNCTION: |
||
4423 | /* |
||
4424 | @ snaptofunction some_function_in_x,some_funtion_in_y |
||
4425 | @ alternative: snaptofun |
||
4426 | @ the next object will snap to the calculated values |
||
4427 | @ note: snaptofun is probably not really useful feature... |
||
4428 | @ if you want only modification of y-values,just use: <code>snaptofunction x,5*sin(1/y)</code> |
||
4429 | @ if you want only modification of x-values,just use: <code>snaptofunction 5*sin(1/x),y</code> |
||
4430 | @ for now only one instance of ''snaptofunction`` is allowed |
||
4431 | @ use rawmath on your functions: no validity checking is done by wims ! |
||
4432 | @ note: switching x and y coordinates? <code>snaptofunction y,x</code> |
||
4433 | @%snaptofunction_1%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%snaptofunction x,5*sin(x)%linewidth 3%crosshairsize 6%userdraw crosshairs,red%linewidth 2%curve blue,5*sin(x)%xunit = x-value%display x,blue,22 |
||
4434 | @%snaptofunction_2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%snaptofunction y^2-9,y%#snaptofunction y^2-9,abs(y)%linewidth 3%crosshairsize 6%userdraw crosshairs,red%linewidth 2%curve blue,sqrt(x+9)%curve blue,-1*sqrt(x+9)%yunit = y-value%display y,blue,22 |
||
4435 | */ |
||
4436 | temp = get_string_argument(infile,0); |
||
4437 | use_snap = 2; |
||
4438 | use_snap = 5; |
||
4439 | js_function[JS_MATH] = 1; |
||
4440 | fprintf(js_include_file,"var snap_fun = {x:to_js_math('%s'),y:to_js_math('%s')};function snap_to_fun(px,py){ var x = px2x(px); var y = px2y(py); return [ x2px(eval(snap_fun.x)) , y2px(eval(snap_fun.y)) ];};",temp,get_string(infile,1)); |
||
4441 | break; |
||
4442 | case SNAPTOPOINTS: |
||
4443 | /* |
||
4444 | @ snaptopoints x1,y1,x2,y2,x3,y3.... |
||
4445 | @ a userdraw object will snap to these points. |
||
18572 | bpr | 4446 | @ the array size (e.g. the number of points) of command ''snaptopoints`` is limited by constant MAX_INT (canvasdraw.h)<br>this command may be repeated multiple times (no limit) to add points |
18552 | bpr | 4447 | @ a draggable object (use command ''drag x|y|xy``) will snap to the closed of these points when dragged (mouseup) |
4448 | @ other options: use keyword ''snaptogrid``, ''xsnaptogrid`` or ''ysnaptogrid`` |
||
4449 | @%snaptopoints%size 400,400%xrange -5,5%yrange -5,5%snaptopoints -1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%linewidth 2%points red,-1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%userdraw arrows,red |
||
4450 | @%snaptopoints%size 400,400%xrange -5,5%yrange -5,5%snaptopoints -1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%linewidth 3%%points blue,-1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%drag xy%ftriangle -4,0,-2,3,0,0,red |
||
4451 | */ |
||
4452 | i = 0; |
||
4453 | while( ! done ){ /* get next item until EOL*/ |
||
4454 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
4455 | if(i%2 == 0 ){ |
||
4456 | double_data[i] = get_real(infile,0); /* x */ |
||
4457 | } |
||
4458 | else { |
||
4459 | double_data[i] = get_real(infile,1); /* y */ |
||
4460 | } |
||
4461 | i++; |
||
4462 | } |
||
4463 | decimals = find_number_of_digits(precision); |
||
4464 | /* NEED AN EXTRA COUNTER VARIABLE FOR MORE THAN 2 CALLS */ |
||
4465 | fprintf(js_include_file,"if( temp_push_array === 'undefined' ){var temp_push_array;};if( points_to_snap_on === 'undefined' ){var points_to_snap_on;};var temp_push_array = [%s];\n",double_xy2js_array(double_data,i,decimals)); |
||
4466 | if( snap_to_points_cnt == 0 ){ |
||
4467 | fprintf(js_include_file,"points_to_snap_on = temp_push_array;function find_min_diff(x,y,X,Y){var diff = 100000000;var chk;var idx = 0;var p = 0;while(X[p] != null){chk = distance(x,y,X[p],Y[p]);if( chk < diff ){ diff = chk; idx = p;};p++;};return idx;};function snap_to_points(x,y){x = px2x(x); y = px2y(y);var xpoints = points_to_snap_on[0];var ypoints = points_to_snap_on[1];var idx = find_min_diff(x,y,xpoints,ypoints);x = xpoints[idx];y = ypoints[idx];return [x2px(x),y2px(y)];};"); |
||
4468 | }else{ |
||
4469 | fprintf(js_include_file,"points_to_snap_on[0].push.apply(points_to_snap_on[0],temp_push_array[0]);points_to_snap_on[1].push.apply(points_to_snap_on[1],temp_push_array[1]);"); |
||
4470 | } |
||
4471 | snap_to_points_cnt = 1; /* do not repeat including the js-functions...just once*/ |
||
4472 | use_snap = 4; |
||
4473 | break; |
||
4474 | case SNAPTOGRID: |
||
4475 | /* |
||
18556 | bpr | 4476 | @ snaptogrid |
4477 | @ keyword (no arguments required) |
||
4478 | @ a draggable object (use command ''drag x|y|xy``) will snap to the given grid when dragged (mouseup) |
||
4479 | @ in case of userdraw the drawn points will snap to xmajor / ymajor grid |
||
4480 | @ if no grid is defined, points will snap to every integer xrange/yrange value. (eg snap_x=1,snap_y=1) |
||
4481 | @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0. |
||
4482 | @ if xminor / yminor is defined,(use keyword ''axis`` to activate the minor steps) the drawing will snap to xminor and yminor<br>use only even dividers in x/y-minor...for example <code>snaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code> will snap on x=0, x=0.5, x=1, x=1.5 .... will snap on y=0, y=0.25 y=0.5 y=0.75 ... |
||
4483 | @%snaptogrid_1%size 400,400%xrange -5,5%yrange -5,5%axis%axisnumbering%precision 1%grid 1,1,grey,2,2,6,grey%linewidth 2%snaptogrid%userdraw crosshairs,blue%mouse red,22 |
||
4484 | @%snaptogrid_2%size 400,400%xrange -5,5%yrange -5,5%axis%axisnumbering%precision 1%grid 1,1,grey,4,1,6,grey%linewidth 1%snaptogrid%userdraw crosshairs,blue%mouse red,22 |
||
18552 | bpr | 4485 | */ |
4486 | use_snap = 1; |
||
4487 | break; |
||
4488 | case SQUARE: |
||
4489 | /* |
||
4490 | @ square x,y,side (px),color |
||
4491 | @ draw a square with left top corner (x:y) with side ''side`` in color 'color' |
||
4492 | @ use command <code>fsquare x,y,side,color</code> for a filled square |
||
4493 | @ use command/keyword <a href='#filled'>filled</a> before command <code>square x,y,side,color</code> |
||
4494 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
4495 | @%square%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%filled%fillcolor blue%square 0,0,120,green |
||
4496 | */ |
||
4497 | for(i=0;i<4;i++){ |
||
4498 | switch(i){ |
||
4499 | case 0:double_data[0] = get_real(infile,0);break; /* x1-values */ |
||
4500 | case 1:double_data[1] = get_real(infile,0);break; /* y1-values */ |
||
4501 | case 2:double_data[2] = get_real(infile,0);break; /* width in px */ |
||
4502 | case 3:stroke_color = get_color(infile,1);/* name or hex color */ |
||
4503 | decimals = find_number_of_digits(precision); |
||
4504 | double_data[3] = double_data[0] + (xmax - xmin)*double_data[2]/xsize; |
||
4505 | double_data[4] = double_data[1] + -1*(ymax - ymin)*double_data[2]/ysize; |
||
4506 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 4507 | tmp_buffer=my_newmem(MAX_BUFFER); |
4508 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,1,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[3],decimals,double_data[3],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[4],decimals,double_data[4],line_width,line_width,line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4509 | add_to_buffer(tmp_buffer); |
4510 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
4511 | reset();break; |
||
4512 | default: break; |
||
4513 | } |
||
4514 | } |
||
4515 | dragstuff[1] = 1; |
||
4516 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4517 | break; |
||
4518 | case STATUS: |
||
4519 | /* |
||
4520 | @ status |
||
4521 | @ keyword |
||
4522 | @ alernative: nostatus |
||
4523 | @ used to override the effects of ''status=done`` in wims (answer.phtml) |
||
4524 | @ affects ''readonly`` in inputfields / textareas in canvasimage and all userdraw based commands |
||
4525 | @ e.g.: if keyword ''status`` is set, the pupil will be able to modify the canvas when the ''wims $status variable`` is set to ''done`` |
||
4526 | */ |
||
11806 | schaersvoo | 4527 | |
18552 | bpr | 4528 | fprintf(js_include_file,"\nwims_status=\"waiting\";\n"); |
4529 | break; |
||
4530 | case STRING: |
||
4531 | /* |
||
18556 | bpr | 4532 | @ string color,x,y,the text string |
4533 | @ may be set ''onclick`` or ''drag xy`` |
||
4534 | @ note: when set ''onclick``, use an extra command ''fontsize`` (default: fontsize=12) to adjust the size of the clicked text-string<br>note: a clicked text string will be hardcoded : fontsize+10 in the font family courier |
||
18572 | bpr | 4535 | @ unicode supported: <code>string red,0,0,\\u2232</code><br> See <a target='new' href='https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode'>https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode</a><br> See <a target='new' href='https://en.wikipedia.org/wiki/Greek_script_in_Unicode'>https://en.wikipedia.org/wiki/Greek_script_in_Unicode</a> |
18556 | bpr | 4536 | @ use a command like <code>fontfamily italic 24px Arial</code> to set fonts on browser that support font change |
4537 | @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>The font family for the sub/sup string will be Helvetica e.g. your font family settings will be ignored <br>to force end the subscript/supscript, use an extra space...see example: |
||
4538 | @%string_sup_sub%size 400,400%xrange -6,6%yrange -6,6%fontfamily 22px Arial%# you can use a single space for separation in formula...%# use double space to create new word%string blue,-5,3,H_3O^+ + OH^- \\u2192 2H_2O%# you can use a single space for separation in formula...%string red,-5,-3,H_3 O^+ + OH^\\u2212 \\u2192 2H_2 O% |
||
4539 | @%string%size 400,400%xrange -10,10%yrange -10,10%fontfamily 14px Arial%crosshair -3,-3,red%crosshair 3,3,blue%string red,-3,-3,Hello World%fontfamily Italic 18px Arial%string red,3,3,Hello World%fontfamily 22pt STIX%string black,-10,8,\\u03B1 \\u03B2 \\u03B3 \\u03B4 \\u03B5 \\u03B6 \\u03B7 \\u03B8 \\u03B9 \\u03BA \\u03BB \\u03BC \\u03BD \\u03BE \\u03BF |
||
18552 | bpr | 4540 | */ |
4541 | if( use_rotate == TRUE ){js_function[JS_ROTATE_MOUSE] = 1; } |
||
4542 | dragstuff[14] = 1; |
||
4543 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4544 | for(i=0;i<5;i++){ |
||
4545 | switch(i){ |
||
4546 | case 0: stroke_color = get_color(infile,0);break;/* name or hex color */ |
||
4547 | case 1: double_data[0] = get_real(infile,0);break; /* x in xrange*/ |
||
4548 | case 2: double_data[1] = get_real(infile,0);break; /* y in yrange*/ |
||
4549 | case 3: decimals = find_number_of_digits(precision); |
||
4550 | if(use_affine == TRUE ){ transform(2,2);} |
||
4551 | /* rotate is done by HTML5/CANVAS context rotation */ |
||
4552 | temp = get_string_argument(infile,1); |
||
4553 | if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;} |
||
4554 | decimals = find_number_of_digits(precision); |
||
4555 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 4556 | tmp_buffer=my_newmem(MAX_BUFFER); |
4557 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4558 | add_to_buffer(tmp_buffer); |
4559 | if(onclick != 0){object_cnt++;} |
||
4560 | //onclick = 0; |
||
4561 | //use_offset = 0; |
||
4562 | reset(); |
||
4563 | break; |
||
4564 | default:break; |
||
4565 | } |
||
4566 | } |
||
4567 | break; |
||
4568 | case STRINGUP: |
||
4569 | /* |
||
18556 | bpr | 4570 | @ stringup color,x,y,rotation_degrees,the text string |
4571 | @ may be set ''onclick`` or ''drag xy`` |
||
4572 | @ note: when set ''onclick``, use an extra command ''fontsize`` (default: fontsize=12) to adjust the size of the clicked text-string<br>note: a clicked text string will be hardcoded : fontsize+10 in the font family courier |
||
4573 | @ unicode supported: <code>stringup red,0,0,45,\\u2232</code> |
||
4574 | @ use a command like <code>fontfamily bold 34px Courier</code> to set fonts on browser that support font change |
||
4575 | @ you could use keyword <a href='#yoffset'>yoffset</a> to -sometimes- do a small correction of text placement under/above a point (e.g. text & point have thesame coordinates) |
||
18572 | bpr | 4576 | @ note: no need to ''killrotate`` after ''stringup``<br><code>onclick<br>rotate 45<br>string red,0,0,AAAAAA<br>killrotate<br>string red,4,4,BBBBBB</code><br>is identical with:<br><code>onclick<br>stringup red,0,0,45,AAAAAA<br>string red,4,4,BBBBBB</code> |
18556 | bpr | 4577 | @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>to end the subscript/supscript, use an extra space...see example: |
4578 | @%stringup_sub_sup%size 400,400%xrange -6,6%yrange -6,6%fontfamily 22px Arial%# use single space for separation in formula...%# use double space to create new word%stringup red,-5,0,45,H_3 O^+ + OH^\\u2212 \\u2192 2H_2 O% |
||
4579 | @%stringup%size 400,400%xrange -10,10%yrange -10,10%fontsize 24%fontfamily 14px Arial%crosshair -3,0,red%crosshair 3,0,blue%onclick%stringup red,-3,0,-90,Hello World%drag xy%stringup red,-3,0,-45,Hello World%stringup red,-3,0,45,Hello World%stringup red,-3,0,90,Hello World%stringup blue,3,0,-90,Hello World%stringup blue,3,0,-45,Hello World%stringup blue,3,0,45,Hello World%stringup blue,3,0,90,Hello World |
||
11806 | schaersvoo | 4580 | |
18552 | bpr | 4581 | */ |
4582 | /* html5 canvas rotation is only used for text objects */ |
||
4583 | use_rotate = TRUE ; |
||
4584 | dragstuff[14] = 1; |
||
4585 | js_function[JS_ROTATE_MOUSE] = 1; |
||
4586 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
10953 | bpr | 4587 | |
18552 | bpr | 4588 | for(i=0;i<6;i++){ |
4589 | switch(i){ |
||
4590 | case 0: stroke_color = get_color(infile,0);break;/* name or hex color */ |
||
4591 | case 1: double_data[0] = get_real(infile,0);break; /* x */ |
||
4592 | case 2: double_data[1] = get_real(infile,0);break; /* y */ |
||
4593 | case 3: angle = get_real(infile,0);break;/* rotation */ |
||
4594 | case 4: decimals = find_number_of_digits(precision); |
||
4595 | temp = get_string_argument(infile,1); |
||
4596 | if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;} |
||
4597 | decimals = find_number_of_digits(precision); |
||
4598 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 4599 | tmp_buffer=my_newmem(MAX_BUFFER); |
4600 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4601 | add_to_buffer(tmp_buffer); |
4602 | if(onclick != 0){object_cnt++;} |
||
4603 | //onclick = 0; |
||
4604 | //use_offset = 0; |
||
4605 | reset(); |
||
4606 | break; |
||
4607 | default:break; |
||
4608 | } |
||
4609 | } |
||
4610 | use_rotate = FALSE; |
||
4611 | break; |
||
4612 | case STYLE: |
||
4613 | /* |
||
18556 | bpr | 4614 | @ highlight color,opacity,linewidth |
4615 | @ NOT IMPLEMENTED |
||
4616 | @ use command ''onclick``: when the object receives a userclick it will increase its linewidth |
||
18552 | bpr | 4617 | */ |
4618 | break; |
||
4619 | case STROKECOLOR: |
||
4620 | /* |
||
4621 | @ strokecolor colorname or #hex |
||
4622 | @ to be used for commands that do not supply a color argument (like command ''linegraph``) |
||
4623 | */ |
||
4624 | stroke_color = get_color(infile,1); |
||
4625 | break; |
||
4626 | case FLY_TEXT: |
||
4627 | /* |
||
4628 | @ text fontcolor,x,y,font,text_string |
||
4629 | @ font may be described by keywords: giant,huge,normal,small,tiny |
||
4630 | @ use command ''fontsize`` to increase base fontsize for these keywords |
||
4631 | @ may be set ''onclick`` or ''drag xy`` |
||
4632 | @ backwards compatible with flydraw |
||
4633 | @ unicode supported: text red,0,0,huge,\\u2232 |
||
4634 | @ special: use '_' and '^' to imitate html sup/sub, like H_3O^+ + OH^\\u22i2 \\u2192 2H_2 O |
||
4635 | @ much better to use command <a href='#string'>string</a> combined with <a href='#fontfamily'>fontfamily</a> for a more fine grained control over html5 canvas text element |
||
4636 | @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>to end the subscript/supscript, use an extra space...see <a href='#string'>string </a> command |
||
4637 | @ Avoid mixing old flydraw commands ''text``, ''textup`` with new canvasdraw commands ''string``, ''stringup``. If the fontfamily was set completely like <code>fontfamily italic 24px Arial</code>. In that case reset ''fontfamily`` to something lke ''fontfamily Arial`` before the old flydraw commands. |
||
4638 | @%text%size 400,400%xrange -10,10%yrange -10,10%fontsize 14%onclick%drag xy%text green,-4,-4,small,Hello World%drag xy%text red,-4,-2,large,Hello World%drag xy%text blue,-4,0,huge,Hello World%drag xy%text green,-4,3,giant,Hello World%drag xy |
||
4639 | */ |
||
4640 | for(i = 0; i < 5 ;i++){ |
||
4641 | switch(i){ |
||
4642 | case 0: stroke_color = get_color(infile,0);break;/* font_color == stroke_color name or hex color */ |
||
4643 | case 1: double_data[0] = get_real(infile,0);break; /* x */ |
||
4644 | case 2: double_data[1] = get_real(infile,0);break; /* y */ |
||
4645 | case 3: fly_font = get_string_argument(infile,0); |
||
4646 | if(strcmp(fly_font,"giant") == 0){ |
||
4647 | fly_font_size = (int)(font_size + 24); |
||
4648 | } |
||
4649 | else { |
||
4650 | if(strcmp(fly_font,"huge") == 0){ |
||
4651 | fly_font_size = (int)(font_size + 14); |
||
4652 | } |
||
4653 | else { |
||
4654 | if(strcmp(fly_font,"large") == 0){ |
||
4655 | fly_font_size = (int)(font_size + 6); |
||
4656 | } |
||
4657 | else { |
||
4658 | if(strcmp(fly_font,"small") == 0){ |
||
4659 | fly_font_size = (int)(font_size - 4); |
||
4660 | if(fly_font_size<0){fly_font_size = 8;} |
||
4661 | } |
||
4662 | } |
||
4663 | } |
||
4664 | } |
||
4665 | break; |
||
4666 | case 4: |
||
4667 | temp = get_string_argument(infile,1); |
||
4668 | if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;} |
||
4669 | decimals = find_number_of_digits(precision); |
||
4670 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
4671 | if(use_affine == TRUE ){ transform(2,2);} |
||
18557 | bpr | 4672 | tmp_buffer=my_newmem(MAX_BUFFER); |
4673 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,%s,%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,fly_font_size,"null",my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4674 | add_to_buffer(tmp_buffer); |
4675 | if(onclick != 0){object_cnt++;} |
||
4676 | reset(); |
||
4677 | break; |
||
4678 | default:break; |
||
4679 | } |
||
4680 | } |
||
4681 | dragstuff[14] = 1; |
||
4682 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4683 | break; |
||
4684 | case TEXTAREA: |
||
4685 | /* |
||
18556 | bpr | 4686 | @ textarea x,y,cols,rows,readonly,value |
4687 | @ may be further controlled by <a href="#css">css</a> |
||
4688 | @ if ''$status=done`` (e.g. in answer.phtml) the inputfield will be cleared and set readonly. Override this by keyword <a href="#status">status</a>. |
||
4689 | @ if mathml inputfields are present and / or some userdraw is performed, these data will <b>not</b> be send as well (<code>javascript:read_canvas();</code>) |
||
4690 | @ keyword ''xoffset | centered`` is not active for command ''textarea`` |
||
4691 | @%textarea%size 400,400%xrange -10,10%yrange -10,10%css color:red;background-color:lightblue;font-size:14px;text-align:center%textarea -3,-2,6,3,1,?%css color:blue;background-color:yellow;font-size:14px;text-align:center%textarea 0,-2,8,2,1,? |
||
18552 | bpr | 4692 | */ |
4693 | js_function[DRAW_TEXTAREAS] = 1; |
||
4694 | for(i = 0 ; i<6;i++){ |
||
4695 | switch(i){ |
||
4696 | case 0: int_data[0]=x2px(get_real(infile,0));break; /* x in px */ |
||
4697 | case 1: int_data[1]=y2px(get_real(infile,0));break; /* y in px */ |
||
4698 | case 2: int_data[2]=abs( (int)(get_real(infile,0)));break;/* cols */ |
||
4699 | case 3: int_data[3]=abs( (int)(get_real(infile,0)));break;/* rows */ |
||
4700 | case 4: if( get_real(infile,1) >0){int_data[4] = 1;}else{int_data[3] = 0;};break; /* readonly */ |
||
4701 | case 5: temp = get_string_argument(infile,1); |
||
18557 | bpr | 4702 | tmp_buffer=my_newmem(MAX_BUFFER); |
4703 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_textareas(%d,%d,%d,%d,%d,%d,%d,\"%s\",\"%s\");\n",canvas_root_id,input_cnt,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],css_class,temp)); |
||
18552 | bpr | 4704 | add_to_buffer(tmp_buffer); |
4705 | input_cnt++;break; |
||
4706 | default: break; |
||
4707 | } |
||
4708 | } |
||
4709 | if(reply_format == 0 ){reply_format = 15;} |
||
4710 | reset(); |
||
4711 | break; |
||
4712 | case TEXTFILL: |
||
4713 | /* |
||
4714 | @ textfill x0,y0,color,some_text |
||
4715 | @ x0,y0 in xrange / yrange |
||
4716 | @ color will be used for the font color |
||
4717 | @ use command <a href="#fontfamily">fontfamily</a> to set font type and size |
||
4718 | @ there is also a command <a href="#userdraw">userdraw textfill,color,some_text</a> |
||
4719 | @%textfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%fontfamily 24pt Arial%circles red,0,0,3,3,3,6%textfill 4,4,blue,HELLO WORLD |
||
4720 | */ |
||
11806 | schaersvoo | 4721 | |
18552 | bpr | 4722 | js_function[DRAW_TEXTFILL] = 1; |
4723 | if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */ |
||
4724 | js_function[DRAW_FILLTOBORDER] = 1; |
||
4725 | add_js_filltoborder(canvas_type); |
||
4726 | } |
||
4727 | decimals = find_number_of_digits(precision); |
||
4728 | for(i=0;i<4;i++){ |
||
4729 | switch(i){ |
||
4730 | case 0: double_data[0] = get_real(infile,0); break; /* x in px */ |
||
4731 | case 1: double_data[1] = get_real(infile,0); break; /* y in py */ |
||
4732 | case 2: font_color = get_color(infile,0); break; |
||
4733 | case 3: temp = get_string(infile,1); |
||
18557 | bpr | 4734 | tmp_buffer=my_newmem(MAX_BUFFER); |
4735 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_textfill(%d,%*.f,%*.f,'%s','%s',%d,%d,'%s',false); ",FILL_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],font_color,font_family,xsize,ysize,temp)); |
||
18552 | bpr | 4736 | add_to_buffer(tmp_buffer); |
4737 | fill_cnt++; |
||
4738 | break; |
||
4739 | default:break; |
||
4740 | } |
||
4741 | } |
||
4742 | reset(); |
||
4743 | break; |
||
4744 | case FLY_TEXTUP: |
||
4745 | /* |
||
18556 | bpr | 4746 | @ textup fontcolor,x,y,font,text_string |
4747 | @ can <b>not</b> be set ''onclick`` or ''drag xy`` (because of translaton matrix...mouse incompatible) |
||
4748 | @ font may be described by keywords: giant,huge,normal,small,tiny |
||
4749 | @ use command ''fontsize`` to increase base fontsize for the keywords |
||
4750 | @ backwards compatible with flydraw |
||
4751 | @ unicode supported: textup red,0,0,huge,\\u2232 |
||
4752 | @ use command ''stringup`` and ''fontfamily`` for a more fine grained control over html5 canvas text element |
||
4753 | @ Avoid mixing old flydraw commands ''text``, ''textup`` with new canvasdraw commands ''string``; ''stringup``. If the fontfamily was set completely like <code>fontfamily italic 24px Arial</code>. In that case reset ''fontfamily`` to something like ''fontfamily Arial`` before the old flydraw commands. |
||
18552 | bpr | 4754 | */ |
4755 | js_function[DRAW_TEXTS] = 1; |
||
4756 | for(i = 0; i<5 ;i++){ |
||
4757 | switch(i){ |
||
4758 | case 0: font_color = get_color(infile,0);break;/* name or hex color */ |
||
4759 | case 1: int_data[0] = x2px(get_real(infile,0));break; /* x */ |
||
4760 | case 2: int_data[1] = y2px(get_real(infile,0));break; /* y */ |
||
4761 | case 3: fly_font = get_string_argument(infile,0); |
||
4762 | if(strcmp(fly_font,"giant") == 0){ |
||
4763 | fly_font_size = (int)(font_size + 24); |
||
4764 | } |
||
4765 | else { |
||
4766 | if(strcmp(fly_font,"huge") == 0){ |
||
4767 | fly_font_size = (int)(font_size + 14); |
||
4768 | } |
||
4769 | else { |
||
4770 | if(strcmp(fly_font,"large") == 0){ |
||
4771 | fly_font_size = (int)(font_size + 6); |
||
4772 | } |
||
4773 | else { |
||
4774 | if(strcmp(fly_font,"small") == 0){ |
||
4775 | fly_font_size = (int)(font_size - 4); |
||
4776 | if(fly_font_size<0){fly_font_size = 8;} |
||
4777 | } |
||
4778 | } |
||
4779 | } |
||
4780 | } |
||
4781 | break; |
||
4782 | case 4: |
||
4783 | decimals = find_number_of_digits(precision); |
||
4784 | temp = get_string_argument(infile,1); |
||
4785 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 4786 | tmp_buffer=my_newmem(MAX_BUFFER); |
4787 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_text(%d,%d,%d,%d,\"%s\",\"%s\",%.2f,90,\"%s\",%d,%.2f,%d);\n",STATIC_CANVAS,int_data[0],int_data[1],fly_font_size,"null",font_color,stroke_opacity,temp,use_rotate,angle,use_offset)); |
||
18552 | bpr | 4788 | add_to_buffer(tmp_buffer); |
4789 | reset(); |
||
4790 | //use_offset = 0; |
||
4791 | break; |
||
4792 | default:break; |
||
4793 | } |
||
4794 | } |
||
4795 | break; |
||
4796 | case TRACE_JSCURVE: |
||
4797 | /* |
||
18556 | bpr | 4798 | @ trace_jscurve some_math_function |
4799 | @ will use a crosshair to trace the jsmath curve |
||
4800 | @ two inputfields will display the current x/y-values (numerical evaluation by javascript) |
||
4801 | @ default labels ''x`` and ''y``; use commands ''xlabel some_x_axis_name`` and ''ylabel some_y_axis_name`` to customize the labels for the input fields |
||
4802 | @ use commands fontsize and css to format the fonts for labels and inputfields. |
||
4803 | @ use commands ''linewidth, strokecolor, crosshairsize`` to adjust the corsshair. |
||
4804 | @ the client browser will convert your math function to javascript math.<br>use parenthesis and rawmath: use 2*x instead of 2x etc etc no check is done on the validity of your function and/or syntax (use error console to debug any errors...) |
||
4805 | @ be aware that the formulas of the plotted function(s) can be found in the page javascript source |
||
4806 | @%trace_jscurve%size 400,400%xrange -10,10%yrange -10,10%precision 0%axis%axisnumbering%grid 2,2,grey,2,2,5,gray%recision 100%css color:blue;%linewidth 4%crosshairsize 8%trace_jscurve 5*sin(0.1*x^2)%linewidth 1%jsplot red,5*sin(0.1*x^2)%#only one curve can be traced |
||
18552 | bpr | 4807 | */ |
4808 | js_function[INTERACTIVE] = 1; |
||
4809 | js_function[DRAW_CROSSHAIRS] = 1; |
||
4810 | js_function[DRAW_LINES] = 1; |
||
4811 | js_function[JS_MATH] = 1; |
||
4812 | add_trace_js_mouse(TRACE_CANVAS,stroke_color,get_string(infile,1),font_size,stroke_opacity,line_width,crosshair_size,css_class); |
||
4813 | break; |
||
4814 | case TRANGE: |
||
4815 | /* |
||
4816 | @ trange tmin,tmax |
||
4817 | @ alternative: ranget |
||
4818 | @ default -2,2 |
||
4819 | */ |
||
4820 | use_parametric = TRUE; |
||
4821 | for(i = 0 ; i<2; i++){ |
||
4822 | switch(i){ |
||
4823 | case 0: tmin = get_real(infile,0);break; |
||
4824 | case 1: tmax = get_real(infile,1);break; |
||
4825 | default: break; |
||
4826 | } |
||
4827 | } |
||
4828 | if(tmin >= tmax ){canvas_error(" trange is not OK: tmin < tmax!\n");} |
||
4829 | break; |
||
4830 | case TRANSLATION: |
||
4831 | /* |
||
18556 | bpr | 4832 | @ translation tx,ty |
4833 | @ alternative: translate |
||
4834 | @ will translate the next objects tx in xrange and ty in yrange |
||
4835 | @ use command ''killtranstation`` to end the command |
||
18569 | bpr | 4836 | @%translation%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%fillpattern grid%triangle -6,6,8,6,5,1,blue%translation 2,2%ftriangle -6,6,8,6,5,1,red |
18552 | bpr | 4837 | */ |
4838 | for(i = 0 ; i<2;i++){ |
||
4839 | switch(i){ |
||
4840 | case 0: affine_matrix[4] = get_real(infile,0);break; |
||
4841 | case 1: affine_matrix[5] = get_real(infile,1); |
||
4842 | use_affine = TRUE; |
||
4843 | /* the other values affine_matrix[0..3] remain untouched*/ |
||
4844 | break; |
||
4845 | default: break; |
||
4846 | } |
||
4847 | } |
||
4848 | break; |
||
4849 | case TRIANGLE: |
||
4850 | /* |
||
18556 | bpr | 4851 | @ triangle x1,y1,x2,y2,x3,y3,color |
4852 | @ use ftriangle or keyword <a href='#filled'>filled</a> for a solid triangle |
||
4853 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
4854 | @%triangle%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%opacity 250,150%drag xy%triangle 0,0,-4,4,6,8,red%drag xy%ftriangle 0,0,-4,-4,6,-8,red%fillpattern grid%drag xy%ftriangle -6,6,8,6,5,1,blue |
||
18552 | bpr | 4855 | */ |
4856 | for(i=0;i<7;i++){ |
||
4857 | switch(i){ |
||
4858 | case 0: double_data[0] = get_real(infile,0);break; /* x */ |
||
4859 | case 1: double_data[1] = get_real(infile,0);break; /* y */ |
||
4860 | case 2: double_data[2] = get_real(infile,0);break; /* x */ |
||
4861 | case 3: double_data[3] = get_real(infile,0);break; /* y */ |
||
4862 | case 4: double_data[4] = get_real(infile,0);break; /* x */ |
||
4863 | case 5: double_data[5] = get_real(infile,0);break; /* y */ |
||
4864 | case 6: stroke_color = get_color(infile,1);/* name or hex color */ |
||
4865 | decimals = find_number_of_digits(precision); |
||
4866 | if( use_rotate == TRUE ){ rotate(6,angle,rotationcenter,2);} |
||
4867 | if( use_affine == TRUE ){ transform(6,2);} |
||
4868 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 4869 | tmp_buffer=my_newmem(MAX_BUFFER); |
4870 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,6,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4871 | add_to_buffer(tmp_buffer); |
4872 | if(onclick != 0){object_cnt++;} |
||
4873 | /* object_cnt++;*/ |
||
4874 | reset(); |
||
4875 | break; |
||
4876 | default: break; |
||
4877 | } |
||
4878 | } |
||
4879 | dragstuff[5] = 1; |
||
4880 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4881 | break; |
||
4882 | case TRIANGLES: |
||
4883 | /* |
||
18556 | bpr | 4884 | @ triangles color,x1,y1,x2,y2,x3,y3,... |
4885 | @ use ftriangles or keyword <a href='#filled'>filled</a> for solid triangles |
||
4886 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
4887 | @%triangles%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%onclick%triangles red,0,0,-4,4,6,8,0,0,-4,-4,6,-8,-6,6,8,6,5,1%# the same as 3 calls to command triangle |
||
18552 | bpr | 4888 | */ |
4889 | stroke_color = get_color(infile,0);/* name or hex color */ |
||
4890 | i = 0; |
||
4891 | decimals = find_number_of_digits(precision); |
||
4892 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
11806 | schaersvoo | 4893 | |
18552 | bpr | 4894 | while( ! done ){ |
4895 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
4896 | double_data[0] = get_real(infile,0); /* x1 */ |
||
4897 | double_data[1] = get_real(infile,0); /* y1 */ |
||
4898 | double_data[2] = get_real(infile,0); /* x2 */ |
||
4899 | double_data[3] = get_real(infile,0); /* y2 */ |
||
4900 | double_data[4] = get_real(infile,0); /* x3 */ |
||
4901 | double_data[5] = get_real(infile,1); /* y3 */ |
||
18557 | bpr | 4902 | tmp_buffer=my_newmem(MAX_BUFFER); |
4903 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,6,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 4904 | add_to_buffer(tmp_buffer); |
4905 | if(onclick != 0){object_cnt++;} |
||
4906 | i = i + 6; |
||
4907 | } |
||
4908 | reset(); |
||
4909 | dragstuff[5] = 1; |
||
4910 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
4911 | break; |
||
4912 | case USERBOXPLOT: |
||
4913 | /* |
||
18556 | bpr | 4914 | @ userboxplot |
4915 | @ keyword, no arguments |
||
4916 | @ use before command <a href="#boxplot">boxplot x_or_y,box-height_or_box-width,x_or_y-position</a> |
||
4917 | @ if set, the student will have to calculate "min,Q1,median,Q3,max" and feed these data into the ''draw_boxplot`` function |
||
4918 | @ for example: put the canvas-script into a html element with id='boxplot' and set style='display:none'<br>define a variable called ''student_boxplot`` and fill it with the 5 student-data (from inputfields or something)<br><code>var student_boxplot = new Array(5)<br>function show_boxplot(){<br>student_boxplot[0] = min;<br>student_boxplot[1] = Q1;<br>student_boxplot[2] = median;<br>student_boxplot[3] = Q3;<br>student_boxplot[4] = max;<br>document.getElementById('boxplot').style.display = "block";<br>draw_boxplot(12345,1,2.00,5.00,[0,0,0,0,0],4,"0,0,255",0.78,"255,165,0",0.60,1,0,1,1);<br>};</code><br>In the canvas-script the function draw_boxplot has the following arguments:<br>draw_boxplot=function(canvas_type,xy,hw,cxy,data,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1) |
||
18552 | bpr | 4919 | */ |
4920 | js_function[DRAW_BOXPLOT] = 1; |
||
4921 | fprintf(js_include_file,"var boxplot_source = 3;\n"); |
||
4922 | js_function[DRAW_JSBOXPLOT] = 2; |
||
4923 | break; |
||
4924 | case USERBOXPLOTDATA: |
||
4925 | /* |
||
18556 | bpr | 4926 | @ userboxplotdata |
4927 | @ keyword, no arguments |
||
4928 | @ use before command <a href="#boxplot">boxplot x_or_y,box-height_or_box-width,x_or_y-position</a> |
||
4929 | @ if set, the student will have to generate some statistical data. These data should be put in a named array ''student_boxplot_data`` |
||
4930 | @ ''min,Q1,median,Q3,max`` are calculated by a js-function and the 'draw_boxplot' function will draw a boxplot. |
||
4931 | @ see command <a href="#userboxplot">userboxplot</a> for calling 'draw_boxplot()' |
||
18552 | bpr | 4932 | */ |
4933 | js_function[DRAW_BOXPLOT] = 1; |
||
4934 | fprintf(js_include_file,"var boxplot_source = 2;\n"); |
||
4935 | js_function[DRAW_JSBOXPLOT] = 1; |
||
4936 | break; |
||
4937 | case USERDRAW: |
||
4938 | /* |
||
4939 | @ userdraw object_type,color |
||
4940 | @ only a single object_type is allowed. |
||
4941 | @ right mouse click will remove last drawn object. |
||
4942 | @ for multiple different 'userdraw' objects in an exercise, use command <a href="#multidraw">multidraw</a> |
||
18572 | bpr | 4943 | @ implemented object_type: <ul><li>point</li><li>points</li><li>crosshair</li><li>crosshairs</li><li>line</li><li>lines</li><li>vline</li><li>vlines</li><li>hline</li><li>hlines</li><li>demiline</li><li>demilines</li><li>segment</li><li>segments</li><li>polyline | brokenline</li><li>circle</li><li>circles</li><li>arrow</li><li>arrow2 (double arrow)</li><li>arrows</li><li>arrows2 (double arrows)</li><li>curvedarrow</li><li>curvedarrows</li><li>curvedarrow2</li><li>curvedarrows2</li><li>triangle</li><li>polygon</li><li>poly[3-9] (e.g poly3 ... poly7...poly9</li><li>rect</li><li>roundrect</li><li>rects</li><li>roundrects</li><li>freehandline | path</li><li>freehandlines | paths</li><li>clickfill: fill the clicked area with color<br>multiple areas may be selected <br>multiple colors may be provided using commands <a href='#colorpalette'>colorpalette color1,color2,color3,...</a> use <a href='#replyformat'>replyformat 10</a> for checking the user click color ... reply=x1:y1:color1,x2:y2:color2...<br>attention: this will <b>not</b> work for pattern filling, because the pattern image is only generated once and after creation can not be changed !<br>the opacity of this image on a separate canvas is set to 0.01 and not 0 (!!)...in the ''fill algorithm`` the opacity of the matching pixels is set to 1</li><li>dotfill: fill the clicked area with a dot pattern; use command linewidth to change dot size</li><li>diamondfill: fill the clicked area with a diamond pattern</li><li>hatchfill: fill the clicked area with a hatch pattern</li><li>gridfill: fill the clicked area with a grid pattern</li><li>textfill: fill the clicked area with a repeating string<br>userdraw textfill,blue,some_text<br>use command <a href="#fontfamily">fontfamily</a> to adjust text style and size</li><li>''clickfill | pattern filling`` in general:<br>the clicks may be set <a href="#snaptogrid">snaptogrid</a><br>can be used together with command <a href="#floodfill">floodfill or fill</a><br><b>always</b> use together with command <a href="#clearbutton">clearbutton some_text</a> for removal of all click_colored areas<br>the function read_canvas() will return the click coordinates in the sequence of the user clicks<br>use command <a href="#canvastype">canvastype</a> to fill another canvas (default should be fine: DRAG_CANVAS = 5)</li><li>text <br>an inputfield is provided, unicode allowed. The text is drawn a the mouse click, or if used with command ''userinput inputfield`` also at the given x/y-coordonates</li><li>arc</li><li>arcs</li><li>image<br>only a single "image" of every supported type(*) may be added to canvas window from the surrounding html page.<br>the image should have an 'id' and an onclick handler.<br>(*) supported types are ''svg``,''bitmap``,''p-element``,''div-element`` and ''mathml/tex-code`` with ''\\mmlid{int}``.</li><li>images</li><li>input<br>place a single inputfield on ''canvas`` <br>use commands 'css' for css styling: use command ''linewidth`` for adjusting the input field size (default 1)</li><li>inputs<br>place multiple inputfield: placing inputfields on top of each other is not possible</li><li>function : identical to <a href="#userinput">userinput function</a></li></ul> |
18552 | bpr | 4944 | @ note: mouselisteners are only active if ''$status != done`` (eg only drawing in an active/non-finished exercise) <br> to overrule use command/keyword ''status`` (no arguments required) |
4945 | @ note: object_type text: Any string or multiple strings may be placed anywhere on the canvas.<br>Use command ''fontfamily`` to set font |
||
4946 | @ note: object_type polygone: Will be finished (the object is closed) when clicked on the first point of the polygone again. |
||
4947 | @ note: all objects will be removed -after a javascript confirm box- when clicked on an object point with middle or right mouse button (e.g. event.button != 1: all buttons but left) |
||
18572 | bpr | 4948 | @ use a prefix <a href='#filled'>filled</a> or ''f`` to set fillable objects filled. (fcircles,filledcircles etc)<br> in case of ''fillpattern`` do not use the ''f`` prefix ! |
18552 | bpr | 4949 | @ for non solid filling, use command <a href="#fillpattern">fillpattern grid,hatch,diamond,dot</a> |
4950 | @ use <a href='#opacity'>opacity int,int</a> and <a href='#fillcolor'>fillcolor color</a> to trigger coloured filling of fillable objects |
||
4951 | @ use command ''dashed`` and/or ''dashtype int,int`` to trigger dashing |
||
4952 | @ use command ''replyformat int`` to control / adjust output formatting of javascript function read_canvas(); (the defaults should be fine...) |
||
4953 | @ may be combined with onclick or drag xy of other components of flyscript objects (although not very useful...) |
||
4954 | @ may be combined with keyword <a href='#userinput_xy'>userinput_xy</a> |
||
4955 | @ may be combined width the <a href='#snaptogrid'>snaptogrid snaptopoints </a> etc, to simplify the checking of the student reply |
||
4956 | @ the cursor may be appropriately styled using command <a href='cursor'>cursor</a> |
||
4957 | @ note: when zooming / panning after a drawing, the drawing will NOT be zoomed / panned...this is a "design" flaw and not a feature <br>To avoid trouble do not use zooming / panning together width userdraw.!<br>use command <a href="#multidraw">multidraw</a> is this is a problem for you... |
||
4958 | @ note: the default replyformat for ''userdraw input(s),color`` used format x1;y1;text1 \n x2;y2;test2 \n x_n;y_n;text_n (e.g. it is not a comma separated array...use ''direct exec`` to test) |
||
4959 | @ note: a special case is ''userdraw image,boguscolor``. Images (bitmap or svg or div) present in the exercise page and the img/svg/div-tag with an unique 'id' and <code>onclick='javascript:place_image_on_canvas(this.id)'</code> can be placed onto the canvas.<br>The ''id`` and (x;y) coordinates will be returned using read_canvas();<br> native MathML, MathJax or KaTeX typesetting may be included in div's.(experiments; wims_modules svn version only!) |
||
4960 | @ note: command <br><code>userdraw function,color</code> is identical to acombination of <code>strokecolor color</code> and <code>userinput function</code><br> |
||
18572 | bpr | 4961 | @ note: commands :<br><code>multicolors red,green,blue<br>multilabel f(x)=:g(x)=:h(x)=<br>userdraw functions3,color</code><br>is identical to commands :<br><code>functionlabel f(x)=:p(x)=:w(x)=<br>strokecolor red<br>userinput function <br>strokecolor green<br>userinput function <br>strokecolor blue<br>userinput function</code> |
18552 | bpr | 4962 | @%userdraw_canvastype_a%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%grid 2,2,grey%replyformat 10%colorpalette orange,yellow,red,green,lightgreen,blue,lightblue,cyan%canvastype 4%userdraw clickfill,blue%clearbutton REMOVE LAST RECTANGLE |
4963 | @%userdraw_canvastype_b%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%canvastype 4%snaptogrid%replyformat 10%userdraw dotfill,blue%clearbutton REMOVE LAST RECTANGLE |
||
4964 | @%userdraw_rect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw rect,green |
||
4965 | @%userdraw_rects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw rects,green |
||
4966 | @%userdraw_frect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw frect,green |
||
4967 | @%userdraw_frects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw frects,green |
||
4968 | @%userdraw_roundrect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw roundrect,green |
||
4969 | @%userdraw_roundrects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw roundrects,green |
||
4970 | @%userdraw_froundrect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw froundrect,green |
||
4971 | @%userdraw_froundrects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw froundrects,green |
||
4972 | @%userdraw_line%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw line,green |
||
4973 | @%userdraw_lines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw lines,green |
||
4974 | @%userdraw_vline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw vline,green |
||
4975 | @%userdraw_vlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw vlines,green |
||
4976 | @%userdraw_hline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw hline,green |
||
4977 | @%userdraw_hlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw hlines,green |
||
4978 | @%userdraw_demiline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw demiline,green |
||
4979 | @%userdraw_demilines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw demilines,green |
||
4980 | @%userdraw_arc%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw arc,green |
||
4981 | @%userdraw_arcs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw arcs,green |
||
4982 | @%userdraw_point%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw point,green |
||
4983 | @%userdraw_points%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw points,green |
||
4984 | @%userdraw_arrow%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrow,green |
||
4985 | @%userdraw_arrows%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrows,green |
||
4986 | @%userdraw_arrow2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrow2,green |
||
4987 | @%userdraw_arrows2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrows2,green |
||
4988 | @%userdraw_curvedarrow%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrow,red%clearbutton REMOVE ALL ARROWS |
||
4989 | @%userdraw_curvedarrows%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrows,red%clearbutton REMOVE ALL ARROWS |
||
4990 | @%userdraw_curvedarrow2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrow2,red%clearbutton REMOVE ALL ARROWS |
||
4991 | @%userdraw_curvedarrows2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrows2,red%clearbutton REMOVE ALL ARROWS |
||
4992 | @%userdraw_crosshair%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw crosshair,green |
||
4993 | @%userdraw_crosshairs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw crosshairs,green |
||
4994 | @%userdraw_circle%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw circle,green |
||
4995 | @%userdraw_circles%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw circles,green |
||
4996 | @%userdraw_segment%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw segment,green |
||
4997 | @%userdraw_segments%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw segments,green |
||
4998 | @%userdraw_line%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw line,green |
||
4999 | @%userdraw_lines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw lines,green |
||
5000 | @%userdraw_triangle%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw triangle,green |
||
5001 | @%userdraw_poly5%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw poly5,green |
||
5002 | @%userdraw_filled_poly5%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw poly5,green |
||
5003 | @%userdraw_poly7%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw poly7,green |
||
5004 | @%userdraw_filled_poly7%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw poly7,green |
||
5005 | @%userdraw_polyline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw polyline,green |
||
5006 | @%userdraw_freehandline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw freehandline,green |
||
5007 | @%userdraw_filled_freehandline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw freehandline,green |
||
5008 | @%userdraw_freehandlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw freehandlines,green |
||
5009 | @%userdraw_input%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%userdraw input,green |
||
5010 | @%userdraw_inputs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%userdraw inputs,green |
||
5011 | @%userdraw_text%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%fontfamily 42px Courier%userdraw text,green |
||
5012 | @%userdraw_function%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%multicolors orange,red,green,blue,cyan%precision 1000%userdraw functions3,red%jscurve blue,x^2,-x^2,5*cos(x)%precision 1%mouse red,22 |
||
5013 | @%userdraw_clickfill_colorpalette%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,4,1,1,6,3,3,3,-3,-3,5%opacity 255,120%colorpalette red,green,yellow,blue%userdraw clickfill,green |
||
5014 | @%userdraw_clickfill_1%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,4,1,1,6,3,3,3,-3,-3,5%opacity 255,120%userdraw clickfill,green |
||
18609 | bpr | 5015 | @%userdraw_clickfill_2%size 400,400%xrange -10,10%yrange -10,10%circles blue,0,0,2,1,1,5,5,5,4,-5,5,6,5,-5,6%userdraw hatchfill,red%#userdraw dotfill,red%#userdraw diamondfill,red%#userdraw gridfill,red |
18552 | bpr | 5016 | @%userdraw_clickfill_2%size 400,400%xrange -10,10%yrange -10,10%bgcolor white%# to get nice click coordinates take invisible ''grid`` and use ''snaptogrid`` %grid 1,1,white%snaptogrid%circles blue,0,0,2,1,1,5,5,5,4,-5,5,6,5,-5,6%userdraw gridfill,red |
5017 | */ |
||
5018 | if( use_userdraw != 0 ){ /* only one object type may be drawn*/ |
||
5019 | canvas_error("Only one userdraw primitive may be used in command 'userdraw' use command 'multidraw' for this..."); |
||
5020 | } |
||
5021 | js_function[INTERACTIVE] = 1; |
||
5022 | draw_type = get_string_argument(infile,0); |
||
5023 | if( strcmp(draw_type,"textfill") == 0){ |
||
5024 | fprintf(js_include_file,"var userdraw_text_string = \"%s\";", get_string(infile,1)); |
||
5025 | } |
||
5026 | else { |
||
5027 | if( strcmp(draw_type,"imagefill") == 0){ |
||
5028 | fprintf(js_include_file,"var userdraw_image_url = \"%s\";", get_string(infile,1)); |
||
5029 | } |
||
5030 | else { |
||
5031 | stroke_color = get_color(infile,1); |
||
5032 | } |
||
5033 | } |
||
5034 | if( strcmp(draw_type,"clickfill") == 0){use_filled = 1;fill_color = stroke_color;} |
||
5035 | reply_precision = precision; |
||
5036 | use_userdraw = 1; |
||
5037 | fprintf(js_include_file,"\n\ |
||
15111 | schaersvoo | 5038 | /* begin userdraw */\ |
5039 | userdraw_x = new Array();userdraw_y = new Array();userdraw_radius = new Array();\ |
||
5040 | var forbidden_zone=[xsize+1,ysize+1];var xy_cnt = 0;\ |
||
5041 | var canvas_userdraw = create_canvas%d(%d,xsize,ysize);\ |
||
5042 | var context_userdraw = canvas_userdraw.getContext(\"2d\");\ |
||
5043 | var use_dashed = %d;\ |
||
5044 | var use_snap = %d;if(use_dashed == 1){if( context_userdraw.setLineDash ){context_userdraw.setLineDash([%d,%d]);}else{if(context_userdraw.mozDash){context_userdraw.mozDash = [%d,%d];};};};\ |
||
5045 | context_userdraw.lineWidth = %d;var use_filled = %d;\ |
||
5046 | context_userdraw.strokeStyle = \"rgba(%s,%.2f)\";\ |
||
5047 | context_userdraw.font = \"%s\";\ |
||
15128 | schaersvoo | 5048 | var user_is_dragging = false;\ |
15111 | schaersvoo | 5049 | if(wims_status != \"done\"){\ |
5050 | canvas_div.addEventListener(\"mousedown\" ,user_draw,false);\ |
||
5051 | canvas_div.addEventListener(\"mousemove\" ,user_drag,false);\ |
||
5052 | canvas_div.addEventListener(\"touchstart\",function(e){ e.preventDefault();user_draw(e.changedTouches[0]);},false);\ |
||
5053 | canvas_div.addEventListener(\"touchmove\" ,function(e){ e.preventDefault();user_drag(e.changedTouches[0]);},false);\ |
||
15128 | schaersvoo | 5054 | canvas_div.addEventListener(\"touchend\" ,function(e){ e.preventDefault();user_drawstop(e.changedTouches[0]);},false);\ |
15111 | schaersvoo | 5055 | };",canvas_root_id,DRAW_CANVAS,use_dashed,use_snap,dashtype[0],dashtype[1],dashtype[0],dashtype[1],line_width,use_filled,stroke_color,stroke_opacity,font_family); |
5056 | |||
18552 | bpr | 5057 | if( use_filled == 0 ){ |
5058 | fprintf(js_include_file,"context_userdraw.fillStyle = \"rgba(255,255,255.0)\";"); |
||
5059 | } |
||
5060 | else { |
||
5061 | if( use_filled == 1 ){ |
||
5062 | fprintf(js_include_file,"context_userdraw.fillStyle = \"rgba(%s,%.2f)\";",fill_color,fill_opacity); |
||
5063 | } |
||
5064 | else { |
||
5065 | js_function[DRAW_FILL_PATTERN] = 1; |
||
5066 | fprintf(js_include_file,"context_userdraw.fillStyle = create_Pattern(0,0,%d,[%s]);\n",use_filled,fill_color); |
||
5067 | } |
||
5068 | } |
||
5069 | add_js_userdraw(draw_type,stroke_color,stroke_opacity,crosshair_size,arrow_head,use_offset,css_class,use_snap,canvas_type,use_filled,fill_color,fill_opacity,line_width,font_family); |
||
5070 | reset(); |
||
5071 | break; |
||
5072 | case USERINPUT: |
||
5073 | /* |
||
18556 | bpr | 5074 | @ userinput function inputfield |
5075 | @ alternative: userinput_function |
||
5076 | @ alternative: userinput_xy |
||
5077 | @ ''inputfield`` is only usable in combination with some ''userdraw draw_type`` |
||
5078 | @ note: the input fields are not cleared after the object is drawn...be aware of multiple idential drawings (many clicks on the ''ok`` button) |
||
5079 | @ ''userinput function`` may be used any time (e.g. without userdraw) |
||
5080 | @ multiple ''userinput function`` commands may be used. |
||
5081 | @ use command <code>functionlabel some_string</code> to define the inputfield text: default value "f(x)=" |
||
5082 | @ use command <code>strokecolor some_color</code> to adjust the plot / functionlabel color |
||
5083 | @ use command <code>css some_css</code> to adjust the inputfields |
||
5084 | @ use command <code>fontsize int</code> to adjust the label fonts. (default 12px) |
||
5085 | @ the user input for the function will be corrected by a simple ''rawmath`` implementation...<br>an error message will be shown if javascript can not interpret the user input |
||
5086 | @%userinput_function%size 400,400%xrange -10,10%yrange -10,10%functionlabel your function g(x)=%axis%axisnumbering%xlabel x-axis%ylabel y-axis%grid 2,2,grey,3,3,5,grey%css color:blue;text-align:center%userinput function%# note: number of function inputs not limited |
||
5087 | @%userinput_points%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%# adding 2 inputfields for x and y%userinput inputfield%userdraw points,blue |
||
5088 | @%userinput_arrows%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%#adding 4 inputfields for (x1;y1)---(x2;y2)%userinput inputfieldd%userdraw arrows,blue |
||
5089 | @%userinput_combined%size 400,400%xrange -10,10%yrange -10,10%functionlabel your function g(x)=%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 0%grid 2,2,grey,3,3,5,grey%css color:blue;text-align:center%precision 1000%strokecolor red%opacity 255,255%userinput function%# note: number of function inputs not limited%userdraw line,blue |
||
18552 | bpr | 5090 | */ |
5091 | temp = get_string_argument(infile,1); |
||
5092 | if(strstr(temp,"function") != 0 || strstr(temp,"curve") != 0 || strstr(temp,"plot") != 0 ){ |
||
5093 | if( js_function[DRAW_JSFUNCTION] != 1 ){ |
||
5094 | js_function[JS_RAWMATH] = 1; |
||
5095 | js_function[DRAW_JSFUNCTION] = 1; |
||
5096 | if(reply_format == 0){reply_format = 24;}/* read canvas_input values */ |
||
5097 | add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size); |
||
5098 | input_cnt++; |
||
5099 | } |
||
5100 | else { |
||
5101 | /* no need to add DRAW_JSFUNCTION, just call it with the parameters */ |
||
5102 | fprintf(js_include_file,"add_input_jsfunction(%d,\"%s\",%s,%d,\"%s\",\"%.2f\",%d,%d,%d,%d);\n",input_cnt,css_class,function_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],font_size); |
||
5103 | input_cnt++; |
||
5104 | } |
||
5105 | js_function[JS_MATH] = 1; |
||
5106 | js_function[JS_PLOT] = 1; |
||
5107 | } |
||
5108 | else { |
||
5109 | if(strstr(temp,"inputfield") != 0 ){ |
||
5110 | js_function[JS_SAFE_EVAL] = 1; |
||
5111 | js_function[ADD_USER_INPUTS] = 1; |
||
5112 | } |
||
5113 | else { |
||
5114 | canvas_error("userinput argument may be \"function\" or \"inputfield\""); |
||
5115 | } |
||
5116 | } |
||
5117 | break; |
||
5118 | case USERINPUT_XY: |
||
5119 | /* |
||
5120 | @ userinput_xy |
||
5121 | @ keyword (no arguments required) |
||
5122 | @ to be used in combination with command "userdraw object_type,color" |
||
5123 | @ if set two (or three) input fields are added to the document<br>(one for x-values, one for y-values and in case of drawing circle one for radius-values) |
||
5124 | @ the student may use this as correction for (x:y) on a drawing (or to draw without mouse, using just the coordinates) |
||
5125 | @ math input is allowed (e.g something like: 1+3,2*6,1/3,sqrt(3), sin(pi/4),10^-2,log(2)...)<br>eval function is ''protected`` against code injection. |
||
5126 | @ can <b>not</b> be combined with command ''intooltip tiptext`` <br>note: the ''tooltip div element`` is used for placing inputfields |
||
5127 | @ user drawings will not zoom on zooming (or pan on panning) |
||
5128 | @ use command ''css some_css`` to adjust the inputarea. |
||
5129 | @ use command ''fontsize int`` to adjust the text labels (if needed) |
||
5130 | @%userinput_xy%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 0%grid 2,2,grey,3,3,6,black%# provides inputfields for (x1:y1)---(x2:y2)%userinput_xy%linewidth 2%precision 1000%userdraw lines,blue |
||
5131 | */ |
||
5132 | /* add simple eval check to avoid code injection with unprotected eval(string) */ |
||
5133 | js_function[JS_SAFE_EVAL] = 1; |
||
5134 | js_function[ADD_USER_INPUTS] = 1; |
||
5135 | break; |
||
5136 | case USERINPUT_FUNCTION: |
||
5137 | /* |
||
5138 | @ userinput_function |
||
5139 | @ alternative: userinput |
||
5140 | @ keyword (no arguments required) |
||
5141 | @ if set, a inputfield will be added to the page |
||
5142 | @ repeat keyword for more function input fields |
||
5143 | @ the userinput value will be plotted in the canvas |
||
5144 | @ this value may be read with <code>read_canvas()</code>. <br>for do it yourself js-scripters: If this is the first inputfield in the script, its id is canvas_input0 |
||
5145 | @ use before this command ''userinput_function``,<br>commands like ''css some_css``, ''xlabel some_description``, ''opacity int,int``, ''linewidth int``, ''dashed`` and ''dashtype int,int`` to modify |
||
5146 | @ fontsize can be set using command ''fontsize int`` |
||
5147 | @ incompatible with command ''intooltip link_text_or_image``: it uses the tooltip div for adding the inputfield |
||
5148 | @%userinput_function%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 0%grid 2,2,grey,2,2,5,grey%precision 1000%linewidth 2%# first inputfield%css color:blue;text-align:center;font-family:Italic;%strokecolor blue%functionlabel g(x)=:p(x)=:k(x)=%userinput function%# second inputfield%css color:green;text-align:center;font-family:Italic;%strokecolor green%userinput function%# third inputfield%css color:purple;text-align:center;font-family:Italic;%strokecolor purple%userinput function%# no limit in number of function inputfields |
||
5149 | */ |
||
5150 | if( js_function[DRAW_JSFUNCTION] != 1 ){ |
||
5151 | js_function[DRAW_JSFUNCTION] = 1; |
||
5152 | js_function[JS_RAWMATH] = 1; |
||
5153 | if(reply_format == 0){reply_format = 24;}/* read canvas_input values */ |
||
5154 | add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size); |
||
5155 | input_cnt++; |
||
5156 | } |
||
5157 | else { |
||
5158 | /* no need to add DRAW_JSFUNCTION, just call it with the parameters */ |
||
5159 | fprintf(js_include_file,"add_input_jsfunction(%d,\"%s\",%s,%d,\"%s\",\"%.2f\",%d,%d,%d,%d);\n",input_cnt,css_class,function_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],font_size); |
||
5160 | input_cnt++; |
||
5161 | } |
||
5162 | js_function[JS_MATH] = 1; |
||
5163 | js_function[JS_PLOT] = 1; |
||
5164 | break; |
||
5165 | case VLINE: |
||
5166 | /* |
||
5167 | @ vline x,y,color |
||
5168 | @ alternative: verticalline |
||
5169 | @ draw a vertical line through point (x:y) in color 'color' |
||
5170 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
5171 | @%vline%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%vline 0,0,red%onclick%vline 1,0,orange%onclick%vline 2,0,blue%onclick%vline 3,0,green |
||
5172 | */ |
||
5173 | for(i=0;i<3;i++) { |
||
5174 | switch(i){ |
||
5175 | case 0: double_data[0] = get_real(infile,0);break; /* x-values */ |
||
5176 | case 1: double_data[1] = get_real(infile,0);break; /* y-values */ |
||
5177 | case 2: stroke_color=get_color(infile,1);/* name or hex color */ |
||
5178 | double_data[2] = double_data[0]; |
||
5179 | decimals = find_number_of_digits(precision); |
||
5180 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
18557 | bpr | 5181 | tmp_buffer=my_newmem(MAX_BUFFER); |
5182 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,100*ymin,decimals,100*ymax,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 5183 | add_to_buffer(tmp_buffer); |
5184 | if(onclick != 0){object_cnt++;} |
||
5185 | /* object_cnt++; */ |
||
5186 | reset(); |
||
5187 | break; |
||
5188 | } |
||
5189 | } |
||
5190 | dragstuff[4] = 1; |
||
5191 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5192 | break; |
||
5193 | case VLINES: |
||
5194 | /* |
||
5195 | @ vlines color,x1,y1,x2,y2.... |
||
5196 | @ alternative: verticallines |
||
5197 | @ draw vertical lines through points (x1:y1),(x2:y2)... in color 'color' |
||
5198 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually |
||
5199 | @%vlines%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%vlines red,1,0,2,0,3,0,4,0 |
||
5200 | */ |
||
5201 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5202 | fill_color = stroke_color; |
||
5203 | i=0; |
||
5204 | while( ! done ){ /* get next item until EOL*/ |
||
5205 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
5206 | if(i%2 == 0 ){ |
||
5207 | double_data[i] = get_real(infile,0); /* x */ |
||
5208 | } |
||
5209 | else { |
||
5210 | double_data[i] = get_real(infile,1); /* y */ |
||
5211 | } |
||
5212 | i++; |
||
5213 | } |
||
5214 | decimals = find_number_of_digits(precision); |
||
5215 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5216 | for(c = 0 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 5217 | tmp_buffer=my_newmem(MAX_BUFFER); |
18607 | bpr | 5218 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c],decimals,100*ymin,decimals,100*ymax,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
18552 | bpr | 5219 | add_to_buffer(tmp_buffer); |
5220 | if(onclick != 0){object_cnt++;} |
||
5221 | /* object_cnt++; */ |
||
5222 | } |
||
5223 | reset(); |
||
5224 | dragstuff[4] = 1; |
||
5225 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5226 | break; |
||
5227 | case VIDEO: |
||
5228 | /* |
||
5229 | @ video x,y,w,h,videofile location |
||
5230 | @ x,y: left top corner of audio element (in xrange / yrange) |
||
5231 | @ w,y: width and height in pixels |
||
5232 | @ video format may be in *.mp4 (todo: other formats) |
||
5233 | @%video%size 400,400%xrange -10,10%yrange -10,10%opacity 200,100%frect -9,9,6,-6,green%video -5,5,200,200,http://techslides.com/demos/sample-videos/small.mp4 |
||
5234 | */ |
||
5235 | js_function[DRAW_VIDEO] = 1; |
||
5236 | for(i=0;i<5;i++){ |
||
5237 | switch(i){ |
||
5238 | case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x in x/y-range coord system -> pixel */ |
||
5239 | case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y in x/y-range coord system -> pixel */ |
||
5240 | case 2: int_data[2] = (int) (get_real(infile,0)); break; /* pixel width */ |
||
5241 | case 3: int_data[3] = (int) (get_real(infile,0)); break; /* height pixel height */ |
||
5242 | case 4: temp = get_string(infile,1); |
||
18557 | bpr | 5243 | tmp_buffer=my_newmem(MAX_BUFFER); |
5244 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_video(%d,%d,%d,%d,%d,\"%s\");\n",canvas_root_id,int_data[0],int_data[1],int_data[2],int_data[3],temp)); |
||
18552 | bpr | 5245 | add_to_buffer(tmp_buffer); |
5246 | break; |
||
5247 | default:break; |
||
5248 | } |
||
5249 | } |
||
5250 | reset(); |
||
5251 | break; |
||
5252 | case X_AXIS_STRINGS: |
||
5253 | /* |
||
18556 | bpr | 5254 | @ xaxis num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n |
5255 | @ alternative: xaxistext |
||
5256 | @ usable for commands <a href="#numberline">numberline</a> and <a href="#grid">grid</a> or combinations thereof |
||
5257 | @ use these x-axis num1...num_n values instead of default xmin...xmax |
||
5258 | @ in case of command ''grid``. there is no need to use keyword <a href="#axisnumbering">axisnumbering</a> |
||
5259 | @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a> |
||
5260 | @ use command ''fontcolor``, ''fontfamily`` to adjust font <br>defaults: black,12,Arial<br>note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>) |
||
5261 | @ a javascript error message will flag non-matching value:name pairs |
||
5262 | @ if the ''x-axis words`` are too big and will overlap, a simple alternating offset will be applied |
||
5263 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
5264 | @ ''xmajor`` steps should be synchronised with numbers eg. ''1`` in the next example <code>grid 1,100,grey,1,4,6,grey</code> |
||
5265 | @%xaxistext%size 800,200%xrange -1,13%yrange -5,10%axis%xaxistext 1:january:2:february:3:march:4:april:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%grid 1,4,grey,1,2,10,red |
||
18552 | bpr | 5266 | */ |
5267 | use_axis_numbering++; |
||
5268 | temp = get_string(infile,1); |
||
5269 | if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");} |
||
5270 | if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/ |
||
5271 | fprintf(js_include_file,"x_strings[%d] = [\"%s\"];x_strings_up[%d] = null;",use_axis_numbering,temp,use_axis_numbering); |
||
5272 | break; |
||
5273 | case X_AXIS_STRINGS_UP: |
||
5274 | /* |
||
18556 | bpr | 5275 | @ xaxisup num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n |
5276 | @ alternative: xaxistextup |
||
5277 | @ the text will be rotated 90° up |
||
5278 | @ no need to use keyword <a href="#axisnumbering">axisnumbering</a> |
||
5279 | @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a> |
||
5280 | @ use these x-axis num1...num_n values instead of default xmin...xmax |
||
5281 | @ use command ''fontcolor``, <a href="#fontfamily">fontfamily</a> to adjust font <br>defaults: black,12,Arial<br>note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>) |
||
5282 | @ a javascript error message will flag non-matching value:name pairs |
||
5283 | @ if the ''x-axis words`` are too big, they will overlap the graph<br> (in this case the text will start from ysize upwards) |
||
5284 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
5285 | @''xmajor`` steps should be synchronised with numbers eg. "1" in the next example <code>grid 1,100,grey,1,4,6,grey</code> |
||
5286 | @%xaxistextup%size 800,300%xrange -1,13%yrange -10,10%fontfamily Italic 18pt Courier%axis%xaxistextup 1:january:2:february:3:march:4:april:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%grid 1,4,grey,1,2,10,red |
||
18552 | bpr | 5287 | */ |
5288 | use_axis_numbering++; |
||
5289 | temp = get_string(infile,1); |
||
5290 | if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");} |
||
5291 | if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/ |
||
5292 | fprintf(js_include_file,"x_strings_up[%d] = 1;x_strings[%d] = [\"%s\"];",use_axis_numbering,use_axis_numbering,temp); |
||
5293 | break; |
||
5294 | case XERRORBARS: |
||
5295 | /* |
||
5296 | @ xerrorbars color,E1,E2,x1,y1,x2,y2,...,x_n,y_n |
||
5297 | @ draw multiple points with x-errorbars E1 (error value left from point) and E2 (error value right from point) at given coordinates in color 'color' |
||
5298 | @ the errors E1 and E2 values are in xrange. |
||
5299 | @ use command ''linewidth int`` to adust size |
||
5300 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
5301 | @%xerrorbars%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%xerrorbars red,0.8,1.3,0,0,1,1,2,3,3,2,4,5,5,2,6,1,-1,-2,-2,0,-3,2,-4,4,-5,-1 |
||
8386 | schaersvoo | 5302 | |
18552 | bpr | 5303 | */ |
5304 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5305 | fill_color = stroke_color; |
||
5306 | i=0; |
||
5307 | while( ! done ){ /* get next item until EOL*/ |
||
5308 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
5309 | if(i%2 == 0 ){ |
||
5310 | double_data[i] = get_real(infile,0); /* x */ |
||
5311 | } |
||
5312 | else { |
||
5313 | double_data[i] = get_real(infile,1); /* y */ |
||
5314 | } |
||
5315 | i++; |
||
5316 | } |
||
5317 | decimals = find_number_of_digits(precision); |
||
5318 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5319 | for(c = 2 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 5320 | tmp_buffer=my_newmem(MAX_BUFFER); |
5321 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,20,[%.*f],[%.*f],[%.2f],[%.2f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[0],double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18552 | bpr | 5322 | add_to_buffer(tmp_buffer); |
5323 | /* object_cnt++; */ |
||
5324 | if(onclick != 0){object_cnt++;} |
||
5325 | } |
||
5326 | reset(); |
||
5327 | dragstuff[20] = 1; |
||
5328 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5329 | break; |
||
5330 | case NEWRANGE: |
||
5331 | /* |
||
5332 | @ newrange xmin,xmax,ymin,ymax |
||
5333 | @ objects defined after command will make use of this new range |
||
5334 | @ https://wimsedu.info/?topic=dessiner-des-portions-de-fonctions-sur-un-meme-graphe |
||
5335 | */ |
||
5336 | for(i = 0 ; i<4; i++){ |
||
5337 | switch(i){ |
||
5338 | case 0: xmin = get_real(infile,0);break; |
||
5339 | case 1: xmax = get_real(infile,0);break; |
||
5340 | case 2: ymin = get_real(infile,0);break; |
||
5341 | case 3: ymax = get_real(infile,1);break; |
||
5342 | default: break; |
||
5343 | } |
||
5344 | } |
||
18557 | bpr | 5345 | tmp_buffer=my_newmem(MAX_BUFFER); |
5346 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "\n\nxmin = %f;xmax = %f;ymin = %f;ymax = %f;\n\n",xmin,xmax,ymin,ymax)); |
||
18552 | bpr | 5347 | add_to_buffer(tmp_buffer); |
5348 | break; |
||
5349 | case XRANGE: |
||
5350 | /* |
||
5351 | @ xrange xmin,xmax |
||
5352 | @ alternative: rangex |
||
5353 | @ if not given: 0,xsize (eg in pixels) |
||
5354 | */ |
||
18556 | bpr | 5355 | for(i = 0 ; i<2; i++){ |
5356 | switch(i){ |
||
5357 | case 0: xmin = get_real(infile,0);break; |
||
5358 | case 1: xmax = get_real(infile,1);break; |
||
5359 | default: break; |
||
5360 | } |
||
5361 | } |
||
5362 | if(xmin >= xmax){canvas_error(" xrange is not OK: xmin < xmax !");} |
||
5363 | fprintf(js_include_file,"var xmin = %f;var xmax = %f;",xmin,xmax); |
||
5364 | found_size_command++; |
||
5365 | break; |
||
18552 | bpr | 5366 | case XSNAPTOGRID: |
5367 | /* |
||
18556 | bpr | 5368 | @ xsnaptogrid |
5369 | @ keyword (no arguments required) |
||
5370 | @ a draggable object (use command ''drag x|y|xy``) will snap to the given x-grid values when dragged (mouseup) |
||
5371 | @ in case of userdraw the drawn points will snap to xmajor grid |
||
5372 | @ if no grid is defined, points will snap to every integer xrange value. (eg snap_x=1) |
||
5373 | @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0. |
||
5374 | @ if xminor is defined (use keyword ''axis`` to activate xminor), the drawing will snap to xminor <br>use only even dividers in x-minor...for example<br><code>xsnaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code><br> will snap on x=0, x=0.5, x=1, x=1.5 ....<br> will snap on y=0, y=0.25 y=0.5 y=0.75 ...<br> |
||
5375 | @%xsnaptogrid_1%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%xsnaptogrid%userdraw segments,red%precision 1%display x,red,12 |
||
5376 | @%xsnaptogrid_2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%drag x%points red,0,0,0,0,0,0,0,0,0,0 |
||
5377 | */ |
||
5378 | use_snap = 2; |
||
5379 | break; |
||
18552 | bpr | 5380 | case XOFFSET: |
5381 | /* |
||
18556 | bpr | 5382 | @ xoffset |
5383 | @ keyword ; to place the text centered above the text coordinates(x:y) ... |
||
5384 | @ may be used for points or other things requiring centered labels |
||
5385 | @ use <a href="#fontfamily">fontfamily</a> for setting the font |
||
5386 | @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-library) |
||
18552 | bpr | 5387 | @%xoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red |
5388 | */ |
||
18556 | bpr | 5389 | use_offset = 2; |
5390 | break; |
||
18552 | bpr | 5391 | case XYOFFSET: |
5392 | /* |
||
18556 | bpr | 5393 | @ xyoffset |
5394 | @ keyword ; to place the text (x:y) to (x+dx:y+dy)... dx/dy are dependent on fontsize/fontfamily |
||
5395 | @ may be used for points or other things requiring labels |
||
5396 | @ use <a href="#fontfamily">fontfamily</a> for setting the font |
||
5397 | @ only active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-librariy |
||
5398 | @ in case of inputfields the inputfield will be centered x and y on its coordinates.<br>for example:<br>inputs 1,1,10,? <br>point 1,1,red <br> the point will be completely invisible<br>note: keyword ''xyoffset`` will also provide centering if used with <a href='#userdraw'>input(s),color</a> |
||
5399 | @%xyoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red |
||
18552 | bpr | 5400 | */ |
18556 | bpr | 5401 | use_offset = 3; |
5402 | break; |
||
18552 | bpr | 5403 | case XUNIT: |
5404 | /* |
||
18556 | bpr | 5405 | @ xunit some_unit_for_x-values |
5406 | @ unicode allowed (no html code) |
||
5407 | @ use together with command <a href="#display">display or mouse</a> |
||
5408 | @ will display the cursor x-coordinate in ''unit`` |
||
5409 | @%xunit%size 400,400%xrange -10,10%yrange -10,10%xunit cm \\u00B2%grid 2,2,grey%linewidth 2%userdraw segments,blue%display x,blue,18 |
||
18552 | bpr | 5410 | */ |
18556 | bpr | 5411 | fprintf(js_include_file,"unit_x = \"%s\";",get_string(infile,1)); |
5412 | break; |
||
18552 | bpr | 5413 | case XLABEL: |
5414 | /* |
||
5415 | @ xlabel some_string |
||
5416 | @ will be used to create a label for the x-axis (label is in quadrant I) |
||
5417 | @ can only be used together with command ''grid``<br>not depending on keywords ''axis`` and ''axisnumbering`` |
||
5418 | @ font setting: italic Courier, fontsize will be slightly larger (fontsize + 4)<br>use command ''fontsize`` to adjust.<br>(command ''fontfamily`` is not active for this command) |
||
5419 | @ use <a href="#ylabel">ylabel</a> |
||
5420 | @%xlabel%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel cm\\u00B2 %ylabel v\\u00B2 %precision 1%grid 2,2,grey,2,2,5,grey |
||
5421 | */ |
||
18556 | bpr | 5422 | temp = get_string(infile,1); |
5423 | fprintf(js_include_file,"var xaxislabel = \"%s\";",temp); |
||
5424 | break; |
||
18552 | bpr | 5425 | case XLOGBASE: |
5426 | /* |
||
5427 | @ xlogbase number |
||
5428 | @ sets the logbase number for the x-axis |
||
5429 | @ default value 10 |
||
5430 | @ use together with commands xlogscale / xylogscale |
||
5431 | */ |
||
18556 | bpr | 5432 | fprintf(js_include_file,"xlogbase=%d;",(int)(get_real(infile,1))); |
5433 | break; |
||
18552 | bpr | 5434 | case XLOGSCALE: |
5435 | /* |
||
18556 | bpr | 5436 | @ xlogscale ymajor,yminor,majorcolor,minorcolor |
5437 | @ the x/y-range are set using commands <code>xrange xmin,xmax</code> and <code>yrange ymin,ymax</code> |
||
5438 | @ ymajor is the major step on the y-axis; yminor is the divisor for the y-step |
||
5439 | @ the linewidth is set using command ''linewidth int`` |
||
5440 | @ the opacity of major / minor grid lines is set by command <a href='#opacity'>opacity</a> |
||
5441 | @ default logbase number = 10 ... when needed, set the logbase number with command ''xlogbase number`` |
||
5442 | @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use command ''precision`` before ''xlogscale`` command to set the precision (decimals) of the axis numbering</li><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the colour</li></ul> |
||
5443 | @ note: the complete canvas will be used for the ''log paper`` |
||
5444 | @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values |
||
5445 | @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\ |
||
5446 | @ note: when using something like ''xrange 0.0001,0.01``...combined with commands <a href='#mouse'>mouse</a> and/or <a href='#userdraw'>userdraw</a>...<br> make sure the <a href='#precision'>precision</a> is set accordingly |
||
5447 | @ note: in case of userdraw, the use of keyword <a href='#userinput_xy'>userinput_xy</a> may be handy ! |
||
5448 | @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result... |
||
5449 | @ <b>attention</b>: do not use command ''zoom`` |
||
5450 | @%xlogscale%size 400,400%xrange 10,50000%yrange -5,5%xlabel x-axis%ylabel y-axis%xlogscale 10,1,black,grey%display x,red,22 |
||
18552 | bpr | 5451 | */ |
18556 | bpr | 5452 | use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;} |
5453 | if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");} |
||
5454 | js_function[DRAW_XLOGSCALE] = 1; |
||
5455 | for(i=0;i<4;i++){ |
||
5456 | switch(i){ |
||
5457 | case 0: double_data[0] = get_real(infile,0);break; /* xmajor */ |
||
5458 | case 1: int_data[0] = (int) (get_real(infile,0));break; /* xminor */ |
||
5459 | case 2: stroke_color = get_color(infile,0); break; |
||
5460 | case 3: fill_color = get_color(infile,1); |
||
18557 | bpr | 5461 | tmp_buffer=my_newmem(MAX_BUFFER); |
5462 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%f,%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,double_data[0],int_data[0],precision)); |
||
18556 | bpr | 5463 | fprintf(js_include_file,"use_xlogscale=1;snap_y = %f;snap_x = xlogbase;",double_data[0]/int_data[0]); |
5464 | add_to_buffer(tmp_buffer); |
||
5465 | break; |
||
5466 | default:break; |
||
5467 | } |
||
5468 | } |
||
5469 | break; |
||
18552 | bpr | 5470 | case XYLOGSCALE: |
5471 | /* |
||
18556 | bpr | 5472 | @ xylogscale majorcolor,minorcolor |
5473 | @ the x/y-range are set using commands ''xrange xmin,xmax`` and ''yrange ymin,ymax`` |
||
5474 | @ the linewidth is set using command ''linewidth int`` |
||
5475 | @ the opacity of major / minor grid lines is set by command ''opacity [0-255],[0-255]`` |
||
5476 | @ default logbase number = 10 ... when needed, set the logbase number with command ''xlogbase number`` and/or ''ylogbase number`` |
||
5477 | @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the colour</li></ul> |
||
5478 | @ note: the complete canvas will be used for the ''log paper`` |
||
5479 | @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values |
||
5480 | @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\ |
||
5481 | @ note: when using something like ''yrange 0.0001,0.01``...combined with commands ''mouse color,fontsize`` and/or ''userdraw type,color``...<br> make sure the precision is set accordingly (eg command ''precision 10000``) |
||
5482 | @ note: in case of userdraw, the use of keyword ''userinput_xy`` may be handy ! |
||
5483 | @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result... |
||
5484 | @ <b>attention</b>: do not use command ''zoom`` |
||
5485 | @%xylogscale%size 400,400%xrange 10,50000%yrange 10,50000%xlabel x-axis%ylabel y-axis%xylogscale black,grey%display xy,red,22 |
||
18552 | bpr | 5486 | */ |
18556 | bpr | 5487 | use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;} |
5488 | if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");} |
||
5489 | js_function[DRAW_XYLOGSCALE] = 1; |
||
5490 | for(i=0;i<2;i++){ |
||
5491 | switch(i){ |
||
5492 | case 0: stroke_color = get_color(infile,0); break; |
||
5493 | case 1: fill_color = get_color(infile,1); |
||
18557 | bpr | 5494 | tmp_buffer=my_newmem(MAX_BUFFER); |
5495 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,precision)); |
||
18556 | bpr | 5496 | fprintf(js_include_file,"use_xlogscale=1;use_ylogscale=1;snap_x = xlogbase;snap_y = ylogbase;"); |
5497 | add_to_buffer(tmp_buffer); |
||
5498 | break; |
||
5499 | default:break; |
||
5500 | } |
||
5501 | } |
||
5502 | break; |
||
18552 | bpr | 5503 | case Y_AXIS_STRINGS: |
5504 | /* |
||
18556 | bpr | 5505 | @ yaxis num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n |
5506 | @ alternative: yaxistext |
||
5507 | @ use command ''fontcolor``, ''fontfamily`` to adjust font <br>defaults: black,12,Arial<br> note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>) |
||
5508 | @ no need to use keyword <a href="#axisnumbering">axisnumbering</a> |
||
5509 | @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a> |
||
5510 | @ use these y-axis num1...num_n values instead of default ymin...ymax |
||
5511 | @ a javascript error message will flag non-matching value:name pairs |
||
5512 | @ to be used before command grid (see <a href="#grid">command grid</a>) |
||
5513 | @%yaxistext%size 400,400%yrange 0,13%xrange -100,500%axis%yaxis 1:january:2:february:3:march:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%#'ymajor' steps should be synchronised with numbers eg. "1" in this example%grid 100,1,grey,4,1,6,grey |
||
18552 | bpr | 5514 | */ |
18556 | bpr | 5515 | temp = get_string(infile,1); |
5516 | if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");} |
||
5517 | if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/ |
||
5518 | fprintf(js_include_file,"y_strings = [\"%s\"];\n ",temp); |
||
5519 | use_axis_numbering++; |
||
5520 | break; |
||
18552 | bpr | 5521 | case YERRORBARS: |
5522 | /* |
||
5523 | @ yerrorbars color,E1,E2,x1,y1,x2,y2,...,x_n,y_n |
||
5524 | @ draw multiple points with y-errorbars E1 (error value under point) and E2 (error value above point) at given coordinates in color 'color' |
||
5525 | @ the errors E1 and E2 values are in yrange. |
||
5526 | @ use command ''linewidth int`` to adust size |
||
5527 | @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
5528 | @%yerrorbars%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%yerrorbars red,0.8,1.3,0,0,1,1,2,3,3,2,4,5,5,2,6,1,-1,-2,-2,0,-3,2,-4,4,-5,-1 |
||
5529 | */ |
||
5530 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5531 | fill_color = stroke_color; |
||
5532 | i=0; |
||
5533 | while( ! done ){ /* get next item until EOL*/ |
||
18556 | bpr | 5534 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
5535 | if(i%2 == 0 ){ |
||
5536 | double_data[i] = get_real(infile,0); /* x */ |
||
5537 | } |
||
5538 | else |
||
5539 | { |
||
5540 | double_data[i] = get_real(infile,1); /* y */ |
||
5541 | } |
||
5542 | i++; |
||
18552 | bpr | 5543 | } |
5544 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5545 | for(c = 2 ; c < i-1 ; c = c+2){ |
||
18557 | bpr | 5546 | tmp_buffer=my_newmem(MAX_BUFFER); |
5547 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,19,[%.*f],[%.*f],[%.2f],[%.2f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[0],double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
18556 | bpr | 5548 | add_to_buffer(tmp_buffer); |
18552 | bpr | 5549 | /* object_cnt++; */ |
18556 | bpr | 5550 | if(onclick != 0){object_cnt++;} |
18552 | bpr | 5551 | } |
5552 | decimals = find_number_of_digits(precision); |
||
5553 | reset(); |
||
5554 | dragstuff[19] = 1; |
||
5555 | if(use_dragstuff == 0 ){ use_dragstuff = 1;} |
||
5556 | break; |
||
5557 | case YOFFSET: |
||
5558 | /* |
||
18556 | bpr | 5559 | @ yoffset |
5560 | @ keyword; to place the text centered above the text coordinates(x:y) ... |
||
5561 | @ may be used for points or other things requiring centered labels |
||
5562 | @ use <a href="#fontfamily">fontfamily</a> for setting the font |
||
5563 | @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-library) |
||
5564 | @%yoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red |
||
18552 | bpr | 5565 | */ |
18556 | bpr | 5566 | use_offset = 1; |
5567 | break; |
||
18552 | bpr | 5568 | case YRANGE: |
5569 | /* |
||
5570 | @ yrange ymin,ymax |
||
5571 | @ alternative: rangey |
||
5572 | @ if not given 0,ysize (eg in pixels) |
||
5573 | */ |
||
18556 | bpr | 5574 | for(i = 0 ; i<2; i++){ |
5575 | switch(i){ |
||
5576 | case 0: ymin = get_real(infile,0);break; |
||
5577 | case 1: ymax = get_real(infile,1);break; |
||
5578 | default: break; |
||
5579 | } |
||
5580 | } |
||
5581 | if(ymin >= ymax){canvas_error(" yrange is not OK: ymin < ymax !<br>");} |
||
5582 | fprintf(js_include_file,"var ymin = %f;var ymax = %f;",ymin,ymax); |
||
5583 | found_size_command++; |
||
5584 | break; |
||
18552 | bpr | 5585 | case YSNAPTOGRID: |
5586 | /* |
||
18556 | bpr | 5587 | @ ysnaptogrid |
5588 | @ keyword (no arguments required) |
||
5589 | @ a draggable object (use command ''drag x|y|xy``) will snap to the given y-grid values when dragged (mouseup) |
||
5590 | @ in case of userdraw the drawn points will snap to ymajor grid |
||
5591 | @ if no grid is defined, points will snap to every integer yrange value. (eg snap_y=1) |
||
5592 | @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0. |
||
5593 | @ if yminor is defined (use keyword ''axis`` to activate yminor), the drawing will snap to yminor <br>use only even dividers in y-minor...for example<br><code>ysnaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code><br> will snap on x=0, x=0.5, x=1, x=1.5 ....<br> will snap on y=0, y=0.25 y=0.5 y=0.75 ...<br> |
||
5594 | @%ysnaptogrid_1%size 400,400%xrange -10,10%yrange -10,10%ysnaptogrid%grid 1,1,grey%linewidth 2%userdraw crosshairs,blue%css font-size:8px;color:blue%clearbutton delete all crosshairs |
||
5595 | @%ysnaptogrid_2%size 400,400%xrange -10,10%yrange -10,10%ysnaptogrid%grid 1,1,grey%linewidth 3%drag y%points red,0,0,0,0,0,0,0,0,0,0 |
||
18552 | bpr | 5596 | */ |
18556 | bpr | 5597 | use_snap = 3; |
5598 | break; |
||
18552 | bpr | 5599 | case YLABEL: |
5600 | /* |
||
5601 | @ ylabel some_string |
||
5602 | @ will be used to create a (vertical) label for the y-axis (label is in quadrant I) |
||
5603 | @ can only be used together with command <a href="#grid">grid</a><br>not depending on keywords ''axis`` and ''axisnumbering`` |
||
5604 | @ font setting: italic Courier, fontsize will be slightly larger (fontsize + 4)<br>use command ''fontsize`` to adjust (command ''fontsize`` is not active for this command) |
||
5605 | @ use <a href="#xlabel">xlabel</a> |
||
5606 | @%ylabel%size 400,400%xrange -10,10%yrange -10,10%fontsize 8%axis%axisnumbering%precision 1%xlabel x-axis%ylabel y-axis%grid 1,1,grey,2,2,2,red |
||
5607 | */ |
||
18556 | bpr | 5608 | temp = get_string(infile,1); |
5609 | fprintf(js_include_file,"var yaxislabel = \"%s\";",temp); |
||
5610 | break; |
||
18552 | bpr | 5611 | case YLOGBASE: |
5612 | /* |
||
5613 | @ ylogbase number |
||
5614 | @ sets the logbase number for the y-axis |
||
5615 | @ default value 10 |
||
5616 | @ use together with commands ylogscale / xylogscale |
||
5617 | */ |
||
5618 | fprintf(js_include_file,"ylogbase=%d;",(int)(get_real(infile,1))); |
||
5619 | break; |
||
5620 | case YLOGSCALE: |
||
5621 | /* |
||
18556 | bpr | 5622 | @ ylogscale xmajor,xminor,majorcolor,minorcolor |
5623 | @ the x/y-range are set using commands ''xrange xmin,xmax`` and ''yrange ymin,ymax`` |
||
5624 | @ xmajor is the major step on the x-axis; xminor is the divisor for the x-step |
||
5625 | @ the linewidth is set using command ''linewidth int`` |
||
5626 | @ the opacity of major / minor grid lines is set by command ''opacity [0-255],[0-255]`` |
||
5627 | @ default logbase number = 10 ... when needed, set the logbase number with command ''ylogbase number`` |
||
5628 | @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use command ''precision`` before ''ylogscale`` command to set the precision (decimals) of the axis numbering</li><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the color</li></ul> |
||
5629 | @ note: the complete canvas will be used for the ''log paper`` |
||
5630 | @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values |
||
5631 | @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\ |
||
5632 | @ note: when using something like ''yrange 0.0001,0.01``...combined with commands ''mouse color,fontsize`` and/or ''userdraw type,color``...<br> make sure the precision is set accordingly (eg command ''precision 10000``) |
||
5633 | @ note: in case of userdraw, the use of keyword ''userinput_xy`` may be handy ! |
||
5634 | @ <b>attention</b>: do not use command ''zoom`` |
||
5635 | @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result... |
||
18552 | bpr | 5636 | */ |
18555 | bpr | 5637 | use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;} |
5638 | if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");} |
||
5639 | js_function[DRAW_YLOGSCALE] = 1; |
||
5640 | for(i=0;i<4;i++){ |
||
5641 | switch(i){ |
||
5642 | case 0: double_data[0] = get_real(infile,0);break; /* xmajor */ |
||
5643 | case 1: int_data[0] = (int) (get_real(infile,0));break; /* xminor */ |
||
5644 | case 2: stroke_color = get_color(infile,0); break; |
||
5645 | case 3: fill_color = get_color(infile,1); |
||
18557 | bpr | 5646 | tmp_buffer=my_newmem(MAX_BUFFER); |
5647 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%f,%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,double_data[0],int_data[0],precision)); |
||
18555 | bpr | 5648 | fprintf(js_include_file,"use_ylogscale=1;snap_x = %f;snap_y = ylogbase;",double_data[0]/int_data[0]); |
5649 | add_to_buffer(tmp_buffer); |
||
5650 | break; |
||
5651 | default:break; |
||
5652 | } |
||
5653 | } |
||
5654 | break; |
||
18552 | bpr | 5655 | case YUNIT: |
5656 | /* |
||
18556 | bpr | 5657 | @ yunit some_unit_for_y-values |
5658 | @ unicode allowed (no html code) |
||
5659 | @ use together with command mousey |
||
5660 | @ will display the cursor y-coordinate in ''unit`` |
||
18552 | bpr | 5661 | */ |
5662 | fprintf(js_include_file,"unit_y = \"%s\";",get_string(infile,1)); |
||
5663 | break; |
||
18555 | bpr | 5664 | case HYPSEGMENTS: |
18556 | bpr | 5665 | /* |
5666 | @ hypsegments color,x1,y1,x2,y2,...,x_n,y_n |
||
5667 | @ draw multiple hyperbolic segments in the Poincaré disk between points (x1:y1)--(x2:y2).....and... (x_n-1:y_n-1)--(x_n:y_n) in color ''color`` |
||
5668 | @ use command ''linewidth int`` to adjust size |
||
5669 | may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!) |
||
5670 | @%hypsegments%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%linewidth 2%hypsegments green,0.1,-0.3,0.6,0.7,0.3,0,-0.8,0.6,0.6,0.5,-0.5,0.6 |
||
5671 | segments_onclick%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1 |
||
5672 | segments_drag_y%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag y%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1 |
||
5673 | */ |
||
18555 | bpr | 5674 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
5675 | fill_color = stroke_color; |
||
5676 | i=0; |
||
5677 | while( ! done ){ /* get next item until EOL*/ |
||
5678 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
5679 | if(i%2 == 0 ){ |
||
5680 | double_data[i] = get_real(infile,0); /* x */ |
||
5681 | } |
||
5682 | else { |
||
5683 | double_data[i] = get_real(infile,1); /* y */ |
||
5684 | } |
||
5685 | i++; |
||
5686 | } |
||
5687 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
5688 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
5689 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5690 | decimals = find_number_of_digits(precision); |
||
5691 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18569 | bpr | 5692 | tmp_buffer=my_newmem(MAX_BUFFER); |
18555 | bpr | 5693 | if (hypgeodaux(double_data+c,res,0)){ |
5694 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5695 | } |
||
5696 | else { |
||
5697 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5698 | } |
||
5699 | add_to_buffer(tmp_buffer); |
||
5700 | if(onclick != 0){object_cnt++;} |
||
5701 | } |
||
5702 | reset(); |
||
5703 | dragstuff[4] = 1;dragstuff[12] = 1; |
||
5704 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5705 | break; |
||
5706 | case HYPLINES: |
||
5707 | /* |
||
5708 | @ hyplines color,x1,y1,x2,y2...x_n-1,y_n-1,x_n,y_n |
||
5709 | @ draw multiple hyperbolic lines in the Poincaré disk through points (x1:y1)--(x2:y2) ...(x_n-1:y_n-1)--(x_n:y_n) in color 'color' |
||
5710 | may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> |
||
5711 | @%hyplines%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%hyplines green,0,0.1,0.1,0.3,0.2,0.3,0.1,0.3,0,0.5,-0.5,0.4 |
||
5712 | */ |
||
5713 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5714 | fill_color = stroke_color; |
||
5715 | i=0; |
||
5716 | while( ! done ){ /* get next item until EOL*/ |
||
5717 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
18562 | bpr | 5718 | if(i%2 == 0 ){ |
5719 | double_data[i] = get_real(infile,0); /* x */ |
||
5720 | } |
||
18555 | bpr | 5721 | else { |
5722 | double_data[i] = get_real(infile,1); /* y */ |
||
5723 | } |
||
5724 | i++; |
||
5725 | } |
||
5726 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
5727 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
5728 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5729 | decimals = find_number_of_digits(precision); |
||
5730 | for(c = 0 ; c < i-1 ; c = c+4){ |
||
18569 | bpr | 5731 | tmp_buffer=my_newmem(MAX_BUFFER); |
18555 | bpr | 5732 | if (hypgeodaux(double_data+c,res,1)){ |
5733 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));} |
||
5734 | else { |
||
5735 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[2],decimals,res[1],decimals,res[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5736 | } |
||
5737 | add_to_buffer(tmp_buffer); |
||
5738 | if(onclick != 0){object_cnt++;} |
||
5739 | } |
||
5740 | reset(); |
||
5741 | dragstuff[4] = 1;dragstuff[12] = 1; |
||
5742 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5743 | break; |
||
5744 | case HYPPOLY: |
||
5745 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5746 | fill_color = stroke_color; |
||
5747 | i=0; |
||
5748 | while( ! done ){ /* get next item until EOL*/ |
||
5749 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
||
5750 | if(i%2 == 0 ){ |
||
5751 | double_data[i] = get_real(infile,0); /* x */ |
||
5752 | } |
||
5753 | else { |
||
5754 | double_data[i] = get_real(infile,1); /* y */ |
||
5755 | } |
||
5756 | i++; |
||
5757 | } |
||
5758 | /* il faut rajouter le premier point à la fin*/ |
||
5759 | double_data[i]=double_data[0]; double_data[i+1]=double_data[1]; |
||
5760 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
5761 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
5762 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5763 | decimals = find_number_of_digits(precision); |
||
5764 | for(c = 0 ; c < i-1 ; c = c+2){ |
||
18606 | bpr | 5765 | tmp_buffer=my_newmem(MAX_BUFFER); |
18555 | bpr | 5766 | if (hypgeodaux(double_data+c,res,0)){ |
5767 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5768 | } |
||
5769 | else { |
||
5770 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5771 | } |
||
5772 | add_to_buffer(tmp_buffer); |
||
5773 | if(onclick != 0){object_cnt++;} |
||
18606 | bpr | 5774 | } |
18569 | bpr | 5775 | dragstuff[4] = 1; dragstuff[12] = 1; |
18555 | bpr | 5776 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
5777 | reset(); |
||
5778 | break; |
||
5779 | case HYPRAYS: |
||
5780 | /* |
||
18556 | bpr | 5781 | @ hyprays color,xc,yc,x1,y1,x2,y2,x3,y3...x_n,y_n |
5782 | @ draw hyperbolic rays in the Poincaré disk in color 'color' and center (xc:yc) |
||
18555 | bpr | 5783 | may be set draggable or onclick (every individual ray) |
18556 | bpr | 5784 | @%hyprays%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%onclick%hyprays blue,0.5,0.5,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9 |
18555 | bpr | 5785 | hyprays_onclick%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%onclick%hyprays blue,0.5,0.5,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9 |
5786 | hyprays_drag_xy%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%drag xy%hyprays blue,0,0,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9 |
||
5787 | */ |
||
5788 | stroke_color=get_color(infile,0); |
||
5789 | fill_color = stroke_color; |
||
5790 | double_data[0] = get_real(infile,0);/* xc */ |
||
5791 | double_data[1] = get_real(infile,0);/* yc */ |
||
5792 | i=2; |
||
18562 | bpr | 5793 | while( ! done ){ /* get next item until EOL*/ |
18555 | bpr | 5794 | if(i > MAX_INT - 1){canvas_error("in command rays too many points / rays in argument: repeat command multiple times to fit");} |
5795 | if(i%2 == 0 ){ |
||
5796 | double_data[i] = get_real(infile,0); /* x */ |
||
5797 | } |
||
5798 | else { |
||
5799 | double_data[i] = get_real(infile,1); /* y */ |
||
5800 | } |
||
5801 | fprintf(js_include_file,"/* double_data[%d] = %f */\n",i,double_data[i]); |
||
5802 | i++; |
||
5803 | } |
||
5804 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);} |
||
5805 | if(use_affine == TRUE ){ transform(i-1,2);} |
||
5806 | if( i%2 != 0 ){canvas_error("in command rays: unpaired x or y value");} |
||
5807 | decimals = find_number_of_digits(precision); |
||
5808 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5809 | for(c=2; c<i;c = c+2){ |
||
18557 | bpr | 5810 | tmp_buffer=my_newmem(MAX_BUFFER); |
18555 | bpr | 5811 | double_data[2]=double_data[c];double_data[3]=double_data[c+1]; |
5812 | if (hypgeodaux(double_data,res,0)){ |
||
5813 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5814 | } |
||
5815 | else { |
||
5816 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[c],decimals,double_data[1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
||
5817 | } |
||
5818 | add_to_buffer(tmp_buffer); |
||
5819 | /* object_cnt++; */ |
||
5820 | if(onclick != 0){object_cnt++;} |
||
5821 | } |
||
5822 | reset(); |
||
5823 | dragstuff[4] = 1; dragstuff[12] = 1; |
||
5824 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5825 | break; |
||
5826 | case HYPCIRCLES: |
||
5827 | /* |
||
5828 | @ hypcircles color,xc1,yc1,r1,xc2,yc2,r2...xc_n,yc_n,r_n |
||
5829 | @ draw hyperbolic circles in Poincaré disk |
||
5830 | @ <b>attention</b> r = radius in x-range (!) |
||
5831 | @ use keyword <code>filled</code> or command <code>fhypcircles</code> to produce solid circles |
||
5832 | @ use command <code>fillcolor color</code> to set the fillcolor |
||
5833 | @%hypcircles%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%hypcircles blue,0,0,1,0.4,0.4,3,0.2,0.6,6 |
||
5834 | hypcircles_drag%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%drag xy%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5%zoom red |
||
5835 | hypcircles_onclick%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%onclick%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5%zoom red |
||
5836 | hypcircles_drag_slider%size 400,400%xrange -1,1%yrange -1,1%linewidth 2%drag xy%# Click circles(s) to activate%opacity 200,50%fillcolor orange%rotationcenter 2,3%slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5 |
||
5837 | */ |
||
5838 | stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/ |
||
5839 | fill_color = stroke_color; |
||
5840 | i=1; |
||
18562 | bpr | 5841 | while( ! done ){ /* get next item until EOL*/ |
18555 | bpr | 5842 | if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");} |
5843 | switch (i%3){ |
||
5844 | case 1:double_data[i-1] = get_real(infile,0);break; /* x */ |
||
5845 | case 2:double_data[i-1] = get_real(infile,0);break; /* y */ |
||
5846 | case 0:double_data[i-1] = get_real(infile,1);break; /* r */ |
||
5847 | } |
||
5848 | i++; |
||
5849 | } |
||
5850 | if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,3);} |
||
5851 | if(use_affine == TRUE ){ transform(i-1,3);} |
||
5852 | if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */ |
||
5853 | decimals = find_number_of_digits(precision); |
||
5854 | for(c = 0 ; c < i-1 ; c = c+3){ |
||
18556 | bpr | 5855 | double Z2=double_data[c]*double_data[c]+double_data[c+1]*double_data[c+1];//[Z]^2 |
18555 | bpr | 5856 | double R=tanh(double_data[c+2]/2);double R2=R*R; |
5857 | double den=1-R2*Z2; double XY=(1-R2)/den; |
||
5858 | double_data[c]=XY*double_data[c]; |
||
5859 | double_data[c+1]=XY*double_data[c+1]; |
||
5860 | double_data[c+2]=(1-Z2)/den*R; |
||
18557 | bpr | 5861 | tmp_buffer=my_newmem(MAX_BUFFER); |
18555 | bpr | 5862 | check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[c+2],double_data[c+2],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset)); |
5863 | add_to_buffer(tmp_buffer); |
||
5864 | if(onclick != 0){object_cnt++;}/* object_cnt++; */ |
||
5865 | } |
||
5866 | reset(); |
||
5867 | dragstuff[13] = 1; |
||
5868 | if(use_dragstuff == 0 ){ use_dragstuff = 1; } |
||
5869 | break; |
||
18552 | bpr | 5870 | case ZOOM: |
5871 | /* |
||
18556 | bpr | 5872 | @ zoom button_color |
5873 | @ introduce a very small ''controlpanel`` at the lower right corner (font size of the panel is fixed to: 22px Arial) |
||
5874 | @ giving six 15×15px ''active`` rectangle areas<br>(''×,↓,↑,←,→,−,+``) for zooming and/or panning of the image |
||
5875 | @ a mouse wheel is active for in/out zooming. Drag panning is not supported (this will conflict with many ''userdraw`` or ''multidraw`` primitives) |
||
5876 | @ the ''controlpanel`` is not active for a ''userdraw`` mousedown (but it can interfere with some ''userdraw`` types) |
||
5877 | @ the ''×`` symbol will reset to your original xmax/xmin ymax/ymin values. |
||
5878 | @ choose an appropriate color, so the small ''×,↓,↑,←,→,−,+`` are clearly visible |
||
5879 | @ command ''opacity`` may be used to set stroke_opacity of buttons |
||
5880 | @ note: on zooming, text will not increase / decrease the font size (todo??) |
||
5881 | @ note: adding ''zooming`` will increase the size of the javascript include with approx. 11 kb |
||
18552 | bpr | 5882 | */ |
18556 | bpr | 5883 | js_function[INTERACTIVE] = 1; |
18552 | bpr | 5884 | js_function[JS_ZOOM] = 1; |
5885 | if( use_userdraw == 1 ){ |
||
5886 | js_function[USERDRAW_AND_ZOOM] = 1; |
||
5887 | fprintf(js_include_file,"forbidden_zone = [%d,%d];",xsize-115,ysize - 20); |
||
5888 | } |
||
5889 | if(jsplot_cnt != -1){ js_function[JSPLOT_AND_ZOOM] = 1;} |
||
5890 | stroke_color = get_color(infile,1); |
||
5891 | /* we use BG_CANVAS (0) */ |
||
5892 | add_js_zoom_buttons(stroke_color,stroke_opacity); |
||
5893 | done = TRUE; |
||
5894 | break; |
||
11806 | schaersvoo | 5895 | |
5896 | /* ready */ |
||
18552 | bpr | 5897 | default:sync_input(infile); |
5898 | break; |
||
5899 | } |
||
7614 | schaersvoo | 5900 | } |
5901 | /* we are done parsing script file */ |
||
18556 | bpr | 5902 | if(use_dragstuff != 0){ |
18562 | bpr | 5903 | /* add the 20kb drag code: nearly always used ... use_dragstuff==1: no-mouse ! */ |
18556 | bpr | 5904 | add_drag_code(DRAG_CANVAS,use_dragstuff,dragstuff,reply_format); |
5905 | if(js_function[JS_ZOOM] == 1){ |
||
15111 | schaersvoo | 5906 | js_function[DRAG_AND_ZOOM] = 1; |
18556 | bpr | 5907 | } |
15111 | schaersvoo | 5908 | } |
15116 | bpr | 5909 | |
14066 | bpr | 5910 | /* check if xrange / yrange was set explicit ... or use xmin=0 xmax=xsize ymin=0 ymax=ysize: Quadrant I */ |
18556 | bpr | 5911 | if( found_size_command == 1 ){ |
5912 | fprintf(js_include_file,"var xmin = 0;var xmax = %d;var ymin = 0;var ymax = %d",xsize,ysize); |
||
7983 | schaersvoo | 5913 | } |
18556 | bpr | 5914 | else |
5915 | { |
||
5916 | if( found_size_command != 3 ){ |
||
5917 | canvas_error("Please specify size first and then both xrange and yrange ..."); |
||
5918 | } |
||
5919 | } |
||
8257 | schaersvoo | 5920 | |
18562 | bpr | 5921 | /* if needed, add generic draw functions (grid / xml etc) to buffer: these are no draggable/clickable shapes / objects ! */ |
18556 | bpr | 5922 | add_javascript_function(); |
7614 | schaersvoo | 5923 | /* add read_canvas() etc functions if needed */ |
18556 | bpr | 5924 | if( reply_format > 0 ){ add_read_canvas(reply_format,reply_precision);} |
7797 | schaersvoo | 5925 | /* no zoom, just add buffer */ |
18556 | bpr | 5926 | fprintf(js_include_file,"\n/* add buffer */\n%s};\n/* end wims_canvas_function */\nwims_canvas_function%d();\n",buffer,canvas_root_id); |
7614 | schaersvoo | 5927 | /* done writing the javascript include file */ |
18556 | bpr | 5928 | fclose(js_include_file); |
5929 | } |
||
7614 | schaersvoo | 5930 | |
5931 | /* if using a tooltip, this should always be printed to the *.phtml file, so stdout */ |
||
18556 | bpr | 5932 | if( use_tooltip > 0 ){ |
5933 | if( use_tooltip == 1 ){ |
||
5934 | add_js_tooltip(tooltip_text,bgcolor); |
||
5935 | } |
||
5936 | else |
||
5937 | { |
||
5938 | if( use_tooltip == 2 ){ |
||
5939 | add_js_popup(getfile_cmd); |
||
5940 | } |
||
5941 | } |
||
9329 | schaersvoo | 5942 | } |
18556 | bpr | 5943 | exit(EXIT_SUCCESS); |
7614 | schaersvoo | 5944 | } |
5945 | /* end main() */ |
||
5946 | |||
5947 | /****************************************************************************** |
||
5948 | ** |
||
5949 | ** sync_input |
||
5950 | ** |
||
5951 | ** synchronises input line - reads to end of line, leaving file pointer |
||
5952 | ** at first character of next line. |
||
5953 | ** |
||
5954 | ** Used by: |
||
5955 | ** main program - error handling. |
||
5956 | ** |
||
5957 | ******************************************************************************/ |
||
5958 | void sync_input(FILE *infile) |
||
5959 | { |
||
18552 | bpr | 5960 | int c = 0; |
7614 | schaersvoo | 5961 | |
18552 | bpr | 5962 | if( c == '\n' || c == ';' ) return; |
5963 | while( ( (c=getc(infile)) != EOF ) && (c != '\n') && (c != '\r') && (c != ';')) ; |
||
5964 | if( c == EOF ) finished = 1; |
||
5965 | if( c == '\n' || c == '\r' || c == ';') line_number++; |
||
5966 | return; |
||
7614 | schaersvoo | 5967 | } |
5968 | |||
5969 | /******************************************************************************/ |
||
15111 | schaersvoo | 5970 | void transform(int num,int incr){ |
5971 | /*. |
||
5972 | only "double_data[]" is used for transformations !! |
||
5973 | */ |
||
5974 | int i;int ii;double x,y; |
||
5975 | for(i=0;i<num;i = i+incr){ |
||
5976 | ii = i+1; |
||
5977 | x = double_data[i]*affine_matrix[0] + double_data[ii]*affine_matrix[1]+affine_matrix[4]; |
||
5978 | y = double_data[i]*affine_matrix[2] + double_data[ii]*affine_matrix[3]+affine_matrix[5]; |
||
15601 | schaersvoo | 5979 | /* |
17351 | bpr | 5980 | printf("(%f:%f) → (%f:%f)<br>",double_data[i],double_data[ii],x,y); |
15601 | schaersvoo | 5981 | */ |
15111 | schaersvoo | 5982 | double_data[i] = x; |
5983 | double_data[ii] = y; |
||
5984 | } |
||
5985 | } |
||
5986 | |||
5987 | void rotate(int num,double angle,double center[],int incr){ |
||
5988 | int i;int ii;double rad = angle * 0.0174532925199; |
||
5989 | double c = cos(rad); |
||
5990 | double s = sin(rad); |
||
5991 | double x,y; |
||
5992 | for(i=0;i<num;i = i+incr){ |
||
5993 | ii = i+1; |
||
5994 | x = c*(double_data[i]-center[0]) + s*(double_data[ii] - center[1] ) + center[0]; |
||
5995 | y = c*(double_data[ii]-center[1]) - s*(double_data[i] - center[0] ) + center[1]; |
||
5996 | double_data[i] = x; |
||
5997 | double_data[ii] = y; |
||
17351 | bpr | 5998 | // printf("(x:y) - (%f:%f)<br>",x,y); |
15111 | schaersvoo | 5999 | } |
6000 | } |
||
6001 | /* not used: see transform() |
||
6002 | void translate(int num){ |
||
6003 | int i;int ii; |
||
6004 | double x,y; |
||
6005 | for(i=0;i<num;i = i+2){ |
||
6006 | ii = i+1; |
||
6007 | x = double_data[i] + affine_matrix[4]; |
||
6008 | y = double_data[ii] + affine_matrix[5]; |
||
6009 | double_data[i] = x; |
||
6010 | double_data[ii] = y; |
||
6011 | } |
||
6012 | } |
||
6013 | */ |
||
7614 | schaersvoo | 6014 | char *str_replace(const char *str, const char *old, const char *new){ |
18562 | bpr | 6015 | if(strlen(str) > MAX_BUFFER){canvas_error("string argument too big");} |
6016 | char *ret, *r; |
||
6017 | const char *p, *q; |
||
6018 | size_t oldlen = strlen(old); |
||
6019 | size_t count = 0; |
||
6020 | size_t retlen = 0; |
||
6021 | size_t newlen = strlen(new); |
||
6022 | if (oldlen != newlen){ |
||
6023 | for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen){ |
||
18552 | bpr | 6024 | count++; |
6025 | retlen = p - str + strlen(p) + count * (newlen - oldlen); |
||
18562 | bpr | 6026 | } |
18552 | bpr | 6027 | } |
18562 | bpr | 6028 | else { |
6029 | retlen = strlen(str); |
||
6030 | } |
||
6031 | if ((ret = malloc(retlen + 1)) == NULL){ |
||
6032 | ret = NULL; |
||
6033 | canvas_error("string argument is NULL"); |
||
6034 | } |
||
6035 | else |
||
6036 | { |
||
6037 | for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) { |
||
18552 | bpr | 6038 | size_t l = q - p; |
6039 | memcpy(r, p, l); |
||
6040 | r += l; |
||
6041 | memcpy(r, new, newlen); |
||
6042 | r += newlen; |
||
18562 | bpr | 6043 | } |
6044 | strcpy(r, p); |
||
18552 | bpr | 6045 | } |
18562 | bpr | 6046 | return ret; |
7614 | schaersvoo | 6047 | } |
6048 | |||
6049 | /******************************************************************************/ |
||
7848 | bpr | 6050 | |
7614 | schaersvoo | 6051 | char *get_color(FILE *infile , int last){ |
18562 | bpr | 6052 | int c,i = 0,is_hex = 0; |
6053 | char temp[MAX_COLOR_STRING], *string; |
||
6054 | const char *not_allowed = "0123456789"; |
||
6055 | while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != ',' ) && ( c != ';' ) && ( c != '\t' ) ){ |
||
6056 | if( i > MAX_COLOR_STRING ){ canvas_error("colour string is too big ... ? ");} |
||
6057 | if( c == '#' ){ |
||
18552 | bpr | 6058 | is_hex = 1; |
18562 | bpr | 6059 | } |
6060 | if( c != ' '){ |
||
18552 | bpr | 6061 | if( is_hex == 0 ){if(strchr(not_allowed,c) != 0){canvas_error("found something like a number...but is should have been a colour or #hex color number...<br>Do not use R,G,B !!! ");}} |
6062 | temp[i]=tolower(c); |
||
6063 | i++; |
||
18562 | bpr | 6064 | } |
18552 | bpr | 6065 | } |
18562 | bpr | 6066 | if( ( c == '\n' || c == EOF || c == ';' || c == '\t' ) && last == 0){canvas_error("expecting more arguments in command");} |
6067 | if( c == '\n' || c == ';' || c == '\t' ){ done = TRUE; line_number++; } |
||
6068 | if( c == EOF ){finished = 1;} |
||
6069 | if( finished == 1 && last != 1 ){ canvas_error("expected more arguments");} |
||
6070 | temp[i]='\0'; |
||
6071 | if( strlen(temp) == 0 ){ canvas_error("expected a colorname or hexnumber, but found nothing !!");} |
||
6072 | if( is_hex == 1 ){ |
||
6073 | char red[3], green[3], blue[3]; |
||
6074 | red[0] = toupper(temp[1]); red[1] = toupper(temp[2]); red[2] = '\0'; |
||
6075 | green[0] = toupper(temp[3]); green[1] = toupper(temp[4]); green[2] = '\0'; |
||
6076 | blue[0] = toupper(temp[5]); blue[1] = toupper(temp[6]); blue[2] = '\0'; |
||
6077 | int r = (int) strtol(red, NULL, 16); |
||
6078 | int g = (int) strtol(green, NULL, 16); |
||
6079 | int b = (int) strtol(blue, NULL, 16); |
||
6080 | int L0 = 1+snprintf(NULL,0,"%d,%d,%d",r,g,b); |
||
6081 | string = my_newmem(L0); |
||
6082 | snprintf(string,L0,"%d,%d,%d",r,g,b); |
||
6083 | return string; |
||
6084 | } |
||
6085 | else |
||
6086 | { |
||
6087 | string = (char *)my_newmem(sizeof(temp)); |
||
6088 | snprintf(string,sizeof(temp),"%s",temp); |
||
6089 | for( i = 0; i < NUMBER_OF_COLORNAMES ; i++ ){ |
||
18552 | bpr | 6090 | if( strcmp( colors[i].name , string ) == 0 ){ |
18562 | bpr | 6091 | return colors[i].rgb; |
18552 | bpr | 6092 | } |
18562 | bpr | 6093 | } |
6094 | canvas_error("I was expecting a color name or hexnumber...but found nothing."); |
||
18552 | bpr | 6095 | } |
18562 | bpr | 6096 | return "0,0,255"; |
7614 | schaersvoo | 6097 | } |
6098 | |||
14066 | bpr | 6099 | char *get_string(FILE *infile,int last){ /* last = 0: more arguments ; last=1 final argument */ |
18562 | bpr | 6100 | int c,i=0; |
6101 | char temp[MAX_BUFFER], *string; |
||
6102 | while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != '\t') ){ |
||
6103 | temp[i]=c; |
||
6104 | i++; |
||
6105 | if(i > MAX_BUFFER){ canvas_error("string size too big...repeat command to fit string");break;} |
||
6106 | } |
||
6107 | if( ( c == '\n' || c == '\t' || c == EOF ) && last == 0){ |
||
6108 | canvas_error("expecting more arguments in command");} |
||
6109 | if( c == '\n' || c == '\t') { done = TRUE; line_number++; } |
||
6110 | if( c == EOF ) {finished = 1;} |
||
6111 | temp[i]='\0'; |
||
6112 | if( strlen(temp) == 0 && last != 3 ){ |
||
6113 | canvas_error("expected a word or string, but found nothing!");} |
||
6114 | string=(char *)my_newmem(strlen(temp)); |
||
6115 | snprintf(string,sizeof(temp),"%s",temp); |
||
6116 | return string; |
||
7614 | schaersvoo | 6117 | } |
6118 | |||
14066 | bpr | 6119 | char *get_string_argument(FILE *infile,int last){ /* last = 0: more arguments ; last=1 final argument */ |
18562 | bpr | 6120 | int c,i=0; |
6121 | char temp[MAX_BUFFER], *string; |
||
6122 | while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != '\t') && ( c != ',')){ |
||
6123 | temp[i]=c; |
||
6124 | i++; |
||
6125 | if(i > MAX_BUFFER){ canvas_error("string size too big...will cut it off");break;} |
||
6126 | } |
||
6127 | if( ( c == '\n' || c == EOF) && last == 0){canvas_error("expecting more arguments in command");} |
||
6128 | if( c == '\n' || c == '\t' ) { line_number++; } |
||
6129 | if( c == EOF ) {finished = 1;} |
||
6130 | if( finished == 1 && last == 0 ){ canvas_error("expected more arguments");} |
||
6131 | temp[i]='\0'; |
||
10953 | bpr | 6132 | /* |
18562 | bpr | 6133 | 17.10.2014 removed (question Perrin) |
6134 | may cause some unwanted effects... |
||
6135 | if( strlen(temp) == 0 ){ canvas_error("expected a word or string (without comma), but found nothing !!");} |
||
8322 | schaersvoo | 6136 | */ |
18562 | bpr | 6137 | string=(char *)my_newmem(sizeof(temp)); |
6138 | snprintf(string,sizeof(temp),"%s",temp); |
||
6139 | done = TRUE; |
||
6140 | return string; |
||
7614 | schaersvoo | 6141 | } |
6142 | |||
14066 | bpr | 6143 | double get_real(FILE *infile, int last){ /* accept anything that looks like an number ? last = 0: more arguments ; last=1 final argument */ |
18562 | bpr | 6144 | int c,i=0,found_calc = 0; |
6145 | double y; |
||
6146 | char tmp[MAX_INT]; |
||
6147 | /* |
||
6148 | these things are 'allowed functions': *,^,+,-,/,(,),e,arc,cos,tan,pi,log,ln,sqrt,abs |
||
6149 | but there should be a better way to avoid segfaults ! |
||
6150 | */ |
||
6151 | const char *allowed = "earcostanpilogqb*+-/^()";/* assuming these are allowed stuff in a 'number'*/ |
||
6152 | const char *not_allowed = "#dfhjkmuvwxyz{}[]%&~!$";/* avoid segmentation faults in a "atof()" and "wims eval" */ |
||
6153 | while(( (c=getc(infile)) != EOF ) && ( c != ',') && (c != '\n') && (c != '\t') && ( c != ';')){ |
||
6154 | if( c != ' ' ){ |
||
8224 | bpr | 6155 | if( i == 0 && c == '+' ){ |
18562 | bpr | 6156 | continue; |
8224 | bpr | 6157 | } |
7614 | schaersvoo | 6158 | else |
6159 | { |
||
18562 | bpr | 6160 | c = tolower(c); |
6161 | if( strchr(not_allowed,c) != 0 ){canvas_error("found a character not associated with a number...");} |
||
6162 | if( strchr(allowed,c) != 0 ){found_calc = 1;}/* hand the string over to wims eval() */ |
||
6163 | tmp[i] = c; |
||
6164 | i++; |
||
7614 | schaersvoo | 6165 | } |
6166 | } |
||
18562 | bpr | 6167 | if( i > MAX_INT - 1){canvas_error("number too large");} |
6168 | } |
||
6169 | if( ( c == '\n' || c == EOF || c == ';' || c == '\t' ) && last == 0){canvas_error("expecting more arguments in command");} |
||
6170 | if( c == '\n' || c == ';' || c == '\t' ){ done = TRUE; line_number++; } |
||
6171 | if( c == EOF ){done = TRUE ; finished = 1;} |
||
6172 | tmp[i]='\0'; |
||
6173 | if( strlen(tmp) == 0 ){canvas_error("expected a number, but found nothing !!");} |
||
6174 | if( found_calc == 1 ){ /* use wims eval to calculate 2*pi/3 */ |
||
6175 | void *f = eval_create(tmp); |
||
6176 | assert(f);if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;} |
||
6177 | y = eval_x(f, 1); |
||
6178 | /* if function is bogus; y = 1: so no core dumps */ |
||
6179 | eval_destroy(f); |
||
6180 | } |
||
6181 | else |
||
6182 | { |
||
6183 | y = atof(tmp); |
||
6184 | } |
||
6185 | return y; |
||
7614 | schaersvoo | 6186 | } |
6187 | void canvas_error(char *msg){ |
||
18562 | bpr | 6188 | fprintf(stdout,"\n</script><hr><span style=\"color:red\">FATAL syntax error: line %d: %s</span><hr>",line_number,msg); |
6189 | finished = 1; |
||
6190 | exit(EXIT_SUCCESS); |
||
7614 | schaersvoo | 6191 | } |
6192 | /* convert x/y coordinates to pixel */ |
||
6193 | int x2px(double x){ |
||
18606 | bpr | 6194 | int res=(x-xmin)/(xmax-xmin)*xsize; |
6195 | return (res==xsize)?xsize-1:res; |
||
7614 | schaersvoo | 6196 | } |
6197 | int y2px(double y){ |
||
18606 | bpr | 6198 | int res=(ymax-y)/(ymax-ymin)*ysize; |
6199 | return (res==ysize)?ysize-1:res; |
||
7614 | schaersvoo | 6200 | } |
6201 | double px2x(int x){ |
||
18562 | bpr | 6202 | return (x*(xmax - xmin)/xsize + xmin); |
7614 | schaersvoo | 6203 | } |
6204 | double px2y(int y){ |
||
18562 | bpr | 6205 | return (y*(ymax - ymin)/ysize + ymin); |
7614 | schaersvoo | 6206 | } |
6207 | void add_to_buffer(char *tmp){ |
||
17351 | bpr | 6208 | //fprintf(stdout,"tmp = %s<br>buffer = %s<br>",tmp,buffer); |
18562 | bpr | 6209 | if( tmp == NULL || tmp == 0 ){ canvas_error("nothing to add_to_buffer()...");} |
6210 | /* do we have enough space left in buffer[MAX_BUFFER] ? */ |
||
6211 | int space_left = (int) (sizeof(buffer) - strlen(buffer)); |
||
6212 | if( space_left > strlen(tmp)){ |
||
6213 | strncat(buffer,tmp,space_left - 1);/* add safely "tmp" to the string buffer */ |
||
6214 | } |
||
6215 | else |
||
6216 | { |
||
6217 | canvas_error("your memory buffer is too big<br>simplify your script...it produces too many lines "); |
||
6218 | } |
||
6219 | tmp = NULL;free(tmp); |
||
6220 | return; |
||
7614 | schaersvoo | 6221 | } |
6222 | void reset(){ |
||
18562 | bpr | 6223 | if(no_reset == FALSE){ /* 8/5/2020 */ |
6224 | use_filled = FALSE; |
||
6225 | use_dashed = FALSE; |
||
6226 | if(onclick != 4 ){onclick = 0;} /* slider param 'active'... onclick=4 */ |
||
6227 | drag_type = -1; |
||
6228 | use_offset = 0; |
||
6229 | } |
||
7614 | schaersvoo | 6230 | } |
15111 | schaersvoo | 6231 | char *getMML(char *tex){ |
18562 | bpr | 6232 | int my_pipe[2];pid_t pid; |
6233 | if(pipe(my_pipe)){canvas_error("mathml(): pipe() failure.\n");} |
||
15111 | schaersvoo | 6234 | pid = fork(); |
6235 | if (pid == (pid_t) 0){ |
||
18562 | bpr | 6236 | char *argv[]={"wims_mathml","--use-zoom","0","--tex-size 100%","--max-mml-size","1024","--tex-string",tex,NULL}; |
6237 | close(my_pipe[0]);dup2(my_pipe[1], 1);dup2(my_pipe[1], 2);close(my_pipe[1]); |
||
6238 | execv("../bin/wims_mathml",argv);canvas_error("could not execute wims_mathml\n"); |
||
15111 | schaersvoo | 6239 | } |
6240 | else |
||
15116 | bpr | 6241 | { |
18562 | bpr | 6242 | if (pid < (pid_t) 0){ |
6243 | close(my_pipe[0]);close(my_pipe[1]);canvas_error("mathml(): fork() failure.\n"); |
||
6244 | } |
||
6245 | int status;FILE *stream;close(my_pipe[1]);stream = fdopen (my_pipe[0], "r"); |
||
6246 | char buffer[MAX_BUFFER+1];memset(buffer,'\0',MAX_BUFFER); |
||
6247 | fgets(buffer, MAX_BUFFER, stream); |
||
6248 | int L0 = 1 + snprintf(NULL,0,"%s", buffer); |
||
6249 | tex = my_newmem(L0);memset(tex,'\0',L0); |
||
6250 | snprintf(tex,L0,"%s",buffer); |
||
6251 | fclose (stream);close(my_pipe[0]);waitpid(pid, &status, 0); |
||
15111 | schaersvoo | 6252 | } |
18562 | bpr | 6253 | return tex; |
15111 | schaersvoo | 6254 | } |
7614 | schaersvoo | 6255 | |
15111 | schaersvoo | 6256 | char *getSVGMOL(char *inputtype,char *keys){ |
6257 | int idx; |
||
6258 | char *forbidden[] = {"-O","-H","-z","-L","-o","-m"}; |
||
6259 | char *argv[1+strlen(keys)]; |
||
6260 | argv[0] = "obabel"; argv[1] = "-i"; argv[2] = inputtype; |
||
6261 | idx = 3;int i; |
||
6262 | char *ptr = strtok(keys,","); |
||
6263 | while(ptr != NULL ){ |
||
6264 | for(i = 0 ; i < 6; i++ ){if( strncmp(ptr,forbidden[i],2) == 0 ){return "NOT ALLOWED ARGUMENT";}} |
||
6265 | argv[idx] = ptr; idx++; |
||
17351 | bpr | 6266 | if(idx > 18){canvas_error("too many arguments for obabel....see docs<br>");} |
15111 | schaersvoo | 6267 | ptr = strtok(NULL,","); |
6268 | } |
||
6269 | /* last arguments; no 'javascript', only 'svg to STDOUT' and 'NULL' */ |
||
6270 | argv[idx] = "-xj";argv[idx+1] = "-o"; argv[idx+2] = "svg";argv[idx+3] = NULL; |
||
6271 | int link[2]; |
||
6272 | pid_t pid; |
||
6273 | char buffer[MAX_BUFFER+1]; |
||
6274 | memset(buffer,'\0',MAX_BUFFER); |
||
6275 | if (pipe(link)==-1){canvas_error("pipe");} |
||
6276 | if ((pid = fork()) == -1){canvas_error("fork");} |
||
15116 | bpr | 6277 | |
15111 | schaersvoo | 6278 | char *svgmol = "error"; |
6279 | int string_length = 0; |
||
15116 | bpr | 6280 | |
15111 | schaersvoo | 6281 | if(pid == 0) { |
6282 | dup2 (link[1], STDOUT_FILENO); |
||
6283 | dup2(link[0], STDERR_FILENO);/* remove annoying messages '1 molecule converted' */ |
||
6284 | close(link[0]); |
||
6285 | close(link[1]); |
||
6286 | execvp("obabel",argv); |
||
6287 | } else { |
||
6288 | close(link[1]); |
||
18109 | schaersvoo | 6289 | read(link[0],buffer, sizeof(buffer)); |
15111 | schaersvoo | 6290 | close(link[0]); |
6291 | /* need to remover newline from svg-string on freebsd */ |
||
6292 | char *pch = strstr(buffer, "\n"); |
||
6293 | while(pch != NULL){ |
||
18555 | bpr | 6294 | strncpy(pch, " ", 1); |
6295 | pch = strstr(buffer, "\n"); |
||
15111 | schaersvoo | 6296 | } |
6297 | string_length = 1 + snprintf(NULL,0,"%s",buffer); |
||
6298 | svgmol= my_newmem(string_length); |
||
6299 | snprintf(svgmol,string_length,"%s",buffer); |
||
6300 | wait(NULL); |
||
6301 | } |
||
18562 | bpr | 6302 | return svgmol; |
15111 | schaersvoo | 6303 | } |
6304 | /* GNU libmatheval library for evaluating mathematical functions. */ |
||
15601 | schaersvoo | 6305 | char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double rotationcenter[]){ |
18555 | bpr | 6306 | void *f; |
6307 | double x; |
||
6308 | double y; |
||
6309 | double xorg; |
||
6310 | int xv; |
||
6311 | int i = 0; |
||
6312 | int xstep =(int)(xsize/plotsteps); |
||
6313 | if( xstep == 0 ){xstep = 1;} |
||
6314 | double a = (xmax - xmin)/xsize; |
||
6315 | f = eval_create(fun); |
||
6316 | assert (f); |
||
6317 | if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;} |
||
6318 | /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */ |
||
6319 | double xydata[MAX_BUFFER+1];/* hmmm */ |
||
6320 | int lim_ymin =(int)( ymin - 4*fabs(ymin));/* 19-4-2015 replacing "abs" by "fabs"*/ |
||
6321 | int lim_ymax =(int)( ymax + 4*fabs(ymax));/* 19-4-2015 replacing "abs" by "fabs"*/ |
||
6322 | double c = 1.0;double s = 1.0; |
||
6323 | if( use_rotate == TRUE ){s = sin(angle*0.0174533);c = cos(angle*0.0174533);} |
||
6324 | for ( xv = 0 ;xv < xsize ; xv = xv+xstep ){ |
||
18562 | bpr | 6325 | x = (double) (xv*a + xmin); |
6326 | xorg = x; |
||
6327 | if( i < MAX_BUFFER - 2){ |
||
18552 | bpr | 6328 | y = eval_x(f, x); |
6329 | if(y < lim_ymax && y > lim_ymin ){ |
||
18562 | bpr | 6330 | if( use_affine == TRUE ){ |
6331 | x = x*affine_matrix[0] + y*affine_matrix[1]+affine_matrix[4]; |
||
6332 | y = xorg*affine_matrix[2] + y*affine_matrix[3]+affine_matrix[5]; |
||
6333 | } |
||
6334 | if( use_rotate == TRUE){ |
||
6335 | x = (c * (x - rotationcenter[0])) + (s * (y - rotationcenter[1])) + rotationcenter[0]; |
||
6336 | y = (c * (y - rotationcenter[1])) - (s * (xorg - rotationcenter[0])) + rotationcenter[1]; |
||
6337 | } |
||
6338 | xydata[i++] = x; |
||
18552 | bpr | 6339 | xydata[i++] = y; |
6340 | } |
||
18562 | bpr | 6341 | } |
6342 | else |
||
6343 | { |
||
18552 | bpr | 6344 | canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... "); |
18562 | bpr | 6345 | } |
18552 | bpr | 6346 | } |
18562 | bpr | 6347 | eval_destroy(f); |
6348 | return double_xy2js_array(xydata,i,find_number_of_digits(precision)); |
||
15111 | schaersvoo | 6349 | } |
6350 | /* plot a very primitive (!) levelcurve : not to be compared with "flydraw levelcurve" */ |
||
6351 | char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level){ |
||
18562 | bpr | 6352 | void *f = eval_create(fun); |
6353 | assert (f); |
||
6354 | if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;} |
||
6355 | double a = (double)((xmax - xmin)/plotsteps); |
||
6356 | double b = (double)((ymax - ymin)/plotsteps); |
||
6357 | double x;double y;double diff; |
||
6358 | double xydata[MAX_BUFFER+1]; |
||
6359 | int i = 0; |
||
6360 | ymin = ymin - 1; |
||
6361 | xmin = xmin - 1; |
||
6362 | ymax = ymax + 1; |
||
6363 | xmax = xmax + 1; |
||
6364 | for( x = xmin ;x < xmax ; x = x + a ){ |
||
6365 | for ( y = ymin ;y < ymax ; y = y + b ){ |
||
18552 | bpr | 6366 | if( i < MAX_BUFFER - 2){ |
18562 | bpr | 6367 | diff = level - eval_x_y(f, x,y); |
6368 | if(diff < 0.1 && diff > -0.1){ |
||
6369 | xydata[i++] = x; |
||
6370 | xydata[i++] = y; |
||
6371 | } |
||
18552 | bpr | 6372 | } |
6373 | else |
||
6374 | { |
||
18562 | bpr | 6375 | canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps, decrease image size...\nor some other means to reduce the amount of data... "); |
18552 | bpr | 6376 | } |
18562 | bpr | 6377 | } |
18552 | bpr | 6378 | } |
18562 | bpr | 6379 | eval_destroy(f); |
6380 | return double_xy2js_array(xydata,i,find_number_of_digits(precision)); |
||
15111 | schaersvoo | 6381 | } |
7614 | schaersvoo | 6382 | |
15111 | schaersvoo | 6383 | /* plot parametric function */ |
18562 | bpr | 6384 | char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin, |
6385 | double xmax,double ymin,double ymax, |
||
6386 | double tmin,double tmax,int plotsteps,int precision,double rotationcenter[]){ |
||
6387 | void *fx; |
||
6388 | void *fy; |
||
6389 | double t; |
||
6390 | int i = 0; |
||
6391 | double tstep = (tmax-tmin)/plotsteps; |
||
6392 | if( tstep == 0 ){canvas_error("zero step for t variable : reduce plotsteps or inrease trange");} |
||
6393 | fx = eval_create(fun1); |
||
6394 | fy = eval_create(fun2); |
||
6395 | assert(fx); |
||
6396 | assert(fy); |
||
6397 | if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;} |
||
15111 | schaersvoo | 6398 | /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */ |
18562 | bpr | 6399 | double xydata[MAX_BUFFER+1];/* hmmm */ |
6400 | double x; /* real x-values */ |
||
6401 | double y; /* real y-values */ |
||
6402 | double xorg; |
||
6403 | /* |
||
6404 | 29/12/2020 |
||
6405 | disabled to try and synchronise curve+affine behaviour in complex scripts produced by "elec, tool circuit" (BPR) |
||
15623 | schaersvoo | 6406 | int lim_ymin =(int)( ymin - 4*fabs(ymin)); |
6407 | int lim_ymax =(int)( ymax + 4*fabs(ymax)); |
||
6408 | */ |
||
18562 | bpr | 6409 | double c = 1.0;double s = 1.0; |
6410 | if( use_rotate == TRUE ){s = sin(angle*0.0174533);c = cos(angle*0.0174533);} |
||
6411 | for( t = tmin ;t <= tmax ; t = t + tstep ){ |
||
6412 | if( i < MAX_BUFFER - 2 ){ |
||
18552 | bpr | 6413 | y = eval_t(fy, t); |
6414 | /* if(y > lim_ymin && y < lim_ymax){*/ |
||
18562 | bpr | 6415 | x = eval_t(fx, t); |
6416 | if( x == x){ /* no NaN */ |
||
6417 | xorg = x; |
||
6418 | if( use_affine == TRUE ){ |
||
6419 | x = x*affine_matrix[0] + y*affine_matrix[1]+affine_matrix[4]; |
||
6420 | y = xorg*affine_matrix[2] + y*affine_matrix[3]+affine_matrix[5]; |
||
6421 | } |
||
6422 | if( use_rotate == TRUE){ |
||
6423 | x = (c * (x - rotationcenter[0])) + (s * (y - rotationcenter[1])) + rotationcenter[0]; |
||
6424 | y = (c * (y - rotationcenter[1])) - (s * (xorg - rotationcenter[0])) + rotationcenter[1]; |
||
6425 | } |
||
6426 | xydata[i++] = x; |
||
6427 | xydata[i++] = y; |
||
6428 | } |
||
6429 | /* } */ |
||
18552 | bpr | 6430 | } |
18562 | bpr | 6431 | else |
6432 | { |
||
18552 | bpr | 6433 | canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... "); |
18562 | bpr | 6434 | } |
18552 | bpr | 6435 | } |
18562 | bpr | 6436 | eval_destroy(fx); |
6437 | eval_destroy(fy); |
||
6438 | return double_xy2js_array(xydata,i,find_number_of_digits(precision)); |
||
15111 | schaersvoo | 6439 | } |
7614 | schaersvoo | 6440 | |
15111 | schaersvoo | 6441 | char *double_xy2js_array(double xy[],int len,int decimals){ |
6442 | /* |
||
6443 | 1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8] |
||
6444 | int xy[] is already checked for errors or overflow in "get_real()" |
||
6445 | just to be sure we double check the size of "temp" |
||
7614 | schaersvoo | 6446 | */ |
18562 | bpr | 6447 | char temp[2*MAX_BUFFER], *string; |
6448 | char *tmp = my_newmem(16);/* <= 9999999999999999 */ |
||
6449 | memset(temp,'\0',2*MAX_BUFFER);/* clear memory */ |
||
6450 | int i;int space_left; |
||
6451 | temp[0] = '[';/* start js-array */ |
||
6452 | for(i = 0; i < len;i = i + 2){ /* x_points[] */ |
||
6453 | if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);} |
||
6454 | else {sprintf(tmp, "%.*f,",decimals,xy[i]);} |
||
6455 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6456 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);} |
||
6457 | else{ |
||
6458 | canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps ");} |
||
15111 | schaersvoo | 6459 | } |
6460 | strncat(temp,"],[",4); /* close js x_values array and start new */ |
||
6461 | for(i = 1; i < len;i = i + 2){ /* y_points */ |
||
18557 | bpr | 6462 | if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);} |
6463 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6464 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps");} |
||
15111 | schaersvoo | 6465 | } |
6466 | strncat(temp,"]",2); |
||
6467 | string=(char *)my_newmem(sizeof(temp)); |
||
6468 | snprintf(string,sizeof(temp),"%s",temp); |
||
6469 | return string; |
||
6470 | } |
||
7614 | schaersvoo | 6471 | |
15111 | schaersvoo | 6472 | char *list2js_array(char *list, char *s){/* abc:defg:hjiuy:qwer --> ["abc","defg","hjiuy","qwer"] */ |
6473 | #define MAX_ARG 128 |
||
18562 | bpr | 6474 | if( strlen(list)> MAX_ARG - 1){canvas_error("argument is too large (> 128)");} |
6475 | char tmp[MAX_ARG]; |
||
6476 | size_t p = 0; |
||
6477 | tmp[0] = '['; |
||
6478 | tmp[1] = '\"'; |
||
6479 | size_t t = 2; |
||
6480 | while(list[p] != '\0'){ |
||
6481 | if( list[p] == s[0] ){ |
||
6482 | tmp[t++]='\"';tmp[t++]=',';tmp[t++]='\"'; |
||
6483 | } |
||
6484 | else |
||
6485 | { |
||
6486 | tmp[t++] = list[p]; |
||
6487 | } |
||
6488 | p++; |
||
15111 | schaersvoo | 6489 | } |
18562 | bpr | 6490 | tmp[t++]='\"';tmp[t++]=']';tmp[t++]= '\0'; |
6491 | char *js_array = (char *)my_newmem(sizeof(tmp)); |
||
6492 | snprintf(js_array,sizeof(tmp),"%s",tmp); |
||
6493 | return js_array; |
||
15111 | schaersvoo | 6494 | } |
7963 | schaersvoo | 6495 | |
15111 | schaersvoo | 6496 | char *xy2js_array(int xy[],int len){ |
6497 | /* |
||
6498 | 1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8] |
||
6499 | int xy[] is already checked for errors or overflow in "get_real()" |
||
6500 | just to be sure we double check the size of "temp" |
||
7614 | schaersvoo | 6501 | */ |
18562 | bpr | 6502 | char temp[MAX_BUFFER], *string; |
6503 | char *tmp = my_newmem(16);/* <= 9999999999999999 */ |
||
6504 | memset(temp,'\0',MAX_BUFFER);/* clear memory */ |
||
6505 | int i;int space_left; |
||
6506 | temp[0] = '[';/* start js-array */ |
||
6507 | for(i = 0; i < len;i = i + 2){ /* x_points[] */ |
||
6508 | if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);} |
||
6509 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6510 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);} |
||
6511 | else { |
||
6512 | canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");} |
||
6513 | } |
||
6514 | strncat(temp,"],[",4); /* close js x_values array and start new */ |
||
6515 | for(i = 1; i < len;i = i + 2){ /* y_points */ |
||
6516 | if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);} |
||
6517 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6518 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);} |
||
6519 | else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data\nreduce image size or plotsteps \n");} |
||
6520 | } |
||
6521 | strncat(temp,"]",2); |
||
6522 | string=(char *)my_newmem(sizeof(temp)); |
||
6523 | snprintf(string,sizeof(temp),"%s",temp); |
||
6524 | return string; |
||
7614 | schaersvoo | 6525 | } |
6526 | |||
15111 | schaersvoo | 6527 | char *data2js_array(int data[],int len){ |
6528 | /* |
||
6529 | 1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8] |
||
6530 | int data[] is already checked for errors or overflow in "get_real()" |
||
6531 | just to be sure we double check the size of "temp" |
||
7614 | schaersvoo | 6532 | */ |
18562 | bpr | 6533 | char temp[MAX_BUFFER], *string; |
6534 | char *tmp = my_newmem(16);/* <= 9999999999999999 */ |
||
6535 | memset(temp,'\0',MAX_BUFFER);/* clear memory */ |
||
6536 | int i;int space_left; |
||
6537 | temp[0] = '[';/* start js-array */ |
||
6538 | for(i = 0; i < len; i++){ |
||
6539 | if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);} |
||
6540 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6541 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);} |
||
6542 | else{ |
||
6543 | canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps "); |
||
15111 | schaersvoo | 6544 | } |
18562 | bpr | 6545 | } |
6546 | strncat(temp,"]",2); |
||
6547 | string=(char *)my_newmem(sizeof(temp)); |
||
6548 | snprintf(string,sizeof(temp),"%s",temp); |
||
6549 | return string; |
||
15111 | schaersvoo | 6550 | } |
7614 | schaersvoo | 6551 | |
15111 | schaersvoo | 6552 | char *doubledata2js_array(double data[],int len, int decimals){ |
6553 | /* |
||
15116 | bpr | 6554 | 1.4355,2.345353,3.3455 --> [1.44,2.35,3.35] |
15111 | schaersvoo | 6555 | double data[] is already checked for errors or overflow in "get_real()" |
6556 | just to be sure we double check the size of "temp" |
||
8448 | schaersvoo | 6557 | */ |
18562 | bpr | 6558 | char temp[MAX_BUFFER], *string; |
6559 | char *tmp = my_newmem(16);/* <= 9999999999999999 */ |
||
6560 | memset(temp,'\0',MAX_BUFFER);/* clear memory */ |
||
6561 | int i;int space_left; |
||
6562 | temp[0] = '[';/* start js-array */ |
||
6563 | for(i = 0; i < len; i++){ |
||
6564 | if(i == len - 1){sprintf(tmp, "%.*f",decimals,data[i]);} |
||
6565 | else{sprintf(tmp, "%.*f,",decimals,data[i]);} |
||
6566 | space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1); |
||
6567 | if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);} |
||
6568 | else{ |
||
6569 | canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");} |
||
6570 | } |
||
6571 | strncat(temp,"]",2); |
||
6572 | string=(char *)my_newmem(sizeof(temp)); |
||
6573 | snprintf(string,sizeof(temp),"%s",temp); |
||
6574 | return string; |
||
15111 | schaersvoo | 6575 | } |
13829 | bpr | 6576 | |
15111 | schaersvoo | 6577 | void *my_newmem(size_t size){ |
18562 | bpr | 6578 | void *p; |
6579 | if((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");} |
||
6580 | return p; |
||
15111 | schaersvoo | 6581 | } |
8224 | bpr | 6582 | |
15111 | schaersvoo | 6583 | int find_number_of_digits(int i){ |
18562 | bpr | 6584 | if(i < 0 ){ i = -1*i;} |
6585 | int digits = 0; |
||
6586 | while ( i > 0){ |
||
6587 | digits++; |
||
6588 | i = i/10; |
||
6589 | } |
||
6590 | return digits; |
||
15111 | schaersvoo | 6591 | } |
7645 | schaersvoo | 6592 | |
16828 | schaersvoo | 6593 | int count_substring(char* string, char* substring) { |
18164 | schaersvoo | 6594 | int i, j, l1, l2; |
16828 | schaersvoo | 6595 | int count = 0; |
6596 | l1 = strlen(string); |
||
6597 | l2 = strlen(substring); |
||
6598 | for(i = 0; i < l1 - l2 + 1; i++) { |
||
6599 | if(strstr(string + i, substring) == string + i) { |
||
6600 | count++; |
||
6601 | i = i + l2 -1; |
||
6602 | } |
||
6603 | } |
||
6604 | return count; |
||
6605 | } |
||
11830 | schaersvoo | 6606 | |
7614 | schaersvoo | 6607 | void check_string_length(int L){ |
18555 | bpr | 6608 | if( L > MAX_BUFFER-1){ |
6609 | canvas_error("problem with your arguments to command..."); |
||
6610 | } |
||
6611 | return; |
||
7614 | schaersvoo | 6612 | } |
18555 | bpr | 6613 | /* useful in hyp commands: determine if the hypsegment is an arc or a line */ |
6614 | int hypgeodaux(double *q, double* ress, int full){ |
||
6615 | double alpha,beta,gamma,r,cx,cy,a1,a2,a3,tmp, |
||
6616 | nx = -q[0]*q[2]*q[2]+(q[0]*q[0]+q[1]*q[1]+1)*q[2]-q[0]*q[3]*q[3]-q[0], |
||
6617 | ny = -q[1]*q[2]*q[2]-q[1]*q[3]*q[3]+(q[0]*q[0]+q[1]*q[1]+1)*q[3]-q[1], |
||
6618 | dy = -2*q[1]*q[2]+2*q[0]*q[3]; |
||
6619 | if (dy*dy*1e4 <= nx*nx+ny*ny){ |
||
6620 | if(full){ |
||
6621 | if (q[1]*q[1]+q[0]*q[0] > q[2]*q[2]+q[3]*q[3]) |
||
6622 | gamma = atan2(q[1],q[0]); |
||
6623 | else |
||
6624 | gamma = atan2(q[3],q[2]); |
||
6625 | ress[0]=cos(gamma); ress[1]=sin(gamma); ress[2]=-cos(gamma); ress[3]=-sin(gamma); |
||
6626 | } |
||
6627 | else |
||
6628 | {int i;for(i=0;i<4;++i) ress[i]=q[i];} |
||
6629 | ress[5]=(q[0]+q[2])/2; |
||
6630 | ress[6]=(q[1]+q[3])/2; |
||
6631 | return 0;} |
||
6632 | cx = ny/dy; cy=-nx/dy; |
||
6633 | r = sqrt(cx*cx+cy*cy-1); |
||
6634 | if(full) |
||
6635 | {alpha=atan(1/r); beta = atan2(cy,cx);a1=M_PI+beta-alpha;a2=M_PI+beta+alpha;} |
||
6636 | else |
||
6637 | {a1 = atan2(q[1]-cy, q[0]-cx);a2 = atan2(q[3]-cy, q[2]-cx);} |
||
6638 | if (fabs(a2-a1)>M_PI){if(a1<a2) a1+=2*M_PI; else a2+=2*M_PI;}; |
||
6639 | a3 = (a1+a2)/2; |
||
6640 | if(a1>a2) {tmp=a1; a1=a2; a2=tmp;} |
||
6641 | ress[0]=cx; |
||
6642 | ress[1]=cy; |
||
6643 | ress[2]=2*r; |
||
6644 | ress[3]=2*r; |
||
6645 | ress[4]=360+180/M_PI*a1; |
||
6646 | ress[5]=360+180/M_PI*a2; |
||
6647 | ress[6]=cx+r*cos(a3); |
||
6648 | ress[7]=cy+r*sin(a3); |
||
6649 | return 1; |
||
6650 | } |
||
7614 | schaersvoo | 6651 | |
6652 | int get_token(FILE *infile){ |
||
18589 | bpr | 6653 | int left,milieu,delta,right,c,i=0; |
18562 | bpr | 6654 | char temp[MAX_INT], *input_type; |
18589 | bpr | 6655 | enum{rien,usefilled,usedashed}; |
6656 | static struct commande {char *nom; int res; int special;} table[]= |
||
6657 | { |
||
6658 | {"#",COMMENT,0}, |
||
6659 | {"affine",AFFINE,0}, |
||
6660 | {"allowdups",ALLOW_DUPLICATES,0}, |
||
6661 | {"angle",ANGLE,0}, |
||
6662 | {"animate",ANIMATE,0}, |
||
6663 | {"arc",ARC,0}, |
||
6664 | {"arcarrow",ARCARROW,0}, |
||
6665 | {"arrow",ARROW,0}, |
||
6666 | {"arrow2",ARROW2,0}, |
||
6667 | {"arrowarc",ARCARROW,0}, |
||
6668 | {"arrowhead",ARROWHEAD,0}, |
||
6669 | {"arrows",ARROWS,0}, |
||
6670 | {"arrows2",ARROWS2,0}, |
||
6671 | {"audio",AUDIO,0}, |
||
6672 | {"audioobject",AUDIOOBJECT,0}, |
||
6673 | {"axis",AXIS,0}, |
||
6674 | {"axisnumbering",AXIS_NUMBERING,0}, |
||
6675 | {"axisnumbers",AXIS_NUMBERING,0}, |
||
6676 | {"backgroundimage",BGIMAGE,0}, |
||
6677 | {"barchart",BARCHART,0}, |
||
6678 | {"bezier",BEZIER,0}, |
||
6679 | {"bgcolor",BGCOLOR,0}, |
||
6680 | {"bgimage",BGIMAGE,0}, |
||
6681 | {"blink",BLINK,0}, |
||
6682 | {"boxplot",BOXPLOT,0}, |
||
6683 | {"boxplotdata",BOXPLOTDATA,0}, |
||
6684 | {"brokenline",POLYLINE,0}, |
||
6685 | {"canvastype",CANVASTYPE,0}, |
||
6686 | {"centered",CENTERED,0}, |
||
6687 | {"centerstring",CENTERSTRING,0}, |
||
6688 | {"chemtex",CHEMTEX,0}, |
||
6689 | {"circle",CIRCLE,0}, |
||
6690 | {"circles",CIRCLES,0}, |
||
6691 | {"clearbutton",CLEARBUTTON,0}, |
||
6692 | {"clicktile",CLICKTILE,0}, |
||
6693 | {"clicktile_colors",CLICKTILE_COLORS,0}, |
||
6694 | {"clock",CLOCK,0}, |
||
6695 | {"colorpalette",COLORPALETTE,0}, |
||
6696 | {"colors",MULTISTROKECOLORS,0}, |
||
6697 | {"copy",COPY,0}, |
||
6698 | {"copyresized",COPYRESIZED,0}, |
||
6699 | {"crosshair",CROSSHAIR,0}, |
||
6700 | {"crosshairs",CROSSHAIRS,0}, |
||
6701 | {"crosshairsize",CROSSHAIRSIZE,0}, |
||
6702 | {"css",CSS,0}, |
||
6703 | {"cursor",CURSOR,0}, |
||
6704 | {"curve",CURVE,0}, |
||
6705 | {"curvedarrow",CURVEDARROW,0}, |
||
6706 | {"curvedarrow2",CURVEDARROW2,0}, |
||
6707 | {"curvedarrows",CURVEDARROWS,0}, |
||
6708 | {"curvedarrows2",CURVEDARROWS2,0}, |
||
6709 | {"darrow",ARROW,usedashed}, |
||
6710 | {"darrow2",ARROW2,usedashed}, |
||
6711 | {"dashed",DASHED,0}, |
||
6712 | {"dashtype",DASHTYPE,0}, |
||
6713 | {"dcurve",CURVE,usedashed}, |
||
6714 | {"delete",CLEARBUTTON,0}, |
||
6715 | {"demiline",HALFLINE,0}, |
||
6716 | {"demilines",HALFLINES,0}, |
||
6717 | {"dhline",HLINE,usedashed}, |
||
6718 | {"diafill",DIAMONDFILL,0}, |
||
6719 | {"diamondfill",DIAMONDFILL,0}, |
||
6720 | {"disk",CIRCLE,usefilled}, |
||
6721 | {"disks",CIRCLES,usefilled}, |
||
6722 | {"display",MOUSE_DISPLAY,0}, |
||
6723 | {"dline",LINE,usedashed}, |
||
6724 | {"dotfill",DOTFILL,0}, |
||
6725 | {"dplot",CURVE,usedashed}, |
||
6726 | {"dpolyline",POLYLINE,usedashed}, |
||
6727 | {"drag",DRAG,0}, |
||
6728 | {"dsegment",SEGMENT,usedashed}, |
||
6729 | {"dsegments",SEGMENTS,usedashed}, |
||
6730 | {"duplicates",ALLOW_DUPLICATES,0}, |
||
6731 | {"dvline",VLINE,usedashed}, |
||
6732 | {"ellipse",ELLIPSE,0}, |
||
6733 | {"ellipses",ELLIPSES,0}, |
||
6734 | {"end",END,0}, |
||
6735 | {"erase",CLEARBUTTON,0}, |
||
6736 | {"farc",ARC,usefilled}, |
||
6737 | {"fcircle",CIRCLE,usefilled}, |
||
6738 | {"fcircles",CIRCLES,usefilled}, |
||
6739 | {"fellipse",ELLIPSE,usefilled}, |
||
6740 | {"fhypcircles",HYPCIRCLES,usefilled}, |
||
6741 | {"fill",FLOODFILL,0}, |
||
6742 | {"fillall",FILLALL,0}, |
||
6743 | {"fillcolor",FILLCOLOR,0}, |
||
6744 | {"fillcolors",MULTIFILLCOLORS,0}, |
||
6745 | {"filled",FILLED,0}, |
||
6746 | {"filledarc",ARC,usefilled}, |
||
6747 | {"filledpoly",POLY,usefilled}, |
||
6748 | {"filledpolygon",POLY,usefilled}, |
||
18608 | bpr | 6749 | {"fillopacity",FILLOPACITY,0}, |
18589 | bpr | 6750 | {"fillpattern",FILLPATTERN,0}, |
6751 | {"filltoborder",FILLTOBORDER,0}, |
||
6752 | {"floodfill",FLOODFILL,0}, |
||
6753 | {"fontcolor",FONTCOLOR,0}, |
||
6754 | {"fontfamily",FONTFAMILY,0}, |
||
6755 | {"fontsize",FONTSIZE,0}, |
||
6756 | {"fpoly",POLY,usefilled}, |
||
6757 | {"fpolygon",POLY,usefilled}, |
||
6758 | {"frect",RECT,usefilled}, |
||
6759 | {"frectangle",RECT,usefilled}, |
||
6760 | {"frects",RECTS,usefilled}, |
||
6761 | {"froundrect",ROUNDRECT,usefilled}, |
||
6762 | {"froundrects",ROUNDRECTS,usefilled}, |
||
6763 | {"fsquare",SQUARE,usefilled}, |
||
6764 | {"fsquares",RECTS,usefilled}, |
||
6765 | {"ftriangle",TRIANGLE,usefilled}, |
||
6766 | {"ftriangles",TRIANGLES,usefilled}, |
||
6767 | {"functionlabel",FUNCTION_LABEL,0}, |
||
6768 | {"functionlabels",FUNCTION_LABEL,0}, |
||
6769 | {"grid",GRID,0}, |
||
6770 | {"gridfill",GRIDFILL,0}, |
||
6771 | {"group",GROUP,0}, |
||
6772 | {"halfline",HALFLINE,0}, |
||
6773 | {"halflines",HALFLINES,0}, |
||
6774 | {"hatchfill",HATCHFILL,0}, |
||
6775 | {"highlight",STYLE,0}, |
||
6776 | {"hline",HLINE,0}, |
||
6777 | {"hlines",HLINES,0}, |
||
6778 | {"horizontalline",HLINE,0}, |
||
6779 | {"horizontallines",HLINES,0}, |
||
6780 | {"html",HTML,0}, |
||
6781 | {"http",HTTP,0}, |
||
6782 | {"hypcircles",HYPCIRCLES,0}, |
||
6783 | {"hyplines",HYPLINES,0}, |
||
6784 | {"hyppolygon",HYPPOLY,0}, |
||
6785 | {"hyprays",HYPRAYS,0}, |
||
6786 | {"hypsegments",HYPSEGMENTS,0}, |
||
6787 | {"imagefill",IMAGEFILL,0}, |
||
6788 | {"imagepalette",IMAGEPALETTE,0}, |
||
6789 | {"input",INPUT,0}, |
||
6790 | {"intooltip",INTOOLTIP,0}, |
||
6791 | {"jscurve",JSCURVE,0}, |
||
6792 | {"jsmath",JSMATH,0}, |
||
6793 | {"jsplot",JSCURVE,0}, |
||
6794 | {"katex",LATEX,0}, |
||
6795 | {"kill",KILL,0}, |
||
6796 | {"killaffine",KILLAFFINE,0}, |
||
6797 | {"killgroup",KILLSLIDER,0}, |
||
6798 | {"killinear",KILLLINEAR,0}, |
||
6799 | {"killlinear",KILLLINEAR,0}, |
||
6800 | {"killreset",NORESET,0}, |
||
6801 | {"killrotate",KILLROTATE,0}, |
||
6802 | {"killslider",KILLSLIDER,0}, |
||
6803 | {"killtranslate",KILLTRANSLATION,0}, |
||
6804 | {"killtranslation",KILLTRANSLATION,0}, |
||
6805 | {"latex",LATEX,0}, |
||
6806 | {"lattice",LATTICE,0}, |
||
6807 | {"legend",LEGEND,0}, |
||
6808 | {"legendcolors",LEGENDCOLORS,0}, |
||
6809 | {"levelcurve",LEVELCURVE,0}, |
||
6810 | {"line",LINE,0}, |
||
6811 | {"linear",LINEAR,0}, |
||
6812 | {"linegraph",LINEGRAPH,0}, |
||
6813 | {"lines",LINES,0}, |
||
6814 | {"linewidth",LINEWIDTH,0}, |
||
6815 | {"linewidths",MULTILINEWIDTH,0}, |
||
6816 | {"math",LATEX,0}, |
||
6817 | {"mathml",MATHML,0}, |
||
6818 | {"mouse",MOUSE,0}, |
||
6819 | {"mousedegree",MOUSE_DEGREE,0}, |
||
6820 | {"mouseprecision",MOUSE_PRECISION,0}, |
||
6821 | {"mousex",MOUSEX,0}, |
||
6822 | {"mousey",MOUSEY,0}, |
||
6823 | {"multicolors",MULTISTROKECOLORS,0}, |
||
6824 | {"multidash",MULTIDASH,0}, |
||
6825 | {"multidraw",MULTIDRAW,0}, |
||
6826 | {"multifill",MULTIFILL,0}, |
||
6827 | {"multifillcolors",MULTIFILLCOLORS,0}, |
||
6828 | {"multifillopacity",MULTIFILLOPACITY,0}, |
||
6829 | {"multiinput",MULTIUSERINPUT,0}, |
||
6830 | {"multilabel",MULTILABEL,0}, |
||
6831 | {"multilinewidth",MULTILINEWIDTH,0}, |
||
6832 | {"multisnap",MULTISNAPTOGRID,0}, |
||
6833 | {"multisnaptogrid",MULTISNAPTOGRID,0}, |
||
6834 | {"multistrokecolors",MULTISTROKECOLORS,0}, |
||
6835 | {"multistrokeopacity",MULTISTROKEOPACITY,0}, |
||
6836 | {"multiuserinput",MULTIUSERINPUT,0}, |
||
6837 | {"newrange",NEWRANGE,0}, |
||
6838 | {"noreset",NORESET,0}, |
||
6839 | {"nostatus",STATUS,0}, |
||
6840 | {"noxaxis",NOXAXIS,0}, |
||
6841 | {"noyaxis",NOYAXIS,0}, |
||
6842 | {"numberline",NUMBERLINE,0}, |
||
6843 | {"obabel",OBABEL,0}, |
||
6844 | {"onclick",ONCLICK,0}, |
||
6845 | {"opacity",OPACITY,0}, |
||
6846 | {"parallel",PARALLEL,0}, |
||
6847 | {"path",POLYLINE,0}, |
||
6848 | {"patternfill",PATTERNFILL,0}, |
||
6849 | {"piechart",PIECHART,0}, |
||
6850 | {"pixels",PIXELS,0}, |
||
6851 | {"pixelsize",PIXELSIZE,0}, |
||
6852 | {"plot",CURVE,0}, |
||
6853 | {"plotstep",PLOTSTEPS,0}, |
||
6854 | {"plotsteps",PLOTSTEPS,0}, |
||
6855 | {"point",POINT,0}, |
||
6856 | {"pointer",CURSOR,0}, |
||
6857 | {"points",POINTS,0}, |
||
6858 | {"poly",POLY,0}, |
||
6859 | {"polygon",POLY,0}, |
||
6860 | {"polyline",POLYLINE,0}, |
||
6861 | {"popup",POPUP,0}, |
||
6862 | {"precision",MOUSE_PRECISION,0}, |
||
6863 | {"protractor",PROTRACTOR,0}, |
||
6864 | {"range",RANGE,0}, |
||
6865 | {"ranget",TRANGE,0}, |
||
6866 | {"rangex",XRANGE,0}, |
||
6867 | {"rangey",YRANGE,0}, |
||
6868 | {"rays",RAYS,0}, |
||
6869 | {"rect",RECT,0}, |
||
6870 | {"rectangle",RECT,0}, |
||
6871 | {"rects",RECTS,0}, |
||
6872 | {"replyformat",REPLYFORMAT,0}, |
||
6873 | {"reset",RESET,0}, |
||
6874 | {"resetoffset",RESETOFFSET,0}, |
||
6875 | {"rotate",ROTATE,0}, |
||
6876 | {"rotationcenter",ROTATION_CENTER,0}, |
||
6877 | {"roundrect",ROUNDRECT,0}, |
||
6878 | {"roundrectangle",ROUNDRECT,0}, |
||
6879 | {"roundrects",ROUNDRECTS,0}, |
||
6880 | {"ruler",RULER,0}, |
||
6881 | {"seg",SEGMENT,0}, |
||
6882 | {"segment",SEGMENT,0}, |
||
6883 | {"segments",SEGMENTS,0}, |
||
6884 | {"segs",SEGMENTS,0}, |
||
6885 | {"setlimits",SETLIMITS,0}, |
||
6886 | {"setpixel",SETPIXEL,0}, |
||
6887 | {"settile",FILLPATTERN,0}, |
||
6888 | {"sgraph",SGRAPH,0}, |
||
6889 | {"size",SIZE,0}, |
||
6890 | {"slider",SLIDER,0}, |
||
6891 | {"snaptofun",SNAPTOFUNCTION,0}, |
||
6892 | {"snaptofunction",SNAPTOFUNCTION,0}, |
||
6893 | {"snaptogrid",SNAPTOGRID,0}, |
||
6894 | {"snaptopoints",SNAPTOPOINTS,0}, |
||
6895 | {"square",SQUARE,0}, |
||
6896 | {"status",STATUS,0}, |
||
6897 | {"string",STRING,0}, |
||
6898 | {"stringup",STRINGUP,0}, |
||
6899 | {"strokecolor",STROKECOLOR,0}, |
||
6900 | {"strokecolors",MULTISTROKECOLORS,0}, |
||
18608 | bpr | 6901 | {"strokeopacity",STROKEOPACITY,0}, |
18589 | bpr | 6902 | {"style",STYLE,0}, |
6903 | {"text",FLY_TEXT,0}, |
||
6904 | {"textarea",TEXTAREA,0}, |
||
6905 | {"textfill",TEXTFILL,0}, |
||
6906 | {"textup",FLY_TEXTUP,0}, |
||
6907 | {"title",CENTERSTRING,0}, |
||
6908 | {"trace_jscurve",TRACE_JSCURVE,0}, |
||
6909 | {"trange",TRANGE,0}, |
||
6910 | {"translate",TRANSLATION,0}, |
||
6911 | {"translation",TRANSLATION,0}, |
||
6912 | {"transparent",OPACITY,0}, |
||
6913 | {"triangle",TRIANGLE,0}, |
||
6914 | {"triangles",TRIANGLES,0}, |
||
6915 | {"tsteps",PLOTSTEPS,0}, |
||
6916 | {"userboxplot",USERBOXPLOT,0}, |
||
6917 | {"userboxplotdata",USERBOXPLOT,0}, |
||
6918 | {"userdraw",USERDRAW,0}, |
||
6919 | {"userinput",USERINPUT,0}, |
||
6920 | {"userinput_function",USERINPUT_FUNCTION,0}, |
||
6921 | {"userinput_xy",USERINPUT_XY,0}, |
||
6922 | {"vector",ARROW,0}, |
||
6923 | {"vectors",ARROWS,0}, |
||
6924 | {"verticalline",VLINE,0}, |
||
6925 | {"verticallines",VLINES,0}, |
||
6926 | {"video",VIDEO,0}, |
||
6927 | {"vline",VLINE,0}, |
||
6928 | {"vlines",VLINES,0}, |
||
6929 | {"xaxis",X_AXIS_STRINGS,0}, |
||
6930 | {"xaxistext",X_AXIS_STRINGS,0}, |
||
6931 | {"xaxistextup",X_AXIS_STRINGS_UP,0}, |
||
6932 | {"xaxisup",X_AXIS_STRINGS_UP,0}, |
||
6933 | {"xerrorbars",XERRORBARS,0}, |
||
6934 | {"xlabel",XLABEL,0}, |
||
6935 | {"xlogbase",XLOGBASE,0}, |
||
6936 | {"xlogscale",XLOGSCALE,0}, |
||
6937 | {"xoffset",XOFFSET,0}, |
||
6938 | {"xrange",XRANGE,0}, |
||
6939 | {"xsnaptogrid",XSNAPTOGRID,0}, |
||
6940 | {"xunit",XUNIT,0}, |
||
6941 | {"xylogscale",XYLOGSCALE,0}, |
||
6942 | {"xyoffset",XYOFFSET,0}, |
||
6943 | {"yaxis",Y_AXIS_STRINGS,0}, |
||
6944 | {"yaxistext",Y_AXIS_STRINGS,0}, |
||
6945 | {"yerrorbars",YERRORBARS,0}, |
||
6946 | {"ylabel",YLABEL,0}, |
||
6947 | {"ylogbase",YLOGBASE,0}, |
||
6948 | {"ylogscale",YLOGSCALE,0}, |
||
6949 | {"yoffset",YOFFSET,0}, |
||
6950 | {"yrange",YRANGE,0}, |
||
6951 | {"ysnaptogrid",YSNAPTOGRID,0}, |
||
6952 | {"yunit",YUNIT,0}, |
||
6953 | {"zoom",ZOOM,0} |
||
6954 | }; |
||
7614 | schaersvoo | 6955 | |
18552 | bpr | 6956 | while(((c = getc(infile)) != EOF)&&(c!='\n')&&(c!=',')&&(c!='=')&&(c!='\r')&&(c!='\t')){ |
6957 | if( i == 0 && (c == ' ') ){ continue; /* white spaces or tabs allowed before first command identifier */ |
||
6958 | }else{ |
||
6959 | if( c == ' ' ){ |
||
6960 | break; |
||
6961 | }else{ |
||
6962 | temp[i] = c; |
||
6963 | if(i > MAX_INT - 2){canvas_error("command string too long !");} |
||
6964 | i++; |
||
6965 | } |
||
6966 | } |
||
6967 | if(temp[0] == '#'){ break; } |
||
6968 | } |
||
6969 | if (c == '\n' || c == '\r' || c == '\t' ){ line_number++; } |
||
6970 | if (c == EOF) {finished=1;return 0;} |
||
7614 | schaersvoo | 6971 | |
18552 | bpr | 6972 | temp[i]='\0'; |
6973 | if(strstr(temp,"dash") !=0 && strlen(temp) > 4 && strstr(temp,"dashtype") == 0 ){ |
||
6974 | /* 4/2024 adapt to Flydraw's dashing syntax for all objects with prefix "dash" */ |
||
6975 | use_dashed = TRUE;int idx=0;int p; |
||
6976 | for( p = 4; p < strlen(temp); p++){temp[idx] = temp[p];idx++;} |
||
6977 | input_type = (char*)my_newmem(idx); snprintf(input_type,idx+1,"%s",temp); |
||
6978 | }else{ |
||
6979 | input_type=(char*)my_newmem(strlen(temp)); |
||
6980 | snprintf(input_type,sizeof(temp),"%s",temp); |
||
6981 | } |
||
18572 | bpr | 6982 | /* fprintf(stdout,"input_type = %s no_reset = %d <br>",input_type,no_reset);*/ |
18589 | bpr | 6983 | |
6984 | left=0; right=sizeof(table)/sizeof(struct commande); |
||
6985 | while (left<right){ |
||
6986 | milieu = (left+right)/2; |
||
6987 | delta = strcmp(input_type, table[milieu].nom); |
||
6988 | if (delta == 0){ |
||
6989 | free(input_type); |
||
6990 | if (table[milieu].special==usefilled) use_filled=TRUE; |
||
6991 | if (table[milieu].special==usedashed) use_dashed=TRUE; |
||
6992 | return table[milieu].res; |
||
6993 | } |
||
6994 | if (delta<0) right=milieu; else left=milieu+1; |
||
18552 | bpr | 6995 | } |
6996 | free(input_type); |
||
18562 | bpr | 6997 | ungetc(c,infile); |
6998 | return 0; |
||
7614 | schaersvoo | 6999 | } |