Sierpinski curve

From Rosetta Code
Revision as of 16:45, 5 March 2020 by Petelomax (talk | contribs) (Created page with "{{draft task|Fractals}} <br/> ;Task Produce a graphical or ASCII-art representation of a Sierpinski curve of at least order 3. =={{header|Go}}== {...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Sierpinski curve is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.


Task

Produce a graphical or ASCII-art representation of a Sierpinski curve of at least order 3.


Go

Library: Go Graphics
Translation of: Phix

A partial translation anyway which produces a static image of a SSC of level 5, yellow on blue, which can be viewed with a utility such as EOG. <lang go>package main

import (

   "github.com/fogleman/gg"
   "math"

)

var (

   width  = 770.0
   height = 770.0
   dc     = gg.NewContext(int(width), int(height))

)

var cx, cy, h float64

func lineTo(newX, newY float64) {

   dc.LineTo(newX-width/2+h, height-newY+2*h)
   cx, cy = newX, newY

}

func lineN() { lineTo(cx, cy-2*h) } func lineS() { lineTo(cx, cy+2*h) } func lineE() { lineTo(cx+2*h, cy) } func lineW() { lineTo(cx-2*h, cy) }

func lineNW() { lineTo(cx-h, cy-h) } func lineNE() { lineTo(cx+h, cy-h) } func lineSE() { lineTo(cx+h, cy+h) } func lineSW() { lineTo(cx-h, cy+h) }

func sierN(level int) {

   if level == 1 {
       lineNE()
       lineN()
       lineNW()
   } else {
       sierN(level - 1)
       lineNE()
       sierE(level - 1)
       lineN()
       sierW(level - 1)
       lineNW()
       sierN(level - 1)
   }

}

func sierE(level int) {

   if level == 1 {
       lineSE()
       lineE()
       lineNE()
   } else {
       sierE(level - 1)
       lineSE()
       sierS(level - 1)
       lineE()
       sierN(level - 1)
       lineNE()
       sierE(level - 1)
   }

}

func sierS(level int) {

   if level == 1 {
       lineSW()
       lineS()
       lineSE()
   } else {
       sierS(level - 1)
       lineSW()
       sierW(level - 1)
       lineS()
       sierE(level - 1)
       lineSE()
       sierS(level - 1)
   }

}

func sierW(level int) {

   if level == 1 {
       lineNW()
       lineW()
       lineSW()
   } else {
       sierW(level - 1)
       lineNW()
       sierN(level - 1)
       lineW()
       sierS(level - 1)
       lineSW()
       sierW(level - 1)
   }

}

func squareCurve(level int) {

   sierN(level)
   lineNE()
   sierE(level)
   lineSE()
   sierS(level)
   lineSW()
   sierW(level)
   lineNW()
   lineNE() // needed to close the square in the top left hand corner

}

func main() {

   dc.SetRGB(0, 0, 1) // blue background
   dc.Clear()
   level := 5
   cx, cy = width/2, height
   h = cx / math.Pow(2, float64(level+1))
   squareCurve(level)
   dc.SetRGB255(255, 255, 0) // yellow curve
   dc.SetLineWidth(2)
   dc.Stroke()
   dc.SavePNG("sierpinski_square_curve.png")

}</lang>

Julia

Modified from Craft of Coding blog, Processing version <lang Julia>using Luxor

function sierpinski_curve(x0, y0, h, level)

   x1, y1 = x0, y0
   lineto(x, y) = begin line(Point(x1, y1), Point(x, y), :stroke); x1, y1 = x, y end
   lineN() = lineto(x1,y1-2*h)
   lineS() = lineto(x1,y1+2*h)
   lineE() = lineto(x1+2*h,y1)
   lineW() = lineto(x1-2*h,y1)
   lineNW() = lineto(x1-h,y1-h)
   lineNE() = lineto(x1+h,y1-h)
   lineSE() = lineto(x1+h,y1+h)
   lineSW() = lineto(x1-h,y1+h)
   function drawN(i)
       if i == 1
           lineNE(); lineN(); lineNW()
       else
           drawN(i-1); lineNE(); drawE(i-1); lineN(); drawW(i-1); lineNW(); drawN(i-1)
       end
   end
   function drawE(i)
       if i == 1
           lineSE(); lineE(); lineNE()
       else
           drawE(i-1); lineSE(); drawS(i-1); lineE(); drawN(i-1); lineNE(); drawE(i-1)
       end
   end
   function drawS(i)
       if i == 1
           lineSW(); lineS(); lineSE()
       else
           drawS(i-1); lineSW(); drawW(i-1); lineS(); drawE(i-1); lineSE(); drawS(i-1)
       end
   end
   function drawW(i)
       if i == 1
           lineNW(); lineW(); lineSW()
       else
           drawW(i-1); lineNW(); drawN(i-1); lineW(); drawS(i-1); lineSW(); drawW(i-1)
       end
   end
   function draw_curve(levl)
       drawN(levl); lineNE(); drawE(levl); lineSE()
       drawS(levl); lineSW(); drawW(levl); lineNW()
   end
   draw_curve(level)

end

Drawing(800, 800) sierpinski_curve(10, 790, 3, 6) finish() preview() </lang>

Phix

Library: pGUI

<lang Phix>-- demo\rosetta\Sierpinski_curve.exw -- -- Draws curves lo to hi (simultaneously), initially {1,1}, max {8,8} -- Press +/- to change hi, shift +/- to change lo. -- ("=_" are also mapped to "+-", for the non-numpad +/-) -- include pGUI.e

Ihandle dlg, canvas cdCanvas cddbuffer, cdcanvas

integer width, height,

       lo = 1, hi = 1

atom cx, cy, h

procedure lineTo(atom newX, newY)

   cdCanvasVertex(cddbuffer, newX-width/2+h, height-newY+2*h)
   cx = newX
   cy = newY

end procedure

procedure lineN() lineTo(cx,cy-2*h) end procedure procedure lineS() lineTo(cx,cy+2*h) end procedure procedure lineE() lineTo(cx+2*h,cy) end procedure procedure lineW() lineTo(cx-2*h,cy) end procedure

procedure lineNW() lineTo(cx-h,cy-h) end procedure procedure lineNE() lineTo(cx+h,cy-h) end procedure procedure lineSE() lineTo(cx+h,cy+h) end procedure procedure lineSW() lineTo(cx-h,cy+h) end procedure

procedure sierN(integer level)

  if level=1 then
     lineNE()  lineN()
     lineNW()
  else
     sierN(level-1)  lineNE()
     sierE(level-1)  lineN()
     sierW(level-1)  lineNW()
     sierN(level-1) 
  end if

end procedure

procedure sierE(integer level)

  if level=1 then
     lineSE()  lineE()
     lineNE() 
  else
     sierE(level-1)  lineSE()
     sierS(level-1)  lineE()
     sierN(level-1)  lineNE()
     sierE(level-1) 
  end if

end procedure

procedure sierS(integer level)

  if level=1 then
     lineSW()  lineS()
     lineSE() 
  else
     sierS(level-1)  lineSW()
     sierW(level-1)  lineS()
     sierE(level-1)  lineSE()
     sierS(level-1) 
  end if

end procedure

procedure sierW(integer level)

  if level=1 then
     lineNW()  lineW()
     lineSW() 
  else
     sierW(level-1)  lineNW()
     sierN(level-1)  lineW()
     sierS(level-1)  lineSW()
     sierW(level-1) 
  end if

end procedure

procedure sierpinskiCurve(integer level)

  sierN(level)     lineNE()
  sierE(level)     lineSE()
  sierS(level)     lineSW()
  sierW(level)     lineNW()

end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, integer /*posy*/)

   {width, height} = IupGetIntInt(canvas, "DRAWSIZE")
   cdCanvasActivate(cddbuffer)
   for level=lo to hi do
       cx = width/2
       cy = height
       h = cx/power(2,level+1)
       cdCanvasBegin(cddbuffer, CD_CLOSED_LINES)
       sierpinskiCurve(level)
       cdCanvasEnd(cddbuffer)
   end for
   cdCanvasFlush(cddbuffer)
   return IUP_DEFAULT

end function

function map_cb(Ihandle ih)

   cdcanvas = cdCreateCanvas(CD_IUP, ih)
   cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
   cdCanvasSetBackground(cddbuffer, CD_WHITE)
   cdCanvasSetForeground(cddbuffer, CD_BLUE)
   return IUP_DEFAULT

end function

function key_cb(Ihandle /*ih*/, atom c)

   if c=K_ESC then return IUP_CLOSE end if
   if find(c,"+=-_") then
       bool bShift = IupGetInt(NULL,"SHIFTKEY")
       if c='+' or c='=' then
           if bShift then
               lo = min(lo+1,hi)
           else
               hi = min(8,hi+1)
           end if
       elsif c='-' or c='_' then
           if bShift then
               lo = max(1,lo-1)
           else
               hi = max(lo,hi-1)
           end if
       end if
       IupSetStrAttribute(dlg, "TITLE", "Sierpinski curve (%d..%d)",{lo,hi})
       cdCanvasClear(cddbuffer)
       IupUpdate(canvas)
   end if
   return IUP_CONTINUE

end function

procedure main()

   IupOpen()
   
   canvas = IupCanvas(NULL)
   IupSetAttribute(canvas, "RASTERSIZE", "770x770")
   IupSetCallback(canvas, "MAP_CB", Icallback("map_cb"))
   IupSetCallback(canvas, "ACTION", Icallback("redraw_cb"))
   dlg = IupDialog(canvas)
   IupSetAttribute(dlg, "TITLE", "Sierpinski curve (1..1)")
   IupSetCallback(dlg, "K_ANY", Icallback("key_cb"))
   IupMap(dlg)
   IupShowXY(dlg,IUP_CENTER,IUP_CENTER)
   IupMainLoop()
   IupClose()

end procedure

main()</lang>