0001 function vb_dragzoom(varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 narginchk(0,3);
0168
0169
0170
0171 hFig = [];
0172 hAx = [];
0173 hAxes = [];
0174
0175
0176 mOrigFigName = [];
0177 mOrigCallbacks = [];
0178 mAxesInfo = [];
0179 mDragStartX = [];
0180 mDragStartY = [];
0181 mDragKeysX = [];
0182 mDragKeysY = [];
0183 mDragShiftStep = [];
0184 mDragSaveShiftStep = [];
0185 mDragShiftStepInc = [];
0186 mDragSave3DShiftStep = [];
0187 mDrag3DShiftStep = [];
0188 mZoomScroll = [];
0189 mZoomMinPow = [];
0190 mZoomMaxPow = [];
0191 mZoomNum = [];
0192 mZoomExtendNum = [];
0193 mZoomKeysNum = [];
0194 mZoom3DExtendNum = [];
0195 mZoom3DKeysNum = [];
0196 mZoom3DIndex = [];
0197 mDefaultZoomGrid = [];
0198 mDefaultZoomSteps = [];
0199 mZoomGrid = [];
0200 mZoomSteps = [];
0201 mZoomIndexX = [];
0202 mZoomIndexY = [];
0203 mZoom3DStartX = [];
0204 mZoom3DStartY = [];
0205 mZoom3DBindX = [];
0206 mZoom3DBindY = [];
0207 mDefaultXLim = [];
0208 mDefaultYLim = [];
0209 mDefaultAxPos = [];
0210 mRotStartAZ = [];
0211 mRotStartEL = [];
0212 mRotStartX = [];
0213 mRotStartY = [];
0214 mRot3DKeysInc = [];
0215 mPointerCross = [];
0216 mRubberBand = [];
0217 mRbEdgeColor = [];
0218 mRbFaceColor = [];
0219 mRbFaceAlpha = [];
0220 mMagnifier = [];
0221 mMgSize = [];
0222 mMgMinSize = [];
0223 mMgMaxSize = [];
0224 mMgZoom = [];
0225 mMgMinZoom = [];
0226 mMgMaxZoom = [];
0227 mMgLinesWidth = [];
0228 mMgShadow = [];
0229 mMgSizeStep = [];
0230 mMgZoomStep = [];
0231 mMgDirection = [];
0232 mLinkOpt = 'xy';
0233
0234
0235 fIsEnabled = false;
0236 fIsSelectedCurrentAxes = true;
0237 fIsDragAllowed = false;
0238 fIsZoomExtendAllowed = false;
0239 fIsZoomExtend3DAllowed = false;
0240 fIsRotate3DAllowed = false;
0241 fIsRubberBandOn = false;
0242 fIsPointerCross = false;
0243 fIsAxesGrid = false;
0244 fIsSmoothing = false;
0245 fIsEnableDragX = true;
0246 fIsEnableDragY = true;
0247 fIsEnableZoomX = true;
0248 fIsEnableZoomY = true;
0249 fIsAxes2D = false;
0250 fIsImage = false;
0251 fIsMagnifierOn = false;
0252 fIsLinkAxesOn = false;
0253 fIsEnableControl = false;
0254 fIsMouseOnLegend = false;
0255 fMode = '';
0256
0257
0258
0259 Initialize(varargin{:})
0260
0261
0262
0263
0264
0265 function Setup()
0266
0267
0268
0269 mDragKeysX = 'normal';
0270 mDragKeysY = 'normal';
0271 mDragShiftStep = 3;
0272 mDragShiftStepInc = 1;
0273 mDrag3DShiftStep = 10;
0274
0275
0276 mZoomScroll = 'normal';
0277 mZoomMinPow = 0;
0278 mZoomMaxPow = 5;
0279 mZoomNum = 51;
0280 mZoomExtendNum = 301;
0281 mZoomKeysNum = 181;
0282 mZoom3DExtendNum = 201;
0283 mZoom3DKeysNum = 181;
0284
0285
0286 mRbEdgeColor = 'k';
0287 mRbFaceColor = 'none';
0288 mRbFaceAlpha = 1;
0289
0290
0291 mMgSize = 100;
0292 mMgMinSize = 50;
0293 mMgMaxSize = 200;
0294 mMgZoom = 2;
0295 mMgMinZoom = 1;
0296 mMgMaxZoom = 100;
0297 mMgLinesWidth = 1;
0298 mMgShadow = 0.95;
0299 mMgSizeStep = 15;
0300 mMgZoomStep = 1.2;
0301
0302
0303 mRot3DKeysInc = 3;
0304
0305 end
0306
0307
0308
0309 function Initialize(varargin)
0310
0311
0312
0313 isWithStatus = ParseInputs(varargin{:});
0314
0315 if isempty(hAxes), return; end
0316
0317 hAx = hAxes(1);
0318 set(hFig, 'CurrentAxes', hAx);
0319
0320
0321 Setup();
0322
0323
0324 UserData = get(hFig, 'UserData');
0325 if isempty(UserData), UserData = struct; end
0326
0327 if (isfield(UserData, 'axesinfo') && isWithStatus)
0328 mAxesInfo = UserData.axesinfo;
0329 mOrigCallbacks = UserData.origcallbacks;
0330 mOrigFigName = UserData.origfigname;
0331 else
0332
0333 if ~isfield(UserData, 'origfigname')
0334 mOrigFigName = get(hFig, 'Name');
0335 end
0336
0337 if isfield(UserData, 'origcallbacks')
0338 mOrigCallbacks = UserData.origcallbacks;
0339 SetOriginalCallbacks();
0340 end
0341
0342
0343 SaveOriginalCallbacks();
0344
0345
0346 mAxesInfo = GetAxesInfo();
0347
0348
0349 for i = 1:numel(mAxesInfo)
0350 resetplotview(mAxesInfo(i).handle, 'InitializeCurrentView');
0351 end
0352
0353 UserData.axesinfo = mAxesInfo;
0354 UserData.origcallbacks = mOrigCallbacks;
0355 UserData.origfigname = mOrigFigName;
0356
0357 if ~isfield(UserData, 'tools')
0358 UserData.tools.pointercross = mPointerCross;
0359 UserData.tools.islinkaxeson = fIsLinkAxesOn;
0360 end
0361
0362 set(hFig, 'UserData', UserData);
0363 end
0364
0365 DeleteOldTools();
0366
0367 axi = GetCurrentAxesIndex();
0368 SetCurrentAxes(axi);
0369 SetDefaultZoomGrid();
0370 SetFigureName();
0371
0372 mDragSaveShiftStep = mDragShiftStep;
0373 mDragSave3DShiftStep = mDrag3DShiftStep;
0374
0375
0376 set(hFig, 'CreateFcn', {@CreateFigureCallback});
0377
0378 if fIsEnabled
0379 SetCallbacks();
0380 else
0381 SetOriginalCallbacks();
0382 end
0383 end
0384
0385
0386
0387 function SaveOriginalCallbacks()
0388
0389
0390 mOrigCallbacks.window_button_down_fcn = get(hFig, 'WindowButtonDownFcn');
0391 mOrigCallbacks.window_button_up_fcn = get(hFig, 'WindowButtonUpFcn');
0392 mOrigCallbacks.window_button_motion_fcn = get(hFig, 'WindowButtonMotionFcn');
0393 mOrigCallbacks.create_fcn = get(hFig, 'CreateFcn');
0394
0395 try
0396 mOrigCallbacks.window_scroll_whell_fcn = get(hFig, 'WindowScrollWheelFcn');
0397 mOrigCallbacks.window_key_press_fcn = get(hFig, 'WindowKeyPressFcn');
0398 mOrigCallbacks.window_key_release_fcn = get(hFig, 'WindowKeyReleaseFcn');
0399 catch
0400 end
0401 end
0402
0403
0404
0405 function SetOriginalCallbacks()
0406
0407
0408 set(hFig, ...
0409 'WindowButtonDownFcn', mOrigCallbacks.window_button_down_fcn, ...
0410 'WindowButtonUpFcn', mOrigCallbacks.window_button_up_fcn, ...
0411 'WindowButtonMotionFcn', mOrigCallbacks.window_button_motion_fcn, ...
0412 'CreateFcn', mOrigCallbacks.create_fcn);
0413
0414 try
0415 set(hFig, ...
0416 'WindowScrollWheelFcn', mOrigCallbacks.window_scroll_whell_fcn, ...
0417 'WindowKeyPressFcn', mOrigCallbacks.window_key_press_fcn, ...
0418 'WindowKeyReleaseFcn', mOrigCallbacks.window_key_release_fcn);
0419 catch
0420 end
0421
0422 end
0423
0424
0425
0426 function SetCallbacks()
0427
0428
0429 if fIsAxes2D
0430
0431 SetFigureCallbacks2D();
0432 else
0433
0434 SetFigureCallbacks3D();
0435 end
0436 end
0437
0438
0439
0440 function SetFigureCallbacks2D()
0441
0442
0443 set(hFig, ...
0444 'WindowButtonDownFcn', {@WindowButtonDownCallback2D}, ...
0445 'WindowButtonUpFcn', {@WindowButtonUpCallback2D}, ...
0446 'WindowButtonMotionFcn', {@WindowButtonMotionCallback2D});
0447 try
0448 set(hFig, ...
0449 'WindowScrollWheelFcn', {@WindowScrollWheelFcn2D}, ...
0450 'WindowKeyPressFcn', {@WindowKeyPressCallback2D}, ...
0451 'WindowKeyReleaseFcn', {@WindowKeyReleaseCallback2D});
0452 catch
0453 end
0454 end
0455
0456
0457
0458 function SetFigureCallbacks3D()
0459
0460
0461 set(hFig, ...
0462 'WindowButtonDownFcn', {@WindowButtonDownCallback3D}, ...
0463 'WindowButtonUpFcn', {@WindowButtonUpCallback3D}, ...
0464 'WindowButtonMotionFcn', {@WindowButtonMotionCallback3D});
0465 try
0466 set(hFig, ...
0467 'WindowScrollWheelFcn', {@WindowScrollWheelFcn3D}, ...
0468 'WindowKeyPressFcn', {@WindowKeyPressCallback3D}, ...
0469 'WindowKeyReleaseFcn', {@WindowKeyReleaseCallback3D});
0470 catch
0471 end
0472 end
0473
0474
0475
0476 function WindowButtonDownCallback2D(src, evnt)
0477
0478
0479 if fIsMouseOnLegend, return; end
0480
0481 clickType = get(src, 'SelectionType');
0482
0483 switch clickType
0484 case 'normal'
0485 DragMouseBegin();
0486 mMgDirection = 'plus';
0487 case 'open'
0488 if fIsMagnifierOn
0489 MagnifierSizeChange(mMgDirection);
0490 else
0491 ResetAxesToOrigView();
0492 end
0493 case 'alt'
0494 RubberBandBegin();
0495 mMgDirection = 'minus';
0496 case 'extend'
0497 if fIsMagnifierOn
0498 MagnifierReset();
0499 else
0500 ZoomMouseExtendBegin();
0501 end
0502 end
0503 eval(mOrigCallbacks.window_button_down_fcn);
0504 end
0505
0506
0507
0508 function WindowButtonUpCallback2D(src, evnt)
0509
0510
0511 DragMouseEnd();
0512 ZoomMouseExtendEnd();
0513 RubberBandEnd();
0514 eval(mOrigCallbacks.window_button_up_fcn);
0515 end
0516
0517
0518
0519 function WindowButtonMotionCallback2D(src, evnt)
0520
0521
0522 if ~(fIsMagnifierOn || fIsDragAllowed || fIsRubberBandOn)
0523
0524 SelectAxesUnderCursor();
0525 end
0526
0527 if fIsEnableControl
0528 DragMouse();
0529 RubberBandUpdate();
0530 MagnifierUpdate();
0531 end
0532
0533 ZoomMouseExtend();
0534 PointerCrossUpdate();
0535 eval(mOrigCallbacks.window_button_motion_fcn);
0536 end
0537
0538
0539
0540 function WindowScrollWheelFcn2D(src, evnt)
0541
0542
0543 if fIsMouseOnLegend, return; end
0544
0545
0546
0547 UpdateCurrentZoomAxes();
0548
0549 switch mZoomScroll
0550 case 'normal'
0551 directions = {'minus', 'plus'};
0552 case 'reverse'
0553 directions = {'plus', 'minus'};
0554 end
0555
0556 verScrollCount = evnt.VerticalScrollCount;
0557
0558 if (verScrollCount > 0)
0559 direction = directions{1};
0560 elseif (verScrollCount < 0)
0561 direction = directions{2};
0562 else
0563 return;
0564 end
0565 ZoomKeys(direction);
0566
0567
0568 ZoomMouse(direction);
0569 PointerCrossUpdate();
0570
0571 MagnifierZoomChange(direction);
0572 end
0573
0574
0575
0576 function WindowKeyPressCallback2D(src, evnt)
0577
0578
0579 modifier = evnt.Modifier;
0580
0581 switch evnt.Key
0582
0583
0584
0585 case {'equal', 'add'}
0586 ZoomKeys('plus');
0587 case {'hyphen', 'subtract'}
0588 ZoomKeys('minus');
0589 case 'leftarrow'
0590 DragKeys('left');
0591 case 'rightarrow'
0592 DragKeys('right');
0593 case 'uparrow'
0594 DragKeys('up');
0595 case 'downarrow'
0596 DragKeys('down');
0597 case 'c'
0598
0599 case 'g'
0600 SetAxesGridKeys();
0601 case 'x'
0602 DragEnable('y', 'off');
0603 ZoomEnable('y', 'off');
0604 case 'y'
0605 DragEnable('x', 'off');
0606 ZoomEnable('x', 'off');
0607 case 'm'
0608 if fIsEnableControl
0609 MagnifierOn();
0610 end
0611 case 'l'
0612 SetLinkAxesKeys(modifier);
0613 case 's'
0614
0615 SetSmoothKeys();
0616 end
0617 end
0618
0619
0620
0621 function WindowKeyReleaseCallback2D(src, evnt)
0622
0623
0624 switch evnt.Key
0625 case {'leftarrow', 'rightarrow', 'uparrow', 'downarrow'}
0626 mDragShiftStep = mDragSaveShiftStep;
0627 case 'x'
0628 DragEnable('y', 'on');
0629 ZoomEnable('y', 'on');
0630 case 'y'
0631 DragEnable('x', 'on');
0632 ZoomEnable('x', 'on');
0633 case 'm'
0634 MagnifierOff();
0635 end
0636 end
0637
0638
0639
0640 function WindowButtonDownCallback3D(src, evnt)
0641
0642
0643 if fIsMouseOnLegend, return; end
0644
0645 clickType = get(src, 'SelectionType');
0646
0647 switch clickType
0648 case 'normal'
0649
0650 RotateMouseBegin3D();
0651
0652
0653
0654 case 'alt'
0655 DragMouseBegin3D();
0656 case 'extend'
0657 ZoomMouseExtendBegin3D();
0658 end
0659 eval(mOrigCallbacks.window_button_down_fcn);
0660 end
0661
0662
0663
0664 function WindowButtonUpCallback3D(src, evnt)
0665
0666
0667 DragMouseEnd3D();
0668 ZoomMouseExtendEnd3D();
0669 RotateMouseEnd3D();
0670 eval(mOrigCallbacks.window_button_up_fcn);
0671 end
0672
0673
0674
0675 function WindowButtonMotionCallback3D(src, evnt)
0676
0677
0678 if ~(fIsDragAllowed || fIsZoomExtend3DAllowed || fIsRotate3DAllowed)
0679 SelectAxesUnderCursor();
0680 end
0681
0682 if fIsEnableControl
0683 DragMouse3D();
0684 RotateMouse3D();
0685 end
0686 ZoomMouseExtend3D();
0687 eval(mOrigCallbacks.window_button_motion_fcn);
0688 end
0689
0690
0691
0692 function WindowScrollWheelFcn3D(src, evnt)
0693
0694
0695 if fIsMouseOnLegend, return; end
0696
0697 UpdateCurrentZoomAxes3D();
0698
0699 switch mZoomScroll
0700 case 'normal'
0701 directions = {'minus', 'plus'};
0702 case 'reverse'
0703 directions = {'plus', 'minus'};
0704 end
0705
0706 verScrollCount = evnt.VerticalScrollCount;
0707
0708 if (verScrollCount > 0)
0709 direction = directions{1};
0710 elseif (verScrollCount < 0)
0711 direction = directions{2};
0712 else
0713 return;
0714 end
0715
0716
0717 ZoomMouse3D(direction);
0718
0719 end
0720
0721
0722
0723 function WindowKeyPressCallback3D(src, evnt)
0724
0725
0726 isModifier = ~isempty(intersect(evnt.Modifier, {'control', 'command'}));
0727
0728 switch evnt.Key
0729 case {'equal', 'add'}
0730 ZoomKeys3D('plus');
0731 case {'hyphen', 'subtract'}
0732 ZoomKeys3D('minus');
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772 end
0773 end
0774
0775
0776
0777 function WindowKeyReleaseCallback3D(src, evnt)
0778
0779
0780 switch evnt.Key
0781 case {'equal', 'add', 'hyphen', 'subtract'}
0782 SetDefaultZoomGrid3D();
0783 case {'leftarrow', 'rightarrow', 'uparrow', 'downarrow'}
0784 mDrag3DShiftStep = mDragSave3DShiftStep;
0785 end
0786 end
0787
0788
0789
0790 function CreateFigureCallback(src, evnt)
0791
0792
0793 hFig = src;
0794
0795 UserData = get(hFig, 'UserData');
0796 mAxesInfo = UserData.axesinfo;
0797 mOrigCallbacks = UserData.origcallbacks;
0798 mOrigFigName = UserData.origfigname;
0799 hAxes = arrayfun(@(x) x.handle, mAxesInfo);
0800
0801 axi = GetCurrentAxesIndex();
0802 SetCurrentAxes(axi)
0803 DeleteOldTools();
0804 end
0805
0806
0807
0808 function SetFigureName()
0809
0810
0811 enableStatus = 'off';
0812 if fIsEnabled
0813 enableStatus = 'on';
0814 end
0815
0816 syncMode = 'Normal';
0817 if fIsLinkAxesOn
0818 syncMode = sprintf('Synchronized %s', upper(mLinkOpt));
0819 end
0820
0821 sep = '';
0822 if ~isempty(mOrigFigName)
0823 sep = ':';
0824 end
0825
0826
0827
0828
0829 end
0830
0831
0832
0833 function DragMouseBegin()
0834
0835
0836 if (~fIsDragAllowed && ~fIsMagnifierOn)
0837 [cx, cy] = GetCursorCoordOnWindow();
0838
0839 mDragStartX = cx;
0840 mDragStartY = cy;
0841
0842 fIsDragAllowed = true;
0843 end
0844 end
0845
0846
0847
0848 function DragMouseEnd()
0849
0850
0851 if fIsDragAllowed
0852 fIsDragAllowed = false;
0853 end
0854 end
0855
0856
0857
0858 function DragMouse()
0859
0860
0861 if fIsDragAllowed
0862 [cx, cy] = GetCursorCoordOnWindow();
0863
0864 pdx = mDragStartX - cx;
0865 pdy = mDragStartY - cy;
0866
0867 mDragStartX = cx;
0868 mDragStartY = cy;
0869
0870 DragAxes(pdx, pdy);
0871 end
0872 end
0873
0874
0875
0876 function DragKeys(direction)
0877
0878
0879 dx = mDragShiftStep;
0880 dy = mDragShiftStep;
0881
0882
0883 mDragShiftStep = mDragShiftStep + mDragShiftStepInc;
0884
0885 directionsX = {'right', 'left'};
0886 directionsY = {'down', 'up'};
0887
0888 switch mDragKeysX
0889 case 'normal'
0890 case 'reverse'
0891 directionsX = fliplr(directionsX);
0892 end
0893 switch mDragKeysY
0894 case 'normal'
0895 case 'reverse'
0896 directionsY = fliplr(directionsY);
0897 end
0898
0899 switch direction
0900 case directionsX{1}
0901 DragAxes(-dx, 0);
0902 case directionsX{2}
0903 DragAxes(dx, 0);
0904 case directionsY{1}
0905 DragAxes(0, dy);
0906 case directionsY{2}
0907 DragAxes(0, -dy);
0908 end
0909
0910 PointerCrossUpdate();
0911 end
0912
0913
0914
0915 function DragAxes(pdx, pdy)
0916
0917
0918 [xLim, yLim] = GetAxesLimits();
0919
0920 pos = GetObjPos(hAx, 'Pixels');
0921 pbar = get(hAx, 'PlotBoxAspectRatio');
0922
0923
0924
0925
0926
0927
0928 imAspectRatioX = pbar(2) / pbar(1);
0929 if (imAspectRatioX ~= 1)
0930 posAspectRatioX = pos(3) / pos(4);
0931 arFactorX = imAspectRatioX * posAspectRatioX;
0932 if (arFactorX < 1)
0933 arFactorX = 1;
0934 end
0935 else
0936 arFactorX = 1;
0937 end
0938
0939 imAspectRatioY = pbar(1) / pbar(2);
0940 if (imAspectRatioY ~= 1)
0941 posAspectRatioY = pos(4) / pos(3);
0942 arFactorY = imAspectRatioY * posAspectRatioY;
0943 if (arFactorY < 1)
0944 arFactorY = 1;
0945 end
0946 else
0947 arFactorY = 1;
0948 end
0949
0950 if fIsEnableDragX
0951
0952 if strcmp(get(hAx, 'xscale'), 'log')
0953 xLim = log10(xLim);
0954 xLim = FixInfLogLimits('x', xLim);
0955 isXLog = true;
0956 else
0957 isXLog = false;
0958 end
0959
0960 dx = pdx * range(xLim) / (pos(3) / arFactorX);
0961 xLim = xLim + dx;
0962
0963
0964 if isXLog
0965 xLim = 10.^(xLim);
0966 end
0967 end
0968 if fIsEnableDragY
0969 if strcmp(get(hAx, 'yscale'), 'log')
0970 yLim = log10(yLim);
0971 yLim = FixInfLogLimits('y', yLim);
0972 isYLog = true;
0973 else
0974 isYLog = false;
0975 end
0976
0977 dy = pdy * range(yLim) / (pos(4) / arFactorY);
0978
0979 if fIsImage
0980 yLim = yLim - dy;
0981 else
0982 yLim = yLim + dy;
0983 end
0984
0985 if isYLog
0986 yLim = 10.^(yLim);
0987 end
0988 end
0989
0990 SetAxesLimits(xLim, yLim);
0991 end
0992
0993
0994
0995 function DragMouseBegin3D()
0996
0997
0998 if ~fIsDragAllowed
0999 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1000
1001 mDragStartX = wcx;
1002 mDragStartY = wcy;
1003
1004 fIsDragAllowed = true;
1005 end
1006 end
1007
1008
1009
1010 function DragMouseEnd3D()
1011
1012
1013 if fIsDragAllowed
1014 fIsDragAllowed = false;
1015 end
1016 end
1017
1018
1019
1020 function DragMouse3D()
1021
1022
1023 if fIsDragAllowed
1024 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1025
1026 dx = mDragStartX - wcx;
1027 dy = mDragStartY - wcy;
1028
1029 DragAxes3D(dx, dy);
1030
1031 mDragStartX = wcx;
1032 mDragStartY = wcy;
1033 end
1034 end
1035
1036
1037
1038 function DragKeys3D(direction)
1039
1040
1041 dx = mDrag3DShiftStep;
1042 dy = mDrag3DShiftStep;
1043
1044 mDrag3DShiftStep = mDrag3DShiftStep + mDragShiftStepInc;
1045
1046 directionsX = {'right', 'left'};
1047 directionsY = {'down', 'up'};
1048
1049 switch mDragKeysX
1050 case 'normal'
1051 case 'reverse'
1052 directionsX = fliplr(directionsX);
1053 end
1054 switch mDragKeysY
1055 case 'normal'
1056 case 'reverse'
1057 directionsY = fliplr(directionsY);
1058 end
1059
1060 switch direction
1061 case directionsX{1}
1062 DragAxes3D(-dx, 0);
1063 case directionsX{2}
1064 DragAxes3D(dx, 0);
1065 case directionsY{1}
1066 DragAxes3D(0, dy);
1067 case directionsY{2}
1068 DragAxes3D(0, -dy);
1069 end
1070 end
1071
1072
1073
1074 function DragAxes3D(dx, dy)
1075
1076
1077 axPos = GetObjPos(hAx, 'pixels');
1078
1079 axPos(1) = axPos(1) - dx;
1080 axPos(2) = axPos(2) - dy;
1081
1082 SetObjPos(hAx, axPos, 'pixels');
1083 end
1084
1085
1086
1087 function DragEnable(ax, action)
1088
1089
1090 switch lower(action)
1091 case 'on'
1092 tf = true;
1093 case 'off'
1094 tf = false;
1095 end
1096
1097 switch lower(ax)
1098 case 'x'
1099 fIsEnableDragX = tf;
1100 case 'y'
1101 fIsEnableDragY = tf;
1102 end
1103 end
1104
1105
1106
1107 function ZoomEnable(ax, action)
1108
1109
1110 switch lower(action)
1111 case 'on'
1112 tf = true;
1113 case 'off'
1114 tf = false;
1115 end
1116
1117 switch lower(ax)
1118 case 'x'
1119 fIsEnableZoomX = tf;
1120 case 'y'
1121 fIsEnableZoomY = tf;
1122 end
1123 end
1124
1125
1126
1127 function ZoomMouse(direction)
1128
1129
1130 if (IsZoomMouseAllowed && ~fIsMagnifierOn)
1131 [acx, acy] = GetCursorCoordOnAxes();
1132 ZoomAxes(direction, acx, acy)
1133 end
1134 end
1135
1136
1137
1138 function ZoomMouseExtendBegin()
1139
1140
1141 if ~fIsZoomExtendAllowed
1142 UpdateCurrentZoomAxes();
1143
1144
1145 [mZoomGrid, mZoomSteps] = ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomExtendNum);
1146 UpdateCurrentZoomAxes();
1147
1148 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1149 [acx, acy] = GetCursorCoordOnAxes();
1150
1151 mZoom3DStartX = wcx;
1152 mZoom3DStartY = wcy;
1153
1154 mZoom3DBindX = acx;
1155 mZoom3DBindY = acy;
1156
1157 fIsZoomExtendAllowed = true;
1158 end
1159 end
1160
1161
1162
1163 function ZoomMouseExtendEnd()
1164
1165
1166 if fIsZoomExtendAllowed
1167
1168 SetDefaultZoomGrid();
1169 fIsZoomExtendAllowed = false;
1170 end
1171 end
1172
1173
1174
1175 function ZoomMouseExtend()
1176
1177
1178 if fIsZoomExtendAllowed
1179 directions = {'minus', 'plus'};
1180
1181 switch mZoomScroll
1182 case 'normal'
1183 case 'reverse'
1184 directions = fliplr(directions);
1185 end
1186
1187
1188
1189 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1190
1191 xy(1) = wcx - mZoom3DStartX;
1192 xy(2) = wcy - mZoom3DStartY;
1193 q = max(-0.9, min(0.9, sum(xy)/70)) + 1;
1194
1195 if (q < 1)
1196 direction = directions{1};
1197 elseif (q > 1)
1198 direction = directions{2};
1199 else
1200 return;
1201 end
1202
1203 ZoomAxes(direction, mZoom3DBindX, mZoom3DBindY)
1204
1205 mZoom3DStartX = wcx;
1206 mZoom3DStartY = wcy;
1207 end
1208 end
1209
1210
1211
1212 function ZoomKeys(direction)
1213
1214
1215 UpdateCurrentZoomAxes();
1216
1217 [mZoomGrid, mZoomSteps] = ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomKeysNum);
1218 UpdateCurrentZoomAxes();
1219
1220 [acx, acy] = GetCursorCoordOnAxes();
1221
1222 ZoomAxes(direction, acx, acy)
1223 PointerCrossUpdate();
1224 SetDefaultZoomGrid();
1225 end
1226
1227
1228
1229 function ZoomAxes(direction, cx, cy)
1230
1231
1232 [xLim, yLim] = GetAxesLimits();
1233
1234 if fIsImage
1235 mZoomIndexX = ChangeZoomIndex(direction, mZoomIndexX);
1236 mZoomIndexY = mZoomIndexX;
1237 zoomPct = GetZoomPercent(mZoomIndexX);
1238
1239 xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPct);
1240 yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPct);
1241 else
1242 if fIsEnableZoomX
1243 mZoomIndexX = ChangeZoomIndex(direction, mZoomIndexX);
1244 zoomPct = GetZoomPercent(mZoomIndexX);
1245
1246 xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPct);
1247 end
1248 if fIsEnableZoomY
1249 mZoomIndexY = ChangeZoomIndex(direction, mZoomIndexY);
1250 zoomPct = GetZoomPercent(mZoomIndexY);
1251
1252 yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPct);
1253 end
1254 end
1255
1256 SetAxesLimits(xLim, yLim);
1257 end
1258
1259
1260
1261 function zoomPct = GetZoomPercent(zoomIndex, zoomGrid)
1262
1263
1264 if (nargin < 2)
1265 zoomGrid = mZoomGrid;
1266 end
1267
1268 zoomPct = zoomGrid(zoomIndex);
1269 end
1270
1271
1272
1273 function zoomIndex = ChangeZoomIndex(direction, zoomIndex, zoomSteps)
1274
1275
1276 if (nargin < 3)
1277 zoomSteps = mZoomSteps;
1278 end
1279
1280 switch direction
1281 case 'plus'
1282 if (zoomIndex < zoomSteps)
1283 zoomIndex = zoomIndex + 1;
1284 end
1285 case 'minus'
1286 if (zoomIndex > 1)
1287 zoomIndex = zoomIndex - 1;
1288 end
1289 end
1290 end
1291
1292
1293
1294 function axLim = RecalcZoomAxesLimits(ax, axLim, axLimDflt, zcCrd, zoomPct)
1295
1296
1297 if strcmp(get(hAx, [ax, 'scale']), 'log')
1298 axLim = log10(axLim);
1299 axLim = FixInfLogLimits(ax, axLim);
1300 axLimDflt = log10(axLimDflt);
1301 zcCrd = log10(zcCrd);
1302 isLog = true;
1303 else
1304 isLog = false;
1305 end
1306
1307 if (zcCrd < axLim(1)), zcCrd = axLim(1); end
1308 if (zcCrd > axLim(2)), zcCrd = axLim(2); end
1309
1310 rf = range(axLim);
1311 ra = range([axLim(1), zcCrd]);
1312 rb = range([zcCrd, axLim(2)]);
1313
1314 cfa = ra / rf;
1315 cfb = rb / rf;
1316
1317 newRange = range(axLimDflt) * 100 / zoomPct;
1318 dRange = newRange - rf;
1319
1320 axLim(1) = axLim(1) - dRange * cfa;
1321 axLim(2) = axLim(2) + dRange * cfb;
1322
1323 if isLog
1324 axLim = 10.^axLim;
1325 end
1326 end
1327
1328
1329
1330 function UpdateCurrentZoomAxes()
1331
1332
1333 [xLim, yLim] = GetAxesLimits();
1334 [curentZoomX, curentZoomY] = GetCurrentZoomAxesPercent(xLim, yLim);
1335
1336 if (curentZoomX ~= GetZoomPercent(mZoomIndexX))
1337 [nu, mZoomIndexX] = min(abs(mZoomGrid - curentZoomX));
1338 end
1339 if (curentZoomY ~= GetZoomPercent(mZoomIndexY))
1340 [nu, mZoomIndexY] = min(abs(mZoomGrid - curentZoomY));
1341 end
1342 end
1343
1344
1345
1346 function [curentZoomX, curentZoomY] = GetCurrentZoomAxesPercent(xLim, yLim)
1347
1348
1349 if strcmp(get(hAx, 'xscale'), 'log')
1350 xLim = log10(xLim);
1351 defaultXLim = log10(mDefaultXLim);
1352 else
1353 defaultXLim = mDefaultXLim;
1354 end
1355 if strcmp(get(hAx, 'yscale'), 'log')
1356 yLim = log10(yLim);
1357 defaultYLim = log10(mDefaultYLim);
1358 else
1359 defaultYLim = mDefaultYLim;
1360 end
1361
1362 curentZoomX = range(defaultXLim) * 100 / range(xLim);
1363 curentZoomY = range(defaultYLim) * 100 / range(yLim);
1364 end
1365
1366
1367
1368 function ZoomMouse3D(direction)
1369
1370
1371 if IsZoomMouseAllowed
1372 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1373 ZoomAxes3D(direction, wcx, wcy)
1374 end
1375 end
1376
1377
1378
1379 function ZoomMouseExtendBegin3D()
1380
1381
1382 if ~fIsZoomExtend3DAllowed
1383 UpdateCurrentZoomAxes3D();
1384 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1385
1386
1387 SetNewZoomGrid3D(mZoomMinPow, mZoomMaxPow, mZoom3DExtendNum);
1388
1389 mZoom3DStartX = wcx;
1390 mZoom3DStartY = wcy;
1391
1392 mZoom3DBindX = wcx;
1393 mZoom3DBindY = wcy;
1394
1395 fIsZoomExtend3DAllowed = true;
1396 end
1397 end
1398
1399
1400
1401 function ZoomMouseExtendEnd3D()
1402
1403
1404 if fIsZoomExtend3DAllowed
1405 SetDefaultZoomGrid3D();
1406
1407 fIsZoomExtend3DAllowed = false;
1408 end
1409 end
1410
1411
1412
1413 function ZoomMouseExtend3D()
1414
1415
1416 if fIsZoomExtend3DAllowed
1417 directions = {'minus', 'plus'};
1418
1419 switch mZoomScroll
1420 case 'normal'
1421 case 'reverse'
1422 directions = fliplr(directions);
1423 end
1424
1425
1426
1427 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1428
1429 xy(1) = wcx - mZoom3DStartX;
1430 xy(2) = wcy - mZoom3DStartY;
1431 q = max(-0.9, min(0.9, sum(xy)/70)) + 1;
1432
1433 if (q < 1)
1434 direction = directions{1};
1435 elseif (q > 1)
1436 direction = directions{2};
1437 else
1438 return;
1439 end
1440
1441 ZoomAxes3D(direction, mZoom3DBindX, mZoom3DBindY)
1442
1443 mZoom3DStartX = wcx;
1444 mZoom3DStartY = wcy;
1445 end
1446 end
1447
1448
1449
1450 function ZoomAxes3D(direction, cx, cy)
1451
1452
1453 mZoom3DIndex = ChangeZoomIndex(direction, mZoom3DIndex, mZoomSteps);
1454 zoomPct = GetZoomPercent(mZoom3DIndex, mZoomGrid);
1455
1456 axPos = GetObjPos(hAx, 'pixels');
1457
1458 [axPos(1), axPos(3)] = RecalcZoomAxesPos3D(axPos(1), axPos(3), ...
1459 mDefaultAxPos(3), cx, zoomPct);
1460
1461 [axPos(2), axPos(4)] = RecalcZoomAxesPos3D(axPos(2), axPos(4), ...
1462 mDefaultAxPos(4), cy, zoomPct);
1463
1464 SetObjPos(hAx, axPos, 'pixels');
1465 end
1466
1467
1468
1469 function [npc, nsz] = RecalcZoomAxesPos3D(pc, sz, dfltSz, zcCrd, zoomPct)
1470
1471
1472 dd = dfltSz * zoomPct / 100 - sz;
1473 rng = range([pc zcCrd]);
1474 cf = rng / sz;
1475 nsz = sz + dd;
1476 npc = pc - dd * cf;
1477 end
1478
1479
1480
1481 function UpdateCurrentZoomAxes3D()
1482
1483
1484 curentZoom = GetCurrentZoomAxesPercent3D();
1485 [nu, mZoom3DIndex] = min(abs(mZoomGrid - curentZoom));
1486 end
1487
1488
1489
1490 function currentZoom = GetCurrentZoomAxesPercent3D()
1491
1492
1493 axPos = GetObjPos(hAx, 'pixels');
1494 currentZoom = axPos(3) / mDefaultAxPos(3) * 100;
1495 end
1496
1497
1498
1499 function ZoomKeys3D(direction)
1500
1501
1502 UpdateCurrentZoomAxes3D();
1503 SetNewZoomGrid3D(mZoomMinPow, mZoomMaxPow, mZoom3DKeysNum);
1504
1505 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1506 ZoomAxes3D(direction, wcx, wcy)
1507 end
1508
1509
1510
1511 function SetNewZoomGrid3D(minPow, maxPow, num)
1512
1513
1514 [mZoomGrid, mZoomSteps] = ZoomLogGrid(minPow, maxPow, num);
1515 UpdateCurrentZoomAxes3D();
1516 end
1517
1518
1519
1520 function SetDefaultZoomGrid()
1521
1522
1523 [mDefaultZoomGrid, mDefaultZoomSteps] = ...
1524 ZoomLogGrid(mZoomMinPow, mZoomMaxPow, mZoomNum);
1525
1526 mZoomGrid = mDefaultZoomGrid;
1527 mZoomSteps = mDefaultZoomSteps;
1528
1529 mZoomIndexX = find(mZoomGrid == 100);
1530 mZoomIndexY = mZoomIndexX;
1531 mZoom3DIndex = mZoomIndexX;
1532 end
1533
1534
1535
1536 function SetDefaultZoomGrid3D()
1537
1538
1539 mZoomGrid = mDefaultZoomGrid;
1540 mZoomSteps = mDefaultZoomSteps;
1541 UpdateCurrentZoomAxes3D();
1542 end
1543
1544
1545
1546 function VisibleAxesKeys3D()
1547
1548
1549 axi = GetCurrentAxesIndex();
1550
1551 if mAxesInfo(axi).isvisible
1552 set(hAx, 'Visible', 'off');
1553 mAxesInfo(axi).isvisible = false;
1554 else
1555 set(hAx, 'Visible', 'on');
1556 mAxesInfo(axi).isvisible = true;
1557 end
1558 end
1559
1560
1561
1562 function SwitchAspectRatioKeys3D()
1563
1564
1565 axi = GetCurrentAxesIndex();
1566
1567 if mAxesInfo(axi).isvis3d
1568 axis(hAx, 'normal');
1569 mAxesInfo(axi).isvis3d = false;
1570 else
1571 axis(hAx, 'vis3d');
1572 mAxesInfo(axi).isvis3d = true;
1573 end
1574 end
1575
1576
1577
1578 function RotateMouseBegin3D()
1579
1580
1581 if ~fIsRotate3DAllowed
1582 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1583
1584 [az, el] = view(hAx);
1585
1586 mRotStartAZ = az;
1587 mRotStartEL = el;
1588 mRotStartX = wcx;
1589 mRotStartY = wcy;
1590
1591 fIsRotate3DAllowed = true;
1592 end
1593 end
1594
1595
1596
1597 function RotateMouseEnd3D()
1598
1599
1600 if fIsRotate3DAllowed
1601 fIsRotate3DAllowed = false;
1602 end
1603 end
1604
1605
1606
1607 function RotateMouse3D()
1608
1609
1610 if fIsRotate3DAllowed
1611 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
1612
1613 dAZ = mRotStartX - wcx;
1614 dEL = mRotStartY - wcy;
1615
1616 az = mRotStartAZ + dAZ;
1617 el = mRotStartEL + dEL;
1618
1619 SetView3D(az, el);
1620 end
1621 end
1622
1623
1624
1625 function RotateKeys3D(mode)
1626
1627
1628 [az, el] = view(hAx);
1629
1630 switch lower(mode)
1631 case 'xy'
1632 az = 0;
1633 el = 90;
1634 case 'xz'
1635 az = 0;
1636 el = 0;
1637 case 'yz'
1638 az = 90;
1639 el = 0;
1640 case 'az+'
1641 az = az + mRot3DKeysInc;
1642 case 'az-'
1643 az = az - mRot3DKeysInc;
1644 case 'el+'
1645 el = el + mRot3DKeysInc;
1646 case 'el-'
1647 el = el - mRot3DKeysInc;
1648 end
1649
1650 SetView3D(az, el)
1651 end
1652
1653
1654
1655 function SetView3D(az, el)
1656
1657
1658 if (el > 90), el = 90; end
1659 if (el < -90), el = -90; end
1660
1661 view(hAx, [az, el]);
1662 end
1663
1664
1665
1666 function PointerCrossOn()
1667
1668
1669 if ~fIsPointerCross
1670
1671 [xlim, ylim] = GetAxesLimits();
1672 x = (xlim(2)-xlim(1))/2;
1673 y = (ylim(2)-ylim(1))/2;
1674 state = get(hAx, 'NextPlot');
1675 hold on;
1676 hcross = [ line('Parent', hAx, 'Xdata', [x, x], 'Ydata', [y, y])
1677 line('Parent', hAx, 'Xdata', [x, x], 'Ydata', [y, y])];
1678 set(hcross, 'HitTest', 'off');
1679 set(hAx, 'NextPlot', state);
1680
1681 h = [
1682 text('Parent', hAx)
1683 text('Parent', hAx)
1684 text('Parent', hAx)
1685 text('Parent', hAx)
1686 ];
1687
1688
1689 mPointerCross = struct(...
1690 'htext', h, ...
1691 'left', 1, ...
1692 'right', 2, ...
1693 'bottom', 3, ...
1694 'top', 4, ...
1695 'hcross', hcross, ...
1696 'horizontal',1, ...
1697 'vertical', 2);
1698
1699 PointerCrossSetup();
1700 fIsPointerCross = true;
1701 PointerCrossUpdate();
1702 end
1703 end
1704
1705
1706
1707 function PointerCrossOff()
1708
1709
1710 if fIsPointerCross
1711 delete(mPointerCross.htext);
1712 delete(mPointerCross.hcross);
1713 SetPointer('arrow');
1714 fIsPointerCross = false;
1715 mPointerCross = [];
1716 end
1717 end
1718
1719
1720
1721 function PointerCrossSetup()
1722
1723
1724 left = mPointerCross.left;
1725 right = mPointerCross.right;
1726 bottom = mPointerCross.bottom;
1727 top = mPointerCross.top;
1728
1729 vabt = {'top', 'bottom'};
1730 if fIsImage
1731 vabt = fliplr(vabt);
1732 end
1733
1734 set(mPointerCross.htext(left), 'VerticalAlignment', 'bottom');
1735 set(mPointerCross.htext(right), 'VerticalAlignment', 'bottom');
1736 set(mPointerCross.htext(bottom), 'VerticalAlignment', vabt{1});
1737 set(mPointerCross.htext(top), 'VerticalAlignment', vabt{2});
1738
1739 bgColor = [251 248 230]/255;
1740 set(mPointerCross.htext(left), 'BackgroundColor', bgColor);
1741 set(mPointerCross.htext(right), 'BackgroundColor', bgColor);
1742 set(mPointerCross.htext(bottom), 'BackgroundColor', bgColor);
1743 set(mPointerCross.htext(top), 'BackgroundColor', bgColor);
1744
1745 edColor = [180 180 180]/255;
1746 set(mPointerCross.htext(left), 'EdgeColor', edColor);
1747 set(mPointerCross.htext(right), 'EdgeColor', edColor);
1748 set(mPointerCross.htext(bottom), 'EdgeColor', edColor);
1749 set(mPointerCross.htext(top), 'EdgeColor', edColor);
1750 end
1751
1752
1753
1754 function PointerCrossUpdate()
1755
1756
1757 if fIsPointerCross
1758 [xlim, ylim] = GetAxesLimits();
1759 [acx, acy] = GetCursorCoordOnAxes();
1760
1761 if acx <= xlim(1), acx = xlim(1); end
1762 if acx >= xlim(2), acx = xlim(2); end
1763 if acy <= ylim(1), acy = ylim(1); end
1764 if acy >= ylim(2), acy = ylim(2); end
1765
1766 left = mPointerCross.left;
1767 right = mPointerCross.right;
1768 bottom = mPointerCross.bottom;
1769 top = mPointerCross.top;
1770 vertical = mPointerCross.vertical;
1771 horizontal = mPointerCross.horizontal;
1772
1773 if fIsImage
1774 xValStr = sprintf(' %d ', round(acx));
1775 yValStr = sprintf(' %d ', round(acy));
1776 else
1777 xtick = get(hAx, 'XTick');
1778 ytick = get(hAx, 'YTick');
1779
1780
1781 prth = 5;
1782
1783 [lenTick, maxi] = max(arrayfun(@(x) length(num2str(x)), xtick));
1784 atick = abs(xtick(maxi));
1785 flt = mod(atick, 1);
1786
1787 if (flt == 0)
1788 countDigX = lenTick + 1;
1789 if countDigX > prth
1790 countDigX = prth;
1791 end
1792 else
1793 countDigX = length(num2str(atick));
1794 if (fix(acx) == 0)
1795 countDigX = countDigX - 1;
1796 end
1797 end
1798
1799 [lenTick, maxi] = max(arrayfun(@(x) length(num2str(x)), ytick));
1800 atick = abs(ytick(maxi));
1801 flt = mod(atick, 1);
1802
1803 if (flt == 0)
1804 countDigY = lenTick + 1;
1805 if countDigY > prth
1806 countDigY = prth;
1807 end
1808 else
1809 countDigY = length(num2str(atick));
1810 if (fix(acy) == 0)
1811 countDigY = countDigY - 1;
1812 end
1813 end
1814
1815 xValStr = sprintf(' %.*g ', countDigX, acx);
1816 yValStr = sprintf(' %.*g ', countDigY, acy);
1817 end
1818
1819 set(mPointerCross.htext(left), 'String', yValStr);
1820 set(mPointerCross.htext(right), 'String', yValStr);
1821 set(mPointerCross.htext(bottom), 'String', xValStr);
1822 set(mPointerCross.htext(top), 'String', xValStr);
1823
1824 extent = get(mPointerCross.htext(left), 'Extent');
1825 xx = extent(3);
1826
1827 if strcmp(get(hAx, 'xscale'), 'log')
1828 leftx = xlim(1);
1829 else
1830 leftx = xlim(1) - xx;
1831 end
1832
1833 set(mPointerCross.htext(left), 'Position', [leftx, acy]);
1834 set(mPointerCross.htext(right), 'Position', [xlim(2) acy]);
1835 set(mPointerCross.htext(bottom), 'Position', [acx, ylim(1)]);
1836 set(mPointerCross.htext(top), 'Position', [acx, ylim(2)]);
1837 set(mPointerCross.hcross(horizontal), 'Xdata', xlim, 'Ydata', [acy, acy]);
1838 set(mPointerCross.hcross(vertical), 'Xdata', [acx, acx], 'Ydata', ylim);
1839 end
1840 end
1841
1842
1843
1844 function RubberBandBegin()
1845
1846
1847 if (~fIsRubberBandOn && ~fIsMagnifierOn)
1848 [acx, acy] = GetCursorCoordOnAxes();
1849
1850
1851 mRubberBand = struct(...
1852 'obj', [patch('Parent', hAx), patch('Parent', hAx)], ...
1853 'x1', acx, ...
1854 'y1', acy, ...
1855 'x2', acx, ...
1856 'y2', acy);
1857
1858 hAxes2d = GetHandlesAxes2D();
1859 if ~isempty(hAxes2d)
1860 set(hAxes2d, ...
1861 'XLimMode', 'manual', ...
1862 'YLimMode', 'manual');
1863 end
1864
1865 RubberBandSetPos();
1866 RubberBandSetup();
1867 fIsRubberBandOn = true;
1868 end
1869 end
1870
1871
1872
1873 function RubberBandEnd()
1874
1875
1876 if fIsRubberBandOn
1877 fIsRubberBandOn = false;
1878
1879 delete(mRubberBand.obj);
1880 RubberBandZoomAxes();
1881 PointerCrossUpdate();
1882 mRubberBand = [];
1883 end
1884 end
1885
1886
1887
1888 function RubberBandUpdate()
1889
1890
1891 if fIsRubberBandOn
1892 [acx, acy] = GetCursorCoordOnAxes();
1893
1894 mRubberBand.x2 = acx;
1895 mRubberBand.y2 = acy;
1896 RubberBandSetPos();
1897 end
1898 end
1899
1900
1901
1902 function RubberBandSetPos()
1903
1904
1905 x1 = mRubberBand.x1;
1906 y1 = mRubberBand.y1;
1907 x2 = mRubberBand.x2;
1908 y2 = mRubberBand.y2;
1909
1910 set(mRubberBand.obj, ...
1911 'XData', [x1 x2 x2 x1], ...
1912 'YData', [y1 y1 y2 y2]);
1913 end
1914
1915
1916
1917 function RubberBandSetup()
1918
1919
1920 set(mRubberBand.obj(1), ...
1921 'EdgeColor', 'w', ...
1922 'FaceColor', 'none', ...
1923 'LineWidth', 1.5, ...
1924 'LineStyle', '-');
1925
1926 set(mRubberBand.obj(2), ...
1927 'EdgeColor', mRbEdgeColor, ...
1928 'FaceColor', mRbFaceColor, ...
1929 'FaceAlpha', mRbFaceAlpha, ...
1930 'LineWidth', 0.5, ...
1931 'LineStyle', '-');
1932 end
1933
1934
1935
1936 function RubberBandZoomAxes()
1937
1938
1939 xLim = sort([mRubberBand.x1, mRubberBand.x2]);
1940 yLim = sort([mRubberBand.y1, mRubberBand.y2]);
1941
1942 if (range(xLim) == 0 || range(yLim) == 0)
1943 return;
1944 end
1945
1946 [zoomPctX, zoomPctY] = GetCurrentZoomAxesPercent(xLim, yLim);
1947
1948 if fIsImage
1949 zoomPctX = min(zoomPctX, zoomPctY);
1950 zoomPctY = zoomPctX;
1951 end
1952
1953 cx = mean(xLim);
1954 cy = mean(yLim);
1955
1956 xLim = RecalcZoomAxesLimits('x', xLim, mDefaultXLim, cx, zoomPctX);
1957 yLim = RecalcZoomAxesLimits('y', yLim, mDefaultYLim, cy, zoomPctY);
1958
1959 SetAxesLimits(xLim, yLim);
1960 end
1961
1962
1963
1964 function MagnifierOn()
1965
1966
1967 if ~fIsMagnifierOn
1968 if fIsPointerCross
1969 isPointerCross = true;
1970 PointerCrossOff();
1971 else
1972 isPointerCross = false;
1973 end
1974
1975 mMgDirection = 'plus';
1976
1977
1978 mMagnifier = struct(...
1979 'obj', copyobj(hAx, hFig), ...
1980 'frame_obj', [], ...
1981 'size', mMgSize, ...
1982 'zoom', mMgZoom);
1983
1984 fIsMagnifierOn = true;
1985 MagnifierSetup();
1986 MagnifierUpdate();
1987
1988 if isPointerCross
1989 PointerCrossOn();
1990 end
1991 end
1992 end
1993
1994
1995
1996 function MagnifierOff()
1997
1998
1999 if fIsMagnifierOn
2000 fIsMagnifierOn = false;
2001 set(hAx, 'Color', get(mMagnifier.obj, 'Color'));
2002
2003 delete(mMagnifier.obj);
2004 mMagnifier = [];
2005 end
2006 end
2007
2008
2009
2010 function MagnifierUpdate()
2011
2012
2013 if fIsMagnifierOn
2014
2015
2016
2017 [acx, acy] = GetCursorCoordOnAxes();
2018 [wcx, wcy] = GetCursorCoordOnWindow('pixels');
2019
2020 [xLim, yLim] = GetAxesLimits();
2021
2022 if strcmp(get(hAx, 'xscale'), 'log')
2023 xLim = log10(xLim);
2024 xLim = FixInfLogLimits('x', xLim);
2025 acx = log10(acx);
2026 isXLog = true;
2027 else
2028 isXLog = false;
2029 end
2030 if strcmp(get(hAx, 'yscale'), 'log')
2031 yLim = log10(yLim);
2032 yLim = FixInfLogLimits('y', yLim);
2033 acy = log10(acy);
2034 isYLog = true;
2035 else
2036 isYLog = false;
2037 end
2038
2039 figPos = GetObjPos(hFig, 'pixels');
2040 axPos = GetObjPos(hAx, 'normalized');
2041
2042
2043 pbar = get(hAx, 'PlotBoxAspectRatio');
2044 af = pbar(1) / pbar(2);
2045 if (af == 1 && (pbar(1) == 1 && pbar(2) == 1))
2046 af = figPos(3) / figPos(4);
2047 end
2048
2049 mgSizePix = round(mMagnifier.size);
2050 mgZoom = mMagnifier.zoom;
2051
2052 mgSize = mgSizePix / figPos(3);
2053
2054 mgPos(3) = mgSize * 2;
2055 mgPos(4) = mgPos(3) * af;
2056
2057 mg3 = round(mgPos(3) * figPos(3));
2058 mg4 = round(mgPos(4) * figPos(4));
2059
2060 if (mg4 < mg3)
2061 mgSize = (mgSizePix * (mg3 / mg4)) / figPos(3);
2062 end
2063
2064 mgPos(3) = mgSize * 2;
2065 mgPos(4) = mgPos(3) * af;
2066
2067 mgPos(1) = wcx / figPos(3) - mgSize;
2068 mgPos(2) = wcy / figPos(4) - mgSize * af;
2069
2070 mgXLim = acx + (1 / mgZoom) * (mgPos(3) / axPos(3)) * diff(xLim) * [-0.5 0.5];
2071 mgYLim = acy + (1 / mgZoom) * (mgPos(4) / axPos(4)) * diff(yLim) * [-0.5 0.5];
2072
2073 SetObjPos(mMagnifier.obj, mgPos, 'normalized');
2074
2075 if isXLog
2076 mgXLim = 10.^mgXLim;
2077 end
2078 if isYLog
2079 mgYLim = 10.^mgYLim;
2080 end
2081
2082 set(mMagnifier.obj, ...
2083 'XLim', mgXLim, ...
2084 'YLim', mgYLim);
2085
2086 MagnifierBorderUpdate();
2087 end
2088 end
2089
2090
2091
2092 function MagnifierSetup()
2093
2094
2095 set(mMagnifier.obj, ...
2096 'Box', 'on', ...
2097 'XMinorTick', 'on', ...
2098 'YMinorTick', 'on');
2099
2100 title(mMagnifier.obj, '');
2101 xlabel(mMagnifier.obj, '');
2102 ylabel(mMagnifier.obj, '');
2103
2104 if fIsImage
2105 mMagnifier.frame_obj = ...
2106 [patch('Parent', mMagnifier.obj), ...
2107 patch('Parent', mMagnifier.obj)];
2108
2109 set(mMagnifier.frame_obj, 'FaceColor', 'none');
2110
2111 set(mMagnifier.frame_obj(1), ...
2112 'LineWidth', 1.5, ...
2113 'EdgeColor', 'w')
2114 set(mMagnifier.frame_obj(2), ...
2115 'LineWidth', 1, ...
2116 'EdgeColor', 'k')
2117
2118 MagnifierBorderUpdate();
2119 end
2120
2121 hLines = findobj(mMagnifier.obj, 'Type', 'line');
2122 if ~isempty(hLines)
2123 if (mMgLinesWidth ~= 1)
2124 set(hLines, 'LineWidth', mMgLinesWidth);
2125 end
2126 end
2127
2128 set(hAx, 'Color', get(hAx, 'Color')*mMgShadow);
2129 end
2130
2131
2132
2133 function MagnifierBorderUpdate()
2134
2135
2136 if fIsImage
2137 x = get(mMagnifier.obj, 'XLim');
2138 y = get(mMagnifier.obj, 'YLim');
2139
2140 set(mMagnifier.frame_obj, ...
2141 'XData', [x(1) x(2) x(2) x(1)], ...
2142 'YData', [y(1) y(1) y(2) y(2)]);
2143 end
2144 end
2145
2146
2147
2148 function MagnifierSizeChange(direction)
2149
2150
2151 if fIsMagnifierOn
2152 switch direction
2153 case 'plus'
2154 if (mMagnifier.size < mMgMaxSize)
2155 mMagnifier.size = mMagnifier.size + mMgSizeStep;
2156 end
2157 case 'minus'
2158 if (mMagnifier.size > mMgMinSize)
2159 mMagnifier.size = mMagnifier.size - mMgSizeStep;
2160 end
2161 end
2162
2163 MagnifierUpdate();
2164 end
2165 end
2166
2167
2168
2169 function MagnifierZoomChange(direction)
2170
2171
2172 if fIsMagnifierOn
2173 switch direction
2174 case 'plus'
2175 if (mMagnifier.zoom < mMgMaxZoom)
2176 mMagnifier.zoom = mMagnifier.zoom * mMgZoomStep;
2177 end
2178 case 'minus'
2179 if (mMagnifier.zoom > mMgMinZoom)
2180 mMagnifier.zoom = mMagnifier.zoom / mMgZoomStep;
2181 end
2182 end
2183
2184 MagnifierUpdate();
2185 end
2186 end
2187
2188
2189
2190 function MagnifierReset()
2191
2192
2193 if fIsMagnifierOn
2194 mMagnifier.size = mMgSize;
2195 mMagnifier.zoom = mMgZoom;
2196 MagnifierUpdate();
2197 end
2198 end
2199
2200
2201
2202 function SetLinkAxesKeys(modifier)
2203
2204
2205 if isempty(modifier)
2206 mLinkOpt = 'xy';
2207 else
2208 switch modifier{1}
2209 case 'control'
2210 mLinkOpt = 'x';
2211 case 'alt'
2212 mLinkOpt = 'y';
2213 end
2214 end
2215
2216 if fIsLinkAxesOn
2217 LinkAxesOff();
2218 else
2219 LinkAxesOn();
2220 end
2221
2222 UserData = get(hFig, 'UserData');
2223 UserData.tools.islinkaxeson = fIsLinkAxesOn;
2224 set(hFig, 'UserData', UserData);
2225 end
2226
2227
2228
2229 function LinkAxesOn()
2230
2231
2232 if ~fIsLinkAxesOn
2233 hAxes2d = GetHandlesAxes2D();
2234 if (length(hAxes2d) > 1)
2235 linkaxes(hAxes2d, mLinkOpt);
2236 fIsLinkAxesOn = true;
2237 SetFigureName();
2238 end
2239 end
2240 end
2241
2242
2243
2244 function LinkAxesOff()
2245
2246
2247 if fIsLinkAxesOn
2248 fIsLinkAxesOn = false;
2249
2250 SetFigureName();
2251 hAxes2d = GetHandlesAxes2D();
2252 linkaxes(hAxes2d, 'off');
2253 end
2254 end
2255
2256
2257
2258 function DeleteOldTools()
2259
2260
2261 UserData = get(hFig, 'UserData');
2262
2263 if (~isempty(UserData) && isfield(UserData, 'tools'))
2264 if ~isempty(UserData.tools.pointercross) && ...
2265 isempty(find(ishandle(UserData.tools.pointercross) == 0))
2266 mPointerCross = UserData.tools.pointercross;
2267 fIsPointerCross = true;
2268 PointerCrossOff();
2269 UserData.tools.pointercross = [];
2270 end
2271
2272 if UserData.tools.islinkaxeson
2273 fIsLinkAxesOn = true;
2274 LinkAxesOff();
2275 UserData.tools.islinkaxeson = false;
2276 end
2277
2278 set(hFig, 'UserData', UserData);
2279 end
2280 end
2281
2282
2283
2284 function hAxes2d = GetHandlesAxes2D()
2285
2286
2287 isAxes2d = arrayfun(@(x) x.is2d && ~x.islegend, mAxesInfo);
2288 hAxes2d = hAxes(isAxes2d);
2289
2290 if ~isempty(hAxes2d)
2291
2292 hAxes2d(eq(hAxes2d, hAx)) = 0;
2293 hAxes2d = sort(hAxes2d);
2294 hAxes2d(eq(hAxes2d, 0)) = hAx;
2295 end
2296 end
2297
2298
2299
2300 function ResetAxesToOrigView()
2301
2302
2303 SetAxesLimits(mDefaultXLim, mDefaultYLim);
2304 PointerCrossUpdate();
2305
2306 mZoomIndexX = find(mZoomGrid == 100);
2307 mZoomIndexY = mZoomIndexX;
2308 end
2309
2310
2311
2312 function ResetAxesToOrigView3D()
2313
2314
2315
2316 axi = GetCurrentAxesIndex();
2317 pos = mAxesInfo(axi).normposition;
2318 SetObjPos(hAx, pos, 'normalized');
2319
2320
2321 resetplotview(hAx, 'ApplyStoredView');
2322
2323 if mAxesInfo(axi).isvis3d
2324 axis(hAx, 'vis3d');
2325 end
2326
2327
2328 mZoom3DIndex = find(mZoomGrid == 100);
2329 end
2330
2331
2332
2333 function [x, y, z] = GetCursorCoordOnAxes()
2334
2335
2336 crd = get(hAx, 'CurrentPoint');
2337 x = crd(2,1);
2338 y = crd(2,2);
2339 z = crd(2,3);
2340 end
2341
2342
2343
2344 function [x, y] = GetCursorCoordOnWindow(units)
2345
2346
2347 if (nargin < 1), units = 'pixels'; end
2348
2349 dfltUnits = get(hFig, 'Units');
2350 set(hFig, 'Units', units);
2351
2352 crd = get(hFig, 'CurrentPoint');
2353 x = crd(1);
2354 y = crd(2);
2355
2356 set(hFig, 'Units', dfltUnits);
2357 end
2358
2359
2360
2361 function pos = GetObjPos(h, units)
2362
2363
2364 if (nargin < 2), units = get(h, 'Units'); end
2365
2366 dfltUnits = get(h, 'Units');
2367 set(h, 'Units', units);
2368 pos = get(h, 'Position');
2369 set(h, 'Units', dfltUnits);
2370 end
2371
2372
2373
2374 function SetObjPos(h, pos, units)
2375
2376
2377 if (nargin < 3), units = get(h, 'Units'); end
2378
2379 dfltUnits = get(h, 'Units');
2380 set(h, 'Units', units);
2381 set(h, 'Position', pos);
2382 set(h, 'Units', dfltUnits);
2383 end
2384
2385
2386
2387 function [xLim, yLim] = GetAxesLimits()
2388
2389
2390 xLim = get(hAx, 'XLim');
2391 yLim = get(hAx, 'YLim');
2392 end
2393
2394
2395
2396 function SetAxesLimits(xLim, yLim)
2397
2398
2399 set(hAx, 'XLim', xLim);
2400 set(hAx, 'YLim', yLim);
2401 end
2402
2403
2404
2405 function SetPointerCrossKeys()
2406
2407
2408 if fIsPointerCross
2409 PointerCrossOff();
2410 else
2411 PointerCrossOn();
2412 end
2413
2414 UserData = get(hFig, 'UserData');
2415 UserData.tools.pointercross = mPointerCross;
2416 set(hFig, 'UserData', UserData);
2417 end
2418
2419
2420
2421 function SetPointer(pointerType)
2422
2423
2424 set(hFig, 'Pointer', pointerType);
2425 end
2426
2427
2428
2429 function SetAxesGridKeys()
2430
2431
2432 if fIsAxesGrid
2433 action = 'off';
2434 fIsAxesGrid = false;
2435 else
2436 action = 'on';
2437 fIsAxesGrid = true;
2438 end
2439
2440 set(hAx, 'XGrid', action, 'YGrid', action, 'ZGrid', action);
2441
2442 if fIsMagnifierOn
2443 set(mMagnifier.obj, 'XGrid', action, 'YGrid', action);
2444 end
2445 end
2446
2447
2448
2449 function SetSmoothKeys()
2450
2451
2452 if fIsSmoothing
2453 action = 'off';
2454 fIsSmoothing = false;
2455 else
2456 action = 'on';
2457 fIsSmoothing = true;
2458 end
2459
2460 if ~fIsImage
2461
2462
2463 hLine = findobj(hAx, 'Type', 'Line');
2464 if ~isempty(hLine)
2465 set(hLine, 'LineSmooth', action);
2466 end
2467 end
2468 end
2469
2470
2471
2472 function [zg, st] = ZoomLogGrid(a, b, n)
2473
2474
2475 zg = unique(round(logspace(a, b, n)));
2476
2477 zg(zg<10) = [];
2478 st = length(zg);
2479
2480 if isempty(find(zg == 100, 1))
2481 error('dragzoom:badZoomGridOptions', 'Options for zoom grid is bad.')
2482 end
2483 end
2484
2485
2486
2487 function tf = IsZoomMouseAllowed()
2488
2489
2490 [wcx, wcy] = GetCursorCoordOnWindow();
2491
2492
2493
2494
2495
2496 cur_units = get(gca, 'Units');
2497 set(gca, 'Units', 'pixels');
2498 figPos = get(gca, 'Position');
2499 set(gca, 'Units', cur_units);
2500
2501 Xrange = [figPos(1), figPos(1)+figPos(3)];
2502 Yrange = [figPos(2), figPos(2)+figPos(4)];
2503 if (Xrange(1) <= wcx && wcx <= Xrange(2)) && ...
2504 (Yrange(1) <= wcy && wcx <= Yrange(2))
2505 tf = true;
2506 else
2507 tf = false;
2508 end
2509 end
2510
2511
2512
2513 function tf = IsImageOnAxes(ax)
2514
2515
2516 if (nargin < 1), ax = hAx; end
2517
2518 h = findobj(ax, 'Type', 'Image');
2519
2520 if isempty(h)
2521 tf = false;
2522 else
2523 tf = true;
2524 end
2525 end
2526
2527
2528
2529 function tf = IsAxes2D(ax)
2530
2531
2532 if (nargin < 1), ax = hAx; end
2533
2534 if isempty(fMode)
2535 tf = is2D(ax);
2536 elseif strcmpi(fMode, '2d')
2537 tf = true;
2538 else
2539 tf = false;
2540 end
2541 end
2542
2543
2544
2545 function tf = IsLegendAxes(ax)
2546
2547
2548 tf = strcmp(get(ax, 'Tag'), 'legend');
2549 end
2550
2551
2552
2553 function targetInBounds = IsInBoundsAxes(ax)
2554
2555
2556 targetInBounds = true;
2557 tol = 3e-16;
2558 cp = get(ax, 'CurrentPoint');
2559
2560 XLims = get(ax, 'XLim');
2561 if ((cp(1,1) - min(XLims)) < -tol || (cp(1,1) - max(XLims)) > tol) && ...
2562 ((cp(2,1) - min(XLims)) < -tol || (cp(2,1) - max(XLims)) > tol)
2563 targetInBounds = false;
2564 end
2565
2566 YLims = get(ax, 'YLim');
2567 if ((cp(1,2) - min(YLims)) < -tol || (cp(1,2) - max(YLims)) > tol) && ...
2568 ((cp(2,2) - min(YLims)) < -tol || (cp(2,2) - max(YLims)) > tol)
2569 targetInBounds = false;
2570 end
2571
2572 ZLims = get(ax, 'ZLim');
2573 if ((cp(1,3) - min(ZLims)) < -tol || (cp(1,3) - max(ZLims)) > tol) && ...
2574 ((cp(2,3) - min(ZLims)) < -tol || (cp(2,3) - max(ZLims)) > tol)
2575 targetInBounds = false;
2576 end
2577 end
2578
2579
2580
2581 function tf = IsCurrentAxes(ax)
2582
2583
2584 hcAx = get(hFig, 'CurrentAxes');
2585 tf = eq(ax, hcAx);
2586 end
2587
2588
2589
2590 function tf = IsAxesVis3D(ax)
2591
2592
2593 visProp = {
2594 get(ax, 'PlotBoxAspectRatioMode')
2595 get(ax, 'DataAspectRatioMode')
2596 get(ax, 'CameraViewAngleMode')
2597 };
2598
2599 tf = all(strcmpi(visProp, 'manual'));
2600 end
2601
2602
2603
2604 function AxesInfo = GetAxesInfo()
2605
2606
2607 countAxes = length(hAxes);
2608
2609 AxesInfo = struct(...
2610 'handle', cell(1, countAxes), ...
2611 'iscurrent', cell(1, countAxes), ...
2612 'is2d', cell(1, countAxes), ...
2613 'isimage', cell(1, countAxes), ...
2614 'isvisible', cell(1, countAxes), ...
2615 'isvis3d', cell(1, countAxes), ...
2616 'islegend', cell(1, countAxes), ...
2617 'position', cell(1, countAxes), ...
2618 'normposition', cell(1, countAxes), ...
2619 'xlim', cell(1, countAxes), ...
2620 'ylim', cell(1, countAxes), ...
2621 'camtarget', cell(1, countAxes), ...
2622 'camposition', cell(1, countAxes));
2623
2624 for i = 1:countAxes
2625 h = hAxes(i);
2626
2627 AxesInfo(i).handle = h;
2628 AxesInfo(i).iscurrent = IsCurrentAxes(h);
2629 AxesInfo(i).is2d = IsAxes2D(h);
2630 AxesInfo(i).isimage = IsImageOnAxes(h);
2631 AxesInfo(i).isvisible = strcmpi(get(h, 'Visible'), 'on');
2632 AxesInfo(i).isvis3d = IsAxesVis3D(h);
2633 AxesInfo(i).islegend = IsLegendAxes(h);
2634 AxesInfo(i).position = GetObjPos(h, 'pixels');
2635 AxesInfo(i).normposition = GetObjPos(h, 'normalized');
2636 AxesInfo(i).xlim = get(h, 'XLim');
2637 AxesInfo(i).ylim = get(h, 'YLim');
2638 AxesInfo(i).camtarget = get(h, 'CameraTarget');
2639 AxesInfo(i).camposition = get(h, 'CameraPosition');
2640 end
2641 end
2642
2643
2644
2645 function SelectAxesUnderCursor()
2646
2647
2648 axi = GetAxesIndexUnderCursor();
2649
2650 if (axi > 0)
2651 fIsEnableControl = true;
2652
2653 if ~mAxesInfo(axi).iscurrent
2654 caxi = GetCurrentAxesIndex();
2655
2656 if isempty(caxi)
2657 DeleteInvalidAxesInfo();
2658
2659 axi = GetAxesIndexUnderCursor();
2660 isCax2d = mAxesInfo(axi).is2d;
2661 else
2662 isCax2d = mAxesInfo(caxi).is2d;
2663 end
2664
2665 SetCurrentAxes(axi);
2666
2667
2668 if mAxesInfo(axi).islegend;
2669 fIsMouseOnLegend = true;
2670 else
2671 fIsMouseOnLegend = false;
2672 end
2673
2674
2675 if (isCax2d ~= mAxesInfo(axi).is2d)
2676
2677 SetCallbacks();
2678
2679 if fIsPointerCross
2680
2681 PointerCrossOff()
2682 end
2683 else
2684 if fIsPointerCross
2685
2686 PointerCrossOff()
2687 SetPointerCrossKeys()
2688 end
2689 end
2690 end
2691 else
2692 fIsEnableControl = false;
2693 end
2694 end
2695
2696
2697
2698 function SetCurrentAxes(axi)
2699
2700
2701 hAx = mAxesInfo(axi).handle;
2702
2703 set(hFig, 'CurrentAxes', hAx);
2704 for i = 1:numel(mAxesInfo)
2705 mAxesInfo(i).iscurrent = false;
2706 end
2707 mAxesInfo(axi).iscurrent = true;
2708
2709 fIsAxes2D = mAxesInfo(axi).is2d;
2710 fIsImage = mAxesInfo(axi).isimage;
2711
2712 mDefaultAxPos = mAxesInfo(axi).position;
2713 mDefaultXLim = mAxesInfo(axi).xlim;
2714 mDefaultYLim = mAxesInfo(axi).ylim;
2715
2716
2717 UserData = get(hFig, 'UserData');
2718 UserData.axesinfo = mAxesInfo;
2719 set(hFig, 'UserData', UserData);
2720 end
2721
2722
2723
2724 function axi = GetCurrentAxesIndex()
2725
2726
2727 axi = [];
2728
2729 for i = 1:numel(mAxesInfo)
2730 if (ishandle(mAxesInfo(i).handle) && mAxesInfo(i).iscurrent)
2731 axi = i;
2732 return;
2733 end
2734 end
2735 end
2736
2737
2738
2739 function axi = GetAxesIndexUnderCursor()
2740
2741
2742 axi = GetCurrentAxesIndex();
2743
2744 if ~fIsSelectedCurrentAxes
2745 caxi = GetCurrentAxesIndex();
2746 if ~IsInBoundsAxes(mAxesInfo(caxi).handle)
2747 axi = 0;
2748 end
2749 return;
2750 end
2751
2752 for i = 1:numel(mAxesInfo)
2753 if (ishandle(mAxesInfo(i).handle) && IsInBoundsAxes(mAxesInfo(i).handle))
2754 axi = i;
2755 return;
2756 else
2757 axi = 0;
2758 end
2759 end
2760 end
2761
2762
2763
2764 function axLim = FixInfLogLimits(ax, axLim)
2765
2766
2767 if (~all(isfinite(axLim)) || ~all(isreal(axLim)))
2768
2769
2770
2771
2772 oldstate = warning('off', 'MATLAB:HandleGraphics:NonfunctionalProperty:RenderLimits');
2773 renderlimits = get(hAx, 'RenderLimits');
2774 warning(oldstate);
2775
2776 switch ax
2777 case 'x'
2778 axLim = renderlimits(1:2);
2779 case 'y'
2780 axLim = renderlimits(3:4);
2781 end
2782 axLim = log10(axLim);
2783 end
2784 end
2785
2786
2787
2788 function DeleteInvalidAxesInfo()
2789
2790
2791 invalidAxes = arrayfun(@(x) ~ishandle(x.handle), mAxesInfo);
2792 mAxesInfo(invalidAxes) = [];
2793 hAxes(invalidAxes) = [];
2794 end
2795
2796
2797
2798 function isWithStatus = ParseInputs(varargin)
2799
2800
2801 isWithStatus = false;
2802
2803 switch nargin
2804 case 0
2805 hObj = gcf;
2806 status = 'on';
2807 ih = 0;
2808 case 1
2809 if ischar(varargin{1})
2810 isWithStatus = true;
2811 hObj = gcf;
2812 status = varargin{1};
2813 ih = 2;
2814 is = 1;
2815 else
2816 hObj = varargin{1};
2817 status = 'on';
2818 ih = 1;
2819 is = 2;
2820 end
2821 case 2
2822
2823 isWithStatus = true;
2824 hObj = varargin{1};
2825 status = varargin{2};
2826 ih = 1;
2827 is = 2;
2828 end
2829
2830 switch lower(status)
2831 case 'on'
2832 fIsEnabled = true;
2833 case 'off'
2834 fIsEnabled = false;
2835 case '2d'
2836 fIsEnabled = true;
2837 fMode = '2d';
2838 case '3d'
2839 fIsEnabled = true;
2840 fMode = '3d';
2841 otherwise
2842 error('dragzoom:invalidInputs', ...
2843 'Input Argument %d must be a string "on" or "off".', is)
2844 end
2845
2846 if all(ishandle(hObj))
2847 handleType = get(hObj(1), 'Type');
2848
2849 switch handleType
2850 case 'axes'
2851 hAxes = unique(hObj);
2852 hFig = ancestor(hAxes(1), 'figure');
2853
2854 case 'figure'
2855 hFig = hObj;
2856 hAxes = findobj(hFig, 'Type', 'axes');
2857
2858 if isempty(hAxes)
2859 warning('dragzoom:notFoundAxes', 'Not found axes objects on figure.')
2860 end
2861
2862 otherwise
2863 error('dragzoom:invalidHandle', ...
2864 'Input Argument %d must be figure or axes handle.', ih)
2865 end
2866 else
2867 error('dragzoom:invalidInputs', ...
2868 'Input Argument %d must be a figure or axes handle.', ih)
2869 end
2870 end
2871
2872
2873
2874 function res = range(x)
2875
2876
2877 res = abs(diff([min(x) max(x)]));
2878 end
2879
2880
2881 end
2882