I need to speed up the cursor response which is hovering over a bunch of rectangles. As the rectangles increase in number(or complexity), the straight forward linear algorithm of iterating over the rectangles starts to deteriorate.
This hyperlink shows a linear search model(remember to add the break keyword!!!)linear approach
To clearly show what I mean,below is code of a JPanel that has two groups of rectangles.The first group is a List of rectangles on the y-axis, the second group is a List of rectangles on the x-axis.
Keep in mind, that my solution is the best I could think of, of using Two threads to concurrently iterate; one thread per List,one for x-axis and other for y-axis. The sub-optimal solution that I abandoned(code not displayed) is where there was a loop within a loop.One loop dedicated for the x-axis rectangles and the other for y-axis rectangles.This,I deemed sub-optimal as searching for a y-axis rectangle through the contain() method (assuming the inner loop is dedicated for y-axis rectangles) imposed an undue overhead by looping over all x-axis rectangles first.
To improve the linear model i thought of this threaded approach to simultaneously engage worker threads.
Btw, am a java novice,especially in multi-threading.
Problem: One thread seems to disturb the performance of the other.The algorithm below is implemented by two wrapper classes extending Thread which both have a method of iterating over rectangles.They each both work excellently if the other is commented out,i.e each works well individually and separately ,but one takes a performance hit when both start at the same time.
If I join() one thread,isn't that reverting to a linear model which is poor search algorithm as rectangles grow in complexity?
(complexity means not only horizontal and vertical, but also diagonal e.t.c rectangles)?
public class FlyingSaucer extends JPanel {
Rectangle2D rec;
Rectangle2D rec1;
List<Rectangle2D> recList;
List<Rectangle2D> recList2;
Rectangle2D.Double mouseBoxx;
int f = 10;
int g = 0;
int s = 10;
int y = 5;
int z = 500;
public FlyingSaucer(){
//FlyingSaucer needs to quickly identify specific points over given areas
//enclosed in rectangles.They use a 'divide and conquer' approach where
//different types of rectangles are first identified and a worker thread
//assigned to each category
mouseBoxx = new Rectangle.Double();
recList = new ArrayList<>();
recList2 = new ArrayList<>();
for(int i = 0; i < 15; i++){
rec = new Rectangle2D.Double(2+f,10+g,5,1000);
f +=50;
recList.add(rec);
}
f = 10;
for(int i = 0; i < 20; i++){
rec1 = new Rectangle2D.Double(2+y,10+s,1000,5);
s +=35;
recList2.add(rec1);
}
s = 10;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
FlyingSaucer fs = new FlyingSaucer();
Laser laser = new Laser(fs);
fs.addMouseMotionListener(laser);
fs.addMouseListener(laser);
frame.getContentPane().add(fs);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700,700);
frame.setVisible(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D)g).setColor(Color.RED);
int a = 10;
int b = 10;
for(int i = 0;i < recList.size();i++){
((Graphics2D)g).draw(recList.get(i));
}
for(int i = 0;i < recList2.size();i++){
((Graphics2D)g).draw(recList2.get(i));
}
}
}
class Laser implements MouseListener,MouseMotionListener{
Rectangle2D.Double mouseBox;
Rectangle2D.Double recx;
Rectangle2D.Double recy;
FlyingSaucer fs;
public Laser(FlyingSaucer fs){
this.fs = fs;
}
@Override public void mouseClicked (MouseEvent e) { }
@Override public void mousePressed (MouseEvent e) { }
@Override public void mouseReleased(MouseEvent e) { }
@Override public void mouseEntered (MouseEvent e) { }
@Override public void mouseExited (MouseEvent e) { }
@Override public void mouseDragged (MouseEvent e) { }
@Override
public void mouseMoved(MouseEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
double x = e.getX();
double y = e.getY();
mouseBox = fs.mouseBoxx;
mouseBox = new Rectangle2D.Double(x-5,y-5,10,10);
Graphics g = fs.getGraphics();
((Graphics2D)g).setColor(Color.BLACK);
((Graphics2D)g).draw(mouseBox);
//thread one for horizontal rectangles
HorizontalBuffer hb = new HorizontalBuffer(fs,e);
hb.start();
//thread two for vertical rectangles
VerticalBuffer vb = new VerticalBuffer(fs,e);
vb.start();
fs.repaint();
g.dispose();
}});
}
class HorizontalBuffer extends Thread{
FlyingSaucer fs;
MouseEvent e;
List<Rectangle2D> recX;
public HorizontalBuffer(FlyingSaucer fs,MouseEvent e){
this.fs = fs;
this.e = e;
}
public void run() {
recX = fs.recList;
Iterator <Rectangle2D> recs = recX.iterator();
int v = 1;
while(recs.hasNext()){
recx = (Rectangle2D.Double) recs.next();
if(recx.contains(e.getPoint())){
System.out.println("X rectangle detected.."+v);
fs.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
break;
}
else {fs.setCursor(Cursor.getDefaultCursor());}
v++;
}
}
}
class VerticalBuffer extends Thread{
FlyingSaucer fs;
MouseEvent e;
//List<Rectangle2D> recX;
List<Rectangle2D> recY;
public VerticalBuffer(FlyingSaucer fs,MouseEvent e){
this.fs = fs;
this.e = e;
}
public void run(){
recY = fs.recList2;
Iterator <Rectangle2D> recs = recY.iterator();
int v = 1;
while(recs.hasNext()){
recy = (Rectangle2D.Double) recs.next();
if(recy.contains(e.getPoint())){
System.out.println("Y rectangle detected.."+v);
fs.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
break;
}
else {fs.setCursor(Cursor.getDefaultCursor());}
v++;
}
}
}
}