I have written a method to resize an array in Java:
public HUD resize(float factor){
int[] array = new int[(int)Math.pow(pixels.length * factor, 2)];//Create new array
for(int y = 0; y < height; ++y){
for(int x = 0; x < width; ++x){
array[(int)((x * 2) + (y * 2) * width * factor)] = pixels[x + y * width];
array[(int)((x * 2 + 1) + (y * 2) * width * factor)] = pixels[x + y * width];
array[(int)((x * 2) + (y * 2 + 1) * width * factor)] = pixels[x + y * width];
array[(int)((x * 2 + 1) + (y * 2 + 1) * width * factor)] = pixels[x + y * width];
}
}
pixels = array;
width = (int)(width * factor);
height = (int)(height * factor);
return this;
}
This method is only called once and an OutOfMemoryError is given out whenever its called
Increasing the heap size of your application may prevent the OutOfMemoryError. This post on SO explains how to do this.
Related
I have an assignment on CodeHS to program a calculator for the surface area of a pyramid and it prints out the wrong surface area off by a few decimals. I don't see how this is incorrect (code below).
I've already tried plugging in the formula from Google for surface area and it did not work and printed the wrong number.
public double surfaceArea() {
double hw = (double)width/2;
double hl = (double)length/2;
double slantHeight1 = ((double)Math.sqrt( (double)height*height +
(double)hw*hw ));
double slantHeight2 = ((double)Math.sqrt( (double)height*height + (double)hl*hl ));
return (double)(((double)0.5 * 2 * slantHeight1 * width)
+ ((double)0.5 * 2 * slantHeight2 * length)
+ (length * width));
Example: for a pyramid with length 1, width 3, and height 5 it is supposed to print 23.29 but it prints 23.69 and I don't know why?
Another alternative solution: this is the equation for surface area of a right rectangular pyramid:
This can be simply written as:
public static void main(String[] args) {
double length = 1;
double width = 3;
double height = 5;
double resultPyramidArea = (length * width) + (length * Math.sqrt(Math.pow(width / 2, 2) +
Math.pow(height, 2))) + (width * Math.sqrt(Math.pow(length / 2, 2) + Math.pow(height, 2)));
System.out.println(resultPyramidArea);
}
change this:
return (double)(((double)0.5 * 2 * slantHeight1 * width)
+ ((double)0.5 * 2 * slantHeight2 * length)
+ (length * width));
to this:
return (double)(((double)0.5 * 2 * slantHeight1 * length)
+ ((double)0.5 * 2 * slantHeight2 * width)
+ (length * width));
you got the formula wrong
How I can add vertex data (float[]) to a Vector3f list? It gives me an error if I try.
float[] vertexData = new float[ allindices2.length * vertexDataSize / 3];
for (int i = 0; i < vertexData.length / vertexDataSize; i++){
vertexData[i * vertexDataSize + 0] = Float.parseFloat(allindices2 [Integer.parseInt(allindices2 [i * source.size() + 0]) * 3 + 0]);
vertexData[i * vertexDataSize + 1] = Float.parseFloat(allpositions2[Integer.parseInt(allindices2[i * source.size() + 0]) * 3 + 1]);
vertexData[i * vertexDataSize + 2] = Float.parseFloat(allpositions2[Integer.parseInt(allindices2[i * source.size() + 0]) * 3 + 2]);
vertices.add(vertexData);
}
If you don't need the vertexData array for any other reason, you should not create it at all. Instead, you can directly create the required Vector3f instances.
for (int i = 0; i < vertexData.length / vertexDataSize; i++){
float x = Float.parseFloat(allindices2 [Integer.parseInt(allindices2[i * source.size() + 0]) * 3 + 0]);
float y = Float.parseFloat(allpositions2[Integer.parseInt(allindices2[i * source.size() + 0]) * 3 + 1]);
float z = Float.parseFloat(allpositions2[Integer.parseInt(allindices2[i * source.size() + 0]) * 3 + 2]);
vertices.add(new Vector3f(x,y,z));
}
Nevertheless, all these parse... calls and the general structure look highly dubious. Unless you obtain this data directly from a file or so, you should consider a different data model.
Additionally:
Are you sure that the first allindices2 should not be allpositions2?
There's no need to do work twice. You can pull out the computation of the index.
Most likely, the code could also be written as
for (int i = 0; i < vertexData.length / vertexDataSize; i++){
int index = Integer.parseInt(allindices2[i * source.size()]);
float x = Float.parseFloat(allpositions2[index * 3 + 0]);
float y = Float.parseFloat(allpositions2[index * 3 + 1]);
float z = Float.parseFloat(allpositions2[index * 3 + 2]);
vertices.add(new Vector3f(x,y,z));
}
I'm looking to convert OS Grid Reference to longitude and latitude, I'm using the jcoord library in Android studio, http://www.jstott.me.uk/jcoord/
I'm interested how I would connect this to a button that on on activity you can type in a grid reference on a edit text, and click convert (Which will do the magic formula) and will show the longitude and latitude below?
Basically I want to make a user interface, with being able to test this on my phone
I believe the formula will be done in the OSRef.java, with the code being the following:
public class OSRef extends Activity implements View.OnClickListener {
EditText osGridNumber;
View convertButton;
TextView latLongBox;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
convertButton = findViewById(R.id.cmdConvert);
convertButton.setOnClickListener(this);
osGridNumber = (EditText) findViewById(R.id.edtOS);
latLongBox = (TextView) findViewById(R.id.txtLngLat);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.cmdConvert:
break;
}
}
/**
* Easting
*/
private double easting;
/**
* Northing
*/
private double northing;
/**
* Create a new Ordnance Survey grid reference.
*
* #param easting the easting in metres
* #param northing the northing in metres
* #since 1.0
*/
public OSRef(double easting, double northing) {
this.easting = easting;
this.northing = northing;
}
/**
* Take a string formatted as a six-figure OS grid reference (e.g. "TG514131")
* and create a new OSRef object that represents that grid reference. The
* first character must be H, N, S, O or T. The second character can be any
* uppercase character from A through Z excluding I.
*
* #param ref a String representing a six-figure Ordnance Survey grid reference
* in the form XY123456
* #throws IllegalArgumentException if ref is not of the form XY123456
* #since 1.0
*/
public OSRef(String ref) throws IllegalArgumentException {
// if (ref.matches(""))
char char1 = ref.charAt(0);
char char2 = ref.charAt(1);
// Thanks to Nick Holloway for pointing out the radix bug here
int east = Integer.parseInt(ref.substring(2, 5)) * 100;
int north = Integer.parseInt(ref.substring(5, 8)) * 100;
if (char1 == 'H') {
north += 1000000;
} else if (char1 == 'N') {
north += 500000;
} else if (char1 == 'O') {
north += 500000;
east += 500000;
} else if (char1 == 'T') {
east += 500000;
}
int char2ord = char2;
if (char2ord > 73)
char2ord--; // Adjust for no I
double nx = ((char2ord - 65) % 5) * 100000;
double ny = (4 - Math.floor((char2ord - 65) / 5)) * 100000;
easting = east + nx;
northing = north + ny;
}
/**
* Return a String representation of this OSGB grid reference showing the
* easting and northing.
*
* #return a String represenation of this OSGB grid reference
* #since 1.0
*/
public String toString() {
return "(" + easting + ", " + northing + ")";
}
/**
* Return a String representation of this OSGB grid reference using the
* six-figure notation in the form XY123456
*
* #return a String representing this OSGB grid reference in six-figure
* notation
* #since 1.0
*/
public String toSixFigureString() {
int hundredkmE = (int) Math.floor(easting / 100000);
int hundredkmN = (int) Math.floor(northing / 100000);
String firstLetter;
if (hundredkmN < 5) {
if (hundredkmE < 5) {
firstLetter = "S";
} else {
firstLetter = "T";
}
} else if (hundredkmN < 10) {
if (hundredkmE < 5) {
firstLetter = "N";
} else {
firstLetter = "O";
}
} else {
firstLetter = "H";
}
int index = 65 + ((4 - (hundredkmN % 5)) * 5) + (hundredkmE % 5);
// int ti = index;
if (index >= 73)
index++;
String secondLetter = Character.toString((char) index);
int e = (int) Math.floor((easting - (100000 * hundredkmE)) / 100);
int n = (int) Math.floor((northing - (100000 * hundredkmN)) / 100);
String es = "" + e;
if (e < 100)
es = "0" + es;
if (e < 10)
es = "0" + es;
String ns = "" + n;
if (n < 100)
ns = "0" + ns;
if (n < 10)
ns = "0" + ns;
return firstLetter + secondLetter + es + ns;
}
/**
* Convert this OSGB grid reference to a latitude/longitude pair using the
* OSGB36 datum. Note that, the LatLng object may need to be converted to the
* WGS84 datum depending on the application.
*
* #return a LatLng object representing this OSGB grid reference using the
* OSGB36 datum
* #since 1.0
*/
public LatLng toLatLng() {
double OSGB_F0 = 0.9996012717;
double N0 = -100000.0;
double E0 = 400000.0;
double phi0 = Math.toRadians(49.0);
double lambda0 = Math.toRadians(-2.0);
double a = RefEll.AIRY_1830.getMaj();
double b = RefEll.AIRY_1830.getMin();
double eSquared = RefEll.AIRY_1830.getEcc();
double phi = 0.0;
double lambda = 0.0;
double E = this.easting;
double N = this.northing;
double n = (a - b) / (a + b);
double M = 0.0;
double phiPrime = ((N - N0) / (a * OSGB_F0)) + phi0;
do {
M =
(b * OSGB_F0)
* (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n)) * (phiPrime - phi0))
- (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))
* Math.sin(phiPrime - phi0) * Math.cos(phiPrime + phi0))
+ ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))
* Math.sin(2.0 * (phiPrime - phi0)) * Math
.cos(2.0 * (phiPrime + phi0))) - (((35.0 / 24.0) * n * n * n)
* Math.sin(3.0 * (phiPrime - phi0)) * Math
.cos(3.0 * (phiPrime + phi0))));
phiPrime += (N - N0 - M) / (a * OSGB_F0);
} while ((N - N0 - M) >= 0.001);
double v =
a * OSGB_F0
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -0.5);
double rho =
a * OSGB_F0 * (1.0 - eSquared)
* Math.pow(1.0 - eSquared * Util.sinSquared(phiPrime), -1.5);
double etaSquared = (v / rho) - 1.0;
double VII = Math.tan(phiPrime) / (2 * rho * v);
double VIII =
(Math.tan(phiPrime) / (24.0 * rho * Math.pow(v, 3.0)))
* (5.0 + (3.0 * Util.tanSquared(phiPrime)) + etaSquared - (9.0 * Util
.tanSquared(phiPrime) * etaSquared));
double IX =
(Math.tan(phiPrime) / (720.0 * rho * Math.pow(v, 5.0)))
* (61.0 + (90.0 * Util.tanSquared(phiPrime)) + (45.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double X = Util.sec(phiPrime) / v;
double XI =
(Util.sec(phiPrime) / (6.0 * v * v * v))
* ((v / rho) + (2 * Util.tanSquared(phiPrime)));
double XII =
(Util.sec(phiPrime) / (120.0 * Math.pow(v, 5.0)))
* (5.0 + (28.0 * Util.tanSquared(phiPrime)) + (24.0 * Util
.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
double XIIA =
(Util.sec(phiPrime) / (5040.0 * Math.pow(v, 7.0)))
* (61.0
+ (662.0 * Util.tanSquared(phiPrime))
+ (1320.0 * Util.tanSquared(phiPrime) * Util
.tanSquared(phiPrime)) + (720.0 * Util.tanSquared(phiPrime)
* Util.tanSquared(phiPrime) * Util.tanSquared(phiPrime)));
phi =
phiPrime - (VII * Math.pow(E - E0, 2.0))
+ (VIII * Math.pow(E - E0, 4.0)) - (IX * Math.pow(E - E0, 6.0));
lambda =
lambda0 + (X * (E - E0)) - (XI * Math.pow(E - E0, 3.0))
+ (XII * Math.pow(E - E0, 5.0)) - (XIIA * Math.pow(E - E0, 7.0));
return new LatLng(Math.toDegrees(phi), Math.toDegrees(lambda));
}
/**
* Get the easting.
*
* #return the easting in metres
* #since 1.0
*/
public double getEasting() {
return easting;
}
/**
* Get the northing.
*
* #return the northing in metres
* #since 1.0
*/
public double getNorthing() {
return northing;
}
}
Thanks in advance
I'm trying to rotate a Bitmap where the pixels are stored in an Array int pixels[]. I got the following method:
public void rotate(double angle) {
double radians = Math.toRadians(angle);
double cos, sin;
cos = Math.cos(radians);
sin = Math.sin(radians);
int[] pixels2 = pixels;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
int centerx = this.width / 2, centery = this.height / 2;
int m = x - centerx;
int n = y - centery;
int j = (int) (m * cos + n * sin);
int k = (int) (n * cos - m * sin);
j += centerx;
k += centery;
if (!((j < 0) || (j > this.width - 1) || (k < 0) || (k > this.height - 1)))
try {
pixels2[(x * this.width + y)] = pixels[(k * this.width + j)];
} catch (Exception e) {
e.printStackTrace();
}
}
pixels = pixels2;
}
But it just gives me crazy results. Does anyone know where the error is?
The line
int[] pixels2 = pixels;
is supposed to copy the array, but you are just copying the reference to it. Use pixels.clone(). In fact, you just need a new, empty array, so new int[pixels.lenght] is enough. In the end you need System.arraycopy to copy the new content into the old array.
There are other problems in your code -- you are mixing up rows and columns. Some expressions are written as though the image is stored row by row, others as if column by column. If row-by-row (my assumption), then this doesn't make sense: x*width + y. It should read y*width + x -- you are skipping y rows down and then moving x columns to the right. All in all, I have this code that works OK:
import static java.lang.System.arraycopy;
public class Test
{
private final int width = 5, height = 5;
private int[] pixels = {0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0};
public Test rotate(double angle) {
final double radians = Math.toRadians(angle),
cos = Math.cos(radians), sin = Math.sin(radians);
final int[] pixels2 = new int[pixels.length];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
final int
centerx = this.width / 2, centery = this.height / 2,
m = x - centerx,
n = y - centery,
j = ((int) (m * cos + n * sin)) + centerx,
k = ((int) (n * cos - m * sin)) + centery;
if (j >= 0 && j < width && k >= 0 && k < this.height)
pixels2[(y * width + x)] = pixels[(k * width + j)];
}
arraycopy(pixels2, 0, pixels, 0, pixels.length);
return this;
}
public Test print() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
System.out.print(pixels[width*y + x]);
System.out.println();
}
System.out.println();
return this;
}
public static void main(String[] args) {
new Test().print().rotate(-45).print();
}
}
public void render(float nx, float ny, float nz, float size, float rotate) {
int wid = (int) ((width - nz) * size);
int hgt = (int) ((height - nz) * size);
if (wid < 0 || hgt < 0) {
wid = 0;
hgt = 0;
}
for (int x = 0; x < wid; x++) {
for (int y = 0; y < hgt; y++) {
double simple = Math.PI;
int xp = (int) (nx +
Math.cos(rotate) * ((x / simple) - (wid / simple) / 2) + Math
.cos(rotate + Math.PI / 2)
* ((y / simple) - (hgt / simple) / 2));
int yp = (int) (ny + Math.sin(rotate)
* ((x / simple) - (wid / simple) / 2) + Math.sin(rotate
+ Math.PI / 2)
* ((y / simple) - (hgt / simple) / 2));
if (xp + width < 0 || yp + height < 0 || xp >= Main.width
|| yp >= Main.height) {
break;
}
if (xp < 0
|| yp < 0
|| pixels[(width / wid) * x + ((height / hgt) * y)
* width] == 0xFFFF00DC) {
continue;
}
Main.pixels[xp + yp * Main.width] = pixels[(width / wid) * x
+ ((height / hgt) * y) * width];
}
}
}
This is only a new to rotating for me, but the process of this is that of a normal rotation. It still needs much fixing -- it's inefficient and slow. But in a small program, this code works. I'm posting this so you can take it, and make it better. :)
Here is the scenario:
// getMatrix() returns int[]. It is 1-d
// I wish it was 2d.
int[] mat = MyMatrix.getMatrix();
// get height and width of the matrix;
int h = MyMatrix.height;
int w = MyMatrix.width;
// calculate the center index of the matrix
int c = ... // need help here
// manipulate the center element of the matrix.
SomeClass.foo(mat[c]);
Example: Suppose I have a 5 x 5 matrix:
* * * * * // index 0 to 4
* * * * * // index 5 to 9
* * * * * // index 10 to 14.
* * * * * // index 15 to 19
* * * * * // index 20 to 24
If getMatrix() were to return int[][], the center coordinate of this matrix would be (2,2) 0-index based. But since getMatrix() returns int[], the center coordinate index c is 12.
However, if the height or width of the matrix is even, the center index can one of its 2 or 4 centers as shown in a 6 x 6 matrix:
* * * * * *
* * * * * *
* * # # * *
* * # # * *
* * * * * *
* * * * * *
--> The center is any of the # above.
How would I calculate for the center index c of an m x n matrix?
The center of the matrix is the center of the array. This is because there will be an equal number of rows above and below the center row. And on the center row, there will be an equal number of cells to the left and right of the center cell.
int c = mat.length / 2;
or, if you want:
int c = (width * height) / 2;
This assumes that there is a single center of the matrix. That is, there is an odd number of rows and columns.
If you want the median (mean of all centers), it will become more complicated:
int x1 = (width - 1)/2;
int x2 = width/2;
int y1 = (height - 1)/2;
int y2 = height/2;
double median = (mat[width*y1 + x1] + mat[width*y1 + x2] +
mat[width*y2 + x1] + mat[width*y2 + x2])*0.25;
If you only need one of the center cells, pick one of the four combinations of x1,x2,y1,y2. Simplest would be:
int c = width * (height / 2) + (width / 2); // lower right center