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

91
LINES

< > BotCompany Repo | #1035476 // ManyCirclePainter

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (9612L/54K).

1  
// Optimal many-translucent-circles painter
2  
// [ O(w*h) + O(n*r) ]
3  
//
4  
// with
5  
//   w = image width
6  
//   h = image height
7  
//   n = # circles
8  
//   r = average height of a circle
9  
//
10  
// Comparison:
11  
// - Naive painting is O(w*h) + O(n*r*r)
12  
// - Naive raytracing is O(w*h*n)
13  
//
14  
// Loose proof of optimality:
15  
// - A term of O(w*h) is always required just to paint each pixel.
16  
// - And n*r is the minimum number of steps you have to do to actually
17  
//   figure out each circle's shape (either by walking around it
18  
//   or by calculating its width on each line).
19  
20  
sclass ManyCirclePainter is MakesBufferedImage {
21  
  settable int w;
22  
  settable int h;
23  
  settable new L<Circle> circles;
24  
  int[] pixels;
25  
26  
  L<Circle>[] startCircle, stopCircle;
27  
  bool ran;
28  
  
29  
  srecord Circle(Pt center, int radius) {}
30  
  
31  
  public int getWidth() { ret w; }
32  
  public int getHeight() { ret h; }
33  
  
34  
  selfType addCircle(int x, int y, int radius) {
35  
    circles.add(new Circle(pt(x, y), radius));
36  
    this;
37  
  }
38  
39  
  run {
40  
    if (ran) ret;
41  
    set ran;
42  
    pixels = new int[w*h];
43  
    if (pixels.length == 0) ret;
44  
    int nCircles = l(circles);
45  
    
46  
    startCircle = new L[h];
47  
    stopCircle = new L[h];
48  
    for (circle : circles) {
49  
      int y1 = max(0, circle.center.y-circle.radius);
50  
      int y2 = circle.center.y+circle.radius+1;
51  
      if (y1 >= y2) continue;
52  
      startCircle[y1] = addOrCreate(startCircle[y1], circle);
53  
      if (y2 < h)
54  
        stopCircle[y2] = addOrCreate(stopCircle[y2], circle);
55  
    }
56  
    
57  
    int[] startStop = new[w];
58  
    new Set<Circle> liveCircles;
59  
    int iPixel = 0;
60  
    
61  
    for y to h: {
62  
      fillArray(startStop, 0);
63  
      addAll(liveCircles, startCircle[y]);
64  
      removeAll(liveCircles, stopCircle[y]);
65  
      for (c : liveCircles) {
66  
        // width of circle at this line
67  
        int width = iround(sqrt(sqr(c.radius)-sqr(y-c.center.y)));
68  
        int x1 = c.center.x-width, x2 = c.center.x+width+1;
69  
        if (x1 > w || x2 <= 0) continue; // not visible at all at this row
70  
        startStop[max(x1, 0)]++;
71  
        if (x2 < w)
72  
          startStop[x2]--;
73  
      }
74  
      
75  
      int count = 0;
76  
      for x to w: {
77  
        count += startStop[x];
78  
        pixels[iPixel++] = countToColor(count, nCircles);
79  
      }
80  
    }
81  
  }
82  
  
83  
  int countToColor(int count, int nCircles) {
84  
    ret rgbIntFromBrightness(doubleRatio(count, min(nCircles, 8)));
85  
  }
86  
  
87  
  public BufferedImage getBufferedImage aka get() {
88  
    run();
89  
    ret bufferedImageWithoutAlpha(w, h, pixels);
90  
  }
91  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035476
Snippet name: ManyCirclePainter
Eternal ID of this version: #1035476/20
Text MD5: e6ba151aa0b3932b0b28394bfdd9b1c1
Transpilation MD5: ca66c0ed4e268d33422ef7098be7d46b
Author: someone
Category:
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-05-22 23:52:19
Source code size: 2552 bytes / 91 lines
Pitched / IR pitched: No / No
Views / Downloads: 159 / 334
Version history: 19 change(s)
Referenced in: [show references]