Reputation: 111
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
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