java - AffineTransform without transforming Stroke? -
when using graphics2d scale()
function 2 different parameters (scaling different ratios in x- , y-direction), drawn later on graphics2d object scaled too. has strange effect lines drawn in 1 direction thicker in direction. following program produces effect, shows window:
public class strokeexample extends jpanel { public void paintcomponent(graphics context) { super.paintcomponent(context); graphics2d g = (graphics2d)context.create(); g.setstroke(new basicstroke(0.2f)); int height = getheight(); int width = getwidth(); g.scale(width/7.0, height/4.0); g.setcolor(color.black); g.draw(new rectangle( 2, 1, 4, 2)); } public static void main(string[] params) { eventqueue.invokelater(new runnable(){public void run() { strokeexample example = new strokeexample(); jframe f = new jframe("strokeexample"); f.setsize(100, 300); f.getcontentpane().setlayout(new borderlayout()); f.getcontentpane().add(example); f.setdefaultcloseoperation(windowconstants.dispose_on_close); f.setvisible(true); }}); } }
i'm using coordinate transform avoid having manually transform application model coordinates (the (2,1, 2,4) in example) screen (or component) pixel coordinates, don't want stroke distortion. in other words, i want have lines same width, independent of current x- , y-scale-factors.
i know produces effect (the stroke object creates stroked shape of rectangle painted in user coordinates, translated screen coordinates), i'm not sure on how solve this.
- should create new stroke implementation strokes shapes differently in x- , y-direction (thereby undoing distortion here)? (or knows such implementation?)
- should transform shapes screen coordinates , stroke there?
- any other (better) ideas?
turns out question not horrible difficult, , 2 ideas given in question same idea. here transformedstroke
class implements distorted stroke
transforming shape
.
import java.awt.*; import java.awt.geom.*; /** * implementation of {@link stroke} transforms stroke * {@link affinetransform} before stroking it. * * class immutable long underlying stroke * immutable. */ public class transformedstroke implements stroke { /** * make serializable without problems. */ private static final long serialversionuid = 1; /** * affinetransform used transform shape before stroking. */ private affinetransform transform; /** * inverse of {@link #transform}, used transform * after stroking. */ private affinetransform inverse; /** * our base stroke. */ private stroke stroke; /** * creates transformedstroke based on stroke * , affinetransform. */ public transformedstroke(stroke base, affinetransform at) throws noninvertibletransformexception { this.transform = new affinetransform(at); this.inverse = transform.createinverse(); this.stroke = base; } /** * strokes given shape stroke, creating outline. * * outline distorted our affinetransform relative * outline given base stroke, in terms * of scaling (i.e. thickness of lines), translation , rotation * undone after stroking. */ public shape createstrokedshape(shape s) { shape strans = transform.createtransformedshape(s); shape stransstroked = stroke.createstrokedshape(strans); shape sstroked = inverse.createtransformedshape(stransstroked); return sstroked; } }
my paint-method using looks this:
public void paintcomponent(graphics context) { super.paintcomponent(context); graphics2d g = (graphics2d)context.create(); int height = getheight(); int width = getwidth(); g.scale(width/4.0, height/7.0); try { g.setstroke(new transformedstroke(new basicstroke(2f), g.gettransform())); } catch(noninvertibletransformexception ex) { // should not occur if width , height > 0 ex.printstacktrace(); } g.setcolor(color.black); g.draw(new rectangle( 1, 2, 2, 4)); }
then window looks this:
i'm quite content this, if has more ideas, feel free answer nevertheless.
attention: g.gettransform()
returning complete transformation of g relative device space, not transformation applied after .create()
. so, if did scaling before giving graphics component, still draw 2-device-pixel width stroke, not 2 pixels of grapics given method. if problem, use this:
public void paintcomponent(graphics context) { super.paintcomponent(context); graphics2d g = (graphics2d)context.create(); affinetransform trans = new affinetransform(); int height = getheight(); int width = getwidth(); trans.scale(width/4.0, height/7.0); g.transform(trans); try { g.setstroke(new transformedstroke(new basicstroke(2f), trans)); } catch(noninvertibletransformexception ex) { // should not occur if width , height > 0 ex.printstacktrace(); } g.setcolor(color.black); g.draw(new rectangle( 1, 2, 2, 4)); }
in swing graphics given paintcomponent
translated (so (0,0) upper left corner of component), not scaled, there no difference.
Comments
Post a Comment