comparison src/graphics.cc @ 12369:e23f4609d558 release-3-4-x

Move axes labels and title positioning to axes::properties
author Konstantinos Poulios <logari81@gmail.com>
date Thu, 03 Feb 2011 19:30:13 +0100
parents 1a24d55b1714
children f6763ab98609
comparison
equal deleted inserted replaced
12368:3458c5bba6e5 12369:e23f4609d558
3299 xset (xlabel.handle_value (), "rotationmode", "auto"); 3299 xset (xlabel.handle_value (), "rotationmode", "auto");
3300 xset (xlabel.handle_value (), "horizontalalignmentmode", "auto"); 3300 xset (xlabel.handle_value (), "horizontalalignmentmode", "auto");
3301 xset (xlabel.handle_value (), "verticalalignmentmode", "auto"); 3301 xset (xlabel.handle_value (), "verticalalignmentmode", "auto");
3302 xset (xlabel.handle_value (), "clipping", "off"); 3302 xset (xlabel.handle_value (), "clipping", "off");
3303 xset (xlabel.handle_value (), "color", get_xcolor ()); 3303 xset (xlabel.handle_value (), "color", get_xcolor ());
3304 update_xlabel_position ();
3304 } 3305 }
3305 3306
3306 void 3307 void
3307 axes::properties::set_ylabel (const octave_value& v) 3308 axes::properties::set_ylabel (const octave_value& v)
3308 { 3309 {
3311 xset (ylabel.handle_value (), "rotationmode", "auto"); 3312 xset (ylabel.handle_value (), "rotationmode", "auto");
3312 xset (ylabel.handle_value (), "horizontalalignmentmode", "auto"); 3313 xset (ylabel.handle_value (), "horizontalalignmentmode", "auto");
3313 xset (ylabel.handle_value (), "verticalalignmentmode", "auto"); 3314 xset (ylabel.handle_value (), "verticalalignmentmode", "auto");
3314 xset (ylabel.handle_value (), "clipping", "off"); 3315 xset (ylabel.handle_value (), "clipping", "off");
3315 xset (ylabel.handle_value (), "color", get_ycolor ()); 3316 xset (ylabel.handle_value (), "color", get_ycolor ());
3317 update_ylabel_position ();
3316 } 3318 }
3317 3319
3318 void 3320 void
3319 axes::properties::set_zlabel (const octave_value& v) 3321 axes::properties::set_zlabel (const octave_value& v)
3320 { 3322 {
3323 xset (zlabel.handle_value (), "rotationmode", "auto"); 3325 xset (zlabel.handle_value (), "rotationmode", "auto");
3324 xset (zlabel.handle_value (), "horizontalalignmentmode", "auto"); 3326 xset (zlabel.handle_value (), "horizontalalignmentmode", "auto");
3325 xset (zlabel.handle_value (), "verticalalignmentmode", "auto"); 3327 xset (zlabel.handle_value (), "verticalalignmentmode", "auto");
3326 xset (zlabel.handle_value (), "clipping", "off"); 3328 xset (zlabel.handle_value (), "clipping", "off");
3327 xset (zlabel.handle_value (), "color", get_zcolor ()); 3329 xset (zlabel.handle_value (), "color", get_zcolor ());
3330 update_zlabel_position ();
3328 } 3331 }
3329 3332
3330 void 3333 void
3331 axes::properties::set_title (const octave_value& v) 3334 axes::properties::set_title (const octave_value& v)
3332 { 3335 {
3335 xset (title.handle_value (), "horizontalalignment", "center"); 3338 xset (title.handle_value (), "horizontalalignment", "center");
3336 xset (title.handle_value (), "horizontalalignmentmode", "auto"); 3339 xset (title.handle_value (), "horizontalalignmentmode", "auto");
3337 xset (title.handle_value (), "verticalalignment", "bottom"); 3340 xset (title.handle_value (), "verticalalignment", "bottom");
3338 xset (title.handle_value (), "verticalalignmentmode", "auto"); 3341 xset (title.handle_value (), "verticalalignmentmode", "auto");
3339 xset (title.handle_value (), "clipping", "off"); 3342 xset (title.handle_value (), "clipping", "off");
3343 update_title_position ();
3340 } 3344 }
3341 3345
3342 void 3346 void
3343 axes::properties::set_defaults (base_graphics_object& obj, 3347 axes::properties::set_defaults (base_graphics_object& obj,
3344 const std::string& mode) 3348 const std::string& mode)
4061 zticklen = ticksign*7; 4065 zticklen = ticksign*7;
4062 4066
4063 xtickoffset = (mode2d ? std::max (0., xticklen) : std::abs (xticklen)) + 5; 4067 xtickoffset = (mode2d ? std::max (0., xticklen) : std::abs (xticklen)) + 5;
4064 ytickoffset = (mode2d ? std::max (0., yticklen) : std::abs (yticklen)) + 5; 4068 ytickoffset = (mode2d ? std::max (0., yticklen) : std::abs (yticklen)) + 5;
4065 ztickoffset = (mode2d ? std::max (0., zticklen) : std::abs (zticklen)) + 5; 4069 ztickoffset = (mode2d ? std::max (0., zticklen) : std::abs (zticklen)) + 5;
4070
4071 update_xlabel_position ();
4072 update_ylabel_position ();
4073 update_zlabel_position ();
4074 update_title_position ();
4075 }
4076
4077 void
4078 axes::properties::update_xlabel_position (void)
4079 {
4080 graphics_xform xform = get_transform ();
4081
4082 text::properties& xlabel_props = reinterpret_cast<text::properties&>
4083 (gh_manager::get_object (get_xlabel ()).get_properties ());
4084
4085 if (xlabel_props.horizontalalignmentmode_is ("auto"))
4086 {
4087 xlabel_props.set_horizontalalignment
4088 (xstate > AXE_DEPTH_DIR
4089 ? "center" : (xyzSym ? "left" : "right"));
4090
4091 xlabel_props.set_horizontalalignmentmode ("auto");
4092 }
4093
4094 if (xlabel_props.verticalalignmentmode_is ("auto"))
4095 {
4096 xlabel_props.set_verticalalignment
4097 (xstate == AXE_VERT_DIR || x2Dtop ? "bottom" : "top");
4098
4099 xlabel_props.set_verticalalignmentmode ("auto");
4100 }
4101
4102 if (xlabel_props.positionmode_is ("auto")
4103 || xlabel_props.rotationmode_is ("auto"))
4104 {
4105 Matrix ext (1, 2, 0.0);
4106 ext = get_ticklabel_extents (get_xtick ().matrix_value (),
4107 get_xticklabel ().all_strings (),
4108 get_xlim ().matrix_value ());
4109
4110 double wmax = ext(0), hmax = ext(1), angle = 0;
4111 ColumnVector p =
4112 graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick);
4113
4114 bool tick_along_z = nearhoriz || xisinf (fy);
4115 if (tick_along_z)
4116 p(2) += (signum(zpTick-zpTickN)*fz*xtickoffset);
4117 else
4118 p(1) += (signum(ypTick-ypTickN)*fy*xtickoffset);
4119
4120 p = xform.transform (p(0), p(1), p(2), false);
4121
4122 switch (xstate)
4123 {
4124 case AXE_ANY_DIR:
4125 p(0) += (xyzSym ? wmax : -wmax);
4126 p(1) += hmax;
4127 break;
4128
4129 case AXE_VERT_DIR:
4130 p(0) -= wmax;
4131 angle = 90;
4132 break;
4133
4134 case AXE_HORZ_DIR:
4135 p(1) += (x2Dtop ? -hmax : hmax);
4136 break;
4137 }
4138
4139 if (xlabel_props.positionmode_is ("auto"))
4140 {
4141 p = xform.untransform (p(0), p(1), p(2), true);
4142 xlabel_props.set_position (p.extract_n (0, 3).transpose ());
4143 xlabel_props.set_positionmode ("auto");
4144 }
4145
4146 if (xlabel_props.rotationmode_is ("auto"))
4147 {
4148 xlabel_props.set_rotation (angle);
4149 xlabel_props.set_rotationmode ("auto");
4150 }
4151 }
4152 }
4153
4154 void
4155 axes::properties::update_ylabel_position (void)
4156 {
4157 graphics_xform xform = get_transform ();
4158
4159 text::properties& ylabel_props = reinterpret_cast<text::properties&>
4160 (gh_manager::get_object (get_ylabel ()).get_properties ());
4161
4162 if (ylabel_props.horizontalalignmentmode_is ("auto"))
4163 {
4164 ylabel_props.set_horizontalalignment
4165 (ystate > AXE_DEPTH_DIR
4166 ? "center" : (!xyzSym ? "left" : "right"));
4167
4168 ylabel_props.set_horizontalalignmentmode ("auto");
4169 }
4170
4171 if (ylabel_props.verticalalignmentmode_is ("auto"))
4172 {
4173 ylabel_props.set_verticalalignment
4174 (ystate == AXE_VERT_DIR && !y2Dright ? "bottom" : "top");
4175
4176 ylabel_props.set_verticalalignmentmode ("auto");
4177 }
4178
4179 if (ylabel_props.positionmode_is ("auto")
4180 || ylabel_props.rotationmode_is ("auto"))
4181 {
4182 Matrix ext (1, 2, 0.0);
4183 ext = get_ticklabel_extents (get_ytick ().matrix_value (),
4184 get_yticklabel ().all_strings (),
4185 get_ylim ().matrix_value ());
4186
4187 double wmax = ext(0), hmax = ext(1), angle = 0;
4188 ColumnVector p =
4189 graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick);
4190
4191 bool tick_along_z = nearhoriz || xisinf (fx);
4192 if (tick_along_z)
4193 p(2) += (signum(zpTick-zpTickN)*fz*ytickoffset);
4194 else
4195 p(0) += (signum(xpTick-xpTickN)*fx*ytickoffset);
4196
4197 p = xform.transform (p(0), p(1), p(2), false);
4198
4199 switch (ystate)
4200 {
4201 case AXE_ANY_DIR:
4202 p(0) += (!xyzSym ? wmax : -wmax);
4203 p(1) += hmax;
4204 break;
4205
4206 case AXE_VERT_DIR:
4207 p(0) += (y2Dright ? wmax : -wmax);
4208 angle = 90;
4209 break;
4210
4211 case AXE_HORZ_DIR:
4212 p(1) += hmax;
4213 break;
4214 }
4215
4216 if (ylabel_props.positionmode_is ("auto"))
4217 {
4218 p = xform.untransform (p(0), p(1), p(2), true);
4219 ylabel_props.set_position (p.extract_n (0, 3).transpose ());
4220 ylabel_props.set_positionmode ("auto");
4221 }
4222
4223 if (ylabel_props.rotationmode_is ("auto"))
4224 {
4225 ylabel_props.set_rotation (angle);
4226 ylabel_props.set_rotationmode ("auto");
4227 }
4228 }
4229 }
4230
4231 void
4232 axes::properties::update_zlabel_position (void)
4233 {
4234 graphics_xform xform = get_transform ();
4235
4236 text::properties& zlabel_props = reinterpret_cast<text::properties&>
4237 (gh_manager::get_object (get_zlabel ()).get_properties ());
4238
4239 bool camAuto = cameraupvectormode_is ("auto");
4240
4241 if (zlabel_props.horizontalalignmentmode_is ("auto"))
4242 {
4243 zlabel_props.set_horizontalalignment
4244 ((zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right");
4245
4246 zlabel_props.set_horizontalalignmentmode ("auto");
4247 }
4248
4249 if (zlabel_props.verticalalignmentmode_is ("auto"))
4250 {
4251 zlabel_props.set_verticalalignment
4252 (zstate == AXE_VERT_DIR
4253 ? "bottom" : ((zSign || camAuto) ? "bottom" : "top"));
4254
4255 zlabel_props.set_verticalalignmentmode ("auto");
4256 }
4257
4258 if (zlabel_props.positionmode_is ("auto")
4259 || zlabel_props.rotationmode_is ("auto"))
4260 {
4261 Matrix ext (1, 2, 0.0);
4262 ext = get_ticklabel_extents (get_ztick ().matrix_value (),
4263 get_zticklabel ().all_strings (),
4264 get_zlim ().matrix_value ());
4265
4266 double wmax = ext(0), hmax = ext(1), angle = 0;
4267 ColumnVector p;
4268
4269 if (xySym)
4270 {
4271 p = graphics_xform::xform_vector (xPlaneN, yPlane,
4272 (zpTickN+zpTick)/2);
4273 if (xisinf (fy))
4274 p(0) += (signum(xPlaneN-xPlane)*fx*ztickoffset);
4275 else
4276 p(1) += (signum(yPlane-yPlaneN)*fy*ztickoffset);
4277 }
4278 else
4279 {
4280 p = graphics_xform::xform_vector (xPlane, yPlaneN,
4281 (zpTickN+zpTick)/2);
4282 if (xisinf (fx))
4283 p(1) += (signum(yPlaneN-yPlane)*fy*ztickoffset);
4284 else
4285 p(0) += (signum(xPlane-xPlaneN)*fx*ztickoffset);
4286 }
4287
4288 p = xform.transform (p(0), p(1), p(2), false);
4289
4290 switch (zstate)
4291 {
4292 case AXE_ANY_DIR:
4293 if (camAuto)
4294 {
4295 p(0) -= wmax;
4296 angle = 90;
4297 }
4298
4299 // FIXME -- what's the correct offset?
4300 //
4301 // p[0] += (!xySym ? wmax : -wmax);
4302 // p[1] += (zSign ? hmax : -hmax);
4303
4304 break;
4305
4306 case AXE_VERT_DIR:
4307 p(0) -= wmax;
4308 angle = 90;
4309 break;
4310
4311 case AXE_HORZ_DIR:
4312 p(1) += hmax;
4313 break;
4314 }
4315
4316 if (zlabel_props.positionmode_is ("auto"))
4317 {
4318 p = xform.untransform (p(0), p(1), p(2), true);
4319 zlabel_props.set_position (p.extract_n (0, 3).transpose ());
4320 zlabel_props.set_positionmode ("auto");
4321 }
4322
4323 if (zlabel_props.rotationmode_is ("auto"))
4324 {
4325 zlabel_props.set_rotation (angle);
4326 zlabel_props.set_rotationmode ("auto");
4327 }
4328 }
4329 }
4330
4331 void
4332 axes::properties::update_title_position (void)
4333 {
4334 graphics_xform xform = get_transform ();
4335
4336 text::properties& title_props = reinterpret_cast<text::properties&>
4337 (gh_manager::get_object (get_title ()).get_properties ());
4338
4339 if (title_props.positionmode_is ("auto"))
4340 {
4341 // FIXME: bbox should be stored in axes::properties
4342 ColumnVector bbox(4);
4343 bbox(0) = octave_Inf;
4344 bbox(1) = octave_Inf;
4345 bbox(2) = -octave_Inf;
4346 bbox(3) = -octave_Inf;
4347 for (int i = 0; i <= 1; i++)
4348 for (int j = 0; j <= 1; j++)
4349 for (int k = 0; k <= 1; k++)
4350 {
4351 ColumnVector p = xform.transform (i ? xPlaneN : xPlane,
4352 j ? yPlaneN : yPlane,
4353 k ? zPlaneN : zPlane, false);
4354 bbox(0) = std::min (bbox(0), p(0));
4355 bbox(1) = std::min (bbox(1), p(1));
4356 bbox(2) = std::max (bbox(2), p(0));
4357 bbox(3) = std::max (bbox(3), p(1));
4358 }
4359
4360 bbox(2) = bbox(2)-bbox(0);
4361 bbox(3) = bbox(3)-bbox(1);
4362
4363 ColumnVector p = xform.untransform (bbox(0)+bbox(2)/2, (bbox(1)-10),
4364 (x_zlim(0)+x_zlim(1))/2, true);
4365
4366 title_props.set_position (p.extract_n(0, 3).transpose ());
4367 title_props.set_positionmode ("auto");
4368 }
4066 } 4369 }
4067 4370
4068 static void 4371 static void
4069 normalized_aspectratios (Matrix& aspectratios, const Matrix& scalefactors, 4372 normalized_aspectratios (Matrix& aspectratios, const Matrix& scalefactors,
4070 double xlength, double ylength, double zlength) 4373 double xlength, double ylength, double zlength)
4633 os << values(i); 4936 os << values(i);
4634 c(i) = os.str (); 4937 c(i) = os.str ();
4635 } 4938 }
4636 4939
4637 labels = c; 4940 labels = c;
4941 }
4942
4943 Matrix
4944 axes::properties::get_ticklabel_extents (const Matrix& ticks,
4945 const string_vector& ticklabels,
4946 const Matrix& limits)
4947 {
4948 #ifdef HAVE_FREETYPE
4949 //FIXME: text_renderer could be cached
4950 ft_render text_renderer;
4951 text_renderer.set_font (get ("fontname").string_value (),
4952 get ("fontweight").string_value (),
4953 get ("fontangle").string_value (),
4954 get ("fontsize").double_value ());
4955 #else
4956 double fontsize = get ("fontsize").double_value ();
4957 #endif
4958
4959 Matrix ext (1, 2, 0.0);
4960 double wmax = 0., hmax = 0.;
4961 int n = std::min (ticklabels.numel (), ticks.numel ());
4962 for (int i = 0; i < n; i++)
4963 {
4964 double val = ticks(i);
4965 if (limits(0) <= val && val <= limits(1))
4966 {
4967 #ifdef HAVE_FREETYPE
4968 ext = text_renderer.get_extent (ticklabels(i));
4969 wmax = std::max (wmax, ext(0));
4970 hmax = std::max (hmax, ext(1));
4971 #else
4972 //FIXME: find a better approximation
4973 int len = ticklabels(i).length();
4974 wmax = std::max (wmax, 0.5*fontsize*len);
4975 hmax = fontsize;
4976 #endif
4977 }
4978 }
4979
4980 ext(0) = wmax;
4981 ext(1) = hmax;
4982 return ext;
4638 } 4983 }
4639 4984
4640 void 4985 void
4641 get_children_limits (double& min_val, double& max_val, double& min_pos, 4986 get_children_limits (double& min_val, double& max_val, double& min_pos,
4642 const Matrix& kids, char limit_type) 4987 const Matrix& kids, char limit_type)