* `nchoosek` is introduced, to compute the binomial coefficients.
* The left .\. and right ./. Kronecker divisions are now implemented, for arrays of decimal or complex numbers.
* `perms` can now build and return only unique permutations, without duplicates.
+* Most of graphic objects can be moved interactively in opened figures.
Help pages:
* [#7724](https://bugzilla.scilab.org/7724): When a figure is created in .auto_resize="on" mode, its .axes_size sets its .figure_size accordingly, not the reverse. But this was not documented.
* [#7732](https://bugzilla.scilab.org/7732): The `datafit` help page needed to be fixed and overhauled.
* [#7765](https://bugzilla.scilab.org/7765): `champ1` is useless. `champ().colored` is available for a long time.
+* [#7777](https://bugzilla.scilab.org/7777): `ged` did not allow moving several objects.
* [#7948](https://bugzilla.scilab.org/7948): `gsort` could not perform multilevel sorting, and could not sort complex numbers completely.
* [#7967](https://bugzilla.scilab.org/7967): The tricky size `[ny,nx]` of `meshgrid(x,y)` results and usages with graphics was not enough documented.
* [#8301](https://bugzilla.scilab.org/8301): `definedfields` wrongly considered as defined void elements in lists, tlists and mlists.
* [#11852](https://bugzilla.scilab.org/11852): File browser didn't update after file creation or removal.
* [#11363](https://bugzilla.scilab.org/11363): `show_window()` did not raise the current graphics window.
* [#12013](https://bugzilla.scilab.org/12013): `bitset` did not work for numbers greater than 2^32-1.
+* [#12302](https://bugzilla.scilab.org/12302): Blocks of legends could not be moved interactively.
* [#12520](https://bugzilla.scilab.org/12520): Variable browser did not display the size of the variables.
* [#12534](https://bugzilla.scilab.org/12534): Variable browser did not display the size of the variables.
* [#12837](https://bugzilla.scilab.org/12837): `strcmpi` was an obsolete duplicate of `strcmp(,'i')`. It is removed.
// F. Delebecque + slight modif from B. Pincon
// modified again by Eric Dubois and Jean-Baptiste Silvy 18/01/07
- rhs=argn(2)
+ rhs = argn(2)
if rhs < 2 then
- error(msprintf(gettext("%s: Wrong number of input arguments: At least %d expected.\n"), "legends", 2));
+ msg = _("%s: Wrong number of input arguments: At least %d expected.\n")
+ error(msprintf(msg, "legends", 2));
end
if type(leg) ~= 10 then,
- error(msprintf(gettext("%s: Wrong type for input argument #%d: String array expected.\n"), "legends", 1));
+ msg = _("%s: Wrong type for input argument #%d: String array expected.\n")
+ error(msprintf(msg, "legends", 1));
end
- nleg=size(leg,"*")
+ nleg = size(leg,"*")
if type(style) ~= 1 & type(style) ~= 9 then
- error(msprintf(gettext("%s: Wrong type for input argument #%d: Real array or graphic handle array expected.\n"), "legends", 2));
+ msg = _("%s: Wrong type for input argument #%d: Real array or graphic handle array expected.\n")
+ error(msprintf(msg, "legends", 2));
end
if ~exists("opt","local") then
- opt=5
+ opt = 5
elseif typeof(opt)=="string" then
select opt
- case "ur" then, opt=1,
- case "ul" then, opt=2,
- case "ll" then, opt=3,
- case "lr" then, opt=4,
- case "?" then, opt=5,
- case "below" then, opt=6,
+ case "ur" then, opt = 1,
+ case "ul" then, opt = 2,
+ case "ll" then, opt = 3,
+ case "lr" then, opt = 4,
+ case "?" then, opt = 5,
+ case "below" then, opt = 6,
else
- error(msprintf(gettext("%s: Wrong value for input argument #%d: ''%s'', ''%s'', ''%s'', ''%s'', ''%s'' or ''%s'' expected.\n"),"legends", 3, "ur", "ul", "ll", "lr", "?", "below"));
+ msg = _("%s: Wrong value for input argument #%d: ''%s'', ''%s'', ''%s'', ''%s'', ''%s'' or ''%s'' expected.\n")
+ error(msprintf(msg,"legends", 3, "ur", "ul", "ll", "lr", "?", "below"));
end
end
if ~exists("with_box","local") then, with_box=%t, end
end
ns=size(style)
- if ns ~= [2 1] & or(ns==1) then, style=matrix(style,1,-1),end
- ns=size(style,2)
+ if ns ~= [2 1] & or(ns==1) then
+ style = matrix(style,1,-1)
+ end
+ ns = size(style,2)
//preserve current graphic context
- f=gcf()
- vis=f.immediate_drawing;
- old_ax=gca(),
- arect=old_ax.margins;
- r1=old_ax.axes_bounds;
+ f = gcf()
+ vis = f.immediate_drawing;
+ old_ax = gca(),
+ arect = old_ax.margins;
+ r1 = old_ax.axes_bounds;
//create small axes on the top left corner (the axes is chosen very
//small to avoid it can be selected for rotation in new graphic mode
//case (a little tricky)
xsetech(wrect=[r1(1),r1(2),r1(3)/1000,r1(4)/1000],frect=[0 0 1,1]/1000,arect=[0,0,0,0])
- xmin=arect(1);xmax=1-arect(2);ymin=-1+arect(4);ymax=-arect(3);
- cur_ax=gca(),
- cur_ax.clip_state="off";
+ xmin = arect(1);xmax=1-arect(2);ymin=-1+arect(4);ymax=-arect(3);
+ cur_ax = gca(),
+ cur_ax.clip_state = "off";
+ cur_ax.tag = "legends" // for ged(6,#)
dy = ymax-ymin ;
yOffset = dy / 60 ;
- drx=(xmax-xmin)/20 //length of the line
+ drx = (xmax-xmin)/20 //length of the line
xOffset = drx/5 ;
- bbx=[]
- for k=1:nleg
+ bbx = []
+ for k = 1:nleg
r = stringbox( leg(k), 0, 0, 0, old_ax.font_style, font_size ) ;
- bbx=[bbx;r(1,3) - r(1,1) , r(2,3) - r(2,1)]; //[width height]
+ bbx = [bbx;r(1,3) - r(1,1) , r(2,3) - r(2,1)]; //[width height]
end
height = sum(bbx(:,2))
pos(1) = xmin + ((opt(1)-r2(1))/(r2(3)-r2(1)))*(1-arect(1)-arect(2))
pos(2) = ymin + ((opt(2)-r2(2))/(r2(4)-r2(2)))*(1-arect(3)-arect(4))
// end bugfix
- opt=0 ;
+ opt = 0 ;
elseif opt<1 | opt>6 then
- error(msprintf(gettext("%s: Wrong value for input argument %s: Must be in the interval [%d, %d]."),"legends", "opt", 1, 6)); // if opt is entered by a string by the user it is in the range
+ msg = gettext("%s: Wrong value for input argument %s: Must be in the interval [%d, %d].")
+ error(msprintf(msg,"legends", "opt", 1, 6)); // if opt is entered by a string by the user it is in the range
end
select opt
case 1 then
- pos=[xmax-width-xOffset,ymax-yOffset]
+ pos = [xmax-width-xOffset, ymax-yOffset]
case 2 then
- pos=[xmin+xOffset,ymax-yOffset]
+ pos = [xmin+xOffset, ymax-yOffset]
case 3 then
- pos=[xmin+xOffset,ymin+height+yOffset]
+ pos = [xmin+xOffset, ymin+height+yOffset]
case 4 then
- pos=[xmax-width-xOffset,ymin+height+yOffset]
+ pos = [xmax-width-xOffset, ymin+height+yOffset]
case 5 then
- rect=dragrect([xmax-width-xOffset,ymax-yOffset,width,height])
- pos=rect(1:2)
+ rect = dragrect([xmax-width-xOffset, ymax-yOffset,width,height])
+ pos = rect(1:2)
case 6 then
// decrease the size of the graph to leave place for the legend
- old_ax.margins=[xmin;arect(2);arect(4);arect(3)+height + 2 * yOffset ]
- pos=[(xmin+xmax)/2-width/2, ymin + height - 2 * yOffset ]
+ old_ax.margins = [xmin; arect(2); arect(4); arect(3)+height + 2 * yOffset ]
+ pos = [(xmin+xmax)/2-width/2, ymin + height - 2 * yOffset ]
end
- x=pos(1)+xOffset
- y=pos(2)
+ x = pos(1) + xOffset
+ y = pos(2)
f.immediate_drawing = "off",
- a=gca() ;
- a.foreground=old_ax.foreground ;
- a.background=old_ax.background ;
- a.font_color=old_ax.font_color ;
- a.font_size =old_ax.font_size ;
- a.font_style=old_ax.font_style ;
-
- R=[]
+ a = gca() ;
+ a.foreground = old_ax.foreground ;
+ a.background = old_ax.background ;
+ a.font_color = old_ax.font_color ;
+ a.font_size = old_ax.font_size ;
+ a.font_style = old_ax.font_style ;
+
+ R = []
if with_box then
xpol = [pos(1), pos(1)+width, pos(1)+width, pos(1)];
ypol = [pos(2), pos(2), pos(2)-height, pos(2)-height];
xfpoly(xpol, ypol,1)
R = gce();
- R.foreground=a.foreground;
- R.background=a.background;
+ R.foreground = a.foreground;
+ R.background = a.background;
end
- for k=1:nleg
- if k<=size(style,2) then
+ for k = 1:nleg
+ if k <= size(style,2) then
if type(style)==9 then
- h=style(k)
+ h = style(k)
select h.type
case "Polyline"
if h.polyline_style==5 then //patch
xfpoly([x;x+drx;x+drx;x;x],[y-bbx(k,2);y-bbx(k,2);y;y;y-bbx(k,2)]);
- r=gce();
+ r = gce();
r = unglue(r); // one xfpoly returns 2 polylines -> tmp bug to fix later F.Leray
- r.foreground=h.foreground;
- r.thickness=h.thickness;
- r.polyline_style=h.polyline_style;
- r.line_style=h.line_style;
+ r.foreground = h.foreground;
+ r.thickness = h.thickness;
+ r.polyline_style = h.polyline_style;
+ r.line_style = h.line_style;
else
if stripblanks(h.mark_mode)=="off"
- xpoly([x;x+drx],[y;y]-bbx(k,2)/2,"lines");r=gce();
- r.foreground=h.foreground;
- r.thickness=h.thickness;
- r.polyline_style=h.polyline_style;
- r.line_style=h.line_style;
+ xpoly([x;x+drx], [y;y]-bbx(k,2)/2, "lines");
+ r = gce();
+ r.foreground = h.foreground;
+ r.thickness = h.thickness;
+ r.polyline_style = h.polyline_style;
+ r.line_style = h.line_style;
else
- xpoly(x+drx/2,y-bbx(k,2)/2);r=gce();
- r.foreground=h.foreground;
- r.thickness=h.thickness;
- r.mark_style=h.mark_style;
- r.mark_size=h.mark_size;
+ xpoly(x+drx/2, y-bbx(k,2)/2);
+ r = gce();
+ r.foreground = h.foreground;
+ r.thickness = h.thickness;
+ r.mark_style = h.mark_style;
+ r.mark_size = h.mark_size;
end
end
else
- error(msprintf(gettext("%s: Wrong type for input argument #%d: Polyline handles expected.\n"),"legends",2));
+ msg = _("%s: Wrong type for input argument #%d: Polyline handles expected.\n")
+ error(msprintf(msg,"legends",2));
end
else
if style(1,k)<= 0 then
- xpoly(x+drx/2,y-bbx(k,2)/2)
- r=gce(),
- r.mark_mode="on"
- r.mark_style=-style(1,k)
- if size(style,1)==2 then r.mark_foreground=style(2,k);end
+ xpoly(x+drx/2, y-bbx(k,2)/2)
+ r = gce(),
+ r.mark_mode = "on"
+ r.mark_style = -style(1,k)
+ if size(style,1)==2 then
+ r.mark_foreground = style(2,k);
+ end
else
- xpoly([x;x+drx],[y;y]-bbx(k,2)/2,"lines")
- r=gce(),
- r.foreground=style(1,k)
- if size(style,1)==2 then r.line_style=style(2,k);end
+ xpoly([x;x+drx], [y;y]-bbx(k,2)/2, "lines")
+ r = gce()
+ r.foreground = style(1,k)
+ if size(style,1)==2 then
+ r.line_style = style(2,k);
+ end
end
end
end
- R=[R,r']
- xstring(x + drx*1.2 + bbx(k,1)/2,y-bbx(k,2)/2,leg(k))
+ R = [R, r']
+ xstring(x + drx*1.2 + bbx(k,1)/2, y-bbx(k,2)/2, leg(k))
- r=gce()
+ r = gce()
r.font_size = font_size ;
r.alignment = "center" ;
r.text_box_mode = "centered" ; // the string is centered on (x,y)
- R=[R,r]
- y=y-bbx(k,2) ;
+ R = [R, r]
+ y = y - bbx(k,2) ;
end
glue(R)
- a=gca();
+ a = gca();
a.data_bounds = [0,0;0.001,0.001];
set("current_axes",old_ax),
--- /dev/null
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+// This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- TEST WITH GRAPHIC -->
+// <-- INTERACTIVE TEST -->
+//
+// Unitary tests for ged(6,figure)
+// = interactively selects and moves objects in a figure
+
+// 1) Executes the following block of instructions to generate the test figure:
+// ==================================
+function move_test(ptitle)
+ x = linspace(-2,2,150);
+ y = exp(2*x).*(1.05+sin(5*x));
+ y2 = exp(2*x).*(1.05+cos(5*x));
+ y3 = exp(x).*(1.05+cos(10*x));
+ plot2d(x,[y', y2' y3'])
+ ax = gca();
+ ax.log_flags = "nln";
+ ax.axes_reverse(1) = "on";
+ ax.grid_style = [8 8];
+ ax.sub_ticks = [1 8];
+ xgrid(color("grey80"))
+ // Labels
+ xtitle([ptitle; "row #2"],"Abscissae (inverted)", "Ordinates (log)")
+ // Text
+ xstring(0.8, 0.02, "Message");
+ e = gce();
+ e.font_size = 3;
+ e.box = "on";
+ xstring(0.5, 0.005, "Titled text");
+ e = gce();
+ e.font_size = 2;
+ e.font_angle = -30;
+ //xstring(-0.5, 3, "Centered"); // bugged
+ //e = gce();
+ //e.font_size = 2;
+ //e.text_box_mode = "centered";
+
+ // Segs - arrows
+ x = linspace(0,2*%pi,20);
+ xv = [sin(x); 9*sin(x)]/20 + 0.4;
+ yv = [cos(x); 9*cos(x)]*2 + 30;
+ xsegs(xv,yv,color("cyan"))
+ e = gce();
+ e.arrow_size = 1;
+ // Rectangle
+ xrect(-0.6, 20, 0.3, 14)
+ e = gce();
+ e.thickness = 2;
+ e.foreground = color("red");
+ // Datatip
+ d = datatipCreate(ax.children($).children(1),[-1.14 0.6]);
+ d.detached_position = [-1.2 1 0];
+ // Arc
+ xarc(0.9, 3.181, 0.6, 3.18, 120*64, 250*64)
+ e = gce();
+ e.foreground = color("orange");
+ e.thickness = 2;
+ // Legends from legends() or legend()
+ legend(['cos(t)';'cos(2*t)';'cos(3*t)']); // "Legend" type
+ legends(['sin(t)';'sin(2*t)';'sin(3*t)'],[-1,2 3],opt="ll") // "Axes" type
+ replot tight
+ // colorbar
+ c = jetcolormap(50);
+ gcf().color_map = [gcf().color_map ; c];
+ colorbar(-5,10,[35 85]);
+ //gce().parent.axes_bounds(3) = 0.06;
+endfunction
+clf reset
+subplot(1,2,1)
+move_test("Subplot")
+subplot(2,2,2)
+plot2d()
+xtitle("plot2d() example","Abscissae X","Ordinates Y")
+
+// Uicontrols
+// ----------
+f = gcf();
+ // listbox
+h = uicontrol(f,'style','listbox','units','normalized','position', [0.55 0.1 0.1 0.15]);
+h.string = "item 1|item 2|item3"; // fill the list
+h.value = 2;
+ // slider
+h = uicontrol(f,'style','slider', 'string', "Slider", ..
+ 'units','normalized','position', [0.68 0.1 0.03 0.15], ..
+ 'min', -3, 'max', 10, 'value', 1, 'sliderstep', [0.1 1]);
+h = uicontrol(f,'style','slider', ..
+ 'units','normalized','position', [0.55 0.05 0.17 0.030], ..
+ 'min', -3, 'max', 10, 'value', 1, 'sliderstep', [0.1 1]);
+ // popup menu
+h = uicontrol(f,'style','popupmenu', 'position', [550 175 100 20], ..
+ 'string', ["Option 1" "Option 2" "$x^{-3}$"], 'value', 2);
+ // Checkbox
+h = uicontrol(f,'style','checkbox', ..
+ 'position', [400 175 130 20], ..
+ 'string', "Absolute position", 'value', 1);
+ // Radio buttons
+h = uicontrol(f,'style','radiobutton', 'position', [400 150 130 20], ..
+ "min", 0, "max", 3, "value", 3, ..
+ 'string', "Resize window & see", "groupname", "test");
+h = uicontrol(f,'style','radiobutton', 'position', [400 125 130 20], ..
+ 'string', "Alternative", "groupname", "test");
+
+// Second separated figure
+// -----------------------
+scf();
+subplot(2,1,2)
+plot2d()
+xtitle("plot2d() example","Abscissae X","Ordinates Y")
+// ==================================
+
+// 2) Click on the "Move objects" icon in the graphic toolbar
+// or in the graphic "Edit => Move objects" menu.
+//
+// 3) Check that the proper message is displayed in the console:
+// "WARNING : Mouse moving picker ON => Console LOCKED
+// On a figure: Click left to get and set. Click middle to QUIT..."
+//
+// 4) Test moving each type of object:
+// - the whole axes: (handle = its box)
+// - both blocks of legends (generated with legend() or with legends())
+// - the boxed "Message" plotted with xstring() (inside the box)
+// - the "Tilted text" plotted with xstring() (inside the box)
+// - one of the curves, displayed with plot2d()
+// - the detached datatip linked to the green curve (inside the box)
+// - the set of cyan segments with arrows (one of its segments)
+// - the red rectangle (border)
+// - the orange arc (arc)
+// - the colorbar (small border)
+// - each uicontrol (border): listbox, popupmenu, sliders.
+// Choose a border point to drag the control ; avoid to push it.
+// - Titles of the plot2d() example in linear scaled
+//
+// 5) Zoom in the semi-log axes, and make the same tests as here-above
+//
+// 6) Click the middle button, and check that the proper message is displayed
+// in the console: "// Moving picker OFF => Back to the console."
+
<submenu label="&Axes properties">
<callback instruction='ged(9,[SCILAB_FIGURE_ID]);' type="0"/>
</submenu>
+ <submenu label="&Move objects">
+ <callback instruction='ged(6,[SCILAB_FIGURE_ID]);' type="0"/>
+ </submenu>
<separator/>
- <submenu label="&Start entity picker">
+ <submenu label="Start entity &picker">
<callback instruction='ged(10,[SCILAB_FIGURE_ID]);' type="0"/>
</submenu>
<submenu label="S&top entity picker">
<callback instruction='ged(11,[SCILAB_FIGURE_ID]);' type="0"/>
</submenu>
<separator/>
- <submenu label="&Start datatip manager" icon="datatips">
+ <submenu label="Start &datatip manager" icon="datatips">
<callback instruction='org.scilab.modules.gui.datatip.DatatipManager.start([SCILAB_FIGURE_ID])' type="3"/>
</submenu>
<submenu label="Stop datatip manager">
<button icon="data_modify" tooltiptext="Toggle curve data modification" toggle="true">
<callback instruction="useeditor([SCILAB_FIGURE_ID])" type="-2"/>
</button>
+ <button icon="ged_move" tooltiptext="Move objects">
+ <callback instruction="ged(6,[SCILAB_FIGURE_ID])" type="-2"/>
+ </button>
<separator/>
<!-- Help -->
<button icon="help-browser" tooltiptext="Help Browser">
+++ /dev/null
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) INRIA
-// Copyright (C) 2012 - 2016 - Scilab Enterprises
-//
-// This file is hereby licensed under the terms of the GNU GPL v2.0,
-// pursuant to article 5.3.4 of the CeCILL v.2.1.
-// This file was originally licensed under the terms of the CeCILL v2.1,
-// and continues to be available under such terms.
-// For more information, see the COPYING file which you should have received
-// along with this program.
-// compute the distance between a point and the arc
-// in 2D included in an axis aligned rectangle whose upper left
-// corner is upperLeft and its wifth and heigth is defined.
-function [dist,diffClose] = dist2Arc( point, upperLeft, width, heigth, sector1, sector2 )
-
-
- if ( width == 0 | heigth == 0 ) then
- dist = %inf ;
- diffClose = [%inf,%inf];
- return ;
- end
-
- // convert the sector into radiant angle
- angle1 = sector1 * %pi / 180. ;
- angle2 = (sector1 + sector2) * %pi / 180. ;
-
- width2 = width / 2. ;
- heigth2 = heigth / 2. ;
- centerC = [ upperLeft(1) + width2, upperLeft(2) - heigth2 ] ; // center of the ellipse
-
- // clicked point in the circle frame
- pointC = [ (point(1) - centerC(1)) / width2, (point(2) - centerC(2)) / heigth2 ] ;
-
- // get the projection of the clicked point on the circle
- closest = pointC / norm( pointC ) ;
-
- // now a quite tricky part. The aim is to find
- // if the closest point is in the drawing sector
- // ie if it is between bound1 and bound2 on the circle
- // maybe a eayer solution exists.
-
- // get the boundaries of the displayed angle
- // the closest point is not on the arc it is one of the two
- // boundaries
- bound1 = [cos(angle1),sin(angle1)] ;
- bound2 = [cos(angle2),sin(angle2)] ;
-
- // now get the vector of bissecting line between the two bounds
- // with the orientation toward the arc
- b2b1 = bound1 - bound2 ;
- bissect(1) = -b2b1(2) ;
- bissect(2) = b2b1(1) ;
-
- // get the position of the point along this axis
- side = closest(1) * bissect(1) + closest(2) * bissect(2) ;
-
- // get the position of one of the bound (same value for both)
- boundPos = bound1(1) * bissect(1) + bound1(2) * bissect(2) ;
-
- if side > boundPos then
- // the closest point is on the arc
- diffClose = ( pointC - closest ) .* [width2,heigth2] ;
- // bring it back to the current frame value
- //diffclose = diffclose .* [width2,heigth2] ;
-
- // get the distance with the closest point
- dist = norm( diffClose ) ;
-
- else
- // the closest point is one of the bounds
- // return back to the real coordinates
- bound1 = centerC + bound1 .* [width2,heigth2];
- bound2 = centerC + bound2 .* [width2,heigth2];
-
- // get the minimum distance
- dist = norm( bound1 - point ) ;
- dist2 = norm( bound2 - point ) ;
- if dist > dist2 then
- diffClose = bound1 - point ;
- else
- dist = dist2 ;
- diffClose = bound2 - point ;
- end
- //dist = min( norm( bound1 - point ), norm( bound2 - point ) ) ;
- end
-
-endfunction
+++ /dev/null
-// compute the square of distance between a point and the ellipse
-// in 2D included in an axis aligned rectangle whose upper left
-// corner is upperLeft and its wifth and heigth is defined.
-function [dist] = dist2Ellipse( point, upperLeft, width, heigth )
- width2 = width / 2. ;
- heigth2 = heigth / 2. ;
- centerC = [ upperLeft(1) + width2, upperLeft(2) - heigth2 ] ; // center of the ellipse
-
- // clicked point in the circle frame
- pointC = [ (point(1) - centerC(1)) / width2, (point(2) - centerC(2)) / heigth2 ] ;
-
- // get the vector between the point and the closest on the circle
- diffclose = ( 1 - 1 / norm( pointC ) ) * pointC ;
- //closest = pointC / sqrt( pointC(1) * pointC(1) + pointC(2) * pointC(2) ) ;
-
- // get the difference between the two
- //ffclose = pointC - closest ;
-
- // bring it back to the current frame value
- diffclose(1) = diffclose(1) * width2 ;
- diffclose(2) = diffclose(2) * heigth2 ;
-
- // get the distance with the closest point
- dist = norm( diffclose ) ;
-
-endfunction
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA
// Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2017 - Samuel GOUGEON
//
// This file is hereby licensed under the terms of the GNU GPL v2.0,
// pursuant to article 5.3.4 of the CeCILL v.2.1.
// For more information, see the COPYING file which you should have received
// along with this program.
-function [h,Axes]=ged_getobject(pt)
- h=[];Axes=[];
- f=get("current_figure");
- aold=get("current_axes")
- axes_array=f.children
- //retains only the entities of type Axes (remove uimenus)
- axes_array(axes_array.type<>"Axes")=[];
- // assume that the lastly created objects
- // are at the beginning of the arrays of children
- // We can then select the last object
- // first in the loop.
- for k=1:size(axes_array,"*")
- Axes=axes_array(k)
- set("current_axes",Axes)
- h=ged_loop(Axes,pt)
+function [h, Axes] = ged_getobject(pt)
+ // Internal private function called by ged_move_entity()
+ // pt: [x,y] coordinates of the last left mouse click, in pixels from top-left
+ // h: Handle of the graphic object
+ h = [];
+ Axes = [];
+ f = gcf();
+ aold = gca();
+ Children = f.children
+ //retains only the entities of type Axes or uicontrol (remove uimenus)
+ axes_array = Children(Children.type=="Axes");
+ uicontrol_array = Children(Children.type=="uicontrol");
+ // Axes
+ for k = 1:size(axes_array,"*")
+ Axes = axes_array(k)
+ set("current_axes", Axes)
+ h = ged_loop(Axes, pt)
if h<>[] then break,end
end
- set("current_axes",aold)
+ if h~=[] then
+ set("current_axes",aold)
+ return
+ end
+ // uicontrols
+ Axes = f;
+ h = ged_loop(uicontrol_array, pt)
endfunction
// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
// Copyright (C) INRIA
// Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2017 - Samuel GOUGEON
//
// This file is hereby licensed under the terms of the GNU GPL v2.0,
// pursuant to article 5.3.4 of the CeCILL v.2.1.
// For more information, see the COPYING file which you should have received
// along with this program.
-function h=ged_loop(a,pt)
+function h = ged_loop(a,pt)
+ // Internal private function called by ged_getobject()
+ // a: handle of the object to scan.
+ // pt: position of the mouse pointer, in pixels from the top-left
+ //
+ // ged_loop() scans all existing graphic objects in the given Axes/object,
+ // and try to find one of them with its handle in the pointer vicinity.
+ // If an object is found, its handle h is returned.
h=[]
minDist = 0.01 ;
minPixDist = 3 ;
- for ka=1:size(a,"*")
+ for ka = 1:size(a,"*") // size>1 for compounds
ck=a(ka) ;
select ck.type
case "Polyline"
- xy=ck.data;
- d=Dist2polyline((xy(:,1)-Xmin)/Dx,(xy(:,2)-Ymin)/Dy,pts)
- if d < minDist then h=ck,return,end
+ x = ck.data(:,1)
+ y = ck.data(:,2)
+ [xn, yn] = ged_get_normalized_axes_xy(x,y)
+ d = Dist2polyline(xn, yn, pts)
+ if d < minDist then
+ h = ck
+ return
+ end
+ h = ged_loop(ck.datatips,pt)
+ if h<>[] then
+ return
+ end
case "Rectangle"
- xy=ck.data;
- x0=xy(1);y0=xy(2);W=xy(3);H=xy(4);
- d=Dist2polyline((x0+[0,W,W,0]-Xmin)/Dx,(y0+[0,0,-H,-H]-Ymin)/Dy,pts)
- if d < minDist then h=ck,return,end
-
- case "Arc"
- xy=ck.data;
- [xp,yp]=xchange(pt(1),pt(2),"i2f")
- //[dist, toto] = dist2Arc( [xp,yp] ./ [Dx,Dy], xy(1:2)./[Dx,Dy], xy(3)/Dx, xy(4)/Dy, xy(5) / 64., xy(6) / 64. ) ;
- dist = pixDist2Arc( [xp,yp], xy(1:2), xy(3), xy(4), xy(5) / 64., xy(6) / 64. ) ;
- if dist <= minPixDist then
- h=ck;
- return;
+ xy = ck.data;
+ [x0, y0, w, h] = (xy(1), xy(2), xy(3), xy(4))
+ x = [x0 x0+w x0+w x0 x0]
+ y = [y0 y0 y0-h y0-h y0]
+ [xn, yn] = ged_get_normalized_axes_xy(x,y)
+ d = Dist2polyline(xn, yn, pts)
+ if d < minDist then
+ h = ck
+ return
+ end
+
+ case "Arc"
+ // The area of detection is not the whole enclosing rectangle, but
+ // only the given arc.
+ xy = ck.data;
+ [x, y, w, h, a0, da] = (xy(1), xy(2), xy(3), xy(4), xy(5)/64, xy(6)/64)
+ pax = ck.parent
+ xc = x + w/2
+ yc = y - h/2
+ A = linspace(a0, a0+da, max(ceil(da),3))
+ x = xc + w/2*cos(A)
+ y = yc + h/2*sin(A)
+ [xn, yn] = ged_get_normalized_axes_xy(x,y)
+ d = Dist2polyline(xn, yn, pts)
+ if d < 2*minDist then
+ h = ck
+ return
end
case "Segs"
- xy=ck.data;
- xv=(matrix(xy(:,1),2,-1)-Xmin)/Dx
- yv=(matrix(xy(:,2),2,-1)-Ymin)/Dy
- for ks=1:size(xv,2)
- d=Dist2polyline(xv(:,ks),yv(:,ks),pts)
- if d < minDist then h=ck,return,end
+ xy = ck.data;
+ xv = matrix(xy(:,1), 2, -1).'
+ yv = matrix(xy(:,2), 2, -1).'
+ [xn, yn] = ged_get_normalized_axes_xy(xv, yv)
+ for ks = 1:size(xn,1)
+ d = Dist2polyline(xn(ks,:).', yn(ks,:).', pts)
+ if d < minDist then h = ck, return, end
end
- case "Compound"
- h=ged_loop(ck.children,pt)
- if h<>[] then return,end
- case "Axes"
- xy=ck.data_bounds;
- [xp,yp]=xchange(pt(1),pt(2),"i2f")
- Xmin=xy(1,1);Ymin=xy(1,2),Dx=xy(2,1)-xy(1,1);Dy=xy(2,2)-xy(1,2);
- pts=[(xp-Xmin)/Dx (yp-Ymin)/Dy]
- d=Dist2polyline([0,1,1,0],[0,0,1,1],pts)
- if d < minDist then h=ck,return,end
- h=ged_loop([a.children(:);ck.x_label;ck.y_label;ck.z_label;ck.title],pt)
+ case "Compound"
+ h = ged_loop(ck.children,pt)
if h<>[] then return,end
case "Text"
- if is_in_text(ck,[xp;yp]) then
- h=ck,
- return,
+ b = mystringbox(ck)
+ if xp0>=b(1) & xp0<=b(2) & yp0>=b(3) & yp0<=b(4)
+ h = ck
+ return
end
case "Label"
- if is_in_text(ck,[xp;yp]) then
- h=ck
- return,
+ b = mystringbox(ck)
+ if xp0>=b(1) & xp0<=b(2) & yp0>=b(3) & yp0<=b(4)
+ h = ck
+ return
+ end
+
+ case "Legend"
+ // Is the click for the legend box?
+ // Whatever is the filling mode of the block, we consider that no
+ // external element on the legend background can be moved.
+ // BTW, the legend content of the box is frozen and can't either
+ // be moved inside it. So, the click is for the legend block as a
+ // whole if it is within the legend frame:
+ b = ged_legend_box_in_data_units(ck)
+ if (xp0>=b(1) & xp0<=b(2)) & (yp0>=b(3) & yp0<=b(4))
+ h = ck
+ return
end
+ case "Datatip"
+ // Only boxes of detached datatips can be moved
+ // Reversed and log axes supported
+ p = ck.detached_position
+ if p~=[]
+ b = mystringbox(ck)
+ if (xp0>=b(1) & xp0<=b(2)) & (yp0>=b(3) & yp0<=b(4))
+ h = ck
+ return
+ end
+ end
+
+ case "Axes"
+ //sca(ck);
+ [xp0, yp0] = xchange(pt(1),pt(2),"i2f")
+ xp = xp0
+ yp = yp0
+ if ck.zoom_box==[]
+ db = ck.data_bounds;
+ else
+ db = ck.zoom_box([1 3 2 4])
+ end
+ if ck.tag=="legends"
+ // micro-axes generated by legends()
+ // The frame is this polygon:
+ p = ck.children.children($).data
+ xmin = p(1,1), xmax = p(2,1)
+ ymin = p(4,2), ymax = p(1,2)
+ if xp>=xmin & xp<=xmax & yp>=ymin & yp<=ymax
+ h = ck // We return the whole axes to move it as a whole
+ return
+ end
+ else
+ Xlog = part(ck.log_flags,1)=="l"
+ if Xlog
+ xp = log10(xp)
+ db(1:2) = log10(db(1:2))
+ end
+ Ylog = part(ck.log_flags,2)=="l"
+ if Ylog
+ yp = log10(yp)
+ db(3:4) = log10(db(3:4))
+ end
+ [Xmin, Xmax, Ymin, Ymax] = (db(1), db(2), db(3), db(4))
+ Dx = Xmax - Xmin
+ Dy = Ymax - Ymin
+ Xreversed = ck.axes_reverse(1)=="on"
+ if ~Xreversed
+ dx = xp - Xmin
+ else
+ dx = Xmax - xp
+ end
+ Yreversed = ck.axes_reverse(2)=="on"
+ if ~Yreversed
+ dy = yp - Ymin
+ else
+ dy = Ymax - yp
+ end
+ pts = [dx/Dx dy/Dy]
+ d = Dist2polyline([0,1,1,0,0],[0,0,1,1,0],pts)
+ if d < minDist then
+ h = ck
+ return
+ end
+ // Restoring linear xp,yp (for recursive calls)
+ xp = xp0, yp = yp0
+ if length(a.children)>0
+ h = ged_loop([ck.children(:);ck.x_label;ck.y_label;ck.z_label;ck.title],pt)
+ if h<>[] then
+ return
+ end
+ end
+ end
+
+ case "uicontrol"
+ tmp = gcf();
+ wh = tmp.axes_size; // width, height
+ xy = ck.position
+ // ck.units == {pixels} | points | normalized
+ if ck.units=="normalized" // => converts into pixels:
+ xy([1 3]) = xy([1 3])*wh(1);
+ xy([2 4]) = xy([2 4])*wh(2);
+ else
+ // "points" case: to be implemented
+ end
+ [x0, y0, w, h] = (xy(1), wh(2)-xy(2)-xy(4), xy(3), xy(4))
+ // y0: position of the top-left corner of the uicontrol, wrt to the
+ // top-left corner of the figure
+ // [xn, yn] = ged_get_normalized_axes_xy(x,y)
+ dd = minDist * sqrt(sum(wh.^2));
+ if pt(1)>x0-dd & pt(1)<(x0+w+dd) & pt(2)>y0-dd & pt(2)<y0+h+dd
+ h = ck
+ return
+ end
+ // RECURSIVE CALLS TO BE IMPLEMENTED (into tabs and frames)
+ // The origin is on the top left corner no longer of the figure
+ // but of the parent frame, as well for xchange()
+ // => code to be overhauled
+ // (As well, axes in frames are not zoomable not pannable)
+ //if ck.style=="frame"
+ // // It may have axes:
+ // h = ged_loop(ck.children(:), pt)
+ // if h<>[] then
+ // return
+ // end
+ //end
end
end
endfunction
+function b = mystringbox(e)
+ // Internal private function for ged_loop()
+ // Works in lin & log scales, but only for angle = 0
+ // e: handle of type "Text" or "Label" or "Datatip"
+ a = gca();
+ db = a.data_bounds;
+ ang = 0;
+ if or(e.type==["Text" "Label"]) then
+ ang = e.font_angle;
+ end
+ ud = e.user_data
+ if typeof(ud)~="st" | ~isfield(ud,"pixbox") | ..
+ ud.text ~= e.text | or(ud.params ~= [ang e.font_style e.font_size]) then
+ drawlater // to avoid flashing
+ old_flags = a.log_flags;
+ a.log_flags = "nnn";
+ b = stringbox(e.text, db(1), db(3), ang, e.font_style, e.font_size);
+ [xpix, ypix] = xchange(b(1,:), b(2,:), "f2i");
+ a.log_flags = old_flags;
+ drawnow
+ xpix = xpix - xpix(1);
+ ypix = ypix - ypix(1);
+ e.userdata.pixbox = [xpix ; ypix];
+ e.userdata.params = [ang e.font_style e.font_size]; // hash
+ e.userdata.text = e.text; // hash
+ else
+ tmp = e.userdata.pixbox;
+ xpix = tmp(1,:);
+ ypix = tmp(2,:);
+ end
+ // Position of the pivot (default = bottom left)
+ if e.type=="Text"
+ pos = e.data;
+ elseif e.type=="Label"
+ pos = e.position
+ else // Detached datatip
+ pos = e.detached_position
+ end
+ [xp0, yp0] = xchange(pos(1), pos(2), "f2i");
+ if ~Xlog & ~Ylog & .. // centered xstring() bugged in log modes
+ e.type=="Text" & e.text_box_mode=="centered" & and(e.text_box==[0 0])
+ xpix = xpix - strange(xpix)/2
+ ypix = ypix - strange(ypix)/2
+ end
+ [xbox, ybox] = xchange(xp0 + xpix, yp0 + ypix, "i2f");
+ b = [ min(xbox) max(xbox) min(ybox) max(ybox) ];
+endfunction
+// function r=is_in_text(h,xy)
+// if h.Type == "Text" & h.text_box_mode=="filled" then
+// r=(xy(1)>h.data(1)&xy(1)<h.data(1)+h.text_box(1))&(xy(2)>h.data(2)&xy(2)<h.data(2)+h.text_box(2))
+// else
+// r = stringbox(h);
+// r=[r r(:,1)];
+// r=and([xy(2) -xy(1)]*diff(r,1,2)+(r(1,1:$-1).*r(2,2:$)-r(1,2:$).*r(2,1:$-1))<0)
+// end
+//endfunction
+
+function [xn,yn] = ged_get_normalized_axes_xy(x,y)
+ // Internal private function for ged_loop()
+ if Xlog
+ k = find(x<=0)
+ x(k) = 1e-308
+ x = log10(x)
+ end
+ if Ylog
+ k = find(y<=0)
+ y(k) = 1e-308
+ y = log10(y)
+ end
+ if ~Xreversed
+ xn = (x - Xmin)/Dx
+ else
+ xn = (Xmax - x)/Dx
+ end
+ if ~Yreversed
+ yn = (y - Ymin)/Dy
+ else
+ yn = (Ymax - y)/Dy
+ end
+endfunction
+
+function rect = ged_legend_box_in_data_units(idLeg)
+ // Internal private function for ged_loop()
+ // Returns rect = [xmin xmax ymin ymax] of the legend box.
+ // * reversed and log axes are implemented
+ // * axes.tight_limits="off" may slightly disturb results (no workaround)
+ // * The box size is set only according to the text box of legends.
+ // legend.position are the coordinates of the top-left corner of the
+ // legend box, in gca().axes_bounds normalized units
+ ax = idLeg.parent
+ db = ax.data_bounds
+
+ // Getting the relative width and height of the block of text in linear scales
+ if typeof(idLeg.userdata)~="st" | ~isfield(idLeg.userdata,"relwidth") | ..
+ idLeg.userdata.text ~= idLeg.text then
+ drawlater
+ old_flags = ax.log_flags;
+ ax.log_flags = "nnn";
+ b = xstringl(db(1), db(3), idLeg.text, idLeg.font_style, idLeg.font_size);
+ ax.log_flags = old_flags
+ drawnow
+ relwidth = b(3)/(db(2)-db(1))
+ relheight = b(4)/(db(4)-db(3))
+ idLeg.userdata.relwidth = relwidth
+ idLeg.userdata.relheight = relheight
+ idLeg.userdata.text = idLeg.text
+ else
+ relwidth = idLeg.userdata.relwidth
+ relheight = idLeg.userdata.relheight
+ end
+ // x position:
+ xlog = part(ax.log_flags,1)=="l"
+ if xlog
+ db(1:2) = log10(db(1:2))
+ end
+ tmp = (idLeg.position(1) - ax.margins(1)) / (1-sum(ax.margins(1:2)))* ..
+ (db(2)-db(1))
+ if ax.axes_reverse(1)=="off"
+ x0 = db(1) + tmp
+ else
+ x0 = db(2) - tmp
+ end
+
+ // y position:
+ ylog = part(ax.log_flags,2)=="l"
+ if ylog
+ db(3:4) = log10(db(3:4))
+ end
+ tmp = (idLeg.position(2) - ax.margins(3)) / (1-sum(ax.margins(3:4)))* ..
+ (db(4)-db(3))
+ if ax.axes_reverse(2)=="off"
+ y0 = db(4) - tmp
+ else
+ y0 = db(3) + tmp
+ end
+
+ // For the time being, the legend block is considered to be
+ // as tall and as wide as the text block only
+ x1 = x0 + (1 - 2*(ax.axes_reverse(1)=="on")) * relwidth * (db(2)-db(1));
+ y1 = y0 - (1 - 2*(ax.axes_reverse(2)=="on")) * relheight * (db(4)-db(3));
+ x = [x0 x1];
+ y = [y0 y1];
+ if xlog, x = 10.^x; end
+ if ylog, y = 10.^y; end
+ rect = [min(x) max(x) min(y) max(y)];
+endfunction
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) INRIA
+// Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+
function ged_move_entity()
- [btn,xc,yc]=xclick()
- pos=[xc,yc]
- [xc,yc]=xchange(xc,yc,"f2i")
- [r,ax]=ged_getobject([xc,yc])
- cur_ax=gca(),sca(ax)
- [xc,yc]=xchange(xc,yc,"i2f");pos=[xc,yc]
- if r==[] return,end
- drawlater();
- rep(3)=-1
- select r.type
- case "Rectangle" then
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.data(1:2)= r.data(1:2)+(rep(1:2)-pos)
- pos=rep(1:2)
- drawnow();
- end
- case "Segs" then //Segment
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.data=r.data+ones(2,1)*(rep(1:2)-pos)
- pos=rep(1:2)
- drawnow();
- end
- case "Polyline" then //Polyline
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.data(:,1:2)=r.data(:,1:2)+ones(r.data(:,1))*(rep(1:2)-pos)
- pos=rep(1:2)
- drawnow();
+ // Internal private function called by ged(6,fig)
+ // - Follows the mouse
+ // - When it is left or right clicked, tries to detect a graphical component
+ // in its vicinity.
+ // - If a component is detected,
+ // - then moves it following the mouse movements
+ // - sets its new position when the mouse is left or right clicked
+ // -... until the center button is clicked or 15 s are elapsed without
+ // moving the mouse on the figure.
+ //
+ // BUG: When the mouse goes out of the figure where the object has been
+ // picked, on another figure, the object may reappear on the current
+ // figure, far from where the mouse stands.
+ // See http://bugzilla.scilab.org/13913
+
+ f0 = gcf();
+ f = f0;
+ if f.default_axes=="off" then
+ // xclick() and xgetmouse() are disabled in such figures
+ return
+ end
+ ax0 = gca(); // Save it to restore it before leaving
+ btn = 0;
+ maxRestTime = 15; // s
+ warning(_("Mouse moving picker ON => Console LOCKED"))
+ mprintf(_("On a figure: Click left to get and set. Click middle to QUIT...\n"))
+ while ~or(btn==[1 4]); // click or press middle button => Quit
+ tic()
+ [btn, xc, yc, nFig, cb] = xclick(); // [xc, yc] are in data scales
+ if nFig ~= f.figure_id
+ f = scf(nFig);
end
- case "Arc" then //Circle
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.data(1:2)= r.data(1:2)+(rep(1:2)-pos)
- pos=rep(1:2)
- drawnow();
+ if toc()>maxRestTime
+ break
end
- case "Text" then
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.data(1:2)= r.data(1:2)+(rep(1:2)-pos)
- pos=rep(1:2)
- drawnow();
+ pos = [xc,yc];
+ [xc,yc] = xchange(xc,yc,"f2i"); // [xc, yc] => in pixels. Origin on the top-left
+ [r,ax] = ged_getobject([xc,yc]); // <-- Detects the clicked object
+ cur_ax = gca()
+ if ax.type=="Axes"
+ sca(ax);
+ Xlog = part(ax.log_flags,1)=="l";
+ Ylog = part(ax.log_flags,2)=="l";
+ [xc,yc] = xchange(xc,yc,"i2f");
+ else // uicontrols: coordinates in pixels
+ Xlog = %f;
+ Ylog = %f;
+ // [xc, yc] remain in pixels coordinates
end
- case "Label" then
- while rep(3)==-1 do
- rep=xgetmouse([%t %t])
- r.position= r.position+(rep(1:2)-pos)
- r.auto_position = "off"
- pos=rep(1:2)
- drawnow();
+ pos = [xc,yc]
+ if r~=[] & type(r)==9
+ rep(3) = -1;
+ //disp(r.type+" clicked")
+ select r.type
+ case "Rectangle" then
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ [nx, ny] = ged_newObjectPosition(r.data, rep, pos);
+ // The sizes of the rectangle are not changed.
+ // So in log scale(s) they are rendered in an elastic way.
+ r.data(1:2) = [nx ny];
+ pos = rep(1:2);
+ end
+ case "Segs" then //Segment
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ r.data = r.data + ones(r.data(:,1))*(rep(1:2)-pos);
+ pos = rep(1:2);
+ end
+ case "Polyline" then //Polyline
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ r.data(:,1:2) = r.data(:,1:2) + ones(r.data(:,1))*(rep(1:2)-pos);
+ pos = rep(1:2);
+ end
+ case "Arc" then //Circle
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ [nx, ny] = ged_newObjectPosition(r.data, rep, pos);
+ // The sizes of the enclosing rectangle of the arc are not changed.
+ // So in log scale(s) they are rendered in an elastic way.
+ r.data(1:2) = [nx ny];
+ pos = rep(1:2);
+ end
+
+ case "Text" then
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ [nx, ny] = ged_newObjectPosition(r.data, rep, pos);
+ r.data = [nx ny];
+ pos = rep(1:2);
+ end
+ case "Label" then
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ [nx, ny] = ged_newObjectPosition(r.position, rep, pos);
+ r.auto_position = "off";
+ r.position = [nx ny];
+ pos = rep(1:2);
+ end
+ case "Axes" then
+ // The axes coordinates are in normalized units in the figure
+ cf = ged_coordinates_in_figure(ax, xc, yc);
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ ncf = ged_coordinates_in_figure(ax, rep(1), rep(2));
+ ax.axes_bounds(1:2) = ax.axes_bounds(1:2) + (ncf - cf);
+ cf = ncf;
+ end
+ case "Datatip" then
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t])
+ p = r.detached_position
+ [nx, ny] = ged_newObjectPosition(p, rep, pos)
+ r.detached_position = [nx ny p(3)]
+ pos = rep(1:2)
+ end
+ case "Legend" then
+ // Legend block generated with legend()
+ // (legends() (with "s") sets an axes instead: move axes
+ // not yet supported)
+ //
+ // * reversed and log axes supported
+ // * prone to slight error if axes.tight_limits=="off"
+ // (no way to take it into account)
+ r.legend_location = "by_coordinates";
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ nx = rep(1); // New x position in data unit
+ ny = rep(2); // New y position in data unit
+ // Conversion in normalized axes units:
+ db = ax.data_bounds;
+ xlog = part(ax.log_flags,1)=="l";
+ if xlog
+ db(1:2) = log10(db(1:2));
+ nx = log10(nx);
+ end
+ if ax.axes_reverse(1)=="off"
+ nxa = (nx - db(1)) / (db(2)-db(1)) * ..
+ (1-sum(ax.margins(1:2))) + ax.margins(1);
+ else
+ nxa = (db(2) - nx) / (db(2)-db(1)) * ..
+ (1-sum(ax.margins(1:2))) + ax.margins(1);
+ end
+ ylog = part(ax.log_flags,2)=="l";
+ if ylog
+ db(3:4) = log10(db(3:4));
+ ny = log10(ny);
+ end
+ if ax.axes_reverse(2)=="off"
+ nya = (db(4) - ny) / (db(4)-db(3)) * ..
+ (1-sum(ax.margins(3:4))) + ax.margins(3);
+ else
+ nya = (ny - db(3)) / (db(4)-db(3)) * ..
+ (1-sum(ax.margins(3:4))) + ax.margins(3);
+ end
+ r.position = [nxa nya];
+ pos = rep(1:2);
+ end
+
+ case "uicontrol"
+ Fx = 1; Fy = 1;
+ if r.units=="normalized"
+ Fx = f.axes_size(1);
+ Fy = f.axes_size(2);
+ end
+ while rep(3)==-1 do
+ rep = xgetmouse([%t %t]);
+ [x, y] = xchange(rep(1),rep(2), "f2i");
+ r.position(1:2) = r.position(1:2) + [(x-pos(1))/Fx, (pos(2)-y)/Fy];
+ pos = [x y];
+ end
+ end
+ sca(cur_ax);
end
+ end
+ // Restoring initial current figure and axes:
+ scf(f0);
+ mprintf(_("\n--> // Moving picker OFF => Back to the console.\n"))
+endfunction
+
+function [nx, ny] = ged_newObjectPosition(objPos, pt, prevpt)
+ if ~Xlog
+ nx = objPos(1) + (pt(1)-prevpt(1))
+ else
+ nx = objPos(1)*(pt(1)/prevpt(1))
+ end
+ if ~Ylog
+ ny = objPos(2) + (pt(2)-prevpt(2))
+ else
+ ny = objPos(2)*(pt(2)/prevpt(2))
+ end
+endfunction
+function xy_in_figure = ged_coordinates_in_figure(idA, xdata,ydata)
+ // reversed and log axes supported
+ ab = idA.axes_bounds
+ db = idA.data_bounds
+ if part(idA.log_flags,1)=="l" then
+ db(1:2) = log10(db(1:2))
+ xdata = log10(xdata)
+ end
+ dx = xdata - db(1)
+ if idA.axes_reverse(1)=="on" then
+ dx = db(2) - xdata
+ end
+ if part(idA.log_flags,2)=="l" then
+ db(3:4) = log10(db(3:4))
+ ydata = log10(ydata)
+ end
+ dy = db(4) - ydata
+ if idA.axes_reverse(2)=="on" then
+ dy = ydata - db(3)
end
- sca(cur_ax)
+ xf = (dx/(db(2)-db(1))*(1-sum(idA.margins(1:2))) + idA.margins(1))*ab(3) + ab(1)
+ yf = (dy/(db(4)-db(3))*(1-sum(idA.margins(3:4))) + idA.margins(3))*ab(4) + ab(2)
+ xy_in_figure = [xf yf]
endfunction
+++ /dev/null
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) INRIA
-// Copyright (C) 2012 - 2016 - Scilab Enterprises
-//
-// This file is hereby licensed under the terms of the GNU GPL v2.0,
-// pursuant to article 5.3.4 of the CeCILL v.2.1.
-// This file was originally licensed under the terms of the CeCILL v2.1,
-// and continues to be available under such terms.
-// For more information, see the COPYING file which you should have received
-// along with this program.
-
-// same as before but return the value in pixels
-function dist = pixDist2Arc( point, upperLeft, width, heigth, sector1, sector2 )
-
- [dist, difference] = dist2Arc( point, upperLeft, width, heigth, sector1, sector2 ) ;
- // convert to pixels
- // get the length of the difference vector
- // we construct it by getting two points
- [origin(1),origin(2)] = xchange(0,0,"f2i");
- [extremity(1),extremity(2)] = xchange(difference(1),difference(2),"f2i");
- dist = norm( extremity - origin ) ;
-
-endfunction