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:

example screenshot

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:

screenshot of undistorted stroke

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

Popular posts from this blog

jQuery clickable div with working mailto link inside -

WPF: binding viewmodel property of type DateTime to Calendar inside ItemsControl -

java - Getting corefrences with Standard corenlp package -