Draw Lorenz attractor from Point3f array in Java 3D - java

I have computed the values of the points I need to draw and I put them in a Point3f array. I have 526 435 points. The next step is to draw the points one after another so that it would look like a continous line OR to draw lines between the points using LineStripArray. Because I didn't find how to draw point by point, I've tried to use LineStripArray.
I've taken the code from here and I've changed the content of the method "createLineTypes" with the following code:
Group lineGroup = new Group();
Appearance app = new Appearance();
ColoringAttributes ca = new ColoringAttributes(black, ColoringAttributes.SHADE_FLAT);
app.setColoringAttributes(ca);
Computing comp = new Computing();
//the following row computes the values of the points I want to draw
//and it works alright; the points are saved into
//**static List<Vector3> computed_values** from class Computing,
// where Vector3 class defines a 3D point actually
comp.do_the_job();
Point3f[] dashPts = new Point3f[Computing.computed_values.size()];
for(int i = 0; i < Computing.computed_values.size(); i++)
{
dashPts[i] = new Point3f((int)Computing.computed_values.get(i).getX(), (int)Computing.computed_values.get(i).getY(), (int)Computing.computed_values.get(i).getZ());
}
System.out.print(Computing.computed_values.size());
int[] a = {Computing.computed_values.size()};
LineStripArray dash = new LineStripArray(Computing.computed_values.size(), LineArray.COORDINATES, a);
dash.setCoordinates(0, dashPts);
LineAttributes dashLa = new LineAttributes();
dashLa.setLineWidth(1.0f);
dashLa.setLinePattern(LineAttributes.PATTERN_SOLID);
Shape3D dashShape = new Shape3D(dash, app);
lineGroup.addChild(dashShape);
return lineGroup;
The problem is that it only draws 1 vertical line. Any ideas?

I've found a solution and it's with PointArray. Here it is
Group lineGroup = new Group();
Appearance app = new Appearance();
ColoringAttributes ca = new ColoringAttributes(black, ColoringAttributes.SHADE_FLAT);
app.setColoringAttributes(ca);
Computing comp = new Computing();
comp.do_the_job();
Point3f[] plaPts = new Point3f[Computing.computed_values.size()];
for(int i = 0; i < Computing.computed_values.size(); i++)
{
plaPts[i] = new Point3f((float)Computing.computed_values.get(i).getX(), (float)Computing.computed_values.get(i).getY(), (float)Computing.computed_values.get(i).getZ());
}
PointArray pla = new PointArray(Computing.computed_values.size(), GeometryArray.COORDINATES);
pla.setCoordinates(0, plaPts);
Shape3D plShape = new Shape3D(pla, app);
lineGroup.addChild(plShape);
return lineGroup;
Important: for my application, I had to cast the values to float, not to int as I initially did.

Related

What is wrong with the .add in my ArrayList?

I'm currently working on a simple game in java, representative of the DOS game Gorillas.bas. I'm creating an arraylist to store the individual buildings do to collision checking and whatnot, but Eclipse is giving me an error no matter how I go about it. Here is what i've got for the arraylist.
ArrayList<Rectangle> Buildings = new ArrayList<Rectangle>();
Point build1 = new Point(75,30);
Rectangle building1 = new Rectangle(build1, BUILDING_WIDTH, 150);
Buildings.add(Rectangle building1);
The error is on the .add() method, it tells me that the method needs a body instead of a semicolon. What does this mean? Is eclipse not recognizing the .add()?
EDIT: A bit of the code around it as requested; doesn't appear to have any syntax errors.
public double bananaX = 85;
public double bananaY = 292;
public double bananaDX = 1;
public double bananaDY = 1;
public double power = 0;
public double direction = 0;
public double rise;
public double run;
Point start = new Point(0,0);
Point finish = new Point(0,0);`
ArrayList<Rectangle> buildings = new ArrayList<Rectangle>();
Point build1 = new Point(75,350);
Point build2 = new Point(225, 250);
Point build3 = new Point(325, 200);
Point build4 = new Point(425, 200);
Point build5 = new Point(525, 250);
Point build6 = new Point(675, 350);
Rectangle building1 = new Rectangle(build1, BUILDING_WIDTH, 150);
buildings.add(building1);
public void power(Point start, Point finish)
{
int power = 0;
power = (int)start.distanceTo(finish);
}
public void direction(Point start, Point finish)
{
double direction = 0;
rise = (finish.y - start.y)*-1;
run = (finish.x - start.x)*-1;
direction = rise/run;
bananaDX = run/10;
bananaDY = (rise/10);
System.out.printf("rise = %f\nrun = %f\ndirection = %f\n\n ",rise, run, direction);
}
You just need to have:
Buildings.add(building1);
Since building1 is already a Rectangle. You have already created the Rectangle object above it so you only need to use the variable itself because it is of the correct type.
Edit: You should probably also rename Buildings buildings to avoid any confusion. When you name a variable with a capital letter it looks like a type and not a variable.
Edit2: Based on the code you provided, you need to have buildings.add(building1); inside of a method of some sort. You should create an initialize method that gets called at the start if you want to have it added in at the beginning.
Don't double up on Rectangle.
Buildings.add(building1);

Stitching 2 images (OpenCV)

I'm trying to stitch two images together, using the OpenCV Java API. However, I get the wrong output and I cannot work out the problem. I use the following steps:
1. detect features
2. extract features
3. match features.
4. find homography
5. find perspective transform
6. warp perspective
7. 'stitch' the 2 images, into a combined image.
but somewhere I'm going wrong. I think it's the way I'm combing the 2 images, but I'm not sure. I get 214 good feature matches between the 2 images, but cannot stitch them?
public class ImageStitching {
static Mat image1;
static Mat image2;
static FeatureDetector fd;
static DescriptorExtractor fe;
static DescriptorMatcher fm;
public static void initialise(){
fd = FeatureDetector.create(FeatureDetector.BRISK);
fe = DescriptorExtractor.create(DescriptorExtractor.SURF);
fm = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE);
//images
image1 = Highgui.imread("room2.jpg");
image2 = Highgui.imread("room3.jpg");
//structures for the keypoints from the 2 images
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
MatOfKeyPoint keypoints2 = new MatOfKeyPoint();
//structures for the computed descriptors
Mat descriptors1 = new Mat();
Mat descriptors2 = new Mat();
//structure for the matches
MatOfDMatch matches = new MatOfDMatch();
//getting the keypoints
fd.detect(image1, keypoints1);
fd.detect(image1, keypoints2);
//getting the descriptors from the keypoints
fe.compute(image1, keypoints1, descriptors1);
fe.compute(image2,keypoints2,descriptors2);
//getting the matches the 2 sets of descriptors
fm.match(descriptors2,descriptors1, matches);
//turn the matches to a list
List<DMatch> matchesList = matches.toList();
Double maxDist = 0.0; //keep track of max distance from the matches
Double minDist = 100.0; //keep track of min distance from the matches
//calculate max & min distances between keypoints
for(int i=0; i<keypoints1.rows();i++){
Double dist = (double) matchesList.get(i).distance;
if (dist<minDist) minDist = dist;
if(dist>maxDist) maxDist=dist;
}
System.out.println("max dist: " + maxDist );
System.out.println("min dist: " + minDist);
//structure for the good matches
LinkedList<DMatch> goodMatches = new LinkedList<DMatch>();
//use only the good matches (i.e. whose distance is less than 3*min_dist)
for(int i=0;i<descriptors1.rows();i++){
if(matchesList.get(i).distance<3*minDist){
goodMatches.addLast(matchesList.get(i));
}
}
//structures to hold points of the good matches (coordinates)
LinkedList<Point> objList = new LinkedList<Point>(); // image1
LinkedList<Point> sceneList = new LinkedList<Point>(); //image 2
List<KeyPoint> keypoints_objectList = keypoints1.toList();
List<KeyPoint> keypoints_sceneList = keypoints2.toList();
//putting the points of the good matches into above structures
for(int i = 0; i<goodMatches.size(); i++){
objList.addLast(keypoints_objectList.get(goodMatches.get(i).queryIdx).pt);
sceneList.addLast(keypoints_sceneList.get(goodMatches.get(i).trainIdx).pt);
}
System.out.println("\nNum. of good matches" +goodMatches.size());
MatOfDMatch gm = new MatOfDMatch();
gm.fromList(goodMatches);
//converting the points into the appropriate data structure
MatOfPoint2f obj = new MatOfPoint2f();
obj.fromList(objList);
MatOfPoint2f scene = new MatOfPoint2f();
scene.fromList(sceneList);
//finding the homography matrix
Mat H = Calib3d.findHomography(obj, scene);
//LinkedList<Point> cornerList = new LinkedList<Point>();
Mat obj_corners = new Mat(4,1,CvType.CV_32FC2);
Mat scene_corners = new Mat(4,1,CvType.CV_32FC2);
obj_corners.put(0,0, new double[]{0,0});
obj_corners.put(0,0, new double[]{image1.cols(),0});
obj_corners.put(0,0,new double[]{image1.cols(),image1.rows()});
obj_corners.put(0,0,new double[]{0,image1.rows()});
Core.perspectiveTransform(obj_corners, scene_corners, H);
//structure to hold the result of the homography matrix
Mat result = new Mat();
//size of the new image - i.e. image 1 + image 2
Size s = new Size(image1.cols()+image2.cols(),image1.rows());
//using the homography matrix to warp the two images
Imgproc.warpPerspective(image1, result, H, s);
int i = image1.cols();
Mat m = new Mat(result,new Rect(i,0,image2.cols(), image2.rows()));
image2.copyTo(m);
Mat img_mat = new Mat();
Features2d.drawMatches(image1, keypoints1, image2, keypoints2, gm, img_mat, new Scalar(254,0,0),new Scalar(254,0,0) , new MatOfByte(), 2);
//creating the output file
boolean imageStitched = Highgui.imwrite("imageStitched.jpg",result);
boolean imageMatched = Highgui.imwrite("imageMatched.jpg",img_mat);
}
public static void main(String args[]){
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
initialise();
}
I cannot embed images nor post more than 2 links, because of reputation points? so I've linked the incorrectly stitched images and an image showing the matched features between the 2 images (to get an understanding of the issue):
incorrect stitched image: http://oi61.tinypic.com/11ac01c.jpg
detected features: http://oi57.tinypic.com/29m3wif.jpg
It seems that you have a lot of outliers that make the estimation of homography is incorrect. SO you can use RANSAC method that recursively reject those outliers.
No need much efforts for that, just use a third parameter in findHomography function as:
Mat H = Calib3d.findHomography(obj, scene, CV_RANSAC);
Edit
Then try to be sure that your images given to detector are 8-bit grayscale image, as mentioned here
The "incorrectly stitched image" you post looks like having a bad conditioned H matrix. Apart from +dervish suggestions, run:
cv::determinant(H) > 0.01
To check if your H matrix is "usable". If the matrix is badly conditioned, you get the effect you are showing.
You are drawing onto a 2x2 canvas size, if that's the case, you won't see plenty of stitching configurations, i.e. it's ok for image A on the left of image B but not otherwise. Try drawing the output onto a 3x3 canvas size, using the following snippet:
// Use the Homography Matrix to warp the images, but offset it to the
// center of the output canvas. Careful to pre-multiply, not post-multiply.
cv::Mat Offset = (cv::Mat_<double>(3,3) << 1, 0,
width, 0, 1, height, 0, 0, 1);
H = Offset * H;
cv::Mat result;
cv::warpPerspective(mat_l,
result,
H,
cv::Size(3*width, 3*height));
// Copy the reference image to the center of the 3x3 output canvas.
cv::Mat roi = result.colRange(width,2*width).rowRange(height,2*height);
mat_r.copyTo(roi);
Where width and height are those of the input images, supposedly both of the same size. Note that this warping assumes the mat_l unchanged (flat) and mat_r warping to get stitched on it.

Android featureDetector out of Bounds

at the moment Iam working with Android Opencv. Iam Using the featureDetector with the Method FAST to find KeyPoints on an 240 x 320 Image.
//create a keypoint mat
MatOfKeyPoint keyPoints = new MatOfKeyPoint();
//create feature detector
FeatureDetector fd = FeatureDetector.create(FeatureDetector.FAST);
//detect feature points
fd.detect(image, keyPoints);
//return feature points
return keyPoints;
Next I will extract the points from the KeyPoints after Matching them:
DMatch[] matchesArray = matches.toArray();
Vector<Point> pointsVec1 = new Vector<Point>();
Vector<Point> pointsVec2 = new Vector<Point>();
for(int i = 0; i < matchesArray.length; i++)
{
pointsVec1.add(keyPoints1.toArray()[matchesArray[i].queryIdx].pt);
pointsVec2.add(keyPoints2.toArray()[matchesArray[i].trainIdx].pt);
}
points1.fromList(pointsVec1);
points2.fromList(pointsVec2);
Later I try to get the pixel color of these points, doing this:
Point[] pointsArray = points.toArray();
Vector<byte[]> colorVector = new Vector<byte[]>();
for(int i = 0; i< pointsArray.length; i++)
{
Point point = pointsArray[i];
byte[] color = new byte[4];
image.get((int) point.x, (int) point.y, color);
colorVector.add(color);
}
return colorVector;
Iam still wondering because there are Points out of border of the Image. For example I found this point by debugging: (308.0, 16.0). By an 240 x 340 Image this point is not in the image. There are more Point of these. I checked already the featureExtractor and the Point is already containing there. So i get a color of R = 0, G = 0, B = 0.
So my question is:
Where does this Points come from?
Have I to filter them on my own or is there something like Threshhold solution in the function?
Or I have to switch x and y or change the conversion of the Points?
In the end it is a small problem but i cant explain myself where doese they come from!
So thanks for your help!
Make sure you have not switch x <-> y or row <-> col.

How can I cast an object as another in java? "javafx.scene.Group cannot be cast to javafx.scene.shape.Rectangle"

How can I change the attributes of objects that are stored in a grid? I tried this, but it gives me the above error:
Group group = new Group();
double dimension_x=100;
double dimension_y=100;
GridPane grid = new GridPane();
grid.setHgap(1);
grid.setVgap(1);
grid.setPadding(new Insets(36));
grid.setGridLinesVisible(true);
Rectangle temp = new Rectangle(dimension_x,dimension_y);
Rectangle temp2 = new Rectangle(dimension_x,dimension_y);
Rectangle temp3 = new Rectangle(dimension_x,dimension_y);
Rectangle temp4 = new Rectangle(dimension_x,dimension_y);
grid.add(temp, 0,0);
grid.add(temp2, 1,1);
grid.add(temp3, 2,2);
grid.add(temp4, 3,3);
for (final Node node : grid.getChildren())
{
Rectangle tempvar = (Rectangle) node; //Errors out at javafx.scene.Group cannot be cast to javafx.scene.shape.Rectangle
node.getStyleClass().add("box");
//tempvar.setFill(Color.TRANSPARENT);
//tempvar.setStroke(Color.WHITE);
}
is there any way to loop through my grid and change the objects?
Print the result of grid.getChildren().
I'm suspicious that grid contains other objects other those 4 Rectangle

JFreeChart to represent 3D data in a 2D graph using colourmaps

I'm currently trying to use JFreeChart to represent 3D data in a 2D graph.
Essentially, I have a 2d array called data[i][j]. The i and j represent the y and x coordinates where I want to plot. The value of data[i][j] represents a frequency value, which I want to represent in the graph as a colour.
I'm not entirely sure what something like this is called, but it would look something like this:
Now I have been trying to do this using XYBlockRenderer, however I am having issues with defining the dataset. I am trying to use DefaultXYZDataset, but I'm really confused at how to even define the data here.
Can someone explain how to use the DefaultXYZDataset to accomplish such a task?
DefaultXYZDataset dataset = new DefaultXYZDataset();
Concentration.dataoutHeight = Concentration.dataout[0].length;
System.out.println(Concentration.dataoutHeight);
System.out.println(ImageProcessor.MAXCBVINT);
double[][] data = new double[3][ImageProcessor.MAXCBVINT];
for (int i = 0; i < Concentration.dataoutHeight; i++) {
for (int j = 0; j < ImageProcessor.MAXCBVINT; j++) {
data[0][j] = j;//x value
data[1][j] = i;//y value
data[2][j] = Concentration.dataout[j][i][0];//Colour
}
dataset.addSeries(i, data);
}
NumberAxis xAxis = new NumberAxis("Intensity");
xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
xAxis.setLowerMargin(0.0);
xAxis.setUpperMargin(0.0);
NumberAxis yAxis = new NumberAxis("Distance to Closest Blood Vessel (um)");
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
yAxis.setLowerMargin(0.0);
yAxis.setUpperMargin(0.0);
XYBlockRenderer renderer = new XYBlockRenderer();
PaintScale scale = new GrayPaintScale(0, 10000.0);
renderer.setPaintScale(scale);
renderer.setBlockHeight(1);
renderer.setBlockWidth(1);
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinesVisible(false);
plot.setRangeGridlinePaint(Color.white);
JFreeChart chart = new JFreeChart("Surface Plot", plot);
chart.removeLegend();
chart.setBackgroundPaint(Color.white);
ChartFrame frame = new ChartFrame("Surface Map - "
+ (Concentration.testing ? "TESTING using "
+ Concentration.testfile : currentFile.getName()), chart);
frame.pack();
frame.setVisible(true);
You have two options:
Represent them as 3d
3D Lib for JFreeChart
You need to use the class : XYBlockRenderer which does exactly what you are asking. You can download the JFreeChart demo collection where the code for this is given.
(source code of class here)
There is also this full code example with 4D very similar.

Categories