Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 243
JJ23 Avatar asked Jan 18 '26 07:01

JJ23


1 Answers

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();
};
like image 177
sasensi Avatar answered Jan 20 '26 19:01

sasensi