So here's the thing, I'm supposed to read a document and import some data.
A line in the document looks like this "A 0 2 5 20 23 25." (.txt).
I can write a method that finds this line and the values but my problem is to draw the actual graph whith the values. X of the graph will be fixed for 10 between each value and the values in the file corresponds to Y. I want to come up with a method that takes the first Y(0), and Draws a straight line to the next Y(2) and from 2-5 etc.
I fail to do this, my method only Draws a line from 0-2 and 5-20 and 23-25.
Book hasn't talked about array's yet so I should do this without arrays, I try to do it as I read the file but..
Here is a bit of my code anyway, any tips?? Much appreciated
public static void drawGraph(String letter, Scanner input, Graphics g){
while (input.hasNextLine()){
int x = 1;
String text = input.nextLine();
Scanner data = new Scanner(text);
String foundLetter = data.next();
if(foundLetter.equalsIgnoreCase(letter)){
while(data.hasNextInt()){
int count = data.nextInt();
//This is where I get Stuck
g.drawLine((x-1)*10, y1, 10*x);
x++;
}
}
}
}
I have made an template drawingpanel for the plot divided into sections of 10's
Thanks,
You have to memorize the last y value, then draw a line from (x-1, last y) to (x, y).
int lastY = data.nextInt();
while (data.hasNextInt()) {
int nextY = data.nextInt();
g.drawLine((x-1)*10, lastY, 10*x, nextY);
x++;
lastY = nextY;
}
Related
Consider a matrix of order m*n.
It has l layers.
I need to rotate each layer in anticlockwise direction.
Like this
This is the code I came up with.
int a1=0; // a1,a2,a3,a4 are counters which start at beginning and the end of each row and column and are then moved to the next layers
int a2=m-1;
int a3=n-1;
int a4=0;
for(int j=0;j<l;j++) // l is the layers of the matrix
{
c=rotate(a,a1,a2,a3,a4);
a1++;
a2--;
a3--;
a4++;
}
And this is the rotate method, which rotates the array passed,which is a, by 1 unit
public static int[][] rotate(int a[][],int a1,int a2,int a3,int a4){
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(j==a1 && i<a2)
c[i+1][j]=a[i][j];
if(i==a2&& j<a3)
c[i][j+1]=a[i][j];
if(j==a3 && i>a4)
c[i-1][j]=a[i][j];
if(i==a4 && j>a1)
c[i][j-1]=a[i][j];}}
return c;}
Note that c is a global variable, which is the 2D array to be printed.
This works fine for a single rotation.
But I need to rotate the matrix 'r' times.
For this I tried this,
for(int i=0;i<r;i++)
{
int a1=0;
int a2=m-1;
int a3=n-1;
int a4=0;
for(int j=0;j<l;j++)
{
c=rotate(c,a1,a2,a3,a4); // c was initialized to a
a1++;
a2--;
a3--;
a4++;
}
}
But this gives a very weird output where most of the spaces are filled with the integer 2.
Is there a simpler way of doing so? I was thinking of replacing c[i+1][j] with c[i+r][j] in rotate(), i.e replacing 1 by r in rotate() but even this gave a weird output with zeroes in some places.
public static int[][] rotate(int a[][],int a1,int a2,int a3,int a4){
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(j==a1 && i+r<a2) //a1,a2
c[i+r][j]=a[i][j];
if(i==a2 && j+r<a3) //a2,a3
c[i][j+r]=a[i][j];
if(j==a3 && i-r>a4) //a3,a4
c[i-r][j]=a[i][j];
if(i==a4 && j-r>a1) //a4,a1
c[i][j-r]=a[i][j];}}
return c;}
How should I resolve this?
Here's a very high-level overview of how I solved the problem. Maybe not the most efficient solution, so let me know if you can improve.
We should use modulo to "rotate" the matrix, so first form an array of rings, starting from the outermost ring and finishing with the innermost.
Here I defined a few key points on the ring: top_right, bottom_right, and bottom_left, where each point corresponds to an index on the ring. Use these points to decide where on the matrix you map your points from.
Now reconstruct the matrix from the array of rings, using the rotations % ring_length as the pointer, just like you would do with regular array rotation.
Is there an efficient algorithm to find straight lines from an unsorted collection of x/y coordinates?
It would be ideal if:
a line is only recognized if at least n (more than two) points are aligned.
It allows a tolerance, so for example the following three coordinates would be considered a (horizontal) line: 10/100, 20/99, 30/100.
Is there some kind of standard approach to solve this? Maybe any (java) libraries? How would you solve it?
I would suggest using two maps, one for horizontal lines and one for vertical ones.
for every point, the key is the X or Y coordinate and the value is the point (use a list of points as values). Now go over the maps, and for each key show the points if there are more than one point, for each key, you should also count the points in the next keys (like in the case of 99 and 100).
I'm not sure if there'd be an efficient algorithm unless you already know of some relationship between the points.
The algorithm I outline below I guess would run in n^4 time.
You'd have something like
public class Line
{
static float tolerance;
float m, cLower, cUpper;
ArrayList<Point> onThisLine = new ArrayList<Point>();
public Line(double m, double c)
{
this.m = m;
cLower = c-tolerance;
cUpper = c+tolerance;
}
public boolean fitsInLine(Point xy)
{...}
public void addToList(Point xy)
{...}
}
where m and c represent what we learned in high school as the gradient and constant of the straight line.
For each point you'd have to compare it to every other point, generate a Line object, and then compare the new Line object to every existing Line and if it doesn't already exist then add it. Note that due to the slight tolerance you allow you consequentially have to allow for a similarity between Lines.
For example, y=-x/10+101 and y=100 are very similar line equations.
Finally, for each Line object you could get the size of the ArrayList keeping Points that fit on it, and throw away Lines that have less Points than what you want.
If you take a pair of points Pi and Pj, you can check in O(n) time which points lie on or near the line Pi Pj. There are O(n2) pairs, so you get an algorithm which is O(n3). Of course, if Pk is exactly on the line Pi Pj, you should no longer check lines Pi Pk and Pj Pk, because they will contain the same points as Pi Pj. However, this is not true if Pk is just close to Pi Pj.
I have made the algorithm displayed below. What it does is it calculates the formula of the line: y= kx+l; Then it makes two lines parallel to that one, one slightly raised and one slightly lowered->(y = kx+l-d and y=kx+l+d, d=tolerance). Then it goes through the rest of points and calculates the y for their x for the upper and lower parallel. If it's real value is between the calculated values it counts as beeing on the line.This is O(n^3).
Code:
public static void main(String[] args) {
Point[] points = generatePoints(5);
List<Set<Point>> lines = findLines(points,2,3);
lines.forEach((line)->{
System.out.println(Arrays.toString(line.toArray()));
});
}
private static List<Set<Point>> findLines(Point[] points,int tolerance,int minNumberOfPoints) {
List<Set<Point>> lines = new LinkedList<>();
for(int i=0;i<points.length;i++){
for(int j=i+1;j<points.length;j++){
//check if that line was all ready found
boolean hasBoth = false;
for(Set<Point> line:lines){
hasBoth =Boolean.logicalAnd(line.contains(points[i]),line.contains(points[j]));
if(hasBoth)
break;
}
if(hasBoth)
break;
int x1 = points[i].getX();
int y1 = points[i].getY();
int x2 = points[j].getX();
int y2 = points[j].getY();
double k = (double)(y1-y2)/(double)(x1-x2);
double l = y1-k*x1;
//y = kx + l -> line
//y1 = kx + l - tolerance -> lower parallel line
//y2 = kx + l + tolerance -> upper parallel line
//take a third point if for its x it gives a y3 where y1<=y3<=y2 then it should be part of the line
Set<Point> line = new HashSet<>();
line.add(points[i]);
line.add(points[j]);
for(int z=j+1;z<points.length;z++){
int x3 = points[z].getX();
int y3 = points[z].getY();
double y1Line = k*x3+l-tolerance;
double y2Line = k*x3+l+tolerance;
if(y1Line<=y3 && y3<=y2Line)
line.add(points[z]);
}
lines.add(line);
}
}
lines = lines.stream().filter((set)->{
return set.size()>=minNumberOfPoints;
}).collect(Collectors.toList());
return lines;
}
private static Point[] generatePoints(int number) {
Point[] points = new Point[number];
Random r = new Random();
for(int i=0;i<number;i++){
points[i] = new Point(r.nextInt(10), r.nextInt(10));
}
return points;
}
private static class Point{
private int x;
private int y;
public Point(int x,int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public String toString() {
return "("+x+","+y+")";
}
}
You could use Hough transformation to detect lines. I experienced hough transformation while detecting features in images. It basically uses polar representation of lines to detect them. Although I think opencv is out of the context for what you want to do, I still want to share the hough line detection page with you which explains the algorithm pretty clearly.
http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html
There is also this source which I had found to be useful :
https://www.cs.sfu.ca/~hamarneh/ecopy/compvis1999_hough.pdf
to describe my issue I must first discuss what I am trying to do, http://i.imgur.com/rcHwze5.png here is an image of a letter with a 10*10 grid over it. For every box in the grid if 1/3 of the pixels are colored a 1 is added to the ArrayList, otherwise a 0 is added. Here is my 3 methods that I have created to do this: https://gist.github.com/VincentMc/7ddf3c282e80bbff7835 BoundBM is a bitmap object with the letter drawn onto it.
Here is an image of my desired output http://i.imgur.com/B0QnUW8.png
Here is an image of my actual output http://i.imgur.com/WgRVXLv.png
It seems once a 1 is added on a row it is constantly added until it reaches the next row, but I can't seem to see why??
Any help would be greatly appreciated I have been at this quite a while, Thanks!
do it in two step:
1: sort each string:
public String sortString(String s1){
char[] chars = s1.toCharArray();
Arrays.sort(chars);
String sorted = new String(chars);
return sorted;
}
2: put each of your string in an array and use:
Arrays.sort(stringArray);
Out of the Code-Segmet you offered, i cant see an obvious mistake. But your design is inviting mistakes. To avoid these you may try:
Don't use count as a classwide variable, thou its not relevant for the hole class but only for the method. So make it an return statement, that you dont loose control over it, that it may be set anywhere or is only changed locally in a method.
totalp should not be calculated in every countPixel() method call, because it is a fixed value for your BoundBM. Initialize it in your constructor maybe, or with loading the bitmap.
At last, you know how large your output array is supposed to be, it doesnt make much sense for me, to keep it a list and to add it. Create an 2D array, and write it directly.
Hope it will help
reineke
EDIT: found the mistake!
in code line 27 you set x to 0 and not to the initial value of the input x, so you continue at the wrong position!!
Here is what i would do:
final int GRID=10;
totalp = boundBM.getWidth()/GRID * boundBM.getHeight()/GRID;
//this method now does not need to read boundBM, so it is more opject-oriented
public int countPixels(int x, int y, int h, int w){
count = 0;
for (i=x; i<x+w; i++){
for(k =y; k<y+h; k++){
if(c != boundBM.getPixel(i, k)) count++;
}
}
//funny thing
return (count>totalp/3) ? 1 : 0;
}
public void createNeuralInput(){
int h = boundBM.getHeight()/GRID;
int w = boundBM.getWidth()/GRID;
int[][] array= new int[GRID][GRID];
for(int i = 0; i < GRID; i++) {
for(int j = 0; j < GRID ; j++) {
n1.add(countPixels(i*h, j*w, h, w));
//i would prefer:
//array[i][j]=countPixels(i*h, j*w);
}
}
}
I am working on a project that draws an X out of multiple x's and the number of x's in a diagonal is given by the user. For example if the number given by the user is 4, it would look like this:
X X
XX
XX
X X
I have written a program with a print diagonal method, the problem occurs when I draw the second diagonal because it draws the second diagonal below the first one in the console. It looks like this:
X
X
X
X
X
X
X
X
I'm wondering if it is possible to set the console line back to the beginning so that I could draw another diagonal from the top. I've looked into System methods but I have not been able to find anything. Any suggestions appreciated.
Thanks
It will be better to print all your output into an 2D array, and print it all at the end of your program. I will be much easier than manipulating the console cursor locations.
Of course it's possible to set cursor locations. I think you'd better lookup some ascii characters such as '\b' (backspace) that is used to directly manipulate cursor locations. However, I think array-based solution will be much easier, and portability is guaranteed.
Here a solution manipulating strings, without moving the cursor on the console.
Print_X(4);
Output:
X X
XX
XX
X X
Function:
public static void Print_X (int num) {
String str;
for(int i=0;i<num;i++) {
str="";
for(int n=0;n<num;n++) str += " ";
str=str.substring(0,i)+'X'+str.substring(i+1);
str=str.substring(0,(num-1)-i)+'X'+str.substring(num-i);
System.out.println(str);
}
}
Or this shorter function direct to the console output:
public static void Print_X (int num) {
int j,i,dz=num-1;
for(i=0;i<num;i++,dz-=2) {
for(j=0;j<num;j++)
System.out.print((j==i || j==i+dz)?"X":" ");
System.out.println();
}
}
I have a small block of code that is reading Line2D values from an array called lineList (in a different class) and storing them in the new array called list. from here I have been trying to convert all of the line values into Polygon points (a point for each x, y coordinate of a line end).
so far I have it working but its not working for the very first point of the first line in the array (that's what I suspect it is) that is added and I am having trouble finding a solution to this as I have tried including this in the first if statement.
I will greatly appreciate any help that anyone is able to provide for me on this.
Below is the code I am using for adding the points from the Line2D values:
Polygon p = new Polygon();
ArrayList<Line2D> list = new ArrayList<Line2D>();
Color pixel;
boolean firstTime = true;
list = segmentation.getLineList();
//loop through lineList and add all x and y coordinates to relative x and y arrays
for(int i = 0; i < list.size(); i++) {
if(firstTime == true){
Line2D line = list.get(i);
Point2D startPoint = line.getP1();
Point2D endPoint = line.getP2();
int startX = (int) startPoint.getX();
int startY = (int) startPoint.getY();
int endX = (int) endPoint.getX();
int endY = (int) endPoint.getY();
p.addPoint(p.xpoints[i] = startX, p.ypoints[i] = startY);
p.addPoint(p.xpoints[i] = endX, p.ypoints[i] = endY);
startPoint = null;
endPoint = null;
line = null;
firstTime = false;
}
else {
Line2D line = list.get(i);
Point2D endPoint = line.getP2();
int endX = (int) endPoint.getX();
int endY = (int) endPoint.getY();
p.addPoint(p.xpoints[i] = endX, p.ypoints[i] = endY);
endPoint = null;
line = null;
}
}
Below is an example of the first point (lower most point) not being included in the polygon points.
Seems like a lot of duplicated code to me. Before we try any more debugging, let's refactor the code and make it simpler to understand and debug.
Refactoring
The first bit of code we can pull out is the code to add a point to the Polygon. Here's the new method.
protected void addPoint(Polygon p, Point2D point) {
int x = (int) point.getX();
int y = (int) point.getY();
p.addPoint(x, y);
}
Now, I didn't get to this in one refactoring. I first pulled out the end point code, because it was identical. After reflecting on the code some more, I generalized it so I could use it for the start point code.
When I first saw this line of code
p.addPoint(p.xpoints[i] = startX, p.ypoints[i] = startY);
I thought, WTF? I'd never seen anyone set values in a method call. In a where clause, sure.
After about 5 minutes of thought, I realized that the Polygon class internal values were being set after the execution of the addPoint method. While this might be useful with some other method call, it's not necessary here. The method call can be simplified to
p.addPoint(x, y);
Java developers, if you need yet another reason for making your class variables non-public, this is a real good one. Keeps people from setting your class variables after you've set them in your setter method.
Priming Read
We can get rid of the first time switch, and a lot of code, if we use a little known algorithm called the priming read.
Most for loops have the input statement as the first statement in the loop. The for (String s : stringList) construction of a loop hides the fact that the input statement is the first statement in the loop.
But sometimes, you have a method where you need a priming read. This method is one of those times.
In pseudo code, a priming read works like this.
Read input
for loop
process input
read input
end loop
process last input
By using a priming read, I was able to greatly simplify the createPolygon method.
Any Cobol programmer reading this thought, "Yep, the priming read."
Java programmers, keep this priming read idea in your mind. You won't use it that often, but as you see, it greatly reduces the amount of code you need in certain cases.
Refactored Code
public Polygon createPolygon(Segmentation segmentation) {
Polygon p = new Polygon();
List<Line2D> list = segmentation.getLineList();
if (list.size() < 2) return p;
Line2D line = list.get(0);
addPoint(p, line.getP1());
// loop through lineList and add all x and y coordinates to relative x
// and y arrays
for (int i = 1; i < list.size(); i++) {
addPoint(p, line.getP2());
line = list.get(i);
}
addPoint(p, line.getP2());
return p;
}
protected void addPoint(Polygon p, Point2D point) {
int x = (int) point.getX();
int y = (int) point.getY();
p.addPoint(x, y);
}
I did two additional things to the code.
I added a test for less than 2 lines. Basically, it takes at least 2 lines to create a triangle (polygon). There was no point executing the method for 1 line or zero lines.
I changed the ArrayList reference to List. In Java, it's better to use an interface over a concrete class. Since the only List method we're using in the code is the get method, we can use the interface. The advantage to using the interface is that the createPolygon method doesn't care whether or not the getLineList method returns an ArrayList, a LinkedList, or a custom class that implements List. This makes future modifications easier.