@@ -70,27 +70,22 @@ var customLineHelp = function(ctx, pattern, points) {
7070};
7171
7272function drawLine(ctx,form) {
73− var points = Foreign.JavaScript.castListToJSArray(form[3][1]);
73+ var points = form[3][1];
7474 switch(form[1][0]) {
7575 case "Solid" : return solid(ctx,form[2],points);
7676 case "Dotted": return customLine([3,3],ctx,form[2],points);
7777 case "Dashed": return customLine([8,4],ctx,form[2],points);
78− case "Custom":
79− var pattern = Foreign.JavaScript.castListToJSArray(form[1][1]);
80− customLine(pattern,ctx,form[2],points);
78+ case "Custom": return customLine(form[1][1],ctx,form[2],points);
8179 }
8280};
8381
8482function drawShape(redo,ctx,shapeStyle,color,points) {
85− points = Foreign.JavaScript.castListToJSArray(points);
86− if (points.length > 0) points.push(points[0]);
8783 switch(shapeStyle[0]) {
8884 case "Filled": return filled(ctx,color,points);
8985 case "Outlined": return solid(ctx,color,points);
9086 case "Textured": return textured(redo,ctx,shapeStyle[1],points);
9187 case "CustomOutline":
92− var pattern = Foreign.JavaScript.castListToJSArray(shapeStyle[1]);
93− customLine(pattern,ctx,color,points);
88+ return customLine(shapeStyle[1],ctx,color,points);
9489 }
9590};
9691
@@ -209,6 +204,107 @@ function updateCollage(node,currs,nexts) {
209204 }
210205}
211206
212−return {collage:collage, updateCollage:updateCollage};
207+function style(clr,n,list) {
208+ return ["Tuple2",
209+ '<span style="font-size:100%;color:' + clr + ';">' + n + '</span>',
210+ list];
211+}
212+
213+function insideForm(point) { return function(form) {
214+ if (!inBoundsOf(point[1],point[2],form)) return false;
215+ var hw, hh;
216+ switch (form[4][0]) {
217+ case "FShape": return insideShape(point,form[1],form[2],form[3],form[4][3][1]);
218+ case "FLine": return false;
219+ case "FImage":
220+ hw = form[4][1] / 2;
221+ hh = form[4][2] / 2;
222+ break;
223+ case "FElement":
224+ hw = form[4][1][3] / 2;
225+ hh = form[4][1][4] / 2;
226+ break;
227+ }
228+ return insideShape(point,form[1],form[2],form[3],
229+ [ [null, hw, hh],
230+ [null,-hw, hh],
231+ [null,-hw,-hh],
232+ [null, hw,-hh],
233+ [null, hw, hh] ]);
234+ };
235+}
236+
237+function inBoundsOf(px,py,form) {
238+ if (form.length < 6) {
239+ var fx = form[3][1], fy = form[3][2];
240+ var radiusSquared = 0;
241+ var scale = form[2];
242+ switch (form[4][0]) {
243+ case "FShape":
244+ var points = form[4][3][1];
245+ for (var i = points.length; --i; ) {
246+ var p = points[i];
247+ radiusSquared = Math.max(radiusSquared, p[1]*p[1] + p[2]*p[2]);
248+ }
249+ radiusSquared *= scale * scale;
250+ break;
251+ case "FLine":
252+ break;
253+ case "FImage":
254+ var x = scale * form[4][1] / 2;
255+ var y = scale * form[4][2] / 2;
256+ radiusSquared = x*x + y*y;
257+ break;
258+ case "FElement":
259+ var x = scale * form[4][1][3] / 2;
260+ var y = scale * form[4][1][4] / 2;
261+ radiusSquared = x*x + y*y;
262+ break;
263+ }
264+ form.push(function(px,py) {
265+ var dx = px - fx;
266+ var dy = py - fy;
267+ return dx*dx + dy*dy < radiusSquared + 1;
268+ });
269+ }
270+ return form[5](px,py);
271+}
272+
273+function insideShape(point,theta,scale,pos,points) {
274+ var counter = 0;
275+ var list = ["Nil"];
276+ var p1,p2;
277+
278+ var x = (point[1] - pos[1]) / scale;
279+ var y = (point[2] - pos[2]) / scale;
280+ if (theta !== 0) {
281+ var angle = 2 * Math.PI * theta;
282+ var t = x === 0 ? (y > 0 ? Math.PI/2 : -Math.PI/2) - angle
283+ : (Math.atan(y/x) + (x > 0 ? 0 : Math.PI)) - angle;
284+ var r = Math.sqrt(x*x + y*y);
285+ x = r * Math.cos(t);
286+ y = r * Math.sin(t);
287+ }
288+
289+ if (points.length === 0) { return false; }
290+ p1 = points[0];
291+ for (var i = points.length - 1; i--; ) {
292+ p2 = points[i];
293+ var p1x = p1[1], p1y = p1[2], p2x = p2[1], p2y = p2[2];
294+
295+ if (p1y < p2y) {var ymin=p1y, ymax=p2y;} else {var ymin=p2y, ymax=p1y;}
296+ if (p1x < p2x) {var xmin=p1x, xmax=p2x;} else {var xmin=p2x, xmax=p1x;}
297+
298+ if (ymin < y && y <= ymax && x <= xmax) {
299+ if (x <= xmin || x <= ((y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x)) {
300+ ++counter;
301+ }
302+ }
303+ p1 = p2;
304+ }
305+ return (counter % 2) === 1;
306+}
307+
308+return {collage:collage, updateCollage:updateCollage, insideForm:insideForm};
213309
214310}();