When you use Graphics2D.scale(); and draw a shape, the outline thickness is also scaled.
Is there a way to draw it without the line thickness being scaled? Perhaps there's another efficient way to scale it other than using the above function?
This question is similar. It looks like you have to mess around with a Stroke object to set the right line width.
You're going to have to save your drawing as a list of line vectors, and scale and render the drawing at various sizes to maintain the line thickness you want.
I've just found a solution to my own question. I've no idea how efficient it is but it works as intended:
Area area = new Area(myShape); //myShape is the shape I want to scale
AffineTransform at = new AffineTransform();
at.scale(2,2);
area = area.createTransformedArea(at);
graphics2d.draw(area); //graphics2d is the Graphics2D instance to do the drawing
Perhaps someone could enlighten me as to whether or not this is a good approach to take?
Related
I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.
I have a cube which can be rotated in x,y and z direction.I figured out how to draw its wireframe and how to fill the sides with one colour per side.But my attempts to texture the cube failed.All possibilities to adapt an image to non-cubic shapes I have found use an external library but I want to do it in pure java.
Here is what i tried:
Polygon polygon = new Polygon();
polygon.addPoint((int)p[1][x]+200, (int)p[1][y]+200);
polygon.addPoint((int)p[2][x]+200, (int)p[2][y]+200);
polygon.addPoint((int)p[6][x]+200, (int)p[6][y]+200);
polygon.addPoint((int)p[5][x]+200, (int)p[5][y]+200);
g.setClip(polygon);
g.drawImage(tex, (int)p[1][x]+200, (int)p[1][y]+200, null);
g.setClip(new Rectangle(0, 0, this.getWidth(), this.getHeight()));
you have to transform the image, you can shear, rotate, translate etc on your image...
to do so you need an Affine-matrix to transform the image...
once you know how to use the matrix you can also use it to transform your points, it's a very comfortable way
see also the a question on how to shear a bitmap:
btw: nice work, there doing it in pure java!
sorry, when i'm only responding in sending links, but maybe you can be a bit more specific on your ptoblem =)
I have a rather pressing question in regards to Swing, which I haven't touched for many years.
I have a code that allows the user to draw different rectangles on the pdf document (contained within JPanel). I draw them, move them, resize them, select them, and even write text on them. What I can't do is to keep them consistent when I zoom the document. As the document gets bigger, the rectangles I've drawn stay at the same position and the same size.
I was wondering if there's a relatively easy logic to track the zooming level and, most importantly, update the rectangles accordingly. I can retrieve zoom factor, it's a float, but, unfortunately, I'm using Rectangle object, which uses int for x, y, height, and width. It will be a hassle to convert it to Rectangle.Float, and I wanted to save it for a last resort.
I've tried to use AffineTransform, but I'm not quite familiar with it, for some reason I'm getting the wrong coordinates for y. Can anyone explain to me:
What's the best way to control the Rectangle object, as the pdf document gets zoomed in and out?
If AffineTransform is the best way, how should I handle it (maybe there's a link to a good explanation, if so - I couldn't find it)?
This is the only issue I've been struggling with and it's getting a bit frustrating now.
To scale using an AffineTransform:
Get the transform T of the Graphics object G
Create an AffineTransform object A
Set the scale of A
Set the transform of the G to A
Draw the shapes
Set the transform of G back to T
Translated into code - assuming scale is the value to scale by:
#Override
protected void paintComponent(Graphics gr){
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
AffineTransform prevTransform = g.getTransform();
AffineTransform at = new AffineTransform(prevTransform);
at.scale(scale, scale);
g.setTransform(at);
g.drawRect(...);
g.setTransform(prevTransform);
}
I have the following code:
private _x,_y,_w,_h;
protected void paintComponent( Graphics g_ ) {
g_.setStroke( new BasicStroke(2) );
g_.drawLine(_x, _y, _x+_w, _y+_h);
g_.drawLine(_x, _y+_h, _x+_w, _y);
}
In my case I'm drawing the diagonals of a square so: _w==_h.
My problem the two line don't have the same apparent thikness: the first line look thicker than the second. When checking the actual pixels drawn here's the difference of rendering:
I don't really care which one should be considered "correct" (though I'd like to understand the reasons of this result), but I'd like some coherence here, that both lines have the same rendering: how can I do that?
(when I use a 1px stroke, there's no difference between the two lines).
Followup to Olavi's ansewer:
Using an odd number of pixel for the stroke doesn't solve the problem:
Enabling anti-aliasing leads to another problem: the stroke of the square in which the cross is drawn gets blurred:
Basically you have two options:
Use an odd-number thickness
Use antialiasing
Personally I prefer antialiasing, because it's pretty and I like pretty things. However to explain why a stroke width of 2 behaves like that: Java does not know whether or not draw the line with the first way or the second way (I can't really explain exactly why it does what it does, but this is what I see). To further elaborate this answer, try starting the other line one pixel to the left or to the right: this should result in two lines with the same thickness.
To use antialiasing, do the following (untested code!). Code picked up from here:
Graphics2D graphics2D = (Graphics2D) g_;
graphics2D.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.drawLine(_x, _y, _x+_w, _y+_h);
graphics2D.drawLine(_x, _y+_h, _x+_w, _y);
This is not really important, but it was bothering me for a little while.
Problem description:
Given: a line (Line2D)
Wanted: drawing the line as a wedge (Filled GeneralPath)
Surely this can be done by creating the wedge as General Path and then filling it by the Graphics (my solution).
My first approach would have been a wedge-stroked line, because I didn't want to change the line object for some reason, also I just wanted to draw the line object and not think about it any more.
Creating the wedge-stroke was no problem (Some calculations and then creating the General Path) - but I was not able to fill it (easily)
Apparently it seems the fill of Graphics2D only fills the shape it gets - and does not handle the filling of the stroke (that behavior makes sense if one thinks about it).
Question: Is there any way to fill a shape of a Stroke (filling a shape - more specifically: a GeneralPath - somehow before drawing it)?
May be BasicStroke.public Shape createStrokedShape(Shape s) can help if you pass the Line2D there?
Once you use createStrokedShape(), note that draw() "strokes the outline of a Shape," while fill() "fills the interior of a Shape."
import java.awt.*;
public static Shape strokeToShape(Shape path, float strokeWidth)
return new BasicStroke(strokeWidth).createStrokedShape(path);
}
You may also specify cap and join parameters of BasicStroke