Expected a different result from `PGS_ShapeBoolean.union()`
mheesakkers opened this issue · 3 comments
Hi Micycle,
This seems like a great library thanks! I was testing the boolean functionality with two simples shapes an ellipse and a rectangle but it didn't gave me the result I was expecting. It seems the PShapes change positions when united with each other? The expected behaviour would be a unified shape at the same position I'd say. Thought?
import micycle.pgs.*;
void setup() {
size(595, 842, P2D);
}
void draw() {
background(0);
PShape shapeOne = createShape(ELLIPSE, 100, 100, width * 0.4, width * 0.4);
shapeOne.setFill(#ffff00);
PShape shapeTwo = createShape(RECT, 150, 150, width * 0.5, width * 0.5);
shapeTwo.setFill(#00ff00);
shape(shapeOne);
shape(shapeTwo);
PShape union = PGS_ShapeBoolean.union(shapeOne, shapeTwo);
union.setFill(#ff0000);
translate(0, 300);
shape(union);
}
In yellow and green the source shapes. In red the unified shape, slightly translated on the y-axis.
createShape()
essentially creates a shape whose vertices are centered on (0, 0); a shape's translation is not encoded in its vertices' coordinates but rather in the shape's affine transformation matrix (which is applied afterwards to a shape's vertices whenever the shape is drawn).
PGS doesn't take into account this translation matrix (because it's not actually a public/accessible field), and reads the shape's raw coordinate values only.
One way around this is to first translate the shape using PGS_Transformation.translate()
. After doing this a shape's vertices' coordinate values will actually encode the translation. Then PGS works as expected:
import micycle.pgs.*;
void setup() {
size(595, 842, P2D);
}
void draw() {
background(0);
PShape shapeOne = createShape(ELLIPSE, 0, 0, width * 0.4, width * 0.4);
shapeOne = PGS_Transformation.translate(shapeOne, 100, 100);
shapeOne.setFill(#ffff00);
shapeOne.setStroke(false);
PShape shapeTwo = createShape(RECT, 150, 150, width * 0.5, width * 0.5);
shapeTwo = PGS_Transformation.translate(shapeTwo, 150, 150);
shapeTwo.setFill(#00ff00);
shapeTwo.setStroke(false);
shape(shapeOne);
shape(shapeTwo);
PShape union = PGS_ShapeBoolean.union(shapeOne, shapeTwo);
union.setFill(#ff0000);
translate(0, 300);
shape(union);
}
A possible fix/workaround to such issues arising from shapes created via createShape()
(and any calls to translate()
or rotate()
, that applies to all shapes) is to have PGS read a PShape
's affine matrix and apply any transformations to the shape's vertices before further processing. The PShape
affine matrix (matrix
) will need to be accessed via Java reflection as it is a protected
field.