Add Shape created by .intersect to a Canvas? - javafx

I am trying to highlight an Area that gets intersected by 2 Circle:
Example 1.:
The Yellow dots get, for testing purposes, random values. Those are used to draw a circle around, as well as to store an ellipse in the Background. In the Case of no intersection, the GUI acts correctly and display this:
After the random Values, the Shapes intersect. As I cannot seem to be able to add the new Shape made trough .intersect(), I just did a quick sp.setContent(), and got this image:
This basicly shows me the intersected space and colors it blue.
Everything is drawn on a Canvas, which basicly does the following:
Canvas canvas = new Canvas(250, 250);
....
gc = canvas.getGraphicsContext2D();
canvas.setHeight(imgTemp.getHeight());
canvas.setWidth(imgTemp.getWidth());
gc.drawImage(imgTemp, 0, 0);
Aswell as with some other Loops to draw the shapes and the circles.
Now, the code for the intersect is the following:
if (!(e.equals(eT))) {
if (e.getBoundsInParent().intersects(eT.getBoundsInParent())) {
System.out.println("Collision detected!");
Shape inter = Shape.intersect(e, eT);
if(inter.getBoundsInLocal().getWidth() > 0 && 0 < inter.getBoundsInLocal().getHeight()){
inter.setFill(BLUE);
inter.setStrokeWidth(3);
sp.setContent(inter);
}
}
I'm not that used to JavaFX and have only begun really working on it this Weekend for a small Project, but I am guessing that I might need to change from canvas to something else to make use of the shapes? Or is there a way to "tranform" the Shape of the intersect into something drawable by GraphicsContext2D?

Why don't you just put your Canvas into a Group and then add your shapes to the same Group. Why would you insist on drawing everything into the Canvas? A Canvas is just a Node like all the other Shapes and you can mix them freely in the SceneGraph.
Another question would be why you are using the Canvas at all if you have already realized that this leads to problems in your case.

Related

Is there a method for generating multiple irregular polygons and/or irregular blobs of equal surface area using p5.js?

For neuroscience research I'm attempting to train rats to press shapes on a touch screen. Ideally, these shapes would be highly distinct polygons or blobs to make it easier for the rats to discriminate. However, to limit some biases toward certain shapes, I'd like to keep the area of each shape equivalent. I've been trying to achieve this on p5.js, but I'm very new to this.
The code I've got so far provides some of the shape randomness, but not the consitency in area:
function setup() {
createCanvas(500, 500);
background(255);
fill(0);
translate(width/2, height/2);
beginShape();
for(let i = 0; i < 5; i++) {
const x = random(-250, 250);
const y = random(-250, 250);
vertex(x, y);
endShape();
}
}
Any help achieving this would be very appreciated
Maybe it's not what you need, the shapes are all inscribed in a circle(edit:the second code ones), not a bounding box as I said earlier.
Both examples are online at p5js editor:
The code I had was more free form, it will eternally increase the number of sides:
about 20 sides:
about 130 sides
But at the begining its more what I think you need
the code is here:
https://editor.p5js.org/v-k-/sketches/siYtDw423
And...
I made a tweeked version to try to go closer to what I think you want :)
The code is here:
https://editor.p5js.org/v-k-/sketches/oMsWC2NHv
Perhaps you can play with the numbers to get What you need. For instance:
You can set the number of sides, or even reject sides smaller than something.
It's very simple stuff ;) Easy to tweek.
Have fun, hope the rats like it.

masking, or clipping mask with p5.js

I want to use one shape (for instance a rectangle) to act as a mask or clipping path for another shape (for instance a circle, or line) in P5.js
I can see solutions for using images as masks, but not shapes. It seems mask() is not a function of shapes:
https://p5js.org/reference/#/p5.Image/mask
yes, you can.
create an extra rendering context with createGraphics().
In the draw loop draw something to this context which will be your
mask. Whatever should be visible in your result has to be colored
with the alpha channel, for example fill('rgba(0, 0, 0, 1)'.
Apply the mask to your original image myImage.mask(circleMask).
Your original image has now been modified by the mask, render it on
the screen: image(myImage, x, y, w, h)
Here is a working code example:
let circleMask;
let myImage;
function setup() {
createCanvas(400, 400);
circleMask = createGraphics(128, 128);
myImage = loadImage('FzFH41IucIY.jpg');
}
function draw() {
background(255);
circleMask.fill('rgba(0, 0, 0, 1)');
circleMask.circle(64, 64, 128);
myImage.mask(circleMask);
image(myImage, 200 - 64, 200 - 64, 128, 128);
}
There isn't a way to do this out of the box with P5.js.
Right now your question is more of a math question than it is a P5.js question. I'd recommend searching for something like "circle rectangle intersection" for a ton of results, including this one: Circle-Rectangle collision detection (intersection)
Depending on what you want to do, you could get away with drawing the shapes to images and then using those images as a mask. But more likely you're going to have to calculate the intersection yourself. You might be able to find a library that does this for you, but again, there isn't a simple out of the box way with P5.js.

Drawing a grid efficiently with EaselJS StageGL

I would like to draw a grid on a canvas using EaselJS. I am using the new WebGL stage, StageGL.
A grid is basically N times of a horizontal line and M times of a vertical line.
I see multiple options:
Draw N+M lines as all different shapes (I am talking about EaselJS "Shape" instances), cache them (as WebGL needs rasters) and add them to the stage.
Draw 1 horizontal and 1 vertical line, cache them (as WebGL needs rasters) and somehow draw the same image in the stage
Draw a single shape which consists of N+M paths, cache it and add it to the stage.
Option #1 seems naive to me. They're all the same image, why drawing them to the cache N+M times?
Option #2 would solve the problem in option #1, but I don't know how to do it.
Option #3 results in a very large image. For N=50, M=50 and gridSpacing=50px, it would result in a 2500x2500 px image. I don't know if this is ideal.
Which one is the best approach?
Are there any other approaches? I don't think I am the first person who draws a grid :)
You can pretty easily cache a shape, and use the resulting cache (canvas) as the source for a Bitmap.
var shape = new createjs.Shape();
shape.graphics.drawStuff();
// Since shapes have no bounds, you will have to know the bounds based on what you draw:
shape.cache(x, y, w, h);
var bmp = new createjs.Bitmap(shape.cacheCanvas);
You can draw as many of these Bitmaps without any additional cost, since its the same source canvas/image. EaselJS StageGL (latest NEXT, released shortly hopefully) renders this in WebGL no problem.
Check out the SpriteSheetBuilder demo and docs in GitHub to draw content to a SpriteSheet/Sprite instead of a Bitmap.
Cheers.

Antialiasing in Qt's QGraphicsScene make overlapping lines darker

When using anti-aliasing rendering in Qt's QGraphicsScene, there is a behavior that makes drawings appear not as expected: overlapping lines become darker. I could not see any description of this behavior in the documentation, and I cannot find a way to disable it.
For example if I want to draw such a polygon:
Because of the number of points, it is impossible not to have overlapping lines - fine. But because anti-aliasing is activated, some borders appear 'thicker' than others.
Is there any way to avoid this and have anti-aliased lines that can overlap and yet at the same time be rendered without getting darker?
I know of course that I can redefine the paint() function and draw manually individual lines that do not overlap, but this is what I want to avoid. I am using Pyside and this would significantly slow down the application, due to the high frequency at which paint() is being called.
EDIT Fixed by defining the object shape using QPainterPath / QGraphicsPathItem instead of QPolygon / QGraphicsPolygonItem. In that case the moveTo function allows to avoid lines that overlap.
Another thing you could try is adding half a pixel to your coordinates (not dimensions). This fixed the anti-aliasing issue for me.
XCoord = int(XValue) + 0.5
YCoord = int(XValue) + 0.5
Also make sure that before that you have integer pixel values.

How does masking work in C4?

I've set up a shape and an image that I'd like to mask my shape with. I set both their centers to the center of the canvas and then I wrote:
shape.mask = img;
But this gives me very strange results. The shape appears to be masked... sort of... the only part that shows up is the bottom right corner, the left half and the top half are cut off.
I also tried with two images, and with two shapes. Neither seems to work.
Am I missing a step? Perhaps the image I'm trying to mask with doesn't have any alpha values (I'm guessing here, I saw it mentioned in another question that they have to be images with alpha values and they mentioned .png files, so that's what I used)?
When I tried with two shapes, I tried setting the alpha value of the fill of the shape I wanted to mask with to 0.5 and 0.0 and also just setting the fillColor to Nil... still nothing.
I also (in a desperate last attempt) tried the method described here: Mask a view in Objective-C but I'm not very good with objective-c on its own so that didn't work either.
What is the correct way to mask in C4?
You're masking the right way.
What's going on is that an object's mask must be positioned based on the coordinate space of the object itself. When you add a subview to an object, it gets positioned relative to the object's {0,0}.
The following code will work and show you 2 things.
First, the masking shape is positioned to the center of the object, and NOT the center of the canvas:
s.center = CGPointMake(m.width/2,m.height/2);
Second, when you touch the canvas the animation will trigger the mask to move to the "center" coordinate of the canvas, but you'll notice that it goes further off. This is because it counts its position from the origin of the image.
#implementation C4WorkSpace {
C4Image *m;
C4Shape *s;
}
-(void)setup {
m = [C4Image imageNamed:#"C4Sky"];
s = [C4Shape ellipse:CGRectMake(0, 0, m.height, m.height)];
m.center = self.canvas.center;
s.center = CGPointMake(m.width/2,m.height/2);
m.mask = s;
[self.canvas addImage:m];
}
-(void)touchesBegan {
s.animationDuration = 1.0f;
s.center = self.canvas.center;
}
#end

Resources