Search code examples
javageometrygraphics2d

Determining if an arc contains/covers another arc


I am, first of all, drawing two arcs randomly using the Graphics drawArc and fillArc methods. One arc, say arc1 is bigger than the other arc, say arc2. Now i want to see if arc1, contains(wholly or partly) arc2. I have tried various ways but to no avail. Forexample, first of all calculating the distances between them and then taking the dot product of these two and seeing if its greater than the radius of the first arc multiplied by the cosine of its orientation. Still no success, any help or suggestions offered will be greatly appreciated. Is there a better/another approach to achieve this? Is it also possible to estimate how much of arc2 is covered by arc1? thanks,


Solution

  • I will give you an easy solution that counts for any shape - not only arcs:

      public Vector measureArea(int[] pix) {
        int i;
        Vector v=new Vector();
        for(i=0; i<pix.length; i++)
          if((pix[i]&0x00ffffff)==0x00000000) v.add(i);
        return v;
      }
    

    This finds the pixels that belong to this area: you could fill the arc as follows then call this function:

    BufferedImage bim=new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics g=bim.getGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, w, h);
    g.setColor(Color.black);
    g2.fillArc(x, y, 2*w/16, 2*h/16, 270, 250);
    int[] pix=bim.getRGB(0, 0, w, h, null, 0, w);
    Vector v=measureArea(pix);
    

    Repeat with the second arc then find the common points.

    for(i=0; i<v.size(); i++) {
      int I=((Integer)v.get(i)).intValue();
      for(j=0; j<v2.size(); j++) {
        int J=((Integer)v2.get(j)).intValue();
        if(I==J) ..... // do something
      }
    }
    

    If you want more of a mathematical approach you have to define the filled arc in terms of circle (or maybe two wedges) and find the area of the intersecting these shapes.

    There is a third approach using Areas in java.

    Area a=new Area(new Arc2D.Double(x+3*w/4-w/16, y+h/4-h/16, 2*w/16, 2*h/16, 270, 250, Arc2D.OPEN));
    Area a2=new Area(new Arc2D.Double(x+3*w/4, y+h/4, 2*w/16, 2*h/16, 270, 200, Arc2D.OPEN));
    Area intrsct=new Area(new Arc2D.Double(x+3*w/4-w/16, y+h/4-h/16, 2*w/16, 2*h/16, 270, 250, Arc2D.OPEN));
    intrsct.intersect(a2);
    

    Now intrsct has the intersection.

    If we expand this to simple Shapes we have:

    Arc2D.Double a=new Arc2D.Double(x+3*w/4-w/16, y+h/4-h/16, 2*w/16, 2*h/16, 270, 250, Arc2D.OPEN);
    Arc2D.Double a2=new Arc2D.Double(x+3*w/4, y+h/4, 2*w/16, 2*h/16, 270, 200, Arc2D.OPEN);
    Rectangle b=a.getBounds();
    int intrsct=0;
    for(i=0; i<b.getWidth(); i++)
    for(j=0; j<b.getHeight(); j++)
      if(a.contains(b.x+i, b.y+j) && a2.contains(b.x+i, b.y+j)) intrsct++;
    

    A fourth approach.

    --

    If you want an arc with a given color you need to check for that color in the first approach. So we change measure area as follows:

      public Vector measureArea(int[] pix, int color) {
        int i;
        Vector v=new Vector();
        int c=color&0x00ffffff;
        for(i=0; i<pix.length; i++)
          if((pix[i]&0x00ffffff)==c) v.add(i);
        return v;
      }
    

    and call it measureArea(pix, Color.red.getRGB()) for example.

    And make sure you clear the image for each shape to be counted on its own:

     public Image init( Graphics g )
        {
             bim=new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
             g=bim.getGraphics();
             g.setColor(Color.yellow);
             g.fillRect(0, 0, w, h);
             g.setColor(Color.red);
             g.fillArc(x, y, 300, 300, 270, 75);  // 2*w/16, 2*h/16 
             int[] pix=bim.getRGB(0, 0, w, h, null, 0, w);
             Vector v1=measureArea(pix, Color.red.getRGB());
             g.setColor(Color.yellow);
             g.fillRect(0, 0, w, h);
             g.setColor(Color.blue);
             g.fillArc(x+100, y+100, 150, 150, 270, 45); //2*w/32, 2*h/32,
             pix=bim.getRGB(0, 0, w, h, null, 0, w);
             Vector v2=measureArea(pix, Color.blue.getRGB());
             System.out.println( intersect(v1, v2) );
             return bim;
        }
    

    Notes 3: the method with Areas is independent of color - use that if it works. The method with pixels can be used later if you have complicated shapes:

    To draw all the shapes together just do what you do now: keep them in one image. To measure the area use another image bim2 where you draw each shape successively call the measure area function clear the image etc - it doesnt have to be shown any where - you have the other image to show all the shapes together. I hope this works.