Javafx path stroke width Lineto - path

I just did some tests with Path of JavaFX, and I observed a bug when I work with the LineTo :
Path border = GraphUtil.buildBorder(w, h, ARC_BORDER);
border.setStroke(Color.BLACK);
border.setStrokeWidth(0.3);
border.setOpacity(0.8);
With my utility method :
public class GraphUtil {
public static Path buildBorder(double w, double h, double arcBorder) {
//FIXME apply arcborder
Path border = new Path();
MoveTo mTo = new MoveTo();
mTo.setX(0);
mTo.setY(0);
LineTo lTop = new LineTo();
lTop.setX(w);
lTop.setY(0);
LineTo lRight = new LineTo();
lRight.setX(w);
lRight.setY(h);
LineTo lBottom = new LineTo();
lBottom.setX(0);
lBottom.setY(h);
LineTo lLeft = new LineTo();
lLeft.setX(0);
lLeft.setY(0);
border.getElements().addAll(mTo, lTop, lRight, lBottom, lLeft);
return border;
}
}
When I do that, it's ok. But when I want the strokewidth to be smaller (0.2 or 0.1), the left border is invisible, the other ones are visible.. Does someone know why?
Thanks.

Maybe same reason as this?
So your options for clean lines when you have an odd stroke width are:
Use a StrokeType.INSIDE or StrokeType.OUTSIDE stroke style.
Offset the co-ordinates of shapes by 0.5 of a pixel so that the strokes line up on the lines rather than the cracks between lines.
Just use the next even number up as the stroke width, e.g. 1 => 2, 3 => 4, etc.
JavaFX graphics "blurred" or anti-aliased? (No effects used)

Related

Drawing grid using CAShapeLayer

Long story short I want draw a diagonal grid on CALayerShape. My code instead of straight lines produces some kind of curved craziness. It looks very interesting and I wish it would be desired effect, but no, it's not.
My questions:
1. How can I draw straight lines using CAShapeLayer?
2. Did I discover some kind of black hole that affects gravity of pixels in my simulator?
func drawPath(_view:UIView, phase:CGFloat, segment:CGFloat){
// we need two runs
var height = CGRectGetHeight(view.frame)
let width = CGRectGetWidth(view.frame)
let segment:CGFloat = 40
var currentX:CGFloat = segment
var cgpath = CGPathCreateMutable()
for var y = height; y > 0 ; y = y - segment {
CGPathMoveToPoint(cgpath, nil, 0, y)
CGPathAddLineToPoint(cgpath, nil, currentX, 0)
CGPathCloseSubpath(cgpath)
currentX += segment
}
var layer = CAShapeLayer()
layer.path = cgpath
layer.strokeColor = UIColor.redColor().CGColor
layer.lineWidth = 1
layer.fillColor = UIColor.blackColor().CGColor
view.layer.addSublayer(layer)
}
What you've drawn is actually straight lines. The fact that it looks curved is an optical illusion. You can get this same effect with yarn and a piece of cardboard.
Your code is doing the wrong thing.
You need to map out the diagonal grid you want with graph paper, figure out the endpoints of your diagonal grid, and then come up with a loop that gives you those endpoints.
If you want to draw a diagonal grid in a 5x5 rectangle you'd draw lines like this:
0,1 to 1,0
0,2 to 2,0
0,3 to 3,0
0,4 to 4,0
Your grid spacing is probably more like 20 or 30 points than every point, and your whole grid is probably the full size of the screen, but you get the idea.

SpriteKit circle particle effect

In iOS SpriteKit. I am trying to create a sk particle emitter where the particle effect will be a circle with some radius r. Any ideas how to do that? Thanks!
The way I achieved this is by using the Color Ramp, starting with a color with zero opacity, to a color with 1% opacity near the end of the range and then having a third color with 100% opacity for the actual circle.
Here are the parameters I used:
Particles: 800, maximum:0
Lifetime: 1.1, range 0.2 (play with that and the location of the colors on the color ramp to set the radius)
position range: x=5, y=5 (not a must)
speed: 30 (should be around that value)
acceleration: x=10, y=10 (small values are good here)
alpha: start=0.3, range=1, speed: 0.1 (play with these)
One solution could be :
the particles of a SKEmitter have a position
all we have to do is to find where and how to change that position
where : in : override func update(_ currentTime: TimeInterval)
how : by : The parametric equation for a circle :
xx = cx + r * cos(a)
yy = cy + r * sin(a)
cx and cy = origin of the circle
r = radius
a: Int = angle : this variable must be a general variable in range 0...359 and reset to zero when it goes over 359
Do not use a for loop in update function but a = a + 1
myEmitter.particlePosition = CGPoint(x: xx, y: yy)
Easiest way is to use the Particle Emitter Editor. There are a couple of ways to achieve your goal. One of them is to change the Lifetime Start setting.
You can also set these values in code with the particleLifetime and particleLifetimeRange commands.

Avoid translation when scaling polynom and center to mouse position

in my application i have a polygon (with 4 points = rectangle) in a canvas. I want to scale the polygon by a factor by using the mouse wheel. For that i use this code:
double scale = 1.0, factor = 1.01, cX, cY;
void polygon_MouseWheel(object sender, MouseWheelEventArgs e)
{
cX = e.GetPosition(polygon).X;
cY = e.GetPosition(polygon).Y;
if (e.Delta > 0) scale *= factor;
else scale /= factor;
polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY);
}
This works fine, when i place the mousepointer to a point P (let's say P is a point near to the top left corner of the polygon) in the polygon and scroll up or down. So the polygon zooms in or out according to that point. But when i move the mouse pointer to an other point Q (near the bottom right corner) and continue zooming in or out, the polygon is shifted towards to top left corner by an amount s. It seems that the amount s depends on the distance between P and Q. So if the distance between P and Q is large, the shift is large.
The desired behaviour in this case is, that the polygon is not shifted, but just scaled to the new point Q.
Does anyone has an idea, whats the reason of the shift? I'm thankful for any hints.
Example code:
<window ...>
<Grid>
<Canvas Name="canvas1" Background="LightBlue">
<Polygon Points="100,100 100,300 300,300 300,100" Name="polygon" Fill="Black" MouseWheel="polygon_MouseWheel"/>
</Canvas>
</Grid>
</Window>
public MainWindow()
{
InitializeComponent();
}
double scale = 1.0, factor = 1.01, cX, cY;
void polygon_MouseWheel(object sender, MouseWheelEventArgs e)
{
cX = e.GetPosition(polygon).X;
cY = e.GetPosition(polygon).Y;
if (e.Delta > 0) scale *= factor;
else scale /= factor;
polygon.RenderTransform = new ScaleTransform(scale, scale, cX, cY);
}
Ok, after trying around a while i found out what causes this behaviour. The MSDN article of the UIElement.RenderTransform property says:
A render transform does not regenerate layout size or render size information. Render transforms are typically intended for animating or applying a temporary effect to an element. For example, the element might zoom when focused or moused over, or might jitter on load to draw the eye to that part of the user interface (UI).
That means, that the polygon itself, respectively the points of the polygon, isn't transformed. When applying the ScaleTransform the points of the polygon do not change and will remain as they were set in the xaml. Nevertheless the transformed polygon will react on mouse events, but the mouse position is mapped to the original bounds.
Example: Let's take the polygon, defined above in the xaml and scale it by factor 1.5. The polygon is displayed scaled and it seems that its points has the values (150,150 150,450 450,450 450,150) now. But internally it still has the old values (100,100 100,300 300,300 300,100). If you catch the position of the mouse pointer at the scaled top right corner, it will be (300,100) instead of (450,150).
Using the mouse position as center for the scaling causes the shift of the scaled polygon.
A solution for this is to scale the points of the polygon itself, instead of using ScaleTransform:
void Scale(double factor, double centerX, double centerY)
{
PointCollection pc = new PointCollection();
foreach (Point p in polygon.Points)
{
Point q = new Point();
q.X = p.X;
q.Y = p.Y;
q.X -= centerX; // translate
q.Y -= centerY;
q.X *= factor; // scale
q.Y *= factor;
q.X += centerX; // translate back
q.Y += centerY;
pc.Add(q);
}
polygon.Points = pc; // polygon is defined in xaml
}
I'm not sure if this is the right way to do it, but it works for me.

How to pick a line closest to the center on a grid?

I am drawing a simple grid, and I want the line closest to the center of the screen to be highlighted a different color.
What is the formula to determine what line was drawn that closely resembles the center of the screen?
It doesn't have to be the exact center, just one that appears to be in the middle of the screen. But it must be a line that was drawn. The user can change the size of the grid at anytime, so this line must move with it.
I am drawing a new line on the screen using a different stroke color, but I can't determine which line to overlap. I can get close but I am always off by a few pixels.
Take a look at this picture in Photoshop. The green line represents the true center of the image. While the pink line is the desired result (center line) because the grid isn't even to the screen size (look at the last grid on the right) The grid is 34x34 and the screen size is 320 x 480.
How to draw the grid:
int xStart = 0, yStart = 0;
int gsX = 19; //Distance between lines
int gsY = 25;
// draw vertical lines
for(int xId=0; xId<=(screenWidth/gsX); xId++) {
int x = xStart + xId * gsX;
[gPath moveToPoint:CGPointMake(x, yStart)];
[gPath addLineToPoint:CGPointMake(x, yStart+screenHeight)];
}
// draw horizontal lines
for(int yId=0; yId<=(screenHeight/gsY); yId++) {
int y = yStart + yId * gsY;
[gPath moveToPoint:CGPointMake(xStart, y)];
[gPath addLineToPoint:CGPointMake(xStart+screenWidth, y)];
}
My centerline code:
This moves the line based upon the grid spacing value, but it isn't drawn over one of the lines near the center.
int x = (screenWidth/gsX) /2;
NSLog(#"New X: %i gsX: %i",x, gsX);
//Veritical
[centerLines moveToPoint:CGPointMake(x, 0)];
[centerLines addLineToPoint:CGPointMake(x, screenHeight)];
Actually every one is right. I ran into something similar not to long ago actually. I couldn't explain it but it felt like the order of operations wasn't being followed correctly. So I broke your equation down so that you can follow the order of the operations. Any way your solution is as followed.
int centerX = (screenWidth/gsX);
int tempA = ( centerX / 2 );
int tempB = tempA * gsX;
NSLog(#"screenwidth / gsX = %i", centerX);
NSLog(#"Temp A: %i ", tempA);
NSLog(#"Temp B: %i ", tempB);
//Veritical
[centerLines moveToPoint:CGPointMake(tempB, 0)];
[centerLines addLineToPoint:CGPointMake(tempB, screenHeight)];
Here's whats happening. You're already drawing this line at one point in your grid code. You just have to figure out which one it is.You know that screenWidth/gsX is the last "line that will be drawn. So that number divided by 2 is the middle line. It's already a factor of the screenSize. Then just multiply that number by how big your grid is. Since it is the 'middle line' closest to the center (screenWidth/gsX) your line should show up on top of the grid
That should always draw a middle line. I don't see any code where you are changing the color. So you will have to take it on blind faith that it is being drawn. If you can change your line color you should be able to see it.
I'll leave it to you to figure out horizontal. (hint: it deals with y value ;-) )
I hope this helps!
Have fun and good luck Mr. Bourne!
Center is
int centerX = ((screenWidth/2) / gsX )* gsX;
int centerY = ((screenHeight/2) / gsY ) * gsY;
Just make sure you are doing integer math above! no floats. It should work out fine.
int x = xStart + (screenWidth/gsX)/2 * gsX;

move a sprite to match borders of a circle in xna

i'm trying to build a game in xna, i got a circle which i want the player to move around it, as you can see in the following picture, its working great except the drawing part which i'm not pleased with
here's a link to an image http://s12.postimage.org/poiip0gtp/circle.png
i want to center the player object to the edge of the circle so it won't look like the player is standing on air
this is how i calculate the position of the player
rad = (degree * Math.PI / 180);
rotationDegree = (float)((Math.PI * degree) / 180);
currentPosition.X = (float)(Math.Cos(rad) * Earth.radius + (GraphicsDevice.Viewport.Width / 2));
currentPosition.Y = (float)(Math.Sin(rad) * Earth.radius + (GraphicsDevice.Viewport.Height / 2));
and this is how i draw the player
spriteBatch.Draw(texture,currentPosition, null, Color.White,rotationDegree, Vector2.Zero,1f,SpriteEffects.None, 1f);
thank you.
Use the origin overload for spritebatch. Which is where the sprite is drawn according to the position.
Spritebatch.Draw(texture,Position, null,Color.White,0f,new Vector2(texture.Width / 2,texture.Height /2),1f,SpriteEffects.None, 0);
Using texture.Width / 2,texture.Height /2 for origin will center it.
It looks like what you want to do here is adjust the sprite's origin, which is the vector that you're passing into SpriteBatch.Draw(). This is used to determine the "center point" of your sprite; {0, 0} represents the sprite's upper-left corner, while {spriteWidth, spriteHeight} represents the bottom-right corner. Your sprite will be positioned and rotated relative to this origin.

Resources