I need some help with a project I'm working on the side to help me in my physics and chemistry class.
This is the code that I have produced so far and it seems to give me an answer that are incorrect for all trials I have given it. All help is appreciated!
public double sinSinUnknown(double opp, double hyp)
{
double sin = 0;
sin = Math.asin((opp / hyp));
return sin;
}
public double sinOppUnknown(double sin, double hyp)
{
double opp = 0;
opp = Math.sin(sin) * hyp;
return opp;
}
public double sinHypUnknown(double sin, double opp)
{
double hyp = 0;
hyp = opp / Math.sin(sin);
return hyp;
}
public double cosCosUnknown(double adj, double hyp)
{
double cos = 0;
cos = Math.acos((adj / hyp));
return cos;
}
public double cosAdjUnknown(double cos, double hyp)
{
double adj = 0;
adj = hyp * Math.cos(cos);
return adj;
}
public double cosHypUnknown(double cos, double adj)
{
double hyp = 0;
hyp = adj / Math.cos(cos);
return hyp;
}
public double tanTanUnknown(double opp, double adj)
{
double tan = 0;
tan = Math.atan((opp / adj));
return tan;
}
public double tanOppUnknown(double tan, double adj)
{
double opp = 0;
opp = adj * Math.tan(tan);
return opp;
}
public double tanAdjUnknown(double tan, double opp)
{
double adj = 0;
adj = opp / Math.tan(tan);
return adj;
}
}
The trigonometric functions in java.lang.Math require inputs in radians, rather than degrees. This can be done using the toRadians function.
You'll need to convert your answers back to degrees, using the toDegrees function.
public double sinSinUnknown(double opp, double hyp)
{
double sin = 0;
sin = Math.asin((Math.toRadians(opp) / Math.toRadians(hyp)));
return Math.toDegrees(sin);
}
Related
I've been working on a project lately that creates procedurally generated terrain which uses 3d simplex noise as well as the Marching cubes algorithm. I am currently running it on my cpu which takes around 10-20 seconds to render a 200x200x200 terrain which isn't optimal if I want to make the world infinite. Is there any way to improve the speed which the terrain renders or is this the maximum speed I can achieve. (I've already tried using compute shaders but limitations with GLSL didn't allow me to pursue that idea.)
Terrain Generation Code
package Terrain;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import Entities.Entity;
import Maths.Vector3f;
import Models.RawModel;
import Render.Loader;
public class Terrain {
private int width = 200, height = 2, interval = 8;
private float x,y,z = 2f;
private int x1,y1,z1;
private Loader loader;
private List<Entity> cubes = new ArrayList<Entity>();
private RawModel model;
private double perlin2DScale = 0.01, perlin3DScale = 0.01;//, maskScale = 0.00;
private double perlin3Dratio = 0.8;// ratio of 3d noise to 2d;
private double amp = 1; //height of mountains
List<Vector3f> verticeArray = new ArrayList<Vector3f>();
float[][][] terrainMap = new float[width+1][height+1][width+1];
float[] SimplexMap3D = new float[(width+1)*(height+1)*(width+1)];
float[] SimplexMap2D = new float[(width+1)*(width+1)];
private float surfaceLevel = 1f;
int seed;
//SimplexComputeBuffer compute = new SimplexComputeBuffer();
public Terrain(float x, float z, Loader loader){
this.loader = loader;
this.x1 = (int) (x*width);
this.z1 = (int) (z*width);
this.x = x*width*interval;
this.z = z*width*interval;
Random rand = new Random();
seed = rand.nextInt(100000);
loadMarchingTerrain();
}
public void changeAmp(double i){
x+=i;
System.out.println("amp ="+amp);
verticeArray.clear();
loadMarchingTerrain();
}
public void changeSurface(double i){
surfaceLevel+=i;
System.out.println("surface ="+surfaceLevel);
verticeArray.clear();
loadMarchingTerrain();
}
public void loadMarchingTerrain(){
for(int x = x1; x<x1+width+1; x++){
for(int y = y1; y<y1+height+1; y++){
for(int z = z1; z<z1+width+1; z++){
double noise3d = this.sumOctaves(4,x,y,z,0.5,perlin3DScale,0,1); // creates 3d terrain like caves and overhangs
double noise2d = this.sumOctaves(4,x,z,0.5,perlin2DScale,0,1); // creates 2d terrain like mountains and hills (gives only height)
//double mask = this.sumOctaves(1,x,z,0.5,maskScale,0,1); // creates a 2d mask to vary heights of regions
float curHeight = (float)height*(float)(noise2d*(1-perlin3Dratio)+noise3d*perlin3Dratio); // mixing them together with correct ratio of 3d and 2d data
terrainMap[x-x1][y-y1][z-z1] = (float)-y+curHeight;
}
}
}
for(int x = 0; x<width; x++){
for(int y = 0; y<height; y++){
for(int z = 0; z<width; z++){
marchCube(new Vector3f(x,y,z));
}
}
}
float[] vertices = new float[verticeArray.size()*3];
int[] indice = new int[verticeArray.size()];
int vertexCount = 0;
for(Vector3f v : verticeArray){
vertices[vertexCount++] =v.x*interval;
vertices[vertexCount++] =v.y*interval;
vertices[vertexCount++] =v.z*interval;
}
for(int i = 0; i<indice.length; i++){
indice[i] = i;
}
model = loader.loadToVao(vertices, null, indice);
}
public int configIndex(float[] cube){
int configIndex = 0;
for(int i = 0; i<8; i++){
if(cube[i] > surfaceLevel){
configIndex |= 1 << i;
}
}
return configIndex;
}
public float sampleTerrain(Vector3f point){
return terrainMap[(int) point.x][(int) point.y][(int) point.z];
}
public Vector3f smoothPoint(Vector3f vert1, Vector3f vert2, int indice, float[] cube){
float sampleVert1 = cube[MarchingCubeTable.edges[indice][0]];
float sampleVert2 = cube[MarchingCubeTable.edges[indice][1]];
float difference = sampleVert1-sampleVert2;
if(difference == 0){
difference = surfaceLevel;
}else{
difference = (surfaceLevel-sampleVert1)/difference;
}
Vector3f a2 = vert1.subtract(vert2).scale(difference);
Vector3f vertPos = vert1.add(a2);
return vertPos;
}
public void marchCube(Vector3f position){
//create cube
float[] cube = new float[8];
for(int i = 0; i<8; i++){
Vector3f corner = position.add(MarchingCubeTable.cornerTable[i]);
cube[i] = terrainMap[(int) corner.x][(int) corner.y][(int) corner.z];
}
//search through index
int currentConfigIndex = configIndex(cube);
if(currentConfigIndex == 0 || currentConfigIndex == 255){
return;
}
//search through points
int edgeIndex = 0;
for(int j = 0; j<5; j++){
for(int i = 0; i<3; i++){
int indice = MarchingCubeTable.getIndex(currentConfigIndex)[edgeIndex];
if(indice == -1){
return;
}
Vector3f vert2 = position.add(MarchingCubeTable.cornerTable[MarchingCubeTable.edges[indice][0]]);
Vector3f vert1 = position.add(MarchingCubeTable.cornerTable[MarchingCubeTable.edges[indice][1]]);
Vector3f vertPos = this.smoothPoint(vert1, vert2, indice, cube);
verticeArray.add(vertPos);
edgeIndex++;
}
}
}
/*
* Simplex Noise functions
*/
public double sumOctaves(int iterations, double x, double y, double z, double persistance, double scale, double low, double high){
double maxamp = 0;
double amp = this.amp;
double frequency = scale;
double noise = 0;
for(int i = 0; i<iterations; i++){
noise += SimplexNoise.noise((x)*frequency, (y)*frequency, (z)*frequency)*amp;
maxamp += amp;
amp *= persistance;
frequency *= 2;
}
noise /= maxamp;
noise = noise * (high - low) / 2 + (high + low) / 2;
return noise;
}
public double sumOctaves(int iterations, int x, int y, double persistance, double scale, double low, double high){
double maxamp = 0;
double amp = this.amp;
double frequency = scale;
double noise = 0;
for(int i = 0; i<iterations; i++){
noise += SimplexNoise.noise((x)*frequency, (y)*frequency)*amp;
maxamp += amp;
amp *= persistance;
frequency *= 2;
}
noise /= maxamp;
noise = noise * (high - low) / 2 + (high + low) / 2;
return noise;
}
public List<Entity> getCubes(){
return cubes;
}
public float getX() {
return x;
}
public float getZ() {
return z;
}
public float getY() {
return y;
}
public RawModel getRawModel(){
return model;
}
}
I have an infinite map generator. It works well with positive coordinates.
Positive coordinates generation 1
But on negative coordinates I have this trash:
Negative coordinates broken generation
2
void generateChunk(int x0, int y0) {
Chunk chunk = new Chunk(x0, y0);
for(int yTile = 0; yTile < Chunk.CHUNK_SIZE; yTile++) {
for(int xTile = 0; xTile < Chunk.CHUNK_SIZE; xTile++) {
int pX = chunk.x0 + xTile;
int pY = chunk.y0 + yTile;
double perlinNoiseHeight = floorPerlinNoise.getHeight(pX, pY);;
if(perlinNoiseHeight > BEACH_AREA) {
chunk.setFloor(GrassTile.ID, xTile, yTile);
} else if(perlinNoiseHeight > 0) {
chunk.setFloor(SandTile.ID, xTile, yTile);
} else {
chunk.setFloor(WaterTile.ID, xTile, yTile);
}
}
}
saveChunk(chunk);
}
Perlin noise class:
package org.ixnomad.game.level.generation;
public class PerlinNoise {
private double persistence, frequency, amplitude;
private int octaves;
private long seed;
public PerlinNoise(double persistence, double frequency, double amplitude, int octaves, long seed) {
this.persistence = persistence;
this.amplitude = amplitude;
this.frequency = frequency;
this.octaves = octaves;
this.seed = seed;
}
public double getHeight(double x, double y) {
return amplitude * total(x, y) + 0.4;
}
private double total(double i, double j) {
double total = 0.0d;
double _ampl = 1;
double _freq = frequency;
for(int k = 0; k < octaves; k++) {
total += getValue(j * _freq + seed, i * _freq + seed) * _ampl;
_ampl *= persistence;
_freq *= 2;
}
return total;
}
private double getValue(double x, double y) {
int xInt = (int) x;
int yInt = (int) y;
double xFrac = x - xInt;
double yFrac = y - yInt;
double n01 = noise(xInt-1, yInt-1);
double n02 = noise(xInt+1, yInt-1);
double n03 = noise(xInt-1, yInt+1);
double n04 = noise(xInt+1, yInt+1);
double n05 = noise(xInt-1, yInt );
double n06 = noise(xInt+1, yInt );
double n07 = noise(xInt , yInt-1);
double n08 = noise(xInt , yInt+1);
double n09 = noise(xInt , yInt );
double n12 = noise(xInt+2, yInt-1);
double n14 = noise(xInt+2, yInt+1);
double n16 = noise(xInt+2, yInt );
double n23 = noise(xInt-1, yInt+2);
double n24 = noise(xInt+1, yInt+2);
double n28 = noise(xInt , yInt+2);
double n34 = noise(xInt+2, yInt+2);
double x0y0 = 0.0625*(n01+n02+n03+n04) + 0.125*(n05+n06+n07+n08) + 0.25*(n09);
double x1y0 = 0.0625*(n07+n12+n08+n14) + 0.125*(n09+n16+n02+n04) + 0.25*(n06);
double x0y1 = 0.0625*(n05+n06+n23+n24) + 0.125*(n03+n04+n09+n28) + 0.25*(n08);
double x1y1 = 0.0625*(n09+n16+n28+n34) + 0.125*(n08+n14+n06+n24) + 0.25*(n04);
double v1 = interpolate(x0y0, x1y0, xFrac);
double v2 = interpolate(x0y1, x1y1, xFrac);
return interpolate(v1, v2, yFrac);
}
private double interpolate(double x, double y, double frac) {
double negFrac = 1.0 - frac;
double negFraqSqr = negFrac * negFrac;
double fac1 = 3.0 * negFraqSqr - 2.0 * negFraqSqr * negFrac;
double fracSqr = frac * frac;
double fac2 = 3.0 * fracSqr - 2.0 * fracSqr * frac;
return x * fac1 + y * fac2;
}
private double noise(int x, int y) {
int n = x + y * 57;
n = (n << 13) ^ n;
int t = (n * (n * n * 15713 + 789221) + 1376312589) & 0x7fffffff;
return 1.0d - (double) (t * 0.931322574615478515625e-9);
}
}
I have tried to solve this problem for a whole day, but I don't know, what I'm doing wrong. I thought that the problem is in bit shift (private double noise(double x, double y)), but the problem doesn't depend on it.
I tried to use this Perlin's algoryth: https://mrl.nyu.edu/~perlin/noise/
But effect is the same.
Good morning, I probably have solved the problem :D Jush should sleep and reload brains)
Just use the max value the integer can bring and move generate coordinates to half :D
int maxint = 0x07fffffff;
double perlinNoiseHeight = floorPerlinNoise.getHeight(pX + (maxint >> 1), pY + (maxint >> 1));
That is a simple solution, but it works)
Negative coordinates
I have an arrayList of markers and I want to find the closest marker to my current location.
I had no idea how to find that marker so I searched and found same problem in here.
Google Maps Api v3 - find nearest markers
then I tried to convert those code to java but it doesn't work now.
closest doesn't change and always it is -1.
Is there any better solution for this problem or I can make the following code usable?
public void findNearMarker(){
double pi = Math.PI;
int R = 6371; //equatorial radius
double[] distances = new double[2];
double d = 0;
int i;
int closest = -1;
for ( i = 0; i == markerArrayList.size(); i++){
double lat2 = markerArrayList.get(i).getPosition().latitude;
double lon2 = markerArrayList.get(i).getPosition().longitude;
double chLat = lat2 - currentLocation.getLatitude();
double chLon = lon2 - currentLocation.getLongitude();
double dLat = chLat*(pi/180);
double dLon = chLon*(pi/180);
double rLat1 = currentLocation.getLatitude()*(pi/180);
double rLat2 = lat2 * (pi/180);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2)
* Math.sin(dLon /2) * Math.cos(rLat1) * Math.cos(rLat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
d = R * c;
distances[i] = d;
if (closest == -1 || d< distances[closest]){
closest = i;
}
}
}
first you need to import the location class of the android sdk
import android.location.Location;
ArrayList<Marker> markers = new ArrayList<>();
markers = sortListbyDistance(markers, currentLocation.getLocation());
public static ArrayList<Marker> sortListbyDistance(ArrayList<Marker> markers, final LatLng location){
Collections.sort(markers, new Comparator<Marker>() {
#Override
public int compare(Marker marker2, Marker marker1) {
//
if(getDistanceBetweenPoints(marker1.getLocation(),location)>getDistanceBetweenPoints(marker2.getLocation(),location)){
return -1;
} else {
return 1;
}
}
});
return markers;
}
public static float getDistanceBetweenPoints(double firstLatitude, double firstLongitude, double secondLatitude, double secondLongitude) {
float[] results = new float[1];
Location.distanceBetween(firstLatitude, firstLongitude, secondLatitude, secondLongitude, results);
return results[0];
}
and to get the nearest marker just get first item in markers, cheers :)
If you follow
Comparing two locations using their Longitude and Latitude
/** calculates the distance between two locations in MILES */
private double distance(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // in miles, change to 6371 for kilometer output
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist; // output distance, in MILES
}
loop through your list with this function and get the lowest return value.
You can also use the Maps API
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
locationB.setLongitude(lngB);
float distance = locationA.distanceTo(locationB);
This is my code:
private final static double[] multipliers = {
1.0, 1.0936133, 0.001, 0.000621371192
};
private final static String[] unitstrings = {
"m", "y", "km", "mi"
};
private void updateMeasurement() {
double distance = calcGeoDistance(startLat, startLon, currentLat, currentLon) * multipliers[unitindex];
String distanceText = "" + RoundDecimal(distance, 2) + " " + unitstrings[unitindex];
((TextView)findViewById(R.id.distance)).setText(distanceText);
}
private double calcGeoDistance(final double lat1, final double lon1, final double lat2, final double lon2)
{
double distance = 0.0;
try
{
final float[] results = new float[3];
Location.distanceBetween(lat1, lon1, lat2, lon2, results);
distance = (double)results[0];
}
catch (final Exception ex)
{
distance = 0.0;
}
return distance;
}
I get 8310 km even when I shake the mobile.
public float distanceFrom(float lat1, float lng1, float lat2, float lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) *Math.cos(Math.toRadians(lat2)) * Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Float(dist * meterConversion).floatValue();
}
Are you using Long and Lat in degrees of the correct format? It would help to see the values you are passing in
double startLatitude = pointStart.getLatitudeE6() / DEG_RATE;
double startLongitude= pointStart.getLongitudeE6() / DEG_RATE;
double endLatitude = pointEnd.getLatitudeE6() / DEG_RATE;
double endLongitude= pointEnd.getLongitudeE6() / DEG_RATE;
float[] result = new float[1];
Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, result);
Where pointStart and pointEnd are com.google.android.maps.GeoPoint
Reference -
http://www.java2s.com/Code/Android/Core-Class/GetDistancebetweentwoGeoPoint.htm
I implemented the "bearing" formula from http://www.movable-type.co.uk/scripts/latlong.html. But it seems highly inaccurate - I suspect some mistakes in my implementation. Could you help me with finding it? My code is below:
protected static double bearing(double lat1, double lon1, double lat2, double lon2){
double longDiff= lon2-lon1;
double y = Math.sin(longDiff)*Math.cos(lat2);
double x = Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(longDiff);
return Math.toDegrees((Math.atan2(y, x))+360)%360;
}
Here is the final code:
protected static double bearing(double lat1, double lon1, double lat2, double lon2){
double longitude1 = lon1;
double longitude2 = lon2;
double latitude1 = Math.toRadians(lat1);
double latitude2 = Math.toRadians(lat2);
double longDiff= Math.toRadians(longitude2-longitude1);
double y= Math.sin(longDiff)*Math.cos(latitude2);
double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
return (Math.toDegrees(Math.atan2(y, x))+360)%360;
}
You just have your parentheses () in the wrong place.
You are adding degrees to a value in radians, which won't work. toDegrees() will do the conversion from radians to degrees for you, then you do the normalisation once you have a value in degrees.
You have:
Math.toDegrees( (Math.atan2(y, x))+360 ) % 360;
But you need:
( Math.toDegrees(Math.atan2(y, x)) + 360 ) % 360;
Remember also that all inputs to Math.sin(), Math.cos() and all the other trigonometric functions must be in radians. If your inputs are degrees you'll need to convert them using Math.toRadians() first.
Bearing from one coordinate to another And Find North,East,south,weast :)
public class FindBearing {
public static void main(String[] args) {
System.out.println(" Your Result >>> "+FindBearing.bearing(19.2859590, 73.4966430, 19.2861020, 73.4988090));
}
protected static String bearing(double lat1, double lon1, double lat2, double lon2){
double longitude1 = lon1;
double longitude2 = lon2;
double latitude1 = Math.toRadians(lat1);
double latitude2 = Math.toRadians(lat2);
double longDiff= Math.toRadians(longitude2-longitude1);
double y= Math.sin(longDiff)*Math.cos(latitude2);
double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
double resultDegree= (Math.toDegrees(Math.atan2(y, x))+360)%360;
String coordNames[] = {"N","NNE", "NE","ENE","E", "ESE","SE","SSE", "S","SSW", "SW","WSW", "W","WNW", "NW","NNW", "N"};
double directionid = Math.round(resultDegree / 22.5);
// no of array contain 360/16=22.5
if (directionid < 0) {
directionid = directionid + 16;
//no. of contains in array
}
String compasLoc=coordNames[(int) directionid];
return resultDegree+" "+compasLoc;
}
}
A little bit cleaned up version of #IvanT answer:
public static double bearingInRadians(LatLng src, LatLng dst) {
double srcLat = Math.toRadians(src.getLatitude());
double dstLat = Math.toRadians(dst.getLatitude());
double dLng = Math.toRadians(dst.getLongitude() - src.getLongitude());
return Math.atan2(Math.sin(dLng) * Math.cos(dstLat),
Math.cos(srcLat) * Math.sin(dstLat) -
Math.sin(srcLat) * Math.cos(dstLat) * Math.cos(dLng));
}
public static double bearingInDegrees(LatLng src, LatLng dst) {
return Math.toDegrees((bearingInRadians(src, dst) + Math.PI) % Math.PI);
}
Where LatLng is:
public final class LatLng {
private final double latitude;
private final double longitude;
public LatLng(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
}