...
class CustomPanel extends JPanel {
public void paintComponent(Graphics painter) {
painter2D = (Graphics2D)painter;
painter2D.translate(width/2, height/2);
...
But I would also prefer the positive values across the y axis to be
positive above the base line and negative below.
I could use
painter2D.rotate(-Math.PI/2);
but then of course the x axis and the y axis replace each other, so then
I have to use, for example,
Rectangle 2D frame = new Rectangle2D.Double(y, x, h, w);
instead of
Rectangle 2D frame = new Rectangle2D.Double(x, y, w, h);
As I see it my choices are:
(a) Get used to the y axis moving downwards.
(b) Use rotation and learn to remember that y replaces x etc.
(c) Use (b) and overwrite the constructors that use x, y, w, h.
I would like to hear what the solution of experienced programmers is. I
tend to accept (a), hoping that after some time it will seem natural.
But is there a (d) option of reversing the direction of the y axis?
Thanks,
emf
--
It ain't THAT, babe! - A radical reinterpretation
https://files.nyu.edu/emf202/public/bd/itaintmebabe.html
From time immemorial screen coordinates have been expressed from the top-left
corner. You will go through a lot of useless effort resisting this.
Take the world for what it is and don't fight to jam it into your preconceptions.
--
Lew
Lew wrote:
> Take the world for what it is and don't fight to jam it into your
> preconceptions.
I missed a few points.
What the heck do you mean by "overwrite the constructors"?
Where did you get the idea that screen coordinates start at the top right?
They don't.
Your line 'Rectangle 2D frame = ...' will not compile.
--
Lew
It is generally a *very* bad idea to try to change the established
conventions, even if you don't like them.
The least readable piece of C code I have ever seen was written by some
programmers who preferred Pascal, and used #define to make their C code
look a bit Pascal-ish. Even for someone fluent in both C and Pascal, it
was very confusing.
If you do something to change the screen coordinate convention, anyone
else working on one of your programs is going to get into all sorts of
trouble dealing with the dissonance between their expectations and your
conventions.
Patricia
> From time immemorial screen coordinates have been expressed from the
> top-left corner. You will go through a lot of useless effort
> resisting this.
But even before such immemorial times, physicists and mathematicians are
used to coordinates starting in the bottom left corner.
> Take the world for what it is and don't fight to jam it into your
> preconceptions.
And Y-flipping is something standard in every sensible graphics package.
Usually one has some world coordinates, some "normalized device
coordinates" (NDC) and the raw device coordinates. Y-flipping is taken
care when passing from NDC to raw.
--
----------------------------------------------------------------------
nos...@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.
Yes. Use a scaling transform on the Graphics or Graphics2D instance,
just as you've already used a translation transform. Scale the X
coordinates by 1.0, and the Y coordinates by -1.0.
Don't forget to set it back to the original state when you're done drawing.
As for whether this is a good idea or not, IMHO the warnings to just
follow the existing conventions are over-cautious.
I agree that manipulating the language itself to try to make it look
like something else is a bad idea. But graphical coordinate systems are
inherently transformable, and it's actually a very good idea to do so
when the data is naturally in some coordinate system other than the
default one. It is much better to transform the coordinate system in
one place, and then just draw the data as it is, than to try to adjust
all of the data for each drawing operation explicitly.
If you are trying to do this just so that you can, for example, lay out
controls in a different coordinate system than the default, then I would
advise against it as others have (I doubt it would even work). But if
this is just about the things that you are drawing yourself, it's not
only not bad, it can actually be a good way to simplify the code.
Pete
Rene' Descartes wrote:
> But even before such immemorial times, physicists and mathematicians are
> used to coordinates starting in the bottom left corner.
>
On computer screens? I think not.
Different domain of discourse, different rules.
My degree is in mathematics, but I don't try to fight the standard for
screen coordinates. I'm much happier that way. I recommend the same
to you.
Lew wrote:
>> Take the world for what it is and don't fight to jam it into your
>> preconceptions.
>
Rene' Descartes wrote:
> And Y-flipping is something standard in every sensible graphics package.
Circular reasoning. You're proving your point by calling the
conclusion "sensible".
> Usually one has some world coordinates, some "normalized device
> coordinates" (NDC) and the raw device coordinates. Y-flipping is taken
> care when passing from NDC to raw.
>
The OP is using libraries that work in terms of screen coordinates.
Ergo, they must use screen coordinates. Y-flipping is not relevant.
--
Lew
Many thanks, Pete. I would have actually been surprised if they was not
a scale method. It works *almost* marvelously. The only thing I've found
so far is that if you try:
Arc2D.Double arc = new Arc2D.Double(0, 0, 100, 100, 0, 90, Arc2D.PIE);
the angle opens *downwards* rather than *upwards* as the angles do in
trigonometry.
Let me may clear that I am neither a programmer nor a mathematician.
15-20 years ago, when I had just learned QBasic I wrote strictly for my
own use a number of programs, the most complex of which would read the
coastline coordinates of the continents and draw globes any way I
wanted, along with doing a couple other specific things I wanted it to
do, with heavy use, of course, or spherical trigonometry. The programs
were sufficient for my needs at the time, and I postponed the
inevitable, that is learning an advanced language, until 5 years ago
when I audited 2 Java classes, working on them certainly much harder
than any of my for credit classmates. Soon, however, afterwards I lost
steam, perhaps realizing that the globe program was still far beyond my
capabilities at the time.
Then, last year my new Vista laptop finally relegated my old programs to
the programming junkyard (where of course they are only useful for still
valuable spare parts), and lately it seems I've caught once more
programming fever :) and started reworking the *easier* of my old
(graphics) programs. I am excited discovering Java's immense
capabilities (think of it: compared with QBasic!) and I enjoy the
learning that comes from hands-on experience. As for the globe program,
that will have to wait a little.
In QBasic I would always declare the screen coordinates as I wanted,
often with (0, 0) at the center of the screen that is indicated for
globes, and had never even occurred to me to opt *not* to have the y
axis *always* move upwards. I fully understand that this is a
convention, and now I soon have to decide on the issue. Your suggestion
would have settled it if only there wasn't this little thing with the
opening of the angles, and, I suspect, other repercussions coming later.
So, I am sorry to say Monsieur Descartes, however much I admire your
reasoning, I am on the brink of letting go and flow with the flow;
except if, after setting scale(1.0, -1.0), there is an easy way to set
the angles opening upwards like in trigonometry...? I doubt it, but I
have to ask before going whichever way I will go.
Eustace
--
Date Calculator with all-purpose JS code
https://files.nyu.edu/emf202/public/js/datecalc.html
Oh, come on Lew. Since anyone ever thought of using a coordinate system
on a computer screen, some APIs have drawn from the bottom up while
others from the top down.
DIBSections on Windows are often bottom up, and at least one of the
current Mac OS APIs puts the origin in the lower left corner.
There is no "one right way" for computers.
> Different domain of discourse, different rules.
>
> My degree is in mathematics, but I don't try to fight the standard for
> screen coordinates. I'm much happier that way. I recommend the same
> to you.
I don't see any evidence anyone is trying to "fight" the API. The
drawing API is specifically designed to allow transformation from one
coordinate system to another.
The GUI APIs, not so much. I'm not aware of a way to position Swing
components, for example, in any coordinate system other than the "origin
top-lef" one, unless one writes a complete transformation layer that
goes between one's own GUI code and the Swing API (which IMHO would
count as "fighting" the API).
But that's not the topic here.
> [...]
> The OP is using libraries that work in terms of screen coordinates.
> Ergo, they must use screen coordinates. Y-flipping is not relevant.
The OP is using libraries that provide robust and reliable control of
the coordinate system in use. They are free to draw using whatever
coordinate system they want, including one where the Y axis is flipped
relative to the default.
Pete
> On 2010-06-16 11:21 Peter Duniho wrote:
[...]
> > Yes. Use a scaling transform on the Graphics or Graphics2D instance,
> > just as you've already used a translation transform. Scale the X
> > coordinates by 1.0, and the Y coordinates by -1.0.
[...]
> Many thanks, Pete. I would have actually been surprised if they was not
> a scale method. It works *almost* marvelously. The only thing I've found
> so far is that if you try:
>
> Arc2D.Double arc = new Arc2D.Double(0, 0, 100, 100, 0, 90, Arc2D.PIE);
>
> the angle opens *downwards* rather than *upwards* as the angles do in
> trigonometry.
This may be a limitation of Arc2D itself, which specifies "that 45
degrees always falls on the line from the center of the ellipse to the
upper right corner of the framing rectangle.
<http://java.sun.com/javase/6/docs/api/java/awt/geom/Arc2D.html>
> 15-20 years ago, when I had just learned QBasic I wrote strictly for my
> own use a number of programs, the most complex of which would read the
> coastline coordinates of the continents and draw globes any way I
> wanted, along with doing a couple other specific things I wanted it to
> do, with heavy use, of course, or spherical trigonometry.
You may enjoy Jerry Huxtable's Globe Applet and map projection library,
written in Java:
<http://www.jhlabs.com/java/maps/proj/index.html>
[...]
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
I would never assume that 0,0 is top left.
I would read the docs to see if it is top left or bottom
left or center or something else.
Top left is by far the most common - probably an inheritage
from hardcopy terminals.
But common != guaranteed.
Arne
You mean:
#define begin {
#define end }
?
I have seen that too !
<various nasty words censored >
Arne
Talking about conventions, the pixel by pixel way of drawing an ark does
not give the same results as the Ard2D:
...
setSize(width, height);
...
Rectangle2D.Double pixel = new Rectangle2D.Double(0, 0, 1, 1);
painter2D.translate(width/2, height/2);
painter2D.setColor(Color.red);
x = -100;
y = -100;
w = 200;
h = 200;
arc = new Arc2D.Double(x, y, w, h, 0, 90, Arc2D.Double.OPEN);
painter2D.draw(arc);
painter2D.setColor(Color.green);
x = 0;
y = 0;
double x0 = x + w/2;
double y0 = y - h/2;
double r = 100;
double q;
for (int i = 0; i < 89; i++) {
q = Math.toRadians(i);
pixel.x = Math.sin(q) * r;
pixel.y = Math.cos(q) * r;
painter2D.fill(pixel);
}
For the second method to give the same arc it has to be:
q = Math.toRadians(i + 90);
(I am using variable q instead of theta, since q is the Latin letter
representing the Greek theta in "Greeklish", that is writing Greek using
the Latin alphabet.)
So Java is following 2 contradicting conventions. I do not remember any
such problems with Basic. If it had even crossed my mind that the
setting of the axes might have been different in other languages, I
would have spent some time investigating how different languages handle
this before plunging into one, and it would have been one of the factors
in my decision.
Anyway, the decisive drawback against using
scale(1.0, -1.0)
is that if you then want to use
painter2D.draw(String, x, y)
the string appears in the right place but upside down. There may be ways
to correct this, but would make programming more complicated than
flowing with the flow, so that settles the issue.
I will be checking the projection library (as well as your website).
Thanks,
emf
--
The folk oratorios of Mikis Theodorakis
https://files.nyu.edu/emf202/public/mt/oratorios.html
> On 2010-06-17 10:42 John B. Matthews wrote:
> > In article <hvc94v$7ep$1...@speranza.aioe.org>,
> > Eustace <emf...@gmail.ccom> wrote:
> >
> >> On 2010-06-16 11:21 Peter Duniho wrote:
> > [...]
> >>> Yes. Use a scaling transform on the Graphics or Graphics2D
> >>> instance, just as you've already used a translation transform.
> >>> Scale the X coordinates by 1.0, and the Y coordinates by -1.0.
[Thoughtful arc implementation elided.]
> Anyway, the decisive drawback against using
>
> scale(1.0, -1.0)
>
> is that if you then want to use
>
> painter2D.draw(String, x, y)
>
> the string appears in the right place but upside down. There may be ways
> to correct this, but would make programming more complicated than
> flowing with the flow, so that settles the issue.
One can always preserve and restore the graphics transform:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
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;
/** @author John B. Matthews */
public class SineTest extends JPanel implements Runnable {
private static final int SIZE = 400;
private AffineTransform at;
public static void main(String[] args) {
EventQueue.invokeLater(new SineTest());
}
@Override
public void run() {
JFrame f = new JFrame("ArcTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public SineTest() {
this.setPreferredSize(new Dimension(640, 480));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
g2d.setColor(Color.gray);
g2d.drawLine(w / 2, 0, w / 2, h);
g2d.drawLine(0, h / 2, w, h / 2);
at = g2d.getTransform();
g2d.translate(w / 2, h / 2);
g2d.scale(1, -1);
g2d.setColor(Color.blue);
double r = SIZE / 2;
double q = -Math.PI / 2;
double d = Math.PI / 180d;
int x1 = (int) Math.round(q * r);
int y1 = (int) Math.round(Math.sin(q) * r);
int x2, y2;
for (int i = 0; i < 180; i++) {
q += d;
x2 = (int) Math.round(q * r);
y2 = (int) Math.round(Math.sin(q) * r);
g2d.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
}
g2d.setTransform(at);
g2d.setColor(Color.blue);
g2d.drawString("y = sin(x)", 100, 100);
}
}
> I will be checking the projection library (as well as your website).
Excellent!
>(a) Get used to the y axis moving downwards.
>
>(b) Use rotation and learn to remember that y replaces x etc.
>
>(c) Use (b) and overwrite the constructors that use x, y, w, h.
The most important thing is, no matter what you choose, document your
convention. If you don't document this, it can confuse, or waste other
people's time trying to figure out what you used. This is especially
true if you change the convention at different stages of your
computation.
--
Roedy Green Canadian Mind Products
http://mindprod.com
There is no harm in being sometimes wrong especially if one is promptly found out.
~ John Maynard Keynes (born: 1883-06-05 died: 1946-04-21 at age: 62)