Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

384
LINES

< > BotCompany Repo | #1000551 // Magnets (v3, with edge points p1 and p2)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (1629L/12K/36K).

1  
!636
2  
3  
import java.awt.*;
4  
import java.awt.image.*;
5  
import javax.imageio.*;
6  
import static java.lang.Math.*;
7  
8  
!standard functions
9  
!image classes
10  
!FrameWithImages
11  
!quicknew
12  
!* ctr
13  
!721 // thread {
14  
15  
class P { double x, y; *(double *x, double *y) {} }
16  
17  
interface Reproducer {
18  
  public main.Params reproduce(RGBImage original);
19  
}
20  
  
21  
interface ReproducerMaker {
22  
  public Reproducer make();
23  
}
24  
25  
main {
26  
  static Object androidContext;
27  
  static int imageWidth = 200;
28  
  
29  
  !include #1000522 // helper functions for image reproduction
30  
  
31  
  static double pi = PI;
32  
  
33  
  static double rotate_x(P p, double angle) {
34  
    angle = angle*pi/180;
35  
    return p.x*cos(angle)-p.y*sin(angle);
36  
  }
37  
  
38  
  static double sideshiftlimit = sqrt(2)/2;
39  
    
40  
  static class Magnet extends Params {
41  
    double angle, sideshift;
42  
    RGB col1 = new RGB(Color.black), col2 = new RGB(Color.white);
43  
    double p1 = -1, p2 = -1;
44  
    
45  
    RGB def(double x, double y) {
46  
      P p = new P(x-0.5, y-0.5);
47  
      x = rotate_x(p, -angle);
48  
      return x < sideshift ? col1 : col2;
49  
    }
50  
    
51  
    Magnet copy() {
52  
      new Magnet p;
53  
      baseClone(p);
54  
      p.sideshift = sideshift;
55  
      p.angle = angle;
56  
      p.col1 = col1;
57  
      p.col2 = col2;
58  
      return p;
59  
    }
60  
    
61  
    public String toString() {
62  
      return "M " + formatDouble(sideshift, 2) + " " + (int) angle + " " + col1 + " " + col2;
63  
    }
64  
65  
    RGBImage render() {
66  
      int w = original.getWidth(), h = original.getHeight();
67  
      RGBImage image = new RGBImage(w, h, Color.white);
68  
      paint(image, this);
69  
      getP1P2();
70  
      image.setPixel(Math.min(w-1, (int) ptox(p1)), Math.min(h-1, (int) ptoy(p1)), Color.red);
71  
      image.setPixel(Math.min(w-1, (int) ptox(p2)), Math.min(h-1, (int) ptoy(p2)), Color.red);
72  
      return image;
73  
    }
74  
    
75  
    double ptox(double i) {
76  
      int w = original.getWidth();
77  
      return i < w ? i : i < 2*w ? w : i < 3*w ? w-(i-2*w) : 0;
78  
    }
79  
    
80  
    double ptoy(double i) {
81  
      int w = original.getWidth();
82  
      return i < w ? 0 : i < 2*w ? i-w : i < 3*w ? w : w-(i-3*w);
83  
    }
84  
    
85  
    void getP1P2() {
86  
      if (p2 != -1) return;
87  
      int w = original.getWidth();
88  
      if (w != original.getHeight()) fail("not a square");
89  
      RGB last = null;
90  
      for (int i = 0; i < 4*w; i++) {
91  
        double x = ptox(i);
92  
        double y = ptoy(i);
93  
        RGB col = def(x/w, y/w);
94  
        if (last == null) last = col;
95  
        else if (!col.equals(last))
96  
          if (p1 == -1) p1 = i; else p2 = i;
97  
      }
98  
      if (p1 != -1 && p2 == -1) p2 = 0;
99  
      if (p1 == -1) p1 = 0;
100  
    }
101  
  }
102  
103  
  static abstract class Params {
104  
    RGBImage original;
105  
    abstract RGBImage render();
106  
    abstract Params copy();
107  
    
108  
    void baseClone(Params p) {
109  
      p.original = original;
110  
    }
111  
    
112  
    RGBImage rendered;
113  
    RGBImage getImage() {
114  
      if (rendered == null)
115  
        rendered = render();
116  
      return rendered;
117  
    }
118  
    
119  
    double score = 2.0;
120  
    double getScore() {
121  
      if (score == 2.0)
122  
        score = calcScore();
123  
      return score;
124  
    }
125  
    
126  
    double calcScore() {
127  
      return diff(original, getImage());
128  
    }
129  
    
130  
    boolean isBetterThan(Params p) {
131  
      return getScore() < p.getScore();
132  
    }
133  
  }
134  
  
135  
  static class RandomMagnet implements Reproducer {
136  
    int n = -1;
137  
    public Params reproduce(RGBImage original) {
138  
      ++n;
139  
      new Magnet p;
140  
      p.original = original;
141  
      p.sideshift = random(-sideshiftlimit, sideshiftlimit);
142  
      p.angle = random()*360;
143  
      if (n % 2 == 0) {
144  
        p.col1 = randomColor();
145  
        p.col2 = randomColor();
146  
      } else {
147  
        p.col1 = probeRandomPixel(original);
148  
        p.col2 = probeRandomPixel(original);
149  
      }
150  
      return p;
151  
    }
152  
  }
153  
  
154  
  static class VaryBest implements Reproducer {
155  
    Reproducer base;
156  
    Params best;
157  
    
158  
    VaryBest(Reproducer base) {
159  
      this.base = base;
160  
    }
161  
    
162  
    public Params reproduce(RGBImage original) {
163  
      Params p = base.reproduce(original);
164  
      if (best == null || p.isBetterThan(best))
165  
        best = p;
166  
      Params variation = vary(best);
167  
      //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
168  
      if (variation.isBetterThan(best)) {
169  
        //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
170  
        best = variation;
171  
      }
172  
      return best;
173  
    }
174  
    
175  
    Params vary(Params p) {
176  
      if (p instanceof Magnet) {
177  
        Magnet n = ((Magnet) p).copy();
178  
        int s = random(3);
179  
        if (s == 0) {
180  
          s = random(2);
181  
          if (s == 0)
182  
            n.sideshift = varySideshift(n.sideshift);
183  
          else {
184  
            //double old = n.angle;
185  
            n.angle = (n.angle+360+random(-5, 5)) % 360;
186  
            //System.out.println("angle: " + formatDouble(old, 1) + " -> " + formatDouble(n.angle, 1));
187  
          }
188  
        } else if (s == 1)
189  
          n.col1 = varyColor(n.col1);
190  
        else
191  
          n.col2 = varyColor(n.col2);
192  
        return n;
193  
      }
194  
      
195  
      return null;
196  
    }
197  
    
198  
    double varySideshift(double sideshift) {
199  
      return max(-sideshiftlimit, min(sideshiftlimit, sideshift+random(-0.1, 0.1)));
200  
    }
201  
    
202  
    double varyN(double x) {
203  
      return Math.max(0, Math.min(1, x+random(-0.1, 0.1)));
204  
    }
205  
    
206  
    float varyChannel(float x) {
207  
      return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1))));
208  
    }
209  
    
210  
    RGB varyColor(RGB rgb) {
211  
      int s = random(3);
212  
      if (s == 0)
213  
        return new RGB(varyChannel(rgb.r), rgb.g, rgb.b);
214  
      else if (s == 1)
215  
        return new RGB(rgb.r, varyChannel(rgb.g), rgb.b);
216  
      else
217  
        return new RGB(rgb.r, rgb.g, varyChannel(rgb.b));
218  
    }
219  
  }
220  
221  
  static class Gridded extends Params {
222  
    int w, h;
223  
    Params[] array;
224  
    
225  
    Gridded(int w, int h) {
226  
      this.w = w;
227  
      this.h = h;
228  
      array = new Params[w*h];
229  
    }
230  
    
231  
    Gridded copy() {
232  
      Gridded p = new Gridded(w, h);
233  
      baseClone(p);
234  
      for (int i = 0; i < w*h; i++)
235  
        p.array[i] = array[i].copy();
236  
      return p;
237  
    }
238  
    
239  
    public String toString() {
240  
      StringBuilder buf = new StringBuilder("grid{");
241  
      for (int i = 0; i < w*h; i++) {
242  
        if (i != 0)
243  
          buf.append(", ");
244  
        buf.append(array[i]);
245  
      }
246  
      return buf + "}";
247  
    }
248  
    
249  
    public RGBImage render() {
250  
      int ow = original.getWidth(), oh = original.getHeight();
251  
      RGBImage img = new RGBImage(ow, oh, Color.white);
252  
      for (int y = 0; y < h; y++)
253  
        for (int x = 0; x < w; x++) {
254  
          int x1 = x*ow/w, y1 = y*oh/h;
255  
          int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
256  
          RGBImage part = array[y*w+x].render();
257  
          main.copy(part, 0, 0, img, x1, y1, part.getWidth(), part.getHeight());
258  
        }
259  
      return img;
260  
    }
261  
  }
262  
  
263  
  static class Grid implements Reproducer {
264  
    int w, h;
265  
    Reproducer[] bases;
266  
    
267  
    Grid(ReproducerMaker maker, int w, int h) {
268  
      this.w = w;
269  
      this.h = h;
270  
      bases = new Reproducer[w*h];
271  
      for (int i = 0; i < w*h; i++)
272  
        bases[i] = maker.make();
273  
    }
274  
    
275  
    RGBImage getGridElement(RGBImage original, int i) {
276  
      int ow = original.getWidth(), oh = original.getHeight();
277  
      int y = i / w;
278  
      int x = i % w;
279  
      int x1 = x*ow/w, y1 = y*oh/h;
280  
      int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
281  
      return original.clip(x1, y1, x2-x1, y2-y1);
282  
    }
283  
      
284  
    public Params reproduce(RGBImage original) {
285  
      Gridded gridded = new Gridded(w, h);
286  
      gridded.original = original;
287  
      for (int i = 0; i < w*h; i++) {
288  
        RGBImage img = getGridElement(original, i);
289  
        Params p = bases[i].reproduce(img);
290  
        if (p == null)
291  
          return null;
292  
        gridded.array[i] = p;
293  
      }
294  
      return gridded;
295  
    }
296  
  }
297  
  
298  
  static ReproducerMaker baseMaker = new ReproducerMaker() {
299  
    public Reproducer make() {
300  
      return new VaryBest(new RandomMagnet());
301  
    }
302  
  };
303  
    
304  
  // main reproduce function
305  
  static Reproducer reproducer;
306  
307  
  static String imageID = "#1000326"; // Bryan Cranston!
308  
  static RGBImage original;
309  
  static FrameWithImages fwi;
310  
    
311  
  psvm {
312  
    if (args.length != 0) imageID = args[0];
313  
    
314  
    fwi = new FrameWithImages(1);
315  
    fwi.setZoom(2);
316  
    fwi.hop();
317  
    
318  
    thread {
319  
      original = loadImage(imageID);
320  
      original = resizeToWidth(original, imageWidth);
321  
      fwi.setInnerSize(original);
322  
      
323  
      int gx = original.getWidth()/8, gy = original.getHeight()/8;
324  
      reproducer = new Grid(baseMaker, gx, gy);
325  
      
326  
      reproduceOpenEnd(original);
327  
    }
328  
    
329  
    /*
330  
    new Magnet m;
331  
    m.sideshift = -0.2;
332  
    m.angle = 30;
333  
    
334  
    while (true) {
335  
      m.angle = (m.angle+1) % 360;
336  
      //System.out.println("Angle: " + m.angle);
337  
      RGBImage img = new RGBImage(100, 100, Color.gray);
338  
      paint(img, m);
339  
      fwi.setImage(0, img);
340  
    }
341  
    */
342  
  }
343  
  
344  
  
345  
  static void reproduceOpenEnd(RGBImage original) {
346  
    Params best = null;
347  
    long lastPrint = 0, lastN = 0;
348  
    for (long ntry = 1; ; ntry++) {
349  
      long now = System.currentTimeMillis();
350  
      if (now >= lastPrint+1000) {
351  
        long tps = (ntry-lastN)*1000/(now-lastPrint);
352  
        lastPrint = now;
353  
        lastN = ntry;
354  
        String s = "Try " + ntry + "(" + tps + "/s)";
355  
        if (best == null)
356  
          System.out.println(s);
357  
        else {
358  
          System.out.println("Best: " + best);
359  
          System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 3) + "%, structure size: " + structureSize(best, Params.class));
360  
        }
361  
      }
362  
      Params p = reproducer.reproduce(original);
363  
      if (best == null || p != null && p.getScore() < best.getScore()) {
364  
        //System.out.println("New best! " + p.getScore());
365  
        best = p;
366  
        fwi.setImage(0, p.getImage());
367  
      }
368  
      
369  
      if (p != null && p.getScore() == 0.0)
370  
        break;
371  
    }
372  
  }
373  
  
374  
  static void paint(RGBImage img, Magnet m) {
375  
    int w = img.getWidth(), h = img.getHeight();
376  
    for (int y = 0; y < h; y++)
377  
      for (int x = 0; x < w; x++) {
378  
        double nx = x/(double)(w-1);
379  
        double ny = y/(double)(h-1);
380  
        img.setPixel(x, y, m.def(nx, ny));
381  
      }
382  
  }
383  
  
384  
}

Author comment

Began life as a copy of #1000550

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, teubizvjbppd, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1000551
Snippet name: Magnets (v3, with edge points p1 and p2)
Eternal ID of this version: #1000551/1
Text MD5: 4c6ec516b329f299970a3e68aadae077
Transpilation MD5: 6b0cef5ebc746c32c39ffe8e7d304b3c
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-12 20:22:03
Source code size: 10440 bytes / 384 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 650 / 631
Referenced in: [show references]