1
\$\begingroup\$

I work with the Oracle JGeometry method which returns (or takes as method argument) 2D segments as double array (x1,y1,x2,y2 ... xn,yn). I need to extend this array to contain 3D segments as double array (x1,y1,z1,x2,y2,z2 ... xn,yn,zn) by default Z value or reduce to 2D (by removing of all Z coordinate). I wrote simple utility methods for making this. Is there any easier or smarter way to do this?

The conversion from 2D to 3D:

public static double[] to3D(double z, double[] inputArray) {
    List<Double> convertedItems = new ArrayList<>();
    for (int i = 0; i < inputArray.length; i++) {
        convertedItems.add(inputArray[i]);
        if ((i + 1) % 2 == 0) {
            convertedItems.add(z);
        }
    }
    return convertedItems.stream().mapToDouble(Double::doubleValue).toArray();
}

The conversion from 3D to 2D:

public static double[] to2D(double[] inputArray) {
    List<Double> convertedItems = new ArrayList<>();
    for (int i = 0; i < inputArray.length; i++) {
       if ((i + 1) % 3 == 0) {
           continue;
       }
       convertedItems.add(inputArray[i]);     
    }
    return convertedItems.stream().mapToDouble(Double::doubleValue).toArray();
}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I would go with primitive Arrays, instead of using Collections and Streams in this case.

public static double[] to3D(double z, double[] in) {
    // Pre-allocated array 1.5 size of the original array
    double[] out = new double[in.length * 3 / 2];
    //loop with a step 2
    for (int i = 0, j = 0; i < in.length; i += 2) {
        out[j++] = in[i];
        out[j++] = in[i + 1];
        out[j++] = z;
    }
    return out;
}

public static double[] to2D(double[] in) {
    // Pre-allocated array 2/3 size of the original array
    double[] out = new double[in.length * 2 / 3];
    //loop with a step 3
    for (int i = 0, j = 0; i < in.length; i += 3) {
        out[j++] = in[i];
        out[j++] = in[i + 1];
    }
    return out;
}

Reasons for using arrays instead of lists: Input and output both are arrays, the target size is known, we only need basic operations and they would be faster in this case.

I hope it helps.

\$\endgroup\$
8
  • \$\begingroup\$ Just a small remark: Starting with j = -1 seems a bit ugly. Using post increment (j++) and starting with j = 0 seems "nicer". \$\endgroup\$
    – RoToRa
    Mar 8, 2021 at 11:59
  • \$\begingroup\$ You are right, I just do it to avoid last unused post-increment, If you think it still should have that then you can edit it or tell me if I must, Thanks \$\endgroup\$
    – rifaqat
    Mar 8, 2021 at 14:04
  • \$\begingroup\$ You can include int j = 0 directly inside the loop and you could explain why you are using arrays instead of lists (fixed cardinality of arrays). \$\endgroup\$ Mar 8, 2021 at 15:49
  • \$\begingroup\$ In this case int j = 0 cannot be initialised inside loop because it needs incremented value in each iteration. \$\endgroup\$
    – rifaqat
    Mar 9, 2021 at 7:49
  • \$\begingroup\$ I badly explained it, I meant for (int i = 0, j = 0; i < in.length; i += 3). \$\endgroup\$ Mar 9, 2021 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.