Since some weeks ago I have been trying to convert this c and other c function to java language (i'm a newbie on it).
My first problem is how-to convert to java code, the pointers on lines like:
q = fdata + ind;
datend = fdata + buff_size;
For example when "ind" has a negative position (-220 for example) the pointer will be on "ind" position before "fdata" values, also the same occur with datend var.
I figured out that can be solved on isolated way by creating an index var for each pointer to know where there are pointing at. The real problem for me comes a few line after that, when i trying to not run over end of frame of "fdata" array.
Can some body with more experiences help me please?
Thank.
static Stat *stat = NULL;
static float *mem = NULL;
static Stat*
get_stationarity(fdata, freq, buff_size, nframes, frame_step, first_time)
float *fdata;
double freq;
int buff_size, nframes, frame_step, first_time;
{
static int nframes_old = 0, memsize;
float preemp = 0.4f, stab = 30.0f;
float *p, *q, *r, *datend;
int ind, i, j, m, size, order, agap, w_type = 3;
agap = (int) (STAT_AINT * freq);
size = (int) (STAT_WSIZE * freq);
ind = (agap - size) / 2;
if (nframes_old < nframes || !stat || first_time) {
/* move this to init_dp_f0() later */
nframes_old = nframes;
if (stat) {
ckfree((char *) stat->stat);
ckfree((char *) stat->rms);
ckfree((char *) stat->rms_ratio);
ckfree((char *) stat);
}
if (mem) ckfree((void *) mem);
stat = (Stat *) ckalloc(sizeof (Stat));
stat->stat = (float*) ckalloc(sizeof (float) *nframes);
stat->rms = (float*) ckalloc(sizeof (float) *nframes);
stat->rms_ratio = (float*) ckalloc(sizeof (float) *nframes);
memsize = (int) (STAT_WSIZE * freq) + (int) (STAT_AINT * freq);
mem = (float *) ckalloc(sizeof (float) * memsize);
for (j = 0; j < memsize; j++) mem[j] = 0;
}
if (nframes == 0) return (stat);
q = fdata + ind;
datend = fdata + buff_size;
if ((order = (int) (2.0 + (freq / 1000.0))) > BIGSORD) {
fprintf(stderr,
"exceeds that allowable (%d); reduce Fs\n", BIGSORD);
order = BIGSORD;
}
/* prepare for the first frame */
for (j = memsize / 2, i = 0; j < memsize; j++, i++) mem[j] = fdata[i];
/* do not run over end of frame */
for (j = 0, p = q - agap; j < nframes; j++, p += frame_step, q += frame_step) {
if ((p >= fdata) && (q >= fdata) && (q + size <= datend))
stat->stat[j] = get_similarity(order, size, p, q,
&(stat->rms[j]),
&(stat->rms_ratio[j]), preemp,
stab, w_type, 0);
else {
if (first_time) {
if ((p < fdata) && (q >= fdata) && (q + size <= datend))
stat->stat[j] = get_similarity(order, size, NULL, q,
&(stat->rms[j]),
&(stat->rms_ratio[j]),
preemp, stab, w_type, 1);
else {
stat->rms[j] = 0.0;
stat->stat[j] = 0.01f * 0.2f; /* a big transition */
stat->rms_ratio[j] = 1.0; /* no amplitude change */
}
} else {
if ((p < fdata) && (q + size <= datend)) {
stat->stat[j] = get_similarity(order, size, mem,
mem + (memsize / 2) + ind,
&(stat->rms[j]),
&(stat->rms_ratio[j]),
preemp, stab, w_type, 0);
/* prepare for the next frame_step if needed */
if (p + frame_step < fdata) {
for (m = 0; m < (memsize - frame_step); m++)
mem[m] = mem[m + frame_step];
r = q + size;
for (m = 0; m < frame_step; m++)
mem[memsize - frame_step + m] = *r++;
}
}
}
}
}
/* last frame, prepare for next call */
for (j = (memsize / 2) - 1, p = fdata + (nframes * frame_step) - 1; j >= 0 && p >= fdata; j--)
mem[j] = *p--;
return (stat);
}
This code is easier rewritten than ported. The reason is, that it uses a large number of pointer-arithmetic and casting.
It looks to me like this code combines a sliding window and averaging functions over the data. You can easily do this in Java, just place each time-series in an array, use an index (instead of a pointer) to point at the array's entries. In the case where the C-code uses a pointer and then a (possibly negative) offset as a second pointer just use two indices into the time-series-array.
It is easier to do this if you have the formula (math-notation. sliding-window plus averaging functions) that this code is supposed to compute and translate the formula to java.
Related
I have to do this 2d DCT of an image for my project.
I translated the formula right to code. It all seems fine logically but it doesn't give the required result. I've tallied it with matlab function to check the results for a 3x3 matrix but they are incorrect.
Also, what and how I've coded gives a huge number of loops such that an actual image operation takes hours to compute.
Any suggestion to reduce the loops and pointing of program error would be great.
Thanks.
This is my code.
double alpha_p, alpha_q;
double pi = Math.atan(1.0) * 4.0;
//dct begins
System.out.println("it begins");
for (int p = 0; p < M; p++) {
for (int q = 0; q < N; q++) {
if (p == 0)
alpha_p = 1 / sqrt(M);
else
alpha_p = sqrt(2 / M);
if (q == 0)
alpha_q = 1 / sqrt(N);
else
alpha_q = sqrt(2 / N);
double toreturn = 0;
for (int m = 0; m < M; m++) {
for (int n = 0; n < N; n++) {
toreturn = toreturn + img[m][n]
* cos(((2 * m + 1) * p * pi) / 2 * M)
* cos(((2 * n + 1) * q * pi) / 2 * N);
}
}
dctimg[p][q] = alpha_p * alpha_q * toreturn;
System.out.println("euta");
}
}
// dct over
System.out.println("its over");
//inverse dct begins
for (int m = 0; m < M; m++) {
for (int n = 0; n < N; n++) {
double toreturn = 0;
for (int p = 0; p < M; p++) {
for (int q = 0; q < N; q++) {
if (p == 0)
alpha_p = 1 / sqrt(M);
else
alpha_p = sqrt(2 / M);
if (q == 0)
alpha_q = 1 / sqrt(N);
else
alpha_q = sqrt(2 / N);
toreturn = toreturn + alpha_p * alpha_q * dctimg[p][q]
* cos(((2 * m + 1) * p * pi) / 2 * M)
* cos(((2 * n + 1) * q * pi) / 2 * N);
}
}
finalimg[m][n] = toreturn;
}
}
//inverse dct over
First of all, in the formula of DCT the denominator of cos is 2 * M. It is a typical mistake. 4 / 2 * 2 = 4 not 1
cos(((2 * m + 1) * p * pi) / 2 * M) should be cos(((2 * m + 1) * p * pi) / (2 * M))
Parentheses are required in all four cases.
Another moment that I want to mention is sqrt(2 / M). If M has an integer type (it is not clear by your code) and it is greater than 2, then the expression 2 / M is equal to 0. Because both operands have integer types and / gives only integer part. To fix it, add a floating point like that sqrt(2.0 / M).
As you have already noticed, there is a lot of loops, in other words, the complexity of the 2D DCT II is O(n^4).
In real life nobody applies DCT to the whole actual image. The image is split into blocks of size 8x8 and each block is processed by DCT. This approach allows to keep n low and the complexity becomes acceptable.
To decrease the algorithmic complexity, I want to link here, where methods of using 1D DCT and FFT are good explained.
I use Java implemented Held-KarpTSP algorithm algo to solve a 25 cities TSP problem.
The program passes with 4 cities.
When it runs with 25 cities it won't stop for several hours. I use jVisualVM to see what's the hotspot, after some optimization now it shows
98% of time is in real computing instead in Map.contains or Map.get.
So I'd like to have your advice, and here is the code:
private void solve() throws Exception {
long beginTime = System.currentTimeMillis();
int counter = 0;
List<BitSetEndPointID> previousCosts;
List<BitSetEndPointID> currentCosts;
//maximum number of elements is c(n,[n/2])
//To calculate m-set's costs just need to keep (m-1)set's costs
List<BitSetEndPointID> lastKeys = new ArrayList<BitSetEndPointID>();
int m;
if (totalNodes < 10) {
//for test data, generate them on the fly
SetUtil3.generateMSet(totalNodes);
}
//m=1
BitSet beginSet = new BitSet();
beginSet.set(0);
previousCosts = new ArrayList<BitSetEndPointID>(1);
BitSetEndPointID beginner = new BitSetEndPointID(beginSet, 0);
beginner.setCost(0f);
previousCosts.add(beginner);
//for m=2 to totalNodes
for (m = 2; m <= totalNodes; m++) {// sum(m=2..n 's C(n,m)*(m-1)(m-1)) ==> O(n^2 * 2^n)
//pick m elements from total nodes, the element id is the index of nodeCoordinates
// the first node is always present
BitSet[] msets;
if (totalNodes < 10) {
msets = SetUtil3.msets[m - 1];
} else {
//for real data set, will read from serialized file
msets = SetUtil3.getMsets(totalNodes, m-1);
}
currentCosts = new ArrayList<BitSetEndPointID>(msets.length);
//System.out.println(m + " sets' size: " + msets.size());
for (BitSet mset : msets) { //C(n,m) mset
int[] candidates = allSetBits(mset, m);
//mset is a BitSet which makes sure begin point 0 comes first
//so end point candidate begins with 1. candidate[0] is always begin point 0
for (int i = 1; i < candidates.length; i++) { // m-1 bits are set
//set the new last point as j, j must not be the same as begin point 0
int j = candidates[i];
//middleNodes = mset -{j}
BitSet middleNodes = (BitSet) mset.clone();
middleNodes.clear(j);
//loop through all possible points which are second to the last
//and get min(A[S-{j},k] + k->j), k!=j
float min = Float.MAX_VALUE;
int k;
for (int ki = 0; ki < candidates.length; ki++) {// m-1 calculation
k = candidates[ki];
if (k == j) continue;
float middleCost = 0;
BitSetEndPointID key = new BitSetEndPointID(middleNodes, k);
int index = previousCosts.indexOf(key);
if (index != -1) {
//System.out.println("get value from map in m " + m + " y key " + middleNodes);
middleCost = previousCosts.get(index).getCost();
} else if (k == 0 && !middleNodes.equals(beginSet)) {
continue;
} else {
System.out.println("middleCost not found!");
continue;
// System.exit(-1);
}
float lastCost = distances[k][j];
float cost = middleCost + lastCost;
if (cost < min) {
min = cost;
}
counter++;
if (counter % 500000 == 0) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException iex) {
System.out.println("Who dares interrupt my precious sleep?!");
}
}
}
//set the costs for chosen mset and last point j
BitSetEndPointID key = new BitSetEndPointID(mset, j);
key.setCost(min);
currentCosts.add(key);
// System.out.println("===========================================>mset " + mset + " and end at " +
// j + " 's min cost: " + min);
// if (m == totalNodes) {
// lastKeys.add(key);
// }
}
}
previousCosts = currentCosts;
System.out.println("...");
}
calcLastStop(lastKeys, previousCosts);
System.out.println(" cost " + (System.currentTimeMillis() - beginTime) / 60000 + " minutes.");
}
private void calcLastStop(List<BitSetEndPointID> lastKeys, List<BitSetEndPointID> costs) {
//last step, calculate the min(A[S={1..n},k] +k->1)
float finalMinimum = Float.MAX_VALUE;
for (BitSetEndPointID key : costs) {
float middleCost = key.getCost();
Integer endPoint = key.lastPointID;
float lastCost = distances[endPoint][0];
float cost = middleCost + lastCost;
if (cost < finalMinimum) {
finalMinimum = cost;
}
}
System.out.println("final result: " + finalMinimum);
}
You can speed up your code by using arrays of primitives (it's likely to have to better memory layout than a list of objects) and operating on bitmasks directly (without bitsets or other objects). Here is some code (it generates a random graph but you can easily change it so that it reads your graph):
import java.io.*;
import java.util.*;
class Main {
final static float INF = 1e10f;
public static void main(String[] args) {
final int n = 25;
float[][] dist = new float[n][n];
Random random = new Random();
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
dist[i][j] = dist[j][i] = random.nextFloat();
float[][] dp = new float[n][1 << n];
for (int i = 0; i < dp.length; i++)
Arrays.fill(dp[i], INF);
dp[0][1] = 0.0f;
for (int mask = 1; mask < (1 << n); mask++) {
for (int lastNode = 0; lastNode < n; lastNode++) {
if ((mask & (1 << lastNode)) == 0)
continue;
for (int nextNode = 0; nextNode < n; nextNode++) {
if ((mask & (1 << nextNode)) != 0)
continue;
dp[nextNode][mask | (1 << nextNode)] = Math.min(
dp[nextNode][mask | (1 << nextNode)],
dp[lastNode][mask] + dist[lastNode][nextNode]);
}
}
}
double res = INF;
for (int lastNode = 0; lastNode < n; lastNode++)
res = Math.min(res, dist[lastNode][0] + dp[lastNode][(1 << n) - 1]);
System.out.println(res);
}
}
It takes only a couple of minutes to complete on my computer:
time java Main
...
real 2m5.546s
user 2m2.264s
sys 0m1.572s
Would anyone be able to tell me what is wrong with this code where I have attempted to implement 4 threads into a Mandelbrot program. The first half of the image in the file is not rendering. Thanks!
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Week2;
/**
*
* #author Alex Humphris
*/
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
public class ParallelMandelbrot4 extends Thread {
final static int N = 4096;
final static int CUTOFF = 100;
static int[][] set = new int[N][N];
public static void main(String[] args) throws Exception {
// Calculate set
long startTime = System.currentTimeMillis();
ParallelMandelbrot4 thread0 = new ParallelMandelbrot4(0);
ParallelMandelbrot4 thread1 = new ParallelMandelbrot4(1);
ParallelMandelbrot4 thread2 = new ParallelMandelbrot4(2);
ParallelMandelbrot4 thread3 = new ParallelMandelbrot4(3);
thread0.start();
thread1.start();
thread2.start();
thread3.start();
thread0.join();
thread1.join();
thread2.join();
thread3.join();
long endTime = System.currentTimeMillis();
System.out.println("Calculation completed in "
+ (endTime - startTime) + " milliseconds");
// Plot image
BufferedImage img = new BufferedImage(N, N,
BufferedImage.TYPE_INT_ARGB);
// Draw pixels
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
int k = set[i][j];
float level;
if (k < CUTOFF) {
level = (float) k / CUTOFF;
} else {
level = 0;
}
Color c = new Color(0, level, 0); // Green
img.setRGB(i, j, c.getRGB());
}
}
// Print file
ImageIO.write(img, "PNG", new File("Mandelbrot.png"));
}
int me;
public ParallelMandelbrot4(int me) {
this.me = me;
}
public void run() {
int begin, end;
if (me == 0) {
begin = 0;
end = (N / 4) * 1;
}
if (me == 1) {
begin = (N / 4) * 1;
end = (N / 4) * 2;
}
if (me == 2) {
begin = (N / 4) * 2;
end = (N / 4) * 3;
} else { // me == 1
begin = (N / 4) * 3;
end = N;
}
for (int i = begin; i < end; i++) {
for (int j = 0; j < N; j++) {
double cr = (4.0 * i - 2 * N) / N;
double ci = (4.0 * j - 2 * N) / N;
double zr = cr, zi = ci;
int k = 0;
while (k < CUTOFF && zr * zr + zi * zi < 4.0) {
// z = c + z * z
double newr = cr + zr * zr - zi * zi;
double newi = ci + 2 * zr * zi;
zr = newr;
zi = newi;
k++;
}
set[i][j] = k;
}
}
}
}
There error lies in your run() statement. By adding the if statement for (me == 3), the entire image is rendered, whereas before, the else statement at the end was being called in 3 different threads.
This is because of the else at the end of your code. Say for example me is 1. When it is one, it will execute the code in the if (me == 1) statement, and it will also execute the code at the end, as me is not equal to 2.
To fix this, I would recommend using the if else statements:
int begin = 0, end = 0;
if (me == 0) {
begin = 0;
end = (N / 4) * 1;
}
else if (me == 1) {
begin = (N / 4) * 1;
end = (N / 4) * 2;
}
else if (me == 2) {
begin = (N / 4) * 2;
end = (N / 4) * 3;
}
else if (me == 3) {
begin = (N / 4) * 3;
end = N;
}
The multithreading part is almost correct. It's the constructor that had some issues. You should consider making me a final private variable. #Skepter's answer is correct. This is how it looks in my IDE and that gave me an idea with the funkiness of the if-else you are using.
Fixing it thus should work:
private final int me;
public ParallelMandelbrot4(int me) {
this.me = me;
}
public void run() {
int begin, end;
if (me == 0) {
begin = 0;
end = (N / 4) * 1;
}
else if (me == 1) {
begin = (N / 4) * 1;
end = (N / 4) * 2;
}
else if (me == 2) {
begin = (N / 4) * 2;
end = (N / 4) * 3;
} else { // me == 3
begin = (N / 4) * 3;
end = N;
}
Recently learned about Cramers rule in precalculus, and decided to make an algorithm in Java to help me understand it better.
The following code works 100% correctly, however it does not use any sort of for loop to do what it does in a much simpler fashion.
Question: Is there a more elegant implementation of Cramers Rule in Java?
I'm thinking that making a basic determinant method, and then doing some column swapping for when I need to take the determinant of Dx, Dy, and Dz. (for Dx, swap column 4 with column 1 of the original matrix, then take determinant and divide by original determinant.)
This sound good?
public static void main(String[] args) {
int[][] matrix = new int[3][3];
matrix[0] = new int[] { 3, 5, -1, -2 };
matrix[1] = new int[] { 1, -4, 2, 13 };
matrix[2] = new int[] { 2, 4, 3, 1 };
int[] r = crame(matrix);
info("x: " + r[0] + ", y: " + r[1] + ", z: " + r[2]);
for(int i = 0; i < matrix.length; i++) {
int[] base = matrix[i];
if(check(base, r, base[3])) {
info("System " + (i+1) + " checks!");
} else {
info("System " + (i+1) + " fails check!");
}
}
}
public static int[] crame(int[][] m) {
int[] result;
if (m.length == 2) {
result = new int[2];
int D = (m[0][0] * m[1][1]) - (m[1][0] * m[0][1]);
int Dx = (m[0][2] * m[1][1]) - (m[1][2] * m[0][1]);
int Dy = (m[0][0] * m[1][2]) - (m[1][0] * m[0][2]);
result[0] = (int) (Dx / D);
result[1] = (int) (Dy / D);
} else if (m.length == 3) {
result = new int[3];
int D = (((m[0][2] * m[1][1] * m[0][2]) + (m[2][1] * m[1][2] * m[0][0]) + (m[2][2]
* m[1][0] * m[0][2])) - ((m[0][0] * m[1][1] * m[2][2])
+ (m[0][1] * m[1][2] * m[0][2]) + (m[0][2] * m[1][0] * m[2][1])));
int Dx = (((m[2][3] * m[1][1] * m[0][2]) + (m[2][1] * m[1][2] * m[0][3]) + (m[2][2]
* m[1][3] * m[0][1])) - ((m[0][3] * m[1][1] * m[2][2])
+ (m[0][1] * m[1][2] * m[2][3]) + (m[0][2] * m[1][3] * m[2][1])));
int Dy = (((m[2][0] * m[1][3] * m[0][2]) + (m[2][3] * m[1][2] * m[0][3]) + (m[2][2]
* m[1][0] * m[0][3])) - ((m[0][0] * m[1][3] * m[2][2])
+ (m[0][3] * m[1][2] * m[2][0]) + (m[0][2] * m[1][0] * m[2][3])));
int Dz = (((m[2][0] * m[1][1] * m[0][3]) + (m[2][1] * m[1][3] * m[0][0]) + (m[2][3]
* m[1][0] * m[0][1])) - ((m[0][0] * m[1][1] * m[2][3])
+ (m[0][1] * m[1][3] * m[2][0]) + (m[0][3] * m[1][0] * m[2][1])));
result[0] = (int) (Dx / D);
result[1] = (int) (Dy / D);
result[2] = (int) (Dz / D);
} else {
return new int[] {};
}
return result;
}
public static int product(int[] a, int[] b) {
int p = 0;
int[] fin = new int[(a.length -1)];
for(int x = 0; x < fin.length; x++) {
fin[x] = a[x] * b[x];
}
for (int f : fin) {
p += f;
}
return p;
}
public static boolean check(int[] a, int[] b, int z) {
return product(a, b) == z;
}
public static void info(String log) {
System.out.println(log);
}
My question pertains to the specific algorithm that can be used to solve systems of equations using Cramers rule only, is there any algorithm that is more elegant? The function is only designed for square matrices.
This is not a homework assignment, after HS I will be studying CS and I've been working on developing algorithms as preliminary practice.
Thank you for checking this out
First of, there is one way in which Cramers rule is perfect: It gives the algebraic solution of a linear system as a rational function in its coefficients.
However, practically, it has its limits. While the most perfect formula for a 2x2 system, and still good for a 3x3 system, its performance, if implemented in the straightforward way, deteriorates with each additional dimension.
An almost literal implementation of Cramers rule can be achieved with the Leverrier-Faddeev algorithm a b. It only requires the computation of matrix products and matrix traces, and manipulations of the matrix diagonal. Not only does it compute the determinant of the matrix A (along with the other coefficients of the characteristic polynomial), it also has the adjugate or co-factor matrix A# in its iteration matrix. The interesting fact about this matrix is that it allows to write the solution of A*x=b as (A#*b)/det(A), that is, the entries of A#*b already are the other determinants required by Cramers rule.
Leverrier-Faddeev requires n4+O(n3) operations. The same results can be obtained by the more complicated Samuelson-Berkowitz algorith, which has one third of that complexity, that is n4/3+O(n3).
The computation of the determinants required in Cramers rule becomes downright trivial if the system (A|b) is first transformed into triangular form. That can be achieved by Gauß elimination, aka LU decomposition (with pivoting for numerical stability) or the QR decomposition (easiest to debug should be the variant with Givens rotations). The efficient application of Cramers rule is then backward substitution in the triangular system.
Your method sounds good to me at least; however, I just may not be aware of any more efficient methods. The not-fun part may be figuring out how to best implement the determinant-calculating method, as apparently it's not an inexpensive operation.
But once you know that that's working, the rest sounds pretty OK to me. Cache the determinant of the original matrix, substitute in columns, etc.
Figured out exactly how to do this effectively.
http://sandsduchon.org/duchon/math/determinantJava.html
Provides a method for seamless determinants, and mentions matrix decomposition. I have not learned this yet as it's not a HS level concept however I did some problems using it and it's a solid method.
Final Code:
public static void main(String[] args) {
int[][] matrix = new int[3][3];
matrix[0] = new int[] { 3, 5, -1, -2 };
matrix[1] = new int[] { 1, -4, 2, 13 };
matrix[2] = new int[] { 2, 4, 3, 1 };
int[] r = crame(matrix);
info("x: " + r[0] + ", y: " + r[1] + ", z: " + r[2]);
for (int i = 0; i < matrix.length; i++) {
int[] base = matrix[i];
if (check(base, r, base[3])) {
info("System " + (i + 1) + " checks!");
} else {
info("System " + (i + 1) + " fails check!");
}
}
}
public static int getDet(int[][] a) {
int n = a.length - 1;
if (n < 0)
return 0;
int M[][][] = new int[n + 1][][];
M[n] = a; // init first, largest, M to a
// create working arrays
for (int i = 0; i < n; i++)
M[i] = new int[i + 1][i + 1];
return getDet(M, n);
} // end method getDecDet double [][] parameter
public static int getDet(int[][][] M, int m) {
if (m == 0)
return M[0][0][0];
int e = 1;
// init subarray to upper left mxm submatrix
for (int i = 0; i < m; i++)
for (int j = 0; j < m; j++)
M[m - 1][i][j] = M[m][i][j];
int sum = M[m][m][m] * getDet(M, m - 1);
// walk through rest of rows of M
for (int i = m - 1; i >= 0; i--) {
for (int j = 0; j < m; j++)
M[m - 1][i][j] = M[m][i + 1][j];
e = -e;
sum += e * M[m][i][m] * getDet(M, m - 1);
} // end for each row of matrix
return sum;
} // end getDecDet double [][][], int
public static int[] crame(int[][] m) {
int[] result;
if (m.length == 2) {
result = new int[m.length];
int D = getDet(m);
for (int i = 0; i < m.length; i++) {
result[i] = getDet(slide(m, i, m.length)) / D;
}
} else if (m.length == 3) {
result = new int[m.length];
int D = getDet(m);
for (int i = 0; i < m.length; i++) {
result[i] = (getDet(slide(m, i, m.length)) / D);
}
} else {
return new int[] {};
}
return result;
}
public static int[][] slide(int[][] base, int col, int fin) {
int[][] copy = new int[base.length][];
for (int i = 0; i < base.length; i++) {
int[] aMatrix = base[i];
int aLength = aMatrix.length;
copy[i] = new int[aLength];
System.arraycopy(aMatrix, 0, copy[i], 0, aLength);
}
for (int i = 0; i < base.length; i++) {
copy[i][col] = base[i][fin];
}
return copy;
}
public static int product(int[] a, int[] b) {
int p = 0;
int[] fin = new int[(a.length - 1)];
for (int x = 0; x < fin.length; x++) {
fin[x] = a[x] * b[x];
}
for (int f : fin) {
p += f;
}
return p;
}
public static boolean check(int[] a, int[] b, int z) {
return product(a, b) == z;
}
public static void info(String log) {
System.out.println(log);
}
I am animating an object along a spline path in OpenGL. I am using some code I found to generate the spline. Sadly, I don't yet understand the mechanics of it. I want my object to align to match the tangent of path so that it looks like its following the path.
Two questions.
How do I find a vector that is tangent to the path at a given point?
Secondly, given that vector and a vector pointing up, how do rotate the object to align?
Here is my spline code.
public Spline(Vector Path[])
{
ControlPoints = Path;
// Flatten out the control points array.
int len = ControlPoints.length;
float[] controlsX = new float[len];
float[] controlsY = new float[len];
float[] controlsZ = new float[len];
for (int i = 0; i < len; ++i)
{
controlsX[i] = ControlPoints[i].x;
controlsY[i] = ControlPoints[i].y;
controlsZ[i] = ControlPoints[i].z;
}
// Calculate the gamma values just once.
final int n = ControlPoints.length - 1;
float[] gamma = new float[n + 1];
gamma[0] = 1.0f / 2.0f;
for (int i = 1; i < n; ++i) gamma[i] = 1 / (4 - gamma[i - 1]);
gamma[n] = 1 / (2 - gamma[n - 1]);
// Calculate the cubic segments.
cubicX = calcNaturalCubic(n, controlsX, gamma);
cubicY = calcNaturalCubic(n, controlsY, gamma);
cubicZ = calcNaturalCubic(n, controlsZ, gamma);
}
private Cubic[] calcNaturalCubic(int n, float[] x, float[] gamma)
{
float[] delta = new float[n + 1];
delta[0] = 3 * (x[1] - x[0]) * gamma[0];
for (int i = 1; i < n; ++i)
{
delta[i] = (3 * (x[i + 1] - x[i - 1]) - delta[i - 1]) * gamma[i];
}
delta[n] = (3 * (x[n] - x[n - 1])-delta[n - 1]) * gamma[n];
float[] D = new float[n + 1];
D[n] = delta[n];
for (int i = n - 1; i >= 0; --i)
{
D[i] = delta[i] - gamma[i] * D[i + 1];
}
// Calculate the cubic segments.
Cubic[] C = new Cubic[n];
for (int i = 0; i < n; i++) {
final float a = x[i];
final float b = D[i];
final float c = 3 * (x[i + 1] - x[i]) - 2 * D[i] - D[i + 1];
final float d = 2 * (x[i] - x[i + 1]) + D[i] + D[i + 1];
C[i] = new Cubic(a, b, c, d);
}
return C;
}
final public Vector GetPoint(float Position)
{
if(Position >= 1) { return ControlPoints[ControlPoints.length - 1]; }
float position = Position * cubicX.length;
int splineIndex = (int)Math.floor(position);
float splinePosition = position - splineIndex;
return new Vector(cubicX[splineIndex].eval(splinePosition), cubicY[splineIndex].eval(splinePosition), cubicZ[splineIndex].eval(splinePosition));
}
First question:
If you keep track of the previous position of your object as well as the new position, you can find out the facing direction without finding the tangent of the spline, like so:
facing = newPosition - previousPosition
Second question:
You can use the answers described here for rotating an object to face a particular direction: What is the easiest way to align the Z axis with a vector?