I need to create an animation which it will make a full circle around another button.
Can i achieve this using classic animations?
Example giving many translates inside an xml file, with specific offset each one? Or i need to create a specific path for this? I'm new in java so i don't know how to start.
Please check image Below:
You need to understand some trigonometric functions.
/**
* #static
* Allows move in circles around given item
* #param r {float|int} radius in px
* #param angle {float|int} current angle between circle center and orbiting element
* #param orbit {object} orbiting el eg. $("#foo")
* #param speed {int} animation's speed
* #param [middle=$('#menubutton')] {object} middle of the circle
*/
static fMenu(r, angle, orbit, speed, middle = Menu.BUTTON) {
const BY = middle.position().top;
const BX = middle.offset().left;
const k = middle.width();
const KY = middle.height();
if (angle === 0) {
angle = 360;
}
const x = Math.cos(angle * Math.PI / 180) * r;
const y = Math.tan(Math.PI * angle / 180) * x;
$(orbit).animate({
top: (BY - y - KY / 2) + "px",
left: (BX + x + k / 2 - orbit.width() / 2) + "px",
opacity: "1"
}, speed);
}
And you shoud do it in loop or setTimeout/setInterval. I've made this code some time ago for jQuery, but you get the idea? - Most important are lines with Math.cos and Math.tan.
Related
I wrote a function that takes the subpixels of an image for the purpose of upscaling, and the subpixel is generated by bilinear interpolation, but I am having some weird artifacts.
Here is my code:
public static int getSubPixel(BufferedImage bi, double x, double y) {
float[] topleft = new Color(bi.getRGB((int) Math.floor(x), (int) Math.floor(y))).getColorComponents(null);
float[] topright = new Color(bi.getRGB(Math.min(bi.getWidth() - 1, (int) Math.ceil(x)), (int) Math.floor(y))).getColorComponents(null);
float[] bottomleft = new Color(bi.getRGB((int) Math.floor(x), Math.min(bi.getHeight() - 1, (int) Math.ceil(y)))).getColorComponents(null);
float[] bottomright = new Color(bi.getRGB(Math.min(bi.getWidth() - 1, (int) Math.ceil(x)), Math.min(bi.getHeight() - 1, (int) Math.ceil(y)))).getColorComponents(null);
for (int i = 0; i < 3; i++) {
topleft[i] *= topleft[i];
topright[i] *= topright[i];
bottomleft[i] *= bottomleft[i];
bottomright[i] *= bottomright[i];
}
double decX = x % 1;
double decY = y % 1;
double inv_DecX = 1 - decX;
double inv_DecY = 1 - decY;
float red = (float) Math.sqrt((topleft[0] * inv_DecX + topright[0] * decX) * inv_DecY + (bottomleft[0] * inv_DecX + bottomright[0] * decX) * decY);
float green = (float) Math.sqrt((topleft[1] * inv_DecX + topright[1] * decX) * inv_DecY + (bottomleft[1] * inv_DecX + bottomright[1] * decX) * decY);
float blue = (float) Math.sqrt((topleft[2] * inv_DecX + topright[2] * decX) * inv_DecY + (bottomleft[2] * inv_DecX + bottomright[2] * decX) * decY);
return new Color(red, green, blue).getRGB();
}
This is the result of scaling up a 16x16 image 20 times:
As you can see, there is weird streaking going on. I did go out of my way to square the colors before averaging, then taking the square root of the result, but something does not seem right here. Any insight?
PS: I understand functions already exist to do this. This is an educational exercise. I am trying to understand the process by doing it on my own.
The stripe artifacts that you are seeing are caused by the linear interpolation scheme. Your implementation is correct (except for the squaring, which is unnecessary and causes the stripes to be stronger in darker regions of the image). This is what I'm seeing with a correct linear interpolation (16x instead of 20x as in the OP, I goofed) but without squaring (note less stripes in the dark blue parts):
If you want to get rid of the stripes, use a better interpolation scheme, such as cubic spline interpolation:
I'm trying to add some distance (e.g. 10px) between a segment (arc) of the pie chart and it's center without success, here's what i've tried so far:
int value = 20; // example
double arcAngle = (value * 360 / 100);
double angle = 360 - (arcAngle / 2); // direction to add the distance to (center of arc)
double newX = pieCenterX + Math.cos(angle * Math.PI / 180.0) * 10;
double newY = pieCenterY + Math.sin(angle * Math.PI / 180.0) * 10;
// then drawing the arc with new x and y
g.fill(new Arc2D.Double(newX, newY, bounds.getWidth(), bounds.getHeight(), startAngle, arcAngle, Arc2D.PIE));
Ideally i should end up with something like that:
I don't know much on how to approach this, so my code was taken from examples i found elsewhere.
Usually zero angle is OX direction (right). So you have to make correction by 90 degrees (if your coordinate system is counterclockwise)
double angle = 90 + 360 - (arcAngle / 2);
I have a vector called, say, ship which every frame I need to set to a certain rotation around another vector called center. Here's a picture to show what I mean.
As you can see, I'd like to be able to rotate ship to any rotation around center, preferably in a function with 2 Vector2 parameters for the positions and then a float for the rotation (in degrees).
The mathematical functions to rotate a point around another point are:
double new_x = current_x * Math.cos(angle) - current_y * Math.sin(angle);
double new_y = current_x * Math.sin(angle) + current_y * Math.cos(angle);
if your center isn't at (0,0), you should first substract it at the current values, then add them again at the end like so:
double new_x = (current_x-center_x) * Math.cos(angle) - (current_y-center_y) * Math.sin(angle) + center_x;
double new_y = (current_x-center_x) * Math.sin(angle) + (current_y-center_y) * Math.cos(angle) + center_y;
Beware, your angle should be in radians and not in degrees, a easy conversion happens like so:
double angle = Math.toRadians(degrees);
Hope this helped!
I have a circle being drawn at a certain position. I can move it just fine with speed set to 10f but when it starts to circle it becomes extremely fast. Its obviously not moving at (units/second) I'm not sure whats going on. I thought that the archSpeed needed to be in radians or something, that slowed it down - still not right though.
Here's the Circle Arc Equation I'm basing off of:
s = r * theta
Here are the functions I'm using:
private void moveOut(double deltaTime)
{
SetPosition(x += direction * speed * deltaTime, y, 0);
if (x - (direction * GetWidth() / 2f) >= centerX + radius + GetWidth() / 2f)
{
//onOutside = true;
}
Log.d(TAG, "moving out");
}
private void circleCenter(double deltaTime)
{
float angleSpeed = (float) (radius * (speed * Math.PI / 180) * deltaTime);
currentAngle += angleSpeed;
if (currentAngle >= 2 * Math.PI)
{
currentAngle = (float) (2 * Math.PI - currentAngle);
}
SetPosition(centerX + radius * FloatMath.cos(currentAngle), centerY + radius * FloatMath.sin(currentAngle), 0);
}
Your angleSpeed formula looks wrong.
I'd work it out first by saying What is the distance I travel in that time. The answer as you already know is speed*deltaTime. Now you have a distance you can work out the angle by using the arc forumla that says arclength = radius*angle. So angle = arclength/radius.
Put these two together to get
angle = speed*deltaTime/radius
This will be in radians of course.
Essentially this boils down to the fact you were multiplying by radius instead of dividing by it (looking at it in terms of units would have helped spot this but that is outside the scope of a programming forum).
I searched about a day now, but didnt find any example for my problem in Javacode.
I have a worldmap with a size of 2000*1400 Pixels with a 'Mollweide' projection.
How can I find out what is the longitude and laltitude of the point (500,300) in my map ?
I would like to code this in Java.
I tried to do this with the 'Java Map Projection Library' :
Point2D.Double pointonmap = null;
Point2D.Double latlon = null;
MolleweideProjection molproj=new MolleweideProjection();
pointonmap = new Point2D.Double (1400,1000);
latlon=molproj.inverseTransform(pointonmap,new Point2D.Double ());
System.out.println("latlon: " + latlon.getX() + ", " + latlon.getY());
Could anyone help me with that ? Codeexample or hint.
thanks and regards
Wikipedia has most of the information you need:
These formulas assume a few things, as usual.
They speak in projected dimension, which is smaller than the component.
[0,0] is at the centre, not top left.
Y coordinate goes up rather than goes down.
And the result is in radius instead of degree.
Fix these and they'll work for you.
Since you didn't provide a link, I assume you are using the Java Map Projection Library on GitHub.
Without documentation and with limited time, I can't understand inverseTransform well enough to fix your code; but the bundled MapComponent is simpler to code:
map.addMouseListener( new MouseAdapter() { #Override public void mouseClicked( MouseEvent e ) {
double x = e.getX() - map.getWidth() / 2, // Mouse X with [0,0] at centre.
y = e.getY() - map.getHeight() / 2, // Mouse Y with [0,0] at centre.
// Max Y of projected map, in pixel with [0,0] at centre.
maxY = map.getMapExtension().getMaxY() * map.getScaleToShowAll(),
sqrt2 = Math.sqrt( 2 ), // Can be optimised away, but let's be faithful.
R = maxY / sqrt2, // Radius of projection, in pixel.
theta = Math.asin( y / ( R * sqrt2 ) );
int delta_long = -lon0Slider.getValue(); // Longtitude shift from -180 to 180.
// Find lat long in radius and converts to degree.
double latInRad = Math.asin( -( 2 * theta + Math.sin( 2 * theta ) ) / Math.PI ),
latitude = Math.toDegrees( latInRad ),
longInRad = Math.PI * x / ( 2 * R * sqrt2 * Math.cos( theta ) ),
longitude = Math.toDegrees( longInRad ) + delta_long;
System.out.println( "Lat: " + latitude + ", Long: " + longitude );
}
You can paste this code into the constructor of ch.ethz.karto.gui.ProjectionSelectionPanel.
The IDE should reports that two methods of the map is private, and you need to change them to public first (or use reflection).
Then launch it, select Mollweide, click on the globe and watch the console. Feel free to resize the window.
This answer uses information from the English Wikipedia entry on Mollweide projection. I've pretty much transcribed the formula from there verbatim.
The short answer, so you can write your own code:
Get the map's radius, r:
projectionWidth /(2 * √2)
Get theta, the point's angle along the map:
arcsine(y / (r * √2))
Note: Arcsine is the inverse of sine. Use Math.asin(a) in java
Get the latitude:
arcsine((2 * theta + sine(2 * theta)) / PI)
Get the longitude:
PI * x / (2 * R * √2 * cosine(theta)) + central meridian.
Or you can copyPasta this.
It's not very efficient; x and y are spec as doubles becaus too lazy to write typecast avoid narrowing
no-setters no-getters all-vars public
all-world-one-love Dr. Bronner's TV-dinners solve your problems for you
and stuff
enoj
public class MolleweidePoint
{
public double x, y, latitude, longitude;
public MolleweidePoint(double projectionWidth, double x, double y)
{
double rootTwo = Math.sqrt(2);
double r = projectionWidth / 2 / rootTwo;
double theta = Math.asin(y / r / rootTwo);
this.x = x;
this.y = y;
longitude = Math.PI * x / 2 / r / rootTwo / Math.cos(theta);
latitude = Math.asin(2 * theta + Math.sin(2 * theta) / Math.PI);
}
}
After calling the constructor like
MolleweidePoint ted = new MolleweidePoint(projection.width, 300, 500)
you can get the latitude and longitude from ted.longitude and ted.latitude. Also, longitude may have to be adjusted based on where the central meridian is placed on your projection.