1. Member Join Date
Dec 2008
Posts
2
Rep Power
0

## AffineTransform help

Hi Folks

Am new to java and this forum, and whilst I try to search and research before turning to forums, I am really struggling with AffineTransform.

I need to display a polyline whose values are supplied in a 'real world' coordinate system, eg:

Java Code:
```int[] xPoints = {126589, 124587, 122369};
int[] yPoints = {632547, 654235, 687954};
g2.drawPolyline(xPoints, yPoints, 2);```
At the moment I have a class that transforms these coordinates into pixel coordinates before sending to the draw method. The problem with my custom class is it uses math to work out the swing container width/height, calcualte the 'real world' height, and refactor based on these values. This seems overly clunky, and not very extensible if I wanted to display other coordinates outwith my hardcoded transform class.

The additional problem is the y coordinates origin is in the south rather than the computers north, so we have to do a bit of additional math here.

Is AffineTransformation a possible friend, and would anyone be able to provide a small snipet based on the above example? Most of the Affine examples I have looked at demo scaling images or flipping text.

Best wishes, tones  Reply With Quote

2. Senior Member Join Date
Aug 2008
Posts
384
Rep Power
13

## So your problem is that the y coordinates go from up --> down instead of down --> up. If you want them to start in the middle of your frame/applet/anything, just use
Java Code:
`newY = -y + height/2;`
Or isn't that what your mean?  Reply With Quote

3. Member Join Date
Dec 2008
Posts
2
Rep Power
0

##  Originally Posted by Supamagier So your problem is that the y coordinates go from up --> down instead of down --> up. If you want them to start in the middle of your frame/applet/anything, just use
Java Code:
`newY = -y + height/2;`
Or isn't that what your mean?

I guess my problem has a few issues, some of which need solving by math, and others which require java knowledge.

I need to read a text file that has (british national grid) coordinates, so an example line such as

Java Code:
```int[] xPoints = {000000,100000, 200000, 300000};
int[] yPoints = {000000,100000, 200000, 300000};```
in the real world would go from bottom left to top right.

If I had a 300x300 px JPanel, then it would be easy enough to just divide each real world coordinate by 1000, and then do something like (jpanelHeight-(Y/1000).

However, problems arise if the window resizes, or we try to draw a line

Java Code:
```int[] xPoints = {400000, 500000, 600000, 700000};
int[] yPoints = {400000, 500000, 700000, 700000};```
As it now doesn't fit into my hardcoded transformation method, the origin of the new polyline is outside of the canvas.

I was hoping that Affine Transformation would help me so that I can just keep to parsing the real world coordinates and let java work out the canvas size, get the real world coordinates and work out where to put it.

Essentially what I would like is that if the window resizes, the graphics all move and repaint so that the line (in our example) stays bottom left to top right. The other requirement is that if I load a second poly outwith the original bounds, it repaints both graphics so that they fit in to the canvas still (i.e scaling).  Reply With Quote

4. ## You can fix the issue of window resize by disabling resize. If this is just an applet running through FF or IE or something then I don't think you have that option.

I believe there is a class dealing with the OS that will let you pull the windowLength, windowWidth variables to use but I'm not positive.  Reply With Quote

5. ## Java Code:
```import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.util.Arrays;
import javax.swing.*;

public class ScaleToView extends JPanel {
int[] xPoints = { 400, 500 };
int[] yPoints = { 600, 400 };
final int TICK = 3;
int[] scaledX;
int[] scaledY;
AffineTransform xform;
Point origin;

protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
if(xform == null) {
initTransform();
}
Color flatBlack = g2.getColor();
Color gridColor = new Color(200,230,240);
// Draw axes.
// Draw axis tick marks and grid lines.
int[] maxVals = getMaxValues();
// Abcissa tick marks and vertical grid lines.
for(int i = 0; i <= maxVals; i += 100) {
Point2D.Double p = new Point2D.Double(i, 0);
Point2D.Double xp = new Point2D.Double();
xform.transform(p, xp);
g2.setPaint(flatBlack);
g2.draw(new Line2D.Double(xp.x, xp.y, xp.x, xp.y+TICK));
if(i > 0) {  // vertical grid lines
g2.setPaint(gridColor);
}
}
// Ordinate tick marks and horizontal grid lines.
for(int i = 0; i <= maxVals; i += 100) {
Point2D.Double p = new Point2D.Double(0, i);
Point2D.Double xp = new Point2D.Double();
xform.transform(p, xp);
g2.setPaint(flatBlack);
g2.draw(new Line2D.Double(xp.x, xp.y, xp.x-TICK, xp.y));
if(i > 0) {  // horizontal grid lines
g2.setPaint(gridColor);
}
}
// Draw labels on axes.
g2.setPaint(flatBlack);
FontRenderContext frc = g2.getFontRenderContext();
Font font = g2.getFont();
LineMetrics lm = font.getLineMetrics("0", frc);
float height = lm.getAscent() + lm.getDescent();
// Label abcissa.
for(int i = 0; i <= maxVals; i += 100) {
Point2D.Float p = new Point2D.Float(i, 0);
Point2D.Float xp = new Point2D.Float();
xform.transform(p, xp);
String s = String.valueOf(i);
float width = (float)font.getStringBounds(s, frc).getWidth();
float x = xp.x - width/2;
float y = xp.y + lm.getAscent() + TICK + SPAD;
g2.drawString(s, x, y);
}
// Label ordinate.
for(int i = 0; i <= maxVals; i += 100) {
Point2D.Float p = new Point2D.Float(0, i);
Point2D.Float xp = new Point2D.Float();
xform.transform(p, xp);
String s = String.valueOf(i);
float width = (float)font.getStringBounds(s, frc).getWidth();
float x = xp.x - width - SPAD - TICK;
float y = xp.y - height/2 + lm.getAscent();
g2.drawString(s, x, y);
}
int numPts = xPoints.length;
// Draw raw data.
// Offscreen -> down and right.
g2.setPaint(Color.blue);
g2.drawPolyline(xPoints, yPoints, numPts);
// Draw transformed src points into view.
g2.setPaint(Color.red);
g2.drawPolyline(scaledX, scaledY, numPts);
}

private void initTransform() {
int[] maxVals = getMaxValues();
System.out.printf("maxVals = [%d, %d]%n",
maxVals, maxVals);
double[] scales = getScales(maxVals);
System.out.printf("scales = [%.1f, %.1f]%n",
scales, scales);
double xScale = scales;
double yScale = scales;
// Move to the origin.
xform = AffineTransform.getTranslateInstance(origin.x, origin.y);
// Scale data into (this component) view.
xform.scale(xScale, yScale);
int[][] coords = getScaledPoints();
scaledX = coords;
scaledY = coords;
System.out.printf("scaledX = %s%nscaledY = %s%n",
Arrays.toString(scaledX),
Arrays.toString(scaledY));
}

private int[] getMaxValues() {
int[] maxVals = new int;
for(int i = 0; i < xPoints.length; i++) {
if(xPoints[i] > maxVals) {
maxVals = xPoints[i];
}
if(yPoints[i] > maxVals) {
maxVals = yPoints[i];
}
}
return maxVals;
}

private double[] getScales(int[] maxima) {
int h = getHeight() - 2*PAD;
double xScale =  (double)w / maxima;
double yScale = -(double)h / maxima;
return new double[] { xScale, yScale };
}

private int[][] getScaledPoints() {
int numPts = xPoints.length;
double[] srcPts = new double[2*numPts];
for(int i = 0, j = 0; i < srcPts.length; i += 2, j++) {
srcPts[i]   = xPoints[j];
srcPts[i+1] = yPoints[j];
}
double[] dstPts = new double[2*numPts];
xform.transform(srcPts, 0, dstPts, 0, numPts);
int[][] scaled = new int[numPts];
for(int i = 0, j = 0; i < numPts; i++) {
scaled[i] = (int)dstPts[j++];
scaled[i] = (int)dstPts[j++];
}
return scaled;
}

public static void main(String[] args) {
ScaleToView test = new ScaleToView();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}

private ComponentListener cl = new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
xform = null;
repaint();
}
};
}```  Reply With Quote

#### Posting Permissions

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