How to draw the middle half of a sphere (in code) - java

I'm trying to create the middle half of a sphere. Basically to create a sphere, stack numbers and slice numbers are given, and there are two variables phi (for slices) and theta (for stacks) responsible for how much to progress. And the process is divided into creating bottom cap, body, and top cap (as seen below). To achieve middle half (theta of middle 50% as below), we need to omit the caps, and somehow modify the body. I was playing around with stack numbers (1/4*stackNumbers to 3/4*stackNumbers) but didn't give the result I wanted.
How should I modify the sphere generation to achieve the middle half (pi/4 <theta <pi*3/4)? My overall problem is how can I split the sphere into 3 different parts upper 25%, middle 50%, and bottom 25%? (25% in terms of angle, i.e. theta)
Here is the popular code for generating a sphere programmatically:
private void generateSphere(int stackNumber, int sliceNumber, boolean facingOut) {
int capVertexNumber = 3 * sliceNumber;
int bodyVertexNumber = 4 * sliceNumber * (stackNumber - 2);
int vertexNumber = (2 * capVertexNumber) + bodyVertexNumber;
int triangleNumber = (2 * capVertexNumber) + (6 * sliceNumber * (stackNumber - 2));
vertices = new float[3 * vertexNumber];
normals = new float[3 * vertexNumber];
texCoords = new float[2 * vertexNumber];
indices = new char[triangleNumber];
// bottom cap
// createCap(stackNumber, sliceNumber, false, facingOut);
// body
createBody(stackNumber, sliceNumber, facingOut);
// top cap
createCap(stackNumber, sliceNumber, true, facingOut);
}
private void createCap(int stackNumber, int sliceNumber, boolean top, boolean facingOut) {
float stackPercentage0;
float stackPercentage1;
if (!top) {
stackPercentage0 = ((float) (stackNumber - 1) / stackNumber);
stackPercentage1 = 1.0f;
} else {
stackPercentage0 = (1.0f / stackNumber);
stackPercentage1 = 0.0f;
}
float t0 = stackPercentage0;
float t1 = stackPercentage1;
double theta0 = stackPercentage0 * Math.PI;
double theta1 = stackPercentage1 * Math.PI;
double cosTheta0 = Math.cos(theta0);
double sinTheta0 = Math.sin(theta0);
double cosTheta1 = Math.cos(theta1);
double sinTheta1 = Math.sin(theta1);
for (int slice = 0; slice < sliceNumber; slice++) {
float slicePercentage0 = ((float) (slice) / sliceNumber);
float slicePercentage1 = ((float) (slice + 1) / sliceNumber);
double phi0 = slicePercentage0 * 2.0 * Math.PI;
double phi1 = slicePercentage1 * 2.0 * Math.PI;
float s0, s1;
if (facingOut) {
s0 = 1 - slicePercentage0;
s1 = 1 - slicePercentage1;
} else {
s0 = slicePercentage0;
s1 = slicePercentage1;
}
float s2 = (s0 + s1) / 2.0f;
double cosPhi0 = Math.cos(phi0);
double sinPhi0 = Math.sin(phi0);
double cosPhi1 = Math.cos(phi1);
double sinPhi1 = Math.sin(phi1);
float x0 = (float) (sinTheta0 * cosPhi0);
float y0 = (float) cosTheta0;
float z0 = (float) (sinTheta0 * sinPhi0);
float x1 = (float) (sinTheta0 * cosPhi1);
float y1 = (float) cosTheta0;
float z1 = (float) (sinTheta0 * sinPhi1);
float x2 = (float) (sinTheta1 * cosPhi0);
float y2 = (float) cosTheta1;
float z2 = (float) (sinTheta1 * sinPhi0);
vertices[vertexCount + 0] = x0;
vertices[vertexCount + 1] = y0;
vertices[vertexCount + 2] = z0;
vertices[vertexCount + 3] = x1;
vertices[vertexCount + 4] = y1;
vertices[vertexCount + 5] = z1;
vertices[vertexCount + 6] = x2;
vertices[vertexCount + 7] = y2;
vertices[vertexCount + 8] = z2;
if (facingOut) {
normals[vertexCount + 0] = x0;
normals[vertexCount + 1] = y0;
normals[vertexCount + 2] = z0;
normals[vertexCount + 3] = x1;
normals[vertexCount + 4] = y1;
normals[vertexCount + 5] = z1;
normals[vertexCount + 6] = x2;
normals[vertexCount + 7] = y2;
normals[vertexCount + 8] = z2;
} else {
normals[vertexCount + 0] = -x0;
normals[vertexCount + 1] = -y0;
normals[vertexCount + 2] = -z0;
normals[vertexCount + 3] = -x1;
normals[vertexCount + 4] = -y1;
normals[vertexCount + 5] = -z1;
normals[vertexCount + 6] = -x2;
normals[vertexCount + 7] = -y2;
normals[vertexCount + 8] = -z2;
}
texCoords[texCoordCount + 0] = s0;
texCoords[texCoordCount + 1] = t0;
texCoords[texCoordCount + 2] = s1;
texCoords[texCoordCount + 3] = t0;
texCoords[texCoordCount + 4] = s2;
texCoords[texCoordCount + 5] = t1;
if ((facingOut && top) || (!facingOut && !top)) {
indices[indexCount + 0] = (char) (triangleCount + 1);
indices[indexCount + 1] = (char) (triangleCount + 0);
indices[indexCount + 2] = (char) (triangleCount + 2);
} else {
indices[indexCount + 0] = (char) (triangleCount + 0);
indices[indexCount + 1] = (char) (triangleCount + 1);
indices[indexCount + 2] = (char) (triangleCount + 2);
}
vertexCount += 9;
texCoordCount += 6;
indexCount += 3;
triangleCount += 3;
}
}
private void createBody(int stackNumber, int sliceNumber, boolean facingOut) {
for (int stack = 1; stack < stackNumber - 1; stack++) {
float stackPercentage0 = ((float) (stack) / stackNumber);
float stackPercentage1 = ((float) (stack + 1) / stackNumber);
float t0 = stackPercentage0;
float t1 = stackPercentage1;
double theta0 = stackPercentage0 * Math.PI;
double theta1 = stackPercentage1 * Math.PI;
double cosTheta0 = Math.cos(theta0);
double sinTheta0 = Math.sin(theta0);
double cosTheta1 = Math.cos(theta1);
double sinTheta1 = Math.sin(theta1);
for (int slice = 0; slice < sliceNumber; slice++) {
float slicePercentage0 = ((float) (slice) / sliceNumber);
float slicePercentage1 = ((float) (slice + 1) / sliceNumber);
double phi0 = slicePercentage0 * 2.0 * Math.PI;
double phi1 = slicePercentage1 * 2.0 * Math.PI;
float s0, s1;
if (facingOut) {
s0 = 1.0f - slicePercentage0;
s1 = 1.0f - slicePercentage1;
} else {
s0 = slicePercentage0;
s1 = slicePercentage1;
}
double cosPhi0 = Math.cos(phi0);
double sinPhi0 = Math.sin(phi0);
double cosPhi1 = Math.cos(phi1);
double sinPhi1 = Math.sin(phi1);
float x0 = (float) (sinTheta0 * cosPhi0);
float y0 = (float) cosTheta0;
float z0 = (float) (sinTheta0 * sinPhi0);
float x1 = (float) (sinTheta0 * cosPhi1);
float y1 = (float) cosTheta0;
float z1 = (float) (sinTheta0 * sinPhi1);
float x2 = (float) (sinTheta1 * cosPhi0);
float y2 = (float) cosTheta1;
float z2 = (float) (sinTheta1 * sinPhi0);
float x3 = (float) (sinTheta1 * cosPhi1);
float y3 = (float) cosTheta1;
float z3 = (float) (sinTheta1 * sinPhi1);
vertices[vertexCount + 0] = x0;
vertices[vertexCount + 1] = y0;
vertices[vertexCount + 2] = z0;
vertices[vertexCount + 3] = x1;
vertices[vertexCount + 4] = y1;
vertices[vertexCount + 5] = z1;
vertices[vertexCount + 6] = x2;
vertices[vertexCount + 7] = y2;
vertices[vertexCount + 8] = z2;
vertices[vertexCount + 9] = x3;
vertices[vertexCount + 10] = y3;
vertices[vertexCount + 11] = z3;
if (facingOut) {
normals[vertexCount + 0] = x0;
normals[vertexCount + 1] = y0;
normals[vertexCount + 2] = z0;
normals[vertexCount + 3] = x1;
normals[vertexCount + 4] = y1;
normals[vertexCount + 5] = z1;
normals[vertexCount + 6] = x2;
normals[vertexCount + 7] = y2;
normals[vertexCount + 8] = z2;
normals[vertexCount + 9] = x3;
normals[vertexCount + 10] = y3;
normals[vertexCount + 11] = z3;
} else {
normals[vertexCount + 0] = -x0;
normals[vertexCount + 1] = -y0;
normals[vertexCount + 2] = -z0;
normals[vertexCount + 3] = -x1;
normals[vertexCount + 4] = -y1;
normals[vertexCount + 5] = -z1;
normals[vertexCount + 6] = -x2;
normals[vertexCount + 7] = -y2;
normals[vertexCount + 8] = -z2;
normals[vertexCount + 9] = -x3;
normals[vertexCount + 10] = -y3;
normals[vertexCount + 11] = -z3;
}
texCoords[texCoordCount + 0] = s0;
texCoords[texCoordCount + 1] = t0;
texCoords[texCoordCount + 2] = s1;
texCoords[texCoordCount + 3] = t0;
texCoords[texCoordCount + 4] = s0;
texCoords[texCoordCount + 5] = t1;
texCoords[texCoordCount + 6] = s1;
texCoords[texCoordCount + 7] = t1;
// one quad looking from outside toward center
//
// #formatter:off
//
// s1 --> s0
//
// t0 1-----0
// | | |
// v | |
// t1 3-----2
//
// #formatter:on
//
// Note that tex_coord t increase from top to bottom because the
// texture image is loaded upside down.
if (facingOut) {
indices[indexCount + 0] = (char) (triangleCount + 0);
indices[indexCount + 1] = (char) (triangleCount + 1);
indices[indexCount + 2] = (char) (triangleCount + 2);
indices[indexCount + 3] = (char) (triangleCount + 2);
indices[indexCount + 4] = (char) (triangleCount + 1);
indices[indexCount + 5] = (char) (triangleCount + 3);
} else {
indices[indexCount + 0] = (char) (triangleCount + 0);
indices[indexCount + 1] = (char) (triangleCount + 2);
indices[indexCount + 2] = (char) (triangleCount + 1);
indices[indexCount + 3] = (char) (triangleCount + 2);
indices[indexCount + 4] = (char) (triangleCount + 3);
indices[indexCount + 5] = (char) (triangleCount + 1);
}
vertexCount += 12;
texCoordCount += 8;
indexCount += 6;
triangleCount += 4;
}
}
}

The code here is using spherical coordinates to calculate the sphere. theta is the variable that represents the up/down coordinate that you're interested in, and theta goes from 0 to PI. You want to go from PI/4 to 3PI/4. stackNumbers simply represent the number of divisions in the sphere, since you can see that it is used as a denominator for stack, which is the wrong variable to change. So you can make the following changes to the code instead. From:
double theta0 = stackPercentage0 * Math.PI;
double theta1 = stackPercentage1 * Math.PI;
to:
double startTheta = Math.PI / 4;
double endTheta = 3 * Math.PI / 4;
double theta0 = stackPercentage0 * (endTheta - startTheta) + startTheta;
double theta1 = stackPercentage1 * (endTheta - startTheta) + startTheta;
And since you aren't using the caps you need to change the start and end stack numbers to reflect that:
for (int stack = 1; stack < stackNumber - 1; stack++) { // old
for (int stack = 0; stack < stackNumber; stack++) { // new
Also, you because you have more body faces now, you need to update the appropriate container for them. Replace (stackNumber - 2) with (stackNumber - 1).

Related

How can I add this float[] vertexData to a Vector3f list?

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));
}

Three random points on a circle

I'm trying to create a program where three random points in a circle are created and result in the creation of an inscribed triangle. However, the angles I'm getting are all screwed up
Here is my code:
public static void main(String[] args) {
double r = 40.0;
double angle1 = Math.random()* (2 * Math.PI);
double angle2 = Math.random()* (2 * Math.PI);
double angle3 = Math.random()* (2 * Math.PI);
double x_1 = r * Math.cos(angle1);
double y_1 = r * Math.sin(angle1);
double x_2 = r * Math.cos(angle2);
double y_2 = r * Math.sin(angle2);
double x_3 = r * Math.cos(angle3);
double y_3 = r * Math.sin(angle3);
System.out.println("The coordinates of the three points are:
(" + x_1 + ", " + y_1 + ")
(" + x_2 + ", " + y_2 + ")
(" + x_3 + ", " + y_3 + ")");
//Get length of each side
double distanceFrom1To2 = Math.sqrt(Math.pow(x_2 - x_1, 2) +
Math.pow(y_2 - y_1, 2));
double distanceFrom2To3 = Math.sqrt(Math.pow(x_3 - x_2, 2) +
Math.pow(y_3 - y_2, 2));
double distanceFrom3To1 = Math.sqrt(Math.pow(x_1 - x_3, 2) +
Math.pow(y_1 - y_3, 2));
//Get angles ***
double triangleAngle1 = Math.atan(distanceFrom1To2 / distanceFrom2To3);
double triangleAngle2 = Math.atan(distanceFrom2To3 / distanceFrom3To1);
double triangleAngle3 = Math.atan(distanceFrom3To1 / distanceFrom1To2);
System.out.println("The three angles are " + triangleAngle1 + " " +
triangleAngle2 + " " + triangleAngle3);
System.out.println(triangleAngle1 + triangleAngle2 + triangleAngle3);
}
I definitely know that the means of getting the angles are screwed up. Here is a sample run of my program:
The coordinates of the three points are: (5.224534224725408,
-39.65733528787168) (-29.696946087404676, 26.79722733944279)
(32.70889681040468, -23.02451018906371)
The three angles are 0.7545364726122026 1.18830825410364
0.40435068059871415
Total angle sum: 2.347195407314557
The angles all add up to much greater than Pi / 2 radians. I've considered the law of sines but you have to know at least one angle for that...
Figured it out
Here is the fixed code:
//Get length of each side
double a = Math.sqrt(Math.pow(x_2 - x_1, 2) + Math.pow(y_2 - y_1, 2)); // distance from 1 to 2
double b = Math.sqrt(Math.pow(x_3 - x_2, 2) + Math.pow(y_3 - y_2, 2)); // distance from 2 to 3
double c = Math.sqrt(Math.pow(x_1 - x_3, 2) + Math.pow(y_1 - y_3, 2)); // distance from 3 to 1
//Get angles ***
double triangleAngle1 = Math.acos((Math.pow(a, 2) + Math.pow(b, 2) - Math.pow(c, 2)) / (2 * a * b));
double triangleAngle2 = Math.acos((Math.pow(b, 2) + Math.pow(c, 2) - Math.pow(a, 2)) / (2 * c * b));
double triangleAngle3 = Math.acos((Math.pow(c, 2) + Math.pow(a, 2) - Math.pow(b, 2)) / (2 * a * c));
I changed it to use the law of cosines.

Why is a Java function so much slower than a JSNI function?

I compared the performance of two functions doing downscaling on a canvas image. It turns out that the Java function is so much slower than the JSNI function. That is strange because I would assume that the GWT compiler optimizes the code that it become at least as fast as the JSNI code.
Here is the Java function:
public static final CanvasElement scaleCanvas(CanvasElement cv, double scale) {
if (!(scale < 1) || !(scale > 0)) {
GWT.log("scale must be a positive number <1");
// throw new Exception("scale must be a positive number <1 ");
}
GWT.log("scaleCanvas start");
double sqScale = scale * scale; // square scale = area of source pixel within target
int sw = cv.getWidth(); // source image width
int sh = cv.getHeight(); // source image height
double tw = Math.ceil(sw * scale); // target image width
double th = Math.ceil(sh * scale); // target image height
int sx = 0, sy = 0, sIndex = 0; // source x,y, index within source array
double tx = 0, ty = 0;
int yIndex = 0, tIndex = 0; // target x,y, x,y index within target array
double tX = 0, tY = 0; // rounded tx, ty
double w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0; // weight / next weight x / y
// weight is weight of current source point within target.
// next weight is weight of current source point within next target's point.
boolean crossX = false; // does scaled px cross its current px right border ?
boolean crossY = false; // does scaled px cross its current px bottom border ?
CanvasPixelArray sBuffer = cv.getContext2d().getImageData(0, 0, sw, sh).getData(); // source buffer 8 bit rgba
Float32Array tBuffer = TypedArrays.createFloat32Array(4 * sw * sh);
double sR = 0, sG = 0, sB = 0; // source's current point r,g,b
// untested !
double sA = 0; //source alpha
for (sy = 0; sy < sh; sy++) {
GWT.log("sy: "+sy+" sh: "+sh);
ty = sy * scale; // y src position within target
tY = (long)ty; // rounded : target pixel's y // ?????
yIndex = (int)Math.floor(4 * tY * tw); // line index within target array
crossY = (tY != ( (long)(ty + scale) )); // ?????
if (crossY) { // if pixel is crossing botton target pixel
wy = (tY + 1 - ty); // weight of point within target pixel
nwy = (ty + scale - tY - 1); // ... within y+1 target pixel
}
for (sx = 0; sx < sw; sx++, sIndex += 4) {
tx = sx * scale; // x src position within target
tX = (long)tx; // rounded : target pixel's x // ?????
tIndex = (int)Math.floor(yIndex + tX * 4); // target pixel index within target array // ?????
crossX = (tX != ((int)Math.floor(tx + scale)));
if (crossX) { // if pixel is crossing target pixel's right
wx = (tX + 1 - tx); // weight of point within target pixel
nwx = (tx + scale - tX - 1); // ... within x+1 target pixel
}
sR = sBuffer.get(sIndex); // retrieving r,g,b for curr src px.
sG = sBuffer.get(sIndex + 1);
sB = sBuffer.get(sIndex + 2);
sA = sBuffer.get(sIndex + 3);
if (!crossX && !crossY) { // pixel does not cross
// just add components weighted by squared scale.
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * sqScale));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * sqScale));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * sqScale));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * sqScale));
} else if (crossX && !crossY) { // cross on X only
w = wx * scale;
// add weighted component for current px
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// add weighted component for next (tX+1) px
nw = nwx * scale;
tBuffer.set(tIndex + 4, (float)(tBuffer.get(tIndex + 4) + sR * nw)); // not 3
tBuffer.set(tIndex + 5, (float)(tBuffer.get(tIndex + 5) + sG * nw)); // not 4
tBuffer.set(tIndex + 6, (float)(tBuffer.get(tIndex + 6) + sB * nw)); // not 5
tBuffer.set(tIndex + 7, (float)(tBuffer.get(tIndex + 7) + sA * nw)); // not 6
} else if (crossY && !crossX) { // cross on Y only
w = wy * scale;
// add weighted component for current px
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// add weighted component for next (tY+1) px
nw = nwy * scale;
tBuffer.set((int)Math.floor(tIndex + 4 * tw) , (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw)) + sR * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 1), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 1)) + sG * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 2), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 2)) + sB * nw)); // *4, not 3
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 3), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 3)) + sA * nw)); // *4, not 3
} else { // crosses both x and y : four target points involved
// add weighted component for current px
w = wx * wy;
tBuffer.set(tIndex , (float)(tBuffer.get(tIndex) + sR * w));
tBuffer.set(tIndex + 1, (float)(tBuffer.get(tIndex + 1) + sG * w));
tBuffer.set(tIndex + 2, (float)(tBuffer.get(tIndex + 2) + sB * w));
tBuffer.set(tIndex + 3, (float)(tBuffer.get(tIndex + 3) + sA * w));
// for tX + 1; tY px
nw = nwx * wy;
tBuffer.set(tIndex + 4, (float)(tBuffer.get(tIndex + 4) + sR * nw)); // same for x
tBuffer.set(tIndex + 5, (float)(tBuffer.get(tIndex + 5) + sG * nw));
tBuffer.set(tIndex + 6, (float)(tBuffer.get(tIndex + 6) + sB * nw));
tBuffer.set(tIndex + 7, (float)(tBuffer.get(tIndex + 7) + sA * nw));
// for tX ; tY + 1 px
nw = wx * nwy;
tBuffer.set((int)Math.floor(tIndex + 4 * tw) , (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw)) + sR * nw)); // same for mul
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 1), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 1)) + sG * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 2), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 2)) + sB * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 3), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 3)) + sA * nw));
// for tX + 1 ; tY +1 px
nw = nwx * nwy;
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 4), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 4)) + sR * nw)); // same for both x and y
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 5), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 5)) + sG * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 6), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 6)) + sB * nw));
tBuffer.set((int)Math.floor(tIndex + 4 * tw + 7), (float)(tBuffer.get((int)Math.floor(tIndex + 4 * tw + 7)) + sA * nw));
}
} // end for sx
} // end for sy
// create result canvas
Canvas resCV = Canvas.createIfSupported();
resCV.getCanvasElement().setWidth((int)Math.floor(tw));
resCV.getCanvasElement().setHeight((int)Math.floor(th));
Context2d resCtx = resCV.getContext2d();
ImageData imgRes = resCtx.getImageData(0, 0, tw, th);
CanvasPixelArray tByteBuffer = imgRes.getData();
// convert float32 array into a UInt8Clamped Array
int pxIndex = 0;
for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 4, tIndex += 4, pxIndex++) {
tByteBuffer.set(tIndex, (int)Math.ceil(tBuffer.get(sIndex)));
tByteBuffer.set(tIndex + 1, (int)Math.ceil(tBuffer.get(sIndex + 1)));
tByteBuffer.set(tIndex + 2, (int)Math.ceil(tBuffer.get(sIndex + 2)));
tByteBuffer.set(tIndex + 3, (int)Math.ceil(tBuffer.get(sIndex + 3)));
}
// writing result to canvas.
resCtx.putImageData(imgRes, 0, 0);
return resCV.getCanvasElement();
}
Here is the equivalent JSNI function:
public static final native CanvasElement resizeCanvas(CanvasElement cv, double scale) /*-{
if (!(scale < 1) || !(scale > 0)) throw ('scale must be a positive number <1 ');
var sqScale = scale * scale; // square scale = area of source pixel within target
var sw = cv.width; // source image width
var sh = cv.height; // source image height
var tw = Math.ceil(sw * scale); // target image width
var th = Math.ceil(sh * scale); // target image height
var sx = 0, sy = 0, sIndex = 0; // source x,y, index within source array
var tx = 0, ty = 0, yIndex = 0, tIndex = 0; // target x,y, x,y index within target array
var tX = 0, tY = 0; // rounded tx, ty
var w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0; // weight / next weight x / y
// weight is weight of current source point within target.
// next weight is weight of current source point within next target's point.
var crossX = false; // does scaled px cross its current px right border ?
var crossY = false; // does scaled px cross its current px bottom border ?
var sBuffer = cv.getContext('2d').getImageData(0, 0, sw, sh).data; // source buffer 8 bit rgba
var tBuffer = new Float32Array(4 * sw * sh); // target buffer Float32 rgb
var sR = 0, sG = 0, sB = 0; // source's current point r,g,b
// untested !
var sA = 0; //source alpha
for (sy = 0; sy < sh; sy++) {
ty = sy * scale; // y src position within target
tY = 0 | ty; // rounded : target pixel's y
yIndex = 4 * tY * tw; // line index within target array
crossY = (tY != (0 | ty + scale));
if (crossY) { // if pixel is crossing botton target pixel
wy = (tY + 1 - ty); // weight of point within target pixel
nwy = (ty + scale - tY - 1); // ... within y+1 target pixel
}
for (sx = 0; sx < sw; sx++, sIndex += 4) {
tx = sx * scale; // x src position within target
tX = 0 | tx; // rounded : target pixel's x
tIndex = yIndex + tX * 4; // target pixel index within target array
crossX = (tX != (0 | tx + scale));
if (crossX) { // if pixel is crossing target pixel's right
wx = (tX + 1 - tx); // weight of point within target pixel
nwx = (tx + scale - tX - 1); // ... within x+1 target pixel
}
sR = sBuffer[sIndex ]; // retrieving r,g,b for curr src px.
sG = sBuffer[sIndex + 1];
sB = sBuffer[sIndex + 2];
sA = sBuffer[sIndex + 3];
if (!crossX && !crossY) { // pixel does not cross
// just add components weighted by squared scale.
tBuffer[tIndex ] += sR * sqScale;
tBuffer[tIndex + 1] += sG * sqScale;
tBuffer[tIndex + 2] += sB * sqScale;
tBuffer[tIndex + 3] += sA * sqScale;
} else if (crossX && !crossY) { // cross on X only
w = wx * scale;
// add weighted component for current px
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// add weighted component for next (tX+1) px
nw = nwx * scale;
tBuffer[tIndex + 4] += sR * nw; // not 3
tBuffer[tIndex + 5] += sG * nw; // not 4
tBuffer[tIndex + 6] += sB * nw; // not 5
tBuffer[tIndex + 7] += sA * nw; // not 6
} else if (crossY && !crossX) { // cross on Y only
w = wy * scale;
// add weighted component for current px
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// add weighted component for next (tY+1) px
nw = nwy * scale;
tBuffer[tIndex + 4 * tw ] += sR * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 1] += sG * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 2] += sB * nw; // *4, not 3
tBuffer[tIndex + 4 * tw + 3] += sA * nw; // *4, not 3
} else { // crosses both x and y : four target points involved
// add weighted component for current px
w = wx * wy;
tBuffer[tIndex ] += sR * w;
tBuffer[tIndex + 1] += sG * w;
tBuffer[tIndex + 2] += sB * w;
tBuffer[tIndex + 3] += sA * w;
// for tX + 1; tY px
nw = nwx * wy;
tBuffer[tIndex + 4] += sR * nw; // same for x
tBuffer[tIndex + 5] += sG * nw;
tBuffer[tIndex + 6] += sB * nw;
tBuffer[tIndex + 7] += sA * nw;
// for tX ; tY + 1 px
nw = wx * nwy;
tBuffer[tIndex + 4 * tw ] += sR * nw; // same for mul
tBuffer[tIndex + 4 * tw + 1] += sG * nw;
tBuffer[tIndex + 4 * tw + 2] += sB * nw;
tBuffer[tIndex + 4 * tw + 3] += sA * nw;
// for tX + 1 ; tY +1 px
nw = nwx * nwy;
tBuffer[tIndex + 4 * tw + 4] += sR * nw; // same for both x and y
tBuffer[tIndex + 4 * tw + 5] += sG * nw;
tBuffer[tIndex + 4 * tw + 6] += sB * nw;
tBuffer[tIndex + 4 * tw + 7] += sA * nw;
}
} // end for sx
} // end for sy
// create result canvas
var resCV = document.createElement('canvas');
resCV.width = tw;
resCV.height = th;
var resCtx = resCV.getContext('2d');
var imgRes = resCtx.getImageData(0, 0, tw, th);
var tByteBuffer = imgRes.data;
// convert float32 array into a UInt8Clamped Array
var pxIndex = 0; //
for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 4, tIndex += 4, pxIndex++) {
tByteBuffer[tIndex] = Math.ceil(tBuffer[sIndex]);
tByteBuffer[tIndex + 1] = Math.ceil(tBuffer[sIndex + 1]);
tByteBuffer[tIndex + 2] = Math.ceil(tBuffer[sIndex + 2]);
tByteBuffer[tIndex + 3] = Math.ceil(tBuffer[sIndex + 3]);
}
// writing result to canvas.
resCtx.putImageData(imgRes, 0, 0);
return resCV;
}-*/;
Why is the Java function so much slower than the JSNI function?
Did you GWT-compiled and run the compiled version of your application in the "java scenario" ?
Because, in case you didn't and just ran from Eclipse Run->Web Application. GWT will convert the java code in javascript at runtime which is a lot slower than the compiled version.

Can someone please help me with the code I am writing? (Java)

I am writing a small program.
I am a beginner at programming java.
Here is the code:
package dnd;
public class Monster {
static String name;
static int level;
static String rang;
static String Class;
static double[] Strength = {1, 1, 0};
static double[] Endurance = {1, 1, 0};
static double[] Agility = {1, 1, 0};
static double[] Precision = {1, 1, 0};
static double[] Wisdom = {0, 1, 1};
static double[] Intelegence = {0, 1, 1};
public static void Monster(String nameC, int levelC, String classesC, int rangC){
name = nameC;
level = levelC;
switch(rangC){
case 1:
rang = "Civillian";
case 2:
rang = "Soldier";
case 3:
rang = "Veteran";
case 4:
rang = "Commander";
case 5:
rang = "Boss";
case 6:
rang = "Elite";
default:
rang = "Civillian";
}
Class = classesC;
switch(Class){
case "Warrior":
Strength[1] = 2;
Endurance[1] = 2;
Intelegence[1] = 0.5;
case "Archer":
Agility[1] = 2;
Precision[1] = 2;
Endurance[1] = 0.5;
case "Rouge":
Agility[1] = 2;
Intelegence[1] = 2;
Endurance[1] = 0.5;
case "Mage":
Wisdom[1] = 2;
Intelegence[1] = 2;
Strength[1] = 0.5;
case "Priest":
Wisdom[1] = 2;
Strength[1] = 0.5;
case "Druid":
Intelegence[1] = 2;
Agility[1] = 0.5;
}
}
public static void defaultStaringPoints(){
int StP;
int EnP;
int InP;
int AgP;
int PrP;
int WiP;
switch(Class){
case "Warrior":
//Strength
//Endurance
//-Intelegence
StP = (int) (Math.random() * 2);
EnP = (int) (Math.random() * (3-StP));
InP = (int) (Math.random() * (3-(StP+EnP)));
Strength[0] = Strength[0] + StP;
Endurance[0] = Endurance[0] + EnP;
Intelegence[0] = Intelegence[0] + InP;
case "Archer":
//Agility
//Precision
//-Endurance
AgP = (int) (Math.random() * 2);
PrP = (int) (Math.random() * (3-AgP));
EnP = (int) (Math.random() * (3-(AgP+PrP)));
Agility[0] = Agility[0] + AgP;
Precision[0] = Precision[0] + PrP;
Endurance[0] = Endurance[0] + EnP;
case "Rouge":
//Agility
//Intelegence
//-Endurance
AgP = (int) (Math.random() * 2);
InP = (int) (Math.random() * (3-AgP));
EnP = (int) (Math.random() * (3-(AgP+InP)));
Agility[0] = Agility[0] + AgP;
Intelegence[0] = Intelegence[0] + InP;
Endurance[0] = Endurance[0] + EnP;
case "Mage":
//Wisdom
//Intelegence
//-Strength
WiP = (int) (Math.random() * 2);
InP = (int) (Math.random() * (3-WiP));
StP = (int) (Math.random() * (3-(WiP+InP)));
Wisdom[0] = Wisdom[0] + WiP;
Intelegence[0] = Intelegence[0] + InP;
Strength[0] = Strength[0] + StP;
case "Priest":
//Wisdom
//-Strength
WiP = (int) (Math.random() * 3);
StP = (int) (Math.random() * (3-WiP));
Wisdom[0] = Wisdom[0] + WiP;
Strength[0] = Strength[0] + StP;
case "Druid":
//Intelegence
//-Agility
InP = (int) (Math.random() * 3);
AgP = (int) (Math.random() * (3-InP));
Intelegence[0] = Intelegence[0] + InP;
Agility[0] = Agility[0] + AgP;
}
}
}
Then I create a new Monster,
run Goblin.Monster("Goblin", 1, "Rouge", 2)
and Goblin.defaultStaringPoints()
the output for Arrays.toString(Goblin.Wisdom) should be [0, 1, 1],
but instead it is [1, 2, 1], [2, 2, 1] or even [3, 2, 1].
I feel, that I am just overseeing something,
but I checked over 10 times.
Thank You in advance!
In each of your switch statements, you need a break; statement at the end of each case. For example:
switch(rangC){
case 1:
rang = "Civillian";
break;
case 2:
rang = "Soldier";
break;
...
}
Without the break;, execution simply falls through to the next case.
Also, you don't have a case for "Goblin" in any of your switch statements.
When you call defaultStartingPoints(), it randomizes the stats so that the Wisdom stat is no longer [0, 1, 1].

Image over another already drawn image in CAPTCHA

I want to generate a captcha by myself without using any other API, but here are some issues. In my code I have treated each character as an image and then form some operation on them but now I want to rotate whole image with respect to its midpoint.
Here is my sample code:
for (int i = 0; i < charsToPrint; i++)
{
double randomValue =Math.random();
int randomIndex = (int) Math.round(randomValue * (chars.length - 1));
char characterToShow = chars[randomIndex];
finalString.append(characterToShow);
int charWidth = fontMetrics.charWidth(characterToShow);
int charDim = Math.max(maxAdvance, fontHeight);
//int halfCharDim = (int) (charDim / 2);
charImage = new BufferedImage(charDim, charDim,BufferedImage.TYPE_INT_ARGB);
charGraphics = charImage.createGraphics();
charGraphics.setColor(textColor);
charGraphics.setFont(textFont);
int rn = ran.nextInt((20 - 10) + 1) + 10;
x1=charDim/rn;
int rn1 = ran.nextInt((20 - 10) + 1) + 10;
y1=charDim/rn1;
int charX = (int) ((0.5 * charDim - 0.5 * charWidth)+x1);
int charY=(int) ((charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent()+y1);
charGraphics.drawString("" + characterToShow, charX, charY);
float x = horizMargin + spacePerChar * (i) - charDim / 2.0f;
int y = (int) ((height - charDim) / 2);
g.setColor(Color.GREEN);
g.drawImage(charImage, (int) (x+x1), (int)(y+y1), charDim,charDim, null,null);
charGraphics.dispose();
}

Categories