Results 1 to 14 of 14
  1. #1
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default Lines, zoom in, zoom out, affinetransformation

    I have written small program for zoom in, and zoom out of lines, and lines that are result of affinetransformations (translate, rotate,...).

    Here is my simple begginer code:

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.geom.AffineTransform;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class LinesExample {
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			
    			@Override
    			public void run() {
    				LinesFrame frame = new LinesFrame();
    				frame.Ulshow();
    			}
    		});
    	}
    }
    
    class LinesFrame extends JFrame {
    	LinesPanel linesPanel;
    	public LinesFrame() {
    		linesPanel = new LinesPanel();
    		getContentPane().add(linesPanel, BorderLayout.CENTER);
    	}
    	
    	public void Ulshow() {
    		setTitle("Poly");		
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setSize(new Dimension(700,400));
    		setLocationRelativeTo(null);
    		setVisible(true);
    	}
    }
    
    class LinesPanel extends JPanel {
    //	AffineTransform at;
    	
    	public LinesPanel() {
    	//	at = new AffineTransform();
    	}
    	
    	public void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		
    		Graphics2D g2 = (Graphics2D)g;
    		
    		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		g2.drawLine(100, 100, 200, 200);
    		g2.drawLine(200, 200, 300, 200);
    		g2.drawLine(300, 200, 250, 70);
    	}
    }
    So in this code I have 3 lines. If I want to do some affine transformations is it better to group this line into some new line?
    Is it possible to group those lines for example in some new shape and then do some transformations on that shape, or it is better solution to put them in collection for example ArrayList of lines and then transform line by line?

    My final goal is to make simple graphics objects (circles, rectangles, lines) and use mouse wheel listener or some other listener to zoom in and zoom out that objects.

    Any kind of help will be useful: links, resources, advices, opinions,...

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Darryl is one of the experts on this sort of thing, and I just sort of dabble, so you might want to see if he puts in his two cents, but you might want to look at some of the classes that implement Shape that will allow you to group things together.

  3. #3
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    Darryl is one of the experts on this sort of thing, and I just sort of dabble, so you might want to see if he puts in his two cents, but you might want to look at some of the classes that implement Shape that will allow you to group things together.
    Do you have some examples or links to some examples of implements Shapes? I have already tried to find some examples on the internet but I haven't succeed.

    arryl is one of the experts on this sort of thing, and I just sort of dabble, so you might want to see if he puts in his two cents
    I think he will.
    Also some says that Josh is a mathematician (my colleague :D), and maybe he will give me some good advices, too.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by cselic View Post
    Also some says that Josh is a mathematician (my colleague :D), and maybe he will give me some good advices, too.
    True, when he hasn't had too much Grolsch.

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    OK, after playing with it a bit, one way is to shove everything into a Path2D and then applying the transform to the Path2D. For e.g.,
    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.*;
    
    import javax.swing.*;
    
    public class ShapePlay extends JPanel {
       private static final float STROKE_SIZE = 4.0f;
       private static final int TIMER_DELAY = 1000;
       private Path2D myPath = new Path2D.Double();
    
       public ShapePlay() {
          setPreferredSize(new Dimension(400, 400));
          myPath.append(new Ellipse2D.Double(30, 30, 100, 100), false);
          myPath.append(new Line2D.Double(250, 350, 350, 250), false);
          myPath.append(new Line2D.Double(350, 350, 250, 250), false);
          myPath.append(new RoundRectangle2D.Double(230, 30, 100, 100, 10, 10), false);
       }
    
       public void setAffineTransform(AffineTransform at) {
          myPath.transform(at);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
          g2.setColor(Color.blue);
          g2.fill(myPath);
    
          g2.setColor(Color.red);
          g2.setStroke(new BasicStroke(STROKE_SIZE));
          g2.draw(myPath);
       }
    
       private static void createAndShowUI() {
          final ShapePlay shapePlay = new ShapePlay();
    
          Timer timer = new Timer(TIMER_DELAY, new ActionListener() {
             int count = 100;
    
             public void actionPerformed(ActionEvent e) {
                if (count > 0) {
                   double sx = (double)count / 100.0;
                   double sy = sx;
                   double tx = (double)shapePlay.getWidth() * (1-sx) / (2 * sx);
                   double ty = (double)shapePlay.getHeight() * (1-sy) / (2 * sy);
                   AffineTransform at = AffineTransform.getScaleInstance(sx, sy);
                   at.translate(tx, ty);
                   shapePlay.setAffineTransform(at);
                   shapePlay.repaint();
                   count -= 5;
                } else {
                   ((Timer)e.getSource()).stop();
                }
             }
          });
          timer.start();
    
          JFrame frame = new JFrame("ShapePlay");
          frame.getContentPane().add(shapePlay);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }

  6. #6
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    Thank you very much for this useful example. I'm now on my way to make similar example, and I will post it here soon as it's possible.

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Iteration two: uses the mouse to translate the Path2D if the mouse is dragged, or expand or contract (scale) the Path2D if the wheel is turned. When scaling the image, translation is also used so that the scaling is centered at the mouse point:

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import javax.swing.*;
    
    public class ShapePlayTest {
    
       private static void createAndShowUI() {
          ShapePlayPanel spPanel = new ShapePlayPanel();
          ShapePlayMouseListener mListener = new ShapePlayMouseListener(spPanel);
          spPanel.addMouseListener(mListener);
          spPanel.addMouseMotionListener(mListener);
          spPanel.addMouseWheelListener(mListener);
    
          JFrame frame = new JFrame("ShapePlay");
          frame.getContentPane().add(spPanel);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class ShapePlayPanel extends JPanel {
       private static final float STROKE_SIZE = 2;
       private Path2D myPath = new Path2D.Double();
    
       public ShapePlayPanel() {
          setPreferredSize(new Dimension(400, 400));
          myPath.append(new Ellipse2D.Double(30, 30, 100, 100), false);
          myPath.append(new Line2D.Double(250, 350, 350, 250), false);
          myPath.append(new Line2D.Double(350, 350, 250, 250), false);
          myPath.append(new RoundRectangle2D.Double(230, 30, 100, 100, 10, 10), false);
       }
    
       public void setAffineTransform(AffineTransform at) {
          myPath.transform(at);
       }
    
       public boolean contains(Point p) {
          return myPath.contains(p);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
          g2.setColor(Color.blue);
          g2.fill(myPath);
    
          g2.setColor(Color.red);
          g2.setStroke(new BasicStroke(STROKE_SIZE));
          g2.draw(myPath);
       }
    
    }
    
    class ShapePlayMouseListener extends MouseAdapter {
       private static final double SCALE_RATIO = 10.0 / 9.0;
       private ShapePlayPanel spPanel;
       private Point mousePressedPt = null;
    
       public ShapePlayMouseListener(ShapePlayPanel spPanel) {
          this.spPanel = spPanel;
       }
    
       @Override
       public void mousePressed(MouseEvent e) {
          Point p = e.getPoint();
          mousePressedPt = p;
       }
    
       @Override
       public void mouseReleased(MouseEvent e) {
          mousePressedPt = null;
       }
    
       @Override
       public void mouseDragged(MouseEvent e) {
          if (mousePressedPt != null) {
             Point p = e.getPoint();
             double tx = p.x - mousePressedPt.x;
             double ty = p.y - mousePressedPt.y;
             spPanel.setAffineTransform(new AffineTransform());
             spPanel.setAffineTransform(AffineTransform.getTranslateInstance(tx, ty));
             spPanel.repaint();
    
             mousePressedPt = p;
          }
       }
    
       @Override
       public void mouseWheelMoved(MouseWheelEvent e) {
          Point p = e.getPoint();
          int wheelRotation = e.getWheelRotation();
    
          // get scale factors based on direction of wheel rotation
          double sx = (wheelRotation > 0) ? SCALE_RATIO : 1 / SCALE_RATIO;
          double sy = sx;
          
          // get translation factors so that expansion is centered at mouse point
          double tx = p.x * (1 - sx);
          double ty = p.y * (1 - sy);
          
          AffineTransform at = AffineTransform.getTranslateInstance(tx, ty);
          at.scale(sx, sy);
          
          spPanel.setAffineTransform(at);
          spPanel.repaint();
       }
    
    }

  8. #8
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    I prefer drawing shapes for the following reason: draw two individual lines: L1 = (0,0) -> (100, 100) and L2= (100, 0) -> (100, 100). Use a thick line (see BasicStroke) and look at the endpoint (100, 100); it doesn't look good. If you draw those two lines L1 and L2 as a Path2D (a Shape) the endpoints merge fine. Those two lines do need to have the same colour when drawn as a Path2D, something that isn't needed when you draw two separate lines ...

    kind regards,

    Jos

    ps. this is what I'm talking about:
    Attached Thumbnails Attached Thumbnails Lines, zoom in, zoom out, affinetransformation-example.png  
    Last edited by JosAH; 08-29-2010 at 09:44 AM.

  9. #9
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    I have written small program based on Fubarable's examples.
    Little program is based on idea to draw map of city with streets.
    I have just added a few streets, but I will add them more later.

    Code:


    Class: Street.java
    Java Code:
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.geom.Line2D;
    import java.awt.geom.Path2D;
    
    public class Street {
    	private Path2D streetPath;
    	private String name;
    	
    	public Street(String streetName) {
    		this.name = streetName;
    		streetPath = new Path2D.Double();
    	}
    	
    	public Path2D getStreetPath() {
    		return streetPath;
    	}
    
    	public void setStreetPath(Path2D streetPath) {
    		this.streetPath = streetPath;
    	}
    
    	public void addLine(Line2D line) {
    		streetPath.append(line, false);
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	private static final float STROKE_SIZE= 6;
    	public void drawStreet(Graphics g) {
    		
    		Graphics2D g2 = (Graphics2D) g;
    		
    		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    				RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		g2.setStroke(new BasicStroke(STROKE_SIZE));
    		g2.setColor(Color.orange);
    		g2.draw(streetPath);
    	}
    }


    class: Streets.java
    Java Code:
    import java.awt.Graphics;
    import java.awt.geom.AffineTransform;
    import java.util.List;
    import java.util.ArrayList;
    
    public class Streets {
    	List<Street> allStreets;
    	
    	public Streets() {
    		allStreets = new ArrayList<Street>();
    	}
    	
    	public void addStreet(Street s) {
    		allStreets.add(s);
    	}
    	
    	public int getSize() {
    		return allStreets.size();
    	}
    	
    	public void remove(int index) {
    		allStreets.remove(index);
    	}
    	
    	public void drawStreets(Graphics g) {
    		for(Street s : allStreets)
    			s.drawStreet(g);
    	}
    	
    	public void transform(AffineTransform at) {
    		for(Street s: allStreets)
    			s.getStreetPath().transform(at);
    	}
    }


    class: StreetsMap.java
    Java Code:
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseWheelEvent;
    import java.awt.event.MouseEvent;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Line2D;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class StreetsMap {
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			
    			@Override
    			public void run() {
    				StreetsFrame frame = new StreetsFrame();
    				frame.showLittle();
    			}
    		});
    	}
    }
    
    class StreetsFrame extends JFrame {
    	private AffineTransform at;
    	private StreetsPanel panel;
    	
    	public StreetsFrame() {
    		panel = new StreetsPanel();
    		getContentPane().add(panel);
    		ZoomMapListener zoomListener = new ZoomMapListener(panel);
    		addMouseListener(zoomListener);
    		addMouseMotionListener(zoomListener);
    		addMouseWheelListener(zoomListener);
    		
    		
    	}
    	
    	public void showLittle() {
    		setTitle("Streets");
    		setSize(new Dimension(550,500));
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setLocationRelativeTo(null);
    		setVisible(true);
    	}
    	
    	class StreetsPanel extends JPanel {
    		Streets streets;
    		Street street;
    		public StreetsPanel() {
    			streets = new Streets();
    			street = new Street("Pearl St");
    			street.addLine(new Line2D.Double(100,400,200,300));
    			street.addLine(new Line2D.Double(200,300,250,100));
    			streets.addStreet(street);
    			
    			street = new Street("Water St");
    			street.addLine(new Line2D.Double(100,100,300,300));
    			streets.addStreet(street);
    			
    			street = new Street("West St");
    			street.addLine(new Line2D.Double(100,200,300,400));
    			streets.addStreet(street);
    			
    			street = new Street("Barclay St");
    			street.addLine(new Line2D.Double(100,50,100,430));
    			streets.addStreet(street);
    		}
    		
    		public void setAffineTransform(AffineTransform at) {
    			streets.transform(at);
    		}
    		
    		public void paintComponent(Graphics g) {
    			super.paintComponent(g);
    			
    			streets.drawStreets(g);
    		}
    	}
    	
    	 private class ZoomMapListener extends MouseAdapter  {
    		private StreetsPanel panel;
    		private static final double SCALE_RATIO = 1.05;
    		private Point mousePressedPoint = null;
    		
    		
    		public ZoomMapListener(StreetsPanel pan) {
    			this.panel = pan;
    		}
    		
    		@Override
    		public void mousePressed(MouseEvent e) {
    			Point p = e.getPoint();
    			mousePressedPoint = p;
    		}
    		
    		@Override
    		public void mouseReleased(MouseEvent e) {
    			mousePressedPoint = null;
    		}
    		
    		@Override
    		   public void mouseDragged(MouseEvent e) {
    			if(mousePressedPoint != null) {
    				Point p = e.getPoint();
    				double tx = p.x - mousePressedPoint.getX();
    				double ty = p.y - mousePressedPoint.getY();
    				panel.setAffineTransform(new AffineTransform());
    				panel.setAffineTransform(AffineTransform.getTranslateInstance(tx, ty));
    				panel.repaint();
    				
    				mousePressedPoint = p;
    			}
    		}
    		
    		@Override
    		public void mouseWheelMoved(MouseWheelEvent e) {
    			Point p = e.getPoint();
    			int currentRotation = e.getWheelRotation();
    			
    			double scaleX = (currentRotation > 0) ? SCALE_RATIO :
    				1 / SCALE_RATIO;
    			double scaleY = scaleX;
    			
    			double translateX = p.x * (1 - scaleX);
    			double translateY = p.y * (1 - scaleY);
    			
    			AffineTransform at = AffineTransform.getTranslateInstance
    									(translateX, translateY);
    			at.scale(scaleX, scaleY);
    			
    			panel.setAffineTransform(at);
    			panel.repaint();
    		}
    	}
    }



    For size of streets I have used basicStroke(6.0f). I think that it is not good to do it with strokes, but that was the first idea on my mind.
    Also I have a problem of drawing names of the streets. Can anyone give me some suggestions about drawing that names?
    Last edited by cselic; 08-29-2010 at 09:16 PM. Reason: typos

  10. #10
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by cselic View Post
    Also I have a problem of drawing names of the streets. Can anyone give me some suggestions about drawing that names?
    You can also rotate text; if (bx, by) and (ex, ey) are the start and endpoints of a street (hopefully a straight line) you can easily find the rotation matrix and possibly a translation vector. Set another affine transformation and print the name of the street. You possibly have to adjust the translation vector a bit for the baseline of the String but I leave that to you ;-)

    kind regards,

    Jos

  11. #11
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    You can also rotate text; if (bx, by) and (ex, ey) are the start and endpoints of a street (hopefully a straight line) you can easily find the rotation matrix and possibly a translation vector. Set another affine transformation and print the name of the street. You possibly have to adjust the translation vector a bit for the baseline of the String but I leave that to you ;-)
    Thanks Josh. I have done it with drawing name of the street at the center of each line (part of the street) of each path (street).
    It is an interesting thing that rotation is not in mathematic positive direction but in negative when I look at screen. At first point I couldn't figure it out why is that so. But I concluded that this is because coordinate system for drawing objects in java begins at up left corner of the screen. And from that perspective rotation is in math positive direction. :D

    In a few minutes I will post improved program.

  12. #12
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    class: Street.java


    Java Code:
    import java.util.List;
    import java.util.ArrayList;
    
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.geom.Line2D;
    import java.awt.geom.Path2D;
    
    public class Street {
    	private List<Line2D> lines;
    	private Path2D streetPath;
    	private String name;
    	private Color color = Color.orange;
    	
    	public Street(String streetName) {
    		this.name = streetName;
    		streetPath = new Path2D.Double();
    		lines = new ArrayList<Line2D>();
    	}
    	
    	public Path2D getStreetPath() {
    		return streetPath;
    	}
    
    	public void setStreetPath(Path2D streetPath) {
    		this.streetPath = streetPath;
    	}
    
    	public void addLine(Line2D line) {
    		streetPath.append(line, false);
    		lines.add(line);
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	private static final float STROKE_SIZE= 6;
    	public void drawStreet(Graphics g) {
    		
    		Graphics2D g2 = (Graphics2D) g;
    		
    		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    				RenderingHints.VALUE_ANTIALIAS_ON);
    		
    		g2.setStroke(new BasicStroke(STROKE_SIZE));
    		g2.setColor(color);
    		g2.draw(streetPath);
    		
    		for(int i = 0; i < lines.size(); i++) {
    			double coeff = getCoefOfLine(i);
    			int xPositionOfString = (int)(lines.get(i).getX1() + lines.get(i).getX2())/2;
    			int yPositionOfString = (int)(lines.get(i).getY1()+lines.get(i).getY2())/2;
    
    			g2.rotate(Math.atan(coeff),xPositionOfString, yPositionOfString);
    			g2.translate(10, -10);
    			g2.drawString(name, xPositionOfString, yPositionOfString);
    			g2.translate(-10, 10);
    			g2.rotate(-Math.atan(coeff), xPositionOfString, yPositionOfString);
    		}
    	}
    	
    	public void changeColor() {
    		color = Color.blue;
    	}
    	
    	public void defaultColor() {
    		color = Color.orange;
    	}
    	
    	public double getCoefOfLine(int index) {
    		Line2D line = lines.get(index);
    		
    		double coeff = (line.getY2() - line.getY1()) / (line.getX2() - line.getX1());
    		
    		return coeff;
    	}
    }


    class: Streets.java

    Java Code:
    import java.awt.Graphics;
    import java.awt.geom.AffineTransform;
    import java.util.List;
    import java.util.ArrayList;
    
    public class Streets {
    	List<Street> allStreets;
    	
    	public Streets() {
    		allStreets = new ArrayList<Street>();
    	}
    	
    	public void addStreet(Street s) {
    		allStreets.add(s);
    	}
    	
    	public int getSize() {
    		return allStreets.size();
    	}
    	
    	public void remove(int index) {
    		allStreets.remove(index);
    	}
    	
    	public Street get(int index) {
    		return allStreets.get(index);
    	}
    	
    	public void drawStreets(Graphics g) {
    		for(Street s : allStreets)
    			s.drawStreet(g);
    	}
    	
    	public void drawStreets(Graphics g, int currentSelected) {
    		for(int i = 0; i < allStreets.size(); i++)
    			if(i != currentSelected)
    				allStreets.get(i).drawStreet(g);
    		
    		allStreets.get(currentSelected).drawStreet(g);
    	}
    	
    	public void transform(AffineTransform at) {
    		for(Street s: allStreets)
    			s.getStreetPath().transform(at);
    	}
    }


    class: ReadStreets.java

    Java Code:
    import java.awt.geom.Line2D;
    import java.io.File;
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.FileNotFoundException;
    
    public class ReadStreets {
    	Street s;
    	Streets streets;
    	public Streets readStreets(String filename) throws IOException {
    		BufferedReader in = null;
    		streets = new Streets();
    		try {
    			in = new BufferedReader(new FileReader(new File(filename)));
    			
    			String line;
    			while((line = in.readLine()) != null) {
    				if(line.startsWith("NAME ")) {
    					line = line.substring(5);
    					line.trim();
    					s = new Street(line);
    					streets.addStreet(s);
    				}
    				else if (line.startsWith("LINE ")) {
    					line = line.substring(5);
    					line.trim();
    					String[] values;
    					values = line.split(", ");
    					
    					int[] coords = new int[values.length];
    					for(int i = 0; i < values.length; i++)
    						coords[i] = Integer.parseInt(values[i]);
    					
    					s.addLine(new Line2D.Double(coords[0],coords[1],coords[2],coords[3]));
    				}
    			}	
    		} catch(FileNotFoundException e) {
    			e.printStackTrace();
    			System.exit(1);	
    		} catch(IOException e) {
    			e.printStackTrace();
    			System.exit(1);
    		} finally {
    			in.close();
    			return streets;
    		}
    	}
    }


    main class: StreetsMap.java

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseWheelEvent;
    import java.awt.geom.AffineTransform;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class StreetsMap {
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(new Runnable() {
    			
    			@Override
    			public void run() {
    				StreetsFrame frame = new StreetsFrame();
    				frame.showMap();
    			}
    		});
    	}
    }
    
    class StreetsFrame extends JFrame {
    	
    	private AffineTransform at;
    	private StreetsPanel panel;
    	private SearchPanel searchPanel;
    	
    	private int currentSelectedStreetIndex = -1;
    
    	Streets streets;
    	Street street;
    	
    	public StreetsFrame() {
    		searchPanel = new SearchPanel();
    		getContentPane().add(searchPanel, BorderLayout.NORTH);
    		
    		panel = new StreetsPanel();
    		getContentPane().add(panel, BorderLayout.CENTER);
    		ZoomMapListener zoomListener = new ZoomMapListener(panel);
    		addMouseListener(zoomListener);
    		addMouseMotionListener(zoomListener);
    		addMouseWheelListener(zoomListener);
    
    		searchPanel.streetWords();
    	}
    	
    	public void showMap() {
    		setTitle("Streets");
    		setSize(new Dimension(550,550));
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setLocationRelativeTo(null);
    		setVisible(true);
    	}
    	
    	class StreetsPanel extends JPanel {
    		ReadStreets read = new ReadStreets();
    	
    		public StreetsPanel() {
    			streets = new Streets();
    			
    			try {
    				streets = read.readStreets("streets.txt");
    			} catch(IOException e) {
    				e.printStackTrace();
    				System.exit(1);
    			}
    		}
    		
    		public void setAffineTransform(AffineTransform at) {
    			streets.transform(at);
    		}
    		
    		public void paintComponent(Graphics g) {
    			super.paintComponent(g);
    			
    			if(currentSelectedStreetIndex >= 0)
    				streets.drawStreets(g, currentSelectedStreetIndex);
    			else
    				streets.drawStreets(g);
    		}
    		
    		public Streets getStreets() {
    			return streets;
    		}
    	}
    	
    	class SearchPanel extends JPanel {
    		JTextField searchField;
    		JButton searchButton;
    		JComboBox comboBox;
    		
    		List<String> words = new ArrayList<String>();
    		
    		public SearchPanel() {
    			
    			searchField = new JTextField(10);
    			searchButton = new JButton("Search");
    			comboBox = new JComboBox();
    			comboBox.addItem("");
    			
    			add(searchField);
    			add(searchButton);
    			add(comboBox);
    			
    			
    			comboBox.addActionListener(new SearchComboListener());
    			searchButton.addActionListener(new SearchBtnListener());
    		}
    		
    		public void streetWords() {
    			for(int i = 0; i < streets.getSize(); i++) {
    				words.add(streets.get(i).getName());
    				comboBox.addItem(words.get(i));
    			}
    						}
    		
    		private class SearchBtnListener implements ActionListener {
    
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				String searchTerm = searchField.getText();
    				
    				int index;
    				
    				for(int i = 0; i < streets.getSize(); i++) {
    					streets.get(i).defaultColor();
    					panel.repaint();
    				}
    				if(words.contains(searchTerm)) {
    					index = words.indexOf(searchTerm);
    					streets.get(index).changeColor();
    					panel.repaint();
    					currentSelectedStreetIndex = index;
    				}
    			}
    		}
    		
    		private class SearchComboListener implements ActionListener {
    
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				for(int i = 0; i < streets.getSize(); i++) {
    					streets.get(i).defaultColor();
    					panel.repaint();
    				}
    				int index = (int)comboBox.getSelectedIndex();
    				if(index > 0) {
    					streets.get(index-1).changeColor();
    					currentSelectedStreetIndex = index - 1;
    				}
    				panel.repaint();
    			}	
    		}
    	}
    	
    	 private class ZoomMapListener extends MouseAdapter  {
    		private StreetsPanel panel;
    		private static final double SCALE_RATIO = 1.05;
    		private Point mousePressedPoint = null;
    		
    		
    		public ZoomMapListener(StreetsPanel pan) {
    			this.panel = pan;
    		}
    		
    		@Override
    		public void mousePressed(MouseEvent e) {
    			Point p = e.getPoint();
    			mousePressedPoint = p;
    		}
    		
    		@Override
    		public void mouseReleased(MouseEvent e) {
    			mousePressedPoint = null;
    		}
    		
    		@Override
    		   public void mouseDragged(MouseEvent e) {
    			if(mousePressedPoint != null) {
    				Point p = e.getPoint();
    				double tx = p.x - mousePressedPoint.getX();
    				double ty = p.y - mousePressedPoint.getY();
    				panel.setAffineTransform(new AffineTransform());
    				panel.setAffineTransform(AffineTransform.getTranslateInstance(tx, ty));
    				panel.repaint();
    				
    				mousePressedPoint = p;
    			}
    		}
    		
    		@Override
    		public void mouseWheelMoved(MouseWheelEvent e) {
    			Point p = e.getPoint();
    			int currentRotation = e.getWheelRotation();
    			
    			double scaleX = (currentRotation > 0) ? SCALE_RATIO :
    				1 / SCALE_RATIO;
    			double scaleY = scaleX;
    			
    			double translateX = p.x * (1 - scaleX);
    			double translateY = p.y * (1 - scaleY);
    			
    			AffineTransform at = AffineTransform.getTranslateInstance
    									(translateX, translateY);
    			at.scale(scaleX, scaleY);
    			
    			panel.setAffineTransform(at);
    			panel.repaint();
    		}
    	}
    }


    file: streets.txt

    Java Code:
    NAME South St
    LINE 100, 200, 50, 70
    LINE 50, 70, 30, 90
    NAME Pearl St
    LINE 100, 400, 200, 300
    LINE 200, 300, 250, 100
    NAME Water St
    LINE 100, 100, 300, 300
    NAME West St
    LINE 100, 200, 300, 400
    NAME Barclay St
    LINE 100, 50, 100, 430

  13. #13
    cselic is offline Senior Member
    Join Date
    Apr 2010
    Location
    Belgrade, Serbia
    Posts
    278
    Rep Power
    5

    Default

    I have done it with few very good improvements for example searching streets, selecting it from a combobox menu, redrawing path so that current selected street is always on top...
    Attached Files Attached Files
    Last edited by cselic; 08-30-2010 at 06:06 PM. Reason: typos

  14. #14
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,375
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by cselic View Post
    Thanks Josh. I have done it with drawing name of the street at the center of each line (part of the street) of each path (street).
    It is an interesting thing that rotation is not in mathematic positive direction but in negative when I look at screen. At first point I couldn't figure it out why is that so. But I concluded that this is because coordinate system for drawing objects in java begins at up left corner of the screen. And from that perspective rotation is in math positive direction. :D
    Yep, the positive Y axis points downwards; you could scale the Y axis by -1 to make it point upwards as we all love it to be and want it to be ;-) The reasons for that silly coordinate system is a memory addressing reason; don't pay too much attention to it, it's nothing an affine transform can't cure.

    kind regards,

    Jos

Similar Threads

  1. How to Zoom in and Zoom out TYPE_USHORT_565_RGB image
    By Santhoshkumarp in forum AWT / Swing
    Replies: 0
    Last Post: 08-07-2010, 02:39 PM
  2. Zoom in and out
    By mickey in forum Java 2D
    Replies: 1
    Last Post: 06-15-2010, 11:39 PM
  3. Java Zoom in and Zoom out?
    By ps20090 in forum Java Applets
    Replies: 2
    Last Post: 09-18-2009, 12:04 PM
  4. how to zoom using slider
    By kumar_gemi in forum New To Java
    Replies: 0
    Last Post: 07-11-2009, 10:06 PM
  5. zoom in swing
    By Alan in forum AWT / Swing
    Replies: 2
    Last Post: 05-31-2007, 02:11 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •