Skip to content

Commit 0dbfc47

Browse files
committed
new vertical size option in the "Cubes Pattern" filter
1 parent 17e31c5 commit 0dbfc47

1 file changed

Lines changed: 51 additions & 50 deletions

File tree

src/main/java/pixelitor/filters/Cubes.java

Lines changed: 51 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919

2020
import pixelitor.Canvas;
2121
import pixelitor.Views;
22-
import pixelitor.filters.gui.ColorParam;
23-
import pixelitor.filters.gui.EnumParam;
24-
import pixelitor.filters.gui.FilterButtonModel;
25-
import pixelitor.filters.gui.RangeParam;
22+
import pixelitor.filters.gui.*;
2623
import pixelitor.filters.util.ShapeWithColor;
2724
import pixelitor.io.FileIO;
2825
import pixelitor.utils.Distortion;
@@ -80,7 +77,7 @@ public String toString() {
8077
}
8178

8279
private final EnumParam<CubeType> typeParam = new EnumParam<>("Type", CubeType.class);
83-
private final RangeParam sizeParam = new RangeParam("Size", 5, 20, 200);
80+
private final GroupedRangeParam sizeParam = new GroupedRangeParam("Size", 5, 20, 200);
8481
private final ColorParam topColorParam = new ColorParam("Top Color", WHITE, MANUAL_ALPHA_ONLY);
8582
private final ColorParam leftColorParam = new ColorParam("Left Color", LIGHT_GRAY, MANUAL_ALPHA_ONLY);
8683
private final ColorParam rightColorParam = new ColorParam("Right Color", GRAY, MANUAL_ALPHA_ONLY);
@@ -169,36 +166,40 @@ private List<ShapeWithColor> createShapes(int width, int height) {
169166
CubeType type = typeParam.getSelected();
170167
boolean interlocking = type.isInterlocking;
171168

172-
double size = sizeParam.getValueAsDouble();
169+
double size = sizeParam.getValueAsDouble(0);
170+
double verSize = sizeParam.getValueAsDouble(1);
171+
172+
double ratio = verSize / size;
173+
173174
// isometric projection constants
174175
double longer = size * Math.cos(Math.PI / 6.0);
175176
double shorter = size * Math.sin(Math.PI / 6.0);
176177

177178
double horizontalSpacing = interlocking ? 3.0 * longer : 2.0 * longer;
178-
double verticalSpacing = interlocking ? size * 0.75 : (size + shorter);
179+
double verticalSpacing = (interlocking ? size * 0.75 : (size + shorter)) * ratio;
179180

180181
// add a buffer to ensure the pattern covers the entire image, even when offset
181182
int numCubesX = (int) (width / horizontalSpacing) + 2;
182-
int numCubesY = (int) (height / verticalSpacing) + (interlocking ? 3 : 2);
183+
int numCubesY = (int) (height / Math.max(1.0, verticalSpacing)) + (interlocking ? 3 : 2);
183184

184185
double moveHorOffset = transform.getHorOffset(width);
185186
double moveVerOffset = transform.getVerOffset(height);
186187

187188
// special y-offset for interlocking to align rows correctly
188-
double verOffset = moveVerOffset + (interlocking ? -size / 2.0 : 0);
189+
double verOffset = moveVerOffset + (interlocking ? -size / 2.0 * ratio : 0);
189190
for (int row = 0; row < numCubesY; row++) {
190191
// offset every other row for a staggered pattern
191192
double horOffset = moveHorOffset + (row % 2 == 0 ? 0 : longer);
192193
if (interlocking) {
193-
// interlocking pattern requires additional horizontal shift
194+
// the interlocking pattern requires additional horizontal shift
194195
horOffset *= 1.5;
195196
}
196197

197198
for (int col = 0; col < numCubesX; col++) {
198199
double baseX = horOffset + col * horizontalSpacing;
199200
double baseY = verOffset + row * verticalSpacing;
200201

201-
addCubeShapes(shapes, baseX, baseY, longer, shorter, size, type,
202+
addCubeShapes(shapes, baseX, baseY, longer, shorter, size, ratio, type,
202203
topColor, rightColor, leftColor);
203204
}
204205
}
@@ -214,11 +215,11 @@ private record CubeFaces(Path2D top, Path2D right, Path2D left) {
214215
*/
215216
private static void addCubeShapes(List<ShapeWithColor> shapes,
216217
double baseX, double baseY,
217-
double longer, double shorter, double size,
218+
double longer, double shorter, double size, double ratio,
218219
CubeType type,
219220
Color topColor, Color rightColor, Color leftColor) {
220221

221-
CubeFaces faces = createCubeFaces(baseX, baseY, longer, shorter, size, type.isInterlocking);
222+
CubeFaces faces = createCubeFaces(baseX, baseY, longer, shorter, size, ratio, type.isInterlocking);
222223

223224
shapes.add(new ShapeWithColor(faces.top, topColor));
224225
shapes.add(new ShapeWithColor(faces.right, rightColor));
@@ -247,103 +248,103 @@ private static void addCubeShapes(List<ShapeWithColor> shapes,
247248
/**
248249
* Creates the three visible faces of a single cube.
249250
*/
250-
private static CubeFaces createCubeFaces(double baseX, double baseY, double longer, double shorter, double size, boolean interlocking) {
251+
private static CubeFaces createCubeFaces(double baseX, double baseY, double longer, double shorter, double size, double ratio, boolean interlocking) {
251252
Path2D topFace;
252253
Path2D rightFace;
253254
Path2D leftFace;
254255

255256
if (interlocking) {
256-
topFace = createInterlockingTop(baseX, baseY, longer, shorter, size);
257-
rightFace = createInterlockingRight(baseX, baseY, longer, shorter, size);
258-
leftFace = createInterlockingLeft(baseX, baseY, longer, shorter, size);
257+
topFace = createInterlockingTop(baseX, baseY, longer, shorter, size, ratio);
258+
rightFace = createInterlockingRight(baseX, baseY, longer, shorter, size, ratio);
259+
leftFace = createInterlockingLeft(baseX, baseY, longer, shorter, size, ratio);
259260
} else {
260-
topFace = createBasicTop(baseX, baseY, longer, shorter, size);
261-
rightFace = createBasicRight(baseX, baseY, longer, shorter, size);
262-
leftFace = createBasicLeft(baseX, baseY, longer, shorter, size);
261+
topFace = createBasicTop(baseX, baseY, longer, shorter, size, ratio);
262+
rightFace = createBasicRight(baseX, baseY, longer, shorter, size, ratio);
263+
leftFace = createBasicLeft(baseX, baseY, longer, shorter, size, ratio);
263264
}
264265
return new CubeFaces(topFace, rightFace, leftFace);
265266
}
266267

267268
/**
268269
* Creates the path for the top face of a basic cube.
269270
*/
270-
private static Path2D createBasicTop(double baseX, double baseY, double longer, double shorter, double size) {
271+
private static Path2D createBasicTop(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
271272
Path2D top = new Path2D.Double();
272273
top.moveTo(baseX, baseY);
273-
top.lineTo(baseX - longer, baseY - shorter);
274-
top.lineTo(baseX, baseY - size);
275-
top.lineTo(baseX + longer, baseY - shorter);
274+
top.lineTo(baseX - longer, baseY - shorter * ratio);
275+
top.lineTo(baseX, baseY - size * ratio);
276+
top.lineTo(baseX + longer, baseY - shorter * ratio);
276277
top.closePath();
277278
return top;
278279
}
279280

280281
/**
281282
* Creates the path for the right face of a basic cube.
282283
*/
283-
private static Path2D createBasicRight(double baseX, double baseY, double longer, double shorter, double size) {
284+
private static Path2D createBasicRight(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
284285
Path2D right = new Path2D.Double();
285286
right.moveTo(baseX, baseY);
286-
right.lineTo(baseX + longer, baseY - shorter);
287-
right.lineTo(baseX + longer, baseY - shorter + size);
288-
right.lineTo(baseX, baseY + size);
287+
right.lineTo(baseX + longer, baseY - shorter * ratio);
288+
right.lineTo(baseX + longer, baseY - shorter * ratio + size * ratio);
289+
right.lineTo(baseX, baseY + size * ratio);
289290
right.closePath();
290291
return right;
291292
}
292293

293294
/**
294295
* Creates the path for the left face of a basic cube.
295296
*/
296-
private static Path2D createBasicLeft(double baseX, double baseY, double longer, double shorter, double size) {
297+
private static Path2D createBasicLeft(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
297298
Path2D left = new Path2D.Double();
298299
left.moveTo(baseX, baseY);
299-
left.lineTo(baseX - longer, baseY - shorter);
300-
left.lineTo(baseX - longer, baseY - shorter + size);
301-
left.lineTo(baseX, baseY + size);
300+
left.lineTo(baseX - longer, baseY - shorter * ratio);
301+
left.lineTo(baseX - longer, baseY - shorter * ratio + size * ratio);
302+
left.lineTo(baseX, baseY + size * ratio);
302303
left.closePath();
303304
return left;
304305
}
305306

306307
/**
307308
* Creates the path for the top face of an interlocking cube.
308309
*/
309-
private static Path2D createInterlockingTop(double baseX, double baseY, double longer, double shorter, double size) {
310+
private static Path2D createInterlockingTop(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
310311
Path2D top = new Path2D.Double();
311312
top.moveTo(baseX, baseY);
312-
top.lineTo(baseX - longer, baseY - shorter);
313-
top.lineTo(baseX - longer / 2.0, baseY - size / 2.0 - shorter / 2.0);
314-
top.lineTo(baseX, baseY - shorter);
315-
top.lineTo(baseX + longer / 2.0, baseY - size / 2.0 - shorter / 2.0);
316-
top.lineTo(baseX + longer, baseY - shorter);
313+
top.lineTo(baseX - longer, baseY - shorter * ratio);
314+
top.lineTo(baseX - longer / 2.0, baseY - (size / 2.0 + shorter / 2.0) * ratio);
315+
top.lineTo(baseX, baseY - shorter * ratio);
316+
top.lineTo(baseX + longer / 2.0, baseY - (size / 2.0 + shorter / 2.0) * ratio);
317+
top.lineTo(baseX + longer, baseY - shorter * ratio);
317318
top.closePath();
318319
return top;
319320
}
320321

321322
/**
322323
* Creates the path for the right face of an interlocking cube.
323324
*/
324-
private static Path2D createInterlockingRight(double baseX, double baseY, double longer, double shorter, double size) {
325+
private static Path2D createInterlockingRight(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
325326
Path2D right = new Path2D.Double();
326327
right.moveTo(baseX, baseY);
327-
right.lineTo(baseX + longer, baseY - shorter);
328-
right.lineTo(baseX + longer, baseY - shorter + size / 2.0);
329-
right.lineTo(baseX + longer / 2.0, baseY + 0.25 * size);
330-
right.lineTo(baseX + longer / 2.0, baseY - shorter / 2.0 + size);
331-
right.lineTo(baseX, baseY + size);
328+
right.lineTo(baseX + longer, baseY - shorter * ratio);
329+
right.lineTo(baseX + longer, baseY + (-shorter + size / 2.0) * ratio);
330+
right.lineTo(baseX + longer / 2.0, baseY + (0.25 * size) * ratio);
331+
right.lineTo(baseX + longer / 2.0, baseY + (-shorter / 2.0 + size) * ratio);
332+
right.lineTo(baseX, baseY + size * ratio);
332333
right.closePath();
333334
return right;
334335
}
335336

336337
/**
337338
* Creates the path for the left face of an interlocking cube.
338339
*/
339-
private static Path2D createInterlockingLeft(double baseX, double baseY, double longer, double shorter, double size) {
340+
private static Path2D createInterlockingLeft(double baseX, double baseY, double longer, double shorter, double size, double ratio) {
340341
Path2D left = new Path2D.Double();
341342
left.moveTo(baseX, baseY);
342-
left.lineTo(baseX - longer, baseY - shorter);
343-
left.lineTo(baseX - longer, baseY - shorter + size / 2.0);
344-
left.lineTo(baseX - longer / 2.0, baseY + 0.25 * size);
345-
left.lineTo(baseX - longer / 2.0, baseY - shorter / 2.0 + size);
346-
left.lineTo(baseX, baseY + size);
343+
left.lineTo(baseX - longer, baseY - shorter * ratio);
344+
left.lineTo(baseX - longer, baseY + (-shorter + size / 2.0) * ratio);
345+
left.lineTo(baseX - longer / 2.0, baseY + (0.25 * size) * ratio);
346+
left.lineTo(baseX - longer / 2.0, baseY + (-shorter / 2.0 + size) * ratio);
347+
left.lineTo(baseX, baseY + size * ratio);
347348
left.closePath();
348349
return left;
349350
}

0 commit comments

Comments
 (0)