# SVG Weave/Crosshatching Pattern Generator

```require 'matrix' class Vector   def pair_mult(v)     map2(v) do |x1, x2|       x1*x2     end   end end BOX_SIZE=Vector[10,10] BOX_COUNT=Vector[8,8] BOX_SHIFT=Vector[1.5,1.5] PATTERN_SIZE=BOX_SIZE.pair_mult(BOX_COUNT) LINES=4 def moveto(p)   "M #{p[0]} #{p[1]}" end def lineto(p)   "L #{p[0]} #{p[1]}" end def envelope_lines(a,b,c,d,lines)   step1=(b-a)*(1.0/(lines+1))   step2=(d-c)*(1.0/(lines+1))   result=[]     lines.times do |i|     result<< moveto(a+step1*(i+1))     result<< lineto(c+step2*(i+1))   end   return result.join " " end points=Array.new(BOX_COUNT[1]) do |j|   row=Array.new(BOX_COUNT[0]) do |i|     Vector[i,j].pair_mult(BOX_SIZE)+Vector[2*rand-1, 2*rand-1].pair_mult(BOX_SHIFT)   end   row<< row[0]+Vector[PATTERN_SIZE[0],0] # Last point is the first point shifted by the width of the whole pattern end # Last row is the first row shifted by the height of the whole pattern points<< points[0].map {|p| p+Vector[0,PATTERN_SIZE[1]]} result="" BOX_COUNT[1].times do |j|   BOX_COUNT[0].times do |i|     a=points[j][i]     b=points[j][i+1]     c=points[j+1][i]     d=points[j+1][i+1]     a,b,c,d=a,c,b,d if (i+j)%2==0 # Swap vertical and horizontal in alternating boxes     result+=envelope_lines(a,b,c,d,LINES)   end end puts <<EOS <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"   "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="4cm" height="4cm" viewBox="0 0 #{PATTERN_SIZE[0]} #{PATTERN_SIZE[1]} "     xmlns="http://www.w3.org/2000/svg" version="1.1">     <defs> <pattern id="weave" patternUnits="userSpaceOnUse"             x="0" y="0" width="#{PATTERN_SIZE[0]}" height="#{PATTERN_SIZE[1]}">     <path stroke="black" d="#{result}" stroke-width="1" />           </pattern>   </defs>   <rect fill="url(#weave)" x="0" y="0" width="#{PATTERN_SIZE[0]}" height="#{PATTERN_SIZE[1]}" /> </svg> EOS```