1

I wish to draw text along a given vector (which might be anything - not necessarily elliptical or straight). The text must be remain tangential to the curve, like in this example.

The way to do it along some simple equation (a straight or elliptic line) is relatively simple in Java. However, this would be complicated in MATLAB:

  1. converting every character to an image using insertText() or vision.TextInserter
  2. computing the coordinates of each character in a straight line
  3. computing an adequate transformation using TFORM
  4. applying it for each character using imwarp()

Since the code is going to create at least thousands of images, each one with several characters, and will include other rendering operations, I am looking for a simpler/more economical way.

Moreover, this provides no solution in the case of a general vector.

Any suggestions? Adding libraries is not a problem if this can solve the problem.

Community
  • 1
  • 1
Yellows
  • 693
  • 4
  • 14
  • I can't see any other way other than what you have proposed. MATLAB was meant for data analysis and processing... and perhaps creating some nice looking GUIs, but never something as sophisticated as drawing text tangential to a curved vector. IMO, I don't think there's a simple way in doing it other than what you have already described! – rayryeng Dec 23 '14 at 17:25
  • Thanks! Then could you suggest some other script based language/environment which will do the job? – Yellows Dec 23 '14 at 17:27
  • If the [java example](http://stackoverflow.com/questions/5159845/curved-text-in-java) you linked to is good enough for you then you're ok. Matlab can integrate `Java` libraries relatively well. Look at the [documentation](http://uk.mathworks.com/help/matlab/using-java-libraries-in-matlab.html) – Hoki Dec 23 '14 at 19:59

1 Answers1

1

I was looking for a solution to this as well and decided to write my own:

Curvy text example

function curvytext(xy,str,varargin)
%//
%// Input: 
%//     xy          2-by-n matrix of x (row 1) and y (row 2) coordinates
%//                 describing any 2D path
%//     str         length m string to be plotted
%//     varargin    standard variable arguments for modifying text
%//                 appearance
%//
    if size(xy,1)>2; xy=xy'; end; 
    n = size(xy,2);
    m = length(str);

    XY = spline(1:n,xy,linspace(1,n,m+1));
    dXY = XY(:,2:end)-XY(:,1:end-1);
    theta = (arrayfun(@(y,x) atan2(y,x),dXY(2,:),dXY(1,:)))/2/pi*360;

    XY = (XY(:,1:end-1)+XY(:,2:end))/2;
    plot(XY(1,:),XY(2,:),'k-'); hold on;
    for i=1:m
        text(XY(1,i),XY(2,i),str(i),'rotation',theta(i),...
             'horizontalalignment','center','verticalalignment','bottom',varargin{:});
    end
    axis equal
end

As written in the commented portion of the code, the input xy is a 2-by-n matrix that describes any 2D path. The input str is the text to plot, and varargin allows you to specify any standard Name,Value pairs just as you would using text.

How it works:

spline and linspace(1,n,m+1) together parameterize the curve into m+1 equally spaced pieces, where m is the number of characters in str.

dXY computes the differences between pairs of consecutive points.

arrayfun and atan2 compute the rotation angle (in radians) for each letter.

XY = (XY(:,1:end-1)+XY(:,2:end))/2; averages consecutive pairs of points so that the m letters are plotted in between the m+1 interpolated points.

Then we loop over each character using text and the rotation property (converted to degrees). Notice varargin is fed into the text command.

Geoff
  • 1,202
  • 10
  • 18
  • Your solution is short, elegant, and much simpler than my suggestion. Even though I finally solved the problem with plain C/ImageMagick, your solution definitely solves the problen. Thanks! – Yellows Nov 18 '15 at 10:48
  • @Geoff, I can't get this to provide a curved text along the line: `curvytext([10:20;(10:20).^2],'This is a test')`. See figure here: db.tt/Kr4Bn25H. – TobiasDK Jun 01 '16 at 07:21
  • @TobiasDK the last line of the script, `axis equal`, is important to preserve the aspect ratio. If you're changing the axis after using `curvytext` the letters won't look perpendicular to the curve, even though they technically are. – Geoff Jun 01 '16 at 10:17
  • @TobiasDK one idea if you must have unequal aspect ratio is to add a third input argument before `varargin`, say `c`, that rotates the letters by some additional constant value `c`. By playing with that value you can probably get the desired effect. – Geoff Jun 01 '16 at 10:18
  • @Geoff, thanks for the answer. It will not give me the desired output, so I'll just do it in tikz - LaTeX :-). Good day to you. – TobiasDK Jun 02 '16 at 08:06