We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi all,
I am having a starting problem. I don't know how I can integrate java files and classes in my processing code. Can anybody tell me how to do it, such that I can build my own library? Or alternatively, can you point me out to a tutorial that clearly describes it?
In the code that is supplied (see below), I call in the draw()-function two other functions: calculateClosestPoint() and displayInfo(). In the function Mousepressed() I call the functio n saveDepthMap().
I would like to have all three functions - calculateClosestPoint(), displayInfo() and saveDepthMap() - as java classes in a library such that I can reuse them in different processing sketches. I have looked around but I have not been able to find an explanation that was clear to me.
From what I have read, it should be rather straight forward, but have not been able yet to get it working. I would really appreciate some help. I am familiar with eclipse and I am at beginners level in java. I have reasonable experience in programming c++.
Thank you very much in advance.
/*************************************************************************
DESCRIPTION : Test voor het werken met Kinect Depth maps
Code based on samples from "Making things see"
VERSION : 150408
***************************************************************************/
import SimpleOpenNI.*;
SimpleOpenNI asus;
//=========================================
// Global variables
//=========================================
// Variables for user enabled choices
//-----------------------------------
// Variables for fileHandling
String gDepthMapDir = "D:/Alldata/Programmeren/Processing_Coding/Sketches_PME/PME/PME_ToProcessingForum_150415/Data/";
String gFileName = "";
String gFileExt = ".xyz";
String gFileTextSep = " ";
// Variables for informing the user
boolean dispFramerateInfo = true;
boolean dispCornerInfo = true;
boolean dispClosestPoint = true;
// Variables for showing displays
boolean gMirrorImg = true;
int gFramerate = 10;
boolean dispRGB = true;
// Variables for calculations
//---------------------------
// Tracking variables for depth
int closestValue;
int closestX;
int closestY;
// Variables for averaging closest point depths
int n = 5;
int[] recentXvalues = new int[n];
int[] recentYvalues = new int[n];
int ctrAvg = 0;
int sumXvalues = 0;
int sumYvalues = 0;
// Variables for handling the image
int imageWidth = 640;
int imageHeight = 480;
int[] depthValues = new int[imageWidth * imageHeight];
PImage rgbImage;
// Variables for storing files
String gDateTimeStart; // Start time of the program
//=========================================
// setup() & draw()
//=========================================
void setup()
{
// Register the time that the program was started
gDateTimeStart =
str(year()) + nf(month(),2) + nf(day(),2) + "_" +
nf(hour(),2) + nf(minute(),2) + nf(second(),2);
size(imageWidth, imageHeight,OPENGL);
frameRate(gFramerate); // Set frameRate to xx fps
asus = new SimpleOpenNI(this);
asus.enableDepth();
//if (dispRGB == true) size(imageWidth*2, imageHeight,OPENGL);
if (dispRGB == true) asus.enableRGB();
if (gMirrorImg == true) asus.setMirror(true);
} // <EOR> setup()
void draw()
{
// Get the depth image
//-------------------------
asus.update();
depthValues = asus.depthMap();
PImage depthImage = asus.depthImage();
image(depthImage, 0, 0);
if (dispRGB == true)
{
rgbImage = asus.rgbImage();
//image(rgbImage, imageWidth,0);
}
// Calculate closest point
//------------------------
calculateClosestPoint();
// Inform the user
//----------------
displayInfo();
} // <EOR> draw()
//================================================
// Userdefined functions
//================================================
void mousePressed()
{
int[] depthValues = asus.depthMap();
int clickPosition = mouseX + mouseY*640;
int clickDepth = depthValues[clickPosition];
if (mouseButton == RIGHT)
// Save the depthimage to a file
{
saveDepthMap();
} // if (mouseButton == RIGHT)
else
{
float cm = clickDepth /10.0;
println (mouseX+","+mouseY+ "\tAfstand = " + cm);
}
} // <EOF> mousPressed()
/*************************************************************************
FUNCTION : displayInfo()
DESCRIPTION : Displays user required information in the kinect image
VERSION : jjmmdd
MODS : PME150704 : Initial code
***************************************************************************/
void displayInfo()
{
// Variables for corner information
int cornerDV = 0; // Element number for the element in the
int distFromSide = 10; // Distance from the side of the image
int cornerX;
int cornerY;
// Coordinates of ulc for placing framerate info
int framerateinfoX = 0;
int framerateinfoY = imageHeight / 2;
// Coordinates of mrs (middel right side) of tracking infromation.
int trackX = imageWidth;
int trackY = imageHeight / 2;
// Display closest point information
//-----------------------------------
if (dispClosestPoint == true)
{
// Draw a red circle over the closest point
fill (255,0,0);
ellipse (closestX, closestY, 3, 3);
// Place a text, showing the measured distance
// including the coordinates at which it was measured.
textAlign(CENTER,BASELINE);
textSize (20);
text(str(closestValue), closestX, closestY);
// Let the user know where the closest point is
//fill (255,255,128);
textSize (15);
textAlign(RIGHT,CENTER);
text("(" + str(closestX)+"," + str(closestY)+")", trackX,trackY);
// textAlign(CENTER,TOP);
//text("(" + str(closestX)+"," + str(closestY)+")", closestX,closestY);
} // if (dispClosestPoint == true)
// Display corner information
//---------------------------
if (dispCornerInfo == true)
{
fill (55,55,255);
// Upper Left Corner
cornerX = 0 + distFromSide;
cornerY = 0 + distFromSide;
cornerDV = cornerX + (cornerY * imageWidth);
textAlign (LEFT,TOP);
textSize(15);
ellipse (cornerX,cornerY, 5,5);
text(str(depthValues[cornerDV]), cornerX,cornerY);
// Upper Right Corner
cornerX = imageWidth - distFromSide;
cornerY = 0 + distFromSide;
cornerDV = cornerX + (cornerY * imageWidth);
textAlign (RIGHT,TOP);
textSize(15);
ellipse (cornerX,cornerY, 5,5);
text(str(depthValues[cornerDV]), cornerX,cornerY);
// Lower Left Corner
cornerX = 0 + distFromSide;
cornerY = imageHeight - distFromSide;
cornerDV = cornerX + (cornerY * imageWidth);
textAlign (LEFT,BOTTOM);
textSize(15);
ellipse (cornerX,cornerY, 5,5);
text(str(depthValues[cornerDV]), cornerX,cornerY);
// Lower Right Corner
cornerX = imageWidth - distFromSide;
cornerY = imageHeight - distFromSide;
cornerDV = cornerX + (cornerY * imageWidth);
textAlign (RIGHT,BOTTOM);
textSize(15);
ellipse (cornerX,cornerY, 5,5);
text(str(depthValues[cornerDV]), cornerX,cornerY);
} // if (dispCornerInfo == true)
// Display Framerate information
//------------------------------
if (dispFramerateInfo == true)
{
fill (255,255,128);
// Place the framerate
textAlign(LEFT,TOP);
text("Framerate = " + str(round(frameRate)), framerateinfoX,framerateinfoY);
text("\n#Frames = " + str(round(frameCount)), framerateinfoX,framerateinfoY);
} // if (dispFramerateInfo == true)
} // <EOR> displayInfo()
/*************************************************************************
FUNCTION : saveDepthMap()
DESCRIPTION : Displays user required information in the kinect image
VERSION : jjmmdd
***************************************************************************/
void saveDepthMap()
{
String thisFUNCTION = "saveDepthMap()";
int startMillis = millis();
int n = (imageWidth) * (imageHeight);
String[] data = new String[n];
String timestamp;
String fileName;
timestamp = gDateTimeStart + "+" + str(millis());
for (int y = 0; y < imageHeight; y++ )
{
for (int x = 0; x < imageWidth; x++)
{
int ctr = x + y * imageWidth; // Columnwise accessing of the array.
data[ctr] = str(x) + gFileTextSep + // X
str(y) + gFileTextSep + // Y
str(depthValues[ctr]);
}
}
// Save to File
// The same file is overwritten by adding the data folder path to saveStrings().
if (gFileName == "")
{
fileName = timestamp;
}
else
{
fileName = gFileName;
}
if (gDepthMapDir != "")
{
saveStrings(gDepthMapDir + fileName + gFileExt, data);
}
else
{
saveStrings("data/" + fileName + gFileExt, data);
}
// Finalise function
//----------------------------------
println (thisFUNCTION + "-> Processing time = " + (millis() - startMillis) + "ms");
} // void saveDepthMap()
/*************************************************************************
FUNCTION : calculateClosestPoint()
DESCRIPTION : Calculate the closest point in the depthimage
VERSION : jjmmdd
***************************************************************************/
void calculateClosestPoint()
{
// Prelimnary calculations
closestValue = 8000;
// Start calculation closete point
//--------------------------------
for (int y=0; y<imageHeight; y++)
{
for (int x=0; x<imageWidth; x++)
{
int i = x + (y*imageWidth);
int currDepthValue = depthValues[i];
if ((currDepthValue > 0) && (currDepthValue < closestValue))
{
// Set the closest depth value
closestValue = currDepthValue;
closestX = x;
closestY = y;
// Update the averaging array
recentXvalues[ctrAvg] = x;
recentYvalues[ctrAvg] = y;
}
}
} // for (int y=0; y<imageHeight; y++)
// Calculate the average position
ctrAvg++;
if (ctrAvg > (n-1)) ctrAvg = 0;
sumXvalues = 0;
sumYvalues = 0;
for (int ctr=0; ctr<n; ctr++)
{
sumXvalues += recentXvalues[ctr];
sumYvalues += recentYvalues[ctr];
}
closestX = sumXvalues / n;
closestY = sumYvalues / n;
} // <EOF> calulateCLosestPoint()
Answers
IMO all of those 3 methods, calculateClosestPoint(), displayInfo(), saveDepthMap(), are unfit for a separate class, much less belong to their own library!
At most they coulda be saved as snippets in some file and copy'n'pasted in sketches that need'em.
Now the harder part, explaining the reasons why:
extends
PApplet and it's a full Java class instance.Basically, the problem w/ your 3 functions is how much they are bound to the sketch's instance.
For instance, calculateClosestPoint() directly reads and writes sketch's fields like closestValue, imageHeight, recentXvalues, etc.
In short, it acts upon the sketch's data and should stay as it is now as a sketch's method.
And displayInfo() & saveDepthMap() go even further in how much they depend on the sketch's state.
Besides having the same problem about depending on the sketch's fields, they also call stateful Processing's API methods.
Anything which acts upon the sketch's canvas or needs to know its folder path demands the sketch's reference if they belong to another external class or library!
Well, any further doubts just ask here again! B-)
Hi GoToLoop,
Thanks for the reply. It makes a lot of sense and it is just the dependency on the sketch that I want to remove. Also, I do not like the extensive use of the global variables as shown in the example. Therefore I am now re-wrting the methods calculateClosestPoint(), displayInfo() and saveDepthMap() into a java class such that these can take arguments. By doing this I remove the dependencies from the sketch and disconnect calculation from the user interface.
When I have finished re-wrting, I will be in a better position to create a library from the classes and I will ask teh question again.
Anyway, thanks a lot. You pointed me in a good direction.
So now I rewrote the code to replace calculateClosestPoint(), displayInfo() and saveDepthMap with two classes: CanvasUpdater{} and CalculationManager{}. The CanvasUpdater takes care of the placing user defined texts on the canvas and the CalculationManager takes care of the calculations. See the code below.
I think I have separated them from the sketch now in the sense that these do not act on the sketch's data anymore. As such they may be candidates to be included in a library.
Now suppose I want to plut them in a library called "myCanvasHandler", how should I proceed? Could anyone point me in the right direction (an explanation in this forum or a link to a tutorial etc).
And if that is still not possible, what is the next best option? I guess it is placing them as snippets in some file (as described earlier), but that leaves me with the questions: where to place that file and how do I include that file in my main sketch?
Thanks in advace for your feedback.