Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a quite intricate question... I have to plot a torus of radii (r,R) with two set of points of different colour on it its surface. The points' coordinates are in two different files that must be properly «incorporated». Finally I have to connect with an arch first point of a type with the first point of the other type, the second point with the second one and so on (the order being determined by their positions in the respective files), the arch being the geodesic on the toroidal surface...

Any suggestion?

share|improve this question
Does this help? –  Philipp Jan 29 '14 at 12:44
@Philipp: The arches in that picture would be geodesic on the "flat" torus, but not on the torus embedded in R^3. –  Charles Staats Jan 29 '14 at 16:04
A couple of comments. First, it would help to know how your coordinates are specified. Are they given as points in 3-space, or points in a rectangle (the domain of a parametrization), or some other format? Second, asking for a geodesic arc on a torus embedded in R^3 is a fairly complex mathematical question, and I doubt you will find any drawing-oriented program with a built-in method to compute this for you. Do you really need the arcs to be geodesic, or just "reasonable"? –  Charles Staats Jan 29 '14 at 16:10
Hi guys. Firstly, thank you for your answers. @Philipp the code helps a lot for drawing the torus, but I am totally unfamiliar with Asymptote unfortunately and I have to import (a lot of) points. I think however that I will use it to draw the donut :) Thanks again. –  user44990 Jan 30 '14 at 16:49
@CharlesStaats I need a sort of geodetic on the flat torus (sorry I write not clearly) and a reasonable solution is fine! The points are in the form x y where x and y are the coordinates in the rectangle, domain of parametrization. However I can clearly recompute their coordinates in another form, if necessary. –  user44990 Jan 30 '14 at 16:50

1 Answer 1

Here is an Asymptote solution that first creates files containing the data (random points), then imports the data from those files, and then creates the desired image. Hopefully you can adapt it to your needs.

This version is rasterized; by adapting the code from my solution here, it may be possible to produce a vector graphic solution if you can avoid an out-of-memory error.

Note that the "geodesics" are geodesic on the flat torus, but not on the actual surface embedded in three-space.

/* Create two human-readable files, each containing 40 random numbers between 0 and 1. */
file fout1 = output("torus_points_type1.txt");
file fout2 = output("torus_points_type2.txt");
for (int i = 0; i < 20; ++i) {
  write(fout1, " ", unitrand(), unitrand());
  write(fout1, endl);

  write(fout2, " ", unitrand(), unitrand());
  write(fout2, endl);


/* Read the files into arrays of points. */

pair[] type1pts, type2pts;

file type1 = input("torus_points_type1.txt").line();
file type2 = input("torus_points_type2.txt").line();

real[] temp;
while(!eof(type1) && !eof(type2)) {
  temp = type1;
  type1pts.push((temp[0], temp[1]));
  temp = type2;
  type2pts.push((temp[0], temp[1]));


/* Now, do the actual drawings. */


import graph3;

triple eye = (10,1,4);

int nu = 40, nv = 32;
surface torus = surface(Circle(c=2Y, r=0.6, normal=X, n=nv), c=O, axis=Z, n=nu);

/* The following line is irrelevant unless you want to embed
   an interactive image in a pdf file. */

draw(torus, surfacepen=emissive(white + opacity(0.6)));

/* Reparametrize over [0,1] x [0,1] */
triple torusPoint(real u, real v) {
  return torus.point(nu*u, nv*v);
triple torusPoint(pair uv) {
  return torusPoint(uv.x, uv.y);

pen gridpen = linewidth(0.3pt) + gray;

int n = 40;
for (int i = 0; i < n; ++i) {
  real u = i/n;
  triple f(real v) {
    return torusPoint(u,v);
  draw(graph(f, 0, 1, n=40, operator..) .. cycle, p=gridpen);

n = 20;
for (int i = 0; i < n; ++i) {
  real v = i/n;
  triple f(real u) {
    return torusPoint(u,v);
  draw(graph(f, 0, 1, n=16, operator..) .. cycle, p=gridpen);

/* Make parampath an alias for triple(real). */
typedef triple parampath(real);

parampath _torusGeodesic(pair a, pair b) {
  return new triple(real t) {
    return torusPoint((1-t)*a + t*b);
path3 torusGeodesic(pair a, pair b) {
  return graph(_torusGeodesic(a,b), 0, 1, n=40, operator..);

for (int i = 0; i < type1pts.length; ++i) {
  pair a = type1pts[i];
  dot(torusPoint(a), heavyblue);
  pair b = type2pts[i];
  for (int du = -1; du <= 1; ++du) {
    for (int dv = -1; dv <= 1; ++dv) {
      pair bprime = b + (du,dv);
      if (length(bprime-a) < length(b-a)) b = bprime;
  dot(torusPoint(b), heavyred);
  draw(torusGeodesic(a,b), 0.1*red + 0.2*blue);

The result:

enter image description here

share|improve this answer
Sorry. I forgot the link of your Asymptote tutorial, where is it? Thanks. :-) –  please stop stalking Jan 31 '14 at 8:03
@Code Mocker: The tutorial in question may be found, for now, at this website. Note that I found this address quickly by googling "Asymptote tutorial." –  Charles Staats Jan 31 '14 at 13:12

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.