int gridsize = 30; int gridscale = 10; float ticksize = 10; PFont consolas; color backgroundcolor = #EEEEEE; color axiscolor = #CCCCCC; color fieldcolor = #888888; color solutioncolor = #555555; color textcolor = #000000; color textbgcolor = 0xCCFFFFFF; boolean solution = true; boolean arrows = true; // differential equation float slope(float x, float y) { return y*y - y + x*y; } void setup() { consolas = loadFont("Consolas-10.vlw"); textFont(consolas); textAlign(LEFT, BOTTOM); //frame.setResizable(true); size(gridsize*gridscale, gridsize*gridscale); background(backgroundcolor); smooth(); console.log(slope(1.0, 2.0)); //noLoop(); draw2(); } void draw() { // needed for mouse events to work } void draw2() { resetMatrix(); background(backgroundcolor); translate(0.5, 0.5); // axes stroke(axiscolor); line(gridsize*gridscale/2, 0, gridsize*gridscale/2, gridsize*gridscale); line(0, gridsize*gridscale/2, gridsize*gridscale, gridsize*gridscale/2); // field stroke(fieldcolor); translate(gridsize*gridscale/2, gridsize*gridscale/2); float hw = gridsize/2; for (float x = -hw; x <= hw; x += ticksize/gridscale) { for (float y = -hw; y <= hw; y += ticksize/gridscale) { float m = slope(x, y); pushMatrix(); translate(x*gridscale, -y*gridscale); rotate(-atan2(m, ticksize)); line(-ticksize/2, 0, ticksize/2, 0); if (arrows) { // arrowheads line(ticksize/2, 0, ticksize/2-ticksize/8, -1); line(ticksize/2, 0, ticksize/2-ticksize/8, 1); } popMatrix(); } } } void mousePressed() { if (mouseButton == LEFT) { solution = !solution; } else if (mouseButton == RIGHT) { arrows = !arrows; } mouseMoved(); } void mouseMoved() { draw2(); if (!solution) return; float mx = (float)mouseX/gridscale-gridsize/2; float my = gridsize/2-(float)mouseY/gridscale; // mouse coordinates pushMatrix(); resetMatrix(); String coords = "("+nfs(mx, 1, 1)+", "+nfs(my, 1, 1)+")"; fill(textbgcolor); noStroke(); rect(0, height - 8 - 6, textWidth(coords) + 5, 8 + 6); fill(textcolor); text(coords, 2, height - 2); popMatrix(); float y = my; float hw = gridsize/2; float lx = mx; stroke(solutioncolor); // instead of fixing rounding errors, go to hw+1 for (float x = mx+1.0/gridscale; x <= hw+1; x += 1.0/gridscale) { float m = slope(x, y)/gridscale/ticksize; //println(x+" "+y+" "+m*gridscale+" "+m); line(lx*gridscale, -y*gridscale, x*gridscale, -(y+m)*gridscale); y += m; lx = x; } lx = mx; y = my; // instead of fixing rounding errors, go to -hw-1 for (float x = mx-1.0/gridscale; x >= -hw-1; x -= 1.0/gridscale) { float m = slope(x, y)/gridscale/ticksize; //println(x+" "+y+" "+m*gridscale+" "+m); line(lx*gridscale, -y*gridscale, x*gridscale, -(y-m)*gridscale); y -= m; lx = x; } //println(); }