JavaFX 8 - How to erase a part of background making it transparent - javafx-8

I have a Pane and inside it I have a Rectangle shape.
The Pane has a red background. What I want is that, in the part where the rectangle is placed, the background is transparent.
This is the code:
Pane pane=new Pane();
pane.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
Rectangle rect=new Rectangle(50,50,50,50, Color.YELLOW);
pane.getChildren().add(rect);
This is the result
This is what I want
In the second picture the grey color is the background color of the stage.
I tried to play with the blending mode but I didn't succeed.

To accomplish your goal, you could try to use 2 instances of Rectangle instead of a Pane and a Rectangle. By doing so, you could use the static substract method of the Shape class to substract the two areas from one another:
Shape.substract(Rect_1, Rect_2);
As stated by Oracle, the method does exactly what you want to do:
public static Shape subtract(Shape shape1,
Shape shape2)
Returns a new Shape which is created by subtracting the specified second shape from the first shape.
The operation works with geometric areas occupied by the input shapes. For a single Shape such area includes the area occupied by the fill if the shape has a non-null fill and the area occupied by the stroke if the shape has a non-null stroke. So the area is empty for a shape with null stroke and null fill. The area of an input shape considered by the operation is independent on the type and configuration of the paint used for fill or stroke. Before the final operation the areas of the input shapes are transformed to the parent coordinate space of their respective topmost parent nodes.
The resulting shape will include areas that were contained only in the first shape and not in the second shape.
shape1 - shape2 = result
+----------------+ +----------------+ +----------------+
|################| |################| | |
|############## | | ##############| |## |
|############ | | ############| |#### |
|########## | | ##########| |###### |
|######## | | ########| |######## |
|###### | | ######| |###### |
|#### | | ####| |#### |
|## | | ##| |## |
+----------------+ +----------------+ +----------------+
Parameters:
shape1 - the first shape
shape2 - the second shape
Returns:
the created Shape
Source

Related

Raycast get local coordinates of hit of Plane

I have a plane with scale (64,1,36) and rotation is (90,-180,0) and need the local coordinate of a raycast hit in the 2d coordinates format:
(0,0)-------(64,0)
| |
| |
| |
(0,36)------(64,36)
with my current code:
RaycastHit hit;
Vector3 coords = new Vector3();
if (Physics.Raycast(GazeOriginCombinedLocal, GazeDirectionCombined, out hit, Mathf.Infinity))
{
if (!hit.transform.Equals("Cube"))
{
Pointer.transform.position = hit.point; //Green cube for visualization of hit in worldspace
// coords = RectTransformUtility.ScreenPointToLocalPointInRectangle(Plane, hit.point, Camera.main, out coords);// no result at all
}
}
Trying this:
hit.transform.InverseTransformPoint(hit.point)
gives me this
(5,-5)---(-5,-5)
| |
| (0,0) |
| |
(5,5)----(-5,5)
Does some have an idea to get the needed format?
Thats how my plane which is a child of the main camera and my hierarchy looks like:
Thanks in advance
I think you could use the Transform.InverseTransformPoint which
Transforms position from world space to local space.
And then since this also is affected by the scale multiple it again by the scale of the plane using Vector3.Scale.
So your coords should probably be something like
coords = hit.transform.localScale / 2f + Vector3.Scale(hit.transform.InverseTransformPoint(hit.point), hit.transform.localScale);
can't test it right now though since typing on smartphone. You might e.g. need to invert the y/z component according to your needs and depending how the plane is rotated etc. But I hope this gives you an idea
In order to debug what's wrong you should probably print out the values step by step
var scale = hit.transform.localScale; // 64, 1, 36
var halfScale = scale / 2f; // 32, 0.5, 18
var localHitPoint = hit.transform.InverseTransformPoint(hit.point);
Debug.Log($"{nameof(localHitPoint)}:{localHitPoint:0.000}");
So what I had expected originally here would be values like
(-0.5, 0.5, 0)----(0.5, 0.5, 0)
| |
| (0, 0, 0) |
| |
(-0.5, -0.5, 0)---(0.5, -0.5, 0)
BUT as you now added: Your plane is rotated!
The 90° on X actually makes that Y and Z switch places. So in order to get the desired Y coordinate you would rather read the localHitPoint.z.
Then the 180° on Y basically inverts both X and Z.
So I would now expect the values to look like
(0.5, 0, -0.5)----(-0.5, 0, -0.5)
| |
| (0, 0, 0) |
| |
(0.5, 0, 0.5)---(-0.5, 0, 0.5)
Which looks pretty much like the values you describe you are getting. Not sure though why you have a factor of 10 and why you didn't need to switch Y and Z.
However since you actually want the 0,0 to be in the top-left corner you only need to flip the X axis and use Z instead of Y so
fixedLocalHitPoint = new Vector2(-localHitPoint.x, localHitPoint.z);
Debug.Log($"{nameof(fixedLocalHitPoint)}:{fixedLocalHitPoint:0.000}");
Which should now give you values like
(-0.5, -0.5)----(0.5, -0.5)
| |
| (0, 0) |
| |
(-0.5, 0.5)----(0.5, 0.5)
And still you need to scale it up again
var scaledHitPoint = Vector2.Scale(fixedLocalHitPoint, new Vector2 (scale.x, scale.z));
Debug.Log($"{nameof(scaledHitPoint)}:{scaledHitPoint:0.000}");
Which should now give values like
(-32, -18)----(32, -18)
| |
| (0, 0) |
| |
(-32, 18)-----(32, 18)
That's why you need to add the center point as a reference
coords = new Vector2(halfScale.x, halfScale.z) + scaledHitPoint;
Debug.Log($"{nameof(coords)}:{coords:0.000}");
Which now should be
(0, 0)------(64, 0)
| |
| (32, 18) |
| |
(0, 36)-----(64, 36)
I hope this brings a bit more light into where these "strange" values come from.
Since your camera is scaled 1,1,1 and there is nothing else involved I have a hard time finding where the factor of 10 would have sneaked its way into the calculation to be honest.
If you want to convert this:
hit.transform.InverseTransformPoint(hit.point)
which gives this:
(5,-5)---(-5,-5)
| |
| (0,0) |
| |
(5,5)----(-5,5)
to this:
(0,0)-------(64,0)
| |
| |
| |
(0,36)------(64,36)
Why not do this:
Vector2.Scale(
hit.transform.InverseTransformPoint(hit.point) - new Vector2(5,-5),
new Vector2(-6.4, 3.6)
);
This answer hardcodes the (5,-5) and (-6.4, 3.6) terms because the question doesn't include enough information to use variables instead.
Assuming the scale of the parent of the plane (Main Camera) is (10,10), then this should suffice:
Vector3 planeScale = hit.transform.localScale;
Vector3 cameraScale = hit.transform.parent.localScale;
result = Vector2.Scale(
hit.transform.InverseTransformPoint(hit.point)
- new Vector2(cameraScale * 0.5f ,-cameraScale * 0.5f),
new Vector2(-planeScale.x * 0.5f/cameraScale.x, planeScale.y * 0.5f / cameraScale.y)
);

How to remove white annotations from image?

I try to remove the white annotations of this image (the numbers and arrows), as well as the black grid, with MATLAB:
I tried to compute, for each pixel, the mode of neighbors, but this process is very slow and I get poor results.
How can I obtain an image like this one?
Thank you for your time.
The general name for such a task is inpainting. If you search for that you will find better methods than what I'm showing here. This is no more than a proof of concept. I'm using DIPimage 3 (because I'm an author and it's easy for me to use).
First we need to create a mask for the regions that we want to remove (inpaint). It is easy to find pixels where all three channels have a high value (white) or a low value (black):
img = readim('https://i.stack.imgur.com/16r9N.png');
% Find a mask for the areas to remove
whitemask = min(img,'tensor') > 50;
blackmask = max(img,'tensor') < 30;
mask = whitemask | blackmask;
This mask doesn't capture all of the black grid, if we increase the threshold we will also remove the dark region of sea off the coast of Spain. And it also captures the white outline of the coasts. We can do a little bit better than this with some additional filtering:
% Find a mask for the areas to remove
whitemask = min(img,'tensor') > 50;
whitemask = whitemask - pathopening(whitemask,50);
blackmask = max(img,'tensor');
blackmask2 = blackmask < 80;
blackmask2 = blackmask2 - areaopening(blackmask2,6);
blackmask = blackmask < 30 | blackmask2;
mask = whitemask | blackmask;
This produces the following mask:
Still far from perfect, but a good start for our proof of concept.
One simple inpainting method uses normalized convolution: using the inverse of the mask we made, convolve the image multiplied by the mask, and convolve the mask separately. The ratio of these two results is a smoothed image that doesn't take the masked pixels into account. Finally, we replace the pixels in the original image under the mask with the values from this normalized convolution:
% Solution 1: normalized convolution
smooth = gaussf(img * ~mask, 2) / gaussf(~mask, 2);
img(mask) = smooth(mask);
An alternative solution applies a closing on the image multiplied by the mask (note that this multiplication makes the pixels we don't want completely black; the closing will spread the surrounding colors over the black areas):
% Solution 2: morphology
smooth = iterate('closing',img * ~mask, 13);
img(mask) = smooth(mask);

How to keep node from moving off of (outside of) another node

I have a few square-shaped nodes (like floor tiles) going along the screen and I'd like to restrict my player (P) node to moving within these nodes.
---------------------------------
| | P | | | | | | | <- Want no movement allowed
--------------------------------- outside of these squares.
| |
-------------
| | | | ...
-------------
I'm wondering if there's an elegant way to do this with SpriteKit Physics, that doesn't involve putting invisible blocks all the way around the floor.
Thanks!
An SKConstraint object describes a mathematical constraint on a node’s position or orientation.
You can use SKConstraint to keep a node a certain distance from a specific point in horizontal axis:
let center = size.width/2.0, difference = CGFloat(170.0)
let leftConstraint = SKConstraint.positionX(SKRange(constantValue: center - difference))
let rightConstraint = SKConstraint.positionX(SKRange(constantValue: center + difference))
player.constraints = [leftConstraint, rightConstraint]
You can also decide to enable or disable a certain constraint during the game:
leftConstraint.enabled = false
You use edge based physics bodies, not volume based physics bodies. So in your construction of the physics body, look for anything with edge in the constructor. Now, if you want to be able to walk between the tiles, you will have to create 1 physics body for the outer wall of your floor, because doing it tile by tile will mean you will be stuck in individual tiles.

How can I apply a LUT to tiles in leaflet

I have an image that is tiled that I display in leaflet. I would like the user to be able to select different options to apply pixel math on these tiles and then use look up table to display the corresponding color. Detailed example given below.
ex:
image name | pixel coordinate | RGB values
tile0.png | (0,0) | [100, 200, 200]
then the user will select option A which will do...R + G and divide by 2 then look up this value in a table to apply a new color.
(100 + 200) / 2 = 150. Use the look up table to find 150, it says change that pixel to [100, 100, 100]

Starling - squared tile map and positioning

I'm making a tile game in Action Script 3 / Starling.
Suppose I have a scenario like this:
+----+----+----+----+----+
| | | | | | 0th row - highest
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+
| | | | | | 3rd row - lowest
+----+----+----+----+----+
In this example, I have a 5x4 tile scenario. In a real gameplay I'll have a 100x100 tile scenario.
This squared map is for an RPG game, where each square could be occupied by an object or a character. Objects can be like trees, which are high and would hide the objects behind.
The key concept here is "hiding objects behind", and the greater is the row number, the "nearest" to the screen it will be, and if the row number is N, rows from 0 to N-1 will be hidden (actually "overlapped") by objects in the layer N (example: if a character is standing on position (x=1,y=2) having a height of 2, and a tree is standing at position (x=1,y=3), the tree would completely overlap the character "above".
I thought about a possible alternative:
If I have the current Starling sprite (which was created by Starling itself passing its class to the Starling constructor), and create one Sprite (sub-sprite) for each row, attaching it to the parent sprite:
private var rows:Vector.<Sprite> = null;
public function createMapRows(nRows:int) {
this.rows = new Vector.<Sprite>();
for(var r:int = 0; r < nRows; r++) {
this.addChild(new Sprite());
}
}
If a character moves left or right, it would remain on the same layer. If a character moves up, I could move the player from the Nth created sprite to the (N-1)th created sprite keeping its (X,Y) coordinates AND performing the 'move up' animation. If a character moves down, I could move the player from the Nth created sprite to the (N-1)th created sprite keeping its (X,Y) coordinates AND performing the 'move down' animation.
I believe this would work but I'm concerned about one aspect: performance.
My Question is: Is this the best way to accomplish this regarding memory performance? Or could be a better solution which does not involve the N+1* problem? (Actually, if the first question has a "NO" answer, I'd like an alternative).
(* No, it's not the N+1 problem regarding database records :p, but amount of sprites).
One thing is to make you'r own sprite instance for every row or just for the objects of that row.
I would do it like this:
The base Sprite object contains all the ground tiles cause there are always under everything else.
And on top of that I would make a Sprite filled with all the objects for that row.
Clouds
Row 0 objects
Row 1 objects
Row 2 objects <-- player is here at the moment
Row 3 objects
BaseLayer - ground tiles
And, like you mentioned before, if the player goes north or south just addChild the player Sprite so the right row Sprite.