Passing 2D Array argument with JACOB - java

I have a COM method I'm trying to invoke, where there's an argument of type 'object' which must be a 2D double safe array, a collection of lat/long points. How can I create a SafeArray in JACOB to send through the COM interface?
I've tried just passing a 2D array as an object in the object list. The method doesn't return error, but I do not see the results I expect in FalconView (rendering of the polygon).
double polyPoints[][] = new double[5][2];
polyPoints[0][0] = 75.3;
polyPoints[0][1] = 4.5;
polyPoints[1][0] = 3.8;
polyPoints[1][1] = 4.8;
polyPoints[2][0] = 2.3;
polyPoints[2][1] = 2.5;
polyPoints[3][0] = 5.3;
polyPoints[3][1] = 6.5;
polyPoints[4][0] = 0.3;
polyPoints[4][1] = -1.5;
// Can't recreate Variant or SafeArray from double[x][y] array;
Object[] polygonArgs = new Object[] {m_mainLayerHandle, polyPoints, 1};
Variant returnAddPolygon = Dispatch.invoke(mainLayerDispatch, "AddPolygon", Dispatch.Method, polygonArgs, new int[1]);
System.out.println("Polygon Handle: " + returnAddPolygon.getInt());
Object[] refreshArgs = new Object[] {m_mainLayerHandle};
Variant refreshVariant = Dispatch.invoke(mainLayerDispatch, "Refresh", Dispatch.Method, refreshArgs, new int[1]);
The second arument documentation:
lat_lon_array
a two dimensional SAFEARRAY of doubles. The first dimension contains the latitude values. The second dimension contains the longitude values

It seems that SafeArray supports 1 Dimensional, 2 Dimensional, and N-Dimensional arrays using some somewhat unclear constructors. Given the 2D double array I created above, I was able to copy the data in to a 2D Double Safe Array. It would certainly be more efficient to create the double[][] up front, but I'm doing this in some prototype code. There may be ways to copy entire arrays in to the safe array... I am not sure.
// 2D array of type double. First dimension size 5, second dimemnsion size 2.
SafeArray safeArray = new SafeArray(Variant.VariantDouble, 5, 2);
for(int i = 0; i < 5; i++) {
for (int j = 0; j < 2; j++) {
// set the value of safearray[i][j] to value polyPoints[i][j]
safeArray.setDouble(i, j, polyPoints[i][j]);
}
}

Related

Java two dimensional array notation and default access

From the following code:
/** Array for internal storage of elements.
#serial internal array storage.
*/
private double[][] A;
/** Row and column dimensions.
#serial row dimension.
#serial column dimension.
*/
private int m, n;
public Matrix times (Matrix B) {
if (B.m != n) {
throw new IllegalArgumentException("Matrix inner dimensions must agree.");
}
Matrix X = new Matrix(m,B.n);
double[][] C = X.getArray();
double[] Bcolj = new double[n];
for (int j = 0; j < B.n; j++) {
for (int k = 0; k < n; k++) {
Bcolj[k] = B.A[k][j];
}
for (int i = 0; i < m; i++) {
double[] Arowi = A[i];
double s = 0;
for (int k = 0; k < n; k++) {
s += Arowi[k]*Bcolj[k];
}
C[i][j] = s;
}
}
return X;
}
double[] Arowi = A[i];
What is this line doing?
A is a two dimensional Matrix, why is A[i] allowed? and what exactly is it doing?
Is that the same thing as A[i][0]?
This notation is confusing.
Also could someone translate that line to .NET, how would you do that with a double[,] Matrix?
I know there is a Matrix.GetLength() which gives you a specified length of a dimension.
But comparison to that line of Java code, how would that be translated?
EDIT
I believe I fixed it by just replacing that line and passing in my matrix to copy the first row into a new one dimensional matrix and returning it
public double[] ConvertFirstRowOfMultiArrayToOneArray(double[,] p)
{
double[] array = new double[p.Length];
for (int i = 0; i < p.GetLength(0); i++)
{
array[i] = p[0, i];
}
return array;
}
What is this line doing?
It's setting Arowi, that's declared as one dimension array, to the array A[i]
Suppose this case:
double[][] A = new double[2][2];
A[0][0] = 1.5;
A[0][1] = 2.5;
A[1][0] = 3.5;
A[1][0] = 4.5;
double[] B = A[0]; // Imagine A[0] as A[i]
/* then value of B is now A[0]
so B is now a unidimensional array containing value:
B[0] == 1.5 == A[0][0]
B[1] == 2.5 == A[0][1] */
A is a two dimensional Matrix, why is A[i] allowed?
Because as you can see, you are setting the unidimensional array value (B||Arowi) as the second dimension that's containing the A[i] array.
Imagine A[i] containing another array in itself (bidimensional). So we are saving this dimension into a new variable. In this case, it would be referencing the memory address, and not the value itself, if I'm not confused, and that if you edit the value in Arowi||B for example, it will change in the original array.
Example:
B[0] == 1.5 == TRUE
B[0] = 1.75
A[0][0] == 1.5 == FALSE
A[0][0] == 1.75 == TRUE
and what exactly is it doing?
I explain it in the example case.
The application is doing the following if I'm not confused:
It saves the result of adding (plus operation, s += Arowi[k]*Bcolj[k]) the values of multiplied A array (current array member/attribute in class (A) or maybe it's the Matrix class itself, I can't see all of the code) by the values of B columns (Matrix object taken by parameter). In each main loop it's going through a new column in B, storing all the values of rows in that column, and then looping the whole A array or class array, to store the results in C and then returning it as a Matrix object. I hope it is understandable and that I'm not confused.
Is that the same thing as A[i][0]?
No
A[i][0] sets the value. A[i] sets an unidimensional array
Sorry for my bad english, I hope you can understand and that the description and ideas are correct.
Edit
Look the example:
static void Main(string[] args)
{
double[][] A = new double[2][] { new double[2], new double[2] };
A[0][0] = 1.5;
A[0][1] = 2.5;
A[1][0] = 3.5;
A[1][1] = 4.5;
System.Console.WriteLine(A[0][0]);
// Prints 1,5
Console.Read();
double[] B = A[0];
System.Console.WriteLine(B[0]);
// Prints 1,5
System.Console.Read();
System.Console.Read();
}
So the line: double[] Arowi = A[i]; would translate to double[] Arowi = A[i];, just the same.
Only renember to create a jagged array double[][] A instead of array like double[,] A, because there seems to not be a way to reference a dimension with not jagged arrays (A[m,n]; being double[] Arowi = A[i]; not possible to be done like in Java). I can't tell why exactly right now. Just tried in my VS2013.
I recommend you to look at MSDN Documentation: http://msdn.microsoft.com/en-us/library/aa288453%28v=vs.71%29.aspx
I also recommend you this thread: Multidimensional Array [][] vs [,]
Not sure how it is in C# (.NET), but java has nothing like two (multi) dimensional arrays. It only has array of arrays (of arrays of arrays ...). So it is possible to have non-rectangular array of arrays.
double[] Arowi = A[i]; means declare new variable named Arowi of type array of doubles and set it to A[i] which is i-th (zero-based) member of A.
It is not the same as A[i][0], because this is 0-th member of i-th member of A.
EDIT: I haven't done any code review.
To understand what
double[] Arowi = A[i];
means, it is easiest to perceive A as an array of array of doubles instead of a matrix. Therefore, if you index A, it will return an array of doubles. Furthermore, if you index A at some index, it will return a double.
Hope this helps!

Number of columns in 2d array declaration

I want to read a text file and insert it into a 2d array. Here is my code.
List<String> list2 = new ArrayList<String>();
String thisLine = null;
while ((thisLine = input1.readLine()) != null) {
list2.add(thisLine);
}
double[][] X;
X = new double[list2.size()][];
String[] temp;
String delims = ",";
for (int k1 = 0; k1 <= (X.length - 1); k1++) {
String line = input.readLine();
temp = line.split(delims);
for (int i = 0; i < temp.length; i++) {
X[k1][i] = Double.parseDouble(temp[i]);
}
}
The problem is that it returns nothing and as soon as I specify the number of columns in 2d array declaration line, everything is fine. Based on my java knowledge, the number of columns in 2d array declaration is not necessary and in my project (Since we apply different datasets), the number of columns is not specified.
A 2d array is basically an array of arrays. Let's call it an outer array consisting of inner arrays.
When initializing a 2d array, it's true that you only have to declare the length of the outer array. I.e. the number of rows. By doing this, only the outer array will be initialized. The inner arrays are yet to be initialized.
In fact, these two arrays will contain the exact same elements:
double[][] array1 = new double[3][];
double[][] array2 = {null, null, null};
To initialize an inner array, you could do one of these:
array1[0] = new double[4];
array1[0] = new double[] {1.0, 3.14, 42.0, 2.718};
In your case, you could simply put this in your code to initialize the inner arrays:
temp = line.split(delims);
X[k1] = new double[temp.length]; //<- Add this line
X = new double[list2.size()][];
You have now created a jagged array, which is an array of arrays, bound by list2.size().
X[k1][i] = Double.parseDouble(temp[i]);
You have attempted to dereference a spot in the jagged array which does not exist. This is bad.
If the number of columns in your spec isn't specified, then it's provided either by the length of the arguments you parse, or implicitly by the element(s) you attempt to place into that location.
This would work, since it defines an array, which is what the jagged array needs...
X[k1][i] = new double[] {Double.parseDouble(temp[i])};
...but it would only give you a two-dimensional array effective as new Double[list2.size()][1].
Considering that you make use of String[] temp, perhaps instead, you want to use that as the condition on your jagged array? Here's a quick and dirty way to do it that involves more variables than I'd like, but would work:
String[] temp;
double[] tempDouble;
for (int k1 = 0; k1 <= (X.length - 1); k1++) {
temp = input.readline().split(delims);
tempDouble = new double[temp.length];
for(int i = 0; i < temp.length; i++) {
tempDouble[i] = Double.parseDouble(temp[i]);
}
// a bit further down, you can use the array as part of your jagged array.
X[k1] = tempDouble;
}

double row length of 2D array

I'm trying to double the length of a 2D array as I add values to it. I know for a 1D an array the code for this is:
int oneD[] = new int[10];
//fill array here
oneD = Arrays.copyOf(oneD, 2 * oneD.length);
so if I have a 2D array and only want to double the amount of rows while keeping say 2 columns I figured I would just do this:
int twoD[][] = new int[10][2];
//fill array here
twoD = Arrays.copyOf(twoD, 2* twoD.length);
This however does not seem to work for the 2D array. How does one go about doubling the length of a 2D array. In this case to make it [20][2] instead.
A 2D array in Java is an array of arrays. For doubling it, you'll have to manually iterate over each row in the array and copy all of its columns in turn.
In your case something like this would do the job:
public static <T> T[][] copyOf(T[][] array, int newLength) {
// ensure that newLength >= 0
T[][] copy = new T[newLength][];
for (int i = 0; i < copy.length && i < array.length; i++) {
copy[i] = Arrays.copyOf(array[i], array[i].length);
// this should also work, just not create new array instances:
// copy[i] = array[i];
}
return copy;
}
And you could call this method, just like you called Arrays.copyOf()

puting 1D arrays into the end of the 2D arrays

Lets say i've got this code:
float[] bigA = {1,2,3,4};
for (int i = 0; i < bigA.length; ++i) {
float abc = bigA[i] - 1;
float[] bigerAbc = {abc};
float[][] wcs = {bigerAbc};
}
The float[][] wcs = {abc}; part is defining the wcs array everytime, and the end result of wcs is {{3}}, but i want wcs to be defined as an empty array, and instead of float[][] wcs = {abc}; i want to write some code to add bigerAbc in the end of the wcs, and in the end wcs should be more like this {{0},{1},{2},{3}}...
To the question is: how can i add a 1D array to the end of a 2D array?
A 2D array in Java is literally an array of arrays, and arrays in java are fixed size. So, you cannot dynamically add an item to the end of an array. You either need to allocate a fixed size array, or use a more flexible structure like a List.
In your example, since the eventual size of wcs is known, you can do the following:
float[] bigA = {1,2,3,4};
float[][] wcs = new float[bigA.length][];
for(int i = 0; i < bigA.length; ++i) {
float abc = bigA[i] - 1;
float[] bigerAbc = {abc};
wcs[i] = bigerAbc;
}

java: How to split a 2d array into two 2d arrays

I'm writing a program to multiply matrices (2d arrays) as efficiently as possible, and for this i need to split my two arrays into two each and send them off to a second program to be multiplied. The issue I have is how to split a 2d array into two 2d arrays, at specific points (halfway). Does anyone have any ideas?
Lets say you have a 2d array of strings like so
String[][] array= new String[][]
{
{"a","b","c"},
{"d","e","f"},
{"h","i","j"},
{"k","l","m"}
};
Now you need a way to split these arrays at the half way point. Lets get the halfway point. Figure out how big the array is and then cut it in half. Note that you also must handle if the array is not an even length. Example, length of 3. If this is the case, we will use the Math.floor() function.
int arrayLength = array.length;
int halfWayPoint = Math.floor(arrayLength/2);
//we also need to know howmany elements are in the array
int numberOfElementsInArray = array[0].length;
Now we have all the info we need to create two 2d arrays from one. Now we must explicitly copy create and copy the data over.
//the length of the first array will be the half way point which we already have
String [][] newArrayA = new String[halfWayPoint][numberOfElementsInArray];
//this copies the data over
for(int i = 0; i &lt halfWayPoint; i++)
{
newArrayA[i] = array[i];
}
//now create the other array
int newArrayBLength = array.length - halfWayPoint;
String[][] newArrayB = new String[newArrayBLength][numberOfElementsInArray];
/*
* This copies the data over. Notice that the for loop starts a halfWayPoint.
* This is because this is where we left of copying in the first array.
*/
for(int i = halfWayPoint; i &lt array.length; i++)
{
newArrayB[i] = array[i];
}
And your done!
Now if you want to do it a little nicer, you could do it like this
int half = Math.floor(array/2);
int numberOfElementsInArray = array[0].length;
String [][] A = new String[half][numberOfElementsInArray];
String [][] B = new String[array.length - half][numberOfElementsInArray];
for(int i = 0; i &lt array.length; i++)
{
if(i &lt half)
{
A[i] = array[i];
}
else
{
B[i] = array[i];
}
}
And lastly, if you dont want to do it explicitly, you can use the built in functions. System.arraycopy() is one example. Here is a link to its api System.arraycopy()
int half = Math.floor(array/2);
int numberOfElementsInArray = array[0].length;
String [][] A = new String[half][numberOfElementsInArray];
String [][] B = new String[array.length - half][numberOfElementsInArray];
System.arraycopy(array,0,A,0,half);
System.arraycopy(array,half,B,0,array.length - half);

Categories

Resources