9

I am trying to get the union of four circles in asymptote:

unitsize(1mm);
import graph;
pair o1 = (0, 0);
pair o2 = (10, 0);
pair o3 = (10, 10);
pair o4 = (0, 10);
path c1 = Circle(o1, 10);
path c2 = Circle(o2, 10);
path c3 = Circle(o3, 10);
path c4 = Circle(o4, 10);
draw(c1^^c2^^c3^^c4, black);

Apparently this is not the right way:

enter image description here

Using inkscape I can get the desired effect:

enter image description here

@g.kov 's answer partially solves the problem, but if the paths are not consecutively intersecting, then buildcycle will not work:

unitsize(1mm);
import graph;
pair o1 = (0, 0);
pair o2 = (10, 0);
pair o3 = (10, 10);
pair o4 = (0, 10);
path c1 = Circle(o1, 8);
path c2 = Circle(o2, 8);
path c3 = Circle(o3, 1);
path c4 = Circle(o4, 1);

guide[] gg=c1^^c2^^c3^^c4;
guide g=gg[0];
for(int i=1;i<gg.length;++i){
  g=buildcycle(g,gg[i]);
}

draw(g,black);

This outputs nothing, while what I wanted is this (output from inkscape):

enter image description here

The reason I am checking out asymptote is that it's a programming language and should be much more powerful when the number of paths increase to a higher order.

qed
  • 708
  • I do not have the answer but relevant examples can be found here: http://asy.gmaths.net/forum/demandes-d-aide-f15/comment-arranger-ca-t322.html It looks to me that you should have a look at the following asymptote commands: buildcycle and intersection – pluton Oct 28 '13 at 21:51
  • Documentation on intersection: Return all (unless there are infinitely many) intersection times of paths p and q as a sorted array of real arrays of length 2, what is intersection times? – qed Oct 28 '13 at 22:40
  • What exactly you think is wrong with your second picture? It still shows the outline of the four circles, three big and one small. – g.kov Oct 28 '13 at 22:42
  • You mean the third picture? I have removed it. Yeah, it's actually ok because I still got four circles consecutively intersecting. I have changed the code, you can try it, it outputs nothing at all. – qed Oct 28 '13 at 22:47
  • @g.kov I have edited the post and added a picture from inkscape – qed Oct 28 '13 at 22:55
  • @qed: In Asympote, every path p has a built-in parametrization; the point at time t is given by the function point(p,t). Each row (column?) of the matrix returned by intersection(p,q) consists of two reals, which identify the same point by its path time on q and p, respectively. In particular, p and q intersect iff intersection(p,q).length > 0. – Charles Staats Oct 28 '13 at 23:56

1 Answers1

9

Consequent buildcycle commands can be used in this case:

unitsize(1mm);
import graph;
pair o1 = (0, 0);
pair o2 = (10, 0);
pair o3 = (10, 10);
pair o4 = (0, 10);
path c1 = Circle(o1, 10);
path c2 = Circle(o2, 10);
path c3 = Circle(o3, 10);
path c4 = Circle(o4, 10);

guide[] gg=c1^^c2^^c3^^c4;
guide g=gg[0];
for(int i=1;i<gg.length;++i){
  g=buildcycle(g,gg[i]);
}

filldraw(g,palegreen,deepblue);

enter image description here

Edit:

Well, the second case is a little more complicated than the original one. This modified code seems to work in this case:

unitsize(1mm);
import graph;
pair o1 = (0, 0);
pair o2 = (10, 0);
pair o3 = (10, 10);
pair o4 = (0, 10);

path c1 = Circle(o1, 8);
path c2 = Circle(o2, 8);
path c3 = Circle(o3, 1);
path c4 = Circle(o4, 1);

guide[] gg=c1^^c2^^c3^^c4;
int[] ind2del;
int j=0;
bool flag=true;
while(flag){
  flag=false;
  ind2del.delete();
  for(int i=j+1;i<gg.length;++i){
    if(intersect(gg[j],gg[i]).length>0){
      gg[j]=buildcycle(gg[j],gg[i]);
      ind2del.push(i);
      flag=true;
    }
  }
  for(int i=ind2del.length-1;i>=0;--i)gg.delete(ind2del[i]);
  ++j;
  if(j<gg.length){
    flag=true;
  }else{
    j=0;
  }
}

filldraw(gg,palegreen,deepblue);

enter image description here

g.kov
  • 21,864
  • 1
  • 58
  • 95
  • According to the documentation: This returns the path surrounding a region bounded by a list of two or more consecutively intersecting paths, following the behaviour of the MetaPost buildcycle command. What if they are not consecutively intersecting? – qed Oct 28 '13 at 22:24
  • @qed: see edited code – g.kov Oct 28 '13 at 23:52
  • What exactly does the ^^ operator do? – qed Oct 29 '13 at 17:39
  • 1
    @qed: From the docs: The ^^ binary operator, which requests that the pen be moved (without drawing or affecting endpoint curvatures) from the final point of the left-hand path to the initial point of the right-hand path, may be used to group several Asymptote paths into a path[] array (equivalent to a PostScript path) – g.kov Oct 29 '13 at 18:59
  • Cool. I have look all over the site and didn't find this one. Could you please post the link to that page? Also, suppose I have 1000 paths, how can I group them into an array? i.e. p1^^p2^^...^^p1000 . – qed Oct 30 '13 at 09:57
  • @qed:It's on page 12 in more-or-less recent main doc file asymptote.pdf, just where the first occurence of the search string ^^ is found. If it somehow happened that you miss this file, you can get it from
    http://asymptote.sourceforge.net/asymptote.pdf.
    – g.kov Oct 30 '13 at 10:45
  • If I change the radii a little bit, then the iterative buildcycle does not work anymore. For example: path c3 = Circle(o3, 4); path c4 = Circle(o4, 4); – qed Oct 30 '13 at 11:55