Help with transforms

Discussion in 'Java' started by Ian Stanley, Jul 30, 2003.

  1. Ian Stanley

    Ian Stanley Guest

    Hi,
    I have a simple program below where the user can draw rectangles on a panel.
    The choice to either rotate or scale any single rectangle should result in
    the appropriate action.(after selecting a shape).
    However, the selected rectangle is transformed(rotated or scaled) but it
    appears to be drawn translated as well.
    I am guessing that it has somethig to do with transforming the coordinate
    system for that shape.
    Is there a way to fix it so that the selected shape is rotated or scaled at
    its current location?
    Thanking you in advance
    Ian.

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.util.*;
    import javax.swing.*;
    public class SwingDraw
    {
    public static void main(String[] args)
    {
    Draw D = new Draw() ;
    }
    }

    interface Constants {
    final int RECTANGLE = 1, ROTATE = 2, SCALE = 3;
    }

    class Draw extends JFrame
    implements Constants, ActionListener{
    JPanel bp = new JPanel() ;
    DrawJPanel djp ;
    Container content = getContentPane() ;
    JButton rectButton, rotateButton, quitButton, scaleButton ;

    Draw() {
    super() ;
    content.setLayout(new BorderLayout()) ;
    djp = new DrawJPanel() ;
    bp.add(rectButton = new JButton("Rectangle")) ;
    bp.add(rotateButton = new JButton("rotate")) ;
    bp.add(scaleButton = new JButton("scale")) ;
    bp.add(quitButton = new JButton("Quit")) ;
    quitButton.addActionListener(
    new ActionListener(){
    public void actionPerformed(ActionEvent
    e) {
    System.exit(0) ;
    }
    }) ;
    rectButton.addActionListener(this) ;
    rotateButton.addActionListener(this) ;
    scaleButton.addActionListener(this) ;
    content.add(bp, BorderLayout.NORTH) ;
    content.add(djp, BorderLayout.CENTER) ;
    setSize(750, 500) ;
    setVisible(true) ;
    }


    public void actionPerformed(ActionEvent e) {
    String cmd = e.getActionCommand() ;
    switch (cmd.charAt(0)) {
    case 'R':
    djp.setMode(RECTANGLE) ;
    break ;
    case 'r':
    djp.setMode(ROTATE) ;
    break ;
    case 's':
    djp.setMode(SCALE) ;
    break ;
    }
    }

    }
    class DrawJPanel extends JPanel
    implements Constants
    {
    Vector v = new Vector();
    Shape current_shape = null;
    int drawingMode;
    public DrawJPanel()
    {
    addMouseListener(
    new MouseAdapter() {
    public void mousePressed(MouseEvent evt)
    {
    int x = evt.getX();
    int y = evt.getY();
    // check if we hit an existing shape
    current_shape = locateRect(x,y);
    // if ( current_shape==null)
    // {
    if (drawingMode == RECTANGLE){
    Rectangle2D.Float e = new
    Rectangle2D.Float(x, y, 80, 50);
    v.add(e);
    repaint();
    }
    else if (drawingMode == ROTATE &&
    current_shape != null ){
    rotateShape(x,y);
    repaint();
    }
    else if (drawingMode == SCALE &&
    current_shape != null ){
    scaleShape(x,y);
    repaint();
    }
    }
    }
    );
    }
    void setMode(int mode) {
    drawingMode = mode ;
    }

    public Shape locateRect(int x, int y)
    {
    for (int i = 0; i < v.size(); i++){
    Shape s = (Shape)v.elementAt(i);
    if (s.contains(x,y) )
    return s;
    }
    return null;
    }

    public Shape rotateShape(int x, int y)
    {
    for (int i = 0; i < v.size(); i++){
    Shape s = (Shape)v.elementAt(i);
    if (s.contains(x,y) ){
    AffineTransform tr =
    AffineTransform.getRotateInstance(Math.toRadians(45));
    Shape ts = tr.createTransformedShape(current_shape);
    v.addElement(ts);
    v.removeElement(s);
    repaint();
    }
    }
    return null;
    }

    public Shape scaleShape(int x, int y)

    {
    for (int i = 0; i < v.size(); i++){
    Shape s = (Shape)v.elementAt(i);
    if (s.contains(x,y) ){
    AffineTransform tr =
    AffineTransform.getScaleInstance(0.7,0.7);
    Shape ts = tr.createTransformedShape(current_shape);
    v.addElement(ts);
    v.removeElement(s);
    repaint();
    }
    }
    return null;
    }

    public void paintComponent(Graphics gr)
    {
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;
    for(int i=0; i<v.size(); i++)
    g.draw((Shape)v.elementAt(i));
    }
    }
    Ian Stanley, Jul 30, 2003
    #1
    1. Advertising

  2. "Ian Stanley" <> wrote in message news:<>...
    > Hi,
    > I have a simple program below where the user can draw rectangles on a panel.
    > The choice to either rotate or scale any single rectangle should result in
    > the appropriate action.(after selecting a shape).
    > However, the selected rectangle is transformed(rotated or scaled) but it
    > appears to be drawn translated as well.
    > I am guessing that it has somethig to do with transforming the coordinate
    > system for that shape.
    > Is there a way to fix it so that the selected shape is rotated or scaled at
    > its current location?


    You want AffineTransform.getRotateInstance(double theta, double x,
    double y), but the definition of center point is up to you. You should
    probably store the original center rather than computing it from
    Shape bounds, to avoid drift. Actually, you should probably store the
    original Shape, current rotation, and current scale. Whenever the
    the rotation or scale changes, rebuild the transformed object. This
    will avoid roundoff errors due to repeated transforming. So v would
    contain objects with: original shape, center point, current rotation,
    current scale, and transformed shape.


    -Larry


    > Thanking you in advance
    > Ian.
    >
    > import java.awt.*;
    > import java.awt.event.*;
    > import java.awt.geom.*;
    > import java.util.*;
    > import javax.swing.*;
    > public class SwingDraw
    > {
    > public static void main(String[] args)
    > {
    > Draw D = new Draw() ;
    > }
    > }
    >
    > interface Constants {
    > final int RECTANGLE = 1, ROTATE = 2, SCALE = 3;
    > }
    >
    > class Draw extends JFrame
    > implements Constants, ActionListener{
    > JPanel bp = new JPanel() ;
    > DrawJPanel djp ;
    > Container content = getContentPane() ;
    > JButton rectButton, rotateButton, quitButton, scaleButton ;
    >
    > Draw() {
    > super() ;
    > content.setLayout(new BorderLayout()) ;
    > djp = new DrawJPanel() ;
    > bp.add(rectButton = new JButton("Rectangle")) ;
    > bp.add(rotateButton = new JButton("rotate")) ;
    > bp.add(scaleButton = new JButton("scale")) ;
    > bp.add(quitButton = new JButton("Quit")) ;
    > quitButton.addActionListener(
    > new ActionListener(){
    > public void actionPerformed(ActionEvent
    > e) {
    > System.exit(0) ;
    > }
    > }) ;
    > rectButton.addActionListener(this) ;
    > rotateButton.addActionListener(this) ;
    > scaleButton.addActionListener(this) ;
    > content.add(bp, BorderLayout.NORTH) ;
    > content.add(djp, BorderLayout.CENTER) ;
    > setSize(750, 500) ;
    > setVisible(true) ;
    > }
    >
    >
    > public void actionPerformed(ActionEvent e) {
    > String cmd = e.getActionCommand() ;
    > switch (cmd.charAt(0)) {
    > case 'R':
    > djp.setMode(RECTANGLE) ;
    > break ;
    > case 'r':
    > djp.setMode(ROTATE) ;
    > break ;
    > case 's':
    > djp.setMode(SCALE) ;
    > break ;
    > }
    > }
    >
    > }
    > class DrawJPanel extends JPanel
    > implements Constants
    > {
    > Vector v = new Vector();
    > Shape current_shape = null;
    > int drawingMode;
    > public DrawJPanel()
    > {
    > addMouseListener(
    > new MouseAdapter() {
    > public void mousePressed(MouseEvent evt)
    > {
    > int x = evt.getX();
    > int y = evt.getY();
    > // check if we hit an existing shape
    > current_shape = locateRect(x,y);
    > // if ( current_shape==null)
    > // {
    > if (drawingMode == RECTANGLE){
    > Rectangle2D.Float e = new
    > Rectangle2D.Float(x, y, 80, 50);
    > v.add(e);
    > repaint();
    > }
    > else if (drawingMode == ROTATE &&
    > current_shape != null ){
    > rotateShape(x,y);
    > repaint();
    > }
    > else if (drawingMode == SCALE &&
    > current_shape != null ){
    > scaleShape(x,y);
    > repaint();
    > }
    > }
    > }
    > );
    > }
    > void setMode(int mode) {
    > drawingMode = mode ;
    > }
    >
    > public Shape locateRect(int x, int y)
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) )
    > return s;
    > }
    > return null;
    > }
    >
    > public Shape rotateShape(int x, int y)
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) ){
    > AffineTransform tr =
    > AffineTransform.getRotateInstance(Math.toRadians(45));
    > Shape ts = tr.createTransformedShape(current_shape);
    > v.addElement(ts);
    > v.removeElement(s);
    > repaint();
    > }
    > }
    > return null;
    > }
    >
    > public Shape scaleShape(int x, int y)
    >
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) ){
    > AffineTransform tr =
    > AffineTransform.getScaleInstance(0.7,0.7);
    > Shape ts = tr.createTransformedShape(current_shape);
    > v.addElement(ts);
    > v.removeElement(s);
    > repaint();
    > }
    > }
    > return null;
    > }
    >
    > public void paintComponent(Graphics gr)
    > {
    > super.paintComponent(gr);
    > Graphics2D g = (Graphics2D)gr;
    > for(int i=0; i<v.size(); i++)
    > g.draw((Shape)v.elementAt(i));
    > }
    > }
    Larry A Barowski, Jul 30, 2003
    #2
    1. Advertising

  3. Ian Stanley

    Roedy Green Guest

    On Wed, 30 Jul 2003 22:00:29 +0930, "Ian Stanley"
    <> wrote or quoted :

    >I am guessing that it has somethig to do with transforming the coordinate
    >system for that shape.


    the tool you probably want is AffineTransform.rotate(double
    thetaInRadians, double x, double y) Concatenates this transform with a
    transform that rotates coordinates around an anchor point.

    see http://mindprod.com/jgloss/affinetransform.html
    and http://mindprod.com/jgloss/coordinates.html

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
    Roedy Green, Jul 30, 2003
    #3
  4. Ian Stanley

    Ian Stanley Guest

    Thanks.
    But is there a "hack" or a simple way where I can first work out where the
    centre of the shape is and apply a translation relative to these coords
    and(0,0) . And then apply the rotation which will rotate the shape about it
    centre.
    I have lookded at the Sun 2d Transform example which rotates/translates
    shapes and they always appear centered. I would like try try something like
    this(for my level of understanding) and then try to understand/utilise the
    api in more detail:--
    Calculate the centre of the panel, working out where the center of the shape
    is and applying a tranformation involving this "offset".
    The Sun tranform example uses the following to center the shape. I have
    tried to do similar in my program but without success.
    AffineTransform toCenterAt = new AffineTransform();
    toCenterAt.concatenate(at);
    toCenterAt.translate(-(r.width/2), -(r.height/2));
    any further help appreciated.
    Ian
    ps the link to the complete transform example:
    http://java.sun.com/docs/books/tutorial/2d/display/transforming.html


    "Ian Stanley" <> wrote in message
    news:...
    > Hi,
    > I have a simple program below where the user can draw rectangles on a

    panel.
    > The choice to either rotate or scale any single rectangle should result in
    > the appropriate action.(after selecting a shape).
    > However, the selected rectangle is transformed(rotated or scaled) but it
    > appears to be drawn translated as well.
    > I am guessing that it has somethig to do with transforming the coordinate
    > system for that shape.
    > Is there a way to fix it so that the selected shape is rotated or scaled

    at
    > its current location?
    > Thanking you in advance
    > Ian.
    >
    > import java.awt.*;
    > import java.awt.event.*;
    > import java.awt.geom.*;
    > import java.util.*;
    > import javax.swing.*;
    > public class SwingDraw
    > {
    > public static void main(String[] args)
    > {
    > Draw D = new Draw() ;
    > }
    > }
    >
    > interface Constants {
    > final int RECTANGLE = 1, ROTATE = 2, SCALE = 3;
    > }
    >
    > class Draw extends JFrame
    > implements Constants, ActionListener{
    > JPanel bp = new JPanel() ;
    > DrawJPanel djp ;
    > Container content = getContentPane() ;
    > JButton rectButton, rotateButton, quitButton, scaleButton ;
    >
    > Draw() {
    > super() ;
    > content.setLayout(new BorderLayout()) ;
    > djp = new DrawJPanel() ;
    > bp.add(rectButton = new JButton("Rectangle")) ;
    > bp.add(rotateButton = new JButton("rotate")) ;
    > bp.add(scaleButton = new JButton("scale")) ;
    > bp.add(quitButton = new JButton("Quit")) ;
    > quitButton.addActionListener(
    > new ActionListener(){
    > public void

    actionPerformed(ActionEvent
    > e) {
    > System.exit(0) ;
    > }
    > }) ;
    > rectButton.addActionListener(this) ;
    > rotateButton.addActionListener(this) ;
    > scaleButton.addActionListener(this) ;
    > content.add(bp, BorderLayout.NORTH) ;
    > content.add(djp, BorderLayout.CENTER) ;
    > setSize(750, 500) ;
    > setVisible(true) ;
    > }
    >
    >
    > public void actionPerformed(ActionEvent e) {
    > String cmd = e.getActionCommand() ;
    > switch (cmd.charAt(0)) {
    > case 'R':
    > djp.setMode(RECTANGLE) ;
    > break ;
    > case 'r':
    > djp.setMode(ROTATE) ;
    > break ;
    > case 's':
    > djp.setMode(SCALE) ;
    > break ;
    > }
    > }
    >
    > }
    > class DrawJPanel extends JPanel
    > implements Constants
    > {
    > Vector v = new Vector();
    > Shape current_shape = null;
    > int drawingMode;
    > public DrawJPanel()
    > {
    > addMouseListener(
    > new MouseAdapter() {
    > public void mousePressed(MouseEvent evt)
    > {
    > int x = evt.getX();
    > int y = evt.getY();
    > // check if we hit an existing shape
    > current_shape = locateRect(x,y);
    > // if ( current_shape==null)
    > // {
    > if (drawingMode == RECTANGLE){
    > Rectangle2D.Float e = new
    > Rectangle2D.Float(x, y, 80, 50);
    > v.add(e);
    > repaint();
    > }
    > else if (drawingMode == ROTATE &&
    > current_shape != null ){
    > rotateShape(x,y);
    > repaint();
    > }
    > else if (drawingMode == SCALE &&
    > current_shape != null ){
    > scaleShape(x,y);
    > repaint();
    > }
    > }
    > }
    > );
    > }
    > void setMode(int mode) {
    > drawingMode = mode ;
    > }
    >
    > public Shape locateRect(int x, int y)
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) )
    > return s;
    > }
    > return null;
    > }
    >
    > public Shape rotateShape(int x, int y)
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) ){
    > AffineTransform tr =
    > AffineTransform.getRotateInstance(Math.toRadians(45));
    > Shape ts = tr.createTransformedShape(current_shape);
    > v.addElement(ts);
    > v.removeElement(s);
    > repaint();
    > }
    > }
    > return null;
    > }
    >
    > public Shape scaleShape(int x, int y)
    >
    > {
    > for (int i = 0; i < v.size(); i++){
    > Shape s = (Shape)v.elementAt(i);
    > if (s.contains(x,y) ){
    > AffineTransform tr =
    > AffineTransform.getScaleInstance(0.7,0.7);
    > Shape ts = tr.createTransformedShape(current_shape);
    > v.addElement(ts);
    > v.removeElement(s);
    > repaint();
    > }
    > }
    > return null;
    > }
    >
    > public void paintComponent(Graphics gr)
    > {
    > super.paintComponent(gr);
    > Graphics2D g = (Graphics2D)gr;
    > for(int i=0; i<v.size(); i++)
    > g.draw((Shape)v.elementAt(i));
    > }
    > }
    >
    >
    Ian Stanley, Jul 31, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Random

    xslt, multiple transforms

    Random, Feb 28, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    1,469
    Wilco Bauwer
    Feb 28, 2005
  2. Ravi
    Replies:
    4
    Views:
    369
    Dimitre Novatchev
    Nov 10, 2003
  3. rush
    Replies:
    3
    Views:
    647
    David Carlisle
    Mar 30, 2005
  4. Replies:
    2
    Views:
    706
    Henry S. Thompson
    Oct 19, 2005
  5. Matthew
    Replies:
    2
    Views:
    479
    Chris Dams
    Oct 3, 2003
Loading...

Share This Page