As the title said, why doesn't it work if I scale the shape doing shape.scale(0.5)
?
It doesn't work even if I do shape(0,0,200,200)
meaning I draw the shape not in the original dimensions. Is this a bug or I'm missing something?
As the title said, why doesn't it work if I scale the shape doing shape.scale(0.5)
?
It doesn't work even if I do shape(0,0,200,200)
meaning I draw the shape not in the original dimensions. Is this a bug or I'm missing something?
It kind of is a bug, although I'm not sure how severe. As you found out from your test the contains()
method doesn't work when transformations(translation/rotation/scale) are used.
I've got two somewhat hacky workarounds:
The first solution sounds like a bit of work and pointless duplication of data, not mention annoying when it comes to handling rotations and also error prone for 'stacked'/complex transformations.
The second workaround looks slightly hacky since contains() should've just worked, but it makes uses of Processing classes so it's not that bad. It works like this:
The svg comes from Examples > Basic > Shape > GetChild. You can open the sketch folder(Ctrl + K / CMD + K) to get "usa-wikipedia.svg" if you want to test the code as is:
import processing.opengl.*;
PShape ohio;
PMatrix2D coordSysSvgInv;//svg coordinate system inversed
void setup() {
size(1200, 480,OPENGL);//the catch is, even though we use PMatrix2D, PShape's applyMatrix() only seems to work with the P3D or OpenGL renderer
PShape usa = loadShape("usa-wikipedia.svg");
ohio = (PShape)usa.getChild("OH");
PMatrix2D transform = new PMatrix2D(); //apply transforms(position,rotation,scale) to this matrix
transform.scale(2); //be aware that the order of operation matters!
transform.translate(-800,-300); //this matrix can be used to convert from screen coordinats to SVG coordinates
coordSysSvgInv = transform.get(); //clone the svg to screen transformation matrix
coordSysSvgInv.invert(); //simply invert it to get the screen to svg
ohio.applyMatrix(transform); //apply this transformation matrix to the SVG
}
void draw() {
//update
PVector mouseInSVG = screenToSVG(mouseX,mouseY);
boolean isOver = ohio.contains(mouseInSVG.x,mouseInSVG.y);
//draw
background(255);
ohio.disableStyle();
fill(isOver ? color(0,192,0) : color(255,127,0));
shape(ohio);
}
PVector screenToSVG(float x,float y){
PVector result = new PVector();//create a new PVector to store transformed vector
coordSysSvgInv.mult(new PVector(x,y),result);//transform PVector by multiplying it to the inverse svg coord. sys.
return result;
}
I've noticed that the applyMatrix() method only works with the P3D
and OPENGL
renderers even thought I'm passing a PMatrix2D instance, otherwise this warning appears:
applyMatrix() with x, y, and z coordinates can only be used with a renderer that supports 3D, such as P3D or OPENGL. Use a version without a z-coordinate instead.
The 'cleaner' option is to modify the contains() method in the PShape class, then recompile Processing's core.jar and use the updated jar. If this is for a one-off small project I don't know if it's worth the trouble though, it might faster to have the slightly messier code from above than recompiling/updating core.jar.