@@ -412,6 +412,7 @@ def render_path(self, pathid):
412412 transpath = agg .conv_transform_path (path .agg_path , aggaffine )
413413
414414 if path .fillcolor is not None :
415+ print 'render path' , path .fillcolor , path .agg_fillcolor
415416 self .rasterizer .add_path (transpath )
416417 renderer .color_rgba8 ( path .agg_fillcolor )
417418 render_scanlines (self .rasterizer , scanline , renderer );
@@ -463,8 +464,9 @@ def render_markers(self, markerid):
463464
464465
465466 for xv ,yv ,tmp in Locs .T :
466- XY [:,0 ] = pathx + xv
467- XY [:,1 ] = pathy + yv
467+ XY [:,0 ] = (pathx + xv ).astype (int ) + 0.5
468+ XY [:,1 ] = (pathy + yv ).astype (int ) + 0.5
469+
468470
469471 pathdata = pathcodes , XY
470472 aggpath = AggPath .make_agg_path (pathdata )
@@ -626,7 +628,7 @@ def _fillcolor__changed(self, oldcolor, newcolor):
626628 self .agg_fillcolor = self .color_to_rgba8 (newcolor )
627629
628630 def _strokecolor__changed (self , oldcolor , newcolor ):
629-
631+ print 'stroke color changed' , newcolor
630632 c = self .color_to_rgba8 (newcolor )
631633 self .agg_strokecolor = c
632634
@@ -725,7 +727,10 @@ def add_artist(self, artist, followdata=True, followview=True):
725727 # respects zorder drawing internally. This makes zordering
726728 # much more flexibel
727729 self .artistd [artist .artistid ] = artist
730+
728731 artist .renderer = self .renderer
732+ self .sync_trait ('renderer' , artist , mutual = False )
733+
729734
730735 artist .followdata = followdata
731736 artist .followview = followview
@@ -740,7 +745,6 @@ def add_artist(self, artist, followdata=True, followview=True):
740745 self .aview .on_trait_change (artist .aview .follow , 'vec6' )
741746
742747
743- self .sync_trait ('renderer' , artist , mutual = False )
744748
745749 def remove_artist (self , artist ):
746750
@@ -761,6 +765,7 @@ def draw(self):
761765 dsu = [(artist .zorder , artist .artistid , artist ) for artist in self .artistd .values ()]
762766 dsu .sort ()
763767 for zorder , artistid , artist in dsu :
768+ #print 'artist draw', self, artist, zorder
764769 artist .draw ()
765770
766771
@@ -938,86 +943,198 @@ class Figure(Artist):
938943 pass
939944
940945
941-
942- class Axes (Artist ):
943- zorder = traits .Float (0.5 )
946+ class Axis (Artist ):
947+ zorder = traits .Float (1.5 )
948+ tickmarkers = mtraits .Markers
949+ linepath = mtraits .Path
950+ linecolor = mtraits .Color ('black' )
951+ linewidth = mtraits .LineWidth (1.0 )
952+ ticklocs = traits .Array ('d' )
953+ ticksize = traits .Float (7.0 )
954+ ticklinewidth = mtraits .LineWidth (1.0 )
955+ tickcolor = mtraits .Color ('black' )
956+
957+ loc = traits .Float (0. ) # the y location of the x-axis
958+ tickoffset = traits .Float (- 0.5 ) # -1 for outer, -0.5 for centered, 0 for inner
944959
945- xtickmarkers = mtraits .Markers
946- xaxisline = mtraits .Line
947- xticklocs = traits .Array ('d' )
948- xaxislocy = traits .Float (0. ) # the y location of the x-axis
949-
950- ytickmarkers = mtraits .Markers
951- yaxisline = mtraits .Line
952- yticklocs = traits .Array ('d' )
953- yaxislocx = traits .Float (0. ) # the x location of the y-axis
954-
955960 def __init__ (self ):
956961 Artist .__init__ (self )
957- self .xtickmarkersid = primitiveID ()
962+ self .tickmarkersid = primitiveID ()
963+ self .linepathid = primitiveID ()
964+
965+ self .affine .on_trait_change (self ._update_blended_affine , 'vec6' )
966+ self .tickmarkers .path .antialiased = False
967+ self .linepath .antialiased = False
968+
969+ self .sync_trait ('linewidth' , self .linepath , mutual = False )
970+ self .sync_trait ('linecolor' , self .linepath , 'strokecolor' , mutual = False )
971+ self .sync_trait ('ticklinewidth' , self .tickmarkers .path , 'linewidth' , mutual = False )
972+ self .sync_trait ('tickcolor' , self .tickmarkers .path , 'strokecolor' , mutual = False )
973+
974+ # XXX, do we have to manually call these or will they get
975+ # calle dautomagically in init
976+ self ._update_tick_path ()
977+ self ._update_marker_locations ()
978+ self ._update_blended_affine ()
979+ self ._update_linepath ()
980+
981+ def _ticklocs_changed (self , old , new ):
982+ self ._update_marker_locations ()
958983
959- self .xtickmarkers .affine .follow (self .adata .vec6 )
960- self .adata .on_trait_change (self .xtickmarkers .affine .follow , 'vec6' )
984+ def _loc_changed (self , old , new ):
985+ self ._update_blended_affine ()
986+
987+ def _ticksize_changed (self , old , new ):
988+ self ._update_tick_path ()
961989
962- def _xticklocs_changed (self , old , new ):
963- self ._update_xtick_markers ( )
990+ def _tickoffset_changed (self , old , new ):
991+ self ._update_tick_path ( self )
964992
965- def _xaxislocy_changed (self , old , new ):
966- self ._update_xtick_markers ()
993+ def _update_blended_affine (self ):
994+ 'blend of xdata and y axis affine'
995+ raise NotImplementedError
967996
968- def _update_xtick_markers (self ):
969- verts = self .xaxislocy * npy .ones (len (new ))
970- verts [:,1 ] = new
971- self .xtickmarkers .verts = verts
997+ def _update_marker_locations (self ):
998+ raise NotImplementedError
999+
1000+ def _update_tick_path (self ):
1001+ raise NotImplementedError
9721002
1003+ def _update_linepath (self ):
1004+ raise NotImplementedError
9731005
9741006 def _renderer_changed (self , old , new ):
9751007 if old is not None :
976- old .remove_markers (self .xtickmarkersid )
1008+ old .remove_markers (self .tickmarkersid )
1009+ old .remove_path (self .linepathid )
9771010
9781011 if new is not None :
979- new .add_markers (self .xtickmarkersid , self .xtickmarkers )
1012+ new .add_markers (self .tickmarkersid , self .tickmarkers )
1013+ new .add_path (self .linepathid , self .linepath )
9801014
9811015 def draw (self ):
9821016 if self .renderer is None or not self .visible : return
983- #print 'Axes data affine:\n', self.adata
984- #print 'Axes view affine :\n', self.aview
985- #print 'Axes affine :\n', self.affine
9861017 Artist .draw (self )
987- self .renderer .render_markers (self .xtickmarkersid )
1018+ self .renderer .render_markers (self .tickmarkersid )
1019+ self .renderer .render_path (self .linepathid )
1020+
1021+ class XAxis (Axis ):
1022+
1023+ def _update_blended_affine (self ):
1024+ 'blend of xdata and y axis affine'
1025+ sx , b , tx = self .adata .data [0 ]
1026+ a = Affine ()
1027+ a .vec6 = sx , b , 0 , 1 , tx , self .loc
1028+ self .tickmarkers .affine .vec6 = (self .aview * a ).vec6
1029+
1030+ a = Affine ()
1031+ a .translate = 0 , self .loc
1032+ self .linepath .affine .vec6 = (self .aview * a ).vec6
1033+
1034+ def _update_marker_locations (self ):
1035+ Nticks = len (self .ticklocs )
1036+ verts = self .loc * npy .ones ((Nticks ,2 ))
1037+ verts [:,0 ] = self .ticklocs
1038+ self .tickmarkers .verts = verts
1039+
1040+ def _update_tick_path (self ):
1041+ codes = Path .MOVETO , Path .LINETO
1042+ verts = npy .array ([[0. , self .tickoffset ], [0 , self .tickoffset + 1 ]])* self .ticksize
1043+ self .tickmarkers .path .pathdata = codes , verts
1044+
1045+ def _update_linepath (self ):
1046+ codes = Path .MOVETO , Path .LINETO
1047+ X = npy .array ([[0 , 1 ], [0 , 0 ]], npy .float_ ).T
1048+ self .linepath .pathdata = codes , X
1049+
1050+ class YAxis (Axis ):
1051+
1052+
1053+ def _update_blended_affine (self ):
1054+ 'blend of xdata and y axis affine'
1055+ c , sy , ty = self .adata .data [1 ]
1056+ a = Affine ()
1057+ a .vec6 = 1 , 0 , 0 , sy , self .loc , ty
1058+ self .tickmarkers .affine .vec6 = (self .aview * a ).vec6
1059+
1060+ a = Affine ()
1061+ a .translate = self .loc , 0
1062+ self .linepath .affine .vec6 = (self .aview * a ).vec6
1063+
1064+ def _update_marker_locations (self ):
1065+ Nticks = len (self .ticklocs )
1066+ verts = self .loc * npy .ones ((Nticks ,2 ))
1067+ verts [:,1 ] = self .ticklocs
1068+ self .tickmarkers .verts = verts
1069+
1070+ def _update_tick_path (self ):
1071+ codes = Path .MOVETO , Path .LINETO
1072+ verts = npy .array ([[self .tickoffset ,0 ], [self .tickoffset + 1 ,0 ]])* self .ticksize
1073+ self .tickmarkers .path .pathdata = codes , verts
1074+
1075+ def _update_linepath (self ):
1076+ codes = Path .MOVETO , Path .LINETO
1077+ X = npy .array ([[0 , 0 ], [0 , 1 ]], npy .float_ ).T
1078+ self .linepath .pathdata = codes , X
1079+
1080+
1081+ class Axes (Artist ):
1082+ zorder = traits .Float (0.5 )
1083+
1084+
1085+
1086+ ytickmarkers = mtraits .Markers
1087+ yaxisline = mtraits .Line
1088+ yticklocs = traits .Array ('d' )
1089+ yticksize = traits .Float (5.0 )
1090+ yaxislocx = traits .Float (0. ) # the x location of the y-axis
1091+
1092+
1093+
9881094
989- x1 = npy .arange (0 , 10. , 0.05 )
990- x2 = npy .arange (0 , 10. , 0.1 )
991- y1 = npy .cos (2 * npy .pi * x1 )
992- y2 = 10 * npy .exp (- x1 )
1095+ def make_subplot_ll (fig ):
1096+ x1 = npy .arange (0 , 10. , 0.05 )
1097+ x2 = npy .arange (0 , 10. , 0.1 )
1098+ y1 = npy .cos (2 * npy .pi * x1 )
1099+ y2 = 10 * npy .exp (- x1 )
9931100
994- fig = Figure ()
995- axes = Axes ()
9961101
997- axes . aview . scale = 0.4 , 0.4
998- axes . aview . translate = 0.1 , 0.1
1102+ axes = Axes ()
1103+ fig . add_artist ( axes , followdata = False , followview = False )
9991104
1000- fig .add_artist (axes , followdata = False , followview = False )
1105+ axes .aview .scale = 0.4 , 0.4
1106+ axes .aview .translate = 0.1 , 0.1
10011107
1002- line1 = Line ().set (X = npy .array ([x1 ,y1 ]).T ,
1003- color = 'blue' , linewidth = 2.0 , marker = 's' , markersize = 5.0 ,
1004- markerfacecolor = 'green' , markeredgewidth = 0.5 )
1108+ xaxis = XAxis ()
1109+ axes .add_artist (xaxis )
10051110
1111+ yaxis = YAxis ()
1112+ axes .add_artist (yaxis )
10061113
1007- axes .add_artist (line1 )
1114+ line1 = Line ().set (X = npy .array ([x1 ,y1 ]).T ,
1115+ color = 'blue' , linewidth = 2.0 , marker = 's' , markersize = 5.0 ,
1116+ markerfacecolor = 'green' , markeredgewidth = 0.5 )
10081117
10091118
1010- rect1 = Rectangle ().set (lbwh = [0 ,0 ,1 ,1 ], facecolor = 'white' )
1011- axes .add_artist (rect1 , followdata = False )
1119+ axes .add_artist (line1 )
10121120
10131121
1122+ rect1 = Rectangle ().set (lbwh = [0 ,0 ,1 ,1 ], facecolor = 'white' )
1123+ axes .add_artist (rect1 , followdata = False )
10141124
1015- # update the view limits, all the affines should be automagically updated
1016- axes .adata .xlim = 0 , 10
1017- axes .adata .ylim = - 1.1 , 1.1
1125+ # update the view limits, all the affines should be automagically updated
1126+ axes .adata .xlim = 0 , 10
1127+ axes .adata .ylim = - 1.1 , 1.1
1128+ xaxis .ticklocs = npy .arange (0. , 11. , 1. )
1129+ xaxis .loc = - 0.1
1130+ xaxis .linecolor = 'red'
10181131
1132+ yaxis .ticklocs = npy .arange (- 1.0 , 1.1 , 0.2 )
1133+ yaxis .loc = - 0.1
1134+ yaxis .linecolor = 'blue'
1135+ yaxis .tickcolor = 'blue'
10191136
1020- if 1 :
1137+ def make_subplot_ur ( fig ) :
10211138 axes2 = Axes ()
10221139
10231140 axes2 .aview .scale = 0.4 , 0.4
@@ -1038,8 +1155,11 @@ def draw(self):
10381155 axes2 .adata .ylim = - 1.1 , 1.1
10391156
10401157
1041- if 1 :
1158+ if __name__ == '__main__' :
10421159 renderer = RendererAgg ()
1160+ fig = Figure ()
10431161 fig .renderer = renderer
1162+ make_subplot_ll (fig )
1163+ make_subplot_ur (fig )
10441164 fig .draw ()
10451165 renderer .show ()
0 commit comments