How to get an ObservableFloatArray from a Stream? - java-8

This is nearly the same question as this one, but in the opposite direction.
I know there's no FloatStream in Java 8, and there're no many use cases for float[], but I have one:
Dealing with TriangleMesh in JavaFX 3D, you have to provide an ObservableFloatArray for the 3D coordinates of the vertices of the whole mesh.
As a result of some calculations I'll have all these coordinates in a List, and to add all of them at once to the mesh, I'll call triangleMesh.getPoints().addAll(), using one of the following methods:
addAll(ObservableFloatArray src)
addAll(float... elements)
addAll(ObservableFloatArray src, int srcIndex, int length)
addAll(float[] src, int srcIndex, int length)
where ObservableFloatArray can be created using FXCollections.observableFloatArray(), FXCollections.observableFloatArray(ObservableFloatArray array) or FXCollections.observableFloatArray(float... values).
Let's say I have this pojo for each vertex:
private class Vertex {
private final float x;
private final float y;
private final float z;
public Vertex(float x, float y, float z){
this.x=x; this.y=y; this.z=z;
}
public float[] getCoordenates(){
return new float[]{x,y,z};
}
}
and after performing some calculations I have List<Vertex> listVertices. I'll need to generate float[] arrayVertices to finally call triangleMesh.getPoints().addAll(arrayVertices);.
For now this is what I'm doing:
listVertices.forEach(vertex->triangleMesh.getPoints().addAll(vertex.getCoordenates()));
But this triggers the associated listener on every new vertex added to the observable array, and for high number of vertices this affects performance.
Should FloatStream and flatMapToFloat() exist, I'd do something like this:
float[] arrayVertices = listVertices.stream()
.map(vertex->FloatStream.of(vertex.getCoordenates()))
.flatMapToFloat(f->f).toArray();
triangleMesh.getPoints().addAll(arrayVertices);
like I actually do with a list of int[] for face indices:
int[] arrayFaces = listFaces.stream()
.map(face->IntStream.of(face.getFaceIndices()))
.flatMapToInt(i->i).toArray();
triangleMesh.getFaces().addAll(arrayFaces);
But as far as I know, there's no way using streams.
Thanks in advance for any possible solution involving streams.

Keep in mind that a Stream defines an operation rather that a storage. So for most operations, using a float provides only little benefit over double values when CPU registers are used. There might be a theoretical improvement for operations that could be accelerated using SSE or GPU, but that’s not relevant here.
So you can use a DoubleStream for that operation, the only thing you need is a collector capable of collecting a DoubleStream into a float[] array:
float[] arrayVertices = listVertices.stream()
.flatMapToDouble(vertex->DoubleStream.of(vertex.x, vertex.y, vertex.z))
.collect(FaCollector::new, FaCollector::add, FaCollector::join)
.toArray();
static class FaCollector {
float[] curr=new float[64];
int size;
void add(double d) {
if(curr.length==size) curr=Arrays.copyOf(curr, size*2);
curr[size++]=(float)d;
}
void join(FaCollector other) {
if(size+other.size > curr.length)
curr=Arrays.copyOf(curr, size+other.size);
System.arraycopy(other.curr, 0, curr, size, other.size);
size+=other.size;
}
float[] toArray() {
if(size!=curr.length) curr=Arrays.copyOf(curr, size);
return curr;
}
}
This supports parallel processing, however, for an operation that merely consist of data copying only, there is no benefit from parallel processing.

I don't think there's any way around the fact that you have to create one data structure (e.g. a double[] or a List<Float>) and then map it into a float[]. (But maybe I am missing something.)
If you want to do this using a Stream-like API, you can use a Collector to do the mapping at the end:
import java.util.List;
import java.util.ListIterator;
import java.util.Random;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javafx.scene.shape.TriangleMesh;
public class StreamFloatsTest {
public static void main(String[] args) {
// The following declaration works in Eclipse 4.4
// however it won't compile from the command line:
// Collector<Float, List<Float>, float[]> toFloatArray =
// This declaration works:
Collector<Float, ?, float[]> toFloatArray =
Collectors.collectingAndThen(Collectors.toList(), floatList -> {
float[] array = new float[floatList.size()];
for (ListIterator<Float> iterator = floatList.listIterator(); iterator.hasNext();) {
array[iterator.nextIndex()] = iterator.next();
}
return array ;
});
// Random vertex list for demo purposes:
Random rng = new Random();
List<Vertex> vertices = IntStream.range(0, 100)
.mapToObj(i -> new Vertex(rng.nextFloat(), rng.nextFloat(), rng.nextFloat()))
.collect(Collectors.toList());
float[] vertexArray = vertices.stream()
.flatMap(v -> Stream.of(v.getX(), v.getY(), v.getZ()))
.collect(toFloatArray);
TriangleMesh mesh = new TriangleMesh();
mesh.getPoints().addListener(obs -> System.out.println("mesh invalidated"));
mesh.getPoints().addListener((array, sizeChanged, from, to) -> System.out.println("mesh changed"));
mesh.getPoints().addAll(vertexArray);
}
public static class Vertex {
private final float x ;
private final float y ;
private final float z ;
public Vertex(float x, float y, float z) {
this.x = x ;
this.y = y ;
this.z = z ;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public float[] getCoordinates() {
return new float[] {x, y, z};
}
}
}

Related

How to call a function inside stream of hash map object , & accumulate sum based on output of method called inside stream

double finalPrice = 0;
for(Map.Entry<Integer, Integer> eachBasketItemEntry:itemsInBasket.entrySet()){
Integer itemId = eachBasketItemEntry.getKey();
if(itemPricingRuleMap.containsKey(itemId)){
//calculate pricing based on pricing rule for that item code
finalPrice+=calculateItemPrice(itemId,eachBasketItemEntry.getValue(),itemPricingRuleMap);
}
else{
throw new IllegalArgumentException("No pricing rule regsitered for the item with item id"+itemId);
}
}
return finalPrice;
private double calculateItemPrice(Integer itemId, Integer itemsCount,Map<Integer, PricingRule> itemPricingRuleMap) {
PricingRule pricingRule = itemPricingRuleMap.get(itemId);
return pricingRule.calculatePrice(itemsCount);
}
How to convert this into java8 streams?
double a1 = itemsInBasket.entrySet().stream().forEach(eachBasketItemEntry->{
double finalPrice = 0;
Integer itemId = eachBasketItemEntry.getKey();
finalPrice+= calculateItemPrice(itemId,eachBasketItemEntry.getValue(),itemPricingRuleMap);
})
Tried doing this but Im unsure how to proceed from here..
Can any one help.
Im new to java 8 streams
Thank you.
You can refer the below sample code whenever some one wants to iterate over the collection and wants to get the reduced single value output.
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) throws Exception {
Map<String,Integer> employeeSalaryMap = new HashMap<>();
employeeSalaryMap.put("emp1",10000);
employeeSalaryMap.put("emp2",20000);
employeeSalaryMap.put("emp3",30000);
employeeSalaryMap.put("emp4",40000);
employeeSalaryMap.put("emp5",50000);
int totalSalaryOfAllEmployees1 = employeeSalaryMap.values().stream().mapToInt(Integer::intValue).sum();
int totalSalaryOfAllEmployees2 = employeeSalaryMap.entrySet().stream().map(Map.Entry::getValue)
.reduce(Integer::sum).orElseThrow(Exception::new);
System.out.println("totalSalaryOfAllEmployees1:: " + totalSalaryOfAllEmployees1);
System.out.println("totalSalaryOfAllEmployees2:: " + totalSalaryOfAllEmployees2);
}
}
**Output**
totalSalaryOfAllEmployees1:: 150000
totalSalaryOfAllEmployees2:: 150000
Both the operations will give you the same result.
Recommended to use: mapToInt/mapToDouble based on the requirements.
Thanks
You can use .map() to map your result calculated from calculateItemPrice method and then use reduce() operation to get required result.
Wrote a sample example for explanation
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
class Main {
public static void main(String[] args) {
Map<Integer, Integer> itemsInBasket = new HashMap<Integer, Integer>();//Creating HashMap
itemsInBasket.put(1, 5); //Put elements in Map
itemsInBasket.put(2, 6);
itemsInBasket.put(3, 7);
itemsInBasket.put(4, 8);
int a1 = itemsInBasket
.entrySet()
.stream()
.map(e -> (e.getKey() + e.getValue()))
.reduce(Integer::sum).orElseThrow(NoSuchElementException::new);
System.out.println(a1);
}
}
For your case : below code can help
double a1 = itemsInBasket
.entrySet()
.stream()
.map(e->calculateItemPrice(e.getKey(), e.getValue(), itemPricingRuleMap))
.reduce(Double::sum).orElseThrow(NoSuchElementException::new);
EDIT : As #Holger Suggested it can be rewritten as
double a1 = itemsInBasket
.entrySet()
.stream()
.mapToDouble(e->calculateItemPrice(e.getKey(), e.getValue(), itemPricingRuleMap))
.sum().orElseThrow(NoSuchElementException::new);
Let me know in comments further if you face further issues.
Thanks.

How can I display pixel by pixel the calculation of a circle?

Few days before, I asked you to help me because I couldn't show the drawing of a circle pixel by pixel (the drawing got stuck). #James_D found the solution and told me it was because a background-thread was trying to modify the UI. Indeed, I have a GraphicEngine class that extends Service : this class is this background-thread and its aim was to calculate and modify the image (now its aim is just to calculate the circle's pixels).
Well, finally, thanks to #James_D, I have now some classes :
GraphicEngine,
ImageAnimation which contains the animation of drawing,
DialogCreationOfCircularGradation, which is a dialog containing a button "OK, draw circle !" and which handles this event.
The below source contains the answer of my program to the user-event "Draw a circle". It gets several Textfield's input and give it to the GraphicsEngine. Moreover it asks the latter to do the calculation of the circle's pixels and asks the ImageAnimation to display the calculation pixel by pixel, during the calculation done by the GraphicsEngine.
CLASS DialogCreationOfCircularGradation
public void dialogHandleEvents() {
Optional r = this.showAndWait();
if(r.isPresent() && r.get() == ButtonType.OK) { // The user clicks on "OK, draw the circle !"
int radius = Integer.parseInt(this.dialog_field_radius.getText());
[...]
this.gui.getImageLoader().loadImageFromUsersPreferences(x0 + thickness + 2*radius, y0 + thickness + 2*radius);
this.gui.getGraphicEngine().setOperationToDo("Circle");
this.gui.getGraphicEngine().setRadius(radius);
[...]
this.gui.getGraphicEngine().restart();
this.gui.getImageAnimation().start();
}
}
The below code is GraphicsEngine's one. As you can see, there is in particular one important variable which is incremented during the circle algorithm : its name is counter_max. Why this variable is important ? Because it's necessary used in the class ImageAnimation. Look at its source after GraphicsEngine's one.
CLASS GraphicEngine
public class GraphicEngine extends Service<Void> {
private int image_width, image_height;
private PixelReader pixel_reader;
private BlockingQueue<Pixel> updates;
private String operation_to_do;
private int radius; [...]
public void setOperationToDo(String operation_to_do) {
this.operation_to_do = operation_to_do;
}
public Task<Void> createTask() {
return new Task<Void>() {
protected Void call() {
switch(operation_to_do) {
[...]
case "Circle" :
traceCircularGradation();
break;
}
return null;
}
};
}
private void traceCircularGradation() {
double w = 2 * 3.141, precision = 0.001;
long counter_max = 0;
int x, y;
this.gui.getImageAnimation().setMax(counter_max);
double[] rgb_gradation;
for (double current_thickness = 0; current_thickness <= this.thickness; current_thickness++) {
for (double angle = 0; angle <= w; angle += precision) {
x = (int) ((current_thickness + radius) * Math.cos(angle) + x0);
y = (int) ((current_thickness + radius) * Math.sin(angle) + y0);
if(x >= 0 && y >= 0) {
counter_max++;
rgb_gradation = PhotoRetouchingFormulas.chromatic_gradation(angle, w);
updates.add(new Pixel(x, y, Color.color(rgb_gradation[0], rgb_gradation[1], rgb_gradation[2])));
}
}
}
this.gui.getImageAnimation().setMax(counter_max);
}
The variable counter_max is used in ImageAnimation (its name has changed, its called : max). It's useful in the last if : if (count >= max).
max/counter_max represent the number of modified pixels. I can't replace it with image_width * image_height because in the circle algorithm, only the circle's pixels are drawn/modified. The other pixels of the image are not.
So I have either to compute counter_max as I did here in the for loops and then give it to ImageAnimation, or find a mathematical formula to determine it before the for. In the first case, the display of the circle doesn't work.
It would be really perfect if a formula existed.
CLASS ImageAnimation
public class ImageAnimation extends AnimationTimer {
private Gui gui;
private long max;
private long count, start;
ImageAnimation (Gui gui) {
this.gui = gui;
this.count = 0;
this.start = -1;
}
public void setMax(long max) {
this.max = max;
}
#Override
public void handle(long timestamp) {
if (start < 0) {
start = timestamp ;
return ;
}
WritableImage writable_image = this.gui.getWritableImage();
BlockingQueue<Pixel> updates = this.gui.getUpdates();
while (timestamp - start > (count* 5_000_000) / (writable_image.getWidth()) && ! updates.isEmpty()) {
Pixel update = updates.remove();
count++;
writable_image.getPixelWriter().setColor(update.getX(), update.getY(), update.getColor());
}
if (count >= max) {
this.count = 0;
this.start = -1;
stop();
}
}
public void startAnimation() {
this.start();
}
}
If you need to compute max later, then you can't initialize it to zero (because if you do any updates before it is set to its "correct" value, then count will exceed max and you will stop the animation). So just initialize it to something it will never reach, e.g. Long.MAX_VALUE.
Relatedly, since you are accessing max from multiple threads, you should either synchronize access to it, or (better) use an AtomicLong. I.e.
public class ImageAnimation extends AnimationTimer {
private Gui gui;
private AtomicLong max;
private long count, start;
ImageAnimation (Gui gui) {
this.gui = gui;
this.count = 0;
this.start = -1;
this.max = new AtomicLong(Long.MAX_VALUE);
}
public void setMax(long max) {
this.max.set(max);
}
#Override
public void handle(long timestamp) {
if (start < 0) {
start = timestamp ;
return ;
}
WritableImage writable_image = this.gui.getWritableImage();
BlockingQueue<Pixel> updates = this.gui.getUpdates();
while (timestamp - start > (count* 5_000_000) / (writable_image.getWidth()) && ! updates.isEmpty()) {
Pixel update = updates.remove();
count++;
writable_image.getPixelWriter().setColor(update.getX(), update.getY(), update.getColor());
}
if (count >= max.get()) {
this.count = 0;
this.start = -1;
this.max.set(Long.MAX_VALUE);
stop();
}
}
public void startAnimation() {
this.start();
}
}

Method error. Method cannot be applied to given types. Required: Double, Found: No arguments

I have an assigment that requires me to read data off a .txt containing gravity levels and then calculate your weight on each planet using methods. There seems to be an issue in the first method with type values? I canno tell. Any advice would be much appreciated.
/**
* Description for 7.04 Weight project
*
`* #author (Your Name)
* #version (The Date)
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
public class Weight
{
// write static methods here
// Note: formula for finding weight on a planet: Earth weight divided by Gravity constant times surface gravity
public static void getGravity(double [] gravity)throws IOException
{
File fileName = new File("gravity.txt");
Scanner inFile = new Scanner(fileName);
int i = 0;
while(inFile.hasNext())
{
gravity[i] = inFile.nextDouble();
}
}
public static void printResults(String[] name, double gravity[] ,double[] weight)
{
for (int i = 0; i <=8; i++)
{
System.out.printf(" %-7s %3.1f %7s", name[i], gravity[i] , weight[i]);
}
}
public static double[] calcWeight(double [] gravity)
{
double myWeight = 100.0;
int i = 0;
for (i = 0; i <= 8; i++)
{
gravity[i] = gravity[i] * myWeight;
}
return gravity;
}
public static void main(String[] args)throws IOException
{
// Extension idea... instead of hard codeing the weight, you may propt the user for input.
double earthWeight = 100.0; // initalize Earth weight to 100 lbs.
String[] names = {"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"};
double[] gravity = getGravity(); // static method you write
double[] weight = calcWeight(earthWeight, gravity); // static method you write
printResults(names, gravity, weight); // static method you write
} //end main
}//end class
Here's your problem:
calcWeight(earthWeight, gravity); //passes two parameters
public static double[] calcWeight(double [] gravity) //takes one paramter
The method call does not match the method definition.

algorithms how to deal with multiple criteria

find 2 rectangles A[i] and A[j] in an array A[n] rectangles such that A[i].width > A[j].width and A[i].length - A[j].length is the longest.
Is there a way to reduce the complexity to O(nlogn)? I can't find a way to get an O(logn) search for the second rectangle. Sorting doesn't seem to help here due to the possibilities of 2 criteria being completely opposite of each other. Maybe I'm just going at it wrong? direct me to the right path please. Thank you.
Note: Homework assignment using different object and using 2 criteria instead of 3, but the context is the same.
Since this is homework, here is a high-level answer, with the implementation left as a problem for the OP:
Sort the elements of the array ascending by width. Then scan down the array subtracting the current length from the highest length encountered so far. keep track of the greatest difference encountered so far (and the corresponding i and j). When done you will have the greatest length difference A[i].length-A[j].length where A[i].width > A[j].width
Analysis: sorting the elements takes O(n*Log(n)), all other steps take O(n).
Here is some java code to achieve the same::
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public class RequiredRectangle {
public static void main(String[] args) {
// test the method
int n=10;
Rectangle[] input = new Rectangle[n];
Random r = new Random();
for(int i=0;i<n;i++){
input[i] = new Rectangle(r.nextInt(100)+1,r.nextInt(100)+1);
}
System.out.println("INPUT:: "+Arrays.deepToString(input));
Rectangle[] output = getMaxLengthDiffAndGreaterBreadthPair(input);
System.out.println("OUTPUT:: "+Arrays.deepToString(output));
}
public static Rectangle[] getMaxLengthDiffAndGreaterBreadthPair(Rectangle[] input){
Rectangle[] output = new Rectangle[2];
Arrays.sort(input, new Comparator<Rectangle>() {
public int compare(Rectangle rc1,Rectangle rc2){
return rc1.getBreadth()-rc2.getBreadth();
}
});
int len=0;
Rectangle obj1,obj2;
for(int i=0;i<input.length;i++){
obj2=input[i];
for(int j=i+1;j<input.length;j++){
obj1=input[j];
int temp=obj1.getLength() - obj2.getLength();
if(temp>len && obj1.getBreadth() > obj2.getBreadth()){
len=temp;
output[0]=obj1;
output[1]=obj2;
}
}
}
return output;
}
}
class Rectangle{
private int length;
private int breadth;
public int getLength(){
return length;
}
public int getBreadth(){
return breadth;
}
public Rectangle(int length,int breadth){
this.length=length;
this.breadth=breadth;
}
#Override
public boolean equals(Object obj){
Rectangle rect = (Rectangle)obj;
if(this.length==rect.length && this.breadth==rect.breadth)
return true;
return false;
}
#Override
public String toString(){
return "["+length+","+breadth+"]";
}
}
`
Sample Output:
INPUT:: [[8,19], [68,29], [92,14], [1,27], [87,24], [57,42], [45,5], [66,27], [45,28], [29,11]]
OUTPUT:: [[87,24], [8,19]]

Stop Skeleton Flickering in Kinect for Windows

Currently working on a project to find the X,Y position of the using who is standing in front of the kinect.
Even though the user is standing still the X,Y keep changing because the kinect skeleton is flickering. Could someone help me how to figure out a way to stop the skeleton flickering
Have you set the smoothing parameter? The following settings result in very smooth movements, but with a lot of latency.
TransformSmoothParameters smoothingParam = new TransformSmoothParameters
{
Smoothing = 0.7f;
Correction = 0.3f;
Prediction = 1.0f;
JitterRadius = 1.0f;
MaxDeviationRadius = 1.0f;
};
sensor.SkeletonStream.Enable(smoothingParam);
If that is not working good enough for you, I had developed a helper class for one of my kinect projects to smooth the coordinates of joints. You have to create an instance of the following helper class for each smoothed joint and call GetSmoothedXPosition/GetSmoothedYPosition with the screen coordinates of the joint:
internal class JointSmoothing
{
#region Constants and Enumerations
private const int QueueLength = 7;
private const double BaseValue = 0.9;
#endregion
#region Fields
private readonly Queue<double> myXValues = new Queue<double>(QueueLength);
private readonly Queue<double> myYValues = new Queue<double>(QueueLength);
#endregion
#region Public Methods
public double GetSmoothedXPosition(double x)
{
if (myXValues.Count >= QueueLength)
{
myXValues.Dequeue();
}
myXValues.Enqueue(x);
return ExponentialMovingAverage(myXValues);
}
public double GetSmoothedYPosition(double y)
{
if (myYValues.Count >= QueueLength)
{
myYValues.Dequeue();
}
myYValues.Enqueue(y);
return ExponentialMovingAverage(myYValues);
}
public void Clear()
{
myXValues.Clear();
myYValues.Clear();
}
#endregion
#region Private Implementation
private static double ExponentialMovingAverage(Queue<double> values)
{
double numerator = 0;
double denominator = 0;
int valueCount = values.Count;
int weight = valueCount - 1;
foreach (double value in values)
{
numerator += value * Math.Pow(BaseValue, weight);
denominator += Math.Pow(BaseValue, weight);
weight--;
}
double average = values.Sum();
average /= values.Count;
numerator += average * Math.Pow(BaseValue, valueCount);
denominator += Math.Pow(BaseValue, valueCount);
return numerator / denominator;
}
#endregion
}

Resources