aspose file tools*
The moose likes Swing / AWT / SWT and the fly likes How does this code work Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "How does this code work" Watch "How does this code work" New topic
Author

How does this code work

Kieran Murray
Ranch Hand

Joined: May 18, 2008
Posts: 47
Dear All,

Can you explain how the objects - Generators are placed in the right place on the drawing canvas by this piece of code - if it is this piece of code that does it.



Kind regards,

Kieran
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Maybe. Each of the Path2D.Double paths will likely have x,y location data built
into them. The AffineTransform "at" may then likely reposition/translate them
(as well as possibly alter them with scale, rotate, shear).
Kieran Murray
Ranch Hand

Joined: May 18, 2008
Posts: 47
Dear Craig,

Thanks again. Just to be sure that I understand what you are saying. In my Generator class below I define the Generator as a Path2D.Double. When I move this object are the co-ordinates in the object updated and is this how they are saved and they re-opened.



Kind regards,

Kieran Murray
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
When I move this object are the co-ordinates in the object updated and is this how they are saved and they re-opened.
No, sorry, I was vague in my reply above.
In the code snippet you posted the coordinates in the Path2D should not have changed; they should remain as you initialized them when you instantiated the path.
In that code the AffineTransform will copy the coordinates of your Path2D into new coordinates, transform them and use these new, transformed coordinates to create and return a new Shape. The transform operation would not alter the original Path2D.
To demonstrate this try drawing the path, drawing a transformed shape and then inspecting the coordinates of the original. They should be the same as you started with.

If you do want to change the coordinates of your original Path2D you could use the Path2D transform(AffineTransform at) method.
Here's an exploration:
Kieran Murray
Ranch Hand

Joined: May 18, 2008
Posts: 47
Dear Craig,

Thanks. From what I understand it is the shape s that has its co-ordinates changed by the Affine Transform.

I am not clear about the following - any explanations would be most welcome.

1. When the Affine Transform "at" is created does it in effect convert all of the JPanel into its new co-ordinate space.

2. When I save and reopen a file with the code below then it works correctly - i.e. the objects - generators are in the positions where they were last left. How does this work because I do not save the Affine Transform "at"



To repopulate the ArrayList for Generators the following code is used



The whole canvas is then repainted.

Finally, would you mind reading my explanation of how I think the program is working at some point - This is for my dissertation. There is a chance that some poor soul might have to interpret this program and develop it at a later date and I do not want to lead him or her up a blind alley.

The Drawing Canvas provided by the ShapePanel class is based on Affine Transforms. Affine Transforms were chosen because of the Zoom feature. Affine Transforms are a concept developed in Euclidean Algebra so that ratios are preserved between items - in essence it is the co-ordinate space that is zoomed not the object itself. This is important otherwise objects will seem to get closer to eachother as they are zoomed into.
The Affine Transform is created in the ShapePanel class
private AffineTransform at = new AffineTransform();
The AffineTransform class is used to move and scale and create electrical items of the Java Shape class. The mouse events are performed on the AffineTransform not on the electrical item as defined in the electrical item class itself. The key method in the paintComponent method is the following line of code
Shape s = at.createTransformedShape(shpnew);
This creates a new object 's' of the Java Shape class. The java Shape class is not to be confused with the Shapes class in the translation package which is a generic class which defines the methods that can be performed on any electrical item. The above code is used to create an affine transformed Shape s which is then drawn. This is done for all of the electrical objects as they come out of the ArrayList. Each of the electrical objects - transformers, transmission lines etc are Shapes created by one Affine Transform 'at'.
The code then provides for all of the electrical objects to be moved on the canvas by the following method
public void movePrimitives(int x, int y) {
System.out.println("Goodbye");
at.translate(x, y);
repaint();
}

It is the use of Affine Transforms that allow this. We are moving the Affine Transform 'at' and all the objects that have been created from it. Again, in the method 'zoomup' where the objects on the canvas are resized, it is due to the use of the Affine Transform that we can do this.
public void zoomup(int p) {
// This keeps the center of the component in place.
cx = this.getWidth() / 2;
cy = this.getHeight() / 2;
at.setToTranslation(cx, cy); //Reset atf*/
at.scale(p, p);
at.translate(-cx, -cy); //bring back the objects to the center
repaint();
}
The actions take place on the Affine Transform and as the electrical objects are part of the Affine Transform they are affected by these actions.

Kind regards,

Kieran
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
From what I understand it is the shape s that has its co-ordinates changed by
the Affine Transform.

Yes, as if the original path were copied and then altered/transformed into a new,
independent shape.

1. When the Affine Transform "at" is created does it in effect convert all of
the JPanel into its new co-ordinate space.

Yes.

2. When I save and reopen a file with the code below then it works correctly -
i.e. the objects - generators are in the positions where they were last left. How
does this work because I do not save the Affine Transform "at"

Consider the MyInterp app on Can move shapes individually but not as a group.
There are two transforming–type things happening in it.
When the user drags a path (dragging) one transform moves the individual path
around by actually changing the/its path data using the Path2D transform
method. This one path has permanently changed its relationship to the rest of the
paths. These changes are permanent and will be preserved after reading/writing
the paths.

The other transform–type activity is moving the "screen" (draggingScreen)
by uniformly translating all the paths in the component view. This is the affect
of the "at" in your first code snippet. This might be thought of as sliding the
drawing surface around within/under the component view. If you don't
save/serialize this (transform) then the reconstituted component would show up
with the drawing surface located at the component view origin (0,0), ie, not
shifted by "at" which would have the identity state.

So a restatement of the answer to the question might be that the paths have their
positions changed by the AffineTransform instance set in the mouseDragged
"else if(dragging)" block of the PathWrangler2 class. This transform and a
reference to the selected path are sent back to the MyInterp class
transformPath
method where the changes are made using the Path2Dtransform
method. This transform method makes the changes permanent in the
selected path.

For the sake of clarity: The AffineTransform instance in the PathWrangler2 class
is used to change the position of any one path as it is being dragged by the
user. The AffineTransform instance in the MyInterp class is used to "move the
screen", ie, to shift all paths together. This is the "at" in the original code
snippet.

would you mind reading my explanation of how I think the program is working at
some point

I'd be glad to. It might be better if I study it a bit.
Craig Wood
Ranch Hand

Joined: Jan 14, 2004
Posts: 1535
Some comments after reading you explanation:
1 — Using the AffineTransform class is a way to use matrix math to shift between one coordinate space and another.

2 — You can use AffineTransform in many ways. Two uses here are:
  • to uniformly move all graphic primitives drawn in a components graphics context
  • to (permanently) change the location of any graphic primitive in relation to others independent of the graphics context in which they may be rendered.

  • 3 — A convenient and flexible way of rendering primitives/shapes into a graphics context is to transform and draw them on–the–fly with the createTransformedShape method.

    4 — Using AffineTransform depends on how you are viewing the relationship between coordinate systems and how you want to move from one to another.
    Kieran Murray
    Ranch Hand

    Joined: May 18, 2008
    Posts: 47
    Dear Craig,

    A big thank you. I will incorporate your comments. The fact that there are two Affine Transforms - one for the ShapePanel(based on your MyInterp class) and one for the PathWrangler2(based on your PathWrangler class) is an important point to make. Those two classes are the fundamental classes in the package that does all my drawing and quite frankly without your help this project would not have been completed.

    Thank you again.

    Kind regards,

    Kieran
     
    wood burning stoves
     
    subject: How does this code work