java - Affine transforms for graph, not for text and labels -
this post suite answer made question: transforming shape
here image want:
here image simple program produces, can see text rotated. want horizontal text:
the canvas scaled, translated, rotated drawing, text not displayed horizontaly , font size need extremely reduced (1.4). program wrote in java (awt , javafx) problem not language or technology relevant, suggestion welcome.
here simple program:
import javafx.application.application; import javafx.geometry.vpos; import javafx.scene.scene; import javafx.scene.canvas.canvas; import javafx.scene.canvas.graphicscontext; import javafx.scene.layout.borderpane; import javafx.scene.paint.color; import javafx.scene.text.font; import javafx.scene.text.textalignment; import javafx.stage.stage; public class transrotscale extends application { private static void drawgraph( graphicscontext g ) { //--- g.scale( 10.0, 10.0 ); g.rotate( math.todegrees( math.atan2( -15.0, 40.0 ))); g.translate( -8, -10 ); //--- g.setstroke( color.darkred ); g.setlinewidth( line_width ); g.strokeline( 10, 20, 10, 30 ); g.strokeline( 10, 30, 50, 30 ); g.strokeline( 50, 30, 50, 35 ); //--- g.setfill( color.black ); g.filloval( 50-endpoint_radius, 35-endpoint_radius, endpoint_diameter, endpoint_diameter ); g.filloval( 10-endpoint_radius, 20-endpoint_radius, endpoint_diameter, endpoint_diameter ); //--- g.setfill( color.lightsalmon ); g.filloval( 10-endpoint_radius, 30-endpoint_radius, endpoint_diameter, endpoint_diameter ); g.filloval( 50-endpoint_radius, 30-endpoint_radius, endpoint_diameter, endpoint_diameter ); //--- g.setstroke( color.darkgray ); g.setfont( font.font( font.getdefault().getfamily(), 1.4 )); g.setlinewidth( 0.1 ); g.settextalign( textalignment.center ); g.settextbaseline( vpos.bottom ); g.stroketext( "[10, 20]", 10, 20-endpoint_radius ); g.settextbaseline( vpos.top ); g.stroketext( "[10, 30]", 10, 30+endpoint_radius ); g.settextbaseline( vpos.bottom ); g.stroketext( "[50, 30]", 50, 30-endpoint_radius ); g.settextbaseline( vpos.top ); g.stroketext( "[50, 35]", 50, 35+endpoint_radius ); } @override public void start( stage primarystage ) throws exception { borderpane bp = new borderpane(); canvas canvas = new canvas( 540, 240 ); bp.setcenter( canvas ); drawgraph( canvas.getgraphicscontext2d()); primarystage.setscene( new scene( bp )); primarystage.centeronscreen(); primarystage.show(); } public static final double endpoint_radius = 2.0; public static final double endpoint_diameter = 2.0*endpoint_radius; public static final double line_width = 1.0; public static void main( string[] args ) { launch(); } }
in program used display first image (the goal), use 2 canvases, first canvas scaled, translated, rotated drawing without text , second canvas used draw labels horizontally, using java.awt.geom.affinetransform
compute coordinates match item displayed in first canvas. both canvases displayed superposed, transparent.
this suggest alexander kirov, if understand well:
import javafx.application.application; import javafx.geometry.vpos; import javafx.scene.scene; import javafx.scene.layout.pane; import javafx.scene.paint.color; import javafx.scene.shape.circle; import javafx.scene.shape.polyline; import javafx.scene.text.font; import javafx.scene.text.text; import javafx.scene.text.textalignment; import javafx.stage.stage; public class transrotscal extends application { @override public void start( stage primarystage ) throws exception { pane pane = new pane(); pane.setscalex( 10.0 ); pane.setscaley( 10.0 ); pane.setrotate( theta ); pane.settranslatex( 468.0 ); pane.settranslatey( 152.0 ); polyline line = new polyline( 10,20, 10,30, 50,30, 50,35 ); line.setstroke( color.darkred ); circle c0 = new circle( 10, 20, 2, color.black ); circle c1 = new circle( 10, 30, 2, color.lightsalmon ); circle c2 = new circle( 50, 30, 2, color.lightsalmon ); circle c3 = new circle( 50, 35, 2, color.black ); text t0 = createtext( 10, 20, "[10,20]", vpos.bottom ); text t1 = createtext( 10, 30, "[10,30]", vpos.top ); text t2 = createtext( 50, 30, "[50,30]", vpos.bottom ); text t3 = createtext( 50, 35, "[50,35]", vpos.top ); pane.getchildren().addall( line, c0, c1, c2, c3, t0, t1, t2, t3 ); primarystage.setscene( new scene( pane )); primarystage.centeronscreen(); primarystage.setwidth ( 580 ); primarystage.setheight( 280 ); primarystage.show(); } private text createtext( int x, int y, string label, vpos vpos ) { text text = new text( x, y, label ); text.setfill( color.darkgray ); text.setfont( font.font( font.getdefault().getfamily(), 1.4 )); text.rotateproperty().set( -theta ); text.textalignmentproperty().setvalue( textalignment.center ); text.setx( text.getx() - text.getboundsinlocal().getwidth()/2.0); text.textoriginproperty().set( vpos ); if( vpos == vpos.bottom ) { text.sety( text.gety() - 2 ); } else { text.sety( text.gety() + 2 ); } return text; } private final double theta = math.todegrees( math.atan2( -15.0, 40.0 )); public static void main( string[] args ) { launch(); } }
it works use node in place of canvas , values adjust texts obtained iterative tries (a lot!); i don't know how calculate them.
alexander, may edit post or post own complete it, in later case i'll delete this.
here result, note approximative placement of text around discs:
Comments
Post a Comment