diff --git a/docs/elements.html b/docs/elements.html deleted file mode 100755 index 22a46ef..0000000 --- a/docs/elements.html +++ /dev/null @@ -1,305 +0,0 @@ ---- -layout: page -title: Elements ---- -
-

Text

-

This is bold and this is strong. This is italic and this is emphasized. - This is superscript text and this is subscript text. - This is underlined and this is code: for (;;) { ... }. Finally, this is a link.

-
-
-

Heading with a Subtitle

-

Lorem ipsum dolor sit amet nullam id egestas urna aliquam

-
-

Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan varius montes viverra nibh in adipiscing blandit tempus accumsan.

-
-
Heading with a Subtitle
-

Lorem ipsum dolor sit amet nullam id egestas urna aliquam

-
-

Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan varius montes viverra nibh in adipiscing blandit tempus accumsan.

-
-

Heading Level 2

-

Heading Level 3

-

Heading Level 4

-
Heading Level 5
-
Heading Level 6
-
-
Blockquote
-
Fringilla nisl. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan faucibus. Vestibulum ante ipsum primis in faucibus lorem ipsum dolor sit amet nullam adipiscing eu felis.
-
Preformatted
-
i = 0;
-
-while (!deck.isInOrder()) {
-  print 'Iteration ' + i;
-  deck.shuffle();
-  i++;
-}
-
-print 'It took ' + i + ' iterations to sort the deck.';
-
-
-

Lists

-
-
-
Unordered
-
    -
  • Dolor pulvinar etiam.
  • -
  • Sagittis adipiscing.
  • -
  • Felis enim feugiat.
  • -
-
Alternate
-
    -
  • Dolor pulvinar etiam.
  • -
  • Sagittis adipiscing.
  • -
  • Felis enim feugiat.
  • -
-
-
-
Ordered
-
    -
  1. Dolor pulvinar etiam.
  2. -
  3. Etiam vel felis viverra.
  4. -
  5. Felis enim feugiat.
  6. -
  7. Dolor pulvinar etiam.
  8. -
  9. Etiam vel felis lorem.
  10. -
  11. Felis enim et feugiat.
  12. -
-
Icons
- -
-
-
Actions
-
-
- - - - -
-
- - -
-
-
-
-

Table

-
Default
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionPrice
Item OneAnte turpis integer aliquet porttitor.29.99
Item TwoVis ac commodo adipiscing arcu aliquet.19.99
Item Three Morbi faucibus arcu accumsan lorem.29.99
Item FourVitae integer tempus condimentum.19.99
Item FiveAnte turpis integer aliquet porttitor.29.99
100.00
-
-
Alternate
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionPrice
Item OneAnte turpis integer aliquet porttitor.29.99
Item TwoVis ac commodo adipiscing arcu aliquet.19.99
Item Three Morbi faucibus arcu accumsan lorem.29.99
Item FourVitae integer tempus condimentum.19.99
Item FiveAnte turpis integer aliquet porttitor.29.99
100.00
-
-
-
-

Buttons

- - - - - - -
-
-

Form

-
-
-
- -
-
- -
-
-
- -
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
-
    -
  • -
  • -
-
-
-
-
-
-

Image

-
Fit
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Left & Right
-

Morbi mattis mi consectetur tortor elementum, varius pellentesque velit convallis. Aenean tincidunt lectus auctor mauris maximus, ac scelerisque ipsum tempor. Duis vulputate ex et ex tincidunt, quis lacinia velit aliquet. Duis non efficitur nisi, id malesuada justo. Maecenas sagittis felis ac sagittis semper. Curabitur purus leo, tempus sed finibus eget, fringilla quis risus. Maecenas et lorem quis sem varius sagittis et a est. Maecenas iaculis iaculis sem. Donec vel dolor at arcu tincidunt bibendum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Fusce ut aliquet justo. Donec id neque ipsum. Integer eget ultricies odio. Nam vel ex a orci fringilla tincidunt. Aliquam eleifend ligula non velit accumsan cursus. Etiam ut gravida sapien. Morbi mattis mi consectetur tortor elementum, varius pellentesque velit convallis. Aenean tincidunt lectus auctor mauris maximus, ac scelerisque ipsum tempor. Duis vulputate ex et ex tincidunt, quis lacinia velit aliquet. Duis non efficitur nisi, id malesuada justo. Maecenas sagittis felis ac sagittis semper. Curabitur purus leo, tempus sed finibus eget, fringilla quis risus. Maecenas et lorem quis sem varius sagittis et a est. Maecenas iaculis iaculis sem. Donec vel dolor at arcu tincidunt bibendum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Fusce ut aliquet justo. Donec id neque ipsum. Integer eget ultricies odio. Nam vel ex a orci fringilla tincidunt. Aliquam eleifend ligula non velit accumsan cursus. Etiam ut gravida sapien.

-

Vestibulum ultrices risus velit, sit amet blandit massa auctor sit amet. Sed eu lectus sem. Phasellus in odio at ipsum porttitor mollis id vel diam. Praesent sit amet posuere risus, eu faucibus lectus. Vivamus ex ligula, tempus pulvinar ipsum in, auctor porta quam. Proin nec dui cursus, posuere dui eget interdum. Fusce lectus magna, sagittis at facilisis vitae, pellentesque at etiam. Quisque posuere leo quis sem commodo, vel scelerisque nisi scelerisque. Suspendisse id quam vel tortor tincidunt suscipit. Nullam auctor orci eu dolor consectetur, interdum ullamcorper ante tincidunt. Mauris felis nec felis elementum varius. Nam sapien ante, varius in pulvinar vitae, rhoncus id massa. Donec varius ex in mauris ornare, eget euismod urna egestas. Etiam lacinia tempor ipsum, sodales porttitor justo. Aliquam dolor quam, semper in tortor eu, volutpat efficitur quam. Fusce nec fermentum nisl. Aenean erat diam, tempus aliquet erat. Etiam iaculis nulla ipsum, et pharetra libero rhoncus ut. Phasellus rutrum cursus velit, eget condimentum nunc blandit vel. In at pulvinar lectus. Morbi diam ante, vulputate et imperdiet eget, fermentum non dolor. Ut eleifend sagittis tincidunt. Sed viverra commodo mi, ac rhoncus justo. Duis neque ligula, elementum ut enim vel, posuere finibus justo. Vivamus facilisis maximus nibh quis pulvinar. Quisque hendrerit in ipsum id tellus facilisis fermentum. Proin mauris dui.

-
diff --git a/docs/generic.html b/docs/generic.html deleted file mode 100755 index 8b1a488..0000000 --- a/docs/generic.html +++ /dev/null @@ -1,11 +0,0 @@ ---- -layout: page -title: Generic ---- -

Lorem ipsum dolor

-

Morbi mattis mi consectetur tortor elementum, varius pellentesque velit convallis. Aenean tincidunt lectus auctor mauris maximus, ac scelerisque ipsum tempor. Duis vulputate ex et ex tincidunt, quis lacinia velit aliquet. Duis non efficitur nisi, id malesuada justo. Maecenas sagittis felis ac sagittis semper. Curabitur purus leo, tempus sed finibus eget, fringilla quis risus. Maecenas et lorem quis sem varius sagittis et a est. Maecenas iaculis iaculis sem. Donec vel dolor at arcu tincidunt bibendum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Fusce ut aliquet justo. Donec id neque ipsum. Integer eget ultricies odio. Nam vel ex a orci fringilla tincidunt. Aliquam eleifend ligula non velit accumsan cursus. Etiam ut gravida sapien.

-

Vestibulum ultrices risus velit, sit amet blandit massa auctor sit amet. Sed eu lectus sem. Phasellus in odio at ipsum porttitor mollis id vel diam. Praesent sit amet posuere risus, eu faucibus lectus. Vivamus ex ligula, tempus pulvinar ipsum in, auctor porta quam. Proin nec dui cursus, posuere dui eget interdum. Fusce lectus magna, sagittis at facilisis vitae, pellentesque at etiam. Quisque posuere leo quis sem commodo, vel scelerisque nisi scelerisque. Suspendisse id quam vel tortor tincidunt suscipit. Nullam auctor orci eu dolor consectetur, interdum ullamcorper ante tincidunt. Mauris felis nec felis elementum varius.

-
-

Feugiat aliquam

-

Nam sapien ante, varius in pulvinar vitae, rhoncus id massa. Donec varius ex in mauris ornare, eget euismod urna egestas. Etiam lacinia tempor ipsum, sodales porttitor justo. Aliquam dolor quam, semper in tortor eu, volutpat efficitur quam. Fusce nec fermentum nisl. Aenean erat diam, tempus aliquet erat.

-

Etiam iaculis nulla ipsum, et pharetra libero rhoncus ut. Phasellus rutrum cursus velit, eget condimentum nunc blandit vel. In at pulvinar lectus. Morbi diam ante, vulputate et imperdiet eget, fermentum non dolor. Ut eleifend sagittis tincidunt. Sed viverra commodo mi, ac rhoncus justo. Duis neque ligula, elementum ut enim vel, posuere finibus justo. Vivamus facilisis maximus nibh quis pulvinar. Quisque hendrerit in ipsum id tellus facilisis fermentum. Proin mauris dui, at vestibulum sit amet, auctor bibendum neque.

diff --git a/graficos/data/baleares.png b/graficos/data/baleares.png new file mode 100644 index 0000000..aa19e04 Binary files /dev/null and b/graficos/data/baleares.png differ diff --git a/graficos/data/capa-0.png b/graficos/data/capa-0.png new file mode 100644 index 0000000..801ebbd Binary files /dev/null and b/graficos/data/capa-0.png differ diff --git a/graficos/data/capa-1.png b/graficos/data/capa-1.png new file mode 100644 index 0000000..1ed7eb7 Binary files /dev/null and b/graficos/data/capa-1.png differ diff --git a/graficos/data/capa-10.png b/graficos/data/capa-10.png new file mode 100644 index 0000000..de0b838 Binary files /dev/null and b/graficos/data/capa-10.png differ diff --git a/graficos/data/capa-2.png b/graficos/data/capa-2.png new file mode 100644 index 0000000..9f3bf39 Binary files /dev/null and b/graficos/data/capa-2.png differ diff --git a/graficos/data/capa-3.png b/graficos/data/capa-3.png new file mode 100644 index 0000000..de0b838 Binary files /dev/null and b/graficos/data/capa-3.png differ diff --git a/graficos/data/capa-4.png b/graficos/data/capa-4.png new file mode 100644 index 0000000..c532612 Binary files /dev/null and b/graficos/data/capa-4.png differ diff --git a/graficos/data/capa-5.png b/graficos/data/capa-5.png new file mode 100644 index 0000000..9aadb93 Binary files /dev/null and b/graficos/data/capa-5.png differ diff --git a/graficos/data/capa-6.png b/graficos/data/capa-6.png new file mode 100644 index 0000000..c89afb1 Binary files /dev/null and b/graficos/data/capa-6.png differ diff --git a/graficos/data/capa-7.png b/graficos/data/capa-7.png new file mode 100644 index 0000000..b3f3031 Binary files /dev/null and b/graficos/data/capa-7.png differ diff --git a/graficos/data/capa-8.png b/graficos/data/capa-8.png new file mode 100644 index 0000000..9d2adba Binary files /dev/null and b/graficos/data/capa-8.png differ diff --git a/graficos/data/capa-9.png b/graficos/data/capa-9.png new file mode 100644 index 0000000..ff66ce3 Binary files /dev/null and b/graficos/data/capa-9.png differ diff --git a/graficos/data/capa-PGC-0.png b/graficos/data/capa-PGC-0.png new file mode 100644 index 0000000..2043ede Binary files /dev/null and b/graficos/data/capa-PGC-0.png differ diff --git a/graficos/data/capa-PGC-1.png b/graficos/data/capa-PGC-1.png new file mode 100644 index 0000000..154f4f6 Binary files /dev/null and b/graficos/data/capa-PGC-1.png differ diff --git a/graficos/data/capa-PGC-10.png b/graficos/data/capa-PGC-10.png new file mode 100644 index 0000000..eb9d5b9 Binary files /dev/null and b/graficos/data/capa-PGC-10.png differ diff --git a/graficos/data/capa-PGC-2.png b/graficos/data/capa-PGC-2.png new file mode 100644 index 0000000..00796b5 Binary files /dev/null and b/graficos/data/capa-PGC-2.png differ diff --git a/graficos/data/capa-PGC-3.png b/graficos/data/capa-PGC-3.png new file mode 100644 index 0000000..6042dc4 Binary files /dev/null and b/graficos/data/capa-PGC-3.png differ diff --git a/graficos/data/capa-PGC-4.png b/graficos/data/capa-PGC-4.png new file mode 100644 index 0000000..7a819bd Binary files /dev/null and b/graficos/data/capa-PGC-4.png differ diff --git a/graficos/data/capa-PGC-5.png b/graficos/data/capa-PGC-5.png new file mode 100644 index 0000000..113fc4f Binary files /dev/null and b/graficos/data/capa-PGC-5.png differ diff --git a/graficos/data/capa-PGC-6.png b/graficos/data/capa-PGC-6.png new file mode 100644 index 0000000..cff3082 Binary files /dev/null and b/graficos/data/capa-PGC-6.png differ diff --git a/graficos/data/capa-PGC-7.png b/graficos/data/capa-PGC-7.png new file mode 100644 index 0000000..2280d1f Binary files /dev/null and b/graficos/data/capa-PGC-7.png differ diff --git a/graficos/data/capa-PGC-8.png b/graficos/data/capa-PGC-8.png new file mode 100644 index 0000000..18b939b Binary files /dev/null and b/graficos/data/capa-PGC-8.png differ diff --git a/graficos/data/capa-PGC-9.png b/graficos/data/capa-PGC-9.png new file mode 100644 index 0000000..2761ea9 Binary files /dev/null and b/graficos/data/capa-PGC-9.png differ diff --git a/graficos/data/cmap-cuencas.png b/graficos/data/cmap-cuencas.png new file mode 100644 index 0000000..010b4af Binary files /dev/null and b/graficos/data/cmap-cuencas.png differ diff --git a/graficos/data/cuencas.png b/graficos/data/cuencas.png new file mode 100644 index 0000000..faef82f Binary files /dev/null and b/graficos/data/cuencas.png differ diff --git a/graficos/data/duero.png b/graficos/data/duero.png new file mode 100644 index 0000000..63e50f3 Binary files /dev/null and b/graficos/data/duero.png differ diff --git a/graficos/data/ebro.png b/graficos/data/ebro.png new file mode 100644 index 0000000..33d4d38 Binary files /dev/null and b/graficos/data/ebro.png differ diff --git a/graficos/data/guadalquivir.png b/graficos/data/guadalquivir.png new file mode 100644 index 0000000..6ad7965 Binary files /dev/null and b/graficos/data/guadalquivir.png differ diff --git a/graficos/data/guadiana.png b/graficos/data/guadiana.png new file mode 100644 index 0000000..6df4f75 Binary files /dev/null and b/graficos/data/guadiana.png differ diff --git a/graficos/data/harvester_1046427_cc.png b/graficos/data/harvester_1046427_cc.png new file mode 100644 index 0000000..25e6207 Binary files /dev/null and b/graficos/data/harvester_1046427_cc.png differ diff --git a/graficos/data/harvester_1046427_cc_p.png b/graficos/data/harvester_1046427_cc_p.png new file mode 100644 index 0000000..21a3b6e Binary files /dev/null and b/graficos/data/harvester_1046427_cc_p.png differ diff --git a/graficos/data/jucar.png b/graficos/data/jucar.png new file mode 100644 index 0000000..55d34d8 Binary files /dev/null and b/graficos/data/jucar.png differ diff --git a/graficos/data/norte.png b/graficos/data/norte.png new file mode 100644 index 0000000..65a33d8 Binary files /dev/null and b/graficos/data/norte.png differ diff --git a/graficos/data/pirineo.png b/graficos/data/pirineo.png new file mode 100644 index 0000000..01871c0 Binary files /dev/null and b/graficos/data/pirineo.png differ diff --git a/graficos/data/segura.png b/graficos/data/segura.png new file mode 100644 index 0000000..34e0954 Binary files /dev/null and b/graficos/data/segura.png differ diff --git a/graficos/data/sur.png b/graficos/data/sur.png new file mode 100644 index 0000000..a7eca00 Binary files /dev/null and b/graficos/data/sur.png differ diff --git a/graficos/data/tajo.png b/graficos/data/tajo.png new file mode 100644 index 0000000..89ba959 Binary files /dev/null and b/graficos/data/tajo.png differ diff --git a/graficos/data/tractor_792349_cc.png b/graficos/data/tractor_792349_cc.png new file mode 100644 index 0000000..5577a2e Binary files /dev/null and b/graficos/data/tractor_792349_cc.png differ diff --git a/graficos/data/tractor_792349_cc_p.png b/graficos/data/tractor_792349_cc_p.png new file mode 100644 index 0000000..e87df14 Binary files /dev/null and b/graficos/data/tractor_792349_cc_p.png differ diff --git a/graficos/expropiacion.html b/graficos/expropiacion.html new file mode 100644 index 0000000..e35b440 --- /dev/null +++ b/graficos/expropiacion.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/graficos/expropiacion.js b/graficos/expropiacion.js new file mode 100644 index 0000000..58d6953 --- /dev/null +++ b/graficos/expropiacion.js @@ -0,0 +1,64 @@ +var exceso, reserva, exceptuadas; +var nombres; +var plot; + +function setup() { + createCanvas(800,519); + nombres = new Array("Norte","Duero","Ebro","Pirineo","Jucar","Tajo","Guadiana","Guadalquivir","Sur", "Segura", "Islas"); + exceso = new Array(15267,35628,136465,3466,19615,64179,81809,148193,13326,35075,3235); + reserva = new Array(12251,62730,131128,24433,54545,68854,82052,140453,20980,131042,5985); + exceptuadas = new Array(7094,31194,128457,3289,15734,39460,21419,68830,23782,68386,15675); + + var pointSizes = []; + var points = []; + + for (var n = 0; n < nombres.length; n++) { + points[n] = new GPoint(exceso[n], exceptuadas[n], nombres[n]); + pointSizes[n] = map(reserva[n],5000,141000,5,100); + } + + // Creamos el plot + plot = new GPlot(this); + plot.setDim(width-230, height-100); + plot.setTitleText("Tierras en exceso, reserva y exceptuadas por cuenca hidrografica segun PGC"); + plot.getXAxis().setAxisLabelText("Tierras en exceso (Has)"); + plot.getYAxis().setAxisLabelText("Tierras exceptuadas (Has)"); + plot.setPoints(points); + plot.setPointSizes(pointSizes); + plot.setPointColor(color(255,0,0,50)); + plot.setLineColor(color(0)); + plot.setLabelBgColor(color(255,0)); +} + + +function draw() { + background(255); + + // Draw the plot + plot.beginDraw(); + plot.drawBox(); + plot.drawXAxis(); + plot.drawYAxis(); + plot.drawTitle(); + plot.drawGridLines(GPlot.BOTH); + plot.drawPoints(); + plot.drawLabels(); + plot.drawAllLabels(); + plot.endDraw(); + + textFont("Helvetica"); + textSize(11); + fill(0); + textAlign(LEFT); + text("Tierras en reserva (Has)", 660, 330); + textAlign(CENTER); + stroke(100); + noFill(); + ellipse(720, 390, 100, 100); + fill(0); + text("140000", 720, 390); + noFill(); + ellipse(720, 455, 10, 10); + fill(0); + text("14000", 720, 475); +} diff --git a/graficos/grafica-0.1.0-mod.js b/graficos/grafica-0.1.0-mod.js new file mode 100644 index 0000000..032f690 --- /dev/null +++ b/graficos/grafica-0.1.0-mod.js @@ -0,0 +1,5444 @@ +/* + * Point class. A GPoint is composed of two coordinates (x, y) and a text label + */ +function GPoint() { + var x, y, label; + + if (arguments.length === 3) { + x = arguments[0]; + y = arguments[1]; + label = arguments[2]; + } else if (arguments.length === 2 && arguments[0] instanceof p5.Vector) { + x = arguments[0].x; + y = arguments[0].y; + label = arguments[1]; + } else if (arguments.length === 2) { + x = arguments[0]; + y = arguments[1]; + label = ""; + } else if (arguments.length === 1 && arguments[0] instanceof GPoint) { + x = arguments[0].getX(); + y = arguments[0].getY(); + label = arguments[0].getLabel(); + } else if (arguments.length === 1 && arguments[0] instanceof p5.Vector) { + x = arguments[0].x; + y = arguments[0].y; + label = ""; + } else if (arguments.length === 0) { + x = 0; + y = 0; + label = ""; + } else { + throw new Error("GPoint constructor: signature not supported"); + } + + this.x = x; + this.y = y; + this.label = label; + this.valid = this.isValidNumber(this.x) && this.isValidNumber(this.y); +} + +GPoint.prototype.isValidNumber = function(number) { + return !isNaN(number) && isFinite(number); +}; + +GPoint.prototype.set = function() { + var x, y, label; + + if (arguments.length === 3) { + x = arguments[0]; + y = arguments[1]; + label = arguments[2]; + } else if (arguments.length === 2 && arguments[0] instanceof p5.Vector) { + x = arguments[0].x; + y = arguments[0].y; + label = arguments[1]; + } else if (arguments.length === 2) { + x = arguments[0]; + y = arguments[1]; + label = ""; + } else if (arguments.length === 1 && arguments[0] instanceof GPoint) { + x = arguments[0].getX(); + y = arguments[0].getY(); + label = arguments[0].getLabel(); + } else if (arguments.length === 1 && arguments[0] instanceof p5.Vector) { + x = arguments[0].x; + y = arguments[0].y; + label = ""; + } else { + throw new Error("GPoint.set(): signature not supported"); + } + + this.x = x; + this.y = y; + this.label = label; + this.valid = this.isValidNumber(this.x) && this.isValidNumber(this.y); +}; + +GPoint.prototype.setX = function(x) { + this.x = x; + this.valid = this.isValidNumber(this.x) && this.isValidNumber(this.y); +}; + +GPoint.prototype.setY = function(y) { + this.y = y; + this.valid = this.isValidNumber(this.x) && this.isValidNumber(this.y); +}; + +GPoint.prototype.setLabel = function(label) { + this.label = label; +}; + +GPoint.prototype.setXY = function() { + var x, y; + + if (arguments.length === 2) { + x = arguments[0]; + y = arguments[1]; + } else if (arguments.length === 1 && arguments[0] instanceof GPoint) { + x = arguments[0].getX(); + y = arguments[0].getY(); + } else if (arguments.length === 1 && arguments[0] instanceof p5.Vector) { + x = arguments[0].x; + y = arguments[0].y; + } else { + throw new Error("GPoint.setXY(): signature not supported"); + } + + this.x = x; + this.y = y; + this.valid = this.isValidNumber(this.x) && this.isValidNumber(this.y); +}; + +GPoint.prototype.getX = function() { + return this.x; +}; + +GPoint.prototype.getY = function() { + return this.y; +}; + +GPoint.prototype.getLabel = function() { + return this.label; +}; + +GPoint.prototype.getValid = function() { + return this.valid; +}; + +GPoint.prototype.isValid = function() { + return this.valid; +}; +/* + * Title class. + */ +function GTitle(parent, dim) { + // The parent processing object + this.parent = parent; + + // General properties + this.dim = dim.slice(); + this.relativePos = 0.5; + this.plotPos = this.relativePos * this.dim[0]; + this.offset = 10; + + // Text properties + this.text = ""; + this.textAlignment = this.parent.CENTER; + this.fontName = "Helvetica"; + this.fontColor = this.parent.color(100); + this.fontStyle = this.parent.BOLD; + this.fontSize = 13; +} + +GTitle.prototype.draw = function() { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textStyle(this.fontStyle); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + this.parent.textAlign(this.textAlignment, this.parent.BOTTOM); + this.parent.text(this.text, this.plotPos, -this.offset - this.dim[1]); + + // There seems to be a bug in p5.js + this.parent.textStyle(this.parent.NORMAL); + this.parent.pop(); +}; + +GTitle.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GTitle.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + this.dim[0] = xDim; + this.dim[1] = yDim; + this.plotPos = this.relativePos * this.dim[0]; + } +}; + +GTitle.prototype.setRelativePos = function(relativePos) { + this.relativePos = relativePos; + this.plotPos = this.relativePos * this.dim[0]; +}; + +GTitle.prototype.setOffset = function(offset) { + this.offset = offset; +}; + +GTitle.prototype.setText = function(text) { + this.text = text; +}; + +GTitle.prototype.setTextAlignment = function(textAlignment) { + if (textAlignment === this.parent.CENTER || textAlignment === this.parent.LEFT || textAlignment === this.parent.RIGHT) { + this.textAlignment = textAlignment; + } +}; + +GTitle.prototype.setFontName = function(fontName) { + this.fontName = fontName; +}; + +GTitle.prototype.setFontColor = function(fontColor) { + this.fontColor = fontColor; +}; + +GTitle.prototype.setFontStyle = function(fontStyle) { + this.fontStyle = fontStyle; +}; + +GTitle.prototype.setFontSize = function(fontSize) { + if (fontSize > 0) { + this.fontSize = fontSize; + } +}; + +GTitle.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + if (fontSize > 0) { + this.fontName = fontName; + this.fontColor = fontColor; + this.fontSize = fontSize; + } +}; +/* + * Axis label class. + */ +function GAxisLabel(parent, type, dim) { + // The parent processing object + this.parent = parent; + + // General properties + this.type = (type === this.parent.BOTTOM || type === this.parent.TOP || type === this.parent.LEFT || type === this.parent.RIGHT) ? type : this.parent.BOTTOM; + this.dim = dim.slice(); + this.relativePos = 0.5; + this.plotPos = (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) ? this.relativePos * this.dim[0] : -this.relativePos * this.dim[1]; + this.offset = 35; + this.rotate = (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) ? false : true; + + // Text properties + this.text = ""; + this.textAlignment = this.parent.CENTER; + this.fontName = "Helvetica"; + this.fontColor = this.parent.color(0); + this.fontSize = 13; +} + +GAxisLabel.prototype.draw = function() { + switch (this.type) { + case this.parent.BOTTOM: + this.drawAsXLabel(); + break; + case this.parent.LEFT: + this.drawAsYLabel(); + break; + case this.parent.TOP: + this.drawAsTopLabel(); + break; + case this.parent.RIGHT: + this.drawAsRightLabel(); + break; + } +}; + +GAxisLabel.prototype.drawAsXLabel = function() { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotate) { + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + this.parent.translate(this.plotPos, this.offset); + this.parent.rotate(-0.5 * Math.PI); + this.parent.text(this.text, 0, 0); + } else { + this.parent.textAlign(this.textAlignment, this.parent.TOP); + this.parent.text(this.text, this.plotPos, this.offset); + } + + this.parent.pop(); +}; + +GAxisLabel.prototype.drawAsYLabel = function() { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotate) { + this.parent.textAlign(this.textAlignment, this.parent.BOTTOM); + this.parent.translate(-this.offset, this.plotPos); + this.parent.rotate(-0.5 * Math.PI); + this.parent.text(this.text, 0, 0); + } else { + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + this.parent.text(this.text, -this.offset, this.plotPos); + } + + this.parent.pop(); +}; + +GAxisLabel.prototype.drawAsTopLabel = function() { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotate) { + this.parent.textAlign(this.parent.LEFT, this.parent.CENTER); + this.parent.translate(this.plotPos, -this.offset - this.dim[1]); + this.parent.rotate(-0.5 * Math.PI); + this.parent.text(this.text, 0, 0); + } else { + this.parent.textAlign(this.textAlignment, this.parent.BOTTOM); + this.parent.text(this.text, this.plotPos, -this.offset - this.dim[1]); + } + + this.parent.pop(); +}; + +GAxisLabel.prototype.drawAsRightLabel = function() { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotate) { + this.parent.textAlign(this.textAlignment, this.parent.TOP); + this.parent.translate(this.offset + this.dim[0], this.plotPos); + this.parent.rotate(-0.5 * Math.PI); + this.parent.text(this.text, 0, 0); + } else { + this.parent.textAlign(this.parent.LEFT, this.parent.CENTER); + this.parent.text(this.text, this.offset + this.dim[0], this.plotPos); + } + + this.parent.pop(); +}; + +GAxisLabel.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GAxisLabel.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + this.dim[0] = xDim; + this.dim[1] = yDim; + this.plotPos = (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) ? this.relativePos * this.dim[0] : -this.relativePos * this.dim[1]; + } +}; + +GAxisLabel.prototype.setRelativePos = function(relativePos) { + this.relativePos = relativePos; + this.plotPos = (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) ? this.relativePos * this.dim[0] : -this.relativePos * this.dim[1]; +}; + +GAxisLabel.prototype.setOffset = function(offset) { + this.offset = offset; +}; + +GAxisLabel.prototype.setRotate = function(rotate) { + this.rotate = rotate; +}; + +GAxisLabel.prototype.setText = function(text) { + this.text = text; +}; + +GAxisLabel.prototype.setTextAlignment = function(textAlignment) { + if (textAlignment === this.parent.CENTER || textAlignment === this.parent.LEFT || textAlignment === this.parent.RIGHT) { + this.textAlignment = textAlignment; + } +}; + +GAxisLabel.prototype.setFontName = function(fontName) { + this.fontName = fontName; +}; + +GAxisLabel.prototype.setFontColor = function(fontColor) { + this.fontColor = fontColor; +}; + +GAxisLabel.prototype.setFontSize = function(fontSize) { + if (fontSize > 0) { + this.fontSize = fontSize; + } +}; + +GAxisLabel.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + if (fontSize > 0) { + this.fontName = fontName; + this.fontColor = fontColor; + this.fontSize = fontSize; + } +}; +/* + * Axis class. + */ +function GAxis(parent, type, dim, lim, log) { + // The parent processing object + this.parent = parent; + + // General properties + this.type = (type === this.parent.BOTTOM || type === this.parent.TOP || type === this.parent.LEFT || type === this.parent.RIGHT) ? type : this.parent.BOTTOM; + this.dim = dim.slice(); + this.lim = lim.slice(); + this.log = log; + + // Do some sanity checks + if (this.log && (this.lim[0] <= 0 || this.lim[1] <= 0)) { + console.log("The limits are negative. This is not allowed in logarithmic scale."); + console.log("Will set them to (0.1, 10)"); + + if (this.lim[1] > this.lim[0]) { + this.lim[0] = 0.1; + this.lim[1] = 10; + } else { + this.lim[0] = 10; + this.lim[1] = 0.1; + } + } + + // Format properties + this.offset = 5; + this.lineColor = this.parent.color(0); + this.lineWidth = 1; + + // Ticks properties + this.nTicks = 5; + this.ticksSeparation = -1; + this.ticks = []; + this.plotTicks = []; + this.ticksInside = []; + this.tickLabels = []; + this.fixedTicks = false; + this.tickLength = 3; + this.smallTickLength = 2; + this.expTickLabels = false; + this.rotateTickLabels = (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) ? false : true; + this.drawTickLabels = (this.type === this.parent.BOTTOM || this.type === this.parent.LEFT) ? true : false; + this.tickLabelOffset = 7; + this.ticksPrecision = undefined; + + // Label properties + this.lab = new GAxisLabel(this.parent, this.type, this.dim); + this.drawAxisLabel = true; + + // Text properties + this.fontName = "Helvetica"; + this.fontColor = this.parent.color(0); + this.fontSize = 11; + + // Update the arrays + this.updateTicks(); + this.updatePlotTicks(); + this.updateTicksInside(); + this.updateTickLabels(); +} + +GAxis.prototype.obtainSigDigits = function(number) { + return Math.round(-Math.log(0.5 * Math.abs(number)) / Math.LN10); +}; + +GAxis.prototype.roundPlus = function(number, sigDigits) { + // Old way of doing it + // var bd = new BigDecimal(number); + // roundedNumber = parseFloat(bd.setScale(sigDigits, RoundingMode.HALF_UP()).longValue().toFixed(sigDigits)); + + number = Math.round(number * Math.pow(10, sigDigits)) / Math.pow(10, sigDigits); + + if (sigDigits <= 0) { + number = Math.round(number); + } + + return number; +}; + +GAxis.prototype.adaptSize = function(a, n) { + if (n < a.length) { + a.splice(n, Number.MAX_VALUE); + } +}; + +GAxis.prototype.updateTicks = function() { + if (this.log) { + this.obtainLogarithmicTicks(); + } else { + this.obtainLinearTicks(); + } +}; + +GAxis.prototype.obtainLogarithmicTicks = function() { + // Get the exponents of the first and last ticks in increasing order + var firstExp, lastExp; + + if (this.lim[1] > this.lim[0]) { + firstExp = Math.floor(Math.log(this.lim[0]) / Math.LN10); + lastExp = Math.ceil(Math.log(this.lim[1]) / Math.LN10); + } else { + firstExp = Math.floor(Math.log(this.lim[1]) / Math.LN10); + lastExp = Math.ceil(Math.log(this.lim[0]) / Math.LN10); + } + + // Calculate the ticks + var n = (lastExp - firstExp) * 9 + 1; + this.adaptSize(this.ticks, n); + + for (var exp = firstExp; exp < lastExp; exp++) { + var base = this.roundPlus(Math.exp(exp * Math.LN10), -exp); + + for (var i = 0; i < 9; i++) { + this.ticks[(exp - firstExp) * 9 + i] = (i + 1) * base; + } + + } + + this.ticks[this.ticks.length - 1] = this.roundPlus(Math.exp(lastExp * Math.LN10), -exp); + + // Change the ticks order if necessary + if (this.lim[1] < this.lim[0]) { + this.ticks.reverse(); + } +}; + +GAxis.prototype.obtainLinearTicks = function() { + // Obtain the required precision for the ticks + var step = 0; + var nSteps = 0; + var sigDigits = 0; + + if (this.ticksSeparation > 0) { + step = (this.lim[1] > this.lim[0]) ? this.ticksSeparation : -this.ticksSeparation; + sigDigits = this.obtainSigDigits(step); + + while (this.roundPlus(step, sigDigits) - step !== 0) { + sigDigits++; + } + + nSteps = Math.floor((this.lim[1] - this.lim[0]) / step); + } else if (this.nTicks > 0) { + step = (this.lim[1] - this.lim[0]) / this.nTicks; + sigDigits = this.obtainSigDigits(step); + step = this.roundPlus(step, sigDigits); + + if (step === 0 || Math.abs(step) > Math.abs(this.lim[1] - this.lim[0])) { + sigDigits++; + step = this.roundPlus((this.lim[1] - this.lim[0]) / this.nTicks, sigDigits); + } + + nSteps = Math.floor((this.lim[1] - this.lim[0]) / step); + } + + // Calculate the linear ticks + if (nSteps > 0) { + // Obtain the first tick + var firstTick = this.lim[0] + ((this.lim[1] - this.lim[0]) - nSteps * step) / 2; + + // Subtract some steps to be sure we have all + firstTick = this.roundPlus(firstTick - 2 * step, sigDigits); + + while ((this.lim[1] - firstTick) * (this.lim[0] - firstTick) > 0) { + firstTick = this.roundPlus(firstTick + step, sigDigits); + } + + // Calculate the rest of the ticks + var n = Math.floor(Math.abs((this.lim[1] - firstTick) / step)) + 1; + this.adaptSize(this.ticks, n); + this.ticks[0] = firstTick; + + for (var i = 1; i < n; i++) { + this.ticks[i] = this.roundPlus(this.ticks[i - 1] + step, sigDigits); + } + + // Save the ticks precision + this.ticksPrecision = sigDigits; + } else { + this.ticks = []; + } +}; + +GAxis.prototype.updatePlotTicks = function() { + var scaleFactor, i; + var n = this.ticks.length; + this.adaptSize(this.plotTicks, n); + + if (this.log) { + if (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) { + scaleFactor = this.dim[0] / Math.log(this.lim[1] / this.lim[0]); + } else { + scaleFactor = -this.dim[1] / Math.log(this.lim[1] / this.lim[0]); + } + + for ( i = 0; i < n; i++) { + this.plotTicks[i] = Math.log(this.ticks[i] / this.lim[0]) * scaleFactor; + } + } else { + if (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) { + scaleFactor = this.dim[0] / (this.lim[1] - this.lim[0]); + } else { + scaleFactor = -this.dim[1] / (this.lim[1] - this.lim[0]); + } + + for ( i = 0; i < n; i++) { + this.plotTicks[i] = (this.ticks[i] - this.lim[0]) * scaleFactor; + } + } +}; + +GAxis.prototype.updateTicksInside = function() { + var i; + var n = this.ticks.length; + this.adaptSize(this.ticksInside, n); + + if (this.type === this.parent.BOTTOM || this.type === this.parent.TOP) { + for ( i = 0; i < n; i++) { + this.ticksInside[i] = (this.plotTicks[i] >= 0) && (this.plotTicks[i] <= this.dim[0]); + } + } else { + for ( i = 0; i < n; i++) { + this.ticksInside[i] = (-this.plotTicks[i] >= 0) && (-this.plotTicks[i] <= this.dim[1]); + } + } +}; + +GAxis.prototype.updateTickLabels = function() { + var tick, logValue, isExactLogValue, i; + var n = this.ticks.length; + this.adaptSize(this.tickLabels, n); + + if (this.log) { + for ( i = 0; i < n; i++) { + tick = this.ticks[i]; + + if (tick > 0) { + logValue = Math.log(tick) / Math.LN10; + isExactLogValue = Math.abs(logValue - Math.round(logValue)) < 0.0001; + + if (isExactLogValue) { + logValue = Math.round(logValue); + + if (this.expTickLabels) { + this.tickLabels[i] = "1e" + logValue; + } else { + if (logValue > -3.1 && logValue < 3.1) { + this.tickLabels[i] = (logValue >= 0) ? "" + Math.round(tick) : "" + tick; + } else { + this.tickLabels[i] = "1e" + logValue; + } + } + } else { + this.tickLabels[i] = ""; + } + } else { + this.tickLabels[i] = ""; + } + } + } else { + for ( i = 0; i < n; i++) { + tick = this.ticks[i]; + + if (tick % 1 === 0) { + this.tickLabels[i] = "" + Math.round(tick); + } else if ( typeof this.ticksPrecision !== "undefined" && this.ticksPrecision >= 0) { + this.tickLabels[i] = "" + parseFloat(tick).toFixed(this.ticksPrecision); + } else { + this.tickLabels[i] = "" + tick; + } + } + } +}; + +GAxis.prototype.moveLim = function(newLim) { + if (newLim[1] !== newLim[0]) { + // Check that the new limit makes sense + if (this.log && (newLim[0] <= 0 || newLim[1] <= 0)) { + console.log("The limits are negative. This is not allowed in logarithmic scale."); + } else { + this.lim[0] = newLim[0]; + this.lim[1] = newLim[1]; + + // Calculate the new ticks if they are not fixed + if (!this.fixedTicks) { + var n = this.ticks.length; + + if (this.log) { + this.obtainLogarithmicTicks(); + } else if (n > 0) { + // Obtain the ticks precision and the tick separation + var step = 0; + var sigDigits = 0; + + if (this.ticksSeparation > 0) { + step = (this.lim[1] > this.lim[0]) ? this.ticksSeparation : -this.ticksSeparation; + sigDigits = this.obtainSigDigits(step); + + while (this.roundPlus(step, sigDigits) - step !== 0) { + sigDigits++; + } + } else { + step = (n === 1) ? this.lim[1] - this.lim[0] : this.ticks[1] - this.ticks[0]; + sigDigits = this.obtainSigDigits(step); + step = this.roundPlus(step, sigDigits); + + if (step === 0 || Math.abs(step) > Math.abs(this.lim[1] - this.lim[0])) { + sigDigits++; + step = (n === 1) ? this.lim[1] - this.lim[0] : this.ticks[1] - this.ticks[0]; + step = this.roundPlus(step, sigDigits); + } + + step = (this.lim[1] > this.lim[0]) ? Math.abs(step) : -Math.abs(step); + } + + // Obtain the first tick + var firstTick = this.ticks[0] + step * Math.ceil((this.lim[0] - this.ticks[0]) / step); + firstTick = this.roundPlus(firstTick, sigDigits); + + if ((this.lim[1] - firstTick) * (this.lim[0] - firstTick) > 0) { + firstTick = this.ticks[0] + step * Math.floor((this.lim[0] - this.ticks[0]) / step); + firstTick = this.roundPlus(firstTick, sigDigits); + } + + // Calculate the rest of the ticks + n = Math.floor(Math.abs((this.lim[1] - firstTick) / step)) + 1; + this.adaptSize(this.ticks, n); + this.ticks[0] = firstTick; + + for (var i = 1; i < n; i++) { + this.ticks[i] = this.roundPlus(this.ticks[i - 1] + step, sigDigits); + } + + // A sanity check + if (this.ticksPrecision !== sigDigits) { + console.log("There is a problem in the axis ticks precision calculation"); + } + } + + // Obtain the new tick labels + this.updateTickLabels(); + } + + // Update the rest of the arrays + this.updatePlotTicks(); + this.updateTicksInside(); + } + } +}; + +GAxis.prototype.draw = function() { + switch (this.type) { + case this.parent.BOTTOM: + this.drawAsXAxis(); + break; + case this.parent.LEFT: + this.drawAsYAxis(); + break; + case this.parent.TOP: + this.drawAsTopAxis(); + break; + case this.parent.RIGHT: + this.drawAsRightAxis(); + break; + } + + if (this.drawAxisLabel) { + this.lab.draw(); + } +}; + +GAxis.prototype.drawAsXAxis = function() { + var i; + + // Draw the ticks + this.parent.push(); + this.parent.stroke(this.lineColor); + this.parent.strokeWeight(this.lineWidth); + this.parent.strokeCap(this.parent.SQUARE); + + this.parent.line(0, this.offset, this.dim[0], this.offset); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i]) { + if (this.log && this.tickLabels[i] === "") { + this.parent.line(this.plotTicks[i], this.offset, this.plotTicks[i], this.offset + this.smallTickLength); + } else { + this.parent.line(this.plotTicks[i], this.offset, this.plotTicks[i], this.offset + this.tickLength); + } + } + } + + this.parent.pop(); + + // Draw the tick labels + if (this.drawTickLabels) { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotateTickLabels) { + var halfPI = 0.5 * Math.PI; + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.push(); + this.parent.translate(this.plotTicks[i], this.offset + this.tickLabelOffset); + this.parent.rotate(-halfPI); + this.parent.text(this.tickLabels[i], 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.CENTER, this.parent.TOP); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.text(this.tickLabels[i], this.plotTicks[i], this.offset + this.tickLabelOffset); + } + } + } + + this.parent.pop(); + } +}; + +GAxis.prototype.drawAsYAxis = function() { + var i; + + // Draw the ticks + this.parent.push(); + this.parent.stroke(this.lineColor); + this.parent.strokeWeight(this.lineWidth); + this.parent.strokeCap(this.parent.SQUARE); + + this.parent.line(-this.offset, 0, -this.offset, -this.dim[1]); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i]) { + if (this.log && this.tickLabels[i] === "") { + this.parent.line(-this.offset, this.plotTicks[i], -this.offset - this.smallTickLength, this.plotTicks[i]); + } else { + this.parent.line(-this.offset, this.plotTicks[i], -this.offset - this.tickLength, this.plotTicks[i]); + } + } + } + + this.parent.pop(); + + // Draw the tick labels + if (this.drawTickLabels) { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.rotateTickLabels) { + var halfPI = 0.5 * Math.PI; + this.parent.textAlign(this.parent.CENTER, this.parent.BOTTOM); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.push(); + this.parent.translate(-this.offset - this.tickLabelOffset, this.plotTicks[i]); + this.parent.rotate(-halfPI); + this.parent.text(this.tickLabels[i], 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.text(this.tickLabels[i], -this.offset - this.tickLabelOffset, this.plotTicks[i]); + } + } + } + + this.parent.pop(); + } +}; + +GAxis.prototype.drawAsTopAxis = function() { + var i; + + // Draw the ticks + this.parent.push(); + this.parent.stroke(this.lineColor); + this.parent.strokeWeight(this.lineWidth); + this.parent.strokeCap(this.parent.SQUARE); + this.parent.translate(0, -this.dim[1]); + + this.parent.line(0, -this.offset, this.dim[0], -this.offset); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i]) { + if (this.log && this.tickLabels[i] === "") { + this.parent.line(this.plotTicks[i], -this.offset, this.plotTicks[i], -this.offset - this.smallTickLength); + } else { + this.parent.line(this.plotTicks[i], -this.offset, this.plotTicks[i], -this.offset - this.tickLength); + } + } + } + + this.parent.pop(); + + // Draw the tick labels + if (this.drawTickLabels) { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + this.parent.translate(0, -this.dim[1]); + + if (this.rotateTickLabels) { + var halfPI = 0.5 * Math.PI; + this.parent.textAlign(this.parent.LEFT, this.parent.CENTER); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.push(); + this.parent.translate(this.plotTicks[i], -this.offset - this.tickLabelOffset); + this.parent.rotate(-halfPI); + this.parent.text(this.tickLabels[i], 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.CENTER, this.parent.BOTTOM); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.text(this.tickLabels[i], this.plotTicks[i], -this.offset - this.tickLabelOffset); + } + } + } + + this.parent.pop(); + } +}; + +GAxis.prototype.drawAsRightAxis = function() { + var i; + + // Draw the ticks + this.parent.push(); + this.parent.stroke(this.lineColor); + this.parent.strokeWeight(this.lineWidth); + this.parent.strokeCap(this.parent.SQUARE); + this.parent.translate(this.dim[0], 0); + + this.parent.line(this.offset, 0, this.offset, -this.dim[1]); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i]) { + if (this.log && this.tickLabels[i] === "") { + this.parent.line(this.offset, this.plotTicks[i], this.offset + this.smallTickLength, this.plotTicks[i]); + } else { + this.parent.line(this.offset, this.plotTicks[i], this.offset + this.tickLength, this.plotTicks[i]); + } + } + } + + this.parent.pop(); + + // Draw the tick labels + if (this.drawTickLabels) { + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + this.parent.translate(this.dim[0], 0); + + if (this.rotateTickLabels) { + var halfPI = 0.5 * Math.PI; + this.parent.textAlign(this.parent.CENTER, this.parent.TOP); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.push(); + this.parent.translate(this.offset + this.tickLabelOffset, this.plotTicks[i]); + this.parent.rotate(-halfPI); + this.parent.text(this.tickLabels[i], 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.LEFT, this.parent.CENTER); + + for ( i = 0; i < this.plotTicks.length; i++) { + if (this.ticksInside[i] && this.tickLabels[i] !== "") { + this.parent.text(this.tickLabels[i], this.offset + this.tickLabelOffset, this.plotTicks[i]); + } + } + } + + this.parent.pop(); + } +}; + +GAxis.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GAxis.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + this.dim[0] = xDim; + this.dim[1] = yDim; + this.updatePlotTicks(); + this.lab.setDim(this.dim); + } +}; + +GAxis.prototype.setLim = function(lim) { + if (lim[1] !== lim[0]) { + // Make sure the new limits makes sense + if (this.log && (lim[0] <= 0 || lim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.lim[0] = lim[0]; + this.lim[1] = lim[1]; + + if (!this.fixedTicks) { + this.updateTicks(); + this.updateTickLabels(); + } + + this.updatePlotTicks(); + this.updateTicksInside(); + } + } +}; + +GAxis.prototype.setLimAndLog = function(lim, log) { + if (lim[1] !== lim[0]) { + // Make sure the new limits makes sense + if (log && (lim[0] <= 0 || lim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.lim[0] = lim[0]; + this.lim[1] = lim[1]; + this.log = log; + + if (!this.fixedTicks) { + this.updateTicks(); + this.updateTickLabels(); + } + + this.updatePlotTicks(); + this.updateTicksInside(); + } + } +}; + +GAxis.prototype.setLog = function(log) { + if (log !== this.log) { + this.log = log; + + // Check if the old limits still make sense + if (this.log && (this.lim[0] <= 0 || this.lim[1] <= 0)) { + console.log("The limits are negative. This is not allowed in logarithmic scale."); + console.log("Will set them to (0.1, 10)"); + + if (this.lim[1] > this.lim[0]) { + this.lim[0] = 0.1; + this.lim[1] = 10; + } else { + this.lim[0] = 10; + this.lim[1] = 0.1; + } + } + + if (!this.fixedTicks) { + this.updateTicks(); + this.updateTickLabels(); + } + + this.updatePlotTicks(); + this.updateTicksInside(); + } +}; + +GAxis.prototype.setOffset = function(offset) { + this.offset = offset; +}; + +GAxis.prototype.setLineColor = function(lineColor) { + this.lineColor = lineColor; +}; + +GAxis.prototype.setLineWidth = function(lineWidth) { + if (lineWidth > 0) { + this.lineWidth = lineWidth; + } +}; + +GAxis.prototype.setNTicks = function(nTicks) { + if (nTicks >= 0) { + this.nTicks = nTicks; + this.ticksSeparation = -1; + + if (!this.log) { + this.fixedTicks = false; + this.updateTicks(); + this.updatePlotTicks(); + this.updateTicksInside(); + this.updateTickLabels(); + } + } +}; + +GAxis.prototype.setTicksSeparation = function(ticksSeparation) { + this.ticksSeparation = ticksSeparation; + + if (!this.log) { + this.fixedTicks = false; + this.updateTicks(); + this.updatePlotTicks(); + this.updateTicksInside(); + this.updateTickLabels(); + } +}; + +GAxis.prototype.setTicks = function(ticks) { + var n = ticks.length; + this.adaptSize(this.ticks, n); + + for (var i = 0; i < n; i++) { + this.ticks[i] = ticks[i]; + } + + this.fixedTicks = true; + + // Set the tick precision to undefined + this.ticksPrecision = undefined; + + this.updatePlotTicks(); + this.updateTicksInside(); + this.updateTickLabels(); +}; + +GAxis.prototype.setTickLabels = function(tickLabels) { + if (tickLabels.length === this.tickLabels.length) { + for (var i = 0; i < this.tickLabels.length; i++) { + this.tickLabels[i] = tickLabels[i]; + } + + this.fixedTicks = true; + + // Set the tick precision to undefined + this.ticksPrecision = undefined; + } +}; + +GAxis.prototype.setFixedTicks = function(fixedTicks) { + if (fixedTicks !== this.fixedTicks) { + this.fixedTicks = fixedTicks; + + if (!this.fixedTicks) { + this.updateTicks(); + this.updatePlotTicks(); + this.updateTicksInside(); + this.updateTickLabels(); + } + } +}; + +GAxis.prototype.setTickLength = function(tickLength) { + this.tickLength = tickLength; +}; + +GAxis.prototype.setSmallTickLength = function(smallTickLength) { + this.smallTickLength = smallTickLength; +}; + +GAxis.prototype.setExpTickLabels = function(expTickLabels) { + if (expTickLabels !== this.expTickLabels) { + this.expTickLabels = expTickLabels; + this.updateTickLabels(); + } +}; + +GAxis.prototype.setRotateTickLabels = function(rotateTickLabels) { + this.rotateTickLabels = rotateTickLabels; +}; + +GAxis.prototype.setDrawTickLabels = function(drawTickLabels) { + this.drawTickLabels = drawTickLabels; +}; + +GAxis.prototype.setTickLabelOffset = function(tickLabelOffset) { + this.tickLabelOffset = tickLabelOffset; +}; + +GAxis.prototype.setDrawAxisLabel = function(drawAxisLabel) { + this.drawAxisLabel = drawAxisLabel; +}; + +GAxis.prototype.setAxisLabelText = function(axisLabelText) { + this.lab.setText(axisLabelText); +}; + +GAxis.prototype.setFontName = function(fontName) { + this.fontName = fontName; +}; + +GAxis.prototype.setFontColor = function(fontColor) { + this.fontColor = fontColor; +}; + +GAxis.prototype.setFontSize = function(fontSize) { + if (fontSize > 0) { + this.fontSize = fontSize; + } +}; + +GAxis.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + if (fontSize > 0) { + this.fontName = fontName; + this.fontColor = fontColor; + this.fontSize = fontSize; + } +}; + +GAxis.prototype.setAllFontProperties = function(fontName, fontColor, fontSize) { + this.setFontProperties(fontName, fontColor, fontSize); + this.lab.setFontProperties(fontName, fontColor, fontSize); +}; + +GAxis.prototype.getTicks = function() { + if (this.fixedTicks) { + return this.ticks.slice(); + } else { + // Return only the ticks that are visible + var validTicks = []; + var counter = 0; + + for (var i = 0; i < this.ticksInside.length; i++) { + if (this.ticksInside[i]) { + validTicks[counter] = this.ticks[i]; + counter++; + } + } + + return validTicks; + } +}; + +GAxis.prototype.getTicksRef = function() { + return this.ticks; +}; + +GAxis.prototype.getPlotTicks = function() { + if (this.fixedTicks) { + return this.plotTicks.slice(); + } else { + var validPlotTicks = []; + var counter = 0; + + for (var i = 0; i < this.ticksInside.length; i++) { + if (this.ticksInside[i]) { + validPlotTicks[counter] = this.plotTicks[i]; + counter++; + } + } + + return validPlotTicks; + } +}; + +GAxis.prototype.getPlotTicksRef = function() { + return this.plotTicks; +}; + +GAxis.prototype.getAxisLabel = function() { + return this.lab; +}; +/* + * Histogram class. + */ +function GHistogram(parent, type, dim, plotPoints) { + // The parent processing object + this.parent = parent; + + // General properties + this.type = (type === GPlot.VERTICAL || type === GPlot.HORIZONTAL) ? type : GPlot.VERTICAL; + this.dim = dim.slice(); + this.plotPoints = []; + + // Copy the plot points + for (var i = 0; i < plotPoints.length; i++) { + this.plotPoints[i] = new GPoint(plotPoints[i]); + } + + this.visible = true; + this.separations = [2]; + this.bgColors = [this.parent.color(150, 150, 255)]; + this.lineColors = [this.parent.color(100, 100, 255)]; + this.lineWidths = [1]; + this.differences = []; + this.leftSides = []; + this.rightSides = []; + this.updateArrays(); + + // Labels properties + this.labelsOffset = 8; + this.drawLabels = false; + this.rotateLabels = false; + this.fontName = "Helvetica"; + this.fontColor = this.parent.color(0); + this.fontSize = 11; +} + +GHistogram.prototype.updateArrays = function() { + var i; + var nPoints = this.plotPoints.length; + + // Remove unused points + if (this.differences.length > nPoints) { + this.differences.splice(nPoints, Number.MAX_VALUE); + this.leftSides.splice(nPoints, Number.MAX_VALUE); + this.rightSides.splice(nPoints, Number.MAX_VALUE); + } + + // Update the arrays + if (nPoints === 1) { + this.leftSides[0] = (this.type === GPlot.VERTICAL) ? 0.2 * this.dim[0] : 0.2 * this.dim[1]; + this.rightSides[0] = this.leftSides[0]; + } else if (nPoints > 1) { + // Calculate the differences between consecutive points + for ( i = 0; i < nPoints - 1; i++) { + if (this.plotPoints[i].isValid() && this.plotPoints[i + 1].isValid()) { + var separation = this.separations[i % this.separations.length]; + var diff; + + if (this.type === GPlot.VERTICAL) { + diff = this.plotPoints[i + 1].getX() - this.plotPoints[i].getX(); + } else { + diff = this.plotPoints[i + 1].getY() - this.plotPoints[i].getY(); + } + + if (diff > 0) { + this.differences[i] = (diff - separation) / 2; + } else { + this.differences[i] = (diff + separation) / 2; + } + } else { + this.differences[i] = 0; + } + } + + // Fill the leftSides and rightSides arrays + this.leftSides[0] = this.differences[0]; + this.rightSides[0] = this.differences[0]; + + for ( i = 1; i < nPoints - 1; i++) { + this.leftSides[i] = this.differences[i - 1]; + this.rightSides[i] = this.differences[i]; + } + + this.leftSides[nPoints - 1] = this.differences[nPoints - 2]; + this.rightSides[nPoints - 1] = this.differences[nPoints - 2]; + } +}; + +GHistogram.prototype.draw = function(plotBasePoint) { + if (this.visible) { + // Calculate the baseline for the histogram + var baseline = 0; + + if (plotBasePoint.isValid()) { + baseline = (this.type === GPlot.VERTICAL) ? plotBasePoint.getY() : plotBasePoint.getX(); + } + + // Draw the rectangles + var point, x1, x2, y1, y2, lw; + var nPoints = this.plotPoints.length; + + this.parent.push(); + this.parent.rectMode(this.parent.CORNERS); + this.parent.strokeCap(this.parent.SQUARE); + + for (var i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid()) { + // Obtain the corners + if (this.type === GPlot.VERTICAL) { + x1 = point.getX() - this.leftSides[i]; + x2 = point.getX() + this.rightSides[i]; + y1 = point.getY(); + y2 = baseline; + } else { + x1 = baseline; + x2 = point.getX(); + y1 = point.getY() - this.leftSides[i]; + y2 = point.getY() + this.rightSides[i]; + } + + if (x1 < 0) { + x1 = 0; + } else if (x1 > this.dim[0]) { + x1 = this.dim[0]; + } + + if (-y1 < 0) { + y1 = 0; + } else if (-y1 > this.dim[1]) { + y1 = -this.dim[1]; + } + + if (x2 < 0) { + x2 = 0; + } else if (x2 > this.dim[0]) { + x2 = this.dim[0]; + } + + if (-y2 < 0) { + y2 = 0; + } else if (-y2 > this.dim[1]) { + y2 = -this.dim[1]; + } + + // Draw the rectangle + lw = this.lineWidths[i % this.lineWidths.length]; + this.parent.fill(this.bgColors[i % this.bgColors.length]); + this.parent.stroke(this.lineColors[i % this.lineColors.length]); + this.parent.strokeWeight(lw); + + if (Math.abs(x2 - x1) > 2 * lw && Math.abs(y2 - y1) > 2 * lw) { + this.parent.rect(x1, y1, x2, y2); + } else if ((this.type === GPlot.VERTICAL && x2 !== x1 && !(y1 === y2 && (y1 === 0 || y1 === -this.dim[1]))) || (this.type === GPlot.HORIZONTAL && y2 !== y1 && !(x1 === x2 && (x1 === 0 || x1 === this.dim[0])))) { + this.parent.rect(x1, y1, x2, y2); + this.parent.line(x1, y1, x1, y2); + this.parent.line(x2, y1, x2, y2); + this.parent.line(x1, y1, x2, y1); + this.parent.line(x1, y2, x2, y2); + } + } + } + + this.parent.pop(); + + // Draw the labels + if (this.drawLabels) { + this.drawHistLabels(); + } + } +}; + +GHistogram.prototype.drawHistLabels = function() { + var point, i; + var nPoints = this.plotPoints.length; + var halfPI = 0.5 * Math.PI; + + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.noStroke(); + + if (this.type === GPlot.VERTICAL) { + if (this.rotateLabels) { + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + + for ( i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid() && point.getX() >= 0 && point.getX() <= this.dim[0]) { + this.parent.push(); + this.parent.translate(point.getX(), this.labelsOffset); + this.parent.rotate(-halfPI); + this.parent.text(point.getLabel(), 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.CENTER, this.parent.TOP); + + for ( i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid() && point.getX() >= 0 && point.getX() <= this.dim[0]) { + this.parent.text(point.getLabel(), point.getX(), this.labelsOffset); + } + } + } + } else { + if (this.rotateLabels) { + this.parent.textAlign(this.parent.CENTER, this.parent.BOTTOM); + + for ( i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid() && -point.getY() >= 0 && -point.getY() <= this.dim[1]) { + this.parent.push(); + this.parent.translate(-this.labelsOffset, point.getY()); + this.parent.rotate(-halfPI); + this.parent.text(point.getLabel(), 0, 0); + this.parent.pop(); + } + } + } else { + this.parent.textAlign(this.parent.RIGHT, this.parent.CENTER); + + for ( i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid() && -point.getY() >= 0 && -point.getY() <= this.dim[1]) { + this.parent.text(point.getLabel(), -this.labelsOffset, point.getY()); + } + } + } + } + + this.parent.pop(); +}; + +GHistogram.prototype.setType = function(type) { + if (type !== this.type && (type === GPlot.VERTICAL || type === GPlot.HORIZONTAL)) { + this.type = type; + this.updateArrays(); + } +}; + +GHistogram.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GHistogram.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + this.dim[0] = xDim; + this.dim[1] = yDim; + this.updateArrays(); + } +}; + +GHistogram.prototype.setPlotPoints = function(plotPoints) { + var i; + var nPoints = plotPoints.length; + + if (this.plotPoints.length === nPoints) { + for ( i = 0; i < nPoints; i++) { + this.plotPoints[i].set(plotPoints[i]); + } + } else if (this.plotPoints.length > nPoints) { + for ( i = 0; i < nPoints; i++) { + this.plotPoints[i].set(plotPoints[i]); + } + + this.plotPoints.splice(nPoints, Number.MAX_VALUE); + } else { + for ( i = 0; i < this.plotPoints.length; i++) { + this.plotPoints[i].set(plotPoints[i]); + } + + for ( i = this.plotPoints.lengh; i < nPoints; i++) { + this.plotPoints[i] = new GPoint(plotPoints[i]); + } + } + + this.updateArrays(); +}; + +GHistogram.prototype.setPlotPoint = function(index, plotPoint) { + if (index < this.plotPoints.length) { + this.plotPoints[index].set(plotPoint); + } else if (index === this.plotPoints.length) { + this.plotPoints[index] = new GPoint(plotPoint); + } else { + throw new Error("GHistogram.setPlotPoint(): the index position is outside the array size"); + } + + this.updateArrays(); +}; + +GHistogram.prototype.addPlotPoint = function() { + if (arguments.length === 2) { + this.plotPoints.push(new GPoint(arguments[0], arguments[1])); + } else if (arguments.length === 1) { + this.plotPoints.push(new GPoint(arguments[0])); + } else { + throw new Error("GHistogram.addPlotPoint(): signature not supported"); + } + + this.updateArrays(); +}; + +GHistogram.prototype.removePlotPoint = function(index) { + if (index < this.plotPoints.length) { + this.plotPoints.splice(index, 1); + } else { + throw new Error("GHistogram.removePlotPoint(): the index position is outside the array size"); + } + + this.updateArrays(); +}; + +GHistogram.prototype.setSeparations = function(separations) { + this.separations = separations.slice(); + this.updateArrays(); +}; + +GHistogram.prototype.setBgColors = function(bgColors) { + this.bgColors = bgColors.slice(); +}; + +GHistogram.prototype.setLineColors = function(lineColors) { + this.lineColors = lineColors.slice(); +}; + +GHistogram.prototype.setLineWidths = function(lineWidths) { + this.lineWidths = lineWidths.slice(); +}; + +GHistogram.prototype.setVisible = function(visible) { + this.visible = visible; +}; + +GHistogram.prototype.setLabelsOffset = function(labelsOffset) { + this.labelsOffset = labelsOffset; +}; + +GHistogram.prototype.setDrawLabels = function(drawLabels) { + this.drawLabels = drawLabels; +}; + +GHistogram.prototype.setRotateLabels = function(rotateLabels) { + this.rotateLabels = rotateLabels; +}; + +GHistogram.prototype.setFontName = function(fontName) { + this.fontName = fontName; +}; + +GHistogram.prototype.setFontColor = function(fontColor) { + this.fontColor = fontColor; +}; + +GHistogram.prototype.setFontSize = function(fontSize) { + if (fontSize > 0) { + this.fontSize = fontSize; + } +}; + +GHistogram.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + if (fontSize > 0) { + this.fontName = fontName; + this.fontColor = fontColor; + this.fontSize = fontSize; + } +}; +/* + * Layer class. A GLayer usually contains an array of points and a histogram + */ +function GLayer(parent, id, dim, xLim, yLim, xLog, yLog) { + // The parent processing object + this.parent = parent; + + // General properties + this.id = id; + this.dim = dim.slice(); + this.xLim = xLim.slice(); + this.yLim = yLim.slice(); + this.xLog = xLog; + this.yLog = yLog; + + // Do some sanity checks + if (this.xLog && (this.xLim[0] <= 0 || this.xLim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + console.log("Will set horizontal limits to (0.1, 10)"); + this.xLim[0] = 0.1; + this.xLim[1] = 10; + } + + if (this.yLog && (this.yLim[0] <= 0 || this.yLim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + console.log("Will set vertical limits to (0.1, 10)"); + this.yLim[0] = 0.1; + this.yLim[1] = 10; + } + + // Points properties + this.points = []; + this.plotPoints = []; + this.inside = []; + this.pointColors = [this.parent.color(255, 0, 0, 150)]; + this.pointSizes = [7]; + + // Line properties + this.lineColor = this.parent.color(0, 150); + this.lineWidth = 1; + + // Histogram properties + this.hist = undefined; + this.histBasePoint = new GPoint(0, 0); + + // Labels properties + this.labelBgColor = this.parent.color(255, 200); + this.labelSeparation = [7, 7]; + this.fontName = "Helvetica"; + this.fontColor = this.parent.color(0); + this.fontSize = 11; + + // Helper variable + this.cuts = [[0, 0], [0, 0], [0, 0], [0, 0]]; +} + +GLayer.prototype.isValidNumber = function(number) { + return !isNaN(number) && isFinite(number); +}; + +GLayer.prototype.isId = function(someId) { + return this.id === someId; +}; + +GLayer.prototype.valueToXPlot = function(x) { + if (this.xLog) { + return this.dim[0] * Math.log(x / this.xLim[0]) / Math.log(this.xLim[1] / this.xLim[0]); + } else { + return this.dim[0] * (x - this.xLim[0]) / (this.xLim[1] - this.xLim[0]); + } +}; + +GLayer.prototype.valueToYPlot = function(y) { + if (this.yLog) { + return -this.dim[1] * Math.log(y / this.yLim[0]) / Math.log(this.yLim[1] / this.yLim[0]); + } else { + return -this.dim[1] * (y - this.yLim[0]) / (this.yLim[1] - this.yLim[0]); + } +}; + +GLayer.prototype.valueToPlot = function() { + if (arguments.length === 2) { + return [this.valueToXPlot(arguments[0]), this.valueToYPlot(arguments[1])]; + } else if (arguments.length === 1 && arguments[0] instanceof GPoint) { + return new GPoint(this.valueToXPlot(arguments[0].getX()), this.valueToYPlot(arguments[0].getY()), arguments[0].getLabel()); + } else if (arguments.length === 1 && arguments[0] instanceof Array && arguments[0][0] instanceof GPoint) { + var xScalingFactor, yScalingFactor, point, xPlot, yPlot, i; + var nPoints = arguments[0].length; + var plotPts = []; + + // Go case by case. More code, but it's faster + if (this.xLog && this.yLog) { + xScalingFactor = this.dim[0] / Math.log(this.xLim[1] / this.xLim[0]); + yScalingFactor = -this.dim[1] / Math.log(this.yLim[1] / this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = arguments[0][i]; + xPlot = Math.log(point.getX() / this.xLim[0]) * xScalingFactor; + yPlot = Math.log(point.getY() / this.yLim[0]) * yScalingFactor; + plotPts[i] = new GPoint(xPlot, yPlot, point.getLabel()); + } + } else if (this.xLog) { + xScalingFactor = this.dim[0] / Math.log(this.xLim[1] / this.xLim[0]); + yScalingFactor = -this.dim[1] / (this.yLim[1] - this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = arguments[0][i]; + xPlot = Math.log(point.getX() / this.xLim[0]) * xScalingFactor; + yPlot = (point.getY() - this.yLim[0]) * yScalingFactor; + plotPts[i] = new GPoint(xPlot, yPlot, point.getLabel()); + } + } else if (this.yLog) { + xScalingFactor = this.dim[0] / (this.xLim[1] - this.xLim[0]); + yScalingFactor = -this.dim[1] / Math.log(this.yLim[1] / this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = arguments[0][i]; + xPlot = (point.getX() - this.xLim[0]) * xScalingFactor; + yPlot = Math.log(point.getY() / this.yLim[0]) * yScalingFactor; + plotPts[i] = new GPoint(xPlot, yPlot, point.getLabel()); + } + } else { + xScalingFactor = this.dim[0] / (this.xLim[1] - this.xLim[0]); + yScalingFactor = -this.dim[1] / (this.yLim[1] - this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = arguments[0][i]; + xPlot = (point.getX() - this.xLim[0]) * xScalingFactor; + yPlot = (point.getY() - this.yLim[0]) * yScalingFactor; + plotPts[i] = new GPoint(xPlot, yPlot, point.getLabel()); + } + } + + return plotPts; + } else { + throw new Error("GLayer.valueToPlot(): signature not supported"); + } +}; + +GLayer.prototype.updatePlotPoints = function() { + var xScalingFactor, yScalingFactor, point, xPlot, yPlot, i; + var nPoints = this.points.length; + + // Update the plotPoints array size if necessary + if (this.plotPoints.length < nPoints) { + for ( i = this.plotPoints.length; i < nPoints; i++) { + this.plotPoints[i] = new GPoint(); + } + } else if (this.plotPoints.length > nPoints) { + this.plotPoints.splice(nPoints, Number.MAX_VALUE); + } + + // Go case by case. More code, but it should be faster + if (this.xLog && this.yLog) { + xScalingFactor = this.dim[0] / Math.log(this.xLim[1] / this.xLim[0]); + yScalingFactor = -this.dim[1] / Math.log(this.yLim[1] / this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = this.points[i]; + xPlot = Math.log(point.getX() / this.xLim[0]) * xScalingFactor; + yPlot = Math.log(point.getY() / this.yLim[0]) * yScalingFactor; + this.plotPoints[i].set(xPlot, yPlot, point.getLabel()); + } + } else if (this.xLog) { + xScalingFactor = this.dim[0] / Math.log(this.xLim[1] / this.xLim[0]); + yScalingFactor = -this.dim[1] / (this.yLim[1] - this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = this.points[i]; + xPlot = Math.log(point.getX() / this.xLim[0]) * xScalingFactor; + yPlot = (point.getY() - this.yLim[0]) * yScalingFactor; + this.plotPoints[i].set(xPlot, yPlot, point.getLabel()); + } + } else if (this.yLog) { + xScalingFactor = this.dim[0] / (this.xLim[1] - this.xLim[0]); + yScalingFactor = -this.dim[1] / Math.log(this.yLim[1] / this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = this.points[i]; + xPlot = (point.getX() - this.xLim[0]) * xScalingFactor; + yPlot = Math.log(point.getY() / this.yLim[0]) * yScalingFactor; + this.plotPoints[i].set(xPlot, yPlot, point.getLabel()); + } + } else { + xScalingFactor = this.dim[0] / (this.xLim[1] - this.xLim[0]); + yScalingFactor = -this.dim[1] / (this.yLim[1] - this.yLim[0]); + + for ( i = 0; i < nPoints; i++) { + point = this.points[i]; + xPlot = (point.getX() - this.xLim[0]) * xScalingFactor; + yPlot = (point.getY() - this.yLim[0]) * yScalingFactor; + this.plotPoints[i].set(xPlot, yPlot, point.getLabel()); + } + } +}; + +GLayer.prototype.xPlotToValue = function(xPlot) { + if (this.xLog) { + return Math.exp(Math.log(this.xLim[0]) + Math.log(this.xLim[1] / this.xLim[0]) * xPlot / this.dim[0]); + } else { + return this.xLim[0] + (this.xLim[1] - this.xLim[0]) * xPlot / this.dim[0]; + } +}; + +GLayer.prototype.yPlotToValue = function(yPlot) { + if (this.yLog) { + return Math.exp(Math.log(this.yLim[0]) - Math.log(this.yLim[1] / this.yLim[0]) * yPlot / this.dim[1]); + } else { + return this.yLim[0] - (this.yLim[1] - this.yLim[0]) * yPlot / this.dim[1]; + } +}; + +GLayer.prototype.plotToValue = function(xPlot, yPlot) { + return [this.xPlotToValue(xPlot), this.yPlotToValue(yPlot)]; +}; + +GLayer.prototype.isInside = function() { + var xPlot, yPlot, valid; + + if (arguments.length === 2) { + xPlot = arguments[0]; + yPlot = arguments[1]; + valid = this.isValidNumber(xPlot) && this.isValidNumber(yPlot); + } else if (arguments.length === 1 && arguments[0] instanceof GPoint) { + xPlot = arguments[0].getX(); + yPlot = arguments[0].getY(); + valid = arguments[0].isValid(); + } else { + throw new Error("GLayer.isInside(): signature not supported"); + } + + return (valid) ? (xPlot >= 0) && (xPlot <= this.dim[0]) && (-yPlot >= 0) && (-yPlot <= this.dim[1]) : false; +}; + +GLayer.prototype.updateInsideList = function() { + var point; + var nPoints = this.plotPoints.length; + + for (var i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + this.inside[i] = (point.isValid()) ? (point.getX() >= 0) && (point.getX() <= this.dim[0]) && (-point.getY() >= 0) && (-point.getY() <= this.dim[1]) : false; + } + + // Remove the unused elements + if (this.inside.length > nPoints) { + this.inside.splice(nPoints, Number.MAX_VALUE); + } +}; + +GLayer.prototype.getPointIndexAtPlotPos = function(xPlot, yPlot) { + var pointIndex; + + if (this.isInside(xPlot, yPlot)) { + var point, distSq; + var minDistSq = 25; + var nPoints = this.plotPoints.length; + + for (var i = 0; i < nPoints; i++) { + if (this.inside[i]) { + point = this.plotPoints[i]; + distSq = Math.pow(point.getX() - xPlot, 2) + Math.pow(point.getY() - yPlot, 2); + + if (distSq < minDistSq) { + minDistSq = distSq; + pointIndex = i; + } + } + } + } + + return pointIndex; +}; + +GLayer.prototype.getPointAtPlotPos = function(xPlot, yPlot) { + return this.points[this.getPointIndexAtPlotPos(xPlot, yPlot)]; +}; + +GLayer.prototype.obtainBoxIntersections = function(plotPoint1, plotPoint2) { + var nCuts = 0; + + if (plotPoint1.isValid() && plotPoint2.isValid()) { + var x1 = plotPoint1.getX(); + var y1 = plotPoint1.getY(); + var x2 = plotPoint2.getX(); + var y2 = plotPoint2.getY(); + var inside1 = this.isInside(x1, y1); + var inside2 = this.isInside(x2, y2); + + // Check if the line between the two points could cut the box borders + var dontCut = (inside1 && inside2) || (x1 < 0 && x2 < 0) || (x1 > this.dim[0] && x2 > this.dim[0]) || (-y1 < 0 && -y2 < 0) || (-y1 > this.dim[1] && -y2 > this.dim[1]); + + if (!dontCut) { + // Obtain the axis cuts of the line that cross the two points + var deltaX = x2 - x1; + var deltaY = y2 - y1; + + if (deltaX === 0) { + nCuts = 2; + this.cuts[0][0] = x1; + this.cuts[0][1] = 0; + this.cuts[1][0] = x1; + this.cuts[1][1] = -this.dim[1]; + } else if (deltaY === 0) { + nCuts = 2; + this.cuts[0][0] = 0; + this.cuts[0][1] = y1; + this.cuts[1][0] = this.dim[0]; + this.cuts[1][1] = y1; + } else { + // Obtain the straight line (y = yCut + slope*x) that + // crosses the two points + var slope = deltaY / deltaX; + var yCut = y1 - slope * x1; + + // Calculate the axis cuts of that line + nCuts = 4; + this.cuts[0][0] = -yCut / slope; + this.cuts[0][1] = 0; + this.cuts[1][0] = (-this.dim[1] - yCut) / slope; + this.cuts[1][1] = -this.dim[1]; + this.cuts[2][0] = 0; + this.cuts[2][1] = yCut; + this.cuts[3][0] = this.dim[0]; + this.cuts[3][1] = yCut + slope * this.dim[0]; + } + + // Select only the cuts that fall inside the box and are located + // between the two points + nCuts = this.getValidCuts(this.cuts, nCuts, plotPoint1, plotPoint2); + + // Make sure we have the correct number of cuts + if (inside1 || inside2) { + // One of the points is inside. We should have one cut only + if (nCuts !== 1) { + var pointInside = (inside1) ? plotPoint1 : plotPoint2; + + // If too many cuts + if (nCuts > 1) { + nCuts = this.removeDuplicatedCuts(this.cuts, nCuts, 0); + + if (nCuts > 1) { + nCuts = this.removePointFromCuts(this.cuts, nCuts, pointInside, 0); + + // In case of rounding number errors + if (nCuts > 1) { + nCuts = this.removeDuplicatedCuts(this.cuts, nCuts, 0.001); + + if (nCuts > 1) { + nCuts = this.removePointFromCuts(this.cuts, nCuts, pointInside, 0.001); + } + } + } + } + + // If the cut is missing, then it must be equal to the point + // inside + if (nCuts === 0) { + nCuts = 1; + this.cuts[0][0] = pointInside.getX(); + this.cuts[1][0] = pointInside.getY(); + } + } + } else { + // Both points are outside. We should have either two cuts or + // none + if (nCuts > 2) { + nCuts = this.removeDuplicatedCuts(this.cuts, nCuts, 0); + + // In case of rounding number errors + if (nCuts > 2) { + nCuts = this.removeDuplicatedCuts(this.cuts, nCuts, 0.001); + } + } + + // If we have two cuts, order them (the closest to the first + // point goes first) + if (nCuts === 2) { + if ((Math.pow(this.cuts[0][0] - x1, 2) + Math.pow(this.cuts[0][1] - y1), 2) > (Math.pow(this.cuts[1][0] - x1, 2) + Math.pow(this.cuts[1][1] - y1, 2))) { + this.cuts[2][0] = this.cuts[0][0]; + this.cuts[2][1] = this.cuts[0][1]; + this.cuts[0][0] = this.cuts[1][0]; + this.cuts[0][1] = this.cuts[1][1]; + this.cuts[1][0] = this.cuts[2][0]; + this.cuts[1][1] = this.cuts[2][1]; + } + } + + // If one cut is missing, add the same one twice + if (nCuts === 1) { + nCuts = 2; + this.cuts[1][0] = this.cuts[0][0]; + this.cuts[1][1] = this.cuts[0][1]; + } + } + + // Some sanity checks + if ((inside1 || inside2) && nCuts !== 1) { + console.log("There should be one cut!!!"); + } else if (!inside1 && !inside2 && nCuts !== 0 && nCuts !== 2) { + console.log("There should be either 0 or 2 cuts!!! " + nCuts + " were found"); + } + } + } + + return nCuts; +}; + +GLayer.prototype.getValidCuts = function(cuts, nCuts, plotPoint1, plotPoint2) { + var x1 = plotPoint1.getX(); + var y1 = plotPoint1.getY(); + var x2 = plotPoint2.getX(); + var y2 = plotPoint2.getY(); + var deltaX = Math.abs(x2 - x1); + var deltaY = Math.abs(y2 - y1); + var counter = 0; + + for (var i = 0; i < nCuts; i++) { + // Check that the cut is inside the inner plotting area + if (this.isInside(cuts[i][0], cuts[i][1])) { + // Check that the cut falls between the two points + if (Math.abs(cuts[i][0] - x1) <= deltaX && Math.abs(cuts[i][1] - y1) <= deltaY && Math.abs(cuts[i][0] - x2) <= deltaX && Math.abs(cuts[i][1] - y2) <= deltaY) { + cuts[counter][0] = cuts[i][0]; + cuts[counter][1] = cuts[i][1]; + counter++; + } + } + } + + return counter; +}; + +GLayer.prototype.removeDuplicatedCuts = function(cuts, nCuts, tolerance) { + var repeated; + var counter = 0; + + for (var i = 0; i < nCuts; i++) { + repeated = false; + + for (var j = 0; j < counter; j++) { + if (Math.abs(cuts[j][0] - cuts[i][0]) <= tolerance && Math.abs(cuts[j][1] - cuts[i][1]) <= tolerance) { + repeated = true; + break; + } + } + + if (!repeated) { + cuts[counter][0] = cuts[i][0]; + cuts[counter][1] = cuts[i][1]; + counter++; + } + } + + return counter; +}; + +GLayer.prototype.removePointFromCuts = function(cuts, nCuts, plotPoint, tolerance) { + var x = plotPoint.getX(); + var y = plotPoint.getY(); + var counter = 0; + + for (var i = 0; i < nCuts; i++) { + if (Math.abs(cuts[i][0] - x) > tolerance || Math.abs(cuts[i][1] - y) > tolerance) { + cuts[counter][0] = cuts[i][0]; + cuts[counter][1] = cuts[i][1]; + counter++; + } + } + + return counter; +}; + +GLayer.prototype.startHistogram = function(histType) { + this.hist = new GHistogram(this.parent, histType, this.dim, this.plotPoints); +}; + +GLayer.prototype.drawPoints = function() { + var nPoints, i; + + if (arguments.length === 0) { + nPoints = this.plotPoints.length; + var nColors = this.pointColors.length; + var nSizes = this.pointSizes.length; + + this.parent.push(); + this.parent.ellipseMode(this.parent.CENTER); + this.parent.stroke(50); + + if (nColors === 1 && nSizes === 1) { + this.parent.fill(this.pointColors[0]); + + for ( i = 0; i < nPoints; i++) { + if (this.inside[i]) { + this.parent.ellipse(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.pointSizes[0], this.pointSizes[0]); + } + } + } else if (nColors === 1) { + this.parent.fill(this.pointColors[0]); + + for ( i = 0; i < nPoints; i++) { + if (this.inside[i]) { + this.parent.fill(0); + this.parent.noStroke(); + this.parent.ellipse(this.plotPoints[i].getX(), this.plotPoints[i].getY(),4,4); + this.parent.stroke(100); + this.parent.fill(this.pointColors[0]); + this.parent.ellipse(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.pointSizes[i % nSizes], this.pointSizes[i % nSizes]); + } + } + } else if (nSizes === 1) { + for ( i = 0; i < nPoints; i++) { + if (this.inside[i]) { + this.parent.fill(this.pointColors[i % nColors]); + this.parent.ellipse(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.pointSizes[0], this.pointSizes[0]); + } + } + } else { + for ( i = 0; i < nPoints; i++) { + if (this.inside[i]) { + this.parent.fill(this.pointColors[i % nColors]); + this.parent.ellipse(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.pointSizes[i % nSizes], this.pointSizes[i % nSizes]); + } + } + } + + this.parent.pop(); + } else if (arguments.length === 1 && arguments[0] instanceof p5.Image) { + nPoints = this.plotPoints.length; + + this.parent.push(); + this.parent.imageMode(this.parent.CENTER); + + for ( i = 0; i < nPoints; i++) { + if (this.inside[i]) { + this.parent.image(arguments[0], this.plotPoints[i].getX(), this.plotPoints[i].getY()); + } + } + + this.parent.pop(); + } else { + throw new Error("GLayer.drawPoints(): signature not supported"); + } +}; + +GLayer.prototype.drawPoint = function() { + var point, pointColor, pointSize, pointImg; + + if (arguments.length === 3) { + point = arguments[0]; + pointColor = arguments[1]; + pointSize = arguments[2]; + } else if (arguments.length === 2 && arguments[1] instanceof p5.Image) { + point = arguments[0]; + pointImg = arguments[1]; + } else if (arguments.length === 1) { + point = arguments[0]; + pointColor = this.pointColors[0]; + pointSize = this.pointSizes[0]; + } else { + throw new Error("GLayer.drawPoint(): signature not supported"); + } + + var xPlot = this.valueToXPlot(point.getX()); + var yPlot = this.valueToYPlot(point.getY()); + + if (this.isInside(xPlot, yPlot)) { + this.parent.push(); + + if ( typeof pointImg !== "undefined") { + this.parent.imageMode(this.parent.CENTER); + this.parent.image(pointImg, xPlot, yPlot); + } else { + this.parent.ellipseMode(this.parent.CENTER); + this.parent.fill(pointColor); + this.parent.noStroke(); + this.parent.ellipse(xPlot, yPlot, pointSize, pointSize); + } + + this.parent.pop(); + } +}; + +GLayer.prototype.drawLines = function() { + var nPoints = this.plotPoints.length; + + this.parent.push(); + this.parent.noFill(); + this.parent.stroke(this.lineColor); + this.parent.strokeWeight(this.lineWidth); + this.parent.strokeCap(this.parent.SQUARE); + + for (var i = 0; i < nPoints - 1; i++) { + if (this.inside[i] && this.inside[i + 1]) { + this.parent.line(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.plotPoints[i + 1].getX(), this.plotPoints[i + 1].getY()); + } else if (this.plotPoints[i].isValid() && this.plotPoints[i + 1].isValid()) { + // At least one of the points is outside the inner region. + // Obtain the valid line box intersections + var nCuts = this.obtainBoxIntersections(this.plotPoints[i], this.plotPoints[i + 1]); + + if (this.inside[i]) { + this.parent.line(this.plotPoints[i].getX(), this.plotPoints[i].getY(), this.cuts[0][0], this.cuts[0][1]); + } else if (this.inside[i + 1]) { + this.parent.line(this.cuts[0][0], this.cuts[0][1], this.plotPoints[i + 1].getX(), this.plotPoints[i + 1].getY()); + } else if (nCuts >= 2) { + this.parent.line(this.cuts[0][0], this.cuts[0][1], this.cuts[1][0], this.cuts[1][1]); + } + } + } + + this.parent.pop(); +}; + +GLayer.prototype.drawLine = function() { + var point1, point2, lc, lw, slope, ycut; + + if (arguments.length === 4 && arguments[0] instanceof GPoint) { + point1 = arguments[0]; + point2 = arguments[1]; + lc = arguments[2]; + lw = arguments[3]; + } else if (arguments.length === 4) { + slope = arguments[0]; + ycut = arguments[1]; + lc = arguments[2]; + lw = arguments[3]; + } else if (arguments.length === 2 && arguments[0] instanceof GPoint) { + point1 = arguments[0]; + point2 = arguments[1]; + lc = this.lineColor; + lw = this.lineWidth; + } else if (arguments.length === 2) { + slope = arguments[0]; + ycut = arguments[1]; + lc = this.lineColor; + lw = this.lineWidth; + } else { + throw new Error("GLayer.drawLine(): signature not supported"); + } + + if ( typeof slope !== "undefined") { + if (this.xLog && this.yLog) { + point1 = new GPoint(this.xLim[0], Math.pow(10, slope * Math.log(this.xLim[0]) / Math.LN10 + yCut)); + point2 = new GPoint(this.xLim[1], Math.pow(10, slope * Math.log(this.xLim[1]) / Math.LN10 + yCut)); + } else if (this.xLog) { + point1 = new GPoint(this.xLim[0], slope * Math.log(this.xLim[0]) / Math.LN10 + yCut); + point2 = new GPoint(this.xLim[1], slope * Math.log(this.xLim[1]) / Math.LN10 + yCut); + } else if (this.yLog) { + point1 = new GPoint(this.xLim[0], Math.pow(10, slope * this.xLim[0] + yCut)); + point2 = new GPoint(this.xLim[1], Math.pow(10, slope * this.xLim[1] + yCut)); + } else { + point1 = new GPoint(this.xLim[0], slope * this.xLim[0] + yCut); + point2 = new GPoint(this.xLim[1], slope * this.xLim[1] + yCut); + } + } + + var plotPoint1 = this.valueToPlot(point1); + var plotPoint2 = this.valueToPlot(point2); + + if (plotPoint1.isValid() && plotPoint2.isValid()) { + var inside1 = this.isInside(plotPoint1); + var inside2 = this.isInside(plotPoint2); + + this.parent.push(); + this.parent.noFill(); + this.parent.stroke(lc); + this.parent.strokeWeight(lw); + this.parent.strokeCap(this.parent.SQUARE); + + if (inside1 && inside2) { + this.parent.line(plotPoint1.getX(), plotPoint1.getY(), plotPoint2.getX(), plotPoint2.getY()); + } else { + // At least one of the points is outside the inner region. + // Obtain the valid line box intersections + var nCuts = this.obtainBoxIntersections(plotPoint1, plotPoint2); + + if (inside1) { + this.parent.line(plotPoint1.getX(), plotPoint1.getY(), this.cuts[0][0], this.cuts[0][1]); + } else if (inside2) { + this.parent.line(this.cuts[0][0], this.cuts[0][1], plotPoint2.getX(), plotPoint2.getY()); + } else if (nCuts >= 2) { + this.parent.line(this.cuts[0][0], this.cuts[0][1], this.cuts[1][0], this.cuts[1][1]); + } + } + + this.parent.pop(); + } +}; + +GLayer.prototype.drawHorizontalLine = function() { + var value, lc, lw; + + if (arguments.length === 3) { + value = arguments[0]; + lc = arguments[1]; + lw = arguments[2]; + } else if (arguments.length === 1) { + value = arguments[0]; + lc = this.lineColor; + lw = this.lineWidth; + } else { + throw new Error("GLayer.drawHorizontalLine(): signature not supported"); + } + + var yPlot = this.valueToYPlot(value); + + if (this.isValidNumber(yPlot) && -yPlot >= 0 && -yPlot <= this.dim[1]) { + this.parent.push(); + this.parent.noFill(); + this.parent.stroke(lc); + this.parent.strokeWeight(lw); + this.parent.strokeCap(this.parent.SQUARE); + this.parent.line(0, yPlot, this.dim[0], yPlot); + this.parent.pop(); + } +}; + +GLayer.prototype.drawVerticalLine = function() { + var value, lc, lw; + + if (arguments.length === 3) { + value = arguments[0]; + lc = arguments[1]; + lw = arguments[2]; + } else if (arguments.length === 1) { + value = arguments[0]; + lc = this.lineColor; + lw = this.lineWidth; + } else { + throw new Error("GLayer.drawVerticalLine(): signature not supported"); + } + + var xPlot = this.valueToXPlot(value); + + if (this.isValidNumber(xPlot) && xPlot >= 0 && xPlot <= this.dim[0]) { + this.parent.push(); + this.parent.noFill(); + this.parent.stroke(lc); + this.parent.strokeWeight(lw); + this.parent.strokeCap(this.parent.SQUARE); + this.parent.line(xPlot, 0, xPlot, -this.dim[1]); + this.parent.pop(); + } +}; + +GLayer.prototype.drawFilledContour = function(contourType, referenceValue) { + // Get the points that compose the shape + var shapePoints; + + if (contourType === GPlot.HORIZONTAL) { + shapePoints = this.getHorizontalShape(referenceValue); + } else if (contourType === GPlot.VERTICAL) { + shapePoints = this.getVerticalShape(referenceValue); + } + + // Draw the shape + if ( typeof shapePoints !== "undefined" && shapePoints.length > 0) { + this.parent.push(); + this.parent.fill(this.lineColor); + this.parent.noStroke(); + this.parent.beginShape(); + + for (var i = 0; i < shapePoints.length; i++) { + if (shapePoints[i].isValid()) { + this.parent.vertex(shapePoints[i].getX(), shapePoints[i].getY()); + } + } + + this.parent.endShape(this.parent.CLOSE); + this.parent.pop(); + } +}; + +GLayer.prototype.getHorizontalShape = function(referenceValue) { + // Collect the points and cuts inside the box + var point, addedPoints, nextIndex; + var nPoints = this.plotPoints.length; + var shapePoints = []; + var indexFirstPoint = -1; + var indexLastPoint = -1; + + for (var i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid()) { + addedPoints = false; + + // Add the point if it's inside the box + if (this.inside[i]) { + shapePoints.push(new GPoint(point.getX(), point.getY(), "normal point")); + addedPoints = true; + } else if (point.getX() >= 0 && point.getX() <= this.dim[0]) { + // If it's outside, add the projection of the point on the + // horizontal axes + if (-point.getY() < 0) { + shapePoints.push(new GPoint(point.getX(), 0, "projection")); + addedPoints = true; + } else { + shapePoints.push(new GPoint(point.getX(), -this.dim[1], "projection")); + addedPoints = true; + } + } + + // Add the box cuts if there is any + nextIndex = i + 1; + + while (nextIndex < nPoints - 1 && !this.plotPoints[nextIndex].isValid()) { + nextIndex++; + } + + if (nextIndex < nPoints && this.plotPoints[nextIndex].isValid()) { + var nCuts = this.obtainBoxIntersections(point, this.plotPoints[nextIndex]); + + for (var j = 0; j < nCuts; j++) { + shapePoints.push(new GPoint(this.cuts[j][0], this.cuts[j][1], "cut")); + addedPoints = true; + } + } + + if (addedPoints) { + if (indexFirstPoint < 0) { + indexFirstPoint = i; + } + + indexLastPoint = i; + } + } + } + + // Continue if there are points in the shape + if (shapePoints.length > 0) { + // Calculate the starting point + var startPoint = new GPoint(shapePoints[0]); + + if (startPoint.getX() !== 0 && startPoint.getX() !== this.dim[0]) { + if (startPoint.getLabel() === "cut") { + if (this.plotPoints[indexFirstPoint].getX() < 0) { + startPoint.setX(0); + startPoint.setLabel("extreme"); + } else { + startPoint.setX(this.dim[0]); + startPoint.setLabel("extreme"); + } + } else if (indexFirstPoint !== 0) { + // Get the previous valid point + var prevIndex = indexFirstPoint - 1; + + while (prevIndex > 0 && !this.plotPoints[prevIndex].isValid()) { + prevIndex--; + } + + if (this.plotPoints[prevIndex].isValid()) { + if (this.plotPoints[prevIndex].getX() < 0) { + startPoint.setX(0); + startPoint.setLabel("extreme"); + } else { + startPoint.setX(this.dim[0]); + startPoint.setLabel("extreme"); + } + } + } + } + + // Calculate the end point + var endPoint = new GPoint(shapePoints[shapePoints.length - 1]); + + if (endPoint.getX() !== 0 && endPoint.getX() !== this.dim[0] && indexLastPoint !== nPoints - 1) { + nextIndex = indexLastPoint + 1; + + while (nextIndex < nPoints - 1 && !this.plotPoints[nextIndex].isValid()) { + nextIndex++; + } + + if (this.plotPoints[nextIndex].isValid()) { + if (this.plotPoints[nextIndex].getX() < 0) { + endPoint.setX(0); + endPoint.setLabel("extreme"); + } else { + endPoint.setX(this.dim[0]); + endPoint.setLabel("extreme"); + } + } + } + + // Add the end point if it's a new extreme + if (endPoint.getLabel() === "extreme") { + shapePoints.push(endPoint); + } + + // Add the reference connections + if (this.yLog && referenceValue <= 0) { + referenceValue = Math.min(this.yLim[0], this.yLim[1]); + } + + var plotReference = this.valueToPlot(1, referenceValue); + + if (-plotReference[1] < 0) { + shapePoints.push(new GPoint(endPoint.getX(), 0)); + shapePoints.push(new GPoint(startPoint.getX(), 0)); + } else if (-plotReference[1] > this.dim[1]) { + shapePoints.push(new GPoint(endPoint.getX(), -this.dim[1])); + shapePoints.push(new GPoint(startPoint.getX(), -this.dim[1])); + } else { + shapePoints.push(new GPoint(endPoint.getX(), plotReference[1])); + shapePoints.push(new GPoint(startPoint.getX(), plotReference[1])); + } + + // Add the starting point if it's a new extreme + if (startPoint.getLabel() === "extreme") { + shapePoints.push(startPoint); + } + } + + return shapePoints; +}; + +GLayer.prototype.getVerticalShape = function(referenceValue) { + // Collect the points and cuts inside the box + var point, addedPoints, nextIndex; + var nPoints = this.plotPoints.length; + var shapePoints = []; + var indexFirstPoint = -1; + var indexLastPoint = -1; + + for (var i = 0; i < nPoints; i++) { + point = this.plotPoints[i]; + + if (point.isValid()) { + addedPoints = false; + + // Add the point if it's inside the box + if (this.inside[i]) { + shapePoints.push(new GPoint(point.getX(), point.getY(), "normal point")); + addedPoints = true; + } else if (-point.getY() >= 0 && -point.getY() <= this.dim[1]) { + // If it's outside, add the projection of the point on the + // vertical axes + if (point.getX() < 0) { + shapePoints.push(new GPoint(0, point.getY(), "projection")); + addedPoints = true; + } else { + shapePoints.push(new GPoint(this.dim[0], point.getY(), "projection")); + addedPoints = true; + } + } + + // Add the box cuts if there is any + nextIndex = i + 1; + + while (nextIndex < nPoints - 1 && !this.plotPoints[nextIndex].isValid()) { + nextIndex++; + } + + if (nextIndex < nPoints && this.plotPoints[nextIndex].isValid()) { + var nCuts = this.obtainBoxIntersections(point, this.plotPoints[nextIndex]); + + for (var j = 0; j < nCuts; j++) { + shapePoints.push(new GPoint(this.cuts[j][0], this.cuts[j][1], "cut")); + addedPoints = true; + } + } + + if (addedPoints) { + if (indexFirstPoint < 0) { + indexFirstPoint = i; + } + + indexLastPoint = i; + } + } + } + + // Continue if there are points in the shape + if (shapePoints.length > 0) { + // Calculate the starting point + var startPoint = new GPoint(shapePoints[0]); + + if (startPoint.getY() !== 0 && startPoint.getY() !== -this.dim[1]) { + if (startPoint.getLabel() === "cut") { + if (-this.plotPoints[indexFirstPoint].getY() < 0) { + startPoint.setY(0); + startPoint.setLabel("extreme"); + } else { + startPoint.setY(-this.dim[1]); + startPoint.setLabel("extreme"); + } + } else if (indexFirstPoint !== 0) { + // Get the previous valid point + var prevIndex = indexFirstPoint - 1; + + while (prevIndex > 0 && !this.plotPoints[prevIndex].isValid()) { + prevIndex--; + } + + if (this.plotPoints[prevIndex].isValid()) { + if (-this.plotPoints[prevIndex].getY() < 0) { + startPoint.setY(0); + startPoint.setLabel("extreme"); + } else { + startPoint.setY(-this.dim[1]); + startPoint.setLabel("extreme"); + } + } + } + } + + // Calculate the end point + var endPoint = new GPoint(shapePoints[shapePoints.length - 1]); + + if (endPoint.getY() !== 0 && endPoint.getY() !== -this.dim[1] && indexLastPoint !== nPoints - 1) { + nextIndex = indexLastPoint + 1; + + while (nextIndex < nPoints - 1 && !this.plotPoints[nextIndex].isValid()) { + nextIndex++; + } + + if (this.plotPoints[nextIndex].isValid()) { + if (-this.plotPoints[nextIndex].getY() < 0) { + endPoint.setY(0); + endPoint.setLabel("extreme"); + } else { + endPoint.setY(-this.dim[1]); + endPoint.setLabel("extreme"); + } + } + } + + // Add the end point if it's a new extreme + if (endPoint.getLabel() === "extreme") { + shapePoints.push(endPoint); + } + + // Add the reference connections + if (this.xLog && referenceValue <= 0) { + referenceValue = Math.min(this.xLim[0], this.xLim[1]); + } + + var plotReference = this.valueToPlot(referenceValue, 1); + + if (plotReference[0] < 0) { + shapePoints.push(new GPoint(0, endPoint.getY())); + shapePoints.push(new GPoint(0, startPoint.getY())); + } else if (plotReference[0] > this.dim[0]) { + shapePoints.push(new GPoint(this.dim[0], endPoint.getY())); + shapePoints.push(new GPoint(this.dim[0], startPoint.getY())); + } else { + shapePoints.push(new GPoint(plotReference[0], endPoint.getY())); + shapePoints.push(new GPoint(plotReference[0], startPoint.getY())); + } + + // Add the starting point if it's a new extreme + if (startPoint.getLabel() === "extreme") { + shapePoints.push(startPoint); + } + } + + return shapePoints; +}; + +GLayer.prototype.drawAllLabels = function() { + for (var n = 0; n < this.points.length; n++) { + this.drawLabel(this.points[n]); + } +} + +GLayer.prototype.drawLabel = function(point) { + var xPlot = this.valueToXPlot(point.getX()); + var yPlot = this.valueToYPlot(point.getY()); + + if (this.isValidNumber(xPlot) && this.isValidNumber(yPlot)) { + var xLabelPos = xPlot + this.labelSeparation[0]; + var yLabelPos = yPlot - 0*this.labelSeparation[1] + 6; + var delta = this.fontSize / 4; + + this.parent.push(); + this.parent.rectMode(this.parent.CORNER); + this.parent.noStroke(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.textAlign(this.parent.LEFT, this.parent.BOTTOM); + + // Draw the background + this.parent.fill(this.labelBgColor); + this.parent.rect(xLabelPos - delta, yLabelPos - this.fontSize - delta, this.parent.textWidth(point.getLabel()) + 2 * delta, this.fontSize + 2 * delta); + + // Draw the text + this.parent.fill(this.fontColor); + this.parent.text(point.getLabel(), xLabelPos, yLabelPos); + this.parent.pop(); + } +}; + +GLayer.prototype.drawLabelAtPlotPos = function(xPlot, yPlot) { + var point = this.getPointAtPlotPos(xPlot, yPlot); + + if ( typeof point !== "undefined") { + this.drawLabel(point); + } +}; + +GLayer.prototype.drawHistogram = function() { + if ( typeof this.hist !== "undefined") { + this.hist.draw(this.valueToPlot(this.histBasePoint)); + } +}; + +GLayer.prototype.drawPolygon = function(polygonPoints, polygonColor) { + var i; + + if (polygonPoints.length > 2) { + // Remove the polygon invalid points + var plotPolygonPoints = this.valueToPlot(polygonPoints); + var counter = 0; + + for ( i = 0; i < plotPolygonPoints.length; i++) { + if (plotPolygonPoints[i].isValid()) { + plotPolygonPoints[counter] = plotPolygonPoints[i]; + counter++; + } + } + + plotPolygonPoints.splice(counter, Number.MAX_VALUE); + + // Create a temporal array with the points inside the plotting area + // and the valid box cuts + var point; + var nPoints = plotPolygonPoints.length; + var tmp = []; + + for ( i = 0; i < nPoints; i++) { + point = plotPolygonPoints[i]; + + if (this.isInside(point)) { + tmp.push(new GPoint(point.getX(), point.getY(), "normal point")); + } + + // Obtain the cuts with the next point + var nextIndex = (i + 1 < nPoints) ? i + 1 : 0; + var nCuts = this.obtainBoxIntersections(point, plotPolygonPoints[nextIndex]); + + if (nCuts === 1) { + tmp.push(new GPoint(this.cuts[0][0], this.cuts[0][1], "single cut")); + } else if (nCuts > 1) { + tmp.push(new GPoint(this.cuts[0][0], this.cuts[0][1], "double cut")); + tmp.push(new GPoint(this.cuts[1][0], this.cuts[1][1], "double cut")); + } + } + + // Final version of the polygon + nPoints = tmp.length; + var croppedPoly = []; + + for ( i = 0; i < nPoints; i++) { + // Add the point + croppedPoly.push(tmp[i]); + + // Add new points in case we have two consecutive cuts, one of + // them is single, and they are in consecutive axes + var next = (i + 1 < nPoints) ? i + 1 : 0; + var label = tmp[i].getLabel(); + var nextLabel = tmp[next].getLabel(); + + var cond = (label === "single cut" && nextLabel === "single cut") || (label === "single cut" && nextLabel === "double cut") || (label === "double cut" && nextLabel === "single cut"); + + if (cond) { + var x1 = tmp[i].getX(); + var y1 = tmp[i].getY(); + var x2 = tmp[next].getX(); + var y2 = tmp[next].getY(); + var deltaX = Math.abs(x2 - x1); + var deltaY = Math.abs(y2 - y1); + + // Check that they come from consecutive axes + if (deltaX > 0 && deltaY > 0 && deltaX !== this.dim[0] && deltaY !== this.dim[1]) { + var x = (x1 === 0 || x1 === this.dim[0]) ? x1 : x2; + var y = (y1 === 0 || y1 === -this.dim[1]) ? y1 : y2; + croppedPoly.push(new GPoint(x, y, "special cut")); + } + } + } + + // Draw the cropped polygon + if (croppedPoly.length > 2) { + this.parent.push(); + this.parent.fill(polygonColor); + this.parent.noStroke(); + this.parent.beginShape(); + + for ( i = 0; i < croppedPoly.length; i++) { + this.parent.vertex(croppedPoly[i].getX(), croppedPoly[i].getY()); + } + + this.parent.endShape(this.parent.CLOSE); + this.parent.pop(); + } + } +}; + +GLayer.prototype.drawAnnotation = function(text, x, y, horAlign, verAlign) { + var xPlot = this.valueToXPlot(x); + var yPlot = this.valueToYPlot(y); + + if (this.isValidNumber(xPlot) && this.isValidNumber(yPlot) && this.isInside(xPlot, yPlot)) { + if (horAlign !== this.parent.CENTER && horAlign !== this.parent.RIGHT && horAlign !== this.parent.LEFT) { + horAlign = this.parent.LEFT; + } + + if (verAlign !== this.parent.CENTER && verAlign !== this.parent.TOP && verAlign !== this.parent.BOTTOM) { + verAlign = this.parent.CENTER; + } + + // A trick to really center the text vertically + if (verAlign === this.parent.CENTER) { + verAlign = this.parent.BOTTOM; + yPlot += this.fontSize / 2; + } + + this.parent.push(); + this.parent.textFont(this.fontName); + this.parent.textSize(this.fontSize); + this.parent.fill(this.fontColor); + this.parent.textAlign(horAlign, verAlign); + this.parent.text(text, xPlot, yPlot); + this.parent.pop(); + } +}; + +GLayer.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GLayer.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + this.dim[0] = xDim; + this.dim[1] = yDim; + this.updatePlotPoints(); + + if ( typeof this.hist !== "undefined") { + this.hist.setDim(this.dim); + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.setXLim = function() { + var xMin, xMax; + + if (arguments.length === 2) { + xMin = arguments[0]; + xMax = arguments[1]; + } else if (arguments.length === 1) { + xMin = arguments[0][0]; + xMax = arguments[0][1]; + } else { + throw new Error("GLayer.setXLim(): signature not supported"); + } + + if (xMin !== xMax && this.isValidNumber(xMin) && this.isValidNumber(xMax)) { + // Make sure the new limits makes sense + if (this.xLog && (xMin <= 0 || xMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.xLim[0] = xMin; + this.xLim[1] = xMax; + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } + } +}; + +GLayer.prototype.setYLim = function() { + var yMin, yMax; + + if (arguments.length === 2) { + yMin = arguments[0]; + yMax = arguments[1]; + } else if (arguments.length === 1) { + yMin = arguments[0][0]; + yMax = arguments[0][1]; + } else { + throw new Error("GLayer.setYLim(): signature not supported"); + } + + if (yMin !== yMax && this.isValidNumber(yMin) && this.isValidNumber(yMax)) { + // Make sure the new limits makes sense + if (this.yLog && (yMin <= 0 || yMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.yLim[0] = yMin; + this.yLim[1] = yMax; + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } + } +}; + +GLayer.prototype.setXYLim = function() { + var xMin, xMax, yMin, yMax; + + if (arguments.length === 4) { + xMin = arguments[0]; + xMax = arguments[1]; + yMin = arguments[2]; + yMax = arguments[3]; + } else if (arguments.length === 2) { + xMin = arguments[0][0]; + xMax = arguments[0][1]; + yMin = arguments[1][0]; + yMax = arguments[1][1]; + } else { + throw new Error("GLayer.setXYLim(): signature not supported"); + } + + if (xMin !== xMax && yMin !== yMax && this.isValidNumber(xMin) && this.isValidNumber(xMax) && this.isValidNumber(yMin) && this.isValidNumber(yMax)) { + // Make sure the new limits make sense + if (this.xLog && (xMin <= 0 || xMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.xLim[0] = xMin; + this.xLim[1] = xMax; + } + + if (this.yLog && (yMin <= 0 || yMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.yLim[0] = yMin; + this.yLim[1] = yMax; + } + + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.setLimAndLog = function() { + var xMin, xMax, yMin, yMax, xLog, yLog; + + if (arguments.length === 6) { + xMin = arguments[0]; + xMax = arguments[1]; + yMin = arguments[2]; + yMax = arguments[3]; + xLog = arguments[4]; + yLog = arguments[5]; + } else if (arguments.length === 4) { + xMin = arguments[0][0]; + xMax = arguments[0][1]; + yMin = arguments[1][0]; + yMax = arguments[1][1]; + xLog = arguments[2]; + yLog = arguments[3]; + } else { + throw new Error("GLayer.setLimAndLog(): signature not supported"); + } + + if (xMin !== xMax && yMin !== yMax && this.isValidNumber(xMin) && this.isValidNumber(xMax) && this.isValidNumber(yMin) && this.isValidNumber(yMax)) { + // Make sure the new limits make sense + if (xLog && (xMin <= 0 || xMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.xLim[0] = xMin; + this.yLim[1] = xMax; + this.xLog = xLog; + } + + if (yLog && (yMin <= 0 || yMax <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.yLim[0] = yMin; + this.yLim[1] = yMax; + this.yLog = yLog; + } + + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.setXLog = function(xLog) { + if (xLog !== this.xLog) { + if (xLog && (this.xLim[0] <= 0 || this.xLim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + console.log("Will set horizontal limits to (0.1, 10)"); + this.xLim[0] = 0.1; + this.xLim[1] = 10; + } + + this.xLog = xLog; + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.setYLog = function(yLog) { + if (yLog !== this.yLog) { + if (yLog && (this.yLim[0] <= 0 || this.yLim[1] <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + console.log("Will set horizontal limits to (0.1, 10)"); + this.yLim[0] = 0.1; + this.yLim[1] = 10; + } + + this.yLog = yLog; + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.setPoints = function(points) { + var i; + var nPoints = points.length; + + if (this.points.length > nPoints) { + this.points.splice(nPoints, Number.MAX_VALUE); + } else { + for ( i = this.points.length; i < nPoints; i++) { + this.points[i] = new GPoint(); + } + } + + for ( i = 0; i < nPoints; i++) { + this.points[i].set(points[i]); + } + + this.updatePlotPoints(); + this.updateInsideList(); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } +}; + +GLayer.prototype.setPoint = function() { + var index, x, y, label; + var nPoints = this.points.length; + + if (arguments.length === 4) { + index = arguments[0]; + x = arguments[1]; + y = arguments[2]; + label = arguments[3]; + } else if (arguments.length === 3) { + index = arguments[0]; + x = arguments[1]; + y = arguments[2]; + label = (index < nPoins) ? this.points[index].getLabel() : ""; + } else if (arguments.length === 2) { + index = arguments[0]; + x = arguments[1].getX(); + y = arguments[1].getY(); + label = arguments[1].getLabel(); + } else { + throw new Error("GLayer.setPoint(): signature not supported"); + } + + if (index < nPoints) { + this.points[index].set(x, y, label); + this.plotPoints[index].set(this.valueToXPlot(x), this.valueToYPlot(y), label); + this.inside[index] = this.isInside(this.plotPoints[index]); + } else if (index === nPoints) { + this.points[index] = new GPoint(x, y, label); + this.plotPoints[index] = new GPoint(this.valueToXPlot(x), this.valueToYPlot(y), label); + this.inside[index] = this.isInside(this.plotPoints[index]); + } else { + throw new Error("GLayer.setPoint(): the index position is outside the array size"); + } + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoint(index, this.plotPoints[index]); + } +}; + +GLayer.prototype.addPoint = function() { + var x, y, label; + + if (arguments.length === 3) { + x = arguments[0]; + y = arguments[1]; + label = arguments[2]; + } else if (arguments.length === 2) { + x = arguments[0]; + y = arguments[1]; + label = ""; + } else if (arguments.length === 1) { + x = arguments[0].getX(); + y = arguments[0].getY(); + label = arguments[0].getLabel(); + } else { + throw new Error("GLayer.addPoint(): signature not supported"); + } + + this.points.push(new GPoint(x, y, label)); + this.plotPoints.push(new GPoint(this.valueToXPlot(x), this.valueToYPlot(y), label)); + this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length - 1])); + + if ( typeof this.hist !== "undefined") { + this.hist.addPlotPoint(this.plotPoints[this.plotPoints.length - 1]); + } +}; + +GLayer.prototype.addPoints = function(newPoints) { + var newPoint; + var nNewPoints = newPoints.length; + + for (var i = 0; i < nNewPoints; i++) { + newPoint = newPoints[i]; + this.points.push(new GPoint(newPoint)); + this.plotPoints.push(new GPoint(this.valueToXPlot(newPoint.getX()), this.valueToYPlot(newPoint.getY()), newPoint.getLabel())); + this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length - 1])); + } + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } +}; + +GLayer.prototype.addPointAtIndexPos = function() { + var index, x, y, label; + + if (arguments.length === 4) { + index = arguments[0]; + x = arguments[1]; + y = arguments[2]; + label = arguments[3]; + } else if (arguments.length === 3) { + index = arguments[0]; + x = arguments[1]; + y = arguments[2]; + label = ""; + } else if (arguments.length === 2) { + index = arguments[0]; + x = arguments[1].getX(); + y = arguments[1].getY(); + label = arguments[1].getLabel(); + } else { + throw new Error("GLayer.addPointAtIndexPos(): signature not supported"); + } + + if (index <= this.points.length) { + this.points.splice(index, 0, new GPoint(x, y, label)); + this.plotPoints.splice(index, 0, new GPoint(this.valueToXPlot(x), this.valueToYPlot(y), label)); + this.inside.splice(index, 0, this.isInside(this.plotPoints[0])); + + if ( typeof this.hist !== "undefined") { + this.hist.setPlotPoints(this.plotPoints); + } + } +}; + +GLayer.prototype.removePoint = function(index) { + if (index < this.points.length) { + this.points.splice(index, 1); + this.plotPoints.splice(index, 1); + this.inside.splice(index, 1); + + if ( typeof this.hist !== "undefined") { + this.hist.removePlotPoint(index); + } + } +}; + +GLayer.prototype.setInside = function(inside) { + if (inside.length === this.inside.length) { + this.inside = inside.slice(); + } +}; + +GLayer.prototype.setPointColors = function(pointColors) { + if (pointColors.length > 0) { + this.pointColors = pointColors.slice(); + } +}; + +GLayer.prototype.setPointColor = function(pointColor) { + this.pointColors = [pointColor]; +}; + +GLayer.prototype.setPointSizes = function(pointSizes) { + if (pointSizes.length > 0) { + this.pointSizes = pointSizes.slice(); + } +}; + +GLayer.prototype.setPointSize = function(pointSize) { + this.pointSizes = [pointSize]; +}; + +GLayer.prototype.setLineColor = function(lineColor) { + this.lineColor = lineColor; +}; + +GLayer.prototype.setLineWidth = function(lineWidth) { + if (lineWidth > 0) { + this.lineWidth = lineWidth; + } +}; + +GLayer.prototype.setHistBasePoint = function(histBasePoint) { + this.histBasePoint.set(histBasePoint); +}; + +GLayer.prototype.setHistType = function(histType) { + if ( typeof this.hist !== "undefined") { + this.hist.setType(histType); + } +}; + +GLayer.prototype.setHistVisible = function(visible) { + if ( typeof this.hist !== "undefined") { + this.hist.setVisible(visible); + } +}; + +GLayer.prototype.setDrawHistLabels = function(drawHistLabels) { + if ( typeof this.hist !== "undefined") { + this.hist.setDrawLabels(drawHistLabels); + } +}; + +GLayer.prototype.setLabelBgColor = function(labelBgColor) { + this.labelBgColor = labelBgColor; +}; + +GLayer.prototype.setLabelSeparation = function(labelSeparation) { + this.labelSeparation[0] = labelSeparation[0]; + this.labelSeparation[1] = labelSeparation[1]; +}; + +GLayer.prototype.setFontName = function(fontName) { + this.fontName = fontName; +}; + +GLayer.prototype.setFontColor = function(fontColor) { + this.fontColor = fontColor; +}; + +GLayer.prototype.setFontSize = function(fontSize) { + if (fontSize > 0) { + this.fontSize = fontSize; + } +}; + +GLayer.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + if (fontSize > 0) { + this.fontName = fontName; + this.fontColor = fontColor; + this.fontSize = fontSize; + } +}; + +GLayer.prototype.setAllFontProperties = function(fontName, fontColor, fontSize) { + this.setFontProperties(fontName, fontColor, fontSize); + + if ( typeof this.hist !== "undefined") { + this.hist.setFontProperties(fontName, fontColor, fontSize); + } +}; + +GLayer.prototype.getId = function() { + return this.id; +}; + +GLayer.prototype.getDim = function() { + return this.dim.slice(); +}; + +GLayer.prototype.getXLim = function() { + return this.xLim.slice(); +}; + +GLayer.prototype.getYLim = function() { + return this.yLim.slice(); +}; + +GLayer.prototype.getXLog = function() { + return this.xLog; +}; + +GLayer.prototype.getYLog = function() { + return this.yLog; +}; + +GLayer.prototype.getPoints = function() { + var points = []; + + for (var i = 0; i < this.points.length; i++) { + points[i] = new GPoint(this.points[i]); + } + + return points; +}; + +GLayer.prototype.getPointsRef = function() { + return this.points; +}; + +GLayer.prototype.getPointColors = function() { + return this.pointColors.slice(); +}; + +GLayer.prototype.getPointSizes = function() { + return this.pointSizes.slice(); +}; + +GLayer.prototype.getLineColor = function() { + return this.lineColor; +}; + +GLayer.prototype.getLineWidth = function() { + return this.lineWidth; +}; + +GLayer.prototype.getHistogram = function() { + return this.hist; +}; +/* + * Plot class. It controls the rest of the graphical elements (layers, axes, + * title, limits). + */ +function GPlot() { + var parent, xPos, yPos, plotWidth, plotHeight; + + if (arguments.length === 5) { + parent = arguments[0]; + xPos = arguments[1]; + yPos = arguments[2]; + plotWidth = arguments[3]; + plotHeight = arguments[4]; + } else if (arguments.length === 3) { + parent = arguments[0]; + xPos = arguments[1]; + yPos = arguments[2]; + plotWidth = 450; + plotHeight = 300; + } else if (arguments.length === 1) { + parent = arguments[0]; + xPos = 0; + yPos = 0; + plotWidth = 450; + plotHeight = 300; + } else { + throw new Error("GPlot constructor: signature not supported"); + } + + // The parent processing object + this.parent = parent; + + // General properties + this.pos = [xPos, yPos]; + this.outerDim = [plotWidth, plotHeight]; + this.mar = [60, 70, 40, 30]; + this.dim = [this.outerDim[0] - this.mar[1] - this.mar[3], this.outerDim[1] - this.mar[0] - this.mar[2]]; + this.xLim = [0, 1]; + this.yLim = [0, 1]; + this.fixedXLim = false; + this.fixedYLim = false; + this.xLog = false; + this.yLog = false; + this.invertedXScale = false; + this.invertedYScale = false; + this.includeAllLayersInLim = true; + this.expandLimFactor = 0.1; + + // Format properties + this.bgColor = this.parent.color(255); + this.boxBgColor = this.parent.color(245); + this.boxLineColor = this.parent.color(210); + this.boxLineWidth = 1; + this.gridLineColor = this.parent.color(210); + this.gridLineWidth = 1; + + // Layers + this.mainLayer = new GLayer(this.parent, GPlot.MAINLAYERID, this.dim, this.xLim, this.yLim, this.xLog, this.yLog); + this.layerList = []; + + // Axes and title + this.xAxis = new GAxis(this.parent, this.parent.BOTTOM, this.dim, this.xLim, this.xLog); + this.topAxis = new GAxis(this.parent, this.parent.TOP, this.dim, this.xLim, this.xLog); + this.yAxis = new GAxis(this.parent, this.parent.LEFT, this.dim, this.yLim, this.yLog); + this.rightAxis = new GAxis(this.parent, this.parent.RIGHT, this.dim, this.yLim, this.yLog); + this.title = new GTitle(this.parent, this.dim); + + // Setup for the mouse events + this.zoomingIsActive = false; + this.zoomFactor = 1.3; + this.increaseZoomButton = this.parent.LEFT; + this.decreaseZoomButton = this.parent.RIGHT; + this.increaseZoomKeyModifier = GPlot.NONE; + this.decreaseZoomKeyModifier = GPlot.NONE; + this.centeringIsActive = false; + this.centeringButton = this.parent.LEFT; + this.centeringKeyModifier = GPlot.NONE; + this.panningIsActive = false; + this.panningButton = this.parent.LEFT; + this.panningKeyModifier = GPlot.NONE; + this.panningReferencePoint = undefined; + this.panningIntervalId = undefined; + this.labelingIsActive = false; + this.labelingButton = this.parent.LEFT; + this.labelingKeyModifier = GPlot.NONE; + this.mousePos = undefined; + this.resetIsActive = false; + this.resetButton = this.parent.RIGHT; + this.resetKeyModifier = this.parent.CONTROL; + this.xLimReset = undefined; + this.yLimReset = undefined; + + // Add the event listeners + window.addEventListener("click", this.clickEvent.bind(this), false); + window.addEventListener("mousedown", this.mouseDownEvent.bind(this), false); + window.addEventListener("touchstart", this.mouseDownEvent.bind(this), false); + window.addEventListener("mouseup", this.mouseUpEvent.bind(this), false); + window.addEventListener("touchend", this.mouseUpEvent.bind(this), false); + window.addEventListener("wheel", this.wheelEvent.bind(this), false); +} + +// Constants +GPlot.MAINLAYERID = "main layer"; +GPlot.VERTICAL = 0; +GPlot.HORIZONTAL = 1; +GPlot.BOTH = 2; +GPlot.NONE = 0; + +GPlot.prototype.addLayer = function() { + var id, layer; + + if (arguments.length === 2) { + id = arguments[0]; + layer = new GLayer(this.parent, id, this.dim, this.xLim, this.yLim, this.xLog, this.yLog); + layer.setPoints(arguments[1]); + } else if (arguments.length === 1) { + id = arguments[0].getId(); + layer = arguments[0]; + } else { + throw new Error("GPlot.addLayer(): signature not supported"); + } + + // Check that it is the only layer with that id + var sameId = false; + + if (this.mainLayer.isId(id)) { + sameId = true; + } else { + for (var i = 0; i < this.layerList.length; i++) { + if (this.layerList[i].isId(id)) { + sameId = true; + break; + } + } + } + + // Add the layer to the list + if (!sameId) { + layer.setDim(this.dim); + layer.setLimAndLog(this.xLim, this.yLim, this.xLog, this.yLog); + this.layerList.push(layer); + + // Calculate and update the new plot limits if necessary + if (this.includeAllLayersInLim) { + this.updateLimits(); + } + } else { + console.log("A layer with the same id exists. Please change the id and try to add it again."); + } +}; + +GPlot.prototype.removeLayer = function(id) { + var index; + + for (var i = 0; i < this.layerList.length; i++) { + if (this.layerList[i].isId(id)) { + index = i; + break; + } + } + + if ( typeof index !== "undefined") { + this.layerList.splice(index, 1); + + // Calculate and update the new plot limits if necessary + if (this.includeAllLayersInLim) { + this.updateLimits(); + } + } else { + console.log("Couldn't find a layer in the plot with id = " + id); + } +}; + +GPlot.prototype.getPlotPosAt = function(xScreen, yScreen) { + var xPlot = xScreen - (this.pos[0] + this.mar[1]); + var yPlot = yScreen - (this.pos[1] + this.mar[2] + this.dim[1]); + + return [xPlot, yPlot]; +}; + +GPlot.prototype.getScreenPosAtValue = function(xValue, yValue) { + var xScreen = this.mainLayer.valueToXPlot(xValue) + (this.pos[0] + this.mar[1]); + var yScreen = this.mainLayer.valueToYPlot(yValue) + (this.pos[1] + this.mar[2] + this.dim[1]); + + return [xScreen, yScreen]; +}; + +GPlot.prototype.getPointAt = function() { + var xScreen, yScreen, layer; + + if (arguments.length === 3) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layer = this.getLayer(arguments[2]); + } else if (arguments.length === 2) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layer = this.mainLayer; + } else { + throw new Error("GPlot.getPointAt(): signature not supported"); + } + + var plotPos = this.getPlotPosAt(xScreen, yScreen); + return layer.getPointAtPlotPos(plotPos[0], plotPos[1]); +}; + +GPlot.prototype.addPointAt = function() { + var xScreen, yScreen, layerId; + + if (arguments.length === 3) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layerId = arguments[2]; + } else if (arguments.length === 2) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layerId = GPlot.MAINLAYERID; + } else { + throw new Error("GPlot.addPointAt(): signature not supported"); + } + + var value = this.getValueAt(xScreen, yScreen); + this.addPoint(value[0], value[1], "", layerId); +}; + +GPlot.prototype.removePointAt = function() { + var xScreen, yScreen, layerId; + + if (arguments.length === 3) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layerId = arguments[2]; + } else if (arguments.length === 2) { + xScreen = arguments[0]; + yScreen = arguments[1]; + layerId = GPlot.MAINLAYERID; + } else { + throw new Error("GPlot.removePointAt(): signature not supported"); + } + + var plotPos = this.getPlotPosAt(xScreen, yScreen); + var pointIndex = this.getLayer(layerId).getPointIndexAtPlotPos(plotPos[0], plotPos[1]); + + if ( typeof pointIndex !== "undefined") { + this.removePoint(pointIndex, layerId); + } +}; + +GPlot.prototype.getValueAt = function(xScreen, yScreen) { + var plotPos = this.getPlotPosAt(xScreen, yScreen); + return this.mainLayer.plotToValue(plotPos[0], plotPos[1]); +}; + +GPlot.prototype.getRelativePlotPosAt = function(xScreen, yScreen) { + var plotPos = this.getPlotPosAt(xScreen, yScreen); + return [plotPos[0] / this.dim[0], -plotPos[1] / this.dim[1]]; +}; + +GPlot.prototype.isOverPlot = function() { + var xScreen, yScreen; + + if (arguments.length === 2) { + xScreen = arguments[0]; + yScreen = arguments[1]; + } else if (arguments.length === 0) { + xScreen = this.parent.mouseX; + yScreen = this.parent.mouseY; + } else { + throw new Error("GPlot.isOverPlot(): signature not supported"); + } + + return (xScreen >= this.pos[0]) && (xScreen <= this.pos[0] + this.outerDim[0]) && (yScreen >= this.pos[1]) && (yScreen <= this.pos[1] + this.outerDim[1]); +}; + +GPlot.prototype.isOverBox = function() { + var xScreen, yScreen; + + if (arguments.length === 2) { + xScreen = arguments[0]; + yScreen = arguments[1]; + } else if (arguments.length === 0) { + xScreen = this.parent.mouseX; + yScreen = this.parent.mouseY; + } else { + throw new Error("GPlot.isOverBox(): signature not supported"); + } + + return (xScreen >= this.pos[0] + this.mar[1]) && (xScreen <= this.pos[0] + this.outerDim[0] - this.mar[3]) && (yScreen >= this.pos[1] + this.mar[2]) && (yScreen <= this.pos[1] + this.outerDim[1] - this.mar[0]); +}; + +GPlot.prototype.updateLimits = function() { + // Calculate the new limits and update the axes if needed + if (!this.fixedXLim) { + this.xLim = this.calculatePlotXLim(); + this.xAxis.setLim(this.xLim); + this.topAxis.setLim(this.xLim); + } + + if (!this.fixedYLim) { + this.yLim = this.calculatePlotYLim(); + this.yAxis.setLim(this.yLim); + this.rightAxis.setLim(this.yLim); + } + + // Update the layers + this.mainLayer.setXYLim(this.xLim, this.yLim); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].setXYLim(this.xLim, this.yLim); + } +}; + +GPlot.prototype.calculatePlotXLim = function() { + // Find the limits for the main layer + var lim = this.calculatePointsXLim(this.mainLayer.getPointsRef()); + + // Include the other layers in the limit calculation if necessary + if (this.includeAllLayersInLim) { + for (var i = 0; i < this.layerList.length; i++) { + var newLim = this.calculatePointsXLim(this.layerList[i].getPointsRef()); + + if ( typeof newLim !== "undefined") { + if ( typeof lim !== "undefined") { + lim[0] = Math.min(lim[0], newLim[0]); + lim[1] = Math.max(lim[1], newLim[1]); + } else { + lim = newLim; + } + } + } + } + + if ( typeof lim !== "undefined") { + // Expand the axis limits a bit + var delta = (lim[0] === 0) ? 0.1 : 0.1 * lim[0]; + + if (this.xLog) { + if (lim[0] !== lim[1]) { + delta = Math.exp(this.expandLimFactor * Math.log(lim[1] / lim[0])); + } + + lim[0] = lim[0] / delta; + lim[1] = lim[1] * delta; + } else { + if (lim[0] !== lim[1]) { + delta = this.expandLimFactor * (lim[1] - lim[0]); + } + + lim[0] = lim[0] - delta; + lim[1] = lim[1] + delta; + } + } else { + if (this.xLog && (this.xLim[0] <= 0 || this.xLim[1] <= 0)) { + lim = [0.1, 10]; + } else { + lim = this.xLim.slice(); + } + } + + // Invert the limits if necessary + if (this.invertedXScale && lim[0] < lim[1]) { + lim = [lim[1], lim[0]]; + } + + return lim; +}; + +GPlot.prototype.calculatePlotYLim = function() { + // Find the limits for the main layer + var lim = this.calculatePointsYLim(this.mainLayer.getPointsRef()); + + // Include the other layers in the limit calculation if necessary + if (this.includeAllLayersInLim) { + for (var i = 0; i < this.layerList.length; i++) { + var newLim = this.calculatePointsYLim(this.layerList[i].getPointsRef()); + + if ( typeof newLim !== "undefined") { + if ( typeof lim !== "undefined") { + lim[0] = Math.min(lim[0], newLim[0]); + lim[1] = Math.max(lim[1], newLim[1]); + } else { + lim = newLim; + } + } + } + } + + if ( typeof lim !== "undefined") { + // Expand the axis limits a bit + var delta = (lim[0] === 0) ? 0.1 : 0.1 * lim[0]; + + if (this.yLog) { + if (lim[0] !== lim[1]) { + delta = Math.exp(this.expandLimFactor * Math.log(lim[1] / lim[0])); + } + + lim[0] = lim[0] / delta; + lim[1] = lim[1] * delta; + } else { + if (lim[0] !== lim[1]) { + delta = this.expandLimFactor * (lim[1] - lim[0]); + } + + lim[0] = lim[0] - delta; + lim[1] = lim[1] + delta; + } + } else { + if (this.yLog && (this.yLim[0] <= 0 || this.yLim[1] <= 0)) { + lim = [0.1, 10]; + } else { + lim = this.yLim.slice(); + } + } + + // Invert the limits if necessary + if (this.invertedYScale && lim[0] < lim[1]) { + lim = [lim[1], lim[0]]; + } + + return lim; +}; + +GPlot.prototype.calculatePointsXLim = function(points) { + // Find the points limits + var lim = [Number.MAX_VALUE, -Number.MAX_VALUE]; + + for (var i = 0; i < points.length; i++) { + if (points[i].isValid()) { + // Use the point if it's inside, and it's not negative if + // the scale is logarithmic + var x = points[i].getX(); + var y = points[i].getY(); + var isInside = true; + + if (this.fixedYLim) { + isInside = ((this.yLim[1] >= this.yLim[0]) && (y >= this.yLim[0]) && (y <= this.yLim[1])) || ((this.yLim[1] < this.yLim[0]) && (y <= this.yLim[0]) && (y >= this.yLim[1])); + } + + if (isInside && !(this.xLog && x <= 0)) { + if (x < lim[0]) { + lim[0] = x; + } + + if (x > lim[1]) { + lim[1] = x; + } + } + } + } + + // Check that the new limits make sense + if (lim[1] < lim[0]) { + lim = undefined; + } + + return lim; +}; + +GPlot.prototype.calculatePointsYLim = function(points) { + // Find the points limits + var lim = [Number.MAX_VALUE, -Number.MAX_VALUE]; + + for (var i = 0; i < points.length; i++) { + if (points[i].isValid()) { + // Use the point if it's inside, and it's not negative if + // the scale is logarithmic + var x = points[i].getX(); + var y = points[i].getY(); + var isInside = true; + + if (this.fixedXLim) { + isInside = ((this.xLim[1] >= this.xLim[0]) && (x >= this.xLim[0]) && (x <= this.xLim[1])) || ((this.xLim[1] < this.xLim[0]) && (x <= this.xLim[0]) && (x >= this.xLim[1])); + } + + if (isInside && !(this.yLog && y <= 0)) { + if (y < lim[0]) { + lim[0] = y; + } + if (y > lim[1]) { + lim[1] = y; + } + } + } + } + + // Check that the new limits make sense + if (lim[1] < lim[0]) { + lim = undefined; + } + + return lim; +}; + +GPlot.prototype.moveHorizontalAxesLim = function(delta) { + // Obtain the new x limits + var deltaLim; + + if (this.xLog) { + deltaLim = Math.exp(Math.log(this.xLim[1] / this.xLim[0]) * delta / this.dim[0]); + this.xLim[0] *= deltaLim; + this.xLim[1] *= deltaLim; + } else { + deltaLim = (this.xLim[1] - this.xLim[0]) * delta / this.dim[0]; + this.xLim[0] += deltaLim; + this.xLim[1] += deltaLim; + } + + // Fix the limits + this.fixedXLim = true; + + // Move the horizontal axes + this.xAxis.moveLim(this.xLim); + this.topAxis.moveLim(this.xLim); + + // Update the plot limits + this.updateLimits(); +}; + +GPlot.prototype.moveVerticalAxesLim = function(delta) { + // Obtain the new y limits + var deltaLim; + + if (this.yLog) { + deltaLim = Math.exp(Math.log(this.yLim[1] / this.yLim[0]) * delta / this.dim[1]); + this.yLim[0] *= deltaLim; + this.yLim[1] *= deltaLim; + } else { + deltaLim = (this.yLim[1] - this.yLim[0]) * delta / this.dim[1]; + this.yLim[0] += deltaLim; + this.yLim[1] += deltaLim; + } + + // Fix the limits + this.fixedYLim = true; + + // Move the vertical axes + this.yAxis.moveLim(this.yLim); + this.rightAxis.moveLim(this.yLim); + + // Update the plot limits + this.updateLimits(); +}; + +GPlot.prototype.centerAndZoom = function(factor, xValue, yValue) { + // Calculate the new limits + var deltaLim; + + if (this.xLog) { + deltaLim = Math.exp(Math.log(this.xLim[1] / this.xLim[0]) / (2 * factor)); + this.xLim = [xValue / deltaLim, xValue * deltaLim]; + } else { + deltaLim = (this.xLim[1] - this.xLim[0]) / (2 * factor); + this.xLim = [xValue - deltaLim, xValue + deltaLim]; + } + + if (this.yLog) { + deltaLim = Math.exp(Math.log(this.yLim[1] / this.yLim[0]) / (2 * factor)); + this.yLim = [yValue / deltaLim, yValue * deltaLim]; + } else { + deltaLim = (this.yLim[1] - this.yLim[0]) / (2 * factor); + this.yLim = [yValue - deltaLim, yValue + deltaLim]; + } + + // Fix the limits + this.fixedXLim = true; + this.fixedYLim = true; + + // Update the horizontal and vertical axes + this.xAxis.setLim(this.xLim); + this.topAxis.setLim(this.xLim); + this.yAxis.setLim(this.yLim); + this.rightAxis.setLim(yLim); + + // Update the plot limits (the layers, because the limits are fixed) + this.updateLimits(); +}; + +GPlot.prototype.zoom = function() { + var factor, deltaLim, offset; + + if (arguments.length === 3) { + factor = arguments[0]; + var xScreen = arguments[1]; + var yScreen = arguments[2]; + + var plotPos = this.getPlotPosAt(xScreen, yScreen); + var value = this.mainLayer.plotToValue(plotPos[0], plotPos[1]); + + if (this.xLog) { + deltaLim = Math.exp(Math.log(this.xLim[1] / this.xLim[0]) / (2 * factor)); + offset = Math.exp((Math.log(this.xLim[1] / this.xLim[0]) / factor) * (0.5 - plotPos[0] / this.dim[0])); + this.xLim = [value[0] * offset / deltaLim, value[0] * offset * deltaLim]; + } else { + deltaLim = (this.xLim[1] - this.xLim[0]) / (2 * factor); + offset = 2 * deltaLim * (0.5 - plotPos[0] / this.dim[0]); + this.xLim = [value[0] + offset - deltaLim, value[0] + offset + deltaLim]; + } + + if (this.yLog) { + deltaLim = Math.exp(Math.log(this.yLim[1] / this.yLim[0]) / (2 * factor)); + offset = Math.exp((Math.log(this.yLim[1] / this.yLim[0]) / factor) * (0.5 + plotPos[1] / this.dim[1])); + this.yLim = [value[1] * offset / deltaLim, value[1] * offset * deltaLim]; + } else { + deltaLim = (this.yLim[1] - this.yLim[0]) / (2 * factor); + offset = 2 * deltaLim * (0.5 + plotPos[1] / this.dim[1]); + this.yLim = [value[1] + offset - deltaLim, value[1] + offset + deltaLim]; + } + + // Fix the limits + this.fixedXLim = true; + this.fixedYLim = true; + + // Update the horizontal and vertical axes + this.xAxis.setLim(this.xLim); + this.topAxis.setLim(this.xLim); + this.yAxis.setLim(this.yLim); + this.rightAxis.setLim(this.yLim); + + // Update the plot limits (the layers, because the limits are fixed) + this.updateLimits(); + } else if (arguments.length === 1) { + factor = arguments[0]; + var centerValue = this.mainLayer.plotToValue(this.dim[0] / 2, -this.dim[1] / 2); + this.centerAndZoom(factor, centerValue[0], centerValue[1]); + } else { + throw new Error("GPlot.zoom(): signature not supported"); + } +}; + +GPlot.prototype.shiftPlotPos = function(valuePlotPos, newPlotPos) { + // Calculate the new limits + var deltaLim; + var deltaXPlot = valuePlotPos[0] - newPlotPos[0]; + var deltaYPlot = valuePlotPos[1] - newPlotPos[1]; + + if (this.xLog) { + deltaLim = Math.exp(Math.log(this.xLim[1] / this.xLim[0]) * deltaXPlot / this.dim[0]); + this.xLim = [this.xLim[0] * deltaLim, this.xLim[1] * deltaLim]; + } else { + deltaLim = (this.xLim[1] - this.xLim[0]) * deltaXPlot / this.dim[0]; + this.xLim = [this.xLim[0] + deltaLim, this.xLim[1] + deltaLim]; + } + + if (this.yLog) { + deltaLim = Math.exp(-Math.log(this.yLim[1] / this.yLim[0]) * deltaYPlot / this.dim[1]); + this.yLim = [this.yLim[0] * deltaLim, this.yLim[1] * deltaLim]; + } else { + deltaLim = -(this.yLim[1] - this.yLim[0]) * deltaYPlot / this.dim[1]; + this.yLim = [this.yLim[0] + deltaLim, this.yLim[1] + deltaLim]; + } + + // Fix the limits + this.fixedXLim = true; + this.fixedYLim = true; + + // Move the horizontal and vertical axes + this.xAxis.moveLim(this.xLim); + this.topAxis.moveLim(this.xLim); + this.yAxis.moveLim(this.yLim); + this.rightAxis.moveLim(this.yLim); + + // Update the plot limits (the layers, because the limits are fixed) + this.updateLimits(); +}; + +GPlot.prototype.align = function() { + var xValue, yValue, xScreen, yScreen; + + if (arguments.length === 4) { + xValue = arguments[0]; + yValue = arguments[1]; + xScreen = arguments[2]; + yScreen = arguments[3]; + } else if (arguments.length === 3) { + xValue = arguments[0][0]; + yValue = arguments[0][1]; + xScreen = arguments[1]; + yScreen = arguments[2]; + } else { + throw new Error("GPlot.align(): signature not supported"); + } + + var valuePlotPos = this.mainLayer.valueToPlot(xValue, yValue); + var newPlotPos = this.getPlotPosAt(xScreen, yScreen); + this.shiftPlotPos(valuePlotPos, newPlotPos); +}; + +GPlot.prototype.center = function(xScreen, yScreen) { + var valuePlotPos = this.getPlotPosAt(xScreen, yScreen); + var newPlotPos = [this.dim[0] / 2, -this.dim[1] / 2]; + this.shiftPlotPos(valuePlotPos, newPlotPos); +}; + +GPlot.prototype.startHistograms = function(histType) { + this.mainLayer.startHistogram(histType); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].startHistogram(histType); + } +}; + +GPlot.prototype.defaultDraw = function() { + this.beginDraw(); + this.drawBackground(); + this.drawBox(); + this.drawXAxis(); + this.drawYAxis(); + this.drawTitle(); + this.drawLines(); + this.drawPoints(); + this.endDraw(); +}; + +GPlot.prototype.beginDraw = function() { + this.parent.push(); + this.parent.translate(this.pos[0] + this.mar[1], this.pos[1] + this.mar[2] + this.dim[1]); +}; + +GPlot.prototype.endDraw = function() { + this.parent.pop(); +}; + +GPlot.prototype.drawBackground = function() { + this.parent.push(); + this.parent.rectMode(this.parent.CORNER); + this.parent.fill(this.bgColor); + this.parent.noStroke(); + this.parent.rect(-this.mar[1], -this.mar[2] - this.dim[1], this.outerDim[0], this.outerDim[1]); + this.parent.pop(); +}; + +GPlot.prototype.drawBox = function() { + this.parent.push(); + this.parent.rectMode(this.parent.CORNER); + this.parent.fill(this.boxBgColor); + this.parent.stroke(this.boxLineColor); + this.parent.strokeWeight(this.boxLineWidth); + this.parent.strokeCap(this.parent.SQUARE); + this.parent.rect(0, -this.dim[1], this.dim[0], this.dim[1]); + this.parent.pop(); +}; + +GPlot.prototype.drawXAxis = function() { + this.xAxis.draw(); +}; + +GPlot.prototype.drawYAxis = function() { + this.yAxis.draw(); +}; + +GPlot.prototype.drawTopAxis = function() { + this.topAxis.draw(); +}; + +GPlot.prototype.drawRightAxis = function() { + this.rightAxis.draw(); +}; + +GPlot.prototype.drawTitle = function() { + this.title.draw(); +}; + +GPlot.prototype.drawPoints = function() { + var i; + + if (arguments.length === 1) { + this.mainLayer.drawPoints(arguments[0]); + + for ( i = 0; i < this.layerList.length; i++) { + this.layerList[0].drawPoints(arguments[0]); + } + } else if (arguments.length === 0) { + this.mainLayer.drawPoints(); + + for ( i = 0; i < this.layerList.length; i++) { + this.layerList[i].drawPoints(); + } + } else { + throw new Error("GPlot.drawPoints(): signature not supported"); + } +}; + +GPlot.prototype.drawPoint = function() { + if (arguments.length === 3) { + this.mainLayer.drawPoint(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 2) { + this.mainLayer.drawPoint(arguments[0], arguments[1]); + } else if (arguments.length === 1) { + this.mainLayer.drawPoint(arguments[0]); + } else { + throw new Error("GPlot.drawPoint(): signature not supported"); + } +}; + +GPlot.prototype.drawLines = function() { + this.mainLayer.drawLines(); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].drawLines(); + } +}; + +GPlot.prototype.drawLine = function() { + if (arguments.length === 4) { + this.mainLayer.drawLine(arguments[0], arguments[1], arguments[2], arguments[3]); + } else if (arguments.length === 2) { + this.mainLayer.drawLine(arguments[0], arguments[1]); + } else { + throw new Error("GPlot.drawLine(): signature not supported"); + } +}; + +GPlot.prototype.drawHorizontalLine = function() { + if (arguments.length === 3) { + this.mainLayer.drawHorizontalLine(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 1) { + this.mainLayer.drawHorizontalLine(arguments[0]); + } else { + throw new Error("GPlot.drawHorizontalLine(): signature not supported"); + } +}; + +GPlot.prototype.drawVerticalLine = function() { + if (arguments.length === 3) { + this.mainLayer.drawVerticalLine(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 1) { + this.mainLayer.drawVerticalLine(arguments[0]); + } else { + throw new Error("GPlot.drawVerticalLine(): signature not supported"); + } +}; + +GPlot.prototype.drawFilledContours = function(contourType, referenceValue) { + this.mainLayer.drawFilledContour(contourType, referenceValue); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].drawFilledContour(contourType, referenceValue); + } +}; + +GPlot.prototype.drawAllLabels = function() { + this.mainLayer.drawAllLabels(); +}; + +GPlot.prototype.drawLabel = function(point) { + this.mainLayer.drawLabel(point); +}; + +GPlot.prototype.drawLabelsAt = function(xScreen, yScreen) { + var plotPos = this.getPlotPosAt(xScreen, yScreen); + this.mainLayer.drawLabelAtPlotPos(plotPos[0], plotPos[1]); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].drawLabelAtPlotPos(plotPos[0], plotPos[1]); + } +}; + +GPlot.prototype.drawLabels = function() { + if (this.labelingIsActive && typeof this.mousePos !== "undefined") { + this.drawLabelsAt(this.mousePos[0], this.mousePos[1]); + } +}; + +GPlot.prototype.drawGridLines = function(gridType) { + var i; + + this.parent.push(); + this.parent.noFill(); + this.parent.stroke(this.gridLineColor); + this.parent.strokeWeight(this.gridLineWidth); + this.parent.strokeCap(this.parent.SQUARE); + + if (gridType === GPlot.BOTH || gridType === GPlot.VERTICAL) { + var xPlotTicks = this.xAxis.getPlotTicksRef(); + + for ( i = 0; i < xPlotTicks.length; i++) { + if (xPlotTicks[i] >= 0 && xPlotTicks[i] <= this.dim[0]) { + this.parent.line(xPlotTicks[i], 0, xPlotTicks[i], -this.dim[1]); + } + } + } + + if (gridType === GPlot.BOTH || gridType === GPlot.HORIZONTAL) { + var yPlotTicks = this.yAxis.getPlotTicksRef(); + + for ( i = 0; i < yPlotTicks.length; i++) { + if (-yPlotTicks[i] >= 0 && -yPlotTicks[i] <= this.dim[1]) { + this.parent.line(0, yPlotTicks[i], this.dim[0], yPlotTicks[i]); + } + } + } + + this.parent.pop(); +}; + +GPlot.prototype.drawHistograms = function() { + this.mainLayer.drawHistogram(); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].drawHistogram(); + } +}; + +GPlot.prototype.drawPolygon = function(polygonPoints, polygonColor) { + this.mainLayer.drawPolygon(polygonPoints, polygonColor); +}; + +GPlot.prototype.drawAnnotation = function(text, x, y, horAlign, verAlign) { + this.mainLayer.drawAnnotation(text, x, y, horAlign, verAlign); +}; + +GPlot.prototype.drawLegend = function(text, xRelativePos, yRelativePos) { + var rectSize = 14; + + this.parent.push(); + this.parent.rectMode(this.parent.CENTER); + this.parent.noStroke(); + + for (var i = 0; i < text.length; i++) { + var plotPosition = [xRelativePos[i] * this.dim[0], -yRelativePos[i] * this.dim[1]]; + var position = this.mainLayer.plotToValue(plotPosition[0] + rectSize, plotPosition[1]); + + if (i === 0) { + this.parent.fill(this.mainLayer.getLineColor()); + this.parent.rect(plotPosition[0], plotPosition[1], rectSize, rectSize); + this.mainLayer.drawAnnotation(text[i], position[0], position[1], this.parent.LEFT, this.parent.CENTER); + } else { + this.parent.fill(this.layerList[i - 1].getLineColor()); + this.parent.rect(plotPosition[0], plotPosition[1], rectSize, rectSize); + this.layerList[i - i].drawAnnotation(text[i], position[0], position[1], this.parent.LEFT, this.parent.CENTER); + } + } + + this.parent.pop(); +}; + +GPlot.prototype.setPos = function() { + if (arguments.length === 2) { + this.pos[0] = arguments[0]; + this.pos[1] = arguments[1]; + } else if (arguments.length === 1) { + this.pos[0] = arguments[0][0]; + this.pos[1] = arguments[0][1]; + } else { + throw new Error("GPlot.setPos(): signature not supported"); + } +}; + +GPlot.prototype.setOuterDim = function() { + var xOuterDim, yOuterDim; + + if (arguments.length === 2) { + xOuterDim = arguments[0]; + yOuterDim = arguments[1]; + } else if (arguments.length === 1) { + xOuterDim = arguments[0][0]; + yOuterDim = arguments[0][1]; + } else { + throw new Error("GPlot.setOuterDim(): signature not supported"); + } + + if (xOuterDim > 0 && yOuterDim > 0) { + // Make sure that the new plot dimensions are positive + var xDim = xOuterDim - this.mar[1] - this.mar[3]; + var yDim = yOuterDim - this.mar[0] - this.mar[2]; + + if (xDim > 0 && yDim > 0) { + this.outerDim[0] = xOuterDim; + this.outerDim[1] = yOuterDim; + this.dim[0] = xDim; + this.dim[1] = yDim; + this.xAxis.setDim(this.dim); + this.topAxis.setDim(this.dim); + this.yAxis.setDim(this.dim); + this.rightAxis.setDim(this.dim); + this.title.setDim(this.dim); + + // Update the layers + this.mainLayer.setDim(this.dim); + + for (var i = 0; i < this.layerList.lenght; i++) { + this.layerList[i].setDim(this.dim); + } + } + } +}; + +GPlot.prototype.setMar = function() { + var bottomMargin, leftMargin, topMargin, rightMargin; + + if (arguments.length === 4) { + bottomMargin = arguments[0]; + leftMargin = arguments[1]; + topMargin = arguments[2]; + rightMargin = arguments[3]; + } else if (arguments.length === 1) { + bottomMargin = arguments[0][0]; + leftMargin = arguments[0][1]; + topMargin = arguments[0][2]; + rightMargin = arguments[0][3]; + } else { + throw new Error("GPlot.setMar(): signature not supported"); + } + + var xOuterDim = this.dim[0] + leftMargin + rightMargin; + var yOuterDim = this.dim[1] + bottomMargin + topMargin; + + if (xOuterDim > 0 && yOuterDim > 0) { + this.mar[0] = bottomMargin; + this.mar[1] = leftMargin; + this.mar[2] = topMargin; + this.mar[3] = rightMargin; + this.outerDim[0] = xOuterDim; + this.outerDim[1] = yOuterDim; + } +}; + +GPlot.prototype.setDim = function() { + var xDim, yDim; + + if (arguments.length === 2) { + xDim = arguments[0]; + yDim = arguments[1]; + } else if (arguments.length === 1) { + xDim = arguments[0][0]; + yDim = arguments[0][1]; + } else { + throw new Error("GPlot.setDim(): signature not supported"); + } + + if (xDim > 0 && yDim > 0) { + // Make sure that the new outer dimensions are positive + var xOuterDim = xDim + this.mar[1] + this.mar[3]; + var yOuterDim = yDim + this.mar[0] + this.mar[2]; + + if (xOuterDim > 0 && yOuterDim > 0) { + this.outerDim[0] = xOuterDim; + this.outerDim[1] = yOuterDim; + this.dim[0] = xDim; + this.dim[1] = yDim; + this.xAxis.setDim(this.dim); + this.topAxis.setDim(this.dim); + this.yAxis.setDim(this.dim); + this.rightAxis.setDim(this.dim); + this.title.setDim(this.dim); + + // Update the layers + this.mainLayer.setDim(this.dim); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].setDim(this.dim); + } + } + } +}; + +GPlot.prototype.setXLim = function() { + var lowerLim, upperLim; + + if (arguments.length === 2) { + lowerLim = arguments[0]; + upperLim = arguments[1]; + } else if (arguments.length === 1) { + lowerLim = arguments[0][0]; + upperLim = arguments[0][1]; + } else { + throw new Error("GPlot.setXLim(): signature not supported"); + } + + if (lowerLim !== upperLim) { + // Make sure the new limits makes sense + if (this.xLog && (lowerLim <= 0 || upperLim <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.xLim[0] = lowerLim; + this.xLim[1] = upperLim; + this.invertedXScale = this.xLim[0] > this.xLim[1]; + + // Fix the limits + this.fixedXLim = true; + + // Update the axes + this.xAxis.setLim(this.xLim); + this.topAxis.setLim(this.xLim); + + // Update the plot limits + this.updateLimits(); + } + } +}; + +GPlot.prototype.setYLim = function() { + var lowerLim, upperLim; + + if (arguments.length === 2) { + lowerLim = arguments[0]; + upperLim = arguments[1]; + } else if (arguments.length === 1) { + lowerLim = arguments[0][0]; + upperLim = arguments[0][1]; + } else { + throw new Error("GPlot.setYLim(): signature not supported"); + } + + if (lowerLim !== upperLim) { + // Make sure the new limits makes sense + if (this.yLog && (lowerLim <= 0 || upperLim <= 0)) { + console.log("One of the limits is negative. This is not allowed in logarithmic scale."); + } else { + this.yLim[0] = lowerLim; + this.yLim[1] = upperLim; + this.invertedYScale = this.yLim[0] > this.yLim[1]; + + // Fix the limits + this.fixedYLim = true; + + // Update the axes + this.yAxis.setLim(this.yLim); + this.rightAxis.setLim(this.yLim); + + // Update the plot limits + this.updateLimits(); + } + } +}; + +GPlot.prototype.setFixedXLim = function(fixedXLim) { + this.fixedXLim = fixedXLim; + + // Update the plot limits + this.updateLimits(); +}; + +GPlot.prototype.setFixedYLim = function(fixedYLim) { + this.fixedYLim = fixedYLim; + + // Update the plot limits + this.updateLimits(); +}; + +GPlot.prototype.setLogScale = function(logType) { + var newXLog = this.xLog; + var newYLog = this.yLog; + + if (logType === "xy" || logType === "yx") { + newXLog = true; + newYLog = true; + } else if (logType === "x") { + newXLog = true; + newYLog = false; + } else if (logType === "y") { + newXLog = false; + newYLog = true; + } else if (logType === "") { + newXLog = false; + newYLog = false; + } + + // Do something only if the scale changed + if (newXLog !== this.xLog || newYLog !== this.yLog) { + // Set the new log scales + this.xLog = newXLog; + this.yLog = newYLog; + + // Unfix the limits if the old ones don't make sense + if (this.xLog && this.fixedXLim && (this.xLim[0] <= 0 || this.xLim[1] <= 0)) { + this.fixedXLim = false; + } + + if (this.yLog && this.fixedYLim && (this.yLim[0] <= 0 || this.yLim[1] <= 0)) { + this.fixedYLim = false; + } + + // Calculate the new limits if needed + if (!this.fixedXLim) { + this.xLim = this.calculatePlotXLim(); + } + + if (!this.fixedYLim) { + this.yLim = this.calculatePlotYLim(); + } + + // Update the axes + this.xAxis.setLimAndLog(this.xLim, this.xLog); + this.topAxis.setLimAndLog(this.xLim, this.xLog); + this.yAxis.setLimAndLog(this.yLim, this.yLog); + this.rightAxis.setLimAndLog(this.yLim, this.yLog); + + // Update the layers + this.mainLayer.setLimAndLog(this.xLim, this.yLim, this.xLog, this.yLog); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].setLimAndLog(this.xLim, this.yLim, this.xLog, this.yLog); + } + } +}; + +GPlot.prototype.setInvertedXScale = function(invertedXScale) { + if (invertedXScale !== this.invertedXScale) { + this.invertedXScale = invertedXScale; + var temp = this.xLim[0]; + this.xLim[0] = this.xLim[1]; + this.xLim[1] = temp; + + // Update the axes + this.xAxis.setLim(this.xLim); + this.topAxis.setLim(this.xLim); + + // Update the layers + this.mainLayer.setXLim(this.xLim); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].setXLim(this.xLim); + } + } +}; + +GPlot.prototype.invertXScale = function() { + this.setInvertedXScale(!this.invertedXScale); +}; + +GPlot.prototype.setInvertedYScale = function(invertedYScale) { + if (invertedYScale !== this.invertedYScale) { + this.invertedYScale = invertedYScale; + var temp = this.yLim[0]; + this.yLim[0] = this.yLim[1]; + this.yLim[1] = temp; + + // Update the axes + this.yAxis.setLim(this.yLim); + this.rightAxis.setLim(this.yLim); + + // Update the layers + this.mainLayer.setYLim(this.yLim); + + for (var i = 0; i < this.layerList.length; i++) { + this.layerList[i].setYLim(this.yLim); + } + } +}; + +GPlot.prototype.invertYScale = function() { + this.setInvertedYScale(!this.invertedYScale); +}; + +GPlot.prototype.setIncludeAllLayersInLim = function(includeAllLayers) { + if (includeAllLayers !== this.includeAllLayersInLim) { + this.includeAllLayersInLim = includeAllLayers; + + // Update the plot limits + this.updateLimits(); + } +}; + +GPlot.prototype.setExpandLimFactor = function(expandFactor) { + if (expandFactor >= 0 && expandFactor !== this.expandLimFactor) { + this.expandLimFactor = expandFactor; + + // Update the plot limits + this.updateLimits(); + } +}; + +GPlot.prototype.setBgColor = function(bgColor) { + this.bgColor = bgColor; +}; + +GPlot.prototype.setBoxBgColor = function(boxBgColor) { + this.boxBgColor = boxBgColor; +}; + +GPlot.prototype.setBoxLineColor = function(boxLineColor) { + this.boxLineColor = boxLineColor; +}; + +GPlot.prototype.setBoxLineWidth = function(boxLineWidth) { + if (boxLineWidth > 0) { + this.boxLineWidth = boxLineWidth; + } +}; + +GPlot.prototype.setGridLineColor = function(gridLineColor) { + this.gridLineColor = gridLineColor; +}; + +GPlot.prototype.setGridLineWidth = function(gridLineWidth) { + if (gridLineWidth > 0) { + this.gridLineWidth = gridLineWidth; + } +}; + +GPlot.prototype.setPoints = function() { + if (arguments.length === 2) { + this.getLayer(arguments[1]).setPoints(arguments[0]); + } else if (arguments.length === 1) { + this.mainLayer.setPoints(arguments[0]); + } else { + throw new Error("GPlot.setPoints(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.setPoint = function() { + if (arguments.length === 5) { + this.getLayer(arguments[4]).setPoint(arguments[0], arguments[1], arguments[2], arguments[3]); + } else if (arguments.length === 4) { + this.mainLayer.setPoint(arguments[0], arguments[1], arguments[2], arguments[3]); + } else if (arguments.length === 3 && arguments[1] instanceof GPoint) { + this.getLayer(arguments[2]).setPoint(arguments[0], arguments[1]); + } else if (arguments.length === 3) { + this.mainLayer.setPoint(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 2) { + this.mainLayer.setPoint(arguments[0], arguments[1]); + } else { + throw new Error("GPlot.setPoint(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.addPoint = function() { + if (arguments.length === 4) { + this.getLayer(arguments[3]).addPoint(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 3) { + this.mainLayer.addPoint(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 2 && arguments[0] instanceof GPoint) { + this.getLayer(arguments[1]).addPoint(arguments[0]); + } else if (arguments.length === 2) { + this.mainLayer.addPoint(arguments[0], arguments[1]); + } else if (arguments.length === 1) { + this.mainLayer.addPoint(arguments[0]); + } else { + throw new Error("GPlot.addPoint(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.addPoints = function() { + if (arguments.length === 2) { + this.getLayer(arguments[1]).addPoints(arguments[0]); + } else if (arguments.length === 1) { + this.mainLayer.addPoints(arguments[0]); + } else { + throw new Error("GPlot.addPoints(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.removePoint = function() { + if (arguments.length === 2) { + this.getLayer(arguments[1]).removePoint(arguments[0]); + } else if (arguments.length === 1) { + this.mainLayer.removePoint(arguments[0]); + } else { + throw new Error("GPlot.removePoint(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.addPointAtIndexPos = function() { + if (arguments.length === 5) { + this.getLayer(arguments[4]).addPointAtIndexPos(arguments[0], arguments[1], arguments[2], arguments[3]); + } else if (arguments.length === 4) { + this.mainLayer.addPointAtIndexPos(arguments[0], arguments[1], arguments[2], arguments[3]); + } else if (arguments.length === 3 && arguments[1] instanceof GPoint) { + this.getLayer(arguments[2]).addPointAtIndexPos(arguments[0], arguments[1]); + } else if (arguments.length === 3) { + this.mainLayer.addPointAtIndexPos(arguments[0], arguments[1], arguments[2]); + } else if (arguments.length === 2) { + this.mainLayer.addPointAtIndexPos(arguments[0], arguments[1]); + } else { + throw new Error("GPlot.addPointAtIndexPos(): signature not supported"); + } + + this.updateLimits(); +}; + +GPlot.prototype.setPointColors = function(pointColors) { + this.mainLayer.setPointColors(pointColors); +}; + +GPlot.prototype.setPointColor = function(pointColor) { + this.mainLayer.setPointColor(pointColor); +}; + +GPlot.prototype.setPointSizes = function(pointSizes) { + this.mainLayer.setPointSizes(pointSizes); +}; + +GPlot.prototype.setPointSize = function(pointSize) { + this.mainLayer.setPointSize(pointSize); +}; + +GPlot.prototype.setLineColor = function(lineColor) { + this.mainLayer.setLineColor(lineColor); +}; + +GPlot.prototype.setLineWidth = function(lineWidth) { + this.mainLayer.setLineWidth(lineWidth); +}; + +GPlot.prototype.setHistBasePoint = function(basePoint) { + this.mainLayer.setHistBasePoint(basePoint); +}; + +GPlot.prototype.setHistType = function(histType) { + this.mainLayer.setHistType(histType); +}; + +GPlot.prototype.setHistVisible = function(histVisible) { + this.mainLayer.setHistVisible(histVisible); +}; + +GPlot.prototype.setDrawHistLabels = function(drawHistLabels) { + this.mainLayer.setDrawHistLabels(drawHistLabels); +}; + +GPlot.prototype.setLabelBgColor = function(labelBgColor) { + this.mainLayer.setLabelBgColor(labelBgColor); +}; + +GPlot.prototype.setLabelSeparation = function(labelSeparation) { + this.mainLayer.setLabelSeparation(labelSeparation); +}; + +GPlot.prototype.setTitleText = function(text) { + this.title.setText(text); +}; + +GPlot.prototype.setAxesOffset = function(offset) { + this.xAxis.setOffset(offset); + this.topAxis.setOffset(offset); + this.yAxis.setOffset(offset); + this.rightAxis.setOffset(offset); +}; + +GPlot.prototype.setTicksLength = function(tickLength) { + this.xAxis.setTickLength(tickLength); + this.topAxis.setTickLength(tickLength); + this.yAxis.setTickLength(tickLength); + this.rightAxis.setTickLength(tickLength); +}; + +GPlot.prototype.setHorizontalAxesNTicks = function(nTicks) { + this.xAxis.setNTicks(nTicks); + this.topAxis.setNTicks(nTicks); +}; + +GPlot.prototype.setHorizontalAxesTicksSeparation = function(ticksSeparation) { + this.xAxis.setTicksSeparation(ticksSeparation); + this.topAxis.setTicksSeparation(ticksSeparation); +}; + +GPlot.prototype.setHorizontalAxesTicks = function(ticks) { + this.xAxis.setTicks(ticks); + this.topAxis.setTicks(ticks); +}; + +GPlot.prototype.setVerticalAxesNTicks = function(nTicks) { + this.yAxis.setNTicks(nTicks); + this.rightAxis.setNTicks(nTicks); +}; + +GPlot.prototype.setVerticalAxesTicksSeparation = function(ticksSeparation) { + this.yAxis.setTicksSeparation(ticksSeparation); + this.rightAxis.setTicksSeparation(ticksSeparation); +}; + +GPlot.prototype.setVerticalAxesTicks = function(ticks) { + this.yAxis.setTicks(ticks); + this.rightAxis.setTicks(ticks); +}; + +GPlot.prototype.setFontName = function(fontName) { + this.maniLayer.setFontName(fontName); +}; + +GPlot.prototype.setFontColor = function(fontColor) { + this.maniLayer.setFontColor(fontColor); +}; + +GPlot.prototype.setFontSize = function(fontSize) { + this.maniLayer.setFontSize(fontSize); +}; + +GPlot.prototype.setFontProperties = function(fontName, fontColor, fontSize) { + this.maniLayer.setFontProperties(fontName, fontColor, fontSize); +}; + +GPlot.prototype.setAllFontProperties = function(fontName, fontColor, fontSize) { + this.xAxis.setAllFontProperties(fontName, fontColor, fontSize); + this.topAxis.setAllFontProperties(fontName, fontColor, fontSize); + this.yAxis.setAllFontProperties(fontName, fontColor, fontSize); + this.rightAxis.setAllFontProperties(fontName, fontColor, fontSize); + this.title.setFontProperties(fontName, fontColor, fontSize); + + this.mainLayer.setAllFontProperties(fontName, fontColor, fontSize); + + for (var i = 0; i < layerList.length; i++) { + this.layerList[i].setAllFontProperties(fontName, fontColor, fontSize); + } +}; + +GPlot.prototype.getPos = function() { + return this.pos.slice(); +}; + +GPlot.prototype.getOuterDim = function() { + return this.outerDim.slice(); +}; + +GPlot.prototype.getMar = function() { + return this.mar.slice(); +}; + +GPlot.prototype.getDim = function() { + return this.dim.slice(); +}; + +GPlot.prototype.getXLim = function() { + return this.xLim.slice(); +}; + +GPlot.prototype.getYLim = function() { + return this.yLim.slice(); +}; + +GPlot.prototype.getFixedXLim = function() { + return this.fixedXLim; +}; + +GPlot.prototype.getFixedYLim = function() { + return this.fixedYLim; +}; + +GPlot.prototype.getXLog = function() { + return this.xLog; +}; + +GPlot.prototype.getYLog = function() { + return this.yLog; +}; + +GPlot.prototype.getInvertedXScale = function() { + return this.invertedXScale; +}; + +GPlot.prototype.getInvertedYScale = function() { + return this.invertedYScale; +}; + +GPlot.prototype.getMainLayer = function() { + return this.mainLayer; +}; + +GPlot.prototype.getLayer = function(id) { + var layer; + + if (this.mainLayer.isId(id)) { + layer = this.mainLayer; + } else { + for (var i = 0; i < this.layerList.length; i++) { + if (this.layerList[i].isId(id)) { + layer = this.layerList[i]; + break; + } + } + } + + if ( typeof layer === "undefined") { + console.log("Couldn't find a layer in the plot with id = " + id); + } + + return layer; +}; + +GPlot.prototype.getXAxis = function() { + return this.xAxis; +}; + +GPlot.prototype.getYAxis = function() { + return this.yAxis; +}; + +GPlot.prototype.getTopAxis = function() { + return this.topAxis; +}; + +GPlot.prototype.getRightAxis = function() { + return this.rightAxis; +}; + +GPlot.prototype.getTitle = function() { + return this.title; +}; + +GPlot.prototype.getPoints = function() { + if (arguments.length === 1) { + return this.getLayer(arguments[0]).getPoints(); + } else if (arguments.length === 0) { + return this.mainLayer.getPoints(); + } else { + throw new Error("GPlot.getPoints(): signature not supported"); + } +}; + +GPlot.prototype.getPointsRef = function() { + if (arguments.length === 1) { + return this.getLayer(arguments[0]).getPointsRef(); + } else if (arguments.length === 0) { + return this.mainLayer.getPointsRef(); + } else { + throw new Error("GPlot.getPointsRef(): signature not supported"); + } +}; + +GPlot.prototype.getHistogram = function() { + if (arguments.length === 1) { + return this.getLayer(arguments[0]).getHistogram(); + } else if (arguments.length === 0) { + return this.mainLayer.getHistogram(); + } else { + throw new Error("GPlot.getHistogram(): signature not supported"); + } +}; + +GPlot.prototype.activateZooming = function() { + var zoomFactor, increaseButton, decreaseButton, increaseKeyModifier, decreaseKeyModifier; + + if (arguments.length === 5) { + zoomFactor = arguments[0]; + increaseButton = arguments[1]; + decreaseButton = arguments[2]; + increaseKeyModifier = arguments[3]; + decreaseKeyModifier = arguments[4]; + } else if (arguments.length === 3) { + zoomFactor = arguments[0]; + increaseButton = arguments[1]; + decreaseButton = arguments[2]; + increaseKeyModifier = GPlot.NONE; + decreaseKeyModifier = GPlot.NONE; + } else if (arguments.length === 1) { + zoomFactor = arguments[0]; + increaseButton = this.parent.LEFT; + decreaseButton = this.parent.RIGHT; + increaseKeyModifier = GPlot.NONE; + decreaseKeyModifier = GPlot.NONE; + } else if (arguments.length === 0) { + zoomFactor = 1.3; + increaseButton = this.parent.LEFT; + decreaseButton = this.parent.RIGHT; + increaseKeyModifier = GPlot.NONE; + decreaseKeyModifier = GPlot.NONE; + } else { + throw new Error("GPlot.activateZooming(): signature not supported"); + } + + this.zoomingIsActive = true; + + if (zoomFactor > 0) { + this.zoomFactor = zoomFactor; + } + + if (increaseButton === this.parent.LEFT || increaseButton === this.parent.RIGHT || increaseButton === this.parent.CENTER) { + this.increaseZoomButton = increaseButton; + } + + if (decreaseButton === this.parent.LEFT || decreaseButton === this.parent.RIGHT || decreaseButton === this.parent.CENTER) { + this.decreaseZoomButton = decreaseButton; + } + + if (increaseKeyModifier === this.parent.SHIFT || increaseKeyModifier === this.parent.CONTROL || increaseKeyModifier === this.parent.ALT || increaseKeyModifier === GPlot.NONE) { + this.increaseZoomKeyModifier = increaseKeyModifier; + } + + if (decreaseKeyModifier === this.parent.SHIFT || decreaseKeyModifier === this.parent.CONTROL || decreaseKeyModifier === this.parent.ALT || decreaseKeyModifier === GPlot.NONE) { + this.decreaseZoomKeyModifier = decreaseKeyModifier; + } +}; + +GPlot.prototype.deactivateZooming = function() { + this.zoomingIsActive = false; +}; + +GPlot.prototype.activateCentering = function() { + var button, keyModifier; + + if (arguments.length === 2) { + button = arguments[0]; + keyModifier = arguments[1]; + } else if (arguments.length === 1) { + button = arguments[0]; + keyModifier = GPlot.NONE; + } else if (arguments.length === 0) { + button = this.parent.LEFT; + keyModifier = GPlot.NONE; + } else { + throw new Error("GPlot.activateCentering(): signature not supported"); + } + + this.centeringIsActive = true; + + if (button === this.parent.LEFT || button === this.parent.RIGHT || button === this.parent.CENTER) { + this.centeringButton = button; + } + + if (keyModifier === this.parent.SHIFT || keyModifier === this.parent.CONTROL || keyModifier === this.parent.ALT || keyModifier === GPlot.NONE) { + this.centeringKeyModifier = keyModifier; + } +}; + +GPlot.prototype.deactivateCentering = function() { + this.centeringIsActive = false; +}; + +GPlot.prototype.activatePanning = function() { + var button, keyModifier; + + if (arguments.length === 2) { + button = arguments[0]; + keyModifier = arguments[1]; + } else if (arguments.length === 1) { + button = arguments[0]; + keyModifier = GPlot.NONE; + } else if (arguments.length === 0) { + button = this.parent.LEFT; + keyModifier = GPlot.NONE; + } else { + throw new Error("GPlot.activatePanning(): signature not supported"); + } + + this.panningIsActive = true; + + if (button === this.parent.LEFT || button === this.parent.RIGHT || button === this.parent.CENTER) { + this.panningButton = button; + } + + if (keyModifier === this.parent.SHIFT || keyModifier === this.parent.CONTROL || keyModifier === this.parent.ALT || keyModifier === GPlot.NONE) { + this.panningKeyModifier = keyModifier; + } +}; + +GPlot.prototype.deactivatePanning = function() { + this.panningIsActive = false; + this.panningReferencePoint = undefined; +}; + +GPlot.prototype.activatePointLabels = function() { + var button, keyModifier; + + if (arguments.length === 2) { + button = arguments[0]; + keyModifier = arguments[1]; + } else if (arguments.length === 1) { + button = arguments[0]; + keyModifier = GPlot.NONE; + } else if (arguments.length === 0) { + button = this.parent.LEFT; + keyModifier = GPlot.NONE; + } else { + throw new Error("GPlot.activatePointLabels(): signature not supported"); + } + + this.labelingIsActive = true; + + if (button === this.parent.LEFT || button === this.parent.RIGHT || button === this.parent.CENTER) { + this.labelingButton = button; + } + + if (keyModifier === this.parent.SHIFT || keyModifier === this.parent.CONTROL || keyModifier === this.parent.ALT || keyModifier === GPlot.NONE) { + this.labelingKeyModifier = keyModifier; + } +}; + +GPlot.prototype.deactivatePointLabels = function() { + this.labelingIsActive = false; + this.mousePos = undefined; +}; + +GPlot.prototype.activateReset = function() { + var button, keyModifier; + + if (arguments.length === 2) { + button = arguments[0]; + keyModifier = arguments[1]; + } else if (arguments.length === 1) { + button = arguments[0]; + keyModifier = GPlot.NONE; + } else if (arguments.length === 0) { + button = this.parent.RIGHT; + keyModifier = GPlot.NONE; + } else { + throw new Error("GPlot.activateReset(): signature not supported"); + } + + this.resetIsActive = true; + this.xLimReset = undefined; + this.yLimReset = undefined; + + if (button === this.parent.LEFT || button === this.parent.RIGHT || button === this.parent.CENTER) { + this.resetButton = button; + } + + if (keyModifier === this.parent.SHIFT || keyModifier === this.parent.CONTROL || keyModifier === this.parent.ALT || keyModifier === GPlot.NONE) { + this.resetKeyModifier = keyModifier; + } +}; + +GPlot.prototype.deactivateReset = function() { + this.resetIsActive = false; + this.xLimReset = undefined; + this.yLimReset = undefined; +}; + +GPlot.prototype.getButton = function(event) { + var button; + + if (event.button === 0) { + button = this.parent.LEFT; + } else if (event.button === 1) { + button = this.parent.CENTER; + } else if (event.button === 2) { + button = this.parent.RIGHT; + } else if ( typeof event.button === "undefined") { + button = this.parent.LEFT; + } + + return button; +}; + +GPlot.prototype.getModifier = function(event) { + var modifier; + + if (event.altKey) { + modifier = this.parent.ALT; + } else if (event.ctrlKey) { + modifier = this.parent.CONTROL; + } else if (event.shiftKey) { + modifier = this.parent.SHIFT; + } else { + modifier = GPlot.NONE; + } + + return modifier; +}; + +GPlot.prototype.saveResetLimits = function() { + if ( typeof this.xLimReset === "undefined" || typeof this.yLimReset === "undefined") { + this.xLimReset = this.xLim.slice(); + this.yLimReset = this.yLim.slice(); + } +}; + +GPlot.prototype.panningFunction = function() { + if ( typeof this.panningReferencePoint !== "undefined") { + this.align(this.panningReferencePoint, this.parent.mouseX, this.parent.mouseY); + } +}; + +GPlot.prototype.clickEvent = function(event) { + e = event || window.event; + + if (this.isOverBox()) { + var button = this.getButton(e); + var modifier = this.getModifier(e); + + if (this.zoomingIsActive) { + if (button === this.increaseZoomButton && modifier === this.increaseZoomKeyModifier) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + this.zoom(this.zoomFactor, this.parent.mouseX, this.parent.mouseY); + } else if (button === this.decreaseZoomButton && modifier === this.decreaseZoomKeyModifier) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + this.zoom(1 / this.zoomFactor, this.parent.mouseX, this.parent.mouseY); + } + } + + if (this.centeringIsActive && button === this.centeringButton && modifier === this.centeringKeyModifier) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + this.center(this.parent.mouseX, this.parent.mouseY); + } + + if (this.resetIsActive && button === this.resetButton && modifier === this.resetKeyModifier) { + if ( typeof this.xLimReset !== "undefined" && typeof this.yLimReset !== "undefined") { + this.setXLim(this.xLimReset); + this.setYLim(this.yLimReset); + this.xLimReset = undefined; + this.yLimReset = undefined; + } + } + } +}; + +GPlot.prototype.mouseDownEvent = function(event) { + e = event || window.event; + + if (this.isOverBox()) { + var button = this.getButton(e); + var modifier = this.getModifier(e); + + if (this.panningIsActive && button === this.panningButton && modifier === this.panningKeyModifier) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + // Calculate the panning reference point + this.panningReferencePoint = this.getValueAt(this.parent.mouseX, this.parent.mouseY); + + // Execute the panning function every 100ms + this.panningIntervalId = setInterval(this.panningFunction.bind(this), 100); + } + + if (this.labelingIsActive && button === this.labelingButton && modifier === this.labelingKeyModifier) { + this.mousePos = [this.parent.mouseX, this.parent.mouseY]; + } + } +}; + +GPlot.prototype.mouseUpEvent = function(event) { + e = event || window.event; + var button = this.getButton(e); + var modifier = this.getModifier(e); + + if (this.panningIsActive && button === this.panningButton && typeof this.panningIntervalId !== "undefined") { + // Stop executing the panning function + clearInterval(this.panningIntervalId); + + // Reset the panning variables + this.panningIntervalId = undefined; + this.panningReferencePoint = undefined; + } + + if (this.labelingIsActive && button === this.labelingButton) { + this.mousePos = undefined; + } + + if (button === this.parent.RIGHT) { + // This is a right click! + this.clickEvent(e); + } +}; + +GPlot.prototype.wheelEvent = function(event) { + e = event || window.event; + + if (this.isOverBox()) { + var deltaY = e.deltaY; + var button = this.parent.CENTER; + var modifier = this.getModifier(e); + + if (this.zoomingIsActive) { + if (button === this.increaseZoomButton && modifier === this.increaseZoomKeyModifier && deltaY > 0) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + this.zoom(this.zoomFactor, this.parent.mouseX, this.parent.mouseY); + } else if (button === this.decreaseZoomButton && modifier === this.decreaseZoomKeyModifier && deltaY < 0) { + // Save the axes limits + if (this.resetIsActive) { + this.saveResetLimits(); + } + + this.zoom(1 / this.zoomFactor, this.parent.mouseX, this.parent.mouseY); + } + } + } +}; + +GPlot.prototype.preventDefaultEvent = function(event) { + e = event || window.event; + + if (this.isOverBox()) { + // Don't show the menu inside the plot area + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + } +}; + +GPlot.prototype.preventWheelDefault = function() { + window.addEventListener("wheel", this.preventDefaultEvent.bind(this), false); +}; + +GPlot.prototype.preventRightClickDefault = function() { + window.addEventListener("contextmenu", this.preventDefaultEvent.bind(this), false); +}; diff --git a/graficos/grafica-0.1.0-mod.min.js b/graficos/grafica-0.1.0-mod.min.js new file mode 100644 index 0000000..192dbac --- /dev/null +++ b/graficos/grafica-0.1.0-mod.min.js @@ -0,0 +1,5 @@ +/*! grafica.js (0.1.0): a library for p5.js. Author: Javier Graciá Carpio, license: LGPL-3.0, 2015-04-12 */ function GPoint(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length&&arguments[0]instanceof p5.Vector)a=arguments[0].x,b=arguments[0].y,c=arguments[1];else if(2===arguments.length)a=arguments[0],b=arguments[1],c="";else if(1===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].getLabel();else if(1===arguments.length&&arguments[0]instanceof p5.Vector)a=arguments[0].x,b=arguments[0].y,c="";else{if(0!==arguments.length)throw new Error("GPoint constructor: signature not supported");a=0,b=0,c=""}this.x=a,this.y=b,this.label=c,this.valid=this.isValidNumber(this.x)&&this.isValidNumber(this.y)}function GTitle(a,b){this.parent=a,this.dim=b.slice(),this.relativePos=.5,this.plotPos=this.relativePos*this.dim[0],this.offset=10,this.text="",this.textAlignment=this.parent.CENTER,this.fontName="Helvetica",this.fontColor=this.parent.color(100),this.fontStyle=this.parent.BOLD,this.fontSize=13}function GAxisLabel(a,b,c){this.parent=a,this.type=b===this.parent.BOTTOM||b===this.parent.TOP||b===this.parent.LEFT||b===this.parent.RIGHT?b:this.parent.BOTTOM,this.dim=c.slice(),this.relativePos=.5,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1],this.offset=35,this.rotate=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?!1:!0,this.text="",this.textAlignment=this.parent.CENTER,this.fontName="Helvetica",this.fontColor=this.parent.color(0),this.fontSize=13}function GAxis(a,b,c,d,e){this.parent=a,this.type=b===this.parent.BOTTOM||b===this.parent.TOP||b===this.parent.LEFT||b===this.parent.RIGHT?b:this.parent.BOTTOM,this.dim=c.slice(),this.lim=d.slice(),this.log=e,this.log&&(this.lim[0]<=0||this.lim[1]<=0)&&(console.log("The limits are negative. This is not allowed in logarithmic scale."),console.log("Will set them to (0.1, 10)"),this.lim[1]>this.lim[0]?(this.lim[0]=.1,this.lim[1]=10):(this.lim[0]=10,this.lim[1]=.1)),this.offset=5,this.lineColor=this.parent.color(0),this.lineWidth=1,this.nTicks=5,this.ticksSeparation=-1,this.ticks=[],this.plotTicks=[],this.ticksInside=[],this.tickLabels=[],this.fixedTicks=!1,this.tickLength=3,this.smallTickLength=2,this.expTickLabels=!1,this.rotateTickLabels=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?!1:!0,this.drawTickLabels=this.type===this.parent.BOTTOM||this.type===this.parent.LEFT?!0:!1,this.tickLabelOffset=7,this.ticksPrecision=void 0,this.lab=new GAxisLabel(this.parent,this.type,this.dim),this.drawAxisLabel=!0,this.fontName="Helvetica",this.fontColor=this.parent.color(0),this.fontSize=11,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()}function GHistogram(a,b,c,d){this.parent=a,this.type=b===GPlot.VERTICAL||b===GPlot.HORIZONTAL?b:GPlot.VERTICAL,this.dim=c.slice(),this.plotPoints=[];for(var e=0;e0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.plotPos=this.relativePos*this.dim[0])},GTitle.prototype.setRelativePos=function(a){this.relativePos=a,this.plotPos=this.relativePos*this.dim[0]},GTitle.prototype.setOffset=function(a){this.offset=a},GTitle.prototype.setText=function(a){this.text=a},GTitle.prototype.setTextAlignment=function(a){(a===this.parent.CENTER||a===this.parent.LEFT||a===this.parent.RIGHT)&&(this.textAlignment=a)},GTitle.prototype.setFontName=function(a){this.fontName=a},GTitle.prototype.setFontColor=function(a){this.fontColor=a},GTitle.prototype.setFontStyle=function(a){this.fontStyle=a},GTitle.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GTitle.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxisLabel.prototype.draw=function(){switch(this.type){case this.parent.BOTTOM:this.drawAsXLabel();break;case this.parent.LEFT:this.drawAsYLabel();break;case this.parent.TOP:this.drawAsTopLabel();break;case this.parent.RIGHT:this.drawAsRightLabel()}},GAxisLabel.prototype.drawAsXLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),this.parent.translate(this.plotPos,this.offset),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.textAlignment,this.parent.TOP),this.parent.text(this.text,this.plotPos,this.offset)),this.parent.pop()},GAxisLabel.prototype.drawAsYLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.textAlignment,this.parent.BOTTOM),this.parent.translate(-this.offset,this.plotPos),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),this.parent.text(this.text,-this.offset,this.plotPos)),this.parent.pop()},GAxisLabel.prototype.drawAsTopLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.parent.LEFT,this.parent.CENTER),this.parent.translate(this.plotPos,-this.offset-this.dim[1]),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.textAlignment,this.parent.BOTTOM),this.parent.text(this.text,this.plotPos,-this.offset-this.dim[1])),this.parent.pop()},GAxisLabel.prototype.drawAsRightLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.textAlignment,this.parent.TOP),this.parent.translate(this.offset+this.dim[0],this.plotPos),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.parent.LEFT,this.parent.CENTER),this.parent.text(this.text,this.offset+this.dim[0],this.plotPos)),this.parent.pop()},GAxisLabel.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GAxisLabel.setDim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a>0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1])},GAxisLabel.prototype.setRelativePos=function(a){this.relativePos=a,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1]},GAxisLabel.prototype.setOffset=function(a){this.offset=a},GAxisLabel.prototype.setRotate=function(a){this.rotate=a},GAxisLabel.prototype.setText=function(a){this.text=a},GAxisLabel.prototype.setTextAlignment=function(a){(a===this.parent.CENTER||a===this.parent.LEFT||a===this.parent.RIGHT)&&(this.textAlignment=a)},GAxisLabel.prototype.setFontName=function(a){this.fontName=a},GAxisLabel.prototype.setFontColor=function(a){this.fontColor=a},GAxisLabel.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GAxisLabel.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxis.prototype.obtainSigDigits=function(a){return Math.round(-Math.log(.5*Math.abs(a))/Math.LN10)},GAxis.prototype.roundPlus=function(a,b){return a=Math.round(a*Math.pow(10,b))/Math.pow(10,b),0>=b&&(a=Math.round(a)),a},GAxis.prototype.adaptSize=function(a,b){bthis.lim[0]?(a=Math.floor(Math.log(this.lim[0])/Math.LN10),b=Math.ceil(Math.log(this.lim[1])/Math.LN10)):(a=Math.floor(Math.log(this.lim[1])/Math.LN10),b=Math.ceil(Math.log(this.lim[0])/Math.LN10));var c=9*(b-a)+1;this.adaptSize(this.ticks,c);for(var d=a;b>d;d++)for(var e=this.roundPlus(Math.exp(d*Math.LN10),-d),f=0;9>f;f++)this.ticks[9*(d-a)+f]=(f+1)*e;this.ticks[this.ticks.length-1]=this.roundPlus(Math.exp(b*Math.LN10),-d),this.lim[1]0){for(a=this.lim[1]>this.lim[0]?this.ticksSeparation:-this.ticksSeparation,c=this.obtainSigDigits(a);this.roundPlus(a,c)-a!==0;)c++;b=Math.floor((this.lim[1]-this.lim[0])/a)}else this.nTicks>0&&(a=(this.lim[1]-this.lim[0])/this.nTicks,c=this.obtainSigDigits(a),a=this.roundPlus(a,c),(0===a||Math.abs(a)>Math.abs(this.lim[1]-this.lim[0]))&&(c++,a=this.roundPlus((this.lim[1]-this.lim[0])/this.nTicks,c)),b=Math.floor((this.lim[1]-this.lim[0])/a));if(b>0){var d=this.lim[0]+(this.lim[1]-this.lim[0]-b*a)/2;for(d=this.roundPlus(d-2*a,c);(this.lim[1]-d)*(this.lim[0]-d)>0;)d=this.roundPlus(d+a,c);var e=Math.floor(Math.abs((this.lim[1]-d)/a))+1;this.adaptSize(this.ticks,e),this.ticks[0]=d;for(var f=1;e>f;f++)this.ticks[f]=this.roundPlus(this.ticks[f-1]+a,c);this.ticksPrecision=c}else this.ticks=[]},GAxis.prototype.updatePlotTicks=function(){var a,b,c=this.ticks.length;if(this.adaptSize(this.plotTicks,c),this.log)for(a=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.dim[0]/Math.log(this.lim[1]/this.lim[0]):-this.dim[1]/Math.log(this.lim[1]/this.lim[0]),b=0;c>b;b++)this.plotTicks[b]=Math.log(this.ticks[b]/this.lim[0])*a;else for(a=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.dim[0]/(this.lim[1]-this.lim[0]):-this.dim[1]/(this.lim[1]-this.lim[0]),b=0;c>b;b++)this.plotTicks[b]=(this.ticks[b]-this.lim[0])*a},GAxis.prototype.updateTicksInside=function(){var a,b=this.ticks.length;if(this.adaptSize(this.ticksInside,b),this.type===this.parent.BOTTOM||this.type===this.parent.TOP)for(a=0;b>a;a++)this.ticksInside[a]=this.plotTicks[a]>=0&&this.plotTicks[a]<=this.dim[0];else for(a=0;b>a;a++)this.ticksInside[a]=-this.plotTicks[a]>=0&&-this.plotTicks[a]<=this.dim[1]},GAxis.prototype.updateTickLabels=function(){var a,b,c,d,e=this.ticks.length;if(this.adaptSize(this.tickLabels,e),this.log)for(d=0;e>d;d++)a=this.ticks[d],a>0?(b=Math.log(a)/Math.LN10,c=Math.abs(b-Math.round(b))<1e-4,c?(b=Math.round(b),this.tickLabels[d]=this.expTickLabels?"1e"+b:b>-3.1&&3.1>b?b>=0?""+Math.round(a):""+a:"1e"+b):this.tickLabels[d]=""):this.tickLabels[d]="";else for(d=0;e>d;d++)a=this.ticks[d],this.tickLabels[d]=a%1===0?""+Math.round(a):"undefined"!=typeof this.ticksPrecision&&this.ticksPrecision>=0?""+parseFloat(a).toFixed(this.ticksPrecision):""+a},GAxis.prototype.moveLim=function(a){if(a[1]!==a[0])if(this.log&&(a[0]<=0||a[1]<=0))console.log("The limits are negative. This is not allowed in logarithmic scale.");else{if(this.lim[0]=a[0],this.lim[1]=a[1],!this.fixedTicks){var b=this.ticks.length;if(this.log)this.obtainLogarithmicTicks();else if(b>0){var c=0,d=0;if(this.ticksSeparation>0)for(c=this.lim[1]>this.lim[0]?this.ticksSeparation:-this.ticksSeparation,d=this.obtainSigDigits(c);this.roundPlus(c,d)-c!==0;)d++;else c=1===b?this.lim[1]-this.lim[0]:this.ticks[1]-this.ticks[0],d=this.obtainSigDigits(c),c=this.roundPlus(c,d),(0===c||Math.abs(c)>Math.abs(this.lim[1]-this.lim[0]))&&(d++,c=1===b?this.lim[1]-this.lim[0]:this.ticks[1]-this.ticks[0],c=this.roundPlus(c,d)),c=this.lim[1]>this.lim[0]?Math.abs(c):-Math.abs(c);var e=this.ticks[0]+c*Math.ceil((this.lim[0]-this.ticks[0])/c);e=this.roundPlus(e,d),(this.lim[1]-e)*(this.lim[0]-e)>0&&(e=this.ticks[0]+c*Math.floor((this.lim[0]-this.ticks[0])/c),e=this.roundPlus(e,d)),b=Math.floor(Math.abs((this.lim[1]-e)/c))+1,this.adaptSize(this.ticks,b),this.ticks[0]=e;for(var f=1;b>f;f++)this.ticks[f]=this.roundPlus(this.ticks[f-1]+c,d);this.ticksPrecision!==d&&console.log("There is a problem in the axis ticks precision calculation")}this.updateTickLabels()}this.updatePlotTicks(),this.updateTicksInside()}},GAxis.prototype.draw=function(){switch(this.type){case this.parent.BOTTOM:this.drawAsXAxis();break;case this.parent.LEFT:this.drawAsYAxis();break;case this.parent.TOP:this.drawAsTopAxis();break;case this.parent.RIGHT:this.drawAsRightAxis()}this.drawAxisLabel&&this.lab.draw()},GAxis.prototype.drawAsXAxis=function(){var a;for(this.parent.push(),this.parent.stroke(this.lineColor),this.parent.strokeWeight(this.lineWidth),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(0,this.offset,this.dim[0],this.offset),a=0;a0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updatePlotTicks(),this.lab.setDim(this.dim))},GAxis.prototype.setLim=function(a){a[1]!==a[0]&&(this.log&&(a[0]<=0||a[1]<=0)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.lim[0]=a[0],this.lim[1]=a[1],this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside()))},GAxis.prototype.setLimAndLog=function(a,b){a[1]!==a[0]&&(b&&(a[0]<=0||a[1]<=0)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.lim[0]=a[0],this.lim[1]=a[1],this.log=b,this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside()))},GAxis.prototype.setLog=function(a){a!==this.log&&(this.log=a,this.log&&(this.lim[0]<=0||this.lim[1]<=0)&&(console.log("The limits are negative. This is not allowed in logarithmic scale."),console.log("Will set them to (0.1, 10)"),this.lim[1]>this.lim[0]?(this.lim[0]=.1,this.lim[1]=10):(this.lim[0]=10,this.lim[1]=.1)),this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside())},GAxis.prototype.setOffset=function(a){this.offset=a},GAxis.prototype.setLineColor=function(a){this.lineColor=a},GAxis.prototype.setLineWidth=function(a){a>0&&(this.lineWidth=a)},GAxis.prototype.setNTicks=function(a){a>=0&&(this.nTicks=a,this.ticksSeparation=-1,this.log||(this.fixedTicks=!1,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()))},GAxis.prototype.setTicksSeparation=function(a){this.ticksSeparation=a,this.log||(this.fixedTicks=!1,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels())},GAxis.prototype.setTicks=function(a){var b=a.length;this.adaptSize(this.ticks,b);for(var c=0;b>c;c++)this.ticks[c]=a[c];this.fixedTicks=!0,this.ticksPrecision=void 0,this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()},GAxis.prototype.setTickLabels=function(a){if(a.length===this.tickLabels.length){for(var b=0;b0&&(this.fontSize=a)},GAxis.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxis.prototype.setAllFontProperties=function(a,b,c){this.setFontProperties(a,b,c),this.lab.setFontProperties(a,b,c)},GAxis.prototype.getTicks=function(){if(this.fixedTicks)return this.ticks.slice();for(var a=[],b=0,c=0;cb&&(this.differences.splice(b,Number.MAX_VALUE),this.leftSides.splice(b,Number.MAX_VALUE),this.rightSides.splice(b,Number.MAX_VALUE)),1===b)this.leftSides[0]=this.type===GPlot.VERTICAL?.2*this.dim[0]:.2*this.dim[1],this.rightSides[0]=this.leftSides[0];else if(b>1){for(a=0;b-1>a;a++)if(this.plotPoints[a].isValid()&&this.plotPoints[a+1].isValid()){var c,d=this.separations[a%this.separations.length];c=this.type===GPlot.VERTICAL?this.plotPoints[a+1].getX()-this.plotPoints[a].getX():this.plotPoints[a+1].getY()-this.plotPoints[a].getY(),this.differences[a]=c>0?(c-d)/2:(c+d)/2}else this.differences[a]=0;for(this.leftSides[0]=this.differences[0],this.rightSides[0]=this.differences[0],a=1;b-1>a;a++)this.leftSides[a]=this.differences[a-1],this.rightSides[a]=this.differences[a];this.leftSides[b-1]=this.differences[b-2],this.rightSides[b-1]=this.differences[b-2]}},GHistogram.prototype.draw=function(a){if(this.visible){var b=0;a.isValid()&&(b=this.type===GPlot.VERTICAL?a.getY():a.getX());var c,d,e,f,g,h,i=this.plotPoints.length;this.parent.push(),this.parent.rectMode(this.parent.CORNERS),this.parent.strokeCap(this.parent.SQUARE);for(var j=0;i>j;j++)c=this.plotPoints[j],c.isValid()&&(this.type===GPlot.VERTICAL?(d=c.getX()-this.leftSides[j],e=c.getX()+this.rightSides[j],f=c.getY(),g=b):(d=b,e=c.getX(),f=c.getY()-this.leftSides[j],g=c.getY()+this.rightSides[j]),0>d?d=0:d>this.dim[0]&&(d=this.dim[0]),0>-f?f=0:-f>this.dim[1]&&(f=-this.dim[1]),0>e?e=0:e>this.dim[0]&&(e=this.dim[0]),0>-g?g=0:-g>this.dim[1]&&(g=-this.dim[1]),h=this.lineWidths[j%this.lineWidths.length],this.parent.fill(this.bgColors[j%this.bgColors.length]),this.parent.stroke(this.lineColors[j%this.lineColors.length]),this.parent.strokeWeight(h),Math.abs(e-d)>2*h&&Math.abs(g-f)>2*h?this.parent.rect(d,f,e,g):(this.type===GPlot.VERTICAL&&e!==d&&(f!==g||0!==f&&f!==-this.dim[1])||this.type===GPlot.HORIZONTAL&&g!==f&&(d!==e||0!==d&&d!==this.dim[0]))&&(this.parent.rect(d,f,e,g),this.parent.line(d,f,d,g),this.parent.line(e,f,e,g),this.parent.line(d,f,e,f),this.parent.line(d,g,e,g)));this.parent.pop(),this.drawLabels&&this.drawHistLabels()}},GHistogram.prototype.drawHistLabels=function(){var a,b,c=this.plotPoints.length,d=.5*Math.PI;if(this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.type===GPlot.VERTICAL)if(this.rotateLabels)for(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&a.getX()>=0&&a.getX()<=this.dim[0]&&(this.parent.push(),this.parent.translate(a.getX(),this.labelsOffset),this.parent.rotate(-d),this.parent.text(a.getLabel(),0,0),this.parent.pop());else for(this.parent.textAlign(this.parent.CENTER,this.parent.TOP),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&a.getX()>=0&&a.getX()<=this.dim[0]&&this.parent.text(a.getLabel(),a.getX(),this.labelsOffset);else if(this.rotateLabels)for(this.parent.textAlign(this.parent.CENTER,this.parent.BOTTOM),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&-a.getY()>=0&&-a.getY()<=this.dim[1]&&(this.parent.push(),this.parent.translate(-this.labelsOffset,a.getY()),this.parent.rotate(-d),this.parent.text(a.getLabel(),0,0),this.parent.pop());else for(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&-a.getY()>=0&&-a.getY()<=this.dim[1]&&this.parent.text(a.getLabel(),-this.labelsOffset,a.getY());this.parent.pop()},GHistogram.prototype.setType=function(a){a===this.type||a!==GPlot.VERTICAL&&a!==GPlot.HORIZONTAL||(this.type=a,this.updateArrays())},GHistogram.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GHistogram.setDim(): signature not supported"); + +a=arguments[0][0],b=arguments[0][1]}a>0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updateArrays())},GHistogram.prototype.setPlotPoints=function(a){var b,c=a.length;if(this.plotPoints.length===c)for(b=0;c>b;b++)this.plotPoints[b].set(a[b]);else if(this.plotPoints.length>c){for(b=0;c>b;b++)this.plotPoints[b].set(a[b]);this.plotPoints.splice(c,Number.MAX_VALUE)}else{for(b=0;bb;b++)this.plotPoints[b]=new GPoint(a[b])}this.updateArrays()},GHistogram.prototype.setPlotPoint=function(a,b){if(a0&&(this.fontSize=a)},GHistogram.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GLayer.prototype.isValidNumber=function(a){return!isNaN(a)&&isFinite(a)},GLayer.prototype.isId=function(a){return this.id===a},GLayer.prototype.valueToXPlot=function(a){return this.xLog?this.dim[0]*Math.log(a/this.xLim[0])/Math.log(this.xLim[1]/this.xLim[0]):this.dim[0]*(a-this.xLim[0])/(this.xLim[1]-this.xLim[0])},GLayer.prototype.valueToYPlot=function(a){return this.yLog?-this.dim[1]*Math.log(a/this.yLim[0])/Math.log(this.yLim[1]/this.yLim[0]):-this.dim[1]*(a-this.yLim[0])/(this.yLim[1]-this.yLim[0])},GLayer.prototype.valueToPlot=function(){if(2===arguments.length)return[this.valueToXPlot(arguments[0]),this.valueToYPlot(arguments[1])];if(1===arguments.length&&arguments[0]instanceof GPoint)return new GPoint(this.valueToXPlot(arguments[0].getX()),this.valueToYPlot(arguments[0].getY()),arguments[0].getLabel());if(1===arguments.length&&arguments[0]instanceof Array&&arguments[0][0]instanceof GPoint){var a,b,c,d,e,f,g=arguments[0].length,h=[];if(this.xLog&&this.yLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=Math.log(c.getX()/this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else if(this.xLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=Math.log(c.getX()/this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else if(this.yLog)for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=(c.getX()-this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=(c.getX()-this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());return h}throw new Error("GLayer.valueToPlot(): signature not supported")},GLayer.prototype.updatePlotPoints=function(){var a,b,c,d,e,f,g=this.points.length;if(this.plotPoints.lengthf;f++)this.plotPoints[f]=new GPoint;else this.plotPoints.length>g&&this.plotPoints.splice(g,Number.MAX_VALUE);if(this.xLog&&this.yLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=Math.log(c.getX()/this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else if(this.xLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=Math.log(c.getX()/this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else if(this.yLog)for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=(c.getX()-this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=(c.getX()-this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel())},GLayer.prototype.xPlotToValue=function(a){return this.xLog?Math.exp(Math.log(this.xLim[0])+Math.log(this.xLim[1]/this.xLim[0])*a/this.dim[0]):this.xLim[0]+(this.xLim[1]-this.xLim[0])*a/this.dim[0]},GLayer.prototype.yPlotToValue=function(a){return this.yLog?Math.exp(Math.log(this.yLim[0])-Math.log(this.yLim[1]/this.yLim[0])*a/this.dim[1]):this.yLim[0]-(this.yLim[1]-this.yLim[0])*a/this.dim[1]},GLayer.prototype.plotToValue=function(a,b){return[this.xPlotToValue(a),this.yPlotToValue(b)]},GLayer.prototype.isInside=function(){var a,b,c;if(2===arguments.length)a=arguments[0],b=arguments[1],c=this.isValidNumber(a)&&this.isValidNumber(b);else{if(!(1===arguments.length&&arguments[0]instanceof GPoint))throw new Error("GLayer.isInside(): signature not supported");a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].isValid()}return c?a>=0&&a<=this.dim[0]&&-b>=0&&-b<=this.dim[1]:!1},GLayer.prototype.updateInsideList=function(){for(var a,b=this.plotPoints.length,c=0;b>c;c++)a=this.plotPoints[c],this.inside[c]=a.isValid()?a.getX()>=0&&a.getX()<=this.dim[0]&&-a.getY()>=0&&-a.getY()<=this.dim[1]:!1;this.inside.length>b&&this.inside.splice(b,Number.MAX_VALUE)},GLayer.prototype.getPointIndexAtPlotPos=function(a,b){var c;if(this.isInside(a,b))for(var d,e,f=25,g=this.plotPoints.length,h=0;g>h;h++)this.inside[h]&&(d=this.plotPoints[h],e=Math.pow(d.getX()-a,2)+Math.pow(d.getY()-b,2),f>e&&(f=e,c=h));return c},GLayer.prototype.getPointAtPlotPos=function(a,b){return this.points[this.getPointIndexAtPlotPos(a,b)]},GLayer.prototype.obtainBoxIntersections=function(a,b){var c=0;if(a.isValid()&&b.isValid()){var d=a.getX(),e=a.getY(),f=b.getX(),g=b.getY(),h=this.isInside(d,e),i=this.isInside(f,g),j=h&&i||0>d&&0>f||d>this.dim[0]&&f>this.dim[0]||0>-e&&0>-g||-e>this.dim[1]&&-g>this.dim[1];if(!j){var k=f-d,l=g-e;if(0===k)c=2,this.cuts[0][0]=d,this.cuts[0][1]=0,this.cuts[1][0]=d,this.cuts[1][1]=-this.dim[1];else if(0===l)c=2,this.cuts[0][0]=0,this.cuts[0][1]=e,this.cuts[1][0]=this.dim[0],this.cuts[1][1]=e;else{var m=l/k,n=e-m*d;c=4,this.cuts[0][0]=-n/m,this.cuts[0][1]=0,this.cuts[1][0]=(-this.dim[1]-n)/m,this.cuts[1][1]=-this.dim[1],this.cuts[2][0]=0,this.cuts[2][1]=n,this.cuts[3][0]=this.dim[0],this.cuts[3][1]=n+m*this.dim[0]}if(c=this.getValidCuts(this.cuts,c,a,b),h||i){if(1!==c){var o=h?a:b;c>1&&(c=this.removeDuplicatedCuts(this.cuts,c,0),c>1&&(c=this.removePointFromCuts(this.cuts,c,o,0),c>1&&(c=this.removeDuplicatedCuts(this.cuts,c,.001),c>1&&(c=this.removePointFromCuts(this.cuts,c,o,.001))))),0===c&&(c=1,this.cuts[0][0]=o.getX(),this.cuts[1][0]=o.getY())}}else c>2&&(c=this.removeDuplicatedCuts(this.cuts,c,0),c>2&&(c=this.removeDuplicatedCuts(this.cuts,c,.001))),2===c&&(Math.pow(this.cuts[0][0]-d,2)+Math.pow(this.cuts[0][1]-e),2>Math.pow(this.cuts[1][0]-d,2)+Math.pow(this.cuts[1][1]-e,2)&&(this.cuts[2][0]=this.cuts[0][0],this.cuts[2][1]=this.cuts[0][1],this.cuts[0][0]=this.cuts[1][0],this.cuts[0][1]=this.cuts[1][1],this.cuts[1][0]=this.cuts[2][0],this.cuts[1][1]=this.cuts[2][1])),1===c&&(c=2,this.cuts[1][0]=this.cuts[0][0],this.cuts[1][1]=this.cuts[0][1]);(h||i)&&1!==c?console.log("There should be one cut!!!"):h||i||0===c||2===c||console.log("There should be either 0 or 2 cuts!!! "+c+" were found")}}return c},GLayer.prototype.getValidCuts=function(a,b,c,d){for(var e=c.getX(),f=c.getY(),g=d.getX(),h=d.getY(),i=Math.abs(g-e),j=Math.abs(h-f),k=0,l=0;b>l;l++)this.isInside(a[l][0],a[l][1])&&Math.abs(a[l][0]-e)<=i&&Math.abs(a[l][1]-f)<=j&&Math.abs(a[l][0]-g)<=i&&Math.abs(a[l][1]-h)<=j&&(a[k][0]=a[l][0],a[k][1]=a[l][1],k++);return k},GLayer.prototype.removeDuplicatedCuts=function(a,b,c){for(var d,e=0,f=0;b>f;f++){d=!1;for(var g=0;e>g;g++)if(Math.abs(a[g][0]-a[f][0])<=c&&Math.abs(a[g][1]-a[f][1])<=c){d=!0;break}d||(a[e][0]=a[f][0],a[e][1]=a[f][1],e++)}return e},GLayer.prototype.removePointFromCuts=function(a,b,c,d){for(var e=c.getX(),f=c.getY(),g=0,h=0;b>h;h++)(Math.abs(a[h][0]-e)>d||Math.abs(a[h][1]-f)>d)&&(a[g][0]=a[h][0],a[g][1]=a[h][1],g++);return g},GLayer.prototype.startHistogram=function(a){this.hist=new GHistogram(this.parent,a,this.dim,this.plotPoints)},GLayer.prototype.drawPoints=function(){var a,b;if(0===arguments.length){a=this.plotPoints.length;var c=this.pointColors.length,d=this.pointSizes.length;if(this.parent.push(),this.parent.ellipseMode(this.parent.CENTER),this.parent.stroke(50),1===c&&1===d)for(this.parent.fill(this.pointColors[0]),b=0;a>b;b++)this.inside[b]&&this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[0],this.pointSizes[0]);else if(1===c)for(this.parent.fill(this.pointColors[0]),b=0;a>b;b++)this.inside[b]&&this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[b%d],this.pointSizes[b%d]);else if(1===d)for(b=0;a>b;b++)this.inside[b]&&(this.parent.fill(this.pointColors[b%c]),this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[0],this.pointSizes[0]));else for(b=0;a>b;b++)this.inside[b]&&(this.parent.fill(this.pointColors[b%c]),this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[b%d],this.pointSizes[b%d]));this.parent.pop()}else{if(!(1===arguments.length&&arguments[0]instanceof p5.Image))throw new Error("GLayer.drawPoints(): signature not supported");for(a=this.plotPoints.length,this.parent.push(),this.parent.imageMode(this.parent.CENTER),b=0;a>b;b++)this.inside[b]&&this.parent.image(arguments[0],this.plotPoints[b].getX(),this.plotPoints[b].getY());this.parent.pop()}},GLayer.prototype.drawPoint=function(){var a,b,c,d;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length&&arguments[1]instanceof p5.Image)a=arguments[0],d=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.drawPoint(): signature not supported");a=arguments[0],b=this.pointColors[0],c=this.pointSizes[0]}var e=this.valueToXPlot(a.getX()),f=this.valueToYPlot(a.getY());this.isInside(e,f)&&(this.parent.push(),"undefined"!=typeof d?(this.parent.imageMode(this.parent.CENTER),this.parent.image(d,e,f)):(this.parent.ellipseMode(this.parent.CENTER),this.parent.fill(b),this.parent.noStroke(),this.parent.ellipse(e,f,c,c)),this.parent.pop())},GLayer.prototype.drawLines=function(){var a=this.plotPoints.length;this.parent.push(),this.parent.noFill(),this.parent.stroke(this.lineColor),this.parent.strokeWeight(this.lineWidth),this.parent.strokeCap(this.parent.SQUARE);for(var b=0;a-1>b;b++)if(this.inside[b]&&this.inside[b+1])this.parent.line(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.plotPoints[b+1].getX(),this.plotPoints[b+1].getY());else if(this.plotPoints[b].isValid()&&this.plotPoints[b+1].isValid()){var c=this.obtainBoxIntersections(this.plotPoints[b],this.plotPoints[b+1]);this.inside[b]?this.parent.line(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.cuts[0][0],this.cuts[0][1]):this.inside[b+1]?this.parent.line(this.cuts[0][0],this.cuts[0][1],this.plotPoints[b+1].getX(),this.plotPoints[b+1].getY()):c>=2&&this.parent.line(this.cuts[0][0],this.cuts[0][1],this.cuts[1][0],this.cuts[1][1])}this.parent.pop()},GLayer.prototype.drawLine=function(){var a,b,c,d,e,f;if(4===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(4===arguments.length)e=arguments[0],f=arguments[1],c=arguments[2],d=arguments[3];else if(2===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0],b=arguments[1],c=this.lineColor,d=this.lineWidth;else{if(2!==arguments.length)throw new Error("GLayer.drawLine(): signature not supported");e=arguments[0],f=arguments[1],c=this.lineColor,d=this.lineWidth}"undefined"!=typeof e&&(this.xLog&&this.yLog?(a=new GPoint(this.xLim[0],Math.pow(10,e*Math.log(this.xLim[0])/Math.LN10+yCut)),b=new GPoint(this.xLim[1],Math.pow(10,e*Math.log(this.xLim[1])/Math.LN10+yCut))):this.xLog?(a=new GPoint(this.xLim[0],e*Math.log(this.xLim[0])/Math.LN10+yCut),b=new GPoint(this.xLim[1],e*Math.log(this.xLim[1])/Math.LN10+yCut)):this.yLog?(a=new GPoint(this.xLim[0],Math.pow(10,e*this.xLim[0]+yCut)),b=new GPoint(this.xLim[1],Math.pow(10,e*this.xLim[1]+yCut))):(a=new GPoint(this.xLim[0],e*this.xLim[0]+yCut),b=new GPoint(this.xLim[1],e*this.xLim[1]+yCut)));var g=this.valueToPlot(a),h=this.valueToPlot(b);if(g.isValid()&&h.isValid()){var i=this.isInside(g),j=this.isInside(h);if(this.parent.push(),this.parent.noFill(),this.parent.stroke(c),this.parent.strokeWeight(d),this.parent.strokeCap(this.parent.SQUARE),i&&j)this.parent.line(g.getX(),g.getY(),h.getX(),h.getY());else{var k=this.obtainBoxIntersections(g,h);i?this.parent.line(g.getX(),g.getY(),this.cuts[0][0],this.cuts[0][1]):j?this.parent.line(this.cuts[0][0],this.cuts[0][1],h.getX(),h.getY()):k>=2&&this.parent.line(this.cuts[0][0],this.cuts[0][1],this.cuts[1][0],this.cuts[1][1])}this.parent.pop()}},GLayer.prototype.drawHorizontalLine=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else{if(1!==arguments.length)throw new Error("GLayer.drawHorizontalLine(): signature not supported");a=arguments[0],b=this.lineColor,c=this.lineWidth}var d=this.valueToYPlot(a);this.isValidNumber(d)&&-d>=0&&-d<=this.dim[1]&&(this.parent.push(),this.parent.noFill(),this.parent.stroke(b),this.parent.strokeWeight(c),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(0,d,this.dim[0],d),this.parent.pop())},GLayer.prototype.drawVerticalLine=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else{if(1!==arguments.length)throw new Error("GLayer.drawVerticalLine(): signature not supported");a=arguments[0],b=this.lineColor,c=this.lineWidth}var d=this.valueToXPlot(a);this.isValidNumber(d)&&d>=0&&d<=this.dim[0]&&(this.parent.push(),this.parent.noFill(),this.parent.stroke(b),this.parent.strokeWeight(c),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(d,0,d,-this.dim[1]),this.parent.pop())},GLayer.prototype.drawFilledContour=function(a,b){var c;if(a===GPlot.HORIZONTAL?c=this.getHorizontalShape(b):a===GPlot.VERTICAL&&(c=this.getVerticalShape(b)),"undefined"!=typeof c&&c.length>0){this.parent.push(),this.parent.fill(this.lineColor),this.parent.noStroke(),this.parent.beginShape();for(var d=0;di;i++)if(b=this.plotPoints[i],b.isValid()){for(c=!1,this.inside[i]?(f.push(new GPoint(b.getX(),b.getY(),"normal point")),c=!0):b.getX()>=0&&b.getX()<=this.dim[0]&&(-b.getY()<0?(f.push(new GPoint(b.getX(),0,"projection")),c=!0):(f.push(new GPoint(b.getX(),-this.dim[1],"projection")),c=!0)),d=i+1;e-1>d&&!this.plotPoints[d].isValid();)d++;if(e>d&&this.plotPoints[d].isValid())for(var j=this.obtainBoxIntersections(b,this.plotPoints[d]),k=0;j>k;k++)f.push(new GPoint(this.cuts[k][0],this.cuts[k][1],"cut")),c=!0;c&&(0>g&&(g=i),h=i)}if(f.length>0){var l=new GPoint(f[0]);if(0!==l.getX()&&l.getX()!==this.dim[0])if("cut"===l.getLabel())this.plotPoints[g].getX()<0?(l.setX(0),l.setLabel("extreme")):(l.setX(this.dim[0]),l.setLabel("extreme"));else if(0!==g){for(var m=g-1;m>0&&!this.plotPoints[m].isValid();)m--;this.plotPoints[m].isValid()&&(this.plotPoints[m].getX()<0?(l.setX(0),l.setLabel("extreme")):(l.setX(this.dim[0]),l.setLabel("extreme")))}var n=new GPoint(f[f.length-1]);if(0!==n.getX()&&n.getX()!==this.dim[0]&&h!==e-1){for(d=h+1;e-1>d&&!this.plotPoints[d].isValid();)d++;this.plotPoints[d].isValid()&&(this.plotPoints[d].getX()<0?(n.setX(0),n.setLabel("extreme")):(n.setX(this.dim[0]),n.setLabel("extreme")))}"extreme"===n.getLabel()&&f.push(n),this.yLog&&0>=a&&(a=Math.min(this.yLim[0],this.yLim[1]));var o=this.valueToPlot(1,a);-o[1]<0?(f.push(new GPoint(n.getX(),0)),f.push(new GPoint(l.getX(),0))):-o[1]>this.dim[1]?(f.push(new GPoint(n.getX(),-this.dim[1])),f.push(new GPoint(l.getX(),-this.dim[1]))):(f.push(new GPoint(n.getX(),o[1])),f.push(new GPoint(l.getX(),o[1]))),"extreme"===l.getLabel()&&f.push(l)}return f},GLayer.prototype.getVerticalShape=function(a){for(var b,c,d,e=this.plotPoints.length,f=[],g=-1,h=-1,i=0;e>i;i++)if(b=this.plotPoints[i],b.isValid()){for(c=!1,this.inside[i]?(f.push(new GPoint(b.getX(),b.getY(),"normal point")),c=!0):-b.getY()>=0&&-b.getY()<=this.dim[1]&&(b.getX()<0?(f.push(new GPoint(0,b.getY(),"projection")),c=!0):(f.push(new GPoint(this.dim[0],b.getY(),"projection")),c=!0)),d=i+1;e-1>d&&!this.plotPoints[d].isValid();)d++;if(e>d&&this.plotPoints[d].isValid())for(var j=this.obtainBoxIntersections(b,this.plotPoints[d]),k=0;j>k;k++)f.push(new GPoint(this.cuts[k][0],this.cuts[k][1],"cut")),c=!0;c&&(0>g&&(g=i),h=i)}if(f.length>0){var l=new GPoint(f[0]);if(0!==l.getY()&&l.getY()!==-this.dim[1])if("cut"===l.getLabel())-this.plotPoints[g].getY()<0?(l.setY(0),l.setLabel("extreme")):(l.setY(-this.dim[1]),l.setLabel("extreme"));else if(0!==g){for(var m=g-1;m>0&&!this.plotPoints[m].isValid();)m--;this.plotPoints[m].isValid()&&(-this.plotPoints[m].getY()<0?(l.setY(0),l.setLabel("extreme")):(l.setY(-this.dim[1]),l.setLabel("extreme")))}var n=new GPoint(f[f.length-1]);if(0!==n.getY()&&n.getY()!==-this.dim[1]&&h!==e-1){for(d=h+1;e-1>d&&!this.plotPoints[d].isValid();)d++;this.plotPoints[d].isValid()&&(-this.plotPoints[d].getY()<0?(n.setY(0),n.setLabel("extreme")):(n.setY(-this.dim[1]),n.setLabel("extreme")))}"extreme"===n.getLabel()&&f.push(n),this.xLog&&0>=a&&(a=Math.min(this.xLim[0],this.xLim[1]));var o=this.valueToPlot(a,1);o[0]<0?(f.push(new GPoint(0,n.getY())),f.push(new GPoint(0,l.getY()))):o[0]>this.dim[0]?(f.push(new GPoint(this.dim[0],n.getY())),f.push(new GPoint(this.dim[0],l.getY()))):(f.push(new GPoint(o[0],n.getY())),f.push(new GPoint(o[0],l.getY()))),"extreme"===l.getLabel()&&f.push(l)}return f},GLayer.prototype.drawLabel=function(a){var b=this.valueToXPlot(a.getX()),c=this.valueToYPlot(a.getY());if(this.isValidNumber(b)&&this.isValidNumber(c)){var d=b+this.labelSeparation[0],e=c-this.labelSeparation[1],f=this.fontSize/4;this.parent.push(),this.parent.rectMode(this.parent.CORNER),this.parent.noStroke(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.textAlign(this.parent.LEFT,this.parent.BOTTOM),this.parent.fill(this.labelBgColor),this.parent.rect(d-f,e-this.fontSize-f,this.parent.textWidth(a.getLabel())+2*f,this.fontSize+2*f),this.parent.fill(this.fontColor),this.parent.text(a.getLabel(),d,e),this.parent.pop()}},GLayer.prototype.drawLabelAtPlotPos=function(a,b){var c=this.getPointAtPlotPos(a,b);"undefined"!=typeof c&&this.drawLabel(c)},GLayer.prototype.drawHistogram=function(){"undefined"!=typeof this.hist&&this.hist.draw(this.valueToPlot(this.histBasePoint))},GLayer.prototype.drawPolygon=function(a,b){var c;if(a.length>2){var d=this.valueToPlot(a),e=0;for(c=0;cc;c++){f=d[c],this.isInside(f)&&h.push(new GPoint(f.getX(),f.getY(),"normal point"));var i=g>c+1?c+1:0,j=this.obtainBoxIntersections(f,d[i]);1===j?h.push(new GPoint(this.cuts[0][0],this.cuts[0][1],"single cut")):j>1&&(h.push(new GPoint(this.cuts[0][0],this.cuts[0][1],"double cut")),h.push(new GPoint(this.cuts[1][0],this.cuts[1][1],"double cut")))}g=h.length;var k=[];for(c=0;g>c;c++){k.push(h[c]);var l=g>c+1?c+1:0,m=h[c].getLabel(),n=h[l].getLabel(),o="single cut"===m&&"single cut"===n||"single cut"===m&&"double cut"===n||"double cut"===m&&"single cut"===n;if(o){var p=h[c].getX(),q=h[c].getY(),r=h[l].getX(),s=h[l].getY(),t=Math.abs(r-p),u=Math.abs(s-q);if(t>0&&u>0&&t!==this.dim[0]&&u!==this.dim[1]){var v=0===p||p===this.dim[0]?p:r,w=0===q||q===-this.dim[1]?q:s;k.push(new GPoint(v,w,"special cut"))}}}if(k.length>2){for(this.parent.push(),this.parent.fill(b),this.parent.noStroke(),this.parent.beginShape(),c=0;c0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updatePlotPoints(),"undefined"!=typeof this.hist&&(this.hist.setDim(this.dim),this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setXLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.setXLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&this.isValidNumber(a)&&this.isValidNumber(b)&&(this.xLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setYLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.setYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&this.isValidNumber(a)&&this.isValidNumber(b)&&(this.yLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=a,this.yLim[1]=b,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setXYLim=function(){var a,b,c,d;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else{if(2!==arguments.length)throw new Error("GLayer.setXYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1]}a!==b&&c!==d&&this.isValidNumber(a)&&this.isValidNumber(b)&&this.isValidNumber(c)&&this.isValidNumber(d)&&(this.xLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b),this.yLog&&(0>=c||0>=d)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=c,this.yLim[1]=d),this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setLimAndLog=function(){var a,b,c,d,e,f;if(6===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3],e=arguments[4],f=arguments[5];else{if(4!==arguments.length)throw new Error("GLayer.setLimAndLog(): signature not supported");a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1],e=arguments[2],f=arguments[3]}a!==b&&c!==d&&this.isValidNumber(a)&&this.isValidNumber(b)&&this.isValidNumber(c)&&this.isValidNumber(d)&&(e&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.yLim[1]=b,this.xLog=e),f&&(0>=c||0>=d)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=c,this.yLim[1]=d,this.yLog=f),this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setXLog=function(a){a!==this.xLog&&(a&&(this.xLim[0]<=0||this.xLim[1]<=0)&&(console.log("One of the limits is negative. This is not allowed in logarithmic scale."),console.log("Will set horizontal limits to (0.1, 10)"),this.xLim[0]=.1,this.xLim[1]=10),this.xLog=a,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setYLog=function(a){a!==this.yLog&&(a&&(this.yLim[0]<=0||this.yLim[1]<=0)&&(console.log("One of the limits is negative. This is not allowed in logarithmic scale."),console.log("Will set horizontal limits to (0.1, 10)"),this.yLim[0]=.1,this.yLim[1]=10),this.yLog=a,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setPoints=function(a){var b,c=a.length;if(this.points.length>c)this.points.splice(c,Number.MAX_VALUE);else for(b=this.points.length;c>b;b++)this.points[b]=new GPoint;for(b=0;c>b;b++)this.points[b].set(a[b]);this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)},GLayer.prototype.setPoint=function(){var a,b,c,d,e=this.points.length;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=aa)this.points[a].set(b,c,d),this.plotPoints[a].set(this.valueToXPlot(b),this.valueToYPlot(c),d),this.inside[a]=this.isInside(this.plotPoints[a]);else{if(a!==e)throw new Error("GLayer.setPoint(): the index position is outside the array size");this.points[a]=new GPoint(b,c,d),this.plotPoints[a]=new GPoint(this.valueToXPlot(b),this.valueToYPlot(c),d),this.inside[a]=this.isInside(this.plotPoints[a])}"undefined"!=typeof this.hist&&this.hist.setPlotPoint(a,this.plotPoints[a])},GLayer.prototype.addPoint=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length)a=arguments[0],b=arguments[1],c="";else{if(1!==arguments.length)throw new Error("GLayer.addPoint(): signature not supported");a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].getLabel()}this.points.push(new GPoint(a,b,c)),this.plotPoints.push(new GPoint(this.valueToXPlot(a),this.valueToYPlot(b),c)),this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length-1])),"undefined"!=typeof this.hist&&this.hist.addPlotPoint(this.plotPoints[this.plotPoints.length-1])},GLayer.prototype.addPoints=function(a){for(var b,c=a.length,d=0;c>d;d++)b=a[d],this.points.push(new GPoint(b)),this.plotPoints.push(new GPoint(this.valueToXPlot(b.getX()),this.valueToYPlot(b.getY()),b.getLabel())),this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length-1]));"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)},GLayer.prototype.addPointAtIndexPos=function(){var a,b,c,d;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d="";else{if(2!==arguments.length)throw new Error("GLayer.addPointAtIndexPos(): signature not supported");a=arguments[0],b=arguments[1].getX(),c=arguments[1].getY(),d=arguments[1].getLabel()}a<=this.points.length&&(this.points.splice(a,0,new GPoint(b,c,d)),this.plotPoints.splice(a,0,new GPoint(this.valueToXPlot(b),this.valueToYPlot(c),d)),this.inside.splice(a,0,this.isInside(this.plotPoints[0])),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.removePoint=function(a){a0&&(this.pointColors=a.slice())},GLayer.prototype.setPointColor=function(a){this.pointColors=[a]},GLayer.prototype.setPointSizes=function(a){a.length>0&&(this.pointSizes=a.slice())},GLayer.prototype.setPointSize=function(a){this.pointSizes=[a]},GLayer.prototype.setLineColor=function(a){this.lineColor=a},GLayer.prototype.setLineWidth=function(a){a>0&&(this.lineWidth=a)},GLayer.prototype.setHistBasePoint=function(a){this.histBasePoint.set(a)},GLayer.prototype.setHistType=function(a){"undefined"!=typeof this.hist&&this.hist.setType(a)},GLayer.prototype.setHistVisible=function(a){"undefined"!=typeof this.hist&&this.hist.setVisible(a)},GLayer.prototype.setDrawHistLabels=function(a){"undefined"!=typeof this.hist&&this.hist.setDrawLabels(a)},GLayer.prototype.setLabelBgColor=function(a){this.labelBgColor=a},GLayer.prototype.setLabelSeparation=function(a){this.labelSeparation[0]=a[0],this.labelSeparation[1]=a[1]},GLayer.prototype.setFontName=function(a){this.fontName=a},GLayer.prototype.setFontColor=function(a){this.fontColor=a},GLayer.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GLayer.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GLayer.prototype.setAllFontProperties=function(a,b,c){this.setFontProperties(a,b,c),"undefined"!=typeof this.hist&&this.hist.setFontProperties(a,b,c)},GLayer.prototype.getId=function(){return this.id},GLayer.prototype.getDim=function(){return this.dim.slice()},GLayer.prototype.getXLim=function(){return this.xLim.slice()},GLayer.prototype.getYLim=function(){return this.yLim.slice()},GLayer.prototype.getXLog=function(){return this.xLog},GLayer.prototype.getYLog=function(){return this.yLog},GLayer.prototype.getPoints=function(){for(var a=[],b=0;b=this.pos[0]&&a<=this.pos[0]+this.outerDim[0]&&b>=this.pos[1]&&b<=this.pos[1]+this.outerDim[1]},GPlot.prototype.isOverBox=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(0!==arguments.length)throw new Error("GPlot.isOverBox(): signature not supported");a=this.parent.mouseX,b=this.parent.mouseY}return a>=this.pos[0]+this.mar[1]&&a<=this.pos[0]+this.outerDim[0]-this.mar[3]&&b>=this.pos[1]+this.mar[2]&&b<=this.pos[1]+this.outerDim[1]-this.mar[0]},GPlot.prototype.updateLimits=function(){this.fixedXLim||(this.xLim=this.calculatePlotXLim(),this.xAxis.setLim(this.xLim),this.topAxis.setLim(this.xLim)),this.fixedYLim||(this.yLim=this.calculatePlotYLim(),this.yAxis.setLim(this.yLim),this.rightAxis.setLim(this.yLim)),this.mainLayer.setXYLim(this.xLim,this.yLim);for(var a=0;a=this.yLim[0]&&e>=this.yLim[0]&&e<=this.yLim[1]||this.yLim[1]=this.yLim[1]),!f||this.xLog&&0>=d||(db[1]&&(b[1]=d))}return b[1]=this.xLim[0]&&d>=this.xLim[0]&&d<=this.xLim[1]||this.xLim[1]=this.xLim[1]),!f||this.yLog&&0>=e||(eb[1]&&(b[1]=e))}return b[1]=0&&c[b]<=this.dim[0]&&this.parent.line(c[b],0,c[b],-this.dim[1])}if(a===GPlot.BOTH||a===GPlot.HORIZONTAL){var d=this.yAxis.getPlotTicksRef();for(b=0;b=0&&-d[b]<=this.dim[1]&&this.parent.line(0,d[b],this.dim[0],d[b])}this.parent.pop()},GPlot.prototype.drawHistograms=function(){this.mainLayer.drawHistogram();for(var a=0;a0&&b>0){var c=a-this.mar[1]-this.mar[3],d=b-this.mar[0]-this.mar[2];if(c>0&&d>0){this.outerDim[0]=a,this.outerDim[1]=b,this.dim[0]=c,this.dim[1]=d,this.xAxis.setDim(this.dim),this.topAxis.setDim(this.dim),this.yAxis.setDim(this.dim),this.rightAxis.setDim(this.dim),this.title.setDim(this.dim),this.mainLayer.setDim(this.dim);for(var e=0;e0&&f>0&&(this.mar[0]=a,this.mar[1]=b,this.mar[2]=c,this.mar[3]=d,this.outerDim[0]=e,this.outerDim[1]=f)},GPlot.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GPlot.setDim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}if(a>0&&b>0){var c=a+this.mar[1]+this.mar[3],d=b+this.mar[0]+this.mar[2];if(c>0&&d>0){this.outerDim[0]=c,this.outerDim[1]=d,this.dim[0]=a,this.dim[1]=b,this.xAxis.setDim(this.dim),this.topAxis.setDim(this.dim),this.yAxis.setDim(this.dim),this.rightAxis.setDim(this.dim),this.title.setDim(this.dim),this.mainLayer.setDim(this.dim);for(var e=0;e=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b,this.invertedXScale=this.xLim[0]>this.xLim[1],this.fixedXLim=!0,this.xAxis.setLim(this.xLim),this.topAxis.setLim(this.xLim),this.updateLimits()))},GPlot.prototype.setYLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GPlot.setYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&(this.yLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=a,this.yLim[1]=b,this.invertedYScale=this.yLim[0]>this.yLim[1],this.fixedYLim=!0,this.yAxis.setLim(this.yLim),this.rightAxis.setLim(this.yLim),this.updateLimits()))},GPlot.prototype.setFixedXLim=function(a){this.fixedXLim=a,this.updateLimits()},GPlot.prototype.setFixedYLim=function(a){this.fixedYLim=a,this.updateLimits()},GPlot.prototype.setLogScale=function(a){var b=this.xLog,c=this.yLog;if("xy"===a||"yx"===a?(b=!0,c=!0):"x"===a?(b=!0,c=!1):"y"===a?(b=!1,c=!0):""===a&&(b=!1,c=!1),b!==this.xLog||c!==this.yLog){this.xLog=b,this.yLog=c,this.xLog&&this.fixedXLim&&(this.xLim[0]<=0||this.xLim[1]<=0)&&(this.fixedXLim=!1),this.yLog&&this.fixedYLim&&(this.yLim[0]<=0||this.yLim[1]<=0)&&(this.fixedYLim=!1),this.fixedXLim||(this.xLim=this.calculatePlotXLim()),this.fixedYLim||(this.yLim=this.calculatePlotYLim()),this.xAxis.setLimAndLog(this.xLim,this.xLog),this.topAxis.setLimAndLog(this.xLim,this.xLog),this.yAxis.setLimAndLog(this.yLim,this.yLog),this.rightAxis.setLimAndLog(this.yLim,this.yLog),this.mainLayer.setLimAndLog(this.xLim,this.yLim,this.xLog,this.yLog);for(var d=0;d=0&&a!==this.expandLimFactor&&(this.expandLimFactor=a,this.updateLimits())},GPlot.prototype.setBgColor=function(a){this.bgColor=a},GPlot.prototype.setBoxBgColor=function(a){this.boxBgColor=a},GPlot.prototype.setBoxLineColor=function(a){this.boxLineColor=a},GPlot.prototype.setBoxLineWidth=function(a){a>0&&(this.boxLineWidth=a)},GPlot.prototype.setGridLineColor=function(a){this.gridLineColor=a},GPlot.prototype.setGridLineWidth=function(a){a>0&&(this.gridLineWidth=a)},GPlot.prototype.setPoints=function(){if(2===arguments.length)this.getLayer(arguments[1]).setPoints(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.setPoints(): signature not supported");this.mainLayer.setPoints(arguments[0])}this.updateLimits()},GPlot.prototype.setPoint=function(){if(5===arguments.length)this.getLayer(arguments[4]).setPoint(arguments[0],arguments[1],arguments[2],arguments[3]);else if(4===arguments.length)this.mainLayer.setPoint(arguments[0],arguments[1],arguments[2],arguments[3]);else if(3===arguments.length&&arguments[1]instanceof GPoint)this.getLayer(arguments[2]).setPoint(arguments[0],arguments[1]);else if(3===arguments.length)this.mainLayer.setPoint(arguments[0],arguments[1],arguments[2]);else{if(2!==arguments.length)throw new Error("GPlot.setPoint(): signature not supported");this.mainLayer.setPoint(arguments[0],arguments[1])}this.updateLimits()},GPlot.prototype.addPoint=function(){if(4===arguments.length)this.getLayer(arguments[3]).addPoint(arguments[0],arguments[1],arguments[2]);else if(3===arguments.length)this.mainLayer.addPoint(arguments[0],arguments[1],arguments[2]);else if(2===arguments.length&&arguments[0]instanceof GPoint)this.getLayer(arguments[1]).addPoint(arguments[0]);else if(2===arguments.length)this.mainLayer.addPoint(arguments[0],arguments[1]);else{if(1!==arguments.length)throw new Error("GPlot.addPoint(): signature not supported");this.mainLayer.addPoint(arguments[0])}this.updateLimits()},GPlot.prototype.addPoints=function(){if(2===arguments.length)this.getLayer(arguments[1]).addPoints(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.addPoints(): signature not supported");this.mainLayer.addPoints(arguments[0])}this.updateLimits()},GPlot.prototype.removePoint=function(){if(2===arguments.length)this.getLayer(arguments[1]).removePoint(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.removePoint(): signature not supported");this.mainLayer.removePoint(arguments[0])}this.updateLimits()},GPlot.prototype.addPointAtIndexPos=function(){if(5===arguments.length)this.getLayer(arguments[4]).addPointAtIndexPos(arguments[0],arguments[1],arguments[2],arguments[3]);else if(4===arguments.length)this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1],arguments[2],arguments[3]);else if(3===arguments.length&&arguments[1]instanceof GPoint)this.getLayer(arguments[2]).addPointAtIndexPos(arguments[0],arguments[1]);else if(3===arguments.length)this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1],arguments[2]);else{if(2!==arguments.length)throw new Error("GPlot.addPointAtIndexPos(): signature not supported");this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1])}this.updateLimits()},GPlot.prototype.setPointColors=function(a){this.mainLayer.setPointColors(a)},GPlot.prototype.setPointColor=function(a){this.mainLayer.setPointColor(a)},GPlot.prototype.setPointSizes=function(a){this.mainLayer.setPointSizes(a)},GPlot.prototype.setPointSize=function(a){this.mainLayer.setPointSize(a)},GPlot.prototype.setLineColor=function(a){this.mainLayer.setLineColor(a)},GPlot.prototype.setLineWidth=function(a){this.mainLayer.setLineWidth(a)},GPlot.prototype.setHistBasePoint=function(a){this.mainLayer.setHistBasePoint(a)},GPlot.prototype.setHistType=function(a){this.mainLayer.setHistType(a)},GPlot.prototype.setHistVisible=function(a){this.mainLayer.setHistVisible(a)},GPlot.prototype.setDrawHistLabels=function(a){this.mainLayer.setDrawHistLabels(a)},GPlot.prototype.setLabelBgColor=function(a){this.mainLayer.setLabelBgColor(a)},GPlot.prototype.setLabelSeparation=function(a){this.mainLayer.setLabelSeparation(a)},GPlot.prototype.setTitleText=function(a){this.title.setText(a)},GPlot.prototype.setAxesOffset=function(a){this.xAxis.setOffset(a),this.topAxis.setOffset(a),this.yAxis.setOffset(a),this.rightAxis.setOffset(a)},GPlot.prototype.setTicksLength=function(a){this.xAxis.setTickLength(a),this.topAxis.setTickLength(a),this.yAxis.setTickLength(a),this.rightAxis.setTickLength(a)},GPlot.prototype.setHorizontalAxesNTicks=function(a){this.xAxis.setNTicks(a),this.topAxis.setNTicks(a)},GPlot.prototype.setHorizontalAxesTicksSeparation=function(a){this.xAxis.setTicksSeparation(a),this.topAxis.setTicksSeparation(a)},GPlot.prototype.setHorizontalAxesTicks=function(a){this.xAxis.setTicks(a),this.topAxis.setTicks(a)},GPlot.prototype.setVerticalAxesNTicks=function(a){this.yAxis.setNTicks(a),this.rightAxis.setNTicks(a)},GPlot.prototype.setVerticalAxesTicksSeparation=function(a){this.yAxis.setTicksSeparation(a),this.rightAxis.setTicksSeparation(a)},GPlot.prototype.setVerticalAxesTicks=function(a){this.yAxis.setTicks(a),this.rightAxis.setTicks(a)},GPlot.prototype.setFontName=function(a){this.maniLayer.setFontName(a)},GPlot.prototype.setFontColor=function(a){this.maniLayer.setFontColor(a)},GPlot.prototype.setFontSize=function(a){this.maniLayer.setFontSize(a)},GPlot.prototype.setFontProperties=function(a,b,c){this.maniLayer.setFontProperties(a,b,c)},GPlot.prototype.setAllFontProperties=function(a,b,c){this.xAxis.setAllFontProperties(a,b,c),this.topAxis.setAllFontProperties(a,b,c),this.yAxis.setAllFontProperties(a,b,c),this.rightAxis.setAllFontProperties(a,b,c),this.title.setFontProperties(a,b,c),this.mainLayer.setAllFontProperties(a,b,c);for(var d=0;d0&&(this.zoomFactor=a),(b===this.parent.LEFT||b===this.parent.RIGHT||b===this.parent.CENTER)&&(this.increaseZoomButton=b),(c===this.parent.LEFT||c===this.parent.RIGHT||c===this.parent.CENTER)&&(this.decreaseZoomButton=c),(d===this.parent.SHIFT||d===this.parent.CONTROL||d===this.parent.ALT||d===GPlot.NONE)&&(this.increaseZoomKeyModifier=d),(e===this.parent.SHIFT||e===this.parent.CONTROL||e===this.parent.ALT||e===GPlot.NONE)&&(this.decreaseZoomKeyModifier=e)},GPlot.prototype.deactivateZooming=function(){this.zoomingIsActive=!1},GPlot.prototype.activateCentering=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activateCentering(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.centeringIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.centeringButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.centeringKeyModifier=b)},GPlot.prototype.deactivateCentering=function(){this.centeringIsActive=!1},GPlot.prototype.activatePanning=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activatePanning(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.panningIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.panningButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.panningKeyModifier=b)},GPlot.prototype.deactivatePanning=function(){this.panningIsActive=!1,this.panningReferencePoint=void 0},GPlot.prototype.activatePointLabels=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activatePointLabels(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.labelingIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.labelingButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.labelingKeyModifier=b)},GPlot.prototype.deactivatePointLabels=function(){this.labelingIsActive=!1,this.mousePos=void 0},GPlot.prototype.activateReset=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activateReset(): signature not supported");a=this.parent.RIGHT,b=GPlot.NONE}this.resetIsActive=!0,this.xLimReset=void 0,this.yLimReset=void 0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.resetButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.resetKeyModifier=b)},GPlot.prototype.deactivateReset=function(){this.resetIsActive=!1,this.xLimReset=void 0,this.yLimReset=void 0},GPlot.prototype.getButton=function(a){var b;return 0===a.button?b=this.parent.LEFT:1===a.button?b=this.parent.CENTER:2===a.button?b=this.parent.RIGHT:"undefined"==typeof a.button&&(b=this.parent.LEFT),b},GPlot.prototype.getModifier=function(a){var b;return b=a.altKey?this.parent.ALT:a.ctrlKey?this.parent.CONTROL:a.shiftKey?this.parent.SHIFT:GPlot.NONE},GPlot.prototype.saveResetLimits=function(){("undefined"==typeof this.xLimReset||"undefined"==typeof this.yLimReset)&&(this.xLimReset=this.xLim.slice(),this.yLimReset=this.yLim.slice())},GPlot.prototype.panningFunction=function(){"undefined"!=typeof this.panningReferencePoint&&this.align(this.panningReferencePoint,this.parent.mouseX,this.parent.mouseY)},GPlot.prototype.clickEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=this.getButton(e),c=this.getModifier(e);this.zoomingIsActive&&(b===this.increaseZoomButton&&c===this.increaseZoomKeyModifier?(this.resetIsActive&&this.saveResetLimits(),this.zoom(this.zoomFactor,this.parent.mouseX,this.parent.mouseY)):b===this.decreaseZoomButton&&c===this.decreaseZoomKeyModifier&&(this.resetIsActive&&this.saveResetLimits(),this.zoom(1/this.zoomFactor,this.parent.mouseX,this.parent.mouseY))),this.centeringIsActive&&b===this.centeringButton&&c===this.centeringKeyModifier&&(this.resetIsActive&&this.saveResetLimits(), +this.center(this.parent.mouseX,this.parent.mouseY)),this.resetIsActive&&b===this.resetButton&&c===this.resetKeyModifier&&"undefined"!=typeof this.xLimReset&&"undefined"!=typeof this.yLimReset&&(this.setXLim(this.xLimReset),this.setYLim(this.yLimReset),this.xLimReset=void 0,this.yLimReset=void 0)}},GPlot.prototype.mouseDownEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=this.getButton(e),c=this.getModifier(e);this.panningIsActive&&b===this.panningButton&&c===this.panningKeyModifier&&(this.resetIsActive&&this.saveResetLimits(),this.panningReferencePoint=this.getValueAt(this.parent.mouseX,this.parent.mouseY),this.panningIntervalId=setInterval(this.panningFunction.bind(this),100)),this.labelingIsActive&&b===this.labelingButton&&c===this.labelingKeyModifier&&(this.mousePos=[this.parent.mouseX,this.parent.mouseY])}},GPlot.prototype.mouseUpEvent=function(a){e=a||window.event;{var b=this.getButton(e);this.getModifier(e)}this.panningIsActive&&b===this.panningButton&&"undefined"!=typeof this.panningIntervalId&&(clearInterval(this.panningIntervalId),this.panningIntervalId=void 0,this.panningReferencePoint=void 0),this.labelingIsActive&&b===this.labelingButton&&(this.mousePos=void 0),b===this.parent.RIGHT&&this.clickEvent(e)},GPlot.prototype.wheelEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=e.deltaY,c=this.parent.CENTER,d=this.getModifier(e);this.zoomingIsActive&&(c===this.increaseZoomButton&&d===this.increaseZoomKeyModifier&&b>0?(this.resetIsActive&&this.saveResetLimits(),this.zoom(this.zoomFactor,this.parent.mouseX,this.parent.mouseY)):c===this.decreaseZoomButton&&d===this.decreaseZoomKeyModifier&&0>b&&(this.resetIsActive&&this.saveResetLimits(),this.zoom(1/this.zoomFactor,this.parent.mouseX,this.parent.mouseY)))}},GPlot.prototype.preventDefaultEvent=function(a){e=a||window.event,this.isOverBox()&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},GPlot.prototype.preventWheelDefault=function(){window.addEventListener("wheel",this.preventDefaultEvent.bind(this),!1)},GPlot.prototype.preventRightClickDefault=function(){window.addEventListener("contextmenu",this.preventDefaultEvent.bind(this),!1)}; diff --git a/graficos/grafica-0.1.0.min.js b/graficos/grafica-0.1.0.min.js new file mode 100644 index 0000000..6e86b8a --- /dev/null +++ b/graficos/grafica-0.1.0.min.js @@ -0,0 +1,5 @@ +/*! grafica.js (0.1.0): a library for p5.js. Author: Javier Graciá Carpio, license: LGPL-3.0, 2015-04-12 */ function GPoint(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length&&arguments[0]instanceof p5.Vector)a=arguments[0].x,b=arguments[0].y,c=arguments[1];else if(2===arguments.length)a=arguments[0],b=arguments[1],c="";else if(1===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].getLabel();else if(1===arguments.length&&arguments[0]instanceof p5.Vector)a=arguments[0].x,b=arguments[0].y,c="";else{if(0!==arguments.length)throw new Error("GPoint constructor: signature not supported");a=0,b=0,c=""}this.x=a,this.y=b,this.label=c,this.valid=this.isValidNumber(this.x)&&this.isValidNumber(this.y)}function GTitle(a,b){this.parent=a,this.dim=b.slice(),this.relativePos=.5,this.plotPos=this.relativePos*this.dim[0],this.offset=10,this.text="",this.textAlignment=this.parent.CENTER,this.fontName="Helvetica",this.fontColor=this.parent.color(100),this.fontStyle=this.parent.BOLD,this.fontSize=13}function GAxisLabel(a,b,c){this.parent=a,this.type=b===this.parent.BOTTOM||b===this.parent.TOP||b===this.parent.LEFT||b===this.parent.RIGHT?b:this.parent.BOTTOM,this.dim=c.slice(),this.relativePos=.5,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1],this.offset=35,this.rotate=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?!1:!0,this.text="",this.textAlignment=this.parent.CENTER,this.fontName="Helvetica",this.fontColor=this.parent.color(0),this.fontSize=13}function GAxis(a,b,c,d,e){this.parent=a,this.type=b===this.parent.BOTTOM||b===this.parent.TOP||b===this.parent.LEFT||b===this.parent.RIGHT?b:this.parent.BOTTOM,this.dim=c.slice(),this.lim=d.slice(),this.log=e,this.log&&(this.lim[0]<=0||this.lim[1]<=0)&&(console.log("The limits are negative. This is not allowed in logarithmic scale."),console.log("Will set them to (0.1, 10)"),this.lim[1]>this.lim[0]?(this.lim[0]=.1,this.lim[1]=10):(this.lim[0]=10,this.lim[1]=.1)),this.offset=5,this.lineColor=this.parent.color(0),this.lineWidth=1,this.nTicks=5,this.ticksSeparation=-1,this.ticks=[],this.plotTicks=[],this.ticksInside=[],this.tickLabels=[],this.fixedTicks=!1,this.tickLength=3,this.smallTickLength=2,this.expTickLabels=!1,this.rotateTickLabels=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?!1:!0,this.drawTickLabels=this.type===this.parent.BOTTOM||this.type===this.parent.LEFT?!0:!1,this.tickLabelOffset=7,this.ticksPrecision=void 0,this.lab=new GAxisLabel(this.parent,this.type,this.dim),this.drawAxisLabel=!0,this.fontName="Helvetica",this.fontColor=this.parent.color(0),this.fontSize=11,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()}function GHistogram(a,b,c,d){this.parent=a,this.type=b===GPlot.VERTICAL||b===GPlot.HORIZONTAL?b:GPlot.VERTICAL,this.dim=c.slice(),this.plotPoints=[];for(var e=0;e0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.plotPos=this.relativePos*this.dim[0])},GTitle.prototype.setRelativePos=function(a){this.relativePos=a,this.plotPos=this.relativePos*this.dim[0]},GTitle.prototype.setOffset=function(a){this.offset=a},GTitle.prototype.setText=function(a){this.text=a},GTitle.prototype.setTextAlignment=function(a){(a===this.parent.CENTER||a===this.parent.LEFT||a===this.parent.RIGHT)&&(this.textAlignment=a)},GTitle.prototype.setFontName=function(a){this.fontName=a},GTitle.prototype.setFontColor=function(a){this.fontColor=a},GTitle.prototype.setFontStyle=function(a){this.fontStyle=a},GTitle.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GTitle.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxisLabel.prototype.draw=function(){switch(this.type){case this.parent.BOTTOM:this.drawAsXLabel();break;case this.parent.LEFT:this.drawAsYLabel();break;case this.parent.TOP:this.drawAsTopLabel();break;case this.parent.RIGHT:this.drawAsRightLabel()}},GAxisLabel.prototype.drawAsXLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),this.parent.translate(this.plotPos,this.offset),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.textAlignment,this.parent.TOP),this.parent.text(this.text,this.plotPos,this.offset)),this.parent.pop()},GAxisLabel.prototype.drawAsYLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.textAlignment,this.parent.BOTTOM),this.parent.translate(-this.offset,this.plotPos),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),this.parent.text(this.text,-this.offset,this.plotPos)),this.parent.pop()},GAxisLabel.prototype.drawAsTopLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.parent.LEFT,this.parent.CENTER),this.parent.translate(this.plotPos,-this.offset-this.dim[1]),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.textAlignment,this.parent.BOTTOM),this.parent.text(this.text,this.plotPos,-this.offset-this.dim[1])),this.parent.pop()},GAxisLabel.prototype.drawAsRightLabel=function(){this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.rotate?(this.parent.textAlign(this.textAlignment,this.parent.TOP),this.parent.translate(this.offset+this.dim[0],this.plotPos),this.parent.rotate(-.5*Math.PI),this.parent.text(this.text,0,0)):(this.parent.textAlign(this.parent.LEFT,this.parent.CENTER),this.parent.text(this.text,this.offset+this.dim[0],this.plotPos)),this.parent.pop()},GAxisLabel.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GAxisLabel.setDim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a>0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1])},GAxisLabel.prototype.setRelativePos=function(a){this.relativePos=a,this.plotPos=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.relativePos*this.dim[0]:-this.relativePos*this.dim[1]},GAxisLabel.prototype.setOffset=function(a){this.offset=a},GAxisLabel.prototype.setRotate=function(a){this.rotate=a},GAxisLabel.prototype.setText=function(a){this.text=a},GAxisLabel.prototype.setTextAlignment=function(a){(a===this.parent.CENTER||a===this.parent.LEFT||a===this.parent.RIGHT)&&(this.textAlignment=a)},GAxisLabel.prototype.setFontName=function(a){this.fontName=a},GAxisLabel.prototype.setFontColor=function(a){this.fontColor=a},GAxisLabel.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GAxisLabel.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxis.prototype.obtainSigDigits=function(a){return Math.round(-Math.log(.5*Math.abs(a))/Math.LN10)},GAxis.prototype.roundPlus=function(a,b){return a=Math.round(a*Math.pow(10,b))/Math.pow(10,b),0>=b&&(a=Math.round(a)),a},GAxis.prototype.adaptSize=function(a,b){bthis.lim[0]?(a=Math.floor(Math.log(this.lim[0])/Math.LN10),b=Math.ceil(Math.log(this.lim[1])/Math.LN10)):(a=Math.floor(Math.log(this.lim[1])/Math.LN10),b=Math.ceil(Math.log(this.lim[0])/Math.LN10));var c=9*(b-a)+1;this.adaptSize(this.ticks,c);for(var d=a;b>d;d++)for(var e=this.roundPlus(Math.exp(d*Math.LN10),-d),f=0;9>f;f++)this.ticks[9*(d-a)+f]=(f+1)*e;this.ticks[this.ticks.length-1]=this.roundPlus(Math.exp(b*Math.LN10),-d),this.lim[1]0){for(a=this.lim[1]>this.lim[0]?this.ticksSeparation:-this.ticksSeparation,c=this.obtainSigDigits(a);this.roundPlus(a,c)-a!==0;)c++;b=Math.floor((this.lim[1]-this.lim[0])/a)}else this.nTicks>0&&(a=(this.lim[1]-this.lim[0])/this.nTicks,c=this.obtainSigDigits(a),a=this.roundPlus(a,c),(0===a||Math.abs(a)>Math.abs(this.lim[1]-this.lim[0]))&&(c++,a=this.roundPlus((this.lim[1]-this.lim[0])/this.nTicks,c)),b=Math.floor((this.lim[1]-this.lim[0])/a));if(b>0){var d=this.lim[0]+(this.lim[1]-this.lim[0]-b*a)/2;for(d=this.roundPlus(d-2*a,c);(this.lim[1]-d)*(this.lim[0]-d)>0;)d=this.roundPlus(d+a,c);var e=Math.floor(Math.abs((this.lim[1]-d)/a))+1;this.adaptSize(this.ticks,e),this.ticks[0]=d;for(var f=1;e>f;f++)this.ticks[f]=this.roundPlus(this.ticks[f-1]+a,c);this.ticksPrecision=c}else this.ticks=[]},GAxis.prototype.updatePlotTicks=function(){var a,b,c=this.ticks.length;if(this.adaptSize(this.plotTicks,c),this.log)for(a=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.dim[0]/Math.log(this.lim[1]/this.lim[0]):-this.dim[1]/Math.log(this.lim[1]/this.lim[0]),b=0;c>b;b++)this.plotTicks[b]=Math.log(this.ticks[b]/this.lim[0])*a;else for(a=this.type===this.parent.BOTTOM||this.type===this.parent.TOP?this.dim[0]/(this.lim[1]-this.lim[0]):-this.dim[1]/(this.lim[1]-this.lim[0]),b=0;c>b;b++)this.plotTicks[b]=(this.ticks[b]-this.lim[0])*a},GAxis.prototype.updateTicksInside=function(){var a,b=this.ticks.length;if(this.adaptSize(this.ticksInside,b),this.type===this.parent.BOTTOM||this.type===this.parent.TOP)for(a=0;b>a;a++)this.ticksInside[a]=this.plotTicks[a]>=0&&this.plotTicks[a]<=this.dim[0];else for(a=0;b>a;a++)this.ticksInside[a]=-this.plotTicks[a]>=0&&-this.plotTicks[a]<=this.dim[1]},GAxis.prototype.updateTickLabels=function(){var a,b,c,d,e=this.ticks.length;if(this.adaptSize(this.tickLabels,e),this.log)for(d=0;e>d;d++)a=this.ticks[d],a>0?(b=Math.log(a)/Math.LN10,c=Math.abs(b-Math.round(b))<1e-4,c?(b=Math.round(b),this.tickLabels[d]=this.expTickLabels?"1e"+b:b>-3.1&&3.1>b?b>=0?""+Math.round(a):""+a:"1e"+b):this.tickLabels[d]=""):this.tickLabels[d]="";else for(d=0;e>d;d++)a=this.ticks[d],this.tickLabels[d]=a%1===0?""+Math.round(a):"undefined"!=typeof this.ticksPrecision&&this.ticksPrecision>=0?""+parseFloat(a).toFixed(this.ticksPrecision):""+a},GAxis.prototype.moveLim=function(a){if(a[1]!==a[0])if(this.log&&(a[0]<=0||a[1]<=0))console.log("The limits are negative. This is not allowed in logarithmic scale.");else{if(this.lim[0]=a[0],this.lim[1]=a[1],!this.fixedTicks){var b=this.ticks.length;if(this.log)this.obtainLogarithmicTicks();else if(b>0){var c=0,d=0;if(this.ticksSeparation>0)for(c=this.lim[1]>this.lim[0]?this.ticksSeparation:-this.ticksSeparation,d=this.obtainSigDigits(c);this.roundPlus(c,d)-c!==0;)d++;else c=1===b?this.lim[1]-this.lim[0]:this.ticks[1]-this.ticks[0],d=this.obtainSigDigits(c),c=this.roundPlus(c,d),(0===c||Math.abs(c)>Math.abs(this.lim[1]-this.lim[0]))&&(d++,c=1===b?this.lim[1]-this.lim[0]:this.ticks[1]-this.ticks[0],c=this.roundPlus(c,d)),c=this.lim[1]>this.lim[0]?Math.abs(c):-Math.abs(c);var e=this.ticks[0]+c*Math.ceil((this.lim[0]-this.ticks[0])/c);e=this.roundPlus(e,d),(this.lim[1]-e)*(this.lim[0]-e)>0&&(e=this.ticks[0]+c*Math.floor((this.lim[0]-this.ticks[0])/c),e=this.roundPlus(e,d)),b=Math.floor(Math.abs((this.lim[1]-e)/c))+1,this.adaptSize(this.ticks,b),this.ticks[0]=e;for(var f=1;b>f;f++)this.ticks[f]=this.roundPlus(this.ticks[f-1]+c,d);this.ticksPrecision!==d&&console.log("There is a problem in the axis ticks precision calculation")}this.updateTickLabels()}this.updatePlotTicks(),this.updateTicksInside()}},GAxis.prototype.draw=function(){switch(this.type){case this.parent.BOTTOM:this.drawAsXAxis();break;case this.parent.LEFT:this.drawAsYAxis();break;case this.parent.TOP:this.drawAsTopAxis();break;case this.parent.RIGHT:this.drawAsRightAxis()}this.drawAxisLabel&&this.lab.draw()},GAxis.prototype.drawAsXAxis=function(){var a;for(this.parent.push(),this.parent.stroke(this.lineColor),this.parent.strokeWeight(this.lineWidth),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(0,this.offset,this.dim[0],this.offset),a=0;a0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updatePlotTicks(),this.lab.setDim(this.dim))},GAxis.prototype.setLim=function(a){a[1]!==a[0]&&(this.log&&(a[0]<=0||a[1]<=0)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.lim[0]=a[0],this.lim[1]=a[1],this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside()))},GAxis.prototype.setLimAndLog=function(a,b){a[1]!==a[0]&&(b&&(a[0]<=0||a[1]<=0)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.lim[0]=a[0],this.lim[1]=a[1],this.log=b,this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside()))},GAxis.prototype.setLog=function(a){a!==this.log&&(this.log=a,this.log&&(this.lim[0]<=0||this.lim[1]<=0)&&(console.log("The limits are negative. This is not allowed in logarithmic scale."),console.log("Will set them to (0.1, 10)"),this.lim[1]>this.lim[0]?(this.lim[0]=.1,this.lim[1]=10):(this.lim[0]=10,this.lim[1]=.1)),this.fixedTicks||(this.updateTicks(),this.updateTickLabels()),this.updatePlotTicks(),this.updateTicksInside())},GAxis.prototype.setOffset=function(a){this.offset=a},GAxis.prototype.setLineColor=function(a){this.lineColor=a},GAxis.prototype.setLineWidth=function(a){a>0&&(this.lineWidth=a)},GAxis.prototype.setNTicks=function(a){a>=0&&(this.nTicks=a,this.ticksSeparation=-1,this.log||(this.fixedTicks=!1,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()))},GAxis.prototype.setTicksSeparation=function(a){this.ticksSeparation=a,this.log||(this.fixedTicks=!1,this.updateTicks(),this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels())},GAxis.prototype.setTicks=function(a){var b=a.length;this.adaptSize(this.ticks,b);for(var c=0;b>c;c++)this.ticks[c]=a[c];this.fixedTicks=!0,this.ticksPrecision=void 0,this.updatePlotTicks(),this.updateTicksInside(),this.updateTickLabels()},GAxis.prototype.setTickLabels=function(a){if(a.length===this.tickLabels.length){for(var b=0;b0&&(this.fontSize=a)},GAxis.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GAxis.prototype.setAllFontProperties=function(a,b,c){this.setFontProperties(a,b,c),this.lab.setFontProperties(a,b,c)},GAxis.prototype.getTicks=function(){if(this.fixedTicks)return this.ticks.slice();for(var a=[],b=0,c=0;cb&&(this.differences.splice(b,Number.MAX_VALUE),this.leftSides.splice(b,Number.MAX_VALUE),this.rightSides.splice(b,Number.MAX_VALUE)),1===b)this.leftSides[0]=this.type===GPlot.VERTICAL?.2*this.dim[0]:.2*this.dim[1],this.rightSides[0]=this.leftSides[0];else if(b>1){for(a=0;b-1>a;a++)if(this.plotPoints[a].isValid()&&this.plotPoints[a+1].isValid()){var c,d=this.separations[a%this.separations.length];c=this.type===GPlot.VERTICAL?this.plotPoints[a+1].getX()-this.plotPoints[a].getX():this.plotPoints[a+1].getY()-this.plotPoints[a].getY(),this.differences[a]=c>0?(c-d)/2:(c+d)/2}else this.differences[a]=0;for(this.leftSides[0]=this.differences[0],this.rightSides[0]=this.differences[0],a=1;b-1>a;a++)this.leftSides[a]=this.differences[a-1],this.rightSides[a]=this.differences[a];this.leftSides[b-1]=this.differences[b-2],this.rightSides[b-1]=this.differences[b-2]}},GHistogram.prototype.draw=function(a){if(this.visible){var b=0;a.isValid()&&(b=this.type===GPlot.VERTICAL?a.getY():a.getX());var c,d,e,f,g,h,i=this.plotPoints.length;this.parent.push(),this.parent.rectMode(this.parent.CORNERS),this.parent.strokeCap(this.parent.SQUARE);for(var j=0;i>j;j++)c=this.plotPoints[j],c.isValid()&&(this.type===GPlot.VERTICAL?(d=c.getX()-this.leftSides[j],e=c.getX()+this.rightSides[j],f=c.getY(),g=b):(d=b,e=c.getX(),f=c.getY()-this.leftSides[j],g=c.getY()+this.rightSides[j]),0>d?d=0:d>this.dim[0]&&(d=this.dim[0]),0>-f?f=0:-f>this.dim[1]&&(f=-this.dim[1]),0>e?e=0:e>this.dim[0]&&(e=this.dim[0]),0>-g?g=0:-g>this.dim[1]&&(g=-this.dim[1]),h=this.lineWidths[j%this.lineWidths.length],this.parent.fill(this.bgColors[j%this.bgColors.length]),this.parent.stroke(this.lineColors[j%this.lineColors.length]),this.parent.strokeWeight(h),Math.abs(e-d)>2*h&&Math.abs(g-f)>2*h?this.parent.rect(d,f,e,g):(this.type===GPlot.VERTICAL&&e!==d&&(f!==g||0!==f&&f!==-this.dim[1])||this.type===GPlot.HORIZONTAL&&g!==f&&(d!==e||0!==d&&d!==this.dim[0]))&&(this.parent.rect(d,f,e,g),this.parent.line(d,f,d,g),this.parent.line(e,f,e,g),this.parent.line(d,f,e,f),this.parent.line(d,g,e,g)));this.parent.pop(),this.drawLabels&&this.drawHistLabels()}},GHistogram.prototype.drawHistLabels=function(){var a,b,c=this.plotPoints.length,d=.5*Math.PI;if(this.parent.push(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.fill(this.fontColor),this.parent.noStroke(),this.type===GPlot.VERTICAL)if(this.rotateLabels)for(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&a.getX()>=0&&a.getX()<=this.dim[0]&&(this.parent.push(),this.parent.translate(a.getX(),this.labelsOffset),this.parent.rotate(-d),this.parent.text(a.getLabel(),0,0),this.parent.pop());else for(this.parent.textAlign(this.parent.CENTER,this.parent.TOP),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&a.getX()>=0&&a.getX()<=this.dim[0]&&this.parent.text(a.getLabel(),a.getX(),this.labelsOffset);else if(this.rotateLabels)for(this.parent.textAlign(this.parent.CENTER,this.parent.BOTTOM),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&-a.getY()>=0&&-a.getY()<=this.dim[1]&&(this.parent.push(),this.parent.translate(-this.labelsOffset,a.getY()),this.parent.rotate(-d),this.parent.text(a.getLabel(),0,0),this.parent.pop());else for(this.parent.textAlign(this.parent.RIGHT,this.parent.CENTER),b=0;c>b;b++)a=this.plotPoints[b],a.isValid()&&-a.getY()>=0&&-a.getY()<=this.dim[1]&&this.parent.text(a.getLabel(),-this.labelsOffset,a.getY());this.parent.pop()},GHistogram.prototype.setType=function(a){a===this.type||a!==GPlot.VERTICAL&&a!==GPlot.HORIZONTAL||(this.type=a,this.updateArrays())},GHistogram.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GHistogram.setDim(): signature not supported"); + +a=arguments[0][0],b=arguments[0][1]}a>0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updateArrays())},GHistogram.prototype.setPlotPoints=function(a){var b,c=a.length;if(this.plotPoints.length===c)for(b=0;c>b;b++)this.plotPoints[b].set(a[b]);else if(this.plotPoints.length>c){for(b=0;c>b;b++)this.plotPoints[b].set(a[b]);this.plotPoints.splice(c,Number.MAX_VALUE)}else{for(b=0;bb;b++)this.plotPoints[b]=new GPoint(a[b])}this.updateArrays()},GHistogram.prototype.setPlotPoint=function(a,b){if(a0&&(this.fontSize=a)},GHistogram.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GLayer.prototype.isValidNumber=function(a){return!isNaN(a)&&isFinite(a)},GLayer.prototype.isId=function(a){return this.id===a},GLayer.prototype.valueToXPlot=function(a){return this.xLog?this.dim[0]*Math.log(a/this.xLim[0])/Math.log(this.xLim[1]/this.xLim[0]):this.dim[0]*(a-this.xLim[0])/(this.xLim[1]-this.xLim[0])},GLayer.prototype.valueToYPlot=function(a){return this.yLog?-this.dim[1]*Math.log(a/this.yLim[0])/Math.log(this.yLim[1]/this.yLim[0]):-this.dim[1]*(a-this.yLim[0])/(this.yLim[1]-this.yLim[0])},GLayer.prototype.valueToPlot=function(){if(2===arguments.length)return[this.valueToXPlot(arguments[0]),this.valueToYPlot(arguments[1])];if(1===arguments.length&&arguments[0]instanceof GPoint)return new GPoint(this.valueToXPlot(arguments[0].getX()),this.valueToYPlot(arguments[0].getY()),arguments[0].getLabel());if(1===arguments.length&&arguments[0]instanceof Array&&arguments[0][0]instanceof GPoint){var a,b,c,d,e,f,g=arguments[0].length,h=[];if(this.xLog&&this.yLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=Math.log(c.getX()/this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else if(this.xLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=Math.log(c.getX()/this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else if(this.yLog)for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=(c.getX()-this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());else for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=arguments[0][f],d=(c.getX()-this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,h[f]=new GPoint(d,e,c.getLabel());return h}throw new Error("GLayer.valueToPlot(): signature not supported")},GLayer.prototype.updatePlotPoints=function(){var a,b,c,d,e,f,g=this.points.length;if(this.plotPoints.lengthf;f++)this.plotPoints[f]=new GPoint;else this.plotPoints.length>g&&this.plotPoints.splice(g,Number.MAX_VALUE);if(this.xLog&&this.yLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=Math.log(c.getX()/this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else if(this.xLog)for(a=this.dim[0]/Math.log(this.xLim[1]/this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=Math.log(c.getX()/this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else if(this.yLog)for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/Math.log(this.yLim[1]/this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=(c.getX()-this.xLim[0])*a,e=Math.log(c.getY()/this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel());else for(a=this.dim[0]/(this.xLim[1]-this.xLim[0]),b=-this.dim[1]/(this.yLim[1]-this.yLim[0]),f=0;g>f;f++)c=this.points[f],d=(c.getX()-this.xLim[0])*a,e=(c.getY()-this.yLim[0])*b,this.plotPoints[f].set(d,e,c.getLabel())},GLayer.prototype.xPlotToValue=function(a){return this.xLog?Math.exp(Math.log(this.xLim[0])+Math.log(this.xLim[1]/this.xLim[0])*a/this.dim[0]):this.xLim[0]+(this.xLim[1]-this.xLim[0])*a/this.dim[0]},GLayer.prototype.yPlotToValue=function(a){return this.yLog?Math.exp(Math.log(this.yLim[0])-Math.log(this.yLim[1]/this.yLim[0])*a/this.dim[1]):this.yLim[0]-(this.yLim[1]-this.yLim[0])*a/this.dim[1]},GLayer.prototype.plotToValue=function(a,b){return[this.xPlotToValue(a),this.yPlotToValue(b)]},GLayer.prototype.isInside=function(){var a,b,c;if(2===arguments.length)a=arguments[0],b=arguments[1],c=this.isValidNumber(a)&&this.isValidNumber(b);else{if(!(1===arguments.length&&arguments[0]instanceof GPoint))throw new Error("GLayer.isInside(): signature not supported");a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].isValid()}return c?a>=0&&a<=this.dim[0]&&-b>=0&&-b<=this.dim[1]:!1},GLayer.prototype.updateInsideList=function(){for(var a,b=this.plotPoints.length,c=0;b>c;c++)a=this.plotPoints[c],this.inside[c]=a.isValid()?a.getX()>=0&&a.getX()<=this.dim[0]&&-a.getY()>=0&&-a.getY()<=this.dim[1]:!1;this.inside.length>b&&this.inside.splice(b,Number.MAX_VALUE)},GLayer.prototype.getPointIndexAtPlotPos=function(a,b){var c;if(this.isInside(a,b))for(var d,e,f=25,g=this.plotPoints.length,h=0;g>h;h++)this.inside[h]&&(d=this.plotPoints[h],e=Math.pow(d.getX()-a,2)+Math.pow(d.getY()-b,2),f>e&&(f=e,c=h));return c},GLayer.prototype.getPointAtPlotPos=function(a,b){return this.points[this.getPointIndexAtPlotPos(a,b)]},GLayer.prototype.obtainBoxIntersections=function(a,b){var c=0;if(a.isValid()&&b.isValid()){var d=a.getX(),e=a.getY(),f=b.getX(),g=b.getY(),h=this.isInside(d,e),i=this.isInside(f,g),j=h&&i||0>d&&0>f||d>this.dim[0]&&f>this.dim[0]||0>-e&&0>-g||-e>this.dim[1]&&-g>this.dim[1];if(!j){var k=f-d,l=g-e;if(0===k)c=2,this.cuts[0][0]=d,this.cuts[0][1]=0,this.cuts[1][0]=d,this.cuts[1][1]=-this.dim[1];else if(0===l)c=2,this.cuts[0][0]=0,this.cuts[0][1]=e,this.cuts[1][0]=this.dim[0],this.cuts[1][1]=e;else{var m=l/k,n=e-m*d;c=4,this.cuts[0][0]=-n/m,this.cuts[0][1]=0,this.cuts[1][0]=(-this.dim[1]-n)/m,this.cuts[1][1]=-this.dim[1],this.cuts[2][0]=0,this.cuts[2][1]=n,this.cuts[3][0]=this.dim[0],this.cuts[3][1]=n+m*this.dim[0]}if(c=this.getValidCuts(this.cuts,c,a,b),h||i){if(1!==c){var o=h?a:b;c>1&&(c=this.removeDuplicatedCuts(this.cuts,c,0),c>1&&(c=this.removePointFromCuts(this.cuts,c,o,0),c>1&&(c=this.removeDuplicatedCuts(this.cuts,c,.001),c>1&&(c=this.removePointFromCuts(this.cuts,c,o,.001))))),0===c&&(c=1,this.cuts[0][0]=o.getX(),this.cuts[1][0]=o.getY())}}else c>2&&(c=this.removeDuplicatedCuts(this.cuts,c,0),c>2&&(c=this.removeDuplicatedCuts(this.cuts,c,.001))),2===c&&(Math.pow(this.cuts[0][0]-d,2)+Math.pow(this.cuts[0][1]-e),2>Math.pow(this.cuts[1][0]-d,2)+Math.pow(this.cuts[1][1]-e,2)&&(this.cuts[2][0]=this.cuts[0][0],this.cuts[2][1]=this.cuts[0][1],this.cuts[0][0]=this.cuts[1][0],this.cuts[0][1]=this.cuts[1][1],this.cuts[1][0]=this.cuts[2][0],this.cuts[1][1]=this.cuts[2][1])),1===c&&(c=2,this.cuts[1][0]=this.cuts[0][0],this.cuts[1][1]=this.cuts[0][1]);(h||i)&&1!==c?console.log("There should be one cut!!!"):h||i||0===c||2===c||console.log("There should be either 0 or 2 cuts!!! "+c+" were found")}}return c},GLayer.prototype.getValidCuts=function(a,b,c,d){for(var e=c.getX(),f=c.getY(),g=d.getX(),h=d.getY(),i=Math.abs(g-e),j=Math.abs(h-f),k=0,l=0;b>l;l++)this.isInside(a[l][0],a[l][1])&&Math.abs(a[l][0]-e)<=i&&Math.abs(a[l][1]-f)<=j&&Math.abs(a[l][0]-g)<=i&&Math.abs(a[l][1]-h)<=j&&(a[k][0]=a[l][0],a[k][1]=a[l][1],k++);return k},GLayer.prototype.removeDuplicatedCuts=function(a,b,c){for(var d,e=0,f=0;b>f;f++){d=!1;for(var g=0;e>g;g++)if(Math.abs(a[g][0]-a[f][0])<=c&&Math.abs(a[g][1]-a[f][1])<=c){d=!0;break}d||(a[e][0]=a[f][0],a[e][1]=a[f][1],e++)}return e},GLayer.prototype.removePointFromCuts=function(a,b,c,d){for(var e=c.getX(),f=c.getY(),g=0,h=0;b>h;h++)(Math.abs(a[h][0]-e)>d||Math.abs(a[h][1]-f)>d)&&(a[g][0]=a[h][0],a[g][1]=a[h][1],g++);return g},GLayer.prototype.startHistogram=function(a){this.hist=new GHistogram(this.parent,a,this.dim,this.plotPoints)},GLayer.prototype.drawPoints=function(){var a,b;if(0===arguments.length){a=this.plotPoints.length;var c=this.pointColors.length,d=this.pointSizes.length;if(this.parent.push(),this.parent.ellipseMode(this.parent.CENTER),this.parent.noStroke(),1===c&&1===d)for(this.parent.fill(this.pointColors[0]),b=0;a>b;b++)this.inside[b]&&this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[0],this.pointSizes[0]);else if(1===c)for(this.parent.fill(this.pointColors[0]),b=0;a>b;b++)this.inside[b]&&this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[b%d],this.pointSizes[b%d]);else if(1===d)for(b=0;a>b;b++)this.inside[b]&&(this.parent.fill(this.pointColors[b%c]),this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[0],this.pointSizes[0]));else for(b=0;a>b;b++)this.inside[b]&&(this.parent.fill(this.pointColors[b%c]),this.parent.ellipse(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.pointSizes[b%d],this.pointSizes[b%d]));this.parent.pop()}else{if(!(1===arguments.length&&arguments[0]instanceof p5.Image))throw new Error("GLayer.drawPoints(): signature not supported");for(a=this.plotPoints.length,this.parent.push(),this.parent.imageMode(this.parent.CENTER),b=0;a>b;b++)this.inside[b]&&this.parent.image(arguments[0],this.plotPoints[b].getX(),this.plotPoints[b].getY());this.parent.pop()}},GLayer.prototype.drawPoint=function(){var a,b,c,d;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length&&arguments[1]instanceof p5.Image)a=arguments[0],d=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.drawPoint(): signature not supported");a=arguments[0],b=this.pointColors[0],c=this.pointSizes[0]}var e=this.valueToXPlot(a.getX()),f=this.valueToYPlot(a.getY());this.isInside(e,f)&&(this.parent.push(),"undefined"!=typeof d?(this.parent.imageMode(this.parent.CENTER),this.parent.image(d,e,f)):(this.parent.ellipseMode(this.parent.CENTER),this.parent.fill(b),this.parent.noStroke(),this.parent.ellipse(e,f,c,c)),this.parent.pop())},GLayer.prototype.drawLines=function(){var a=this.plotPoints.length;this.parent.push(),this.parent.noFill(),this.parent.stroke(this.lineColor),this.parent.strokeWeight(this.lineWidth),this.parent.strokeCap(this.parent.SQUARE);for(var b=0;a-1>b;b++)if(this.inside[b]&&this.inside[b+1])this.parent.line(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.plotPoints[b+1].getX(),this.plotPoints[b+1].getY());else if(this.plotPoints[b].isValid()&&this.plotPoints[b+1].isValid()){var c=this.obtainBoxIntersections(this.plotPoints[b],this.plotPoints[b+1]);this.inside[b]?this.parent.line(this.plotPoints[b].getX(),this.plotPoints[b].getY(),this.cuts[0][0],this.cuts[0][1]):this.inside[b+1]?this.parent.line(this.cuts[0][0],this.cuts[0][1],this.plotPoints[b+1].getX(),this.plotPoints[b+1].getY()):c>=2&&this.parent.line(this.cuts[0][0],this.cuts[0][1],this.cuts[1][0],this.cuts[1][1])}this.parent.pop()},GLayer.prototype.drawLine=function(){var a,b,c,d,e,f;if(4===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(4===arguments.length)e=arguments[0],f=arguments[1],c=arguments[2],d=arguments[3];else if(2===arguments.length&&arguments[0]instanceof GPoint)a=arguments[0],b=arguments[1],c=this.lineColor,d=this.lineWidth;else{if(2!==arguments.length)throw new Error("GLayer.drawLine(): signature not supported");e=arguments[0],f=arguments[1],c=this.lineColor,d=this.lineWidth}"undefined"!=typeof e&&(this.xLog&&this.yLog?(a=new GPoint(this.xLim[0],Math.pow(10,e*Math.log(this.xLim[0])/Math.LN10+yCut)),b=new GPoint(this.xLim[1],Math.pow(10,e*Math.log(this.xLim[1])/Math.LN10+yCut))):this.xLog?(a=new GPoint(this.xLim[0],e*Math.log(this.xLim[0])/Math.LN10+yCut),b=new GPoint(this.xLim[1],e*Math.log(this.xLim[1])/Math.LN10+yCut)):this.yLog?(a=new GPoint(this.xLim[0],Math.pow(10,e*this.xLim[0]+yCut)),b=new GPoint(this.xLim[1],Math.pow(10,e*this.xLim[1]+yCut))):(a=new GPoint(this.xLim[0],e*this.xLim[0]+yCut),b=new GPoint(this.xLim[1],e*this.xLim[1]+yCut)));var g=this.valueToPlot(a),h=this.valueToPlot(b);if(g.isValid()&&h.isValid()){var i=this.isInside(g),j=this.isInside(h);if(this.parent.push(),this.parent.noFill(),this.parent.stroke(c),this.parent.strokeWeight(d),this.parent.strokeCap(this.parent.SQUARE),i&&j)this.parent.line(g.getX(),g.getY(),h.getX(),h.getY());else{var k=this.obtainBoxIntersections(g,h);i?this.parent.line(g.getX(),g.getY(),this.cuts[0][0],this.cuts[0][1]):j?this.parent.line(this.cuts[0][0],this.cuts[0][1],h.getX(),h.getY()):k>=2&&this.parent.line(this.cuts[0][0],this.cuts[0][1],this.cuts[1][0],this.cuts[1][1])}this.parent.pop()}},GLayer.prototype.drawHorizontalLine=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else{if(1!==arguments.length)throw new Error("GLayer.drawHorizontalLine(): signature not supported");a=arguments[0],b=this.lineColor,c=this.lineWidth}var d=this.valueToYPlot(a);this.isValidNumber(d)&&-d>=0&&-d<=this.dim[1]&&(this.parent.push(),this.parent.noFill(),this.parent.stroke(b),this.parent.strokeWeight(c),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(0,d,this.dim[0],d),this.parent.pop())},GLayer.prototype.drawVerticalLine=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else{if(1!==arguments.length)throw new Error("GLayer.drawVerticalLine(): signature not supported");a=arguments[0],b=this.lineColor,c=this.lineWidth}var d=this.valueToXPlot(a);this.isValidNumber(d)&&d>=0&&d<=this.dim[0]&&(this.parent.push(),this.parent.noFill(),this.parent.stroke(b),this.parent.strokeWeight(c),this.parent.strokeCap(this.parent.SQUARE),this.parent.line(d,0,d,-this.dim[1]),this.parent.pop())},GLayer.prototype.drawFilledContour=function(a,b){var c;if(a===GPlot.HORIZONTAL?c=this.getHorizontalShape(b):a===GPlot.VERTICAL&&(c=this.getVerticalShape(b)),"undefined"!=typeof c&&c.length>0){this.parent.push(),this.parent.fill(this.lineColor),this.parent.noStroke(),this.parent.beginShape();for(var d=0;di;i++)if(b=this.plotPoints[i],b.isValid()){for(c=!1,this.inside[i]?(f.push(new GPoint(b.getX(),b.getY(),"normal point")),c=!0):b.getX()>=0&&b.getX()<=this.dim[0]&&(-b.getY()<0?(f.push(new GPoint(b.getX(),0,"projection")),c=!0):(f.push(new GPoint(b.getX(),-this.dim[1],"projection")),c=!0)),d=i+1;e-1>d&&!this.plotPoints[d].isValid();)d++;if(e>d&&this.plotPoints[d].isValid())for(var j=this.obtainBoxIntersections(b,this.plotPoints[d]),k=0;j>k;k++)f.push(new GPoint(this.cuts[k][0],this.cuts[k][1],"cut")),c=!0;c&&(0>g&&(g=i),h=i)}if(f.length>0){var l=new GPoint(f[0]);if(0!==l.getX()&&l.getX()!==this.dim[0])if("cut"===l.getLabel())this.plotPoints[g].getX()<0?(l.setX(0),l.setLabel("extreme")):(l.setX(this.dim[0]),l.setLabel("extreme"));else if(0!==g){for(var m=g-1;m>0&&!this.plotPoints[m].isValid();)m--;this.plotPoints[m].isValid()&&(this.plotPoints[m].getX()<0?(l.setX(0),l.setLabel("extreme")):(l.setX(this.dim[0]),l.setLabel("extreme")))}var n=new GPoint(f[f.length-1]);if(0!==n.getX()&&n.getX()!==this.dim[0]&&h!==e-1){for(d=h+1;e-1>d&&!this.plotPoints[d].isValid();)d++;this.plotPoints[d].isValid()&&(this.plotPoints[d].getX()<0?(n.setX(0),n.setLabel("extreme")):(n.setX(this.dim[0]),n.setLabel("extreme")))}"extreme"===n.getLabel()&&f.push(n),this.yLog&&0>=a&&(a=Math.min(this.yLim[0],this.yLim[1]));var o=this.valueToPlot(1,a);-o[1]<0?(f.push(new GPoint(n.getX(),0)),f.push(new GPoint(l.getX(),0))):-o[1]>this.dim[1]?(f.push(new GPoint(n.getX(),-this.dim[1])),f.push(new GPoint(l.getX(),-this.dim[1]))):(f.push(new GPoint(n.getX(),o[1])),f.push(new GPoint(l.getX(),o[1]))),"extreme"===l.getLabel()&&f.push(l)}return f},GLayer.prototype.getVerticalShape=function(a){for(var b,c,d,e=this.plotPoints.length,f=[],g=-1,h=-1,i=0;e>i;i++)if(b=this.plotPoints[i],b.isValid()){for(c=!1,this.inside[i]?(f.push(new GPoint(b.getX(),b.getY(),"normal point")),c=!0):-b.getY()>=0&&-b.getY()<=this.dim[1]&&(b.getX()<0?(f.push(new GPoint(0,b.getY(),"projection")),c=!0):(f.push(new GPoint(this.dim[0],b.getY(),"projection")),c=!0)),d=i+1;e-1>d&&!this.plotPoints[d].isValid();)d++;if(e>d&&this.plotPoints[d].isValid())for(var j=this.obtainBoxIntersections(b,this.plotPoints[d]),k=0;j>k;k++)f.push(new GPoint(this.cuts[k][0],this.cuts[k][1],"cut")),c=!0;c&&(0>g&&(g=i),h=i)}if(f.length>0){var l=new GPoint(f[0]);if(0!==l.getY()&&l.getY()!==-this.dim[1])if("cut"===l.getLabel())-this.plotPoints[g].getY()<0?(l.setY(0),l.setLabel("extreme")):(l.setY(-this.dim[1]),l.setLabel("extreme"));else if(0!==g){for(var m=g-1;m>0&&!this.plotPoints[m].isValid();)m--;this.plotPoints[m].isValid()&&(-this.plotPoints[m].getY()<0?(l.setY(0),l.setLabel("extreme")):(l.setY(-this.dim[1]),l.setLabel("extreme")))}var n=new GPoint(f[f.length-1]);if(0!==n.getY()&&n.getY()!==-this.dim[1]&&h!==e-1){for(d=h+1;e-1>d&&!this.plotPoints[d].isValid();)d++;this.plotPoints[d].isValid()&&(-this.plotPoints[d].getY()<0?(n.setY(0),n.setLabel("extreme")):(n.setY(-this.dim[1]),n.setLabel("extreme")))}"extreme"===n.getLabel()&&f.push(n),this.xLog&&0>=a&&(a=Math.min(this.xLim[0],this.xLim[1]));var o=this.valueToPlot(a,1);o[0]<0?(f.push(new GPoint(0,n.getY())),f.push(new GPoint(0,l.getY()))):o[0]>this.dim[0]?(f.push(new GPoint(this.dim[0],n.getY())),f.push(new GPoint(this.dim[0],l.getY()))):(f.push(new GPoint(o[0],n.getY())),f.push(new GPoint(o[0],l.getY()))),"extreme"===l.getLabel()&&f.push(l)}return f},GLayer.prototype.drawLabel=function(a){var b=this.valueToXPlot(a.getX()),c=this.valueToYPlot(a.getY());if(this.isValidNumber(b)&&this.isValidNumber(c)){var d=b+this.labelSeparation[0],e=c-this.labelSeparation[1],f=this.fontSize/4;this.parent.push(),this.parent.rectMode(this.parent.CORNER),this.parent.noStroke(),this.parent.textFont(this.fontName),this.parent.textSize(this.fontSize),this.parent.textAlign(this.parent.LEFT,this.parent.BOTTOM),this.parent.fill(this.labelBgColor),this.parent.rect(d-f,e-this.fontSize-f,this.parent.textWidth(a.getLabel())+2*f,this.fontSize+2*f),this.parent.fill(this.fontColor),this.parent.text(a.getLabel(),d,e),this.parent.pop()}},GLayer.prototype.drawLabelAtPlotPos=function(a,b){var c=this.getPointAtPlotPos(a,b);"undefined"!=typeof c&&this.drawLabel(c)},GLayer.prototype.drawHistogram=function(){"undefined"!=typeof this.hist&&this.hist.draw(this.valueToPlot(this.histBasePoint))},GLayer.prototype.drawPolygon=function(a,b){var c;if(a.length>2){var d=this.valueToPlot(a),e=0;for(c=0;cc;c++){f=d[c],this.isInside(f)&&h.push(new GPoint(f.getX(),f.getY(),"normal point"));var i=g>c+1?c+1:0,j=this.obtainBoxIntersections(f,d[i]);1===j?h.push(new GPoint(this.cuts[0][0],this.cuts[0][1],"single cut")):j>1&&(h.push(new GPoint(this.cuts[0][0],this.cuts[0][1],"double cut")),h.push(new GPoint(this.cuts[1][0],this.cuts[1][1],"double cut")))}g=h.length;var k=[];for(c=0;g>c;c++){k.push(h[c]);var l=g>c+1?c+1:0,m=h[c].getLabel(),n=h[l].getLabel(),o="single cut"===m&&"single cut"===n||"single cut"===m&&"double cut"===n||"double cut"===m&&"single cut"===n;if(o){var p=h[c].getX(),q=h[c].getY(),r=h[l].getX(),s=h[l].getY(),t=Math.abs(r-p),u=Math.abs(s-q);if(t>0&&u>0&&t!==this.dim[0]&&u!==this.dim[1]){var v=0===p||p===this.dim[0]?p:r,w=0===q||q===-this.dim[1]?q:s;k.push(new GPoint(v,w,"special cut"))}}}if(k.length>2){for(this.parent.push(),this.parent.fill(b),this.parent.noStroke(),this.parent.beginShape(),c=0;c0&&b>0&&(this.dim[0]=a,this.dim[1]=b,this.updatePlotPoints(),"undefined"!=typeof this.hist&&(this.hist.setDim(this.dim),this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setXLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.setXLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&this.isValidNumber(a)&&this.isValidNumber(b)&&(this.xLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setYLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GLayer.setYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&this.isValidNumber(a)&&this.isValidNumber(b)&&(this.yLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=a,this.yLim[1]=b,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)))},GLayer.prototype.setXYLim=function(){var a,b,c,d;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else{if(2!==arguments.length)throw new Error("GLayer.setXYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1]}a!==b&&c!==d&&this.isValidNumber(a)&&this.isValidNumber(b)&&this.isValidNumber(c)&&this.isValidNumber(d)&&(this.xLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b),this.yLog&&(0>=c||0>=d)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=c,this.yLim[1]=d),this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setLimAndLog=function(){var a,b,c,d,e,f;if(6===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3],e=arguments[4],f=arguments[5];else{if(4!==arguments.length)throw new Error("GLayer.setLimAndLog(): signature not supported");a=arguments[0][0],b=arguments[0][1],c=arguments[1][0],d=arguments[1][1],e=arguments[2],f=arguments[3]}a!==b&&c!==d&&this.isValidNumber(a)&&this.isValidNumber(b)&&this.isValidNumber(c)&&this.isValidNumber(d)&&(e&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.yLim[1]=b,this.xLog=e),f&&(0>=c||0>=d)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=c,this.yLim[1]=d,this.yLog=f),this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setXLog=function(a){a!==this.xLog&&(a&&(this.xLim[0]<=0||this.xLim[1]<=0)&&(console.log("One of the limits is negative. This is not allowed in logarithmic scale."),console.log("Will set horizontal limits to (0.1, 10)"),this.xLim[0]=.1,this.xLim[1]=10),this.xLog=a,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setYLog=function(a){a!==this.yLog&&(a&&(this.yLim[0]<=0||this.yLim[1]<=0)&&(console.log("One of the limits is negative. This is not allowed in logarithmic scale."),console.log("Will set horizontal limits to (0.1, 10)"),this.yLim[0]=.1,this.yLim[1]=10),this.yLog=a,this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.setPoints=function(a){var b,c=a.length;if(this.points.length>c)this.points.splice(c,Number.MAX_VALUE);else for(b=this.points.length;c>b;b++)this.points[b]=new GPoint;for(b=0;c>b;b++)this.points[b].set(a[b]);this.updatePlotPoints(),this.updateInsideList(),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)},GLayer.prototype.setPoint=function(){var a,b,c,d,e=this.points.length;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=aa)this.points[a].set(b,c,d),this.plotPoints[a].set(this.valueToXPlot(b),this.valueToYPlot(c),d),this.inside[a]=this.isInside(this.plotPoints[a]);else{if(a!==e)throw new Error("GLayer.setPoint(): the index position is outside the array size");this.points[a]=new GPoint(b,c,d),this.plotPoints[a]=new GPoint(this.valueToXPlot(b),this.valueToYPlot(c),d),this.inside[a]=this.isInside(this.plotPoints[a])}"undefined"!=typeof this.hist&&this.hist.setPlotPoint(a,this.plotPoints[a])},GLayer.prototype.addPoint=function(){var a,b,c;if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2];else if(2===arguments.length)a=arguments[0],b=arguments[1],c="";else{if(1!==arguments.length)throw new Error("GLayer.addPoint(): signature not supported");a=arguments[0].getX(),b=arguments[0].getY(),c=arguments[0].getLabel()}this.points.push(new GPoint(a,b,c)),this.plotPoints.push(new GPoint(this.valueToXPlot(a),this.valueToYPlot(b),c)),this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length-1])),"undefined"!=typeof this.hist&&this.hist.addPlotPoint(this.plotPoints[this.plotPoints.length-1])},GLayer.prototype.addPoints=function(a){for(var b,c=a.length,d=0;c>d;d++)b=a[d],this.points.push(new GPoint(b)),this.plotPoints.push(new GPoint(this.valueToXPlot(b.getX()),this.valueToYPlot(b.getY()),b.getLabel())),this.inside.push(this.isInside(this.plotPoints[this.plotPoints.length-1]));"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints)},GLayer.prototype.addPointAtIndexPos=function(){var a,b,c,d;if(4===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d=arguments[3];else if(3===arguments.length)a=arguments[0],b=arguments[1],c=arguments[2],d="";else{if(2!==arguments.length)throw new Error("GLayer.addPointAtIndexPos(): signature not supported");a=arguments[0],b=arguments[1].getX(),c=arguments[1].getY(),d=arguments[1].getLabel()}a<=this.points.length&&(this.points.splice(a,0,new GPoint(b,c,d)),this.plotPoints.splice(a,0,new GPoint(this.valueToXPlot(b),this.valueToYPlot(c),d)),this.inside.splice(a,0,this.isInside(this.plotPoints[0])),"undefined"!=typeof this.hist&&this.hist.setPlotPoints(this.plotPoints))},GLayer.prototype.removePoint=function(a){a0&&(this.pointColors=a.slice())},GLayer.prototype.setPointColor=function(a){this.pointColors=[a]},GLayer.prototype.setPointSizes=function(a){a.length>0&&(this.pointSizes=a.slice())},GLayer.prototype.setPointSize=function(a){this.pointSizes=[a]},GLayer.prototype.setLineColor=function(a){this.lineColor=a},GLayer.prototype.setLineWidth=function(a){a>0&&(this.lineWidth=a)},GLayer.prototype.setHistBasePoint=function(a){this.histBasePoint.set(a)},GLayer.prototype.setHistType=function(a){"undefined"!=typeof this.hist&&this.hist.setType(a)},GLayer.prototype.setHistVisible=function(a){"undefined"!=typeof this.hist&&this.hist.setVisible(a)},GLayer.prototype.setDrawHistLabels=function(a){"undefined"!=typeof this.hist&&this.hist.setDrawLabels(a)},GLayer.prototype.setLabelBgColor=function(a){this.labelBgColor=a},GLayer.prototype.setLabelSeparation=function(a){this.labelSeparation[0]=a[0],this.labelSeparation[1]=a[1]},GLayer.prototype.setFontName=function(a){this.fontName=a},GLayer.prototype.setFontColor=function(a){this.fontColor=a},GLayer.prototype.setFontSize=function(a){a>0&&(this.fontSize=a)},GLayer.prototype.setFontProperties=function(a,b,c){c>0&&(this.fontName=a,this.fontColor=b,this.fontSize=c)},GLayer.prototype.setAllFontProperties=function(a,b,c){this.setFontProperties(a,b,c),"undefined"!=typeof this.hist&&this.hist.setFontProperties(a,b,c)},GLayer.prototype.getId=function(){return this.id},GLayer.prototype.getDim=function(){return this.dim.slice()},GLayer.prototype.getXLim=function(){return this.xLim.slice()},GLayer.prototype.getYLim=function(){return this.yLim.slice()},GLayer.prototype.getXLog=function(){return this.xLog},GLayer.prototype.getYLog=function(){return this.yLog},GLayer.prototype.getPoints=function(){for(var a=[],b=0;b=this.pos[0]&&a<=this.pos[0]+this.outerDim[0]&&b>=this.pos[1]&&b<=this.pos[1]+this.outerDim[1]},GPlot.prototype.isOverBox=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(0!==arguments.length)throw new Error("GPlot.isOverBox(): signature not supported");a=this.parent.mouseX,b=this.parent.mouseY}return a>=this.pos[0]+this.mar[1]&&a<=this.pos[0]+this.outerDim[0]-this.mar[3]&&b>=this.pos[1]+this.mar[2]&&b<=this.pos[1]+this.outerDim[1]-this.mar[0]},GPlot.prototype.updateLimits=function(){this.fixedXLim||(this.xLim=this.calculatePlotXLim(),this.xAxis.setLim(this.xLim),this.topAxis.setLim(this.xLim)),this.fixedYLim||(this.yLim=this.calculatePlotYLim(),this.yAxis.setLim(this.yLim),this.rightAxis.setLim(this.yLim)),this.mainLayer.setXYLim(this.xLim,this.yLim);for(var a=0;a=this.yLim[0]&&e>=this.yLim[0]&&e<=this.yLim[1]||this.yLim[1]=this.yLim[1]),!f||this.xLog&&0>=d||(db[1]&&(b[1]=d))}return b[1]=this.xLim[0]&&d>=this.xLim[0]&&d<=this.xLim[1]||this.xLim[1]=this.xLim[1]),!f||this.yLog&&0>=e||(eb[1]&&(b[1]=e))}return b[1]=0&&c[b]<=this.dim[0]&&this.parent.line(c[b],0,c[b],-this.dim[1])}if(a===GPlot.BOTH||a===GPlot.HORIZONTAL){var d=this.yAxis.getPlotTicksRef();for(b=0;b=0&&-d[b]<=this.dim[1]&&this.parent.line(0,d[b],this.dim[0],d[b])}this.parent.pop()},GPlot.prototype.drawHistograms=function(){this.mainLayer.drawHistogram();for(var a=0;a0&&b>0){var c=a-this.mar[1]-this.mar[3],d=b-this.mar[0]-this.mar[2];if(c>0&&d>0){this.outerDim[0]=a,this.outerDim[1]=b,this.dim[0]=c,this.dim[1]=d,this.xAxis.setDim(this.dim),this.topAxis.setDim(this.dim),this.yAxis.setDim(this.dim),this.rightAxis.setDim(this.dim),this.title.setDim(this.dim),this.mainLayer.setDim(this.dim);for(var e=0;e0&&f>0&&(this.mar[0]=a,this.mar[1]=b,this.mar[2]=c,this.mar[3]=d,this.outerDim[0]=e,this.outerDim[1]=f)},GPlot.prototype.setDim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GPlot.setDim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}if(a>0&&b>0){var c=a+this.mar[1]+this.mar[3],d=b+this.mar[0]+this.mar[2];if(c>0&&d>0){this.outerDim[0]=c,this.outerDim[1]=d,this.dim[0]=a,this.dim[1]=b,this.xAxis.setDim(this.dim),this.topAxis.setDim(this.dim),this.yAxis.setDim(this.dim),this.rightAxis.setDim(this.dim),this.title.setDim(this.dim),this.mainLayer.setDim(this.dim);for(var e=0;e=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.xLim[0]=a,this.xLim[1]=b,this.invertedXScale=this.xLim[0]>this.xLim[1],this.fixedXLim=!0,this.xAxis.setLim(this.xLim),this.topAxis.setLim(this.xLim),this.updateLimits()))},GPlot.prototype.setYLim=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else{if(1!==arguments.length)throw new Error("GPlot.setYLim(): signature not supported");a=arguments[0][0],b=arguments[0][1]}a!==b&&(this.yLog&&(0>=a||0>=b)?console.log("One of the limits is negative. This is not allowed in logarithmic scale."):(this.yLim[0]=a,this.yLim[1]=b,this.invertedYScale=this.yLim[0]>this.yLim[1],this.fixedYLim=!0,this.yAxis.setLim(this.yLim),this.rightAxis.setLim(this.yLim),this.updateLimits()))},GPlot.prototype.setFixedXLim=function(a){this.fixedXLim=a,this.updateLimits()},GPlot.prototype.setFixedYLim=function(a){this.fixedYLim=a,this.updateLimits()},GPlot.prototype.setLogScale=function(a){var b=this.xLog,c=this.yLog;if("xy"===a||"yx"===a?(b=!0,c=!0):"x"===a?(b=!0,c=!1):"y"===a?(b=!1,c=!0):""===a&&(b=!1,c=!1),b!==this.xLog||c!==this.yLog){this.xLog=b,this.yLog=c,this.xLog&&this.fixedXLim&&(this.xLim[0]<=0||this.xLim[1]<=0)&&(this.fixedXLim=!1),this.yLog&&this.fixedYLim&&(this.yLim[0]<=0||this.yLim[1]<=0)&&(this.fixedYLim=!1),this.fixedXLim||(this.xLim=this.calculatePlotXLim()),this.fixedYLim||(this.yLim=this.calculatePlotYLim()),this.xAxis.setLimAndLog(this.xLim,this.xLog),this.topAxis.setLimAndLog(this.xLim,this.xLog),this.yAxis.setLimAndLog(this.yLim,this.yLog),this.rightAxis.setLimAndLog(this.yLim,this.yLog),this.mainLayer.setLimAndLog(this.xLim,this.yLim,this.xLog,this.yLog);for(var d=0;d=0&&a!==this.expandLimFactor&&(this.expandLimFactor=a,this.updateLimits())},GPlot.prototype.setBgColor=function(a){this.bgColor=a},GPlot.prototype.setBoxBgColor=function(a){this.boxBgColor=a},GPlot.prototype.setBoxLineColor=function(a){this.boxLineColor=a},GPlot.prototype.setBoxLineWidth=function(a){a>0&&(this.boxLineWidth=a)},GPlot.prototype.setGridLineColor=function(a){this.gridLineColor=a},GPlot.prototype.setGridLineWidth=function(a){a>0&&(this.gridLineWidth=a)},GPlot.prototype.setPoints=function(){if(2===arguments.length)this.getLayer(arguments[1]).setPoints(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.setPoints(): signature not supported");this.mainLayer.setPoints(arguments[0])}this.updateLimits()},GPlot.prototype.setPoint=function(){if(5===arguments.length)this.getLayer(arguments[4]).setPoint(arguments[0],arguments[1],arguments[2],arguments[3]);else if(4===arguments.length)this.mainLayer.setPoint(arguments[0],arguments[1],arguments[2],arguments[3]);else if(3===arguments.length&&arguments[1]instanceof GPoint)this.getLayer(arguments[2]).setPoint(arguments[0],arguments[1]);else if(3===arguments.length)this.mainLayer.setPoint(arguments[0],arguments[1],arguments[2]);else{if(2!==arguments.length)throw new Error("GPlot.setPoint(): signature not supported");this.mainLayer.setPoint(arguments[0],arguments[1])}this.updateLimits()},GPlot.prototype.addPoint=function(){if(4===arguments.length)this.getLayer(arguments[3]).addPoint(arguments[0],arguments[1],arguments[2]);else if(3===arguments.length)this.mainLayer.addPoint(arguments[0],arguments[1],arguments[2]);else if(2===arguments.length&&arguments[0]instanceof GPoint)this.getLayer(arguments[1]).addPoint(arguments[0]);else if(2===arguments.length)this.mainLayer.addPoint(arguments[0],arguments[1]);else{if(1!==arguments.length)throw new Error("GPlot.addPoint(): signature not supported");this.mainLayer.addPoint(arguments[0])}this.updateLimits()},GPlot.prototype.addPoints=function(){if(2===arguments.length)this.getLayer(arguments[1]).addPoints(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.addPoints(): signature not supported");this.mainLayer.addPoints(arguments[0])}this.updateLimits()},GPlot.prototype.removePoint=function(){if(2===arguments.length)this.getLayer(arguments[1]).removePoint(arguments[0]);else{if(1!==arguments.length)throw new Error("GPlot.removePoint(): signature not supported");this.mainLayer.removePoint(arguments[0])}this.updateLimits()},GPlot.prototype.addPointAtIndexPos=function(){if(5===arguments.length)this.getLayer(arguments[4]).addPointAtIndexPos(arguments[0],arguments[1],arguments[2],arguments[3]);else if(4===arguments.length)this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1],arguments[2],arguments[3]);else if(3===arguments.length&&arguments[1]instanceof GPoint)this.getLayer(arguments[2]).addPointAtIndexPos(arguments[0],arguments[1]);else if(3===arguments.length)this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1],arguments[2]);else{if(2!==arguments.length)throw new Error("GPlot.addPointAtIndexPos(): signature not supported");this.mainLayer.addPointAtIndexPos(arguments[0],arguments[1])}this.updateLimits()},GPlot.prototype.setPointColors=function(a){this.mainLayer.setPointColors(a)},GPlot.prototype.setPointColor=function(a){this.mainLayer.setPointColor(a)},GPlot.prototype.setPointSizes=function(a){this.mainLayer.setPointSizes(a)},GPlot.prototype.setPointSize=function(a){this.mainLayer.setPointSize(a)},GPlot.prototype.setLineColor=function(a){this.mainLayer.setLineColor(a)},GPlot.prototype.setLineWidth=function(a){this.mainLayer.setLineWidth(a)},GPlot.prototype.setHistBasePoint=function(a){this.mainLayer.setHistBasePoint(a)},GPlot.prototype.setHistType=function(a){this.mainLayer.setHistType(a)},GPlot.prototype.setHistVisible=function(a){this.mainLayer.setHistVisible(a)},GPlot.prototype.setDrawHistLabels=function(a){this.mainLayer.setDrawHistLabels(a)},GPlot.prototype.setLabelBgColor=function(a){this.mainLayer.setLabelBgColor(a)},GPlot.prototype.setLabelSeparation=function(a){this.mainLayer.setLabelSeparation(a)},GPlot.prototype.setTitleText=function(a){this.title.setText(a)},GPlot.prototype.setAxesOffset=function(a){this.xAxis.setOffset(a),this.topAxis.setOffset(a),this.yAxis.setOffset(a),this.rightAxis.setOffset(a)},GPlot.prototype.setTicksLength=function(a){this.xAxis.setTickLength(a),this.topAxis.setTickLength(a),this.yAxis.setTickLength(a),this.rightAxis.setTickLength(a)},GPlot.prototype.setHorizontalAxesNTicks=function(a){this.xAxis.setNTicks(a),this.topAxis.setNTicks(a)},GPlot.prototype.setHorizontalAxesTicksSeparation=function(a){this.xAxis.setTicksSeparation(a),this.topAxis.setTicksSeparation(a)},GPlot.prototype.setHorizontalAxesTicks=function(a){this.xAxis.setTicks(a),this.topAxis.setTicks(a)},GPlot.prototype.setVerticalAxesNTicks=function(a){this.yAxis.setNTicks(a),this.rightAxis.setNTicks(a)},GPlot.prototype.setVerticalAxesTicksSeparation=function(a){this.yAxis.setTicksSeparation(a),this.rightAxis.setTicksSeparation(a)},GPlot.prototype.setVerticalAxesTicks=function(a){this.yAxis.setTicks(a),this.rightAxis.setTicks(a)},GPlot.prototype.setFontName=function(a){this.maniLayer.setFontName(a)},GPlot.prototype.setFontColor=function(a){this.maniLayer.setFontColor(a)},GPlot.prototype.setFontSize=function(a){this.maniLayer.setFontSize(a)},GPlot.prototype.setFontProperties=function(a,b,c){this.maniLayer.setFontProperties(a,b,c)},GPlot.prototype.setAllFontProperties=function(a,b,c){this.xAxis.setAllFontProperties(a,b,c),this.topAxis.setAllFontProperties(a,b,c),this.yAxis.setAllFontProperties(a,b,c),this.rightAxis.setAllFontProperties(a,b,c),this.title.setFontProperties(a,b,c),this.mainLayer.setAllFontProperties(a,b,c);for(var d=0;d0&&(this.zoomFactor=a),(b===this.parent.LEFT||b===this.parent.RIGHT||b===this.parent.CENTER)&&(this.increaseZoomButton=b),(c===this.parent.LEFT||c===this.parent.RIGHT||c===this.parent.CENTER)&&(this.decreaseZoomButton=c),(d===this.parent.SHIFT||d===this.parent.CONTROL||d===this.parent.ALT||d===GPlot.NONE)&&(this.increaseZoomKeyModifier=d),(e===this.parent.SHIFT||e===this.parent.CONTROL||e===this.parent.ALT||e===GPlot.NONE)&&(this.decreaseZoomKeyModifier=e)},GPlot.prototype.deactivateZooming=function(){this.zoomingIsActive=!1},GPlot.prototype.activateCentering=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activateCentering(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.centeringIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.centeringButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.centeringKeyModifier=b)},GPlot.prototype.deactivateCentering=function(){this.centeringIsActive=!1},GPlot.prototype.activatePanning=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activatePanning(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.panningIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.panningButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.panningKeyModifier=b)},GPlot.prototype.deactivatePanning=function(){this.panningIsActive=!1,this.panningReferencePoint=void 0},GPlot.prototype.activatePointLabels=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activatePointLabels(): signature not supported");a=this.parent.LEFT,b=GPlot.NONE}this.labelingIsActive=!0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.labelingButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.labelingKeyModifier=b)},GPlot.prototype.deactivatePointLabels=function(){this.labelingIsActive=!1,this.mousePos=void 0},GPlot.prototype.activateReset=function(){var a,b;if(2===arguments.length)a=arguments[0],b=arguments[1];else if(1===arguments.length)a=arguments[0],b=GPlot.NONE;else{if(0!==arguments.length)throw new Error("GPlot.activateReset(): signature not supported");a=this.parent.RIGHT,b=GPlot.NONE}this.resetIsActive=!0,this.xLimReset=void 0,this.yLimReset=void 0,(a===this.parent.LEFT||a===this.parent.RIGHT||a===this.parent.CENTER)&&(this.resetButton=a),(b===this.parent.SHIFT||b===this.parent.CONTROL||b===this.parent.ALT||b===GPlot.NONE)&&(this.resetKeyModifier=b)},GPlot.prototype.deactivateReset=function(){this.resetIsActive=!1,this.xLimReset=void 0,this.yLimReset=void 0},GPlot.prototype.getButton=function(a){var b;return 0===a.button?b=this.parent.LEFT:1===a.button?b=this.parent.CENTER:2===a.button?b=this.parent.RIGHT:"undefined"==typeof a.button&&(b=this.parent.LEFT),b},GPlot.prototype.getModifier=function(a){var b;return b=a.altKey?this.parent.ALT:a.ctrlKey?this.parent.CONTROL:a.shiftKey?this.parent.SHIFT:GPlot.NONE},GPlot.prototype.saveResetLimits=function(){("undefined"==typeof this.xLimReset||"undefined"==typeof this.yLimReset)&&(this.xLimReset=this.xLim.slice(),this.yLimReset=this.yLim.slice())},GPlot.prototype.panningFunction=function(){"undefined"!=typeof this.panningReferencePoint&&this.align(this.panningReferencePoint,this.parent.mouseX,this.parent.mouseY)},GPlot.prototype.clickEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=this.getButton(e),c=this.getModifier(e);this.zoomingIsActive&&(b===this.increaseZoomButton&&c===this.increaseZoomKeyModifier?(this.resetIsActive&&this.saveResetLimits(),this.zoom(this.zoomFactor,this.parent.mouseX,this.parent.mouseY)):b===this.decreaseZoomButton&&c===this.decreaseZoomKeyModifier&&(this.resetIsActive&&this.saveResetLimits(),this.zoom(1/this.zoomFactor,this.parent.mouseX,this.parent.mouseY))),this.centeringIsActive&&b===this.centeringButton&&c===this.centeringKeyModifier&&(this.resetIsActive&&this.saveResetLimits(), +this.center(this.parent.mouseX,this.parent.mouseY)),this.resetIsActive&&b===this.resetButton&&c===this.resetKeyModifier&&"undefined"!=typeof this.xLimReset&&"undefined"!=typeof this.yLimReset&&(this.setXLim(this.xLimReset),this.setYLim(this.yLimReset),this.xLimReset=void 0,this.yLimReset=void 0)}},GPlot.prototype.mouseDownEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=this.getButton(e),c=this.getModifier(e);this.panningIsActive&&b===this.panningButton&&c===this.panningKeyModifier&&(this.resetIsActive&&this.saveResetLimits(),this.panningReferencePoint=this.getValueAt(this.parent.mouseX,this.parent.mouseY),this.panningIntervalId=setInterval(this.panningFunction.bind(this),100)),this.labelingIsActive&&b===this.labelingButton&&c===this.labelingKeyModifier&&(this.mousePos=[this.parent.mouseX,this.parent.mouseY])}},GPlot.prototype.mouseUpEvent=function(a){e=a||window.event;{var b=this.getButton(e);this.getModifier(e)}this.panningIsActive&&b===this.panningButton&&"undefined"!=typeof this.panningIntervalId&&(clearInterval(this.panningIntervalId),this.panningIntervalId=void 0,this.panningReferencePoint=void 0),this.labelingIsActive&&b===this.labelingButton&&(this.mousePos=void 0),b===this.parent.RIGHT&&this.clickEvent(e)},GPlot.prototype.wheelEvent=function(a){if(e=a||window.event,this.isOverBox()){var b=e.deltaY,c=this.parent.CENTER,d=this.getModifier(e);this.zoomingIsActive&&(c===this.increaseZoomButton&&d===this.increaseZoomKeyModifier&&b>0?(this.resetIsActive&&this.saveResetLimits(),this.zoom(this.zoomFactor,this.parent.mouseX,this.parent.mouseY)):c===this.decreaseZoomButton&&d===this.decreaseZoomKeyModifier&&0>b&&(this.resetIsActive&&this.saveResetLimits(),this.zoom(1/this.zoomFactor,this.parent.mouseX,this.parent.mouseY)))}},GPlot.prototype.preventDefaultEvent=function(a){e=a||window.event,this.isOverBox()&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},GPlot.prototype.preventWheelDefault=function(){window.addEventListener("wheel",this.preventDefaultEvent.bind(this),!1)},GPlot.prototype.preventRightClickDefault=function(){window.addEventListener("contextmenu",this.preventDefaultEvent.bind(this),!1)}; diff --git a/graficos/hidraulicas.html b/graficos/hidraulicas.html new file mode 100755 index 0000000..be3038e --- /dev/null +++ b/graficos/hidraulicas.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/graficos/hidraulicas.js b/graficos/hidraulicas.js new file mode 100644 index 0000000..72fedda --- /dev/null +++ b/graficos/hidraulicas.js @@ -0,0 +1,112 @@ +var cuencas, cmap; +var nombres,colores,x,y; +var canales, acequias; +var totCanales = 0,totAcequias = 0; +var cuenta = 0, last; + +function setup() { + createCanvas(800,519); + cuencas = loadImage("data/cuencas.png"); + cmap = loadImage("data/cmap-cuencas.png"); + nombres = new Array("Norte","Duero","Ebro","Pirineo","Jucar","Tajo","Guadiana","Guadalquivir","Sur", "Segura", "Baleares y Canarias"); + colores = new Array("#f00","#0f0","#00f","#ff0","#0ff","#a00","#0a0","#00a","#aa0","#0aa", "#aaa"); + canales = new Array(157.3,1422.1,810, 132.5,525.7,764.9,360.5,1111.7,266.7,85.7,-1); + acequias= new Array(448.1,2215.3,1872.7,258.7,2378,1356.7,1210.5,1215.7,191.7,2004.1,-1); + x = new Array(158,243, 449, 597, 432, 308, 236, 263, 362,412, 601); + y = new Array(77,158,140, 139,278, 253, 327, 393, 441,368, 322); + + for (var n = 0; n < nombres.length; n++) { + if (canales[n] != -1) totCanales = totCanales + canales[n]; + if (acequias[n] != -1) totAcequias = totAcequias + acequias[n]; + } +} + +function draw() { + background(200,225,225); + image(cuencas,0,0); + + var mc = cmap.get(mouseX,mouseY); + var over = []; + for (var n = 0; n < colores.length; n++) { + over[n] = compara(mc,color(colores[n])); + } + + for (var n = 0; n < colores.length; n++) { + if (over[n]) { + fill(0); + textStyle(NORMAL); + if (canales[n] != -1) { + text("Canales: " + canales[n] + " Km", x[n], y[n]+5); + text("Acequias: " + acequias[n] + " Km", x[n], y[n]+20); + } + else { + textSize(10); + text("(Sin datos)", x[n], y[n]+5); + } + } + } + + // nombres + textStyle(BOLD); + textSize(14); + for (var n = 0; n < nombres.length; n++) { + var nbr = String.toUpperCase(nombres[n]); + fill(255); + noStroke(); + fill(0); + text(nbr, x[n], y[n]-10); + } + + cuenta = cuenta + 0.5; + + // Canales + for (var n = 0; n < nombres.length; n++) { + if (!over[n]) { + if (canales[n] == -1) { + textSize(10); + fill(0); + text("(Sin datos)", x[n], y[n]+5); + } + var pct = map(canales[n]/totCanales,0,1,0,50); + for (var i = 0; i < min(cuenta,pct); i++) { + var xi = x[n] + 10*i; + stroke(0); + line(xi+3, y[n]-4,xi+10+3,y[n]-4); + noStroke(); + fill(0); + quad(xi+10+4,y[n]-4,xi+10+4,y[n]-4+7, xi+10,y[n]+7, xi+10,y[n]); + fill(0,255,255); + quad(xi+3, y[n]-3,xi+10+3,y[n]-3,xi+10,y[n],xi, y[n]); + noStroke(); + fill(0); + rect(xi, y[n],10,7) + fill(255); + arc(xi+5,y[n]+7,7,8,PI,TWO_PI); + } + } + } + + // Acequias + for (var n = 0; n < nombres.length; n++) { + if (!over[n]) { + pct = map(acequias[n]/totAcequias,0,1,0,50); + for (var i = 0; i < min(cuenta,pct); i++) { + var xi = x[n] + 10*i; + stroke(0); + line(xi, y[n]+15,xi+10,y[n]+15); + line(xi+3, y[n]+15-3,xi+10+3,y[n]+15-3); + noStroke(); + fill(0); + quad(xi+10+4,y[n]+15-3, xi+10+4,y[n]+15+4-3-1, xi+10, y[n]+15+4, xi+10, y[n]+15); + fill(0,255,255); + quad(xi+3, y[n]+15-2,xi+10+3,y[n]+15-2, xi+10,y[n]+15,xi, y[n]+15); + fill(0); + rect(xi, y[n]+15, 10, 4); + } + } + } +} + +function compara(c1, c2) { + return red(c1) == red(c2) && green(c1) == green(c2) && blue(c1) == blue(c2); +} diff --git a/graficos/mecanizacion.html b/graficos/mecanizacion.html new file mode 100644 index 0000000..1d6e1ef --- /dev/null +++ b/graficos/mecanizacion.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/graficos/mecanizacion.js b/graficos/mecanizacion.js new file mode 100644 index 0000000..9cbe3ab --- /dev/null +++ b/graficos/mecanizacion.js @@ -0,0 +1,101 @@ +var cuencas, cmap; +var nombres,colores,x,y; +var tractores, cosechadoras; +var totTractores = 0,totCosechadoras = 0; +var cuenta = 0, last; +var imgTractor,imgCosechadora; + +function setup() { + createCanvas(800,519); + cuencas = loadImage("data/cuencas.png"); + cmap = loadImage("data/cmap-cuencas.png"); + imgTractor = loadImage("data/tractor_792349_cc_p.png"); + imgCosechadora = loadImage("data/harvester_1046427_cc_p.png"); + nombres = new Array("Norte","Duero","Ebro","Pirineo","Jucar","Tajo","Guadiana","Guadalquivir","Sur", "Segura", "Baleares y Canarias"); + colores = new Array("#f00","#0f0","#00f","#ff0","#0ff","#a00","#0a0","#00a","#aa0","#0aa", "#aaa"); + tractores = new Array(31.5,32.8,81.4,-1,128.5,37.6,59.1,30.6,11.2,34.6,-1); + cosechadoras= new Array(0,1.2,2.8,-1,5,0.6,0.9,2.6,0.2,0.5,-1); + + x = new Array(128,233, 409, 597, 392, 248, 206, 217, 362,402, 651); + y = new Array(77,128,110, 139,248, 243, 307, 390, 431,368, 322); + + for (var n = 0; n < nombres.length; n++) { + if (tractores[n] != -1) totTractores = totTractores + tractores[n]; + if (cosechadoras[n] != -1) totCosechadoras = totCosechadoras + cosechadoras[n]; + } +} + +function draw() { + background(200,225,225); + image(cuencas,0,0); + + + var mc = cmap.get(mouseX,mouseY); + var over = []; + for (var n = 0; n < colores.length; n++) { + over[n] = compara(mc,color(colores[n])); + } + + for (var n = 0; n < colores.length; n++) { + if (over[n]) { + fill(0); + textStyle(NORMAL); + if (tractores[n] != -1) { + text("Tractores: " + tractores[n], x[n], y[n]+10); + text("Cosechadoras: " + cosechadoras[n], x[n], y[n]+25); + } + else { + textSize(10); + text("(Sin datos)", x[n], y[n]+5); + } + } + } + + + cuenta = cuenta + 0.5; + + // Cosechadoras + var mpct = []; + for (var n = 0; n < nombres.length; n++) { + if (!over[n]) { + pct = map(cosechadoras[n]/totCosechadoras,0,1,0,40); + mpct[n] = floor(pct)+1; + for (var i = 0; i < min(cuenta,pct); i++) { + var xi = x[n] + 20*(i%4); + var yi = y[n] + floor(i/4)*20; + image(imgCosechadora,xi,yi,20,20); + } + } + } + + // Tractores + for (var n = 0; n < nombres.length; n++) { + if (!over[n]) { + if (tractores[n] == -1) { + textSize(10); + textStyle(NORMAL); + fill(0); + text("(Sin datos)", x[n], y[n]+5); + } + var pct = map(tractores[n]/totTractores,0,1,0,40); + for (var i = 0; i < min(cuenta,pct); i++) { + var xi = x[n] + 20*(i%4) + min(4,mpct[n])*20; + var yi = y[n] + floor(i/4)*20; + image(imgTractor,xi,yi,18,18); + } + } + } + + // nombres + textStyle(BOLD); + textSize(14); + for (var n = 0; n < nombres.length; n++) { + var nbr = nombres[n]; + fill(0); + text(nbr, x[n], y[n]-7); + } +} + +function compara(c1, c2) { + return red(c1) == red(c2) && green(c1) == green(c2) && blue(c1) == blue(c2); +} diff --git a/graficos/parcelas-old.js b/graficos/parcelas-old.js new file mode 100644 index 0000000..b368d77 --- /dev/null +++ b/graficos/parcelas-old.js @@ -0,0 +1,94 @@ +var cuencas, cmap; +var ids,nombres,colores,x,y; +var capas,imgs; +var dim; + +function preload() { + ids = new Array("norte","duero","ebro","pirineo","jucar","tajo","guadiana","guadalquivir","sur","segura","baleares"); + imgs = new Array(); + for (var n = 0; n < ids.length; n++) { + imgs[n] = loadImage("data/"+ids[n]+".png"); + } + cuencas = loadImage("data/cuencas.png"); + cmap = loadImage("data/cmap-cuencas.png"); +} + +function setup() { + createCanvas(800,519); + nombres = new Array("Norte","Duero","Ebro","Pirineo","Jucar","Tajo","Guadiana","Guadalquivir","Sur", "Segura", "Baleares y Canarias"); + colores = new Array("#f00","#0f0","#00f","#ff0","#0ff","#a00","#0a0","#00a","#aa0","#0aa", "#aaa"); + x = new Array(158,243, 449, 597, 432, 308, 236, 263, 362,432, 651); + y = new Array(77,158,140, 139,278, 253, 327, 393, 441,368, 322); + dim = new Array(11,8.4,11,-1,6,7.5,8.6,5.3,5.9,6.6,-1); + capas = new Array(); + for (var n = 0; n < ids.length; n++) { + capas[n] = createImage(width,height); + capas[n].loadPixels(); + + if (dim[n] != -1) { + var paso = map(dim[n],0, 15, 2, 20); + + colorMode(HSB,360,255,255); + var h = random(70,130); + var numi = floor(width/paso)+1; + var numj = floor(height/paso)+1; + var c = []; + for (var i = 0; i < numi; i++) { + c[i] = []; + for (var j = 0; j < numj; j++) { + var s = random(100,200); + c[i][j] = color(h, s, random(150,200) ); + } + } + colorMode(RGB,255,255,255); + for (var i = 0; i < width; i++) { + var pasoi = floor(i/paso); + for (var j = 0; j < height; j++) { + var pasoj = floor(j/paso); + capas[n].set(i,j,c[pasoi][pasoj]); + } + } + capas[n].updatePixels(); + capas[n].mask(imgs[n]); + } + } +} + +function draw() { + background(200,225,225); + + // capas + for (var n = 0; n < ids.length; n++) { + tint(200,180,130); + image(imgs[n],0,0); + tint(255,min(frameCount*40,255)); + if (dim[n] != -1) image(capas[n],0,0); + else text("(Sin datos)", x[n], y[n]+5); + } + + // Mas datos + var mc = cmap.get(mouseX,mouseY); + for (var n = 0; n < colores.length; n++) { + if (compara(mc,color(colores[n]))) { + noTint(); + image(imgs[n],0,0); + } + } + + + // nombres + textSize(14); + for (var n = 0; n < nombres.length; n++) { + var nbr = nombres[n]; + fill(255); + noStroke(); + fill(0); + text(nbr, x[n], y[n]-10); + } +} + + + +function compara(c1, c2) { + return red(c1) == red(c2) && green(c1) == green(c2) && blue(c1) == blue(c2); +} diff --git a/graficos/parcelas.html b/graficos/parcelas.html new file mode 100644 index 0000000..a3eb0a8 --- /dev/null +++ b/graficos/parcelas.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/graficos/parcelas.js b/graficos/parcelas.js new file mode 100644 index 0000000..7372bc4 --- /dev/null +++ b/graficos/parcelas.js @@ -0,0 +1,78 @@ +var cuencas, cmap; +var ids,nombres,colores,x,y; +var capas,capaspg,imgs; +var dim, dimr; + +function preload() { + ids = new Array("norte","duero","ebro","pirineo","jucar","tajo","guadiana","guadalquivir","sur","segura","baleares"); + dimr = new Array(11,8.4,11,-1,6,7.5,8.6,5.3,5.9,6.6,-1); + dim = new Array(12,10,14.2,8,7.6,8,7.6,10,4.7,10,11); + imgs = new Array(); + capas = new Array(); + capaspg = new Array(); + for (var n = 0; n < ids.length; n++) { + imgs[n] = loadImage("data/"+ids[n]+".png"); + capaspg[n] = loadImage("data/capa-PGC-"+n+".png"); + if (dim[n] != -1) { + capas[n] = loadImage("data/capa-"+n+".png"); + } + } + cuencas = loadImage("data/cuencas.png"); + cmap = loadImage("data/cmap-cuencas.png"); +} + +function setup() { + createCanvas(800,519); + nombres = new Array("Norte","Duero","Ebro","Pirineo","Jucar","Tajo","Guadiana","Guadalquivir","Sur", "Segura", "Baleares y Canarias"); + colores = new Array("#f00","#0f0","#00f","#ff0","#0ff","#a00","#0a0","#00a","#aa0","#0aa", "#aaa"); + x = new Array(158,243, 429, 597, 432, 268, 226, 253, 362,432, 611); + y = new Array(77,158,140, 139,278, 263, 327, 393, 441, 368, 322); +} + + +function draw() { + background(200,225,225); + + // capas + for (var n = 0; n < ids.length; n++) { + if (dimr[n] != -1) image(capas[n],0,0); + else { + image(imgs[n],0,0); + } + } + + // Parcelas segun PGC + var mc = cmap.get(mouseX,mouseY); + for (var n = 0; n < colores.length; n++) { + if (compara(mc,color(colores[n]))) { + tint(255,100); + image(capaspg[n],0,0); + noTint(); + } + } + + + // nombres + textSize(14); + for (var n = 0; n < nombres.length; n++) { + var nbr = String.toUpperCase(nombres[n]); + if (dimr[n] != -1 || !compara(mc,color(colores[n]))) fill(0); + else fill(0); + textStyle(BOLD); + text(nbr, x[n], y[n]-10); + textStyle(NORMAL); + if (compara(mc,color(colores[n]))) { + text("Plan inicial: " + dim[n]+" Has", x[n], y[n]+5); + } + else { + if (dimr[n] != -1) text("Parcela media: " + dimr[n]+" Has", x[n], y[n]+5); + else text("(Sin datos)", x[n], y[n]+5); + } + } +} + + + +function compara(c1, c2) { + return red(c1) == red(c2) && green(c1) == green(c2) && blue(c1) == blue(c2); +}