六角形のフラクタル図形 kotlin 版 を書きました。2023-02-04 更新
コードが少し長いのですが、ここにメモしておきます。
class SvgUtils {
def createXYWH = { bounds->
def sb = ''<<''
sb.append("x=\"").append( bounds.x ).append("\" ")
sb.append("y=\"").append( bounds.y ).append("\" ")
sb.append("width=\"").append( bounds.width ).append("\" ")
sb.append("height=\"").append( bounds.height ).append("\" ")
sb.toString()
}
def createViewBox = { bounds->
def sb = ''<<''
sb.append("viewBox=\"").append( bounds.x ).append(" ").append( bounds.y ).append(" ").append( bounds.width ).append(" ").append( bounds.height ).append("\"");
sb.toString()
}
def createSVGHeader = { viewBoxBounds1, viewBoxBounds2->
def br = System.getProperty('line.separator')
def sb = ''<<''
sb << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
sb << br
sb << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
sb << br
sb << "<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" "
sb << br
sb << createXYWH(viewBoxBounds1)
sb << " "
sb << createViewBox(viewBoxBounds2)
sb << ">"
sb << "<g style=\"stroke:rgb(0,0,0)\" stroke-width=\"1\" fill=\"black\">"
sb << "<rect x=\"${viewBoxBounds2.x}\" y=\"${viewBoxBounds2.y}\" width=\"${viewBoxBounds2.width}\" height=\"${viewBoxBounds2.height}\"/>"
sb << "</g>"
sb.toString()
}
def createSVGFooter = {
'</svg>'
}
}
class AwtUtils {
private def random = new Random()
def createRandomValue(){
int minimumValue = 64
int max = 255 - minimumValue
Math.abs(random.nextInt() % max) + minimumValue
}
def createRandomColor(){
int r = createRandomValue()
int g = createRandomValue()
int b = createRandomValue()
[red:r,green:g,blue:b]
}
def createPoint = {x,y-> [x:x,y:y] }
def createRectangle = { x,y,width,height-> [x:x,y:y,width:width,height:height] }
def centerPoint = { rectangle->
def x = rectangle.x + rectangle.width/2f
def y = rectangle.y + rectangle.height/2f
createPoint(x,y)
}
// calc each vertex of a honeycomb
def createPoints = { rectangle->
def centerPt = centerPoint(rectangle)
def vertexes = 6
def radius=Math.min(rectangle.width,rectangle.height)/2.0f
def angle = 2 * Math.PI/vertexes
def pointList = []
(0..(vertexes-1)).each{
def x = radius*Math.sin(angle*it)
def y = radius*Math.cos(angle*it)*(-1)
// translate
x = x + centerPt.x
y = y + centerPt.y
pointList.add( createPoint(x,y) )
}
pointList
}
}
class HoneycombsMaker {
def sb
def awtUtils
HoneycombsMaker(){
sb = ''<<''
awtUtils=new AwtUtils()
}
// 指定した点を中心に半径r の(円に入る)六角形を描写 色は c で指定
void createHoneycomb(Map centerPt, float r, Map c, float scale ){
def myCreatePoints = { left,top,right,bottom->
def x = left
def y = top
def w = right -left
def h = bottom -top
def points = awtUtils.createPoints( awtUtils.createRectangle( x,y,w,h ) )
points
}
def myR = r * scale
def left = centerPt.x -myR
def top = centerPt.y -myR
def right = centerPt.x +myR
def bottom = centerPt.y +myR
sb << "<g style=\"stroke:rgb(${c.red},${c.green},${c.blue})\" stroke-width=\"1\" fill=\"none\">"
sb << "<path d=\""
myCreatePoints(left,top,right,bottom).eachWithIndex{ pt,index->
if( index==0 ) sb << "M${pt.x},${pt.y}"
else sb << "L${pt.x},${pt.y}"
}
sb << ' z"/>' // z ... close path
sb << '</g>'
if( r>5f ){
def left2 = centerPt.x -r
def top2 = centerPt.y -r
def right2 = centerPt.x +r
def bottom2 = centerPt.y +r
def c2 = awtUtils.createRandomColor()
myCreatePoints(left2,top2,right2,bottom2).each { pt->
sb << createHoneycomb( [x:pt.x,y:pt.y],(r*scale as float),c2, scale)
}
}
}
}
def canvasW = 640
def canvasH = 640
def scale = 0.32f
def svgUtils = new SvgUtils()
def awtUtils = new AwtUtils()
def paperRect = awtUtils.createRectangle( 0,0,canvasW,canvasH )
def viewBoxRect = awtUtils.createRectangle( 0,0,canvasW,canvasH )
def br = System.getProperty('line.separator')
def sb = ''<<''
sb << svgUtils.createSVGHeader( paperRect,viewBoxRect )
sb << br
def c = awtUtils.createRandomColor()
def maker = new HoneycombsMaker()
maker.createHoneycomb(
[x:canvasW/2f,y:canvasH/2f],
(Math.min(canvasW, canvasH)*scale) as Integer,
c,
scale )
sb << maker.sb.toString()
sb << br
sb << svgUtils.createSVGFooter()
new File('result.svg').text = sb.toString()