Search code examples
matlabmatlab-figurelegendlegend-properties

Legend Location 'Best', but still in corner if possible


I want to set the Location of my legend to 'Best' (like legend('y1','y2','Location','Best')) so the legend doesn't collide with my lines, but at the same time, I would prefer to have it in a corner if that's possible with no data collision. Is there a way of implementing this?


Solution

  • In case anyone's interested in this, I wrote a function based on @S.. answer that does, what I wanted to achieve. Here's the code:

    function setPositionCornerBest( figureHandle )
    %Sets the Location of the legend of the figure that is referenced by figureHandle to one of the Corners if there is no data in the Corners. Otherwise it sets it to 'Best'
    h = figureHandle;
    
    figObjects = get(h,'Children');
    legHandle = findobj(figObjects,'Tag','legend');
    axHandle = findobj(figObjects,'Type','axes','-and','Tag','');
    lineHandle = findobj(figObjects,'Type','line','-and','Parent',axHandle);
    axPos = get(axHandle,'Position');
    
    LimX = get(axHandle,'XLim');
    LimY = get(axHandle,'YLim');
    
    xScaling = (LimX(2)-LimX(1))/axPos(3);
    yScaling = (LimY(2)-LimY(1))/axPos(4);
    
    locCell = {'NorthWest','NorthEast','SouthEast','SouthWest'};
    ii = 1;
    interSecFlag = true;
    
    while (interSecFlag) && (ii<=4)
        set(legHandle,'Location',locCell{ii});
        legPos = get(legHandle,'Position');
    
        x(1) = LimX(1)+(legPos(1)-axPos(1))*xScaling;
        x(2) = x(1);
        x(3) = LimX(1)+(legPos(1)+legPos(3)-axPos(1))*xScaling;
        x(4) = x(3);
        x(5) = x(1);
    
        y(1) = LimY(1)+(legPos(2)-axPos(2))*yScaling;
        y(2) = LimY(1)+(legPos(2)+legPos(4)-axPos(2))*yScaling;
        y(3) = y(2);
        y(4) = y(1);
        y(5) = y(1);
    
        for jj = 1:numel(lineHandle)
            xline = get(lineHandle(jj),'XData');
            yline = get(lineHandle(jj),'YData');
            [xInter ~] = intersections(x,y,xline,yline);
            if numel(xInter) == 0
                xInterFlag(jj) = 0;
            else
                xInterFlag(jj) = 1;
            end
        end
    
        if all(xInterFlag==0)
            interSecFlag = false;
        end
    
        ii = ii + 1;
    end
    
    if interSecFlag
        set(legHandle,'Location','Best');
    end
    
    end