JJ23
JJ23

Reputation: 111

Circle filled with points on canvas in paper.js

I'm trying to fill get a circle shaped area filled with rectangles (to be precise, Raster width dimensions 12x20).

After some research and experiments, I found one solution. To draw a circle, get its bounding box and iterate through every pixel to found that distance is smaller or equal to circle R.

Some code sample here, I'm using three.js

let shapeSize = [12, 20];

let circleR = R / 2;
let circle = new Circle(position, circleR);
let bounds = circle.bounds;
for (let i = bounds.x; i <= bounds.x + bounds.width; i += 1) {
  for (let j = bounds.y; j <= bounds.y + bounds.height; j += 20) {
    let center = new Point(i, j);
    if (center.getDistance(position) <= circleR) {
      center = new Point(i, j);
      let shape = new Shape({center, alpha: 0.7, scale: 0.8});
      j += shapeSize[1] - 1; // this part smells 
    }
  }
}

Shape is square with a rester - size 12x20.

But with this code sample, it's impossible to get a circle filled with squares. If I increment i+=12 and y+=20, I get too much space around, and if by one every square is over another and it generates too many squares.

Any idea how to do it nice and elegant?

Upvotes: 3

Views: 1177

Answers (1)

sasensi
sasensi

Reputation: 4650

As JJ23 said, you can use the circle as a clip mask for a group containing your rasters grid.
Here is a Sketch demonstrating how to do it with Paper.js.

// constants
var RADIUS       = 200;
var IMAGE        = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAUCAIAAAA2kktGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE82lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTA5LTI2VDA5OjE0OjQ5KzAyOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDE4LTA5LTI2VDA5OjE0OjQ5KzAyOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOC0wOS0yNlQwOToxNDo0OSswMjowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTYwZDg3MWYtZmFjOS0wYTRjLThmOGQtYjdmNDdhMGRiYzBlIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjU2MGQ4NzFmLWZhYzktMGE0Yy04ZjhkLWI3ZjQ3YTBkYmMwZSIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjU2MGQ4NzFmLWZhYzktMGE0Yy04ZjhkLWI3ZjQ3YTBkYmMwZSIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NTYwZDg3MWYtZmFjOS0wYTRjLThmOGQtYjdmNDdhMGRiYzBlIiBzdEV2dDp3aGVuPSIyMDE4LTA5LTI2VDA5OjE0OjQ5KzAyOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+tv5OvAAAAiRJREFUKJFdks9qKjEUxs9JJk5GHdFBqEVBEAa6UHwA22codNeVWze+WR9CXHbRhZsqtP7BjjAYGWWs4+gkuYvI5XKzCt/5nZzvnBMkhCilAAAAOOe2bedyOUppkiRxHCulKKWWIRDR87xOp9NoNCilQRB8f3+fz+c0TSuVimXeKBQK/X7/9fU1CIK3t7fZbBaG4eVyQcTL5WIY8H3//f396+trOBzWajXHccrlsm3biEgIIQayLAsAFovFeDwWQriu2263Pc8DAK31rZwQYjKZMMbiONZaSylXq9XxeDQQJYRora/X63a73Ww28/k8TdM0TU+nU5qmt7bu7+/DMFRKMcYYY1mWcc5rtVqxWFwul1EUaa3J4+Mj5xwAsixLkoQx1m63X15eer2e0QGADgaDz89Pk4GIACCl/Pn5mUwmQgillNbauru7q1QqiKi1Nv6CIAiCQCll27bZh7Xf77MsAwBKKSJyzi3LklIqpZRSt1C9Xv/4+EiSpFgsIuL1epVSaq2zLCOE5HI5AEDf91erFWOsVCoBgFkF59x13Uaj4XnedDq11uu1ydvtdlprxpjrus1m8+npqdvtRlFEKUXbtvP5/OFwcBzH87zT6fT7++s4ju/71Wp1vV5HUYQPDw/7/V4I0Wq1np+fN5vNaDQKw9C0opSSUlpCiOPxiIjlcvl8PsdxLKU00zIX89sQAAghjDFjzgwQ/j0G+k8hhPzVOed/AJQ+QEC6tzaSAAAAAElFTkSuQmCC';
var IMAGE_WIDTH  = 12;
var IMAGE_HEIGHT = 20;

// create image
var raster    = new Raster(IMAGE);
// wait for image loading
raster.onLoad = function ()
{
    // draw raster grid as a group
    var group  = new Group();
    var stepsX = Math.ceil(RADIUS * 2 / IMAGE_WIDTH);
    var stepsY = Math.ceil(RADIUS * 2 / IMAGE_HEIGHT);
    for (var i = 0; i < stepsX; i++)
    {
        for (var j = 0; j < stepsY; j++)
        {
            // calculate grid point
            var point            = new Point(i * IMAGE_WIDTH, j * IMAGE_HEIGHT);
            // clone original raster
            var rasterClone      = raster.clone();
            // position it at grid point
            rasterClone.position = point;
            // add it to the group
            group.addChild(rasterClone);
        }
    }

    // draw circle
    var circle = new Path.Circle(group.position, RADIUS);
    // add it to the group as first child
    group.insertChild(0, circle);
    // enable clipping
    group.clipped = true;

    // position group at view center
    group.position = view.center;

    // delete original raster
    raster.remove();
};

Upvotes: 1

Related Questions