• fullscreen
  • tiles_star.pde
  • // do some stuff
    
    // Convert pattern to stars, using something like the Hankin method.
    // To do: add line separation...
    
    Vector  polys;
    
    boolean isInteractive = false; // turn off when you've found a good ratio for this tiling...
    
    float minx=10000, maxx=-10000, miny=10000, maxy=-10000;
    float dxs = 1;
    float dys = 1;
    float lm = 10;
    float tm = 10;
    float ratio = 1;
    float angStar = (2*PI)/18;  // 30 degrees
    float edgeDist = .1;
    float starEdge = 1000;
    
    void setup()
    {
      size(600,600);
      colorMode(RGB, 1);
      smooth();
      strokeWeight(2);
      //   noLoop();
      polys = new Vector();
      ReadFile("altair1.txt");
    }
    
    void draw()
    {
    
      angStar = .001 + (float) mouseX/width*PI;
      edgeDist = (float) mouseY/height;
      // println("angstar = " + angStar  + " lm = " + lm);
    //    println("ratio = " + ratio);
    //  }
      background(.5);
      for (int i = 0; i < polys.size(); ++i) {
        Poly poly = (Poly) polys.elementAt(i);
        poly.doDraw();
      }
    }
    
    void ReadFile(String vFileName)
    {
      Vector vipts = new Vector();
      String lines[] = loadStrings(vFileName);
      for (int i = 0; i < lines.length; ++i) {
          if (lines[i].length() < 3)
            continue;
          String nums[] = lines[i].split(",");
          for (int j = 0; j < nums.length; ++j) {
            if (nums[j].substring(0,1).equals(" "))
              nums[j] = nums[j].substring(1);
            if (nums[j].length() > 0)
              vipts.addElement(new Float(float(nums[j])));
          }
        }
        polys = new Vector();
        float[] ipts;
        ipts = new float[vipts.size()];
        println("loaded " + vipts.size() + " points");
        for (int i = 0; i < vipts.size(); ++i) {
          ipts[i] = ((Float) vipts.elementAt(i)).floatValue();
        }
    
        for (int i = 0; i < vipts.size(); ) 
        {
          int nbrSides = (int) ipts[i++];
          Poly poly = new Poly(nbrSides);
          for (int j = 0; j < nbrSides; ++j) {
            poly.AddDot(ipts[i+j*2],ipts[i+j*2+1]);
          }
          i += nbrSides*2;
          polys.addElement(poly);
        }
        println("loaded " + polys.size() + " polys");
        dxs = (width-lm*2)/(float)(maxx-minx);
        dys = (height-tm*2)/(float)(maxy-miny);    
    
    }
    
    
    class Point
    {
      float x,y;
      Point(float x, float y)
      {
        this.x = x;
        this.y = y;
        if (x < minx)  minx = x;
        if (x > maxx)  maxx = x;
        if (y < miny)  miny = y;
        if (y > maxy)  maxy = y;
      }  
    }
    
    // this crashes in certain situations...
    Point intersection(float x1,float y1,float x2,float y2, 
       float x3, float y3, float x4,float y4 ) 
       {
        float d = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4);
        try {
    //      float xi = ((x3-x4)*(x1*y2-y1*x2)-(x1-x2)*(x3*y4-y3*x4))/d;
    //      float yi = ((y3-y4)*(x1*y2-y1*x2)-(y1-y2)*(x3*y4-y3*x4))/d;
          float denom = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
          float numea = (x4-x3)*(y1-y3) - (y4-y3)*(x1-x3);
          float numeb = (x2-x1)*(y1-y3) - (y2-y1)*(x1-x3);
          if (abs(denom) < 0.01) {
            if (numea == 0.0 && numeb == 0.0)
            {
                // coincident
                println("c");
                return new Point ( x1, y1 );
            }
            else {
                // parallel
                println("p");
                return null;
            }
          }
          float ua = numea / denom;
          float ub = numeb / denom;
          if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
          {
            float xi = x1 + ua*(x2-x1);
            float yi = y1 + ua*(y2-y1);
            if (xi > 0 && xi < width && yi > 0 && yi < width)
              return new Point(xi,yi);
            else
              return null;
          }
          else {
            // not intersecting - this works well...
            return new Point (x1, y1 );
          }
        }
        catch (Exception e)
        {
          println("e");
          return null;
        }  
    }
    
    class Poly
    {
      Vector  pts;
      int nbrSides;
      
      Poly(int nbrSides)
      {
        this.nbrSides = nbrSides;
        this.pts = new Vector();
      }
      
      void AddDot(float x, float y)
      {
        pts.add( new Point(x,y) );
      }
      
      void doDraw()
      {
        if (outsideBorder())
        {
          fill(.5);
          return;
        }
        else
          fill(1);
        
        float r = sin(nbrSides*PI*2/8.0);
        float g = sin(nbrSides*PI*2/8.0+2);
        float b = sin(nbrSides*PI*2/8.0+4);
        fill  (.9+r*.1, .9+g*.1, .9+b*.1);
        stroke(.8+r*.1, .8+g*.1, .8+b*.1);
    
        String outStr = nbrSides +",";
        beginShape();
        
        for (int i = 0; i <= nbrSides; ++i) {
          Point pt = (Point) pts.elementAt(i % nbrSides);
          vertex( tx(pt.x), ty(pt.y) );
          if (i < nbrSides)
            outStr += pt.x + "," + pt.y + ",";
        }
        endShape();
        // println(outStr);
    
        stroke(0);
    
        float cx = 0;
        float cy = 0;
        for (int i = 0; i < nbrSides; ++i) {
          Point pt = (Point) pts.elementAt(i % nbrSides);
          cx += tx(pt.x);
          cy += ty(pt.y);
        }
        cx /= nbrSides;
        cy /= nbrSides;
        for (int i = 0; i < nbrSides; ++i) {
           Point p1 = (Point) pts.elementAt(i % nbrSides);
           Point p2 = (Point) pts.elementAt((i+1) % nbrSides);
           Point p3 = (Point) pts.elementAt((i+2) % nbrSides);
           // Draw segment that starts at midpoint of p2,p1 and goes at angle p2,p1 + (PI-angStar)/2
           // to the point where it intersects segment that starts at midpoint of p2,p3 and goes at angle p2,p3-(PI-angStar)/2
           float mx1 = (p1.x + p2.x)/2;
           float my1 = (p1.y + p2.y)/2;
           mx1 += (p1.x - p2.x)*edgeDist;
           my1 += (p1.y - p2.y)*edgeDist;
           float mx2 = (p3.x + p2.x)/2;
           float my2 = (p3.y + p2.y)/2;
           mx2 += (p3.x - p2.x)*edgeDist;
           my2 += (p3.y - p2.y)*edgeDist;
           float ang1 = atan2(p2.y-p1.y,p2.x-p1.x) + (PI-angStar)/2;
           float ang2 = atan2(p2.y-p3.y,p2.x-p3.x) - (PI-angStar)/2;
           float ex1 = mx1+cos(ang1)*starEdge;
           float ey1 = my1+sin(ang1)*starEdge;
           float ex2 = mx2+cos(ang2)*starEdge;
           float ey2 = my2+sin(ang2)*starEdge;
           Point ip = intersection(mx1,my1,ex1,ey1,mx2,my2,ex2,ey2);
           if (ip == null)
             continue;
           line(tx(mx1),ty(my1), tx(ip.x), ty(ip.y));
           line(tx(mx2),ty(my2), tx(ip.x), ty(ip.y));
           // Find point where these lines intersect, and draw line from mx1,my1 ix,iy   and mx2,my2,ix,iy
        }
      }
    
      boolean outsideBorder()
      {
        float cx = 0;
        float cy = 0;
        for (int i = 0; i < nbrSides; ++i) {
          Point pt = (Point) pts.elementAt(i % nbrSides);
          cx += tx(pt.x);
          cy += ty(pt.y);
        }
        cx /= nbrSides;
        cy /= nbrSides;
        float dx = cx - width/2;
        float dy = cy - height/2;
        return sqrt(dx*dx + dy*dy) > ratio*width/2 ;
      }
    }
    
    float tx(float x)
    {
      return (x - minx)*dxs + lm;
    }
    
    float ty(float y)
    {
      return (y - miny)*dys + tm;
    }
    
    void myLine(float x1, float y1, float x2, float y2)
    {
      line(tx(x1),ty(y1),tx(x2),ty(y2));
    }
    
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement


    Jim Bumgardner (KrazyDad)

    Islamic Stars

    Add to Faves Me Likey@! 27
    You must login/register to add this sketch to your favorites.

    Move the mouse horizontally and vertically to change the image. X and Y control two different parameters.

    This was an experiment with a method used to produce Arabic/Islamic star tiling patterns, from an underlying grid of polygons.

    Starting with an underlying grid of polygons, the star pattern is produced by drawing lines from two equidistant points on each polygon edge at some fixed angle (controlled by the mouse). At the point where the lines would intersect with other lines, they are clipped.

    Y controls the distance from the center of the polygon edge.
    X controls angle.

    Evelyn Eastmond
    20 Mar 2009
    I've been experimenting with Islamic tiling in Processing. This is very inspiring, thank you so much for sharing it and the source code!
    Note: The data folder contains some alternate tilings. You can experiment with them by changing the line that reads

    ReadFile("altair1.txt");

    I used this tiling to produce the Slitherlink puzzles on my website (which were constructed in Processing).

    http://www.krazydad.com/slitherlink/index.php?fmt=altair

    http://www.krazydad.com/slitherlink/
    Email me at jbum "at" jbum "dot" com for copies of tiling files in the data folder - I forgot they were tucked inside the Jar file...
    this is nice!!
    Elto Desukane
    1 Apr 2012
    Tried to run your code, but no data folder.
    So I get a NullPointerException
    after
    String lines[] = loadStrings(vFileName);
    from
    ReadFile&#40;"altair1.txt"&#41;;
    Tilings can be downloaded here:

    http://krazydad.com/tiles_star.zip
    Paola
    5 Oct 2012
    Hello... thanks for sharing this!
    I was trying to make it work with the "snowflake.txt" example but it gave me some problems apparently in the poly.AddDot(ipts[i+j*2],ipts[i+j*2+1]); line, stating that the "Exception in thread "Animation Thread" java.lang.ArrayIndexOutOfBoundsException: 1536
    at tiles_star.ReadFile&#40;tiles_star.java:95&#41;
    at tiles_star.setup(tiles_star.java:49)"

    I am a complete newbie so I don't know what and where to change it.. assuming that the snowflake has two many sides or points and that is what is wrong...
    And, PLEASE, could you tell me where or how to change the polygon's images (bmp I assume? to text) into matrix data? It would be great if I could try with polygons/images I did on my own... Thank you so much!!!!
    Hi Paola. If you load one of the working tile files into a text editor, e.g. "hexagons.txt", you'll see a series of lines like the following:

    6,320.0,300.0,310.0,317.3205,290.0,317.3205,280.0,300.0,290.0,282.6795,310.0,282.6795,
    6,310.0,317.3205,320.0,300.0,340.0,300.0,350.0,317.3205,340.0,334.641,320.00003,334.641,
    6,290.0,317.3205,310.0,317.3205,320.0,334.641,310.0,351.9615,290.0,351.9615,280.0,334.641,
    6,280.0,300.0,290.0,317.3205,280.0,334.641,260.0,334.641,250.00002,317.3205,260.00003,300.0,

    Each line defines a single polygon in the tiling. The first number on the line is the number of points (6 in this case). The remaining numbers (2 per point) are x,y coordinates. I prepared these files using other processing scripts. It won't be super easy to convert your existing SVG files to this format, unfortunately. You can email me directly at dad (at) krazydad (dot) com.
    hi plz i need help the project give me error at opening it select the word victor ploys at and nothing happen
    i want to make snow flakes am new at processing i ned help thnxx alot
    error called cant find a type or class called ''victor''
    You need to login/register to comment.