<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>coolbutuseless</title>
    <link>https://coolbutuseless.github.io/</link>
    <description>Recent content on coolbutuseless</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 29 Jul 2022 18:05:00 +1000</lastBuildDate>
    
	<atom:link href="https://coolbutuseless.github.io/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Toy WASM interpreter in base R</title>
      <link>https://coolbutuseless.github.io/2022/07/29/toy-wasm-interpreter-in-base-r/</link>
      <pubDate>Fri, 29 Jul 2022 18:05:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/29/toy-wasm-interpreter-in-base-r/</guid>
      <description>


&lt;div id=&#34;wasm&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;WASM&lt;/h2&gt;
&lt;p&gt;One of the big buzzes at #RStudioConf2022 was the whiff of serverless “Shiny”
in both python and R by harnessing &lt;a href=&#34;https://en.wikipedia.org/wiki/WebAssembly&#34;&gt;WASM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;WASM (a.k.a. WebAssembly) is a portable binary-code format initially targetted
at running code in a web browser at near-native speeds.&lt;/p&gt;
&lt;p&gt;This post is a small exploration into what a WASM binary actually looks like
and how it is structured.&lt;/p&gt;
&lt;p&gt;I also create a toy interpreter for WASM in R. Note: You would never do this
in real-life - it’s just for a bit of fun (maybe because I had so much fun with the
virtual machine interpreter for &lt;a href=&#34;http://localhost:4321/2022/07/29/anotherworld-game-written-playable-in-r-with-nara-and-eventloop/&#34;&gt;AnotherWorld&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;c-function-to-calculate-factorialn&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;C function to calculate &lt;code&gt;factorial(n)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is a classic bit of C code for calculating &lt;code&gt;n!&lt;/code&gt; i.e. &lt;code&gt;n * (n-1) * (n-2) * ... * 1&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;int factorial(int n) {
  if (n == 0)
    return 1;
  else
    return n * factorial(n-1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;factorialn-in-wat-human-readable-wasm-text&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;factorial(n)&lt;/code&gt; in WAT (human readable WASM text)&lt;/h2&gt;
&lt;p&gt;There is a human-readable version of WASM called “WAT” which has a structure
similar to S-expressions.&lt;/p&gt;
&lt;p&gt;The above C code would be compiled to WASM/WAT as follows:&lt;/p&gt;
&lt;pre class=&#34;wat&#34;&gt;&lt;code&gt;(func (param i64) (result i64)
  local.get 0             # put arg[0] on stack
  i64.eqz                 # compare top of stack to zero
  if (result i64)         # if it is zero
      i64.const 1         # put 1 on stack
  else       
      local.get 0         # put arg[0] on stack
      local.get 0         # put arg[0] on stack
      i64.const 1         # put 1 on stack
      i64.sub             # subtract the top 2 values in stack
      call 0              # Call function #0 (return value is on the stack)
      i64.mul             # Multiply 
  end)&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;compile-wat-to-wasm&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compile WAT to WASM&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/WebAssembly/wabt&#34;&gt;WebAssembly Binary Toolkit (WABT)&lt;/a&gt;
can be used to compile the WAT file into a binary WASM file&lt;/p&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;brew install wabt
wat2wasm helloworld.wat   # Creates &amp;#39;helloworld.wasm&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# helloworld.wasm
00 61 73 6d 01 00 00 00 01 06 01 60 01 7e 01 7e 03 02 01 00 0a 17 01 15 00 20 00 50 04 7e 42 01 05 20 00 20 00 42 01 7d 10 00 7e 0b 0b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;wasm-raw-bytes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;WASM raw bytes&lt;/h2&gt;
&lt;p&gt;With some googling and using the reference list of &lt;a href=&#34;https://webassembly.github.io/spec/core/appendix/index-instructions.html&#34;&gt;WASM bytecodes&lt;/a&gt;
it is possible to deconstruct and understand the bytes in the &lt;code&gt;*.wasm&lt;/code&gt; file for
the &lt;code&gt;factorial(n)&lt;/code&gt; function&lt;/p&gt;
&lt;pre class=&#34;wasm&#34;&gt;&lt;code&gt;  0x00, 0x61, 0x73, 0x6D, # magick = \0asm
  0x01, 0x00, 0x00, 0x00, # version = 1
  
  # The &amp;#39;type&amp;#39; section contains function signatures.
  0x01, 0x06 ,     # section &amp;quot;type&amp;quot;. 6 bytes
  0x01,            # Num types = 1 i.e. just a single &amp;#39;function&amp;#39; type defined here
  0x60,            # Function (begin definition)
  0x01,            # Number of parameters = 1
  0x7e,            #  param types: i64
  0x01,            # Number of results = 1
  0x7e,            #  result types: i64
  
  # The &amp;#39;function&amp;#39; section stores indexes of the function signature
  0x03, 0x02,      # section &amp;quot;function&amp;quot;. section size = 2 bytes
  0x01,            # Number of functions
  0x00,            # Index of function
  
  # The &amp;#39;code&amp;#39; section contains the actual function code
  0x0A, 0x17,      # Section &amp;quot;code&amp;quot;.  section size = 0x17 = 23 bytes
  0x01,            # Number of functions = 1 
  0x15,            # Function body size = 0x15 = 21 bytes
  0x00,            # Number of local declarations = 0
  0x20, 0x00,      #   local.get 0
  0x50,            #   i64.eqz
  0x04, 0x7E,      #   if i64
  0x42, 0x01,      #     i64.const 1
  0x05,            #   else
  0x20, 0x00,      #     local.get 0
  0x20, 0x00,      #     local get 0
  0x42, 0x01,      #     i64.const 1
  0x7D,            #     i64.sub
  0x10, 0x00,      #     call 0
  0x7E,            #     i64.mul
  0x0B,            #   end
  0x0B             # end&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;wasm-virtual-stack-machine&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;WASM virtual stack machine&lt;/h2&gt;
&lt;p&gt;WASM bytecode is intended to be run on a virtual stack machine.&lt;/p&gt;
&lt;p&gt;A simple way of implementing a stack machine in R is to have a giant switch statement
and a stack implementation. The &lt;code&gt;switch&lt;/code&gt; statement chooses what
operations to do based upon the bytecode.&lt;/p&gt;
&lt;p&gt;I’m cheating a little bit here and have hand-parsed the code split at the
if-else statement into two blocks.&lt;/p&gt;
&lt;div id=&#34;other-cheats&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Other cheats:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;you would normally need 64bit integers (i.e. &lt;code&gt;i64&lt;/code&gt; type in WASM) to interpret the &lt;code&gt;factorial()&lt;/code&gt; code
in WASM, but as long as you don’t give it a large number it will be fine.&lt;/li&gt;
&lt;li&gt;integers in WASM are encoded as &lt;a href=&#34;https://en.wikipedia.org/wiki/LEB128&#34;&gt;LEB128 variable length integers&lt;/a&gt;
but since the code sizes are all small, every integer fits in 7-bits which
means that no encoding/decoding is necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;warnings&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Warnings&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This unoptimized interpreter is going to be terribly slow.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;stack&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Stack&lt;/h4&gt;
&lt;p&gt;Stack implementations don’t come much more naive than this.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;stack&lt;/code&gt; variable itself is just going to exist in the global environment.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Naive stack
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stack &amp;lt;- c()

# Pop a value of the stack
stack_pop &amp;lt;- function() {
  res   &amp;lt;- stack[1]
  stack &amp;lt;&amp;lt;- stack[-1]
  res
}

# Push a value on the stack
stack_push &amp;lt;- function(val) {
  stack &amp;lt;&amp;lt;- c(val, stack)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;define-the-functions&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Define the functions&lt;/h4&gt;
&lt;p&gt;The major cheat here is that i’ve pre-parsed the function into initial code
in the function and the two code blocks that are executed depending on
the &lt;code&gt;if/else&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;There may be multiple functions in general, so &lt;code&gt;all_funcs&lt;/code&gt; is a list of
all the functions in the code, and the correct function is extracted
during a &lt;code&gt;call&lt;/code&gt; opcode (i.e. &lt;code&gt;0x10&lt;/code&gt;)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;all_funcs &amp;lt;- list(
  func &amp;lt;- list(
    args = c(),
    start = c(
      0x20, 0x00,      #   local.get 0
      0x50,            #   i64.eqz
      0x04, 0x7E       #   if i64
    ),
    if_branch = c(
      0x42, 0x01       #     i64.const 1
    ),
    else_branch = c(
      0x20, 0x00,      #     local.get 0
      0x20, 0x00,      #     local get 0
      0x42, 0x01,      #     i64.const 1
      0x7D,            #     i64.sub
      0x10, 0x00,      #     call 0
      0x7E             #     i64.mul
    )
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;quot; Recursively interpret the given function
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
interp_wasm &amp;lt;- function(func) {
  
  # Set the bytecode to be the starting code of the function
  byte_idx &amp;lt;- 1
  bytecode &amp;lt;- func$start
  
  # Helper function to read &amp;#39;n&amp;#39; bytes from the bytecode
  read_bytes &amp;lt;- function(n) {
    res &amp;lt;- bytecode[byte_idx + seq(n) - 1]
    byte_idx &amp;lt;&amp;lt;- byte_idx + n
    res
  }
  
  # For each opcode, determine what to do within a giant `switch` statement
  while(byte_idx &amp;lt;= length(bytecode)) {
    opcode &amp;lt;- read_bytes(1)
    opcode &amp;lt;- sprintf(&amp;quot;0x%02x&amp;quot;, opcode)
    switch(
      opcode, 
      &amp;#39;0x04&amp;#39; = { # if
        type = read_bytes(1) # value type that if() operates on. ignored
        value = stack_pop()  # get the value. treat as boolean.
        if (value == 1) {
          # Jump the bytecode into the respective TRUE/FALSE branch
          bytecode &amp;lt;- func$if_branch
          byte_idx &amp;lt;- 1
        } else {
          bytecode &amp;lt;- func$else_branch
          byte_idx &amp;lt;- 1
        }
      },
      &amp;#39;0x10&amp;#39; = { # call
        # Select the function to call, setup the arguments and call it
        func_idx &amp;lt;- read_bytes(1)
        next_func &amp;lt;- all_funcs[[func_idx + 1]]
        arg &amp;lt;- stack_pop()
        next_func$args &amp;lt;- arg
        if (verbose) message(&amp;quot;factorial(&amp;quot;, arg, &amp;quot;)&amp;quot;)
        interp_wasm(next_func)
      },
      &amp;#39;0x20&amp;#39; = { # local.get idx
        # Push a local variable onto the stack.
        # In this simple case all local vars are just the args to the function
        idx &amp;lt;- read_bytes(1)
        value &amp;lt;- func$args[idx + 1]
        stack_push(value)
      },
      &amp;#39;0x42&amp;#39; = { # i64 const
        # Push a constant onto the stack
        value &amp;lt;- read_bytes(1)
        stack_push(value)
      },
      &amp;#39;0x50&amp;#39; = { # i64.eqz
        # Is value at top of stack == 0?  No/Yes = 0/1
        value &amp;lt;- stack_pop()
        result &amp;lt;- value == 0
        stack_push(result)
      },
      &amp;#39;0x7d&amp;#39; = { # i64.sub
        # Subtract the two values at the top of the stack
        val2 &amp;lt;- stack_pop()
        val1 &amp;lt;- stack_pop()
        result &amp;lt;- val1 - val2
        stack_push(result)
      },
      &amp;#39;0x7e&amp;#39; = { # i64.mul
        # Multiply the 2 values at the top of the stack
        val2 &amp;lt;- stack_pop()
        val1 &amp;lt;- stack_pop()
        result &amp;lt;- val1 * val2
        stack_push(result)
      }
    )
    
    if (verbose) {
      message(opcode, &amp;quot; -&amp;gt; stack: &amp;quot;, deparse(stack))
    }
  }
  return(stack[1])
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;factorial3-running-in-wasm&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;factorial(3)&lt;/code&gt; running in WASM&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Select the factorial function
func &amp;lt;- all_funcs[[1]]

# Set the argument to be &amp;#39;3&amp;#39;
func$args &amp;lt;- 3

# interpret the code
verbose &amp;lt;- FALSE
interp_wasm(func)
#&amp;gt; [1] 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;factorial3-running-in-wasm-verbose&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;factorial(3)&lt;/code&gt; running in WASM (verbose)&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;func$args &amp;lt;- 4
verbose &amp;lt;- TRUE
interp_wasm(func)
#&amp;gt; 0x20 -&amp;gt; stack: c(4, 6)
#&amp;gt; 0x50 -&amp;gt; stack: c(0, 6)
#&amp;gt; 0x04 -&amp;gt; stack: 6
#&amp;gt; 0x20 -&amp;gt; stack: c(4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(4, 4, 6)
#&amp;gt; 0x42 -&amp;gt; stack: c(1, 4, 4, 6)
#&amp;gt; 0x7d -&amp;gt; stack: c(3, 4, 6)
#&amp;gt; factorial(3)
#&amp;gt; 0x20 -&amp;gt; stack: c(3, 4, 6)
#&amp;gt; 0x50 -&amp;gt; stack: c(0, 4, 6)
#&amp;gt; 0x04 -&amp;gt; stack: c(4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(3, 4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(3, 3, 4, 6)
#&amp;gt; 0x42 -&amp;gt; stack: c(1, 3, 3, 4, 6)
#&amp;gt; 0x7d -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; factorial(2)
#&amp;gt; 0x20 -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; 0x50 -&amp;gt; stack: c(0, 3, 4, 6)
#&amp;gt; 0x04 -&amp;gt; stack: c(3, 4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(2, 2, 3, 4, 6)
#&amp;gt; 0x42 -&amp;gt; stack: c(1, 2, 2, 3, 4, 6)
#&amp;gt; 0x7d -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; factorial(1)
#&amp;gt; 0x20 -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; 0x50 -&amp;gt; stack: c(0, 2, 3, 4, 6)
#&amp;gt; 0x04 -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; 0x20 -&amp;gt; stack: c(1, 1, 2, 3, 4, 6)
#&amp;gt; 0x42 -&amp;gt; stack: c(1, 1, 1, 2, 3, 4, 6)
#&amp;gt; 0x7d -&amp;gt; stack: c(0, 1, 2, 3, 4, 6)
#&amp;gt; factorial(0)
#&amp;gt; 0x20 -&amp;gt; stack: c(0, 1, 2, 3, 4, 6)
#&amp;gt; 0x50 -&amp;gt; stack: c(1, 1, 2, 3, 4, 6)
#&amp;gt; 0x04 -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; 0x42 -&amp;gt; stack: c(1, 1, 2, 3, 4, 6)
#&amp;gt; 0x10 -&amp;gt; stack: c(1, 1, 2, 3, 4, 6)
#&amp;gt; 0x7e -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; 0x10 -&amp;gt; stack: c(1, 2, 3, 4, 6)
#&amp;gt; 0x7e -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; 0x10 -&amp;gt; stack: c(2, 3, 4, 6)
#&amp;gt; 0x7e -&amp;gt; stack: c(6, 4, 6)
#&amp;gt; 0x10 -&amp;gt; stack: c(6, 4, 6)
#&amp;gt; 0x7e -&amp;gt; stack: c(24, 6)
#&amp;gt; [1] 24&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-next&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What’s next?&lt;/h1&gt;
&lt;p&gt;Nothing really.&lt;/p&gt;
&lt;p&gt;An actual WASM stack machine would need signed &amp;amp; unsigned 64 bit integers.
You could use &lt;a href=&#34;https://cran.rstudio.com/web/packages/bit64/index.html&#34;&gt;&lt;code&gt;{bit64}&lt;/code&gt;&lt;/a&gt; to support this, if you really wanted to.&lt;/p&gt;
&lt;p&gt;There are ~250 standard opcodes, and another ~250 SSE opcodes. I have no
appetite for implementing all these - but it could be fun at some future date.&lt;/p&gt;
&lt;p&gt;Please steal/adapt the code if you’re interested.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>AnotherWorld game written &#43; playable in R (with {nara} and {eventloop})</title>
      <link>https://coolbutuseless.github.io/2022/07/29/anotherworld-game-written-playable-in-r-with-nara-and-eventloop/</link>
      <pubDate>Fri, 29 Jul 2022 17:07:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/29/anotherworld-game-written-playable-in-r-with-nara-and-eventloop/</guid>
      <description>


&lt;div id=&#34;anotherworld-playable-game-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;AnotherWorld&lt;/code&gt; playable game in R&lt;/h1&gt;
&lt;p&gt;This is the full code for a playable R version of the 16-bit game &lt;a href=&#34;https://en.wikipedia.org/wiki/Another_World_(video_game)&#34;&gt;&lt;code&gt;AnotherWorld&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The game plays in realtime using 2 key packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/nara&#34;&gt;&lt;code&gt;{nara}&lt;/code&gt;&lt;/a&gt; for manipulation of
&lt;em&gt;nativeRaster&lt;/em&gt; images as a fast in-memory drawing canvas&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/eventloop&#34;&gt;&lt;code&gt;{eventloop}&lt;/code&gt;&lt;/a&gt; for event-driven
interaction - allowing for keyboard feedback while rendering the game with
sound.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;you-can-play-this-game-today-in-r&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;You can play this game &lt;em&gt;today&lt;/em&gt; in R!!&lt;/h3&gt;
&lt;p&gt;However, there are still some graphics bugs etc to work out.&lt;/p&gt;
&lt;p&gt;Please file an issue on github if you think something is definitely wrong!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;gameplay-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Gameplay in R&lt;/h2&gt;
&lt;p&gt;A live capture of playing the game in R&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/anotherworld/anotherworld.gif&#34; width=&#34;70%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Install the dependencies
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/nara&#34;&gt;&lt;code&gt;{nara}&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/eventloop&#34;&gt;&lt;code&gt;{eventloop}&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Retrieve the anotherworld game code from &lt;a href=&#34;https://github.com/coolbutless/anotherworld&#34;&gt;github&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Note that this is &lt;em&gt;not&lt;/em&gt; a package, but just a collection of R scripts and
code. This should make it easier to hack on, extend and adapt.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;library(remotes)

# Install dependencies
remotes::install_github(&amp;#39;coolbutuseless/eventloop&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/nara&amp;#39;)

# Install packages
install.packages(&amp;#39;audio&amp;#39;)
install.packages(&amp;#39;beepr&amp;#39;)

# Grab a copy of the code (this is not distributed as a package)
system(&amp;quot;git clone https://github.com/coolbutuseless/anotherworld&amp;quot;)
setwd(&amp;#39;anotherworld&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;controls&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Controls&lt;/h2&gt;
&lt;p&gt;After your experiment on Earth goes awry, you are transported to &lt;em&gt;another world&lt;/em&gt;
where you must survive and, hopefully, escape!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run game with &lt;code&gt;source(&#39;game.R&#39;)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;PART&lt;/code&gt; variable first to the section you want to play.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Control game with arrow keys and space bar (for action)&lt;/li&gt;
&lt;li&gt;Press ‘p’ to pause&lt;/li&gt;
&lt;li&gt;Press ‘ESC’ to quit&lt;/li&gt;
&lt;li&gt;When you finish a section the game does not automatically advance to the next
section.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;play-the-game&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Play the game&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;16001&lt;/strong&gt; “Introduction”: cinematic introduction. No user interactivity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16002&lt;/strong&gt; “Water”: If you want to get to playing the game, this is the section to run.
&lt;ul&gt;
&lt;li&gt;Hint: Press “Up” at the start when it looks like you’re underwater.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16003&lt;/strong&gt; “Jail”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16004&lt;/strong&gt; “City”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16005&lt;/strong&gt; “Arena”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16006&lt;/strong&gt; “Luxe”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;16007&lt;/strong&gt; “Final”&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;PART &amp;lt;- 16001  # &amp;lt;------- select the part of the game to play
source(&amp;#39;game.R&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;gameplay&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;GamePlay&lt;/h2&gt;
&lt;div id=&#34;game-walkthrough-on-the-amiga&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Game walkthrough on the Amiga&lt;/h4&gt;
&lt;p&gt;This looks pretty similar to the R version as it’s running on the same
in-game virtual machine.&lt;/p&gt;
&lt;p&gt;Click the image below to watch it on youtube.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=utrxk5_PeEY&#34;&gt;&lt;img src=&#34;https://img.youtube.com/vi/utrxk5_PeEY/0.jpg&#34; alt=&#34;AnotherWorld gameplay&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;screenshots-of-the-r-version&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Screenshots of the R version&lt;/h4&gt;
&lt;div&gt;
&lt;div style=&#34;float: left; width: 45%;&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/anotherworld/01.png&#34; width=&#34;95%&#34; /&gt;
&lt;/div&gt;
&lt;div style=&#34;float: left; width: 45%;&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/anotherworld/02.png&#34; width=&#34;95%&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div style=&#34;float: left; width: 45%;&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/anotherworld/03.png&#34; width=&#34;95%&#34; /&gt;
&lt;/div&gt;
&lt;div style=&#34;float: left; width: 45%;&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/anotherworld/04.png&#34; width=&#34;95%&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Controls still feel a bit “sticky”. This feels like a bug in my code.&lt;/li&gt;
&lt;li&gt;Incorporate display of pre-rendered bitmaps which are part of the in-game data
&lt;ul&gt;
&lt;li&gt;You’ll notice some scenes are a little blank because these bitmaps
aren’t drawn yet.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Still some rendering anomalies&lt;/li&gt;
&lt;li&gt;See if I can get sound playback with &lt;code&gt;{audio}&lt;/code&gt; package working correctly&lt;/li&gt;
&lt;li&gt;While there are sound effects in the R version, there is currently no music
as it hasn’t been looked into yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;requirements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Running this on macOS requires &lt;a href=&#34;https://www.xquartz.org/&#34;&gt;XQuartz&lt;/a&gt; to have been
installed in order to support the &lt;code&gt;x11()&lt;/code&gt; device.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;R needs to have been compiled with &lt;code&gt;x11()&lt;/code&gt; and Cairo support.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitation---windowsos&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitation - WindowsOS&lt;/h2&gt;
&lt;p&gt;The WindowsOS version of R does not currently have support for the &lt;code&gt;onIdle&lt;/code&gt; callback and
therefore does not support event-driven interactive graphics as implemented
in the &lt;code&gt;{eventloop}&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you are a windows developer capable of adding support for an &lt;code&gt;onIdle&lt;/code&gt; callback
to R itself, please get in touch!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitation---flickering-cursor&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitation - Flickering Cursor&lt;/h2&gt;
&lt;p&gt;The cursor icon in an &lt;code&gt;{eventloop}&lt;/code&gt; window will flicker because of some hard-coded
behaviour in R’s double-buffered &lt;code&gt;x11()&lt;/code&gt; graphics device.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{eventloop}&lt;/code&gt; makes use of the &lt;code&gt;x11()&lt;/code&gt; graphics device with a double-buffered
backend based on Cairo (&lt;code&gt;x11(type = &#39;dbcairo&#39;)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The double-buffering within the graphics device is coordinated through use
of &lt;code&gt;dev.hold()&lt;/code&gt; and &lt;code&gt;dev.flush()&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Whenever &lt;code&gt;dev.hold()&lt;/code&gt; is called, the cursor will be set to the busy cursor
(usually a stopwatch on macOS), and when &lt;code&gt;dev.flush()&lt;/code&gt; is called the
cursor reverts to a normal pointer arrow.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;dev.hold()&lt;/code&gt; and &lt;code&gt;dev.flush()&lt;/code&gt; are called when drawing every single
frame, the cursor will flicker between these two images.&lt;/p&gt;
&lt;p&gt;The interim solution is to not have the cursor over the window when interacting
with the app. This only really works when the app solely relies on keyboard
feedback (like this game of AnotherWorld).&lt;/p&gt;
&lt;p&gt;The more complicated solution will involve crafting a patch to R itself to
make the cursor change behaviour user-configurable rather than hard-coded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you are are an R developer capable of crafting such a patch to R ,
please get in touch with me!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;reference-source-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Reference Source Code&lt;/h2&gt;
&lt;p&gt;The reference code for this port was the JavaScript code from &lt;a href=&#34;https://github.com/cyxx/another_js&#34;&gt;github/cyxx/another_js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Further details have been extracted from the C code from &lt;a href=&#34;https://github.com/fabiensanglard/Another-World-Bytecode-Interpreter&#34;&gt;Fabien’s C++ Interpreter&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;challenges&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Challenges&lt;/h2&gt;
&lt;div id=&#34;based-vs-1-based-indexing&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;0-based vs 1-based indexing&lt;/h3&gt;
&lt;p&gt;Javascript and C code used for reference both use 0-based indexing, whereas R
uses 1-based indexing.&lt;/p&gt;
&lt;p&gt;To try and avoid editing all references to array indexint to &lt;code&gt;+1&lt;/code&gt;, I created
a new class &lt;code&gt;cindex&lt;/code&gt; which has 1-based indexing in R.&lt;/p&gt;
&lt;p&gt;There still a lot of refacoring to do, and many structures are still indexed
by a character string representation of the hexadecimal version of the
index or address i.e. ugly.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bitwise-operations&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;bitwise operations&lt;/h3&gt;
&lt;p&gt;JS and C both use &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;|&lt;/code&gt; for bitwise operations, whereas R uses them
for logical operations.&lt;/p&gt;
&lt;p&gt;I created a set of infix operators (&lt;code&gt;%|%&lt;/code&gt; etc) to mimic the bitwise operators
in C.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bytekiller-compression&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;‘Bytekiller’ compression&lt;/h3&gt;
&lt;p&gt;Data in the original game is compressed with ‘bytekiller’ which is a very very
old skool data compression algorithm.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Pacman game written in R with {nara} and {eventloop}</title>
      <link>https://coolbutuseless.github.io/2022/07/26/pacman-game-written-in-r-with-nara-and-eventloop/</link>
      <pubDate>Tue, 26 Jul 2022 07:07:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/26/pacman-game-written-in-r-with-nara-and-eventloop/</guid>
      <description>


&lt;div id=&#34;pacman-style-game-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Pacman-style game in R&lt;/h1&gt;
&lt;p&gt;This is the full code for a playable, pacman-style game in R.&lt;/p&gt;
&lt;p&gt;The game plays in realtime using 2 key packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/nara&#34;&gt;&lt;code&gt;{nara}&lt;/code&gt;&lt;/a&gt; for manipulation of
&lt;em&gt;nativeRaster&lt;/em&gt; images as a fast in-memory drawing canvas&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/eventloop&#34;&gt;&lt;code&gt;{eventloop}&lt;/code&gt;&lt;/a&gt; for event-driven
interaction - allowing for keyboard feedback while rendering the game with
sound.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;gameplay&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Gameplay&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/pacman/pacman-game.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;controls&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Controls&lt;/h2&gt;
&lt;p&gt;The aim of this pacman-style game is to eat all 288 dots before you lose
your 5 pacman lives.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run game with &lt;code&gt;source(&#39;game.R&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Control pacman with arrow keys (or WASD).&lt;/li&gt;
&lt;li&gt;Score 10 points for each dot consume.&lt;/li&gt;
&lt;li&gt;Lose 100 points for every collision with a ghost.&lt;/li&gt;
&lt;li&gt;Maximum possible score: 2880 for consume all dots and never colliding with a ghost.&lt;/li&gt;
&lt;li&gt;There are no power-ups. Ghosts cannot die. Every collision with a
ghost will take one of your lives.&lt;/li&gt;
&lt;li&gt;The portal between the left and right side of the board, as present on a
regular pacman game, is not included here.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Install the dependencies
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/nara&#34;&gt;&lt;code&gt;{nara}&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/eventloop&#34;&gt;&lt;code&gt;{eventloop}&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Retrieve the pacman game code from &lt;a href=&#34;https://github.com/coolbutless/pacman&#34;&gt;github&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Note that this is &lt;em&gt;not&lt;/em&gt; a package, but just a collection of R scripts and
code. This should make it easier to hack on, extend and adapt.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;library(remotes)

# Packages required for interactive rendering
remotes::install_githb(&amp;quot;coolbutuseless/eventloop&amp;quot;)
remotes::install_githb(&amp;quot;coolbutuseless/nara&amp;quot;)

# Grab a copy of the pacman game code
x &amp;lt;- remotes::remote_download(remotes::github_remote(&amp;#39;coolbutuseless/pacman&amp;#39;))
untar(x, exdir = &amp;#39;pacman&amp;#39;)
setwd(&amp;#39;pacman&amp;#39;)
source(&amp;#39;game.R&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;requirements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Running this on macOS requires &lt;a href=&#34;https://www.xquartz.org/&#34;&gt;XQuartz&lt;/a&gt; to have been
installed in order to support the &lt;code&gt;x11()&lt;/code&gt; device.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;R needs to have been compiled with &lt;code&gt;x11()&lt;/code&gt; and Cairo support.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitation---windowsos&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitation - WindowsOS&lt;/h2&gt;
&lt;p&gt;The WindowsOS version of R does not currently have support for the &lt;code&gt;onIdle&lt;/code&gt; callback and
therefore does not support event-driven interactive graphics as implemented
in the &lt;code&gt;{eventloop}&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you are a windows developor capable of adding support for an &lt;code&gt;onIdle&lt;/code&gt; callback
to R itself, please get in touch!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitation---flickering-cursor&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitation - Flickering Cursor&lt;/h2&gt;
&lt;p&gt;The cursor icon in an &lt;code&gt;{eventloop}&lt;/code&gt; window will flicker because of some hard-coded
behaviour in R’s double-buffered &lt;code&gt;x11()&lt;/code&gt; graphics device.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{eventloop}&lt;/code&gt; makes use of the &lt;code&gt;x11()&lt;/code&gt; graphics device with a double-buffered
backend based on Cairo (&lt;code&gt;x11(type = &#39;dbcairo&#39;)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The double-buffering within the graphics device is coordinated through use
of &lt;code&gt;dev.hold()&lt;/code&gt; and &lt;code&gt;dev.flush()&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Whenever &lt;code&gt;dev.hold()&lt;/code&gt; is called, the cursor will be set to the busy cursor
(usually a stopwatch on macOS), and when &lt;code&gt;dev.flush()&lt;/code&gt; is called the
cursor reverts to a normal pointer arrow.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;dev.hold()&lt;/code&gt; and &lt;code&gt;dev.flush()&lt;/code&gt; are called when drawing every single
frame, the cursor will flicker between these two images.&lt;/p&gt;
&lt;p&gt;The interim solution is to not have the cursor over the window when interacting
with the app. This only really works when the app solely relies on keyboard
feedback (like this pacman game).&lt;/p&gt;
&lt;p&gt;The more complicated solution will involve crafting a patch to R itself to
make the cursor change behaviour user-configurable rather than hard-coded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you are are an R developer capable of crafting such a patch to R ,
please get in touch with me!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {nara} for nativeRaster handling for fast in-memory rendering buffers</title>
      <link>https://coolbutuseless.github.io/2022/07/25/introducing-nara-for-nativeraster-handling-for-fast-in-memory-rendering-buffers/</link>
      <pubDate>Mon, 25 Jul 2022 15:15:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/25/introducing-nara-for-nativeraster-handling-for-fast-in-memory-rendering-buffers/</guid>
      <description>


&lt;div id=&#34;nara&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;nara &lt;img src=&#34;https://coolbutuseless.github.io/img/nara/logo-nara.png&#34; align=&#34;right&#34; width=&#34;300&#34; /&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/nativeraster-dev/actions/workflows/R-CMD-check.yaml&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/nara/actions/workflows/R-CMD-check.yaml/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{nara}&lt;/code&gt; provides tools for working with R’s &lt;code&gt;nativeRaster&lt;/code&gt; image format to
enable fast double-buffered graphics rendering.&lt;/p&gt;
&lt;div id=&#34;why&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;nativeRaster&lt;/code&gt; buffers are fast enough to use for rendering at speed &amp;gt;30 frames-per-second.&lt;br /&gt;
This makes them useful for games and other interactive applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Example&lt;/h3&gt;
&lt;p&gt;An example graphics demo is this non-playable version of pacman created and running in R in realtime &lt;a href=&#34;https://coolbutuseless.github.io/package/nara/articles/pacman.html&#34;&gt;(see the vignette)&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nara/pacman.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;details&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Details&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;{nara}&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is an &lt;em&gt;off-screen&lt;/em&gt; rendering buffer.&lt;/li&gt;
&lt;li&gt;is fast to render.&lt;/li&gt;
&lt;li&gt;uses &lt;em&gt;in-place&lt;/em&gt; operations to avoid memory allocations.&lt;/li&gt;
&lt;li&gt;is focussed on rendering discrete pixels, so
&lt;ul&gt;
&lt;li&gt;no anti-aliasing is done.&lt;/li&gt;
&lt;li&gt;all dimensions are rounded to integer values prior to rendering.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;what-is-a-nativeraster-and-why-is-it-fast&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What is a &lt;code&gt;nativeRaster&lt;/code&gt; and why is it fast?&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;nativeRaster&lt;/code&gt; is a built-in datatype in R.&lt;/p&gt;
&lt;p&gt;It is an integer matrix where each integer represents the RGBA colour at
a single pixel. The 32-bit integer at each location is interpreted within
R to be four colour channels (RGBA) represented by 8 bits each.&lt;/p&gt;
&lt;p&gt;This way of encoding colour information is closer to the internal representation
used by graphics devices, and therefore can be faster to render, save and load
(as fewer data conversion steps are needed).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-place-operation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;In-place operation&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;{nara}&lt;/code&gt; is targeted at fast rendering (&amp;gt;30fps), and tries to minimise
R function calls and memory allocations.&lt;/p&gt;
&lt;p&gt;When updating &lt;code&gt;nativeRaster&lt;/code&gt; objects with this package, all changes are done
&lt;em&gt;in place&lt;/em&gt; on the current object i.e. a new object is &lt;strong&gt;not&lt;/strong&gt; created.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;anti-aliasinginterpolation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Anti-aliasing/Interpolation&lt;/h3&gt;
&lt;p&gt;No anti-aliasing is done by the draw methods in this package.&lt;/p&gt;
&lt;p&gt;No interpolation is done - &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; values for drawing coordinates are
converted to integers.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/nara&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/nara&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/nara/articles/pacman.html&#34;&gt;Pacman demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/nara/articles/conversion.html&#34;&gt;Creating, transforming, reading, writing nativeRaster images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;static-rendering-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Static Rendering: Example&lt;/h2&gt;
&lt;p&gt;The following is a rendering of a single scene with multiple elements.&lt;/p&gt;
&lt;p&gt;The interesting thing about this scene that drawing all the objects into
the &lt;code&gt;nativeRaster&lt;/code&gt; image and rendering to screen can take as little as
5 millseconds.&lt;/p&gt;
&lt;p&gt;This means that this scene could render at around 200 frames-per-second.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(nara)
set.seed(1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create &amp;#39;nr&amp;#39; image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
w  &amp;lt;- 10
h  &amp;lt;- 8
nr &amp;lt;- nr_new(w * 30, h * 30, fill = &amp;#39;grey98&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a grid of squares
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
colours &amp;lt;- viridisLite::inferno(w * h)
coords  &amp;lt;- expand.grid(y = seq(0, h-1) * 30 + 1, x = seq(0, w-1) * 30 + 1)
nr_rect(nr, x = coords$x, y = coords$y, w = 27, h = 27, colour = NA, fill = colours)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a bunch of dinos
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nr_blit(nr, dino[[1]], x = sample(300, 15), y = sample(200, 15))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add an image read from file (with alpha transparency)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
img &amp;lt;- png::readPNG(system.file(&amp;quot;img&amp;quot;, &amp;quot;Rlogo.png&amp;quot;, package=&amp;quot;png&amp;quot;), native = TRUE)
nr_blit(nr, img, 1, 1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add a polygon
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
thetas &amp;lt;- seq(pi/6, 2*pi, pi/3)
x &amp;lt;- 50 * cos(thetas) + 240
y &amp;lt;- 50 * sin(thetas) + 180
nr_polygon(nr, x = x, y = y, fill = &amp;#39;#556688c0&amp;#39;, col = &amp;#39;blue&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add text to the image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nr_text(nr, &amp;quot;Hello #RStats&amp;quot;, 180, 1, fontsize = 16)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copy image to the device
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.raster(nr, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-25-introducing-nara_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;static-rendering-displaying-sprites&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Static Rendering: Displaying Sprites&lt;/h2&gt;
&lt;p&gt;Included with &lt;code&gt;{nara}&lt;/code&gt; are 16 frames of cartoon dinosaur animation from the
BubbleBobble video game - see &lt;code&gt;dino&lt;/code&gt; data.&lt;/p&gt;
&lt;div id=&#34;blit-the-first-dino-frame-onto-a-native-raster-canvas.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Blit the first dino frame onto a native raster canvas.&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

nr &amp;lt;- nr_new(100, 30, &amp;#39;grey80&amp;#39;)
nr_blit(nr, dino[[1]], 2, 1)
grid.raster(nr, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-25-introducing-nara_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dynamic-realtime-rendering-walking-dino&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Dynamic (realtime) Rendering: Walking Dino&lt;/h4&gt;
&lt;p&gt;The reason to use &lt;code&gt;{nara}&lt;/code&gt; is that operations are fast enough that &lt;code&gt;nativeRaster&lt;/code&gt;
can be used as an &lt;em&gt;in-memory&lt;/em&gt; buffer for a double-bufferred rendering system.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Double-buffered&lt;/code&gt; rendering is where two buffers are used for rendering with
one buffer being shown to the user, and the other existing in memory as a
place to render.&lt;/p&gt;
&lt;p&gt;In this example, the &lt;code&gt;dino&lt;/code&gt; sprite is renderd to a &lt;code&gt;nativeRaster&lt;/code&gt; image. This
&lt;em&gt;in-memory&lt;/em&gt; buffer is then displayed to the user using &lt;code&gt;grid.raster()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By altering the position and animation frame every time the dino is shown,
smooth animation is possible.&lt;/p&gt;
&lt;p&gt;This simple code runs at well over 100 frames-per-second.&lt;/p&gt;
&lt;p&gt;It is unlikely your screen will refresh this fast, but it does indicate that
there is plenty of headroom for more complicated computations for each frame.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

# Setup a fast graphics device that can render quickly
x11(type = &amp;#39;cairo&amp;#39;, antialias = &amp;#39;none&amp;#39;)
dev.control(&amp;#39;inhibit&amp;#39;)

# Create the in-memory nativeRaster canvas
nr &amp;lt;- nr_new(100, 30, &amp;#39;grey80&amp;#39;)

# Clear, blit and render =&amp;gt; animation!
for (i in -30:110) {
  nr_fill(nr, &amp;#39;grey80&amp;#39;)                    # Clear the nativeRaster
  nr_blit(nr, dino[[(i %% 16) + 1]], i, 1) # copy dino to nativeRaster
  grid.raster(nr, interpolate = FALSE)     # copy nativeRaster to screen
  Sys.sleep(0.02)                          # Stop animation running too fast.
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;live-screen-recording&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Live screen recording&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nara/dino.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;dino-multi-ball&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dino Multi-Ball&lt;/h2&gt;
&lt;p&gt;You can quickly &lt;em&gt;blit&lt;/em&gt; (i.e. copy) a sprite into multiple locations on the nativeraster with
&lt;code&gt;nr_blit()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this example 100 random positions and velocities are first created. A
character sprite is then blitted to each of these 100 locations.&lt;/p&gt;
&lt;p&gt;The positions are updated using the velocities, and the next frame is rendered.
In this way multiple sprites are rendered and animated on screen.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

# Setup a fast graphics device that can render quickly
x11(type = &amp;#39;dbcairo&amp;#39;, antialias = &amp;#39;none&amp;#39;, width = 8, height = 6)
dev.control(&amp;#39;inhibit&amp;#39;)

# Number of sprites
N &amp;lt;- 100

# Window size
w &amp;lt;- 400 
h &amp;lt;- 300 

# location and movement vector of all the sprites
x  &amp;lt;- sample(w -25, N, replace = TRUE)
y  &amp;lt;- sample(h - 25, N, replace = TRUE)
vx &amp;lt;- sample(seq(-5, 5), N, replace = TRUE)
vy &amp;lt;- sample(seq(-5, 5)[-6], N, replace = TRUE)

# Create an empty nativeraster with a grey background
nr &amp;lt;- nr_new(w, h, &amp;#39;grey80&amp;#39;)


for (frame in 1:1000) {
  # Clear the nativeraster and blit in all the dinosaurs
  nr_fill(nr, &amp;#39;grey80&amp;#39;) 
  nr_blit(nr, dino[[(frame) %% 16 + 1]], x, y)
  
  # Draw the nativeraster to screen
  dev.hold()
  grid.raster(nr, interpolate = FALSE)
  dev.flush()

  # Update the position and velocity of each dino
  # Dinos move at constant velocity and bounce off the sides of the image
  x  &amp;lt;- x + vx
  y  &amp;lt;- y + vy
  vx &amp;lt;- ifelse(x &amp;gt; (w - 25)| x &amp;lt; 1, -vx, vx)
  vy &amp;lt;- ifelse(y &amp;gt; (h - 25)| y &amp;lt; 1, -vy, vy)
  
  # slight pause to slow things down 
  Sys.sleep(0.03)
}&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;live-screen-recording-1&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Live screen recording&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nara/multiball.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;coordinate-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Coordinate System&lt;/h2&gt;
&lt;p&gt;The coordinate system for &lt;code&gt;nara&lt;/code&gt; nativeRaster objects has its origins
at the bottom left corner of the image with coordinates &lt;code&gt;(1,1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nara/coords.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark-raster-vs-nativeraster&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark &lt;code&gt;raster&lt;/code&gt; vs &lt;code&gt;nativeRaster&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;A pretty naive benchmark showing that drawing a &lt;code&gt;nativeRaster&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is approx &lt;strong&gt;5x faster&lt;/strong&gt; than drawing a &lt;code&gt;raster&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;allocates &lt;strong&gt;only one quarter of the memory&lt;/strong&gt; compared to &lt;code&gt;raster&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;nr  &amp;lt;- nr_new(800, 600)
ras &amp;lt;- nr_to_raster(nr)

x11(type = &amp;#39;dbcairo&amp;#39;)
dev.control(&amp;#39;inhibit&amp;#39;)

draw_nr &amp;lt;- function() {
  dev.hold()
  grid.raster(nr, interpolate = FALSE)
  dev.flush()
}


draw_raster &amp;lt;- function() {
  dev.hold()
  grid.raster(ras, interpolate = FALSE)
  dev.flush()
}

bench::mark(
  draw_nr(),
  draw_raster()
)
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;draw_nr()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;269.8799&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.83MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;draw_raster()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.6820&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.32MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;More efficient polygon drawing with active edge lists.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>World&#39;s simplest R music system. Part 3 - Non-sinusoidal Waveforms</title>
      <link>https://coolbutuseless.github.io/2022/07/12/worlds-simplest-r-music-system.-part-3-non-sinusoidal-waveforms/</link>
      <pubDate>Tue, 12 Jul 2022 15:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/12/worlds-simplest-r-music-system.-part-3-non-sinusoidal-waveforms/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;A note doesn’t have to be a &lt;a href=&#34;https://en.wikipedia.org/wiki/Sine_wave&#34;&gt;sine wave&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Square, Triangle and sawtooth waves are also common and have different sound
characteristics.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;utilities-developed-in-prior-posts&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Utilities developed in prior posts&lt;/h2&gt;
&lt;details&gt;
&lt;summary&gt;
Click to reveal ADSR profiling and other utilities
&lt;/summary&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create an ADSR profile of the given length - using only linear segments
#&amp;#39; 
#&amp;#39; @param N length of profile (integer)
#&amp;#39; @param a,d,r fractions of the profile devoted to attack, decay and release
#&amp;#39;        respectively
#&amp;#39; @param s the level of sustain in range [0,1].  The duration of the sustain
#&amp;#39;        will be the remaining fraction after attack, decay and release
#&amp;#39;        are accounted for
#&amp;#39;
#&amp;#39; @return numeric vector in range [0,1] of length N which defines a 
#&amp;#39;         volumn envelope for the note.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_adsr_profile &amp;lt;- function(N, a, d, s, r) {
   
  dur &amp;lt;- 1 - a - d - r
  stopifnot(dur &amp;gt;= 0)
  
  profile &amp;lt;- c(
    seq(0, 1, length.out = a * N),
    seq(1, s, length.out = d * N),
    rep(s, length.out = dur * N),
    seq(s, 0, length.out = r * N)
  )
  
  # Ensure we have the right number of elements in case of weird rounding
  length(profile) &amp;lt;- N
  profile[is.na(profile)] &amp;lt;- 0
  
  profile
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play a note
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
play_note &amp;lt;- function(samples) {
  audio::play(samples, rate = 44100)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;create-simple-note-with-different-waveforms&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create simple note with different waveforms&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a note - sine wave
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_sine_wave &amp;lt;- function(freq, duration) {
  t &amp;lt;- seq(duration * 44100)
  samples &amp;lt;- sin((t) * 2*pi/ (44100/freq))
  samples
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a note - square wave
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_square_wave &amp;lt;- function(freq, duration) {
  samples &amp;lt;- create_sine_wave(freq, duration)
  samples &amp;lt;- ifelse(samples &amp;gt;=0, 1, -1)
  samples
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a note - triangular wave. 
# Create as a cumsum() of a square wave.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_triangle_wave &amp;lt;- function(freq, duration) {
  period &amp;lt;- 44100/freq
  wave &amp;lt;- c(
    seq( 0,  1, length.out = (period/4 - 1)),
    seq( 1, -1, length.out = (period/2 - 1)),
    seq(-1,  0, length.out = (period/4 - 1))
  )
  
  rep(wave, length.out = 44100 * duration)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a note - sawtooth wave
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_sawtooth_wave &amp;lt;- function(freq, duration) {
  period &amp;lt;- 44100/freq
  wave &amp;lt;- seq(-1,  1, length.out = period - 1)
  rep(wave, length.out = 44100 * duration)
}



note_sine &amp;lt;- create_sine_wave(440, 1)
plot(note_sine[1:300], type = &amp;#39;l&amp;#39;)
title(&amp;#39;Sine&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-12-sound-waveforms_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;

note_square &amp;lt;- create_square_wave(440, 1)
plot(note_square[1:300], type = &amp;#39;l&amp;#39;)
title(&amp;#39;Square&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-12-sound-waveforms_files/figure-html/unnamed-chunk-3-2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
note_tri &amp;lt;- create_triangle_wave(440, 1) 
plot(note_tri[1:300], type = &amp;#39;l&amp;#39;)
title(&amp;#39;Triangle&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-12-sound-waveforms_files/figure-html/unnamed-chunk-3-3.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
note_saw &amp;lt;- create_sawtooth_wave(440, 1)
plot(note_saw[1:300], type = &amp;#39;l&amp;#39;)
title(&amp;#39;Sawtooth&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-12-sound-waveforms_files/figure-html/unnamed-chunk-3-4.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;profile &amp;lt;- create_adsr_profile(44100, 0.2, 0.3, 0.8, 0.5)

play_note(note_sine   * profile)
play_note(note_square * profile)
play_note(note_tri    * profile)
play_note(note_saw    * profile)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;sine&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Sine&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/note_sine.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;square&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Square&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/note_square.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;triangle&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Triangle&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/note_tri.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sawtooth&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Sawtooth&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/note_saw.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;worlds-simplest-r-music-system---with-linear-adsr-profile-shaping-sawtooth-waveform&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;World’s simplest R music system - with linear ADSR profile shaping + sawtooth waveform&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Octaves/Notes/Frequencies in an equal tempered scale
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ets &amp;lt;- tibble(
  freq   = 440 * (2 ^ ((-57:50)/12)),
  note   = rep(c(&amp;#39;C&amp;#39;, &amp;#39;C#&amp;#39;, &amp;#39;D&amp;#39;, &amp;#39;D#&amp;#39;, &amp;#39;E&amp;#39;, &amp;#39;F&amp;#39;, &amp;#39;F#&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;G#&amp;#39;, &amp;#39;A&amp;#39;, &amp;#39;A#&amp;#39;, &amp;#39;B&amp;#39;), 9),
  octave = rep(0:8, each = 12),
  mnote  = ifelse(nchar(note) == 1, paste(note, octave, sep = &amp;quot;-&amp;quot;), paste(note, octave, sep = &amp;quot;&amp;quot;))
)

head(ets)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note-to-Freq lookup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
freq &amp;lt;- setNames(ets$freq, ets$mnote)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function: Play a note of the given frequency for the given duration
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
profile &amp;lt;- create_adsr_profile(0.4 * 44100, 0.1, 0.25, 0.2, 0.6)
  
play_note &amp;lt;- function(freq, duration) {
  samples &amp;lt;- create_sawtooth_wave(freq, duration)
  samples &amp;lt;- samples * profile
  
  
  audio::play(samples , rate = 44100)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mary had a little lamb.
# Format is &amp;quot;[Note]-[Octave]&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mhall &amp;lt;- c(
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;,
  &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;C-5&amp;#39;, &amp;#39;C-5&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (note in mhall) {
  play_note(freq[[note]], 0.4)
  Sys.sleep(0.4)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;different-waveforms-sound-different&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Different waveforms sound different&lt;/h1&gt;
&lt;p&gt;The following two live captures of the same song at the same pitch with the same
ADSR note shaping - only the note waveform is different.&lt;/p&gt;
&lt;div id=&#34;live-capture-of-mary-had-a-little-lamb---with-adsr-note-shaping-sawtooth-waveform&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Live capture of “Mary had a little lamb” - with ADSR note shaping + sawtooth waveform&lt;/h2&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/mhall-adsr-sawtooth.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;live-capture-of-mary-had-a-little-lamb---with-adsr-note-shaping-sine-waveform&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Live capture of “Mary had a little lamb” - with ADSR note shaping + sine waveform&lt;/h2&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/mhall-adsr.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>World&#39;s simplest R music system. Part 2 - linear ADSR note shaping</title>
      <link>https://coolbutuseless.github.io/2022/07/11/worlds-simplest-r-music-system.-part-2-linear-adsr-note-shaping/</link>
      <pubDate>Mon, 11 Jul 2022 15:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/11/worlds-simplest-r-music-system.-part-2-linear-adsr-note-shaping/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Using a raw sine curve as a note will lead to clipping artefacts as the note
immediately starts with maximum amplitude and terminates abruptly.&lt;/p&gt;
&lt;p&gt;To make the note sound anything like an actual note from an instrument the profile
of the note must be shaped to emulate the actual characteristics of a note
produced by an actual physical object e.g. the note will ramp up to its playing volume,
and then ramp down again.&lt;/p&gt;
&lt;p&gt;So by shaping the profile of the raw note (raw sine curve) we can make
something that sounds more plausibly like an instrument.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-naive-note&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create naive note&lt;/h2&gt;
&lt;p&gt;If we create a note of the correct frequency, but with a constant amplitude,
then the note will sound harsh.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a note
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_note &amp;lt;- function(freq, duration) {
  t &amp;lt;- seq(duration * 44100)
  samples &amp;lt;- sin((t) * 2*pi/ (44100/freq))
  samples
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play a note
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
play_note &amp;lt;- function(samples) {
  audio::play(samples, rate = 44100)
}

note &amp;lt;- create_note(440, 1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;play_note(note)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;raw-note&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Raw note&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/sample1.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;shape-of-a-naive-note&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shape of a naive note&lt;/h2&gt;
&lt;p&gt;Looking at the profile of the note we are playing, this immediately starts
at the maximum volume i.e. amplitude = 1&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(note[1:300], type = &amp;#39;l&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-11-sound-adsr_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;attack-decay-sustain-release-linear&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Attack Decay Sustain Release (linear)&lt;/h2&gt;
&lt;p&gt;Instead of a note staying at the same loudness/amplitude for its duration,
we instead shape the note using an envelope.&lt;/p&gt;
&lt;p&gt;A common way of shaping the profile of a note is via ADSR - Attack, Decay,
Sustain and Release.&lt;/p&gt;
&lt;p&gt;Note this code is only creating a piecewise-linear profile. Better sounding
envelopes are possible using exponentials.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create an ADSR profile of the given length - using only linear segments
#&amp;#39; 
#&amp;#39; @param N length of profile (integer)
#&amp;#39; @param a,d,r fractions of the profile devoted to attack, decay and release
#&amp;#39;        respectively
#&amp;#39; @param s the level of sustain in range [0,1].  The duration of the sustain
#&amp;#39;        will be the remaining fraction after attack, decay and release
#&amp;#39;        are accounted for
#&amp;#39;
#&amp;#39; @return numeric vector in range [0,1] of length N which defines a 
#&amp;#39;         volumn envelope for the note.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_adsr_profile &amp;lt;- function(N, a, d, s, r) {
   
  dur &amp;lt;- 1 - a - d - r
  stopifnot(dur &amp;gt;= 0)
  
  profile &amp;lt;- c(
    seq(0, 1, length.out = a * N),
    seq(1, s, length.out = d * N),
    rep(s, length.out = dur * N),
    seq(s, 0, length.out = r * N)
  )
  
  # Ensure we have the right number of elements in case of weird rounding
  length(profile) &amp;lt;- N
  profile[is.na(profile)] &amp;lt;- 0
  
  profile
}


profile &amp;lt;- create_adsr_profile(500, 0.25, 0.25, 0.8, 0.25)
plot(profile, type = &amp;#39;l&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-11-sound-adsr_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Compare the sounds of a &lt;em&gt;raw&lt;/em&gt; note, and a note profiled with ADSR&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;note1 &amp;lt;- create_note(440, 0.5)
plot(note1, type = &amp;#39;l&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-11-sound-adsr_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
profile &amp;lt;- create_adsr_profile(length(note1), 0.1, 0.25, 0.2, 0.6)
note2 &amp;lt;- note1 * profile
plot(note2, type = &amp;#39;l&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-11-sound-adsr_files/figure-html/unnamed-chunk-5-2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;play_note(note1)
play_note(note2)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;raw-note-1&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Raw note&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/sample1.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;note-adjusted-with-adsr-profile&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Note adjusted with ADSR profile&lt;/h4&gt;
&lt;p&gt;&lt;audio controls=&#34;controls&#34; &gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/sample2.wav&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio element.
&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;The profiled note should sound less “harsh” than the raw note - possibly
more like a real note from a hypothetical instrument!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;worlds-simplest-r-mustic-system---with-linear-adsr-profile-shaping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;World’s simplest R mustic system - with linear ADSR profile shaping&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Octaves/Notes/Frequencies in an equal tempered scale
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ets &amp;lt;- tibble(
  freq   = 440 * (2 ^ ((-57:50)/12)),
  note   = rep(c(&amp;#39;C&amp;#39;, &amp;#39;C#&amp;#39;, &amp;#39;D&amp;#39;, &amp;#39;D#&amp;#39;, &amp;#39;E&amp;#39;, &amp;#39;F&amp;#39;, &amp;#39;F#&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;G#&amp;#39;, &amp;#39;A&amp;#39;, &amp;#39;A#&amp;#39;, &amp;#39;B&amp;#39;), 9),
  octave = rep(0:8, each = 12),
  mnote  = ifelse(nchar(note) == 1, paste(note, octave, sep = &amp;quot;-&amp;quot;), paste(note, octave, sep = &amp;quot;&amp;quot;))
)

head(ets)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note-to-Freq lookup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
freq &amp;lt;- setNames(ets$freq, ets$mnote)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function: Play a note of the given frequency for the given duration
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
play_note &amp;lt;- function(freq, duration) {
  t &amp;lt;- seq(duration * 44100)
  samples &amp;lt;- sin((t) * 2*pi/ (44100/freq))
  
  profile &amp;lt;- create_adsr_profile(length(samples), 0.1, 0.25, 0.2, 0.6)
  samples &amp;lt;- samples * profile

  audio::play(samples, rate = 44100)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mary had a little lamb.
# Format is &amp;quot;[Note]-[Octave]&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mhall &amp;lt;- c(
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;,  &amp;#39;A-4&amp;#39;,  &amp;#39;A-4&amp;#39;,  &amp;#39;A-4&amp;#39;,
  &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;C-5&amp;#39;, &amp;#39;C-5&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (note in mhall) {
  play_note(freq[[note]], 0.4)
  Sys.sleep(0.4)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;live-capture-of-mary-had-a-little-lamb---with-adsr-note-shaping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Live capture of “Mary had a little lamb” - with ADSR note shaping&lt;/h2&gt;
&lt;p&gt;This will sound as if someone is playing this on a toy piano or similar
low quality instrument. But at least it doesn’t sound too harsh.&lt;/p&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/mhall-adsr.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;live-capture-of-mary-had-a-little-lamb---raw-note-unmodified-sine-curve&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Live capture of “Mary had a little lamb” - raw note (unmodified sine curve)&lt;/h2&gt;
&lt;p&gt;This sounds harsh and clipped. Not as pleasant as the notes shaped with ADSR.&lt;/p&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/mhall.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>World&#39;s simplest R music system</title>
      <link>https://coolbutuseless.github.io/2022/07/10/worlds-simplest-r-music-system/</link>
      <pubDate>Sun, 10 Jul 2022 20:55:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/10/worlds-simplest-r-music-system/</guid>
      <description>


&lt;div id=&#34;worlds-simplest-r-mustic-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;World’s simplest R mustic system&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Octaves/Notes/Frequencies in an equal tempered scale
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ets &amp;lt;- tibble(
  freq   = 440 * (2 ^ ((-57:50)/12)),
  note   = rep(c(&amp;#39;C&amp;#39;, &amp;#39;C#&amp;#39;, &amp;#39;D&amp;#39;, &amp;#39;D#&amp;#39;, &amp;#39;E&amp;#39;, &amp;#39;F&amp;#39;, &amp;#39;F#&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;G#&amp;#39;, &amp;#39;A&amp;#39;, &amp;#39;A#&amp;#39;, &amp;#39;B&amp;#39;), 9),
  octave = rep(0:8, each = 12),
  mnote  = ifelse(nchar(note) == 1, paste(note, octave, sep = &amp;quot;-&amp;quot;), paste(note, octave, sep = &amp;quot;&amp;quot;))
)

head(ets)
#&amp;gt; # A tibble: 6 × 4
#&amp;gt;    freq note  octave mnote
#&amp;gt;   &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;  &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;
#&amp;gt; 1  16.4 C          0 C-0  
#&amp;gt; 2  17.3 C#         0 C#0  
#&amp;gt; 3  18.4 D          0 D-0  
#&amp;gt; 4  19.4 D#         0 D#0  
#&amp;gt; 5  20.6 E          0 E-0  
#&amp;gt; 6  21.8 F          0 F-0

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note-to-Freq lookup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
freq &amp;lt;- setNames(ets$freq, ets$mnote)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function: Play a note of the given frequency for the given duration
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
play_note &amp;lt;- function(freq, duration) {
  t &amp;lt;- seq(duration * 44100)
  audio::play(sin((t) * 2*pi/ (44100/freq)), rate = 44100)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mary had a little lamb.
# Format is &amp;quot;[Note]-[Octave]&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mhall &amp;lt;- c(
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;,  &amp;#39;A-4&amp;#39;,  &amp;#39;A-4&amp;#39;,  &amp;#39;A-4&amp;#39;,
  &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;C-5&amp;#39;, &amp;#39;C-5&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;A-4&amp;#39;,
  &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;A-4&amp;#39;, &amp;#39;G-4&amp;#39;, &amp;#39;F-4&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (note in mhall) {
  play_note(freq[[note]], 0.4)
  Sys.sleep(0.4)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;live-capture-of-mary-had-a-little-lamb&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Live capture of “Mary had a little lamb”&lt;/h2&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/mhall/mhall.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>{isocubes} v0.1.2 update with Signed Distance Fields</title>
      <link>https://coolbutuseless.github.io/2022/07/01/isocubes-v0.1.2-update-with-signed-distance-fields/</link>
      <pubDate>Fri, 01 Jul 2022 15:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/07/01/isocubes-v0.1.2-update-with-signed-distance-fields/</guid>
      <description>


&lt;div id=&#34;isocubes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;isocubes &lt;img src=&#34;https://coolbutuseless.github.io/img/isocubes/logo.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/isocubes/actions/workflows/R-CMD-check.yaml&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/isocubes/actions/workflows/R-CMD-check.yaml/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The purpose of this package is to provide a 3D rendering backend for a very
particular visual aesthetic.&lt;/p&gt;
&lt;p&gt;That is, &lt;code&gt;{isocubes}&lt;/code&gt; is an isometric rendering canvas with cubes as the only graphics primitive.&lt;/p&gt;
&lt;p&gt;Some tools are included for creating particular scenes, but in general, if
you can provide a list of (x,y,z) integer coorindates of what to render, then
isocumes will create a 3d render.&lt;/p&gt;
&lt;div id=&#34;whats-new-in-v0.1.2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s new in v0.1.2&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Signed distance fields for creating objects&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/isocubes&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/isocubes&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;fake-terrain-with-ambient&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Fake Terrain with &lt;code&gt;ambient&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(ggplot2)
library(dplyr)
library(ambient)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create some perline noise on an NxN grid
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set.seed(3)
N &amp;lt;- 60

dat &amp;lt;- long_grid(x = seq(0, 10, length.out = N), y = seq(0, 10, length.out = N)) %&amp;gt;% 
  mutate(
    noise = 
      gen_perlin(x, y, frequency = 0.3) + 
      gen_perlin(x, y, frequency = 2) / 10
  ) 

hm &amp;lt;- dat %&amp;gt;%
  mutate(
    x = x * 4,
    z = y * 4,
    y = noise * 4
  )

pal  &amp;lt;- topo.colors(11)
sy   &amp;lt;- as.integer(10 * (hm$y - min(hm$y)) / diff(range(hm$y))) + 1
cols &amp;lt;- pal[sy]

cubes  &amp;lt;- isocubesGrob(hm, ysize = 1/45, xo = 0.7, fill = cols, col = NA)

grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-01-isocubes_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bitmap-font-rendering&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bitmap font rendering&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(isocubes)
library(bdftools)


bdf &amp;lt;- bdftools::read_bdf_builtin(&amp;quot;spleen-32x64.bdf&amp;quot;)
single_word &amp;lt;- bdftools::bdf_create_df(bdf, &amp;quot;#RStats!&amp;quot;)

N    &amp;lt;- 10
cols &amp;lt;- rainbow(N)

multiple_words &amp;lt;- purrr::map_dfr(seq(N), function(i) {
  single_word$z &amp;lt;- i
  single_word$col &amp;lt;- cols[i]
  single_word
}) 

cubes  &amp;lt;- isocubesGrob(multiple_words, ysize = 1/170, xo = 0.1, fill = multiple_words$col)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-01-isocubes_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;signed-distance-fields---simple&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Signed Distance Fields - Simple&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(dplyr)
library(isocubes)

# Create a scene that consists of a scaled torus
scene &amp;lt;- sdf_torus(3, 1) %&amp;gt;% 
  sdf_scale(5)

# Render the scene into a list of coordinates of voxels inside objects
coords &amp;lt;- sdf_render(scene, N = 30)

# Create cubes, and draw
cubes  &amp;lt;- isocubesGrob(coords, ysize = 1/50, xo = 0.5, yo = 0.5, fill = &amp;#39;lightblue&amp;#39;)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-01-isocubes_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;signed-distance-fields---more-complex&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Signed Distance Fields - More Complex&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(grid)
library(isocubes)


sphere &amp;lt;- sdf_sphere() %&amp;gt;%
  sdf_scale(40)

box &amp;lt;- sdf_box() %&amp;gt;%
  sdf_scale(32)

cyl &amp;lt;- sdf_cyl() %&amp;gt;%
  sdf_scale(16)

scene &amp;lt;- sdf_subtract_smooth(
  sdf_intersect(box, sphere),
  sdf_union(
    cyl,
    sdf_rotatey(cyl, pi/2),
    sdf_rotatex(cyl, pi/2)
  )
)

coords &amp;lt;- sdf_render(scene, 50)
cubes  &amp;lt;- isocubesGrob(coords, ysize = 1/100, xo = 0.5, yo = 0.5, fill = &amp;#39;lightseagreen&amp;#39;)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-07-01-isocubes_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;signed-distance-fields---animated&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Signed Distance Fields - Animated&lt;/h2&gt;
&lt;p&gt;Unfortunately this isn’t fast enough to animate in realtime, so I’ve
stitched together individuall saved frames to create an animation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;thetas &amp;lt;- seq(0, pi, length.out = 45)

for (i in seq_along(thetas)) {
  cat(&amp;#39;.&amp;#39;)
  theta &amp;lt;- thetas[i]
  
  rot_scene &amp;lt;- scene %&amp;gt;% 
    sdf_rotatey(theta) %&amp;gt;%
    sdf_rotatex(theta * 2) %&amp;gt;%
    sdf_rotatez(theta / 2)
  
  coords &amp;lt;- sdf_render(rot_scene, 50)
  cubes  &amp;lt;- isocubesGrob(coords, ysize = 1/110, xo = 0.5, yo = 0.5)
  
  png_filename &amp;lt;- sprintf(&amp;quot;working/anim/%03i.png&amp;quot;, i)
  png(png_filename, width = 800, height = 800)
  grid.draw(cubes)
  dev.off()
}

# ffmpeg -y -framerate 20 -pattern_type glob -i &amp;#39;anim/*.png&amp;#39; -c:v libx264 -pix_fmt yuv420p -s 800x800 &amp;#39;anim.mp4&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/isocubes/sdf.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical Bits&lt;/h2&gt;
&lt;div id=&#34;cube-occlusion&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Cube occlusion&lt;/h4&gt;
&lt;p&gt;In an isometric view, a cube at position &lt;code&gt;(x, y, z)&lt;/code&gt; will block the view
of any cube at &lt;code&gt;(x + n, y - n, z + n)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since cube positions must be integer values, hashes of cube positions are
calculated as &lt;code&gt;x + (y * 256) + (z * 256^2)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For each initial cube position, calculate the hash or coordinates of several
occluded cubes. Then remove any initial cubes which match the occluded cube
hashes.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;cube-sort&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Cube sort&lt;/h4&gt;
&lt;p&gt;Arrange cubes by &lt;code&gt;-x&lt;/code&gt;, &lt;code&gt;-z&lt;/code&gt; then &lt;code&gt;y&lt;/code&gt; to ensure cubes are drawn in the correct
ordering such that cubes in front are drawn over the top of cubes which
are behind.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;grob&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;grob&lt;/h4&gt;
&lt;p&gt;All the faces of all the cubes are then calculated as polygons - each with
4 vertices.&lt;/p&gt;
&lt;p&gt;The data for all polygons is then concatenated into a single &lt;code&gt;polygonGrob()&lt;/code&gt;
call with an appropiate vector for &lt;code&gt;id.lengths&lt;/code&gt; to split the data.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;prototyping&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Prototyping&lt;/h4&gt;
&lt;p&gt;Most of the prototyping for this package was done with &lt;a href=&#34;https://github.com/coolbutuseless/ingrid&#34;&gt;&lt;code&gt;{ingrid}&lt;/code&gt;&lt;/a&gt; -
a package I wrote which I find makes working iteratively/at-the-console with base grid graphics
a bit easier.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing isocubes - an isometric rendering backend</title>
      <link>https://coolbutuseless.github.io/2022/06/21/introducing-isocubes-an-isometric-rendering-backend/</link>
      <pubDate>Tue, 21 Jun 2022 16:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/06/21/introducing-isocubes-an-isometric-rendering-backend/</guid>
      <description>


&lt;div id=&#34;isocubes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;isocubes &lt;img src=&#34;https://coolbutuseless.github.io/img/isocubes/logo.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{isocubes}&lt;/code&gt; is an isometric rendering canvas with cubes as the only graphics primitive.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isocubesGrob()&lt;/code&gt; to convert 3d integer coordinates into a grob for plotting&lt;/li&gt;
&lt;li&gt;&lt;code&gt;coord_heightmap()&lt;/code&gt; to create coordinates for a heightmap from a matrix and (optional)
colour information&lt;/li&gt;
&lt;li&gt;&lt;code&gt;coord_sphere()&lt;/code&gt; to create coordinates for all isocubes within a sphere&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;coordinate-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Coordinate system&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The size and positioning of the isometric coordinate system is controlled by
arguments &lt;code&gt;isocubesGrob(coords, max_y, xo, yo)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xo&lt;/code&gt; and &lt;code&gt;yo&lt;/code&gt; give the positition of the origin of the isometric view within
the graphics window. These are fractional values which will be interpreted
as &lt;code&gt;snpc&lt;/code&gt; units i.e. fractional width and height of the graphics devices.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_y&lt;/code&gt; is the main control for cube sizing. This value is the number of
cubes that can be stacked to fill the vertical extents of the window.
Higher values of &lt;code&gt;max_y&lt;/code&gt; means smaller cubes.&lt;/li&gt;
&lt;li&gt;The isometric view is a left-handed coordinate system with &lt;code&gt;y&lt;/code&gt; vertical.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;(x, y, z)&lt;/code&gt; coordinates given to position the cubes will be rounded to the
nearest integer. There is no fractional positioning of cubes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/isocubes/coordinate-system.png&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;why-isometric&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Why isometric?&lt;/h4&gt;
&lt;p&gt;Isometric cubes have advantages over other axonometric and perspective coordinate
systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No perspective correction needed.&lt;/li&gt;
&lt;li&gt;No foreshortening along different dimensions.&lt;/li&gt;
&lt;li&gt;The cube is just a hexagon with each third shaded differently, and the
polygons for each face are trivial to calculate and draw.&lt;/li&gt;
&lt;li&gt;The rules for occlusion are simple i.e. it’s easy to cull cubes
from the drawing process if they’re hidden behind other cubes and won’t
be seen. Fewer cubes mean a faster rendering time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/isocubes&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/isocubes&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;r-in-isocubes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;‘R’ in isocubes&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(purrr)
library(isocubes)

x &amp;lt;- c(9, 8, 7, 6, 5, 4, 3, 2, 10, 9, 3, 2, 11, 10, 3, 2, 11, 10, 
3, 2, 11, 10, 3, 2, 11, 10, 3, 2, 10, 9, 3, 2, 9, 8, 7, 6, 5, 
4, 3, 2, 10, 9, 3, 2, 11, 10, 3, 2, 11, 10, 3, 2, 11, 10, 3, 
2, 11, 10, 3, 2, 11, 10, 3, 2, 11, 10, 3, 2)

y &amp;lt;- c(15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 
13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 
9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 
4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1)

coords &amp;lt;- data.frame(x = x, y = y, z = 0)
cubes  &amp;lt;- isocubesGrob(coords, max_y = 25)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/example-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Colour the cubes with rainbow
cubes &amp;lt;- isocubesGrob(coords, fill = rainbow(nrow(coords)), max_y = 25)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/example-2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# VaporWave palette
cubes &amp;lt;- isocubesGrob(coords, fill = &amp;#39;#ff71ce&amp;#39;, fill_left = &amp;#39;#01cdfe&amp;#39;,
                      fill_right = &amp;#39;#05ffa1&amp;#39;, max_y = 25)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/example-3.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Nightmare palette
cubes &amp;lt;- isocubesGrob(coords, 
                      fill = rainbow(nrow(coords)), 
                      fill_left = &amp;#39;hotpink&amp;#39;,
                      fill_right = viridisLite::inferno(nrow(coords)), 
                      max_y = 25, col = NA)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/example-4.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;calculate-isocubes-within-a-sphere&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Calculate isocubes within a sphere&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(isocubes)

N      &amp;lt;- 13
coords &amp;lt;- expand.grid(x=seq(-N, N), y = seq(-N, N), z = seq(-N, N))
keep   &amp;lt;- with(coords, sqrt(x * x + y * y + z * z)) &amp;lt; N
coords &amp;lt;- coords[keep,]

cubes &amp;lt;- isocubesGrob(coords, max_y = 35, xo = 0.5, yo = 0.5)
grid.newpage()
grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/sphere-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;random-rainbow-volume-of-isocubes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Random rainbow volume of isocubes&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(isocubes)

N      &amp;lt;- 15
coords &amp;lt;- expand.grid(x=0:N, y=0:N, z=0:N)
coords &amp;lt;- coords[sample(nrow(coords), 0.66 * nrow(coords)),]
fill   &amp;lt;- rgb(red = 1 - coords$x / N, coords$y /N, 1 - coords$z/N, maxColorValue = 1)

cubes &amp;lt;- isocubesGrob(coords, fill, max_y = 40, occlusion_depth = 4)
grid.newpage()
grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/rainbow-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;heightmap-as-isocubes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Heightmap as isocubes&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Prepare a matrix of values
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat &amp;lt;- volcano

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# An optional matrix of colours
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
val &amp;lt;- as.vector(mat)
val &amp;lt;- round(255 * (val - min(val)) / diff(range(val)))
col &amp;lt;- viridisLite::viridis(256)[val + 1L]
dim(col) &amp;lt;- dim(mat) 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Find the (integer) coordiinates of the cubes in the heightmap
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
coords &amp;lt;- coords_heightmap(mat - min(mat), col = col, scale = 0.3)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert the coordinates into a grob
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cubes  &amp;lt;- isocubesGrob(coords, max_y = 100, fill = coords$col, xo = 0.8)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;image-as-isocubes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Image as isocubes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Treat image to a heightmap&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Load image and convert to a matrix of heights
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
img &amp;lt;- png::readPNG(&amp;quot;../../static/img/isocubes/Rlogo-small-blur.png&amp;quot;)
ht        &amp;lt;- round( 10 * (1 - img[,,2]) ) # Use Green channel intensity as height
ht[,1]    &amp;lt;- 0 # image editing to remove some artefacts

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A matrix of colours extracted from the image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
col       &amp;lt;- rgb(img[,,1], img[,,2], img[,,3])
dim(col)  &amp;lt;- dim(ht) 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# convert to cubes and draw
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
coords &amp;lt;- coords_heightmap(ht, col = col, ground = &amp;#39;xy&amp;#39;)
cubes  &amp;lt;- isocubesGrob(coords, max_y = 130, fill = coords$col, col = NA)
grid.newpage(); grid.draw(cubes)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-20-isocubes_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical Bits&lt;/h2&gt;
&lt;div id=&#34;cube-occlusion&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Cube occlusion&lt;/h4&gt;
&lt;p&gt;In an isometric view, a cube at position &lt;code&gt;(x, y, z)&lt;/code&gt; will block the view
of any cube at &lt;code&gt;(x + n, y - n, z + n)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since cube positions must be integer values, hashes of cube positions are
calculated as &lt;code&gt;x + (y * 256) + (z * 256^2)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For each initial cube position, calculate the hash or coordinates of several
occluded cubes. Then remove any initial cubes which match the occluded cube
hashes.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;cube-sort&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Cube sort&lt;/h4&gt;
&lt;p&gt;Arrange cubes by &lt;code&gt;-x&lt;/code&gt;, &lt;code&gt;-z&lt;/code&gt; then &lt;code&gt;y&lt;/code&gt; to ensure cubes are drawn in the correct
ordering such that cubes in front are drawn over the top of cubes which
are behind.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;grob&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;grob&lt;/h4&gt;
&lt;p&gt;All the faces of all the cubes are then calculated as polygons - each with
4 vertices.&lt;/p&gt;
&lt;p&gt;The data for all polygons is then concatenated into a single &lt;code&gt;polygonGrob()&lt;/code&gt;
call with an appropiate vector for &lt;code&gt;id.lengths&lt;/code&gt; to split the data.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Nesting Functions</title>
      <link>https://coolbutuseless.github.io/2022/06/15/nesting-functions/</link>
      <pubDate>Wed, 15 Jun 2022 09:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/06/15/nesting-functions/</guid>
      <description>


&lt;div id=&#34;introduction&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Many structured formats for documents and data have a natural nested hierarchy.&lt;/p&gt;
&lt;p&gt;That is, there are lower-level elements nested within higher level structures&lt;/p&gt;
&lt;p&gt;A great xample of a nested document creation using nested function calls is HTML creation with &lt;code&gt;{htmltools}&lt;/code&gt;. In the code below, the call to create the &lt;code&gt;body()&lt;/code&gt; is
&lt;em&gt;nested within&lt;/em&gt; the function call to create the top-level &lt;code&gt;html()&lt;/code&gt; document.&lt;/p&gt;
&lt;p&gt;The structure of the nested function calls in R match the structure of
the created HTML document. This is both aesthetically pleasing, and low friction
e.g. it’s easy to work out the structure of the input if you know what you
want as the output (and vice versa).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(htmltools) 

tags$html(
  tags$body(
    tags$p(&amp;#39;...&amp;#39;), 
    tags$p(&amp;#39;...&amp;#39;)
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;p&amp;gt; ... &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt; ... &amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;However&lt;/strong&gt; there are many document formats where the current tools do
not support this idea of nested creation. This may be because the
underlying C library or API doesn’t really support the concept.&lt;/p&gt;
&lt;p&gt;A (contrived) example of this is the creation of &lt;code&gt;{grid}&lt;/code&gt; graphics with nested viewports.&lt;/p&gt;
&lt;p&gt;The following code creates two nested&lt;code&gt;viewport&lt;/code&gt; and then draw squares within them.&lt;br /&gt;
I’m calling this style of document creation &lt;strong&gt;linear&lt;/strong&gt; (in contrast to &lt;strong&gt;nested&lt;/strong&gt;).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
grid.newpage()
vp1 &amp;lt;- viewport(x = 0.5, y = 0.5, angle = 22.5)
pushViewport(vp1)
grid.rect(width=20, height=20, default.units = &amp;#39;mm&amp;#39;, gp = gpar(fill=&amp;#39;hotpink&amp;#39;))
vp2 &amp;lt;- viewport(x = 0.5, y = 0.5, angle = 22.5)
pushViewport(vp2)
grid.rect(width=10, height=10, default.units = &amp;#39;mm&amp;#39;, gp = gpar(fill=&amp;#39;blue&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-06-15-nesting-functions_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;A hypothetical alterative &lt;em&gt;nested&lt;/em&gt; syntax for grid graphics creation could look
like the following code.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;viewport(
  angle = 22.5,
  grid.rect(...),
  viewport(
    angle = 22.5,
    grid.rect(...)
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code, the nested makes clearer the relationship between the
viewports and the rectangles.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-use-case-document-creation&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;My use-case: document creation&lt;/h1&gt;
&lt;p&gt;I am working through a situation where the tools available are &lt;em&gt;linear&lt;/em&gt; (because
of the underlying C library), but I want a &lt;em&gt;nested&lt;/em&gt; structure exposed to the
user.&lt;/p&gt;
&lt;p&gt;In its simplest form, my use case is for the creation of a document consisting
of multiple paragraphs. Each paragraph in turn consisting of multiple sentences.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;document
    paragraph
        sentence
        sentence
    paragraph
        sentence
        sentence
        sentence&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The constraints on this problem are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The creation of the document, paragraph and sentence should each
be separate functions.&lt;/li&gt;
&lt;li&gt;There is a &lt;code&gt;document&lt;/code&gt; object which all the functions manipulate.&lt;/li&gt;
&lt;li&gt;The final &lt;code&gt;document&lt;/code&gt; is returned to the user&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following post details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The current &lt;em&gt;linear&lt;/em&gt; structure for document creation&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;nested&lt;/em&gt; structure for document creation&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;current-linear-function-structure&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Current &lt;em&gt;linear&lt;/em&gt; function structure&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Document is stored in a list
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
new_doc &amp;lt;- function() {
  list(par = 0, words = list())
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Creating a new paragraph increases the &amp;#39;par&amp;#39; counts and prepares some
# space for the words in this paragraph
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
new_par &amp;lt;- function(doc) {
  doc$par &amp;lt;- doc$par + 1
  doc$words[[doc$par]] &amp;lt;- list()
  doc
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add a sentence to the current paragraph
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
new_sentence &amp;lt;- function(doc, words) {
  doc$words[[doc$par]] &amp;lt;- append(doc$words[[doc$par]], words)
  doc
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Simple print method
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print_doc &amp;lt;- function(doc) {
  for (i in seq_along(doc$words)) {
    cat(strwrap(paste(doc$words[[i]], collapse = &amp;quot; &amp;quot;), width = 20), sep = &amp;quot;\n&amp;quot;)
    if (i != length(doc$words)) cat(&amp;quot;\n&amp;quot;)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;linear-function-calls&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Linear function calls&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Modify the `document` with every call
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my_doc &amp;lt;- new_doc()
my_doc &amp;lt;- new_par(my_doc)
my_doc &amp;lt;- new_sentence(my_doc, &amp;quot;Hello there.&amp;quot;)
my_doc &amp;lt;- new_sentence(my_doc, &amp;quot;My name is greg.&amp;quot;)
my_doc &amp;lt;- new_par(my_doc)
my_doc &amp;lt;- new_sentence(my_doc, &amp;quot;Start of second par.&amp;quot;)

print_doc(my_doc)
#&amp;gt; Hello there. My
#&amp;gt; name is greg.
#&amp;gt; 
#&amp;gt; Start of second
#&amp;gt; par.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Notes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;document&lt;/code&gt; object must be passed in to each function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;document&lt;/code&gt; object is modified and returned by each function&lt;/li&gt;
&lt;li&gt;There is no auto indentation in R which would indicate which sentences
go with which paragraphs i.e. the &lt;em&gt;linear&lt;/em&gt; structure of the functions
don’t reveal the nested structure of the document when coding.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr/&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;nested-function-structure&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Nested function structure&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Nested evaluation 
# @param ... child elements are evaluated after the parent is created
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc &amp;lt;- function(...) {
  # Create document
  document &amp;lt;- as.environment(list(par = 0, words = c()))
  
  # Evaluate child &amp;#39;par&amp;#39; elements within this document
  # Adapt the call for child elements to include a &amp;#39;document&amp;#39; as argument
  for (elem in rlang::enquos(...)) {
    elem &amp;lt;- rlang::call_modify(elem, document = document)
    rlang::eval_tidy(elem)
  }
  
  as.list(document)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add a paragraph to the current document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
par &amp;lt;- function(document, ...) {
  document$par &amp;lt;- document$par + 1
  document$words[[document$par]] &amp;lt;- list()
  for (elem in rlang::enquos(...)) {
    elem &amp;lt;- rlang::call_modify(elem, document = document)
    rlang::eval_tidy(elem, env = sys.frame())
  }
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add words to the current paragraph
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sentence &amp;lt;- function(document, words) {
  document$words[[document$par]] &amp;lt;- append(document$words[[document$par]], words)
}&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;nested-function-calls&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Nested function calls&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_doc &amp;lt;- doc(
  par(
    sentence(&amp;quot;Hello there.&amp;quot;),
    sentence(&amp;quot;My name is Greg.&amp;quot;)
  ),
  par(
    sentence(&amp;quot;Start of second par.&amp;quot;)
  )
)

print_doc(my_doc)
#&amp;gt; Hello there. My
#&amp;gt; name is Greg.
#&amp;gt; 
#&amp;gt; Start of second
#&amp;gt; par.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;notes-1&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Notes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Code structure now mimics document structure&lt;/li&gt;
&lt;li&gt;Internally adapting the function calls so that the user does not need
to specify the passing of the &lt;code&gt;document&lt;/code&gt; to each call. This simplifies
the users code at the cost of complicating the functions a little.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing `{tickle}` quickly build UIs in base R</title>
      <link>https://coolbutuseless.github.io/2022/06/03/introducing-tickle-quickly-build-uis-in-base-r/</link>
      <pubDate>Fri, 03 Jun 2022 15:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/06/03/introducing-tickle-quickly-build-uis-in-base-r/</guid>
      <description>


&lt;div id=&#34;tickle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;tickle &lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/logo-tickle.png&#34; align=&#34;right&#34; width=&#34;230&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/tickle/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/tickle/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{tickle}&lt;/code&gt; is a package for creating UIs in base R.&lt;/p&gt;
&lt;p&gt;This is an &lt;strong&gt;opinionated abstraction&lt;/strong&gt; over the base R package &lt;code&gt;{tcltk}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This package aims to provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;simplified&lt;/strong&gt; UI creation process similar to &lt;code&gt;shiny&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;modern-looking&lt;/strong&gt; visual default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;more documentation&lt;/strong&gt; to help create common UI elements without resorting to the online tcl/tk
documentation.&lt;/li&gt;
&lt;li&gt;a way to still access the low-level tcl/tk structures in order to achieve
complex effects and customisation.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An array of &lt;code&gt;tic_*()&lt;/code&gt; functions for nested creation of a UI specification.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;render_ui()&lt;/code&gt; to render a UI specification into a window onscreen.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reactive_*()&lt;/code&gt; to create reactive values used to transfer values between
the UI and R&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_*()&lt;/code&gt; functions to do some simple drawing an manipulation on canvas widgets.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create reactive variables (with &lt;code&gt;reactive_*()&lt;/code&gt;) in order to pass values between R and the UI. e.g. the
value of the slider, or the text in a text entry box.&lt;/li&gt;
&lt;li&gt;Define callback functions that are called, say, when a button is pressed.&lt;/li&gt;
&lt;li&gt;Create a UI specification by nesting containers and widgets with &lt;code&gt;tic_*()&lt;/code&gt; calls. This specification can include
&lt;ul&gt;
&lt;li&gt;binding callback functions to particular events like mouse buttons or key presses (&lt;code&gt;bind&lt;/code&gt; argument)&lt;/li&gt;
&lt;li&gt;controlling how widgets are packed within their parent container (&lt;code&gt;pack&lt;/code&gt; argument)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Render the UI to an actual object on the screen with &lt;code&gt;render_ui()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The object returned by &lt;code&gt;render_ui()&lt;/code&gt; can be ignored by beginners. For intermediate/advanced users,
this object is a nested list of &lt;code&gt;tclObj&lt;/code&gt; objects representing the UI components,
and these can be further manipulated with &lt;code&gt;{tcltk}&lt;/code&gt; to finesse and configure the UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/tickle&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/tickle&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;hello-world&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hello World&lt;/h2&gt;
&lt;p&gt;Things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define a reactive variable for the slider before defining the UI&lt;/li&gt;
&lt;li&gt;UI specificaiton created with nested &lt;code&gt;tic_*()&lt;/code&gt; calls.&lt;/li&gt;
&lt;li&gt;Some commands (e.g. &lt;code&gt;tic_button()&lt;/code&gt;) have an explicit command function which
is run when they are activated.&lt;/li&gt;
&lt;li&gt;After defining the UI specificaiton, it is rendered to screen with &lt;code&gt;render_ui()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tickle)

value &amp;lt;- reactive_dbl(40)

ui_spec &amp;lt;- tic_window(
  title = &amp;quot;Hello World&amp;quot;, 
  tic_row(
    tic_col(
      tic_button(&amp;quot;Hello&amp;quot;, command = function() {message(&amp;quot;Hello&amp;quot;)}, style = &amp;#39;primary&amp;#39;),
      tic_button(&amp;quot;World&amp;quot;, command = function() {message(&amp;quot;World&amp;quot;)})
    ),
    tic_col(
      tic_slider(value),
      tic_label(textvariable = value)
    )
  )
)

win &amp;lt;- render_ui(ui_spec)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/helloworld.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;gallery&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Gallery&lt;/h2&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/detailed-example.html&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/demo-complex.png&#34; width=&#34;60%&#34; /&gt;
&lt;/a&gt;
&lt;hr /&gt;
&lt;br /&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/juliaset.html&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/julia.png&#34; width=&#34;60%&#34; /&gt;
&lt;/a&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;br /&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/ggreview.html&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/ggreview-snap.png&#34; width=&#34;60%&#34; /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;examplesvignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Examples/Vignettes&lt;/h2&gt;
&lt;p&gt;Please view the online vignettes for more details on how to use &lt;code&gt;{tickle}&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/detailed-example.html&#34;&gt;Big example with lots of widgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/reactive.html&#34;&gt;Reactive Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/ggreview.html&#34;&gt;Annotate ggplots (using mouse events)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/popups.html&#34;&gt;Pop-up Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/widgets.html&#34;&gt;Overview of all Widgets &amp;amp; Containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/juliaset.html&#34;&gt;JuliaSet explorer (using keyboard events and rendering to a grid window)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/fonts.html&#34;&gt;Changing font&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/tickle/articles/packing.html&#34;&gt;Understanding widget layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;containers&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Containers&lt;/h2&gt;
&lt;p&gt;Containers are ways of grouping multiple widgets.&lt;/p&gt;
&lt;p&gt;Containers can be nested within other containers to achieve complex layouts.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Container&lt;/th&gt;
&lt;th&gt;Code/Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-window.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_window(…)&lt;/code&gt;&lt;br /&gt; Create a top level window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-col.png&#34; width=&#34;100&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_col(A, B, C)&lt;/code&gt;&lt;br /&gt; Layout objects in column&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-row.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_row(A, B, C)&lt;/code&gt;&lt;br /&gt; Layout objects rowwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-frame.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_frame(…)&lt;/code&gt;&lt;br /&gt; Invisible container. Useful for advanced users who want to customize layout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-labelframe.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_labelframe(…)&lt;/code&gt;&lt;br /&gt; Frame with a a label and usually visible outline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-notebook.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_notebook(A, B, C)&lt;/code&gt;&lt;br /&gt; Tabbed display&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/container-panedwindow.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_panedwindow(A, B, C)&lt;/code&gt;&lt;br /&gt; Layout multiple elements which can be resized as panes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;widgets&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Widgets&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Widget&lt;/th&gt;
&lt;th&gt;Code/Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-label.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_label(…)&lt;/code&gt;&lt;br /&gt; Display text. If you need headings rather than body text, Use &lt;code&gt;style = &#39;h1&#39;&lt;/code&gt; to &lt;code&gt;style = &#39;h5&#39;&lt;/code&gt; for different sized text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-button.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_button(…)&lt;/code&gt;&lt;br /&gt; Clickable button. Available &lt;code&gt;style&lt;/code&gt; options: ‘primary’, ‘seconary’, ‘info’, ‘success’, ‘warning’, ‘danger’, ‘light’, ‘dark’&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-checkbutton-default.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_checkbutton(…)&lt;/code&gt;&lt;br /&gt; On/off button (default styling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-checkbutton-toggle.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_checkbutton(…)&lt;/code&gt;&lt;br /&gt; On/off button with &lt;code&gt;style = &#39;toggle&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-checkbutton-switch.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_checkbutton(…)&lt;/code&gt;&lt;br /&gt; On/off button with &lt;code&gt;style = &#39;switch&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-radiobutton.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_radiobutton(…)&lt;/code&gt;&lt;br /&gt; Groups of mutually exclusion options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-menubutton.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_menubutton(…)&lt;/code&gt;&lt;br /&gt; Button which displays a drop-down menu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-canvas.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_canvas(…)&lt;/code&gt;&lt;br /&gt; General drawing canvas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-spinbox.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_spinbox(…)&lt;/code&gt;&lt;br /&gt; Choose options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-combobox.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_combobox(…)&lt;/code&gt;&lt;br /&gt; Choose options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-textentry.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_textentry(…)&lt;/code&gt;&lt;br /&gt; Single line text entry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-textbox.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_textbox(…)&lt;/code&gt;&lt;br /&gt; Multipe line text entry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-progressbar.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_progressbar(…)&lt;/code&gt;&lt;br /&gt; Progress bar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/widget-slider.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tic_slider(…)&lt;/code&gt;&lt;br /&gt; Slider&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;popups&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Popups&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Popups&lt;/em&gt; are windows which are initiated separate from the main UI.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Popup&lt;/th&gt;
&lt;th&gt;Code/Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/popup-color-picker.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;popup_color_picker()&lt;/code&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/popup-messagebox.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;popup_messagebox()&lt;/code&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/popup-open-file.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;popup_open_file()&lt;/code&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/tickle/widgets/popup-save-file.png&#34; width=&#34;200&#34; /&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;popup_save_file()&lt;/code&gt;&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;canvas&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Canvas&lt;/h2&gt;
&lt;p&gt;After creating a canvas with &lt;code&gt;tic_canvas()&lt;/code&gt;, it can be manipulated with the following
commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Draw on the canvas
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;canvas_line()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_text()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_rect()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_polygon()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_oval()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_arc()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_plot()&lt;/code&gt; render a plot to the canvas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_clear()&lt;/code&gt; clear all objects from the canvas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_image()&lt;/code&gt; render an image from a file to the canvas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;canvas_save()&lt;/code&gt; save the contents of the canvas to an image file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The actual canvas in tcl/tk renders &lt;em&gt;structured graphics&lt;/em&gt; and it is much more like
SVG or PDF than just a simple array of pixels.&lt;/p&gt;
&lt;p&gt;The canvas implementation in this package treats the canvas as just a raster
object i.e. a rectangular collection of pixels. This made it easier to write
this package and keep the API/syntax simple, but it doesn’t unleash the full
power of the canvas.&lt;/p&gt;
&lt;p&gt;The effort to write a more complete abstraction over the canvas is
not currently warranted. &lt;strong&gt;Please get in contact if such a facility is important to you.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;theme&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Theme&lt;/h1&gt;
&lt;p&gt;The theme for this package is an adaptaton of the &lt;code&gt;sun-valley-light&lt;/code&gt;
theme available &lt;a href=&#34;https://github.com/rdbende/Sun-Valley-ttk-theme&#34;&gt;from rdbende on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;sun-valley-light&lt;/code&gt; theme is MIT licensed (see “LICENSE-sun-valley”) and has been adapted
into the theme &lt;code&gt;r-sun-valley-light&lt;/code&gt; included in this package which has the following extra features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Styles ‘h1’ through ‘h5’ for different sized heading text to use with &lt;code&gt;tic_label()&lt;/code&gt; widgets.
&lt;ul&gt;
&lt;li&gt;To use: &lt;code&gt;tic_label(..., style = &#39;h1&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Standard buttons colours from &lt;a href=&#34;https://getbootstrap.com/docs/4.0/components/buttons/&#34;&gt;Bootstrap&lt;/a&gt;
to use with &lt;code&gt;tic_button()&lt;/code&gt; widgets.
&lt;ul&gt;
&lt;li&gt;To use: &lt;code&gt;tic_button(..., style = &#39;primary&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Available styles: primary, secondary, success, danger, warning, info, light, dark&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;possible-future-features&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Possible Future Features&lt;/h2&gt;
&lt;p&gt;The following items are not yet implemented, or incomplete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Popup menus when a user right-clicks in the window.&lt;/li&gt;
&lt;li&gt;No access yet to the “grid” geometry layout.&lt;/li&gt;
&lt;li&gt;treeview, listbox and some other widgets&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;package-name&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Package Name&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tcl&lt;/code&gt; is the scripting language&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tk&lt;/code&gt; is the graphics toolkit for &lt;code&gt;tcl&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcl/tk&lt;/code&gt; is often how the langauge and toolkit are talked about as a single entity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{tcltk}&lt;/code&gt; is the R package interfacing to &lt;code&gt;tcl/tk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcl&lt;/code&gt; is often pronounced as “tickle” i.e. &lt;code&gt;tcl/tk&lt;/code&gt; = “tickle-tee-kay”&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing `{tr808r}` a TR-808 Drum Machine in R</title>
      <link>https://coolbutuseless.github.io/2022/05/14/introducing-tr808r-a-tr-808-drum-machine-in-r/</link>
      <pubDate>Sat, 14 May 2022 07:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/05/14/introducing-tr808r-a-tr-808-drum-machine-in-r/</guid>
      <description>


&lt;p&gt;A TR-808 Drum machine in R using &lt;a href=&#34;https://github.com/coolbutuseless/eventloop&#34;&gt;&lt;code&gt;{eventloop}&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Check it out on &lt;a href=&#34;https://github.com/coolbutuseless/tr808r&#34;&gt;github&lt;/a&gt;!&lt;/p&gt;
&lt;div id=&#34;playback&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Playback&lt;/h4&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/tr808r/demo1.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;realtime-interactive-pattern-editing&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Realtime Interactive Pattern Editing&lt;/h4&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/tr808r/compose.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;fetching-patterns-from-tweets&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Fetching patterns from tweets&lt;/h4&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/tr808r/tweetable.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A naive implementation of Visvalingam&#39;s line simplification in R</title>
      <link>https://coolbutuseless.github.io/2022/05/07/a-naive-implementation-of-visvalingams-line-simplification-in-r/</link>
      <pubDate>Sat, 07 May 2022 18:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/05/07/a-naive-implementation-of-visvalingams-line-simplification-in-r/</guid>
      <description>


&lt;div id=&#34;visvalinghams-line-simplification-algorithm&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Visvalingham’s Line Simplification Algorithm&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Given a number of points defining a line&lt;/li&gt;
&lt;li&gt;Find the areas of the triangles defined by each set of 3 continuous points&lt;/li&gt;
&lt;li&gt;Remove the point which is the centre of the triangle with the minimum area&lt;/li&gt;
&lt;li&gt;Recalculate areas (as two will have changed when removing the point)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-r-implementation&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Naive R implementation&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Full set of all triangle areas is calculated prior to the remove of each point
&lt;ul&gt;
&lt;li&gt;A priority queue would help here&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Visvalingham Line Simplification
#&amp;#39;
#&amp;#39; @param x,y coordinates
#&amp;#39; @param n number of points to keep
#&amp;#39;
#&amp;#39; @importFrom utils head tail
#&amp;#39; @export
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
visvalingam &amp;lt;- function(x, y, n) {

  # Sanity Check
  stopifnot(length(x) == length(y))
  stopifnot (n &amp;lt;= length(x) &amp;amp;&amp;amp; n &amp;gt;= 2)
  if (length(x) == 2) {
    return(list(x=x, y=y))
  }

  # Remove points
  for (i in seq_len(length(x) - n)) {
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Find areas
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    x1 &amp;lt;- head(x, -2)
    x2 &amp;lt;- head(x[-1], -1)
    x3 &amp;lt;- tail(x, -2)

    y1 &amp;lt;- head(y, -2)
    y2 &amp;lt;- head(y[-1], -1)
    y3 &amp;lt;- tail(y, -2)

    a0 &amp;lt;- x1 - x2
    a1 &amp;lt;- x3 - x2

    b0 &amp;lt;- y1 - y2
    b1 &amp;lt;- y3 - y2

    tri_areas &amp;lt;- abs(a0 * b1 - a1 * b0)  # / 2

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Find minimim area triangle and remove its centre vertex from all pts
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    min_tri &amp;lt;- which.min(tri_areas)
    
    x &amp;lt;- x[-(min_tri + 1)]
    y &amp;lt;- y[-(min_tri + 1)]
  }

  list(x = x, y = y)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;demo&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;p&gt;This demo shows how visvalingam can be used to tidy up a noisy drawing
of a square&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a messy square
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set.seed(2)
N &amp;lt;- 20
x &amp;lt;- c(seq(0, 1, length.out = N), rep(1, N), seq(1, 0, length.out = N), rep(0, N)) / 2 + 0.25
y &amp;lt;- c(rep(0, N), seq(0, 1, length.out = N), rep(1, N), seq(1, 0, length.out = N)) / 2 + 0.25

x &amp;lt;- x + runif(length(x), -0.02, 0.02)
y &amp;lt;- y + runif(length(x), -0.02, 0.02)

x[1] &amp;lt;- y[1] &amp;lt;- x[N*4] &amp;lt;- y[N*4] &amp;lt;- 0.25

grid::grid.newpage()
grid::grid.lines(x, y)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2022-05-07-visvalingam-line-simplification_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Capture the simplification step by step.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xs &amp;lt;- list()
ys &amp;lt;- list()

for (n in (4*N):5) {
  res &amp;lt;- visvalingam(x, y, n)
  xs &amp;lt;- c(xs, list(res$x))
  ys &amp;lt;- c(ys, list(res$y))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save frames 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in seq_along(xs)) {
  filename &amp;lt;- sprintf(&amp;quot;jnk/%03i.png&amp;quot;, i)
  png(filename)
    grid.lines(xs[[i]], ys[[i]], gp = gpar(lwd= 4))
  dev.off()
}
# ffmpeg -y -framerate 15 -pattern_type glob -i &amp;#39;*.png&amp;#39; -c:v libx264 -pix_fmt yuv420p -s 800x800 anim.mp4&lt;/code&gt;&lt;/pre&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/visvalingam/anim.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;p&gt;Your browser does not support the video tag.
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {eventloop} - Realtime interactive rendering in R</title>
      <link>https://coolbutuseless.github.io/2022/05/06/introducing-eventloop-realtime-interactive-rendering-in-r/</link>
      <pubDate>Fri, 06 May 2022 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/05/06/introducing-eventloop-realtime-interactive-rendering-in-r/</guid>
      <description>


&lt;div id=&#34;eventloop&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;eventloop &lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/eventloop-logo.png&#34; align=&#34;right&#34; width=&#34;230&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/dependencies-zero-blue.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/eventloop/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/eventloop/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;{eventloop}&lt;/code&gt; package provides a framework for rendering interactive graphics
and handling mouse+keyboard events from the user at speeds fast enough to be
considered interesting for games and other realtime applications.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{eventloop}&lt;/code&gt; is a wrapper around the built-in event handling available in
base R as part of &lt;code&gt;{grDevices}&lt;/code&gt;, but presents it in a more palatable format
with some enhanced features.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;{eventloop}&lt;/code&gt; package will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initiate an &lt;code&gt;x11()&lt;/code&gt; window with monitoring for keyboard &amp;amp; mouse events.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Capture events as they happen such that they will be available to the user-supplied function.&lt;/li&gt;
&lt;li&gt;Coordinate the setup of the user-defined callback function to be run
continually with access to the latest event information presented as the
function arguments.&lt;/li&gt;
&lt;li&gt;Optionally limit the frequency of screen updates by maintaining a frame-rate
specified by the user.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At each call, the user’s function processes events and updates the display.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;run_loop()&lt;/code&gt; takes a user-specified function and calls it continuously
within an event-driven loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;supported-platforms&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Supported Platforms&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;9%&#34; /&gt;
&lt;col width=&#34;51%&#34; /&gt;
&lt;col width=&#34;38%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;System&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;x11() device has ‘onIdle()’ event callback&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;System supported in {eventloop}&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;macOS&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✅Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✅Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;*nix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✅Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✅Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Windows&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;❌ No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Notes:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;windows &lt;code&gt;x11()&lt;/code&gt; device does not support &lt;code&gt;onIdle&lt;/code&gt; callback and hence this
package does not work on windows&lt;/li&gt;
&lt;li&gt;macOS &lt;code&gt;x11()&lt;/code&gt; support is via &lt;a href=&#34;https://www.xquartz.org/&#34;&gt;Xquartz&lt;/a&gt;. Xquartz may slow to
a crawl after running for a while. You will need to logout-and-log-back in,
or restart your machine to regain full speed. This bug may be in Xquartz
or how x11() support is implemented in macOS - I’m really not sure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Pre-requisites&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unix-like systems
&lt;ul&gt;
&lt;li&gt;R compiled with X11() support&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;macOS
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.xquartz.org/&#34;&gt;Xquartz&lt;/a&gt; installed&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;windows
&lt;ul&gt;
&lt;li&gt;Sorry, but R on windows does not support features needed for this package&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/eventloop&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---basic-drawing-app&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - Basic Drawing app&lt;/h2&gt;
&lt;p&gt;This is a basic application which lets the user draw in
a window using the mouse.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(eventloop)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up the global variables which store the state of the world
#  &amp;#39;drawing&amp;#39;      = Is the mouse button currently pressed?
#  last_x/last_y  = the last mouse position is manually saved every time
#                 the callback function runs.
#
# These values will be updated manually by the user in the `draw()` function
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drawing &amp;lt;- FALSE
last_x  &amp;lt;- NA
last_y  &amp;lt;- NA

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Callback function - &amp;#39;draw()&amp;#39; 
#&amp;#39;
#&amp;#39; If &amp;#39;event&amp;#39; is not NULL, then it means that the user interacted with the
#&amp;#39; display.  
#&amp;#39; 
#&amp;#39; The following events are handled by this callback:
#&amp;#39;  - hold mouse to set drawing mode
#&amp;#39;  - releasing the mouse button stops drawing mode
#&amp;#39;  - pressing SPACE clears the canvas
#&amp;#39;  
#&amp;#39; Press ESC to quit.
#&amp;#39; 
#&amp;#39; @param event The event from the graphics device. Is NULL when no event
#&amp;#39;        occurred.  Otherwise has `type` element set to:
#&amp;#39;        `event$type = &amp;#39;mouse_down&amp;#39;` 
#&amp;#39;               - an event in which a mouse button was pressed
#&amp;#39;               - `event$button` gives the index of the button
#&amp;#39;        `event$type = &amp;#39;mouse_up&amp;#39;`   
#&amp;#39;               - a mouse button was released
#&amp;#39;        `event$type = &amp;#39;mouse_move&amp;#39;`   
#&amp;#39;               - mouse was moved 
#&amp;#39;        `event$type = &amp;#39;key_press&amp;#39;`  
#&amp;#39;               - a key was pressed
#&amp;#39;               - `event$str` String describing which key was pressed. See \code{grDevices::setGraphicsEventHandlers} for more information.
#&amp;#39; @param mouse_x,mouse_y current location of mouse within window in normalised coordinates in the range [0, 1]. If mouse is 
#&amp;#39;        not within window, this will be set to the last available coordinates
#&amp;#39; @param frame_num Current frame number (integer)
#&amp;#39; @param fps_actual,fps_target the curent framerate and the framerate specified
#&amp;#39;        by the user
#&amp;#39; @param dev_width,dev_height the width and height of the output device. Note:
#&amp;#39;        this does not cope well if you resize the window
#&amp;#39; @param ... any extra arguments ignored
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
draw &amp;lt;- function(event, mouse_x, mouse_y, ...) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Process events
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (!is.null(event)) {
    if (event$type == &amp;#39;mouse_down&amp;#39;) {
      drawing &amp;lt;&amp;lt;- TRUE
    } else if (event$type == &amp;#39;mouse_up&amp;#39;) {
      drawing &amp;lt;&amp;lt;- FALSE
      last_x  &amp;lt;&amp;lt;- NA
      last_y  &amp;lt;&amp;lt;- NA
    } else if (event$type == &amp;#39;key_press&amp;#39; &amp;amp;&amp;amp; event$str == &amp;#39; &amp;#39;) {
      grid::grid.rect(gp = gpar(col=NA, fill=&amp;#39;white&amp;#39;)) # clear screen
    }
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If &amp;#39;drawing&amp;#39; is currently TRUE, then draw a line from last known 
  # coordinates to current mouse coordinates
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (drawing) {
    if (!is.na(last_x)) {
      grid::grid.lines(
        x = c(last_x, mouse_x),
        y = c(last_y, mouse_y),
        gp = gpar(col = &amp;#39;black&amp;#39;)
      )
    }
    
    # Keep track of where the mouse was for the next time we draw
    last_x &amp;lt;&amp;lt;- mouse_x
    last_y &amp;lt;&amp;lt;- mouse_y
  }
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Start the event loop. Press ESC to quit.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eventloop::run_loop(draw, fps_target = NA, double_buffer = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/hello-r.gif&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every time the callback function &lt;code&gt;draw()&lt;/code&gt; is executed from within the event loop, it draws a line from the last mouse position to the current mouse position.&lt;/li&gt;
&lt;li&gt;The position of the mouse during the previous call is saved manually using global variables.&lt;/li&gt;
&lt;li&gt;A boolean variable (&lt;code&gt;drawing&lt;/code&gt;) is used to note whether the mouse button
is currently pressed or not. Changes to the screen only happend if &lt;code&gt;drawing == TRUE&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;gallery-of-puzzles-games-applications-implemented-in-the-vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Gallery of Puzzles, Games + Applications implemented in the vignettes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Click an image to view the code/vignette&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The linked pages contain videos of realtime screen captures which
illustrate how the interactive nature of these applications work.&lt;/p&gt;
&lt;p&gt;All examples are written in plain R using the &lt;code&gt;{eventloop}&lt;/code&gt; package.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/drawing-grid.html&#34;&gt;Grid-based drawing &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/grid-based.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/drawing-lines.html&#34;&gt;Line-based drawing &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/line-based.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/stream-plotting.html&#34;&gt;Streaming plot data &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/plot-stream.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/game-of-life.html&#34;&gt;Game of Life &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/game-of-life.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/game-asteroids.html&#34;&gt;Asteroids&lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/asteroids.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/game-raycaster.html&#34;&gt;Raycast ‘Wolfenstein’ 3d engine &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/raycast.png&#34; width=&#34;89%&#34;  /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/game-wordle.html&#34;&gt;Wordle &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/wordle.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/verbose-example.html&#34;&gt;Interactive Mystery Curves &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/mystery-curves.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/eventloop/articles/verbose-example.html&#34;&gt;Verbose example &lt;br/&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/gallery/debug.png&#34; width=&#34;89%&#34; /&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;faq&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;div id=&#34;why-is-windows-not-supported&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Why is Windows not supported?&lt;/h4&gt;
&lt;p&gt;No graphics device on windows supports the &lt;code&gt;onIdle&lt;/code&gt; callback, which is essential
to the workings of this package.&lt;/p&gt;
&lt;p&gt;The Windows operating system supports the concept of an &lt;code&gt;onIdle&lt;/code&gt; callback, but
no one has yet written this into the R graphics device on this platform.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-does-this-run-so-slow-on-macos-sometimes&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Why does this run so slow on macOS sometimes?&lt;/h4&gt;
&lt;p&gt;Through some unknown combination of factors, after running &lt;code&gt;x11()&lt;/code&gt; windows
on macOS for some number of times or duration, the system will slowdown from hundreds-of-frames-per-second
to just ten-frames-per-second.&lt;/p&gt;
&lt;p&gt;This feels like a bug in either the &lt;code&gt;XQuartz()&lt;/code&gt; x11 framework, or it could be
a bug within R in how it interfaces with &lt;code&gt;XQuartz()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Note that I have not seen any slowdowns when using &lt;code&gt;x11()&lt;/code&gt; devices on Linux machines.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;tech-bits-what-is-an-event-loop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tech bits: What is an event loop?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.gameprogrammingpatterns.com/game-loop.html&#34;&gt;gameprogrammingpatterns.com&lt;/a&gt;
defines an event loop (also known as a &lt;em&gt;game loop&lt;/em&gt;) as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;A game loop runs continuously during gameplay. Each turn of the loop, it 
processes user input without blocking, updates the game state, and renders 
the game. It tracks the passage of time to control the rate of gameplay.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;tech-bits-how-is-the-event-loop-implemented-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tech bits: How is the event loop implemented in R?&lt;/h2&gt;
&lt;p&gt;Graphics windows in R can have &lt;em&gt;event handlers&lt;/em&gt; attached which instruct the
device to run a function when a certain event occurs.&lt;/p&gt;
&lt;p&gt;When a mouse or keyboard event occurs, &lt;code&gt;{eventloop}&lt;/code&gt; stores the event in
an environment for later access.&lt;/p&gt;
&lt;p&gt;When there is no event occuring, another function is called continuously. This
function is the &lt;em&gt;‘onIdle’ event callback&lt;/em&gt; and is only available in the &lt;code&gt;x11()&lt;/code&gt;
device on macOS and *nix.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;{eventloop}&lt;/code&gt; package orchestrates the events and window information into
arguments to the user-supplied ‘onIdle’ function - calling this function over and over
while the event loop is running.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/eventloop/event-handlers.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {cstructr} - a demonstration package showing how C structs may be exposed to R</title>
      <link>https://coolbutuseless.github.io/2022/04/26/introducing-cstructr-a-demonstration-package-showing-how-c-structs-may-be-exposed-to-r/</link>
      <pubDate>Tue, 26 Apr 2022 17:20:10 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/04/26/introducing-cstructr-a-demonstration-package-showing-how-c-structs-may-be-exposed-to-r/</guid>
      <description>


&lt;div id=&#34;cstructr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;cstructr&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{cstructr}&lt;/code&gt; is a demonstration package illustrating how a C struct may be
wrapped and manipulated from within R as an external pointer.&lt;/p&gt;
&lt;p&gt;This is a “full-service” implementation which makes the internal values
of the struct accessible from R via getters and setters.&lt;/p&gt;
&lt;p&gt;For bespoke solutions, a lot of the code could be excised to just keep
some core functions.&lt;/p&gt;
&lt;div id=&#34;note-the-code-in-this-package-was-auto-generated-by-parsing-the-c-struct-definition-and-the-c-library-function-declaration.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Note: The code in this package was auto-generated by parsing the C struct definition and the C library function declaration.&lt;/h4&gt;
&lt;/div&gt;
&lt;div id=&#34;c-struct-definition&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;C Struct Definition&lt;/h4&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;typedef struct {
  int N;
  double strength;
} MyCStruct;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;c-library-function-declaration&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;C Library Function Declaration&lt;/h4&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;double multiply(MyCStruct *mycstruct);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/cstructr&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cstructr&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-and-manipulate&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create and Manipulate&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cstructr)
mycstruct &amp;lt;- MyCStruct(N = 1, strength = 13)
mycstruct
#&amp;gt; MyCStruct(N = 1, strength = 13)

class(mycstruct)
#&amp;gt; [1] &amp;quot;MyCstruct_extptr&amp;quot;
typeof(mycstruct)
#&amp;gt; [1] &amp;quot;externalptr&amp;quot;

mycstruct$N
#&amp;gt; [1] 1
mycstruct$strength
#&amp;gt; [1] 13

mycstruct$N &amp;lt;- 3
mycstruct
#&amp;gt; MyCStruct(N = 3, strength = 13)

rm(mycstruct)
gc()
#&amp;gt; MyCStruct finalizer called to free the C pointer memory
#&amp;gt;           used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#&amp;gt; Ncells  568772 30.4    1291230   69         NA   667665 35.7
#&amp;gt; Vcells 1036286  8.0    8388608   64      16384  1824267 14.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create multiple structs at once&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lots &amp;lt;- MyCStructs(n = 3)
class(lots)
#&amp;gt; [1] &amp;quot;list&amp;quot;
lots
#&amp;gt; [[1]]
#&amp;gt; MyCStruct(N = 0, strength = 0)
#&amp;gt; [[2]]
#&amp;gt; MyCStruct(N = 0, strength = 0)
#&amp;gt; [[3]]
#&amp;gt; MyCStruct(N = 0, strength = 0)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;call-a-c-library-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Call a C library function&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Write a “bridge function” wrapper (in C) that maps from R objects to C objects&lt;/li&gt;
&lt;li&gt;Call the C library function from this wrapper&lt;/li&gt;
&lt;li&gt;Return the result to R in an appropriate container&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An example of a C function in a library is as follows. C libraries know
nothing about R or SEXP objects.&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;double multiply(MyCStruct *mycstruct) {
  return mycstruct-&amp;gt;N * mycstruct-&amp;gt;strength;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The “bridge” function between R and the C library call is written in C as follows.&lt;/p&gt;
&lt;p&gt;This function unpacks the externalptr to a real &lt;code&gt;MyCStruct&lt;/code&gt; pointer, calls the
C library function, and then returns the results as an R real numeric value.&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;SEXP multiply_(SEXP mycstruct_ptr_) {
  MyCStruct *mycstruct = external_ptr_to_MyCStruct_ptr(mycstruct_ptr_);
  double res = multiply(mycstruct);
  return ScalarReal(res);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The call from R is:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;multiply &amp;lt;- function(mycstruct) {
  .Call(multiply_, mycstruct)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All these functions combine such that we can create a pointer to a C struct
in R, and then call the C library function as follows&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cstructr)
mycstruct &amp;lt;- MyCStruct(N=2, strength = 4.5)
multiply(mycstruct)
#&amp;gt; [1] 9&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;auto-generation-of-bridge-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Auto-generation of bridge function&lt;/h2&gt;
&lt;p&gt;A lot of the code to wrap a C function and make it callable from R is standard boilerplate.&lt;/p&gt;
&lt;p&gt;For simple library functions, you could auto-generate a lot of this R + C code from the
C function declaration.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Find sets of five words in the wordle dictionary that contain 25 unique letters</title>
      <link>https://coolbutuseless.github.io/2022/01/17/find-sets-of-five-words-in-the-wordle-dictionary-that-contain-25-unique-letters/</link>
      <pubDate>Mon, 17 Jan 2022 17:25:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/01/17/find-sets-of-five-words-in-the-wordle-dictionary-that-contain-25-unique-letters/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;find-five-words-in-the-wordle-dictionary-that-contain-25-unique-letters&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Find five words in the wordle dictionary that contain 25 unique letters&lt;/h1&gt;
&lt;p&gt;While thinking about &lt;a href=&#34;&#34;&gt;wordle&lt;/a&gt; I wondered if there existed any sets of
five words in the wordle dictionary that would cover 25 unique letters
of the alphabet.&lt;/p&gt;
&lt;p&gt;Given there are twelve thousand words in the wordle dictionary, there are &lt;code&gt;12000^5&lt;/code&gt;
five-word sets. This is approx
2.5x10^20 - which means that if I could test a million five-word sets every second
it would take well over a million years.&lt;/p&gt;
&lt;p&gt;So I thought about how I might practically do this with recurstion and
vicious pruning of candidates in the search tree.&lt;/p&gt;
&lt;p&gt;All in base R!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;general-solution-process&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;General solution process&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Develop data structures which are easy for R to compute on and help with
pruning candidate words&lt;/li&gt;
&lt;li&gt;At each step of choosing anew word, prune quickly all the words that could
no longer be part of a possible 5-word set
&lt;ul&gt;
&lt;li&gt;e.g. if &lt;code&gt;abers&lt;/code&gt; is the first word, then the pool of remaining words to
choose should immediately discard any word with an &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;r&lt;/code&gt;
or &lt;code&gt;s&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;overivew-of-solution-technique&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Overivew of solution technique&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Remove all words with repeated letters.&lt;/li&gt;
&lt;li&gt;Build list of letters in each word. &lt;code&gt;letters_in_word&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build letter membership indices. The &lt;code&gt;words_with_letter&lt;/code&gt; data structure.&lt;/li&gt;
&lt;li&gt;Recursive searching (with early termination) with vicious pruning
of the remaining candidate words at each stage.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;start-with-the-wordle-dictionary&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Start with the wordle dictionary&lt;/h1&gt;
&lt;p&gt;The wordle dictionary contains 12972 five-letter words.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- wordle::wordle_dict
length(words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 12972&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;aahed&amp;quot; &amp;quot;aalii&amp;quot; &amp;quot;aargh&amp;quot; &amp;quot;aarti&amp;quot; &amp;quot;abaca&amp;quot; &amp;quot;abaci&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;remove-words-with-repeated-letters&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Remove words with repeated letters&lt;/h1&gt;
&lt;p&gt;If I need five words covering 25 letters, then no word should have two of the
same letter.&lt;/p&gt;
&lt;p&gt;Once these are filteredd out 8322 words remain.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Determine if a word has any repeated letters
#&amp;#39; @param words character vector of words
#&amp;#39; @return logical vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
has_doubles &amp;lt;- function(words) {
  vapply(strsplit(words, &amp;#39;&amp;#39;), function(lets) {
    any(table(lets) &amp;gt; 1)
  }, logical(1))
}

words &amp;lt;- words[!has_doubles(words)]
length(words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 8322&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pre-calc-strsplit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Pre-calc strsplit&lt;/h1&gt;
&lt;p&gt;Pre-calculate a data structure with the letters in each word.&lt;/p&gt;
&lt;p&gt;Letters are represented by their index within the alphabet&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;letters_in_word &amp;lt;- lapply(words, function(word) {
  utf8ToInt(word) - 96L
})

test_idx &amp;lt;- which(words == &amp;#39;panic&amp;#39;)
letters_in_word[[test_idx]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 16  1 14  9  3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;letters[letters_in_word[[test_idx]]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;p&amp;quot; &amp;quot;a&amp;quot; &amp;quot;n&amp;quot; &amp;quot;i&amp;quot; &amp;quot;c&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;build-letter-membership-indices&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Build letter membership indices&lt;/h1&gt;
&lt;p&gt;Build a data structure mapping each letter of the alphabet to which words
contain that letter.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Membership indices
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
words_with_letter &amp;lt;- list()
for (let in letters) {
  words_with_letter[[let]] &amp;lt;- grep(let, words)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For instance, can now lookup all the letters which contain ‘q’&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words_with_letter[[&amp;#39;q&amp;#39;]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1]  984 1268 1437 2196 2197 2198 2289 2418 2419 3099 4370 4870 5391 5723 5724
#&amp;gt; [16] 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739
#&amp;gt; [31] 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754
#&amp;gt; [46] 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769
#&amp;gt; [61] 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784
#&amp;gt; [76] 5785 5786 5787 6079 6798 6799 6800 6801 6802 6803 6804 6805 6806 7307 7359
#&amp;gt; [91] 7545 7896&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words[words_with_letter[[&amp;#39;q&amp;#39;]]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;burqa&amp;quot; &amp;quot;cinqs&amp;quot; &amp;quot;coqui&amp;quot; &amp;quot;equal&amp;quot; &amp;quot;equid&amp;quot; &amp;quot;equip&amp;quot; &amp;quot;faqir&amp;quot; &amp;quot;fiqhs&amp;quot; &amp;quot;fique&amp;quot;
#&amp;gt; [10] &amp;quot;guqin&amp;quot; &amp;quot;maqui&amp;quot; &amp;quot;niqab&amp;quot; &amp;quot;pique&amp;quot; &amp;quot;qadis&amp;quot; &amp;quot;qaids&amp;quot; &amp;quot;qapik&amp;quot; &amp;quot;qibla&amp;quot; &amp;quot;qophs&amp;quot;
#&amp;gt; [19] &amp;quot;qorma&amp;quot; &amp;quot;quack&amp;quot; &amp;quot;quads&amp;quot; &amp;quot;quags&amp;quot; &amp;quot;quail&amp;quot; &amp;quot;quair&amp;quot; &amp;quot;quais&amp;quot; &amp;quot;quake&amp;quot; &amp;quot;quaky&amp;quot;
#&amp;gt; [28] &amp;quot;quale&amp;quot; &amp;quot;qualm&amp;quot; &amp;quot;quant&amp;quot; &amp;quot;quare&amp;quot; &amp;quot;quark&amp;quot; &amp;quot;quart&amp;quot; &amp;quot;quash&amp;quot; &amp;quot;quasi&amp;quot; &amp;quot;quate&amp;quot;
#&amp;gt; [37] &amp;quot;quats&amp;quot; &amp;quot;quayd&amp;quot; &amp;quot;quays&amp;quot; &amp;quot;qubit&amp;quot; &amp;quot;quean&amp;quot; &amp;quot;quena&amp;quot; &amp;quot;quern&amp;quot; &amp;quot;query&amp;quot; &amp;quot;quest&amp;quot;
#&amp;gt; [46] &amp;quot;queyn&amp;quot; &amp;quot;queys&amp;quot; &amp;quot;quich&amp;quot; &amp;quot;quick&amp;quot; &amp;quot;quids&amp;quot; &amp;quot;quiet&amp;quot; &amp;quot;quilt&amp;quot; &amp;quot;quims&amp;quot; &amp;quot;quina&amp;quot;
#&amp;gt; [55] &amp;quot;quine&amp;quot; &amp;quot;quino&amp;quot; &amp;quot;quins&amp;quot; &amp;quot;quint&amp;quot; &amp;quot;quipo&amp;quot; &amp;quot;quips&amp;quot; &amp;quot;quire&amp;quot; &amp;quot;quirk&amp;quot; &amp;quot;quirt&amp;quot;
#&amp;gt; [64] &amp;quot;quist&amp;quot; &amp;quot;quite&amp;quot; &amp;quot;quits&amp;quot; &amp;quot;quoad&amp;quot; &amp;quot;quods&amp;quot; &amp;quot;quoif&amp;quot; &amp;quot;quoin&amp;quot; &amp;quot;quoit&amp;quot; &amp;quot;quonk&amp;quot;
#&amp;gt; [73] &amp;quot;quops&amp;quot; &amp;quot;quota&amp;quot; &amp;quot;quote&amp;quot; &amp;quot;quoth&amp;quot; &amp;quot;qursh&amp;quot; &amp;quot;quyte&amp;quot; &amp;quot;roque&amp;quot; &amp;quot;squab&amp;quot; &amp;quot;squad&amp;quot;
#&amp;gt; [82] &amp;quot;squat&amp;quot; &amp;quot;squaw&amp;quot; &amp;quot;squeg&amp;quot; &amp;quot;squib&amp;quot; &amp;quot;squid&amp;quot; &amp;quot;squit&amp;quot; &amp;quot;squiz&amp;quot; &amp;quot;toque&amp;quot; &amp;quot;tranq&amp;quot;
#&amp;gt; [91] &amp;quot;umiaq&amp;quot; &amp;quot;waqfs&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pick-a-word-and-recursively-build-word-sets&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Pick a word and recursively build word sets&lt;/h1&gt;
&lt;p&gt;This function bails early if the set of ramining candidate words in any
search drops to zero.&lt;/p&gt;
&lt;p&gt;If a five-word sequence is found then print it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Recursively filter a set of words
#&amp;#39;
#&amp;#39; @param word_idx an index in [1, length(words)]
#&amp;#39; @param remaining_idx all other word indexes remaining at this stage
#&amp;#39; @param word_seq integer vector of the word indices up to this point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
filter_words &amp;lt;- function(word_idx,
                         remaining_idx,
                         word_seq   = c()) {

  # In the remaining list of words, filter out any words that contain
  # any of the letters of the current word
  for (letter_idx in letters_in_word[[word_idx]]) {
    remaining_idx &amp;lt;- setdiff(remaining_idx, words_with_letter[[letter_idx]])
  }

  # Bail early if no words available after exclusion
  if (length(remaining_idx) == 0L) return()

  # Update the word sequence 
  word_seq &amp;lt;- c(word_seq, word_idx)

  if (length(word_seq) == 4) {
    # terminal condition
    for (j in remaining_idx) {
      cat(words[c(word_seq, j)], &amp;quot;\n&amp;quot;)
    }
  } else {
    for (jj in seq_along(remaining_idx)) {
      filter_words(
        word_idx      = remaining_idx[[jj]],
        remaining_idx = remaining_idx[-seq(jj)],
        word_seq      = word_seq
      )
    }
  }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-starting-at-jumby&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example starting at &lt;code&gt;jumby&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Picking &lt;code&gt;jumby&lt;/code&gt; as the first word and trying all word sets which start with this word
takes about a minute on my old laptop.&lt;/p&gt;
&lt;p&gt;However, different starting words will take different times because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;candidate words are only those which come alphabetically &lt;em&gt;after&lt;/em&gt; the starting word,
so words later in the dictionary will be faster because only words which are after
this one are posibble candidate words in the search tree.&lt;/li&gt;
&lt;li&gt;different starting words can more rapidly prune the search space, meaning that
there are fewer possible candidate words in the search tree&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;i &amp;lt;- 3666  # &amp;#39;jumby&amp;#39;
filter_words(
  word_idx = i,
  remaining_idx = seq.int(i+1L, length(words))
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; jumby pling treck vozhd waqfs&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;search-the-entire-space-of-five-word-sets&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Search the entire space of five-word sets&lt;/h1&gt;
&lt;p&gt;I’ve run this sequentially in a for loop and it took about 8 hours to find the word sets.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;for (i in seq_along(words)) {
  filter_words(
    word_idx = i,
    remaining_idx = seq.int(i+1L, length(words))
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;bemix clunk grypt vozhd waqfs
bling jumpy treck vozhd waqfs
blunk cimex grypt vozhd waqfs
brick glent jumpy vozhd waqfs
brung cylix kempt vozhd waqfs
brung kempt vozhd waqfs xylic
chunk fjord gymps vibex waltz
clipt jumby kreng vozhd waqfs
fjord gucks nymph vibex waltz
glent jumby prick vozhd waqfs
jumby pling treck vozhd waqfs&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>{wordle} v0.1.5 - a package for playing (and helping solve) Wordle puzzles</title>
      <link>https://coolbutuseless.github.io/2022/01/04/wordle-v0.1.5-a-package-for-playing-and-helping-solve-wordle-puzzles/</link>
      <pubDate>Tue, 04 Jan 2022 20:35:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2022/01/04/wordle-v0.1.5-a-package-for-playing-and-helping-solve-wordle-puzzles/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;wordle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;wordle&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/wordle/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/wordle/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;{wordle}&lt;/code&gt; package contains code to assist in finding good candidate
words for Wordle.&lt;/p&gt;
&lt;p&gt;“Wordle” itself is a guess-a-word puzzle &lt;a href=&#34;https://www.powerlanguage.co.uk/wordle/&#34;&gt;playable online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The game plays like the old ‘mastermind’ board game, but with letters instead of
coloured pins. The gameplay is as follows:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Enter a word as a guess for the hidden target word.&lt;/li&gt;
&lt;li&gt;Any letters which are within the hidden target word are coloured in yellow.&lt;/li&gt;
&lt;li&gt;Any letters which match exactly the letter in the hidden target word are
coloured green&lt;/li&gt;
&lt;li&gt;Figure out a new candidate word as a guess for the hidden target word,
and go back to Step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the following game of Wordle, the first guess was &lt;code&gt;eaten&lt;/code&gt;, the second was
&lt;code&gt;arise&lt;/code&gt;, and then the third guess really only has one good option given the
constraints revealed so far: &lt;code&gt;aside&lt;/code&gt;. This was the hidden target word,
which means the puzzle is solved!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/eg.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The process of finding good candidate words given letters which have been seen
so far is a good match for regular expressions. This package aims to help
you find these good candidate words.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;play_wordle()&lt;/code&gt; Simple way to play a game of wordle in the R console&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wordle_dict&lt;/code&gt; an ‘official’ list of words scraped from the Wordle
website&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WordleHelper&lt;/code&gt; R6 Class is the primary way of finding candidate words. It
has the following methods:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$new()&lt;/code&gt; to start a new object to help with a new puzzle.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$words&lt;/code&gt; to get a list of all the remaining possible valid words given the
words and responses that have been seen so far&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$update()&lt;/code&gt; to notify the object of what the latest &lt;code&gt;word&lt;/code&gt; was,
and the colour responses received back from the game for each
letter.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;WordleHelper&lt;/code&gt; class is a stateful wrapper around &lt;code&gt;filter_words()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Advanced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;filter_words()&lt;/code&gt; is a stateless function for filtering a list of
words by various constraints on letter position.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WordleGame&lt;/code&gt; R6 class represnting a wordle game engine
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$new()&lt;/code&gt; to create a new game and internally choose a target word for this game&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$try(word)&lt;/code&gt; to try a word and see what the respnse is in relation to
the hidden target word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$share()&lt;/code&gt; create a block of unicode representing the evolution of the
solution process.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;play_wordle()&lt;/code&gt; is a simple helper function wrapping this class.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/wordle&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/wordle&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;play-a-game-of-wordle-in-your-r-console&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Play a game of Wordle in your R console&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;wordle::play_wordle()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/game.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;help-solve-a-puzzle-with-wordlewordlehelper&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Help solve a puzzle with &lt;code&gt;wordle::WordleHelper&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In this example, after picking my favourite starting word, at each step I will
just pick the first word in the alphabetical list of remaining possible words.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/00.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;helper &amp;lt;- WordleHelper$new(nchar = 5)
length(helper$words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 12972&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(helper$words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;aahed&amp;quot; &amp;quot;aalii&amp;quot; &amp;quot;aargh&amp;quot; &amp;quot;aarti&amp;quot; &amp;quot;abaca&amp;quot; &amp;quot;abaci&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;initial-word-choice-arose&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Initial word choice: &lt;code&gt;arose&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;There are many opinions on a good starting word - I like: &lt;code&gt;arose&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/01.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;helper$update(&amp;quot;arose&amp;quot;, c(&amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;green&amp;#39;))
helper$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;besee&amp;quot; &amp;quot;disme&amp;quot; &amp;quot;ensue&amp;quot; &amp;quot;esile&amp;quot; &amp;quot;fusee&amp;quot; &amp;quot;geste&amp;quot; &amp;quot;gusle&amp;quot; &amp;quot;issue&amp;quot; &amp;quot;istle&amp;quot;
#&amp;gt; [10] &amp;quot;lisle&amp;quot; &amp;quot;mesne&amp;quot; &amp;quot;piste&amp;quot; &amp;quot;pusle&amp;quot; &amp;quot;scene&amp;quot; &amp;quot;scute&amp;quot; &amp;quot;sedge&amp;quot; &amp;quot;segue&amp;quot; &amp;quot;seine&amp;quot;
#&amp;gt; [19] &amp;quot;seize&amp;quot; &amp;quot;selle&amp;quot; &amp;quot;semee&amp;quot; &amp;quot;semie&amp;quot; &amp;quot;sente&amp;quot; &amp;quot;shine&amp;quot; &amp;quot;shite&amp;quot; &amp;quot;shive&amp;quot; &amp;quot;shule&amp;quot;
#&amp;gt; [28] &amp;quot;shute&amp;quot; &amp;quot;sidhe&amp;quot; &amp;quot;sidle&amp;quot; &amp;quot;siege&amp;quot; &amp;quot;sieve&amp;quot; &amp;quot;since&amp;quot; &amp;quot;singe&amp;quot; &amp;quot;sithe&amp;quot; &amp;quot;sixte&amp;quot;
#&amp;gt; [37] &amp;quot;skene&amp;quot; &amp;quot;skite&amp;quot; &amp;quot;skive&amp;quot; &amp;quot;skyte&amp;quot; &amp;quot;slice&amp;quot; &amp;quot;slide&amp;quot; &amp;quot;slime&amp;quot; &amp;quot;slipe&amp;quot; &amp;quot;slive&amp;quot;
#&amp;gt; [46] &amp;quot;slype&amp;quot; &amp;quot;smeke&amp;quot; &amp;quot;smile&amp;quot; &amp;quot;smite&amp;quot; &amp;quot;snide&amp;quot; &amp;quot;snipe&amp;quot; &amp;quot;spice&amp;quot; &amp;quot;spide&amp;quot; &amp;quot;spike&amp;quot;
#&amp;gt; [55] &amp;quot;spile&amp;quot; &amp;quot;spine&amp;quot; &amp;quot;spite&amp;quot; &amp;quot;spule&amp;quot; &amp;quot;spume&amp;quot; &amp;quot;stede&amp;quot; &amp;quot;stele&amp;quot; &amp;quot;steme&amp;quot; &amp;quot;stile&amp;quot;
#&amp;gt; [64] &amp;quot;stime&amp;quot; &amp;quot;stipe&amp;quot; &amp;quot;stive&amp;quot; &amp;quot;stude&amp;quot; &amp;quot;stupe&amp;quot; &amp;quot;style&amp;quot; &amp;quot;styme&amp;quot; &amp;quot;styte&amp;quot; &amp;quot;suede&amp;quot;
#&amp;gt; [73] &amp;quot;suete&amp;quot; &amp;quot;suite&amp;quot; &amp;quot;sujee&amp;quot; &amp;quot;swede&amp;quot; &amp;quot;swile&amp;quot; &amp;quot;swine&amp;quot; &amp;quot;swipe&amp;quot; &amp;quot;swive&amp;quot; &amp;quot;sybbe&amp;quot;
#&amp;gt; [82] &amp;quot;sycee&amp;quot; &amp;quot;sythe&amp;quot; &amp;quot;teste&amp;quot; &amp;quot;unsee&amp;quot; &amp;quot;upsee&amp;quot; &amp;quot;usque&amp;quot; &amp;quot;visie&amp;quot; &amp;quot;visne&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;choose-the-first-word-besee&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Choose the first word: &lt;code&gt;besee&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/02.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;helper$update(&amp;quot;besee&amp;quot;, c(&amp;#39;grey&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;green&amp;#39;))
helper$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;esile&amp;quot; &amp;quot;scene&amp;quot; &amp;quot;siege&amp;quot; &amp;quot;sieve&amp;quot; &amp;quot;skene&amp;quot; &amp;quot;smeke&amp;quot; &amp;quot;stede&amp;quot; &amp;quot;stele&amp;quot; &amp;quot;steme&amp;quot;
#&amp;gt; [10] &amp;quot;suede&amp;quot; &amp;quot;suete&amp;quot; &amp;quot;sujee&amp;quot; &amp;quot;swede&amp;quot; &amp;quot;sycee&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;choose-the-first-word-esile&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Choose the first word: &lt;code&gt;esile&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/03.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;helper$update(&amp;quot;esile&amp;quot;, c(&amp;#39;yellow&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;green&amp;#39;))
helper$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;siege&amp;quot; &amp;quot;sieve&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;choose-the-first-word-siege&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Choose the first word: &lt;code&gt;siege&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/04.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Success!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;optimizing-word-selection&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Optimizing word selection&lt;/h1&gt;
&lt;p&gt;In the above worked example no effort was made to optimize the word choice - instead
the first word in the alphabetical list of remaining words was chosen.&lt;/p&gt;
&lt;p&gt;There may be opportunities to pick the “best” word that helps to solve the puzzle faster,
but no such code is included in this package - yet!&lt;/p&gt;
&lt;p&gt;For example, it may be possible to pick the word that when played results
in the most &lt;em&gt;other&lt;/em&gt; words in the remaining list of words to be eliminated.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-wordle-game-engine&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Tweetable Wordle Game Engine&lt;/h1&gt;
&lt;p&gt;A playable game of Wordle in a tweet.&lt;/p&gt;
&lt;p&gt;This was an exercise to see if I could simplify the WordleGame into just 280 characters. It’s mostly unreadable, and lacks safety checks, but it works!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#RStats #wordle in a tweet
s=\(x)el(strsplit(x,&amp;#39;&amp;#39;))
t=s(sample(grep(&amp;quot;^[a-z]{5}$&amp;quot;,readLines(&amp;#39;/usr/share/dict/words&amp;#39;),v=T),1))
while(1){g=s(readline(&amp;quot;? &amp;quot;))
M=t==g
r=which(!M)
for(i in r)for(j in r)if(g[i]==t[j]){M[i]=2;r=r[r!=j]}
cat(paste0(&amp;#39;\033[48;5;&amp;#39;,c(249,46,226)[M+1],&amp;#39;m &amp;#39;,g))}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle/tweetable.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;expert-function-filter_words&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Expert Function: &lt;code&gt;filter_words()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;WordleHelper&lt;/code&gt; R6 class is just a stateful wrapper around a core function
called &lt;code&gt;filter_words()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In general you wouldn’t need to call this function for solving a Wordle puzzle
but it might come in handy for other word puzzles.&lt;/p&gt;
&lt;p&gt;In this example, I’m searching for a word:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;with 9 letters&lt;/li&gt;
&lt;li&gt;starting with &lt;code&gt;p&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;containing &lt;code&gt;v&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; somewhere, but not as the first letter&lt;/li&gt;
&lt;li&gt;containing only one &lt;code&gt;z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;without an &lt;code&gt;a&lt;/code&gt; or an &lt;code&gt;o&lt;/code&gt; in it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- readLines(&amp;quot;/usr/share/dict/words&amp;quot;)

filter_words(
  words            = words,
  exact            = &amp;quot;p........&amp;quot;,
  wrong_spot       = c(&amp;quot;vz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;),
  min_count        = c(v = 1),
  known_count      = c(z = 1, a = 0, o = 0)
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;pulverize&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {wordle} - a package for helping solve Wordle puzzles</title>
      <link>https://coolbutuseless.github.io/2021/12/31/introducing-wordle-a-package-for-helping-solve-wordle-puzzles/</link>
      <pubDate>Fri, 31 Dec 2021 06:35:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/31/introducing-wordle-a-package-for-helping-solve-wordle-puzzles/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;wordle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;wordle&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/wordle-old/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/wordle-old/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;{wordle}&lt;/code&gt; package contains code to assist in finding good candidate
words for Wordle.&lt;/p&gt;
&lt;p&gt;“Wordle” itself is a guess-a-word puzzle &lt;a href=&#34;https://www.powerlanguage.co.uk/wordle-old/&#34;&gt;playable online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The game plays like the old ‘mastermind’ board game, but with letters instead of
coloured pins. The gameplay is as follows:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Enter a word as a guess for the hidden target word.&lt;/li&gt;
&lt;li&gt;Any letters which are within the hidden target word are coloured in yellow.&lt;/li&gt;
&lt;li&gt;Any letters which match exactly the letter in the hidden target word are
coloured green&lt;/li&gt;
&lt;li&gt;Figure out a new candidate word as a guess for the hidden target word,
and go back to Step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the following game of Wordle, the first guess was &lt;code&gt;eaten&lt;/code&gt;, the second was
&lt;code&gt;arise&lt;/code&gt;, and then the third guess really only has one good option given the
constraints revealed so far: &lt;code&gt;aside&lt;/code&gt;. This was the hidden target word,
which means the puzzle is solved!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/eg.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The process of finding good candidate words given letters which have been seen
so far is a good match for regular expressions. This package aims to help
you find these good candidate words.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Wordle&lt;/code&gt; R6 Class is the primary way of finding candidate words. It has the
following methods:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$new()&lt;/code&gt; to start a new object to help with a new puzzle. Use the
&lt;code&gt;word_file&lt;/code&gt; argument to set the location of a list of words to start
with. This defaults to &lt;code&gt;/usr/share/dict/words&lt;/code&gt; (which should work
on macOS and many unix-ish systems).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$words&lt;/code&gt; to get a list of candidate words given the words
and responses that have been seen so far&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$update()&lt;/code&gt; to notify the object of what the latest &lt;code&gt;word&lt;/code&gt; was, and the
colour responses received back from the game for each letter.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filter_words()&lt;/code&gt; is a stateless function for filtering a list of words
by various constraints on letter position.
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Wordle&lt;/code&gt; class is a stateful wrapper around &lt;code&gt;filter_words()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/wordle&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/wordle&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;solving-a-puzzle-with-wordle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solving a puzzle with &lt;code&gt;Wordle&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/00.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle &amp;lt;- wordle::WordleHelper$new(nchar = 5)
head(puzzle$words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;aahed&amp;quot; &amp;quot;aalii&amp;quot; &amp;quot;aargh&amp;quot; &amp;quot;aarti&amp;quot; &amp;quot;abaca&amp;quot; &amp;quot;abaci&amp;quot; &amp;quot;aback&amp;quot; &amp;quot;abacs&amp;quot; &amp;quot;abaft&amp;quot;
#&amp;gt; [10] &amp;quot;abaka&amp;quot; &amp;quot;abamp&amp;quot; &amp;quot;aband&amp;quot; &amp;quot;abase&amp;quot; &amp;quot;abash&amp;quot; &amp;quot;abask&amp;quot; &amp;quot;abate&amp;quot; &amp;quot;abaya&amp;quot; &amp;quot;abbas&amp;quot;
#&amp;gt; [19] &amp;quot;abbed&amp;quot; &amp;quot;abbes&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;guess-eaten&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;eaten&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;There are a lot of uncommon words in the word list, and the online puzzle doesn’t
accept some of them, so you’ll need to pick out a likely word - in this case
I picked: &lt;code&gt;eaten&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/01.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle$update(&amp;quot;eaten&amp;quot;, c(&amp;#39;yellow&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;))
head(puzzle$words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;bebop&amp;quot; &amp;quot;becks&amp;quot; &amp;quot;bedim&amp;quot; &amp;quot;befog&amp;quot; &amp;quot;begum&amp;quot; &amp;quot;beigy&amp;quot; &amp;quot;belch&amp;quot; &amp;quot;bells&amp;quot; &amp;quot;belly&amp;quot;
#&amp;gt; [10] &amp;quot;below&amp;quot; &amp;quot;bemix&amp;quot; &amp;quot;bemud&amp;quot; &amp;quot;bergs&amp;quot; &amp;quot;berko&amp;quot; &amp;quot;berks&amp;quot; &amp;quot;berms&amp;quot; &amp;quot;berob&amp;quot; &amp;quot;berry&amp;quot;
#&amp;gt; [19] &amp;quot;beryl&amp;quot; &amp;quot;besom&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-rodeo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;rodeo&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/02.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle$update(&amp;quot;rodeo&amp;quot;, c(&amp;#39;yellow&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;yellow&amp;#39;, &amp;#39;grey&amp;#39;))
puzzle$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;   [1] &amp;quot;bergs&amp;quot; &amp;quot;berks&amp;quot; &amp;quot;berms&amp;quot; &amp;quot;berry&amp;quot; &amp;quot;beryl&amp;quot; &amp;quot;biers&amp;quot; &amp;quot;birle&amp;quot; &amp;quot;birse&amp;quot; &amp;quot;breis&amp;quot;
#&amp;gt;  [10] &amp;quot;brers&amp;quot; &amp;quot;brews&amp;quot; &amp;quot;breys&amp;quot; &amp;quot;bribe&amp;quot; &amp;quot;brise&amp;quot; &amp;quot;brize&amp;quot; &amp;quot;brule&amp;quot; &amp;quot;brume&amp;quot; &amp;quot;burke&amp;quot;
#&amp;gt;  [19] &amp;quot;burse&amp;quot; &amp;quot;cerci&amp;quot; &amp;quot;ceric&amp;quot; &amp;quot;clerk&amp;quot; &amp;quot;crems&amp;quot; &amp;quot;creps&amp;quot; &amp;quot;crepy&amp;quot; &amp;quot;cress&amp;quot; &amp;quot;crews&amp;quot;
#&amp;gt;  [28] &amp;quot;crime&amp;quot; &amp;quot;cripe&amp;quot; &amp;quot;crise&amp;quot; &amp;quot;cruse&amp;quot; &amp;quot;cruve&amp;quot; &amp;quot;curie&amp;quot; &amp;quot;curse&amp;quot; &amp;quot;curve&amp;quot; &amp;quot;femur&amp;quot;
#&amp;gt;  [37] &amp;quot;ferly&amp;quot; &amp;quot;fermi&amp;quot; &amp;quot;ferms&amp;quot; &amp;quot;ferry&amp;quot; &amp;quot;fibre&amp;quot; &amp;quot;fiers&amp;quot; &amp;quot;fiery&amp;quot; &amp;quot;firie&amp;quot; &amp;quot;fleur&amp;quot;
#&amp;gt;  [46] &amp;quot;fresh&amp;quot; &amp;quot;frise&amp;quot; &amp;quot;frize&amp;quot; &amp;quot;furze&amp;quot; &amp;quot;gebur&amp;quot; &amp;quot;germs&amp;quot; &amp;quot;germy&amp;quot; &amp;quot;grews&amp;quot; &amp;quot;greys&amp;quot;
#&amp;gt;  [55] &amp;quot;grice&amp;quot; &amp;quot;grike&amp;quot; &amp;quot;grime&amp;quot; &amp;quot;gripe&amp;quot; &amp;quot;grise&amp;quot; &amp;quot;grize&amp;quot; &amp;quot;grufe&amp;quot; &amp;quot;grume&amp;quot; &amp;quot;gryce&amp;quot;
#&amp;gt;  [64] &amp;quot;gryke&amp;quot; &amp;quot;grype&amp;quot; &amp;quot;gurge&amp;quot; &amp;quot;heirs&amp;quot; &amp;quot;herbs&amp;quot; &amp;quot;herby&amp;quot; &amp;quot;herls&amp;quot; &amp;quot;herms&amp;quot; &amp;quot;herry&amp;quot;
#&amp;gt;  [73] &amp;quot;huers&amp;quot; &amp;quot;icers&amp;quot; &amp;quot;jerks&amp;quot; &amp;quot;jerky&amp;quot; &amp;quot;jerry&amp;quot; &amp;quot;jirre&amp;quot; &amp;quot;kefir&amp;quot; &amp;quot;keirs&amp;quot; &amp;quot;kerbs&amp;quot;
#&amp;gt;  [82] &amp;quot;kerfs&amp;quot; &amp;quot;kerky&amp;quot; &amp;quot;kerry&amp;quot; &amp;quot;kiers&amp;quot; &amp;quot;kurre&amp;quot; &amp;quot;kyrie&amp;quot; &amp;quot;lehrs&amp;quot; &amp;quot;leirs&amp;quot; &amp;quot;lemur&amp;quot;
#&amp;gt;  [91] &amp;quot;lerps&amp;quot; &amp;quot;liers&amp;quot; &amp;quot;livre&amp;quot; &amp;quot;lucre&amp;quot; &amp;quot;lurve&amp;quot; &amp;quot;merch&amp;quot; &amp;quot;mercs&amp;quot; &amp;quot;mercy&amp;quot; &amp;quot;meril&amp;quot;
#&amp;gt; [100] &amp;quot;meris&amp;quot; &amp;quot;merks&amp;quot; &amp;quot;merls&amp;quot; &amp;quot;merry&amp;quot; &amp;quot;murre&amp;quot; &amp;quot;perch&amp;quot; &amp;quot;percs&amp;quot; &amp;quot;peril&amp;quot; &amp;quot;peris&amp;quot;
#&amp;gt; [109] &amp;quot;perks&amp;quot; &amp;quot;perky&amp;quot; &amp;quot;perms&amp;quot; &amp;quot;perps&amp;quot; &amp;quot;perry&amp;quot; &amp;quot;pervs&amp;quot; &amp;quot;pervy&amp;quot; &amp;quot;piers&amp;quot; &amp;quot;preif&amp;quot;
#&amp;gt; [118] &amp;quot;prems&amp;quot; &amp;quot;premy&amp;quot; &amp;quot;preps&amp;quot; &amp;quot;press&amp;quot; &amp;quot;prexy&amp;quot; &amp;quot;preys&amp;quot; &amp;quot;price&amp;quot; &amp;quot;prime&amp;quot; &amp;quot;prise&amp;quot;
#&amp;gt; [127] &amp;quot;prize&amp;quot; &amp;quot;pryse&amp;quot; &amp;quot;puers&amp;quot; &amp;quot;purge&amp;quot; &amp;quot;purse&amp;quot; &amp;quot;query&amp;quot; &amp;quot;quire&amp;quot; &amp;quot;sehri&amp;quot; &amp;quot;seirs&amp;quot;
#&amp;gt; [136] &amp;quot;serfs&amp;quot; &amp;quot;seric&amp;quot; &amp;quot;serif&amp;quot; &amp;quot;serks&amp;quot; &amp;quot;serrs&amp;quot; &amp;quot;serry&amp;quot; &amp;quot;serum&amp;quot; &amp;quot;shire&amp;quot; &amp;quot;sieur&amp;quot;
#&amp;gt; [145] &amp;quot;skers&amp;quot; &amp;quot;skyre&amp;quot; &amp;quot;smerk&amp;quot; &amp;quot;speir&amp;quot; &amp;quot;sperm&amp;quot; &amp;quot;spire&amp;quot; &amp;quot;sprue&amp;quot; &amp;quot;spyre&amp;quot; &amp;quot;sucre&amp;quot;
#&amp;gt; [154] &amp;quot;suers&amp;quot; &amp;quot;surge&amp;quot; &amp;quot;sweir&amp;quot; &amp;quot;swerf&amp;quot; &amp;quot;swire&amp;quot; &amp;quot;umbre&amp;quot; &amp;quot;ureic&amp;quot; &amp;quot;users&amp;quot; &amp;quot;usure&amp;quot;
#&amp;gt; [163] &amp;quot;verbs&amp;quot; &amp;quot;verry&amp;quot; &amp;quot;vezir&amp;quot; &amp;quot;viers&amp;quot; &amp;quot;virge&amp;quot; &amp;quot;weirs&amp;quot; &amp;quot;wersh&amp;quot; &amp;quot;wreck&amp;quot; &amp;quot;xeric&amp;quot;
#&amp;gt; [172] &amp;quot;xerus&amp;quot; &amp;quot;yerks&amp;quot; &amp;quot;zerks&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-shire&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;shire&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/03.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle$update(&amp;quot;shire&amp;quot;, c(&amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;grey&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;yellow&amp;#39;))
puzzle$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;berry&amp;quot; &amp;quot;clerk&amp;quot; &amp;quot;ferry&amp;quot; &amp;quot;jerry&amp;quot; &amp;quot;kerry&amp;quot; &amp;quot;merry&amp;quot; &amp;quot;perry&amp;quot; &amp;quot;query&amp;quot; &amp;quot;verry&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-merry&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;merry&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/04.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Update puzzle state with the word played and the response:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle$update(&amp;quot;merry&amp;quot;, c(&amp;#39;grey&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;green&amp;#39;, &amp;#39;green&amp;#39;))
puzzle$words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;berry&amp;quot; &amp;quot;ferry&amp;quot; &amp;quot;jerry&amp;quot; &amp;quot;kerry&amp;quot; &amp;quot;perry&amp;quot; &amp;quot;verry&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-ferry&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;ferry&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/05.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Success!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;expert-users-filter_words&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Expert Users: &lt;code&gt;filter_words()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;Wordle&lt;/code&gt; R6 class is just a stateful wrapper around a core function
called &lt;code&gt;filter_words()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In general you wouldn’t need to call this function for solving a Wordle puzzle
but it might come in handy for other word puzzles.&lt;/p&gt;
&lt;p&gt;In this example, I’m searching for a word:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;with 9 letters&lt;/li&gt;
&lt;li&gt;starting with &lt;code&gt;p&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;containing &lt;code&gt;v&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; somewhere, but not as the first letter&lt;/li&gt;
&lt;li&gt;containing only one &lt;code&gt;z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;without an &lt;code&gt;a&lt;/code&gt; or an &lt;code&gt;o&lt;/code&gt; in it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- readLines(&amp;quot;/usr/share/dict/words&amp;quot;)

filter_words(
  words            = words,
  exact            = &amp;quot;p........&amp;quot;,
  wrong_spot       = c(&amp;quot;vz&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;),
  min_count        = c(v = 1),
  known_count      = c(z = 1, a = 0, o = 0)
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;pulverize&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Solving a Wordle with assistance from R</title>
      <link>https://coolbutuseless.github.io/2021/12/28/solving-a-wordle-with-assistance-from-r/</link>
      <pubDate>Tue, 28 Dec 2021 04:35:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/28/solving-a-wordle-with-assistance-from-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;wordles&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Wordles!&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Wordles&lt;/code&gt; are a word guessing puzzle &lt;a href=&#34;https://www.powerlanguage.co.uk/wordle-old/&#34;&gt;playable online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There’s a small write-up in a recent &lt;a href=&#34;https://www.theguardian.com/games/2021/dec/23/what-is-wordle-the-new-viral-word-game-delighting-the-internet&#34;&gt;article in The Guardian&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The game plays like the old ‘mastermind’ board game, but with letters instead of
coloured pins.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Enter a word as a guess&lt;/li&gt;
&lt;li&gt;Any letters which are within the hidden target word are coloured in yellow.&lt;/li&gt;
&lt;li&gt;Any letters which match exactly the letter in the hidden target word are
coloured green&lt;/li&gt;
&lt;li&gt;Figure out a new candidate word as a guess for the hidden target word,
and go back to Step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process of finding strong and weak matches for characters in a word
seems quite suited for regular expressions.&lt;/p&gt;
&lt;p&gt;The code below is a first rough attempt at generating good candidate guesses
to solve Wordle puzzles.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;establish-a-scoring-system-for-words&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Establish a scoring system for words&lt;/h1&gt;
&lt;p&gt;At any stage of the game there will be a number of candidate words which match
the letters which have been guessed so far. I’ll use an trivial scoring
system to determine a priority list of possible next words.&lt;/p&gt;
&lt;p&gt;As a rough rule-of-thumb, I’ll score each word by scoring the letters within the
word.&lt;/p&gt;
&lt;p&gt;Common letters like &lt;code&gt;e&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt; score low, while &lt;code&gt;q&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; score high.&lt;/p&gt;
&lt;p&gt;Tally the scores of all letters in a word to determine a score for a word.&lt;/p&gt;
&lt;p&gt;This score will then be used to sort words in order to choose a candidate
for the next attempt.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a scoring vector c(e=1, t=2, a=3 ... z=26)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
letter_freqs  &amp;lt;- strsplit(&amp;#39;etaoinshrdlcumwfgypbvkjxqz&amp;#39;, &amp;#39;&amp;#39;)[[1]]
letter_scores &amp;lt;- setNames(1:26, letter_freqs)
score_letters &amp;lt;- function(letters) sum(letter_scores[tolower(letters)])

score_letters(c(&amp;#39;h&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;o&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 35&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;score_letters(c(&amp;#39;z&amp;#39;, &amp;#39;y&amp;#39;, &amp;#39;x&amp;#39;, &amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 110&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;glorified-regular-expressions-in-a-function&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Glorified regular expressions in a function&lt;/h1&gt;
&lt;p&gt;The regular expression to find candidate words from a larger list of words evolves
with each guess as new letters are discovered or excluded.&lt;/p&gt;
&lt;p&gt;To help out with this regex evolution, I wrote a function to wrap a number
of common operations starting from a candidate list of words:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;keep only words which have known letters in their exact position.&lt;/li&gt;
&lt;li&gt;Discard words which have letters we know are excluded.&lt;/li&gt;
&lt;li&gt;Discard words which have letter counts are in excess of requirments&lt;/li&gt;
&lt;li&gt;Carefully filter out words where we know particular letters are not correct&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Filter words based upon &amp;quot;Wordle&amp;quot; game state
#&amp;#39;
#&amp;#39; @param words character vector of candidate words
#&amp;#39; @param exact single string representing known characters in the word, with
#&amp;#39;        &amp;#39;.&amp;#39; used to indicate the letter at this position is unknown.
#&amp;#39;        E.g. For a 5 letter word if the 3rd and 4th letters are known to be &amp;#39;a&amp;#39; and &amp;#39;c&amp;#39;, but
#&amp;#39;        all other letters are unknown, then \code{exact = &amp;quot;..ac.&amp;quot;}
#&amp;#39; @param excluded_letters string containing letters known to not be in the word
#&amp;#39; @param wrong_spot a character vector the same length as the number of letters 
#&amp;#39;        in the target word.  Each string in this vector represents all letters
#&amp;#39;        which are known to be part of the word, but in the wrong spot.
#&amp;#39;        E.g. if &amp;#39;a&amp;#39; has been attempted as the first character, and it exists
#&amp;#39;        in the word, but worlde claims it is not yet in the correct position,
#&amp;#39;        then \code{wrong_spot = c(&amp;#39;a&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;)}
#&amp;#39; @param known_count name character vector giving letters and their known counts.
#&amp;#39;        E.g. This can be used if it is known definitively that there is only 
#&amp;#39;        one letter &amp;#39;e&amp;#39; in the target word, in which case
#&amp;#39;        \code{known_count = c(e = 1)}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
filter_words &amp;lt;- function(words, exact = &amp;quot;.....&amp;quot;, excluded_letters = &amp;quot;&amp;quot;, wrong_spot = c(&amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;), known_count = c()) {

  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Build a regex to match the exact case, but exclude any words which 
  # contain excluded letters, or letters in the wrong spot
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  excluded_letters &amp;lt;- rep(excluded_letters, nchar(exact))

  stopifnot(length(wrong_spot) == nchar(exact))
  excluded_letters &amp;lt;- paste(excluded_letters, wrong_spot, sep = &amp;quot;&amp;quot;)
  excluded_letters &amp;lt;- ifelse(nchar(excluded_letters) == 0, &amp;#39;.&amp;#39;, paste0(&amp;quot;[^&amp;quot;, excluded_letters, &amp;quot;]&amp;quot;))

  regex &amp;lt;- strsplit(exact, &amp;#39;&amp;#39;)[[1]]
  regex &amp;lt;- ifelse(regex == &amp;#39;.&amp;#39;, excluded_letters, regex)
  regex &amp;lt;- paste(regex, collapse = &amp;quot;&amp;quot;)
  regex &amp;lt;- paste0(&amp;#39;^&amp;#39;, regex, &amp;#39;$&amp;#39;)


  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Keep only words which match the exact case, and do not contain excluded
  # letters, or letters in the wrong spot
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  words &amp;lt;- grep(regex, words, value = TRUE, ignore.case = TRUE)

  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Built a vector of all included letters regardless of whether they&amp;#39;re in
  # the wrong spot or not.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  included_letters1 &amp;lt;- strsplit(exact, &amp;#39;&amp;#39;)[[1]]
  included_letters2 &amp;lt;- unlist(strsplit(wrong_spot, &amp;#39;&amp;#39;))
  included_letters  &amp;lt;- c(included_letters1, included_letters2)
  included_letters  &amp;lt;- included_letters[included_letters != &amp;#39;.&amp;#39;]
  included_letters  &amp;lt;- sort(unique(included_letters))
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check that we have all included letters required
  # Do this by comparing the sorted letters within each word vs a sorted regex
  # e.g. to check for letters &amp;#39;r&amp;#39; and &amp;#39;e&amp;#39; in &amp;#39;rebel&amp;#39;
  #  grepl(&amp;#39;e.*r&amp;#39;, &amp;#39;beerl&amp;#39;)
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (length(included_letters) &amp;gt; 0) {

    sorted_included_letters &amp;lt;- paste(sort(included_letters), collapse = &amp;quot;.*&amp;quot;)

    split_words &amp;lt;- strsplit(words, &amp;#39;&amp;#39;)
    sorted_letters &amp;lt;- vapply(split_words, function(letters) {
      paste0(sort(letters), collapse = &amp;quot;&amp;quot;)
    }, character(1))

    matching_included_letters &amp;lt;- which(grepl(sorted_included_letters, sorted_letters))
    words &amp;lt;- words[matching_included_letters]
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # enforce a known count e.g. if it is known that there is only a single
  # &amp;#39;e&amp;#39; then drop words like &amp;quot;rebel&amp;quot; from the list of candidate words
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  split_words &amp;lt;- strsplit(words, &amp;#39;&amp;#39;)
  for (i in seq_along(known_count)) {
    letter &amp;lt;- names(known_count)[1]
    count  &amp;lt;- known_count[[1]]
    match_counts &amp;lt;- vapply(split_words, function(x) {
      sum(x == letter) == count
    }, logical(1))
    words &amp;lt;- words[match_counts]
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Re-order words by their score. lowest first.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  split_words &amp;lt;- strsplit(words, &amp;#39;&amp;#39;)
  word_scores &amp;lt;- vapply(split_words, score_letters, numeric(1))
  words[order(word_scores)]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle---whats-my-first-guess&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Puzzle - What’s my first guess?&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/00.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read a bit list of words that is available on many MacOS/Linux systems
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
words &amp;lt;- readLines(&amp;quot;/usr/share/dict/words&amp;quot;)

words &amp;lt;- filter_words(words, exact = &amp;quot;.....&amp;quot;)
head(words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;otate&amp;quot; &amp;quot;tatta&amp;quot; &amp;quot;tenet&amp;quot; &amp;quot;Aotea&amp;quot; &amp;quot;eaten&amp;quot; &amp;quot;enate&amp;quot; &amp;quot;tatie&amp;quot; &amp;quot;teest&amp;quot; &amp;quot;teste&amp;quot;
#&amp;gt; [10] &amp;quot;setae&amp;quot; &amp;quot;tease&amp;quot; &amp;quot;teeth&amp;quot; &amp;quot;theet&amp;quot; &amp;quot;State&amp;quot; &amp;quot;state&amp;quot; &amp;quot;taste&amp;quot; &amp;quot;Tates&amp;quot; &amp;quot;testa&amp;quot;
#&amp;gt; [19] &amp;quot;Teton&amp;quot; &amp;quot;arete&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;guess-eaten&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;eaten&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;There’s a lot of sillier words in the word list, so I picked out something a
bit more common: &lt;code&gt;eaten&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/01.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For the next guess:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;t&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt; are definitely excluded letters
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;excluded_letters = &#34;atn&#34;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;the first &lt;code&gt;e&lt;/code&gt; was correct but in the wrong spot
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wrong_spot = c(&#39;e&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;, &#39;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;the second &lt;code&gt;e&lt;/code&gt; is not part of the word at all, which means there can be only 1 e in this word
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;known_count = c(e = 1)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- filter_words(words, exact = &amp;quot;.....&amp;quot;, excluded_letters = &amp;quot;atn&amp;quot;, 
                      wrong_spot = c(&amp;#39;e&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;), known_count = c(e=1))
head(words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;hoose&amp;quot; &amp;quot;hoise&amp;quot; &amp;quot;issei&amp;quot; &amp;quot;osier&amp;quot; &amp;quot;Rhoeo&amp;quot; &amp;quot;serio&amp;quot; &amp;quot;diose&amp;quot; &amp;quot;idose&amp;quot; &amp;quot;loose&amp;quot;
#&amp;gt; [10] &amp;quot;oside&amp;quot; &amp;quot;ohelo&amp;quot; &amp;quot;rodeo&amp;quot; &amp;quot;shies&amp;quot; &amp;quot;Heidi&amp;quot; &amp;quot;helio&amp;quot; &amp;quot;horse&amp;quot; &amp;quot;roleo&amp;quot; &amp;quot;shoer&amp;quot;
#&amp;gt; [19] &amp;quot;shore&amp;quot; &amp;quot;cooer&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-rodeo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;rodeo&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/02.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For the next guess:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;o&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt; should be added to &lt;code&gt;excluded_letters&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;e&lt;/code&gt; is still not in the correct spot, and we now know that &lt;code&gt;r&lt;/code&gt; is part of the
word but it should not be in the first position.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- filter_words(words, exact = &amp;quot;.....&amp;quot;, excluded_letters = &amp;quot;atnod&amp;quot;, 
                      wrong_spot = c(&amp;#39;er&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;&amp;#39;), known_count = c(e=1))
head(words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;hirse&amp;quot; &amp;quot;shire&amp;quot; &amp;quot;Seric&amp;quot; &amp;quot;cheir&amp;quot; &amp;quot;cress&amp;quot; &amp;quot;swire&amp;quot; &amp;quot;crile&amp;quot; &amp;quot;serif&amp;quot; &amp;quot;shure&amp;quot;
#&amp;gt; [10] &amp;quot;cerci&amp;quot; &amp;quot;ceric&amp;quot; &amp;quot;Circe&amp;quot; &amp;quot;girse&amp;quot; &amp;quot;curie&amp;quot; &amp;quot;ferri&amp;quot; &amp;quot;freir&amp;quot; &amp;quot;Iberi&amp;quot; &amp;quot;meril&amp;quot;
#&amp;gt; [19] &amp;quot;ureic&amp;quot; &amp;quot;crime&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-shire&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;shire&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/03.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For the next guess:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I now know that &lt;code&gt;r&lt;/code&gt; is the 4th letter in the word
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;exact = &#34;...r.&#34;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;s&lt;/code&gt;, &lt;code&gt;h&lt;/code&gt; and &lt;code&gt;i&lt;/code&gt; are all excluded from this word.&lt;/li&gt;
&lt;li&gt;I now know that &lt;code&gt;e&lt;/code&gt; should not be the last letter in this word&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- filter_words(words, exact = &amp;quot;...r.&amp;quot;, excluded_letters = &amp;quot;atnodshi&amp;quot;, 
                      wrong_spot = c(&amp;#39;er&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;e&amp;#39;), known_count = c(e=1))
head(words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;merry&amp;quot; &amp;quot;ferry&amp;quot; &amp;quot;clerk&amp;quot; &amp;quot;Perry&amp;quot; &amp;quot;perry&amp;quot; &amp;quot;berry&amp;quot; &amp;quot;lyery&amp;quot; &amp;quot;Kerry&amp;quot; &amp;quot;kerry&amp;quot;
#&amp;gt; [10] &amp;quot;querl&amp;quot; &amp;quot;becry&amp;quot; &amp;quot;Jerry&amp;quot; &amp;quot;jerry&amp;quot; &amp;quot;Jewry&amp;quot; &amp;quot;query&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-merry&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;merry&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/04.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words &amp;lt;- filter_words(words, exact = &amp;quot;.erry&amp;quot;, excluded_letters = &amp;quot;atnodshim&amp;quot;, 
                      wrong_spot = c(&amp;#39;er&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;e&amp;#39;), known_count = c(e=1))
head(words, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;ferry&amp;quot; &amp;quot;Perry&amp;quot; &amp;quot;perry&amp;quot; &amp;quot;berry&amp;quot; &amp;quot;Kerry&amp;quot; &amp;quot;kerry&amp;quot; &amp;quot;Jerry&amp;quot; &amp;quot;jerry&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;guess-ferry&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Guess &lt;code&gt;ferry&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wordle-old/05.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;solved-now-what&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Solved! Now what?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;This might be a nifty Shiny app if anyone felt so inclined.&lt;/li&gt;
&lt;li&gt;Streamline/optimise code -
but it runs fast enough for now for it not to be an issue&lt;/li&gt;
&lt;li&gt;Nicer interface - maybe an R6 wrapper to retain state&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {ggsvg} - use SVG as ggplot points</title>
      <link>https://coolbutuseless.github.io/2021/12/23/introducing-ggsvg-use-svg-as-ggplot-points/</link>
      <pubDate>Thu, 23 Dec 2021 21:35:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/23/introducing-ggsvg-use-svg-as-ggplot-points/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggsvg---use-svg-as-points-in-ggplot&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggsvg - Use SVG as points in ggplot&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggsvg&lt;/code&gt; is an extension to ggplot to use arbitrary SVG as points.&lt;/p&gt;
&lt;p&gt;This SVG can be customised to respond to aesthetics e.g. element colours can
changes in response to fill and/or colour scales.&lt;/p&gt;
&lt;p&gt;However, aesthetics are not limited to colour - any other SVG parameter can be
linked to any aesthetic which makes sense e.g. an aesthethic may be used
to control the corner radius on a rounded rectangle.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;geom_point_svg()&lt;/code&gt; is equivalent to &lt;code&gt;geom_point()&lt;/code&gt; except it also requires
SVG text to be set (via the &lt;code&gt;svg&lt;/code&gt; argument)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scale_svg_*&lt;/code&gt; a full(?) set of compatible scale functions for controlling the mapping
of values to arbitrary named aesthetics.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/ggsvg&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cssparser&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/svgparser&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/ggsvg&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;debugging&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Debugging&lt;/h4&gt;
&lt;p&gt;Set &lt;code&gt;options(GGSVG_DEBUG = TRUE)&lt;/code&gt; for some verbose debugging.&lt;/p&gt;
&lt;p&gt;This will cause &lt;code&gt;{ggsvg}&lt;/code&gt; to output the final SVG for each and every element
it wants to put on the plot.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-svg-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple SVG Image&lt;/h2&gt;
&lt;p&gt;An SVG Christmas Tree with a hex star on top!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggsvg)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define simple SVG
#   - Square with rounded corners and a circle inside it.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
svg_text &amp;lt;- &amp;#39;
  &amp;lt;svg viewBox=&amp;quot;0 0 100 100 &amp;quot;&amp;gt;
    &amp;lt;polygon points = &amp;quot;20,80 80,80 50,20&amp;quot; fill=&amp;quot;darkgreen&amp;quot; /&amp;gt;
    &amp;lt;polygon points = &amp;quot;40,83 60,83 60,95 40,95&amp;quot; fill=&amp;quot;darkred&amp;quot; /&amp;gt;
    &amp;lt;polygon points = &amp;quot;58.66 25.00 50.00 30.00 41.34 25.00 41.34 15.00 50.00 10.00 58.66 15.00 58.66 25.00&amp;quot; 
       fill=&amp;quot;yellow3&amp;quot; /&amp;gt;
  &amp;lt;/svg&amp;gt;
  &amp;#39;


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render SVG with `{svgparser}`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grob &amp;lt;- svgparser::read_svg(svg_text)
grid::grid.newpage()
grid::grid.draw(grob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-23-ggsvg_files/figure-html/simple_svg-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-svg-drawn-for-each-point&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple SVG drawn for each point&lt;/h2&gt;
&lt;p&gt;Here, the simple SVG will be used as a plotting character.&lt;/p&gt;
&lt;p&gt;The point locations are given by the capital “R” in the Hershey script
font.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# remotes::install_github(&amp;#39;coolbutuseless/hershey&amp;#39;)
library(hershey)
letter &amp;lt;- hershey[hershey$char == &amp;#39;R&amp;#39; &amp;amp; hershey$font == &amp;#39;scriptc&amp;#39;,]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use &amp;#39;geom_point_svg&amp;#39; to plot SVG image at each point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(letter) +
  geom_path(aes(x, y, group = stroke), alpha = 0.5) +
  geom_point_svg(
    mapping  = aes(x, y),
    svg      = svg_text,
    size     = 10
  ) +
  theme_bw() + 
  coord_equal() + 
  labs(
    title    = &amp;quot;Merry Christmas #RStats&amp;quot;,
    subtitle = &amp;quot;{ggsvg} Using SVG as points&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-23-ggsvg_files/figure-html/simple-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-aesthetics&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple aesthetics&lt;/h2&gt;
&lt;p&gt;This is a basic example showing how ggplot aesthetics may be used to control
SVG image properties.&lt;/p&gt;
&lt;p&gt;Some key things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Locations for ggplot to insert aesthetics via the &lt;code&gt;glue&lt;/code&gt; package are
marked with &lt;strong&gt;double&lt;/strong&gt; curly braces i.e. &lt;code&gt;{{...}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;One such variables has been added to the SVG - &lt;code&gt;{{fill_tree}}&lt;/code&gt; is
used in place of the static colour that was defined in the original SVG&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fill_tree&lt;/code&gt; must now appear as an aesthetic in the call to
&lt;code&gt;geom_point_svg()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Need to inform &lt;code&gt;ggplot2&lt;/code&gt; of the default value for each new aesthetic by setting
the &lt;code&gt;defaults&lt;/code&gt; argument&lt;/li&gt;
&lt;li&gt;For each aesthetic, you will need to add a scale with
&lt;code&gt;scale_svg_*()&lt;/code&gt; to let ggplot know how it should turn the mapped variable into
a value to insert in the SVG.&lt;/li&gt;
&lt;li&gt;In this case, the variables is a &lt;code&gt;fill&lt;/code&gt; variable, so use one of
&lt;code&gt;scale_svg_fill_*()&lt;/code&gt; family to ensure that the value is mapped to a colour.&lt;/li&gt;
&lt;li&gt;The new &lt;code&gt;scale_svg_*()&lt;/code&gt; scales are mostly identical to their &lt;code&gt;ggplot&lt;/code&gt; counterparts
except:
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;aesthetics&lt;/code&gt; argument no longer has a default value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colourbar&lt;/code&gt; guides have been tweaked to allow for non-standard aesthetics.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggsvg)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define some SVG
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
svg_text &amp;lt;- &amp;#39;
  &amp;lt;svg viewBox=&amp;quot;0 0 100 100 &amp;quot;&amp;gt;
    &amp;lt;polygon points = &amp;quot;20,80 80,80 50,20&amp;quot; fill=&amp;quot;{{fill_tree}}&amp;quot; /&amp;gt;
    &amp;lt;polygon points = &amp;quot;40,83 60,83 60,95 40,95&amp;quot; fill=&amp;quot;darkred&amp;quot; /&amp;gt;
    &amp;lt;polygon points = &amp;quot;58.66 25.00 50.00 30.00 41.34 25.00 41.34 15.00 50.00 10.00 58.66 15.00 58.66 25.00&amp;quot; 
       fill=&amp;quot;yellow3&amp;quot; /&amp;gt;
  &amp;lt;/svg&amp;gt;
  &amp;#39;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use &amp;#39;geom_svg&amp;#39; to plot with this symbol
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(mtcars) +
  geom_point_svg(
    mapping     = aes(
      x           = mpg, 
      y           = wt, 
      size        = cyl, 
      fill_tree   = as.factor(cyl)
    ),
    svg         = svg_text,
    defaults    = list(fill_tree = &amp;#39;darkgreen&amp;#39;)
  ) +
  labs(
    title    = &amp;quot;{ggsvg} Simple SVG with fill aesthetic&amp;quot;,
    subtitle = &amp;quot;`cyl` mapped to tree colour and size&amp;quot;
  ) + 
  theme_bw() +
  scale_size(range = c(5, 12), guide = &amp;#39;none&amp;#39;) + 
  scale_svg_fill_viridis_d(&amp;#39;fill_tree&amp;#39;, guide = guide_legend(override.aes = list(size = 7)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-23-ggsvg_files/figure-html/simpleaes-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;more-complex-example---virus-with-multiple-aesthetics&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;More complex example - Virus with multiple aesthetics&lt;/h2&gt;
&lt;p&gt;This is an SVG image of something virus-like from &lt;a href=&#34;https://commons.wikimedia.org/wiki/File:Virus_black_white.svg&#34;&gt;wikimedia&lt;/a&gt; - it is public domain.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;svg_file &amp;lt;- system.file(&amp;quot;Virus_black_white.svg&amp;quot;, package = &amp;quot;ggsvg&amp;quot;)
grob &amp;lt;- svgparser::read_svg(svg_file)
grid::grid.draw(grob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-23-ggsvg_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;I have hand-edited the SVG to add two locations for &lt;code&gt;{glue}&lt;/code&gt; to insert text:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;fill = &#34;{{fill_inner}}&#34;&lt;/code&gt; has been added to all elements in the central
body of the virus.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fill = &#34;{{fill_outer}}&#34;&lt;/code&gt; has been added to the “arms” of the virus&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggsvg)

fake_data &amp;lt;- readr::read_csv(
&amp;#39;county, month, count, majority
A, 1, 1.00, delta
A, 2, 1.40, delta
A, 3, 1.96, delta
A, 4, 2.74, delta
A, 5, 3.85, omicron
A, 6, 5.38, omicron
B, 1, 1.00, delta
B, 2, 1.10, delta
B, 3, 1.21, omicron
B, 4, 1.33, omicron
B, 5, 1.46, omicron
B, 6, 1.61, omicron
&amp;#39;, show_col_types = FALSE)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read in the SVG as text.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
svg_file &amp;lt;- system.file(&amp;quot;virus.svg&amp;quot;, package = &amp;quot;ggsvg&amp;quot;)
svg_text &amp;lt;- paste(readLines(svg_file), collapse = &amp;quot;\n&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use &amp;#39;geom_svg&amp;#39; to plot with this symbol
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(fake_data) +
  geom_line(aes(month, count, group = county)) +
  geom_point_svg(
    mapping = aes(month, count, 
                  size = count, 
                  fill_inner = county, 
                  fill_outer = majority),
    svg         = svg_text,
    defaults    = list(fill_inner = &amp;#39;#aaaaaa80&amp;#39;, fill_outer = &amp;#39;#aaaaaa80&amp;#39;)
  ) +
  theme_bw() +
  scale_size_continuous(range = c(6, 20), guide = &amp;#39;none&amp;#39;) +
  scale_svg_fill_brewer(
    aesthetics = &amp;#39;fill_inner&amp;#39;, 
    palette = &amp;#39;Dark2&amp;#39;,
    guide = guide_legend(override.aes = list(size = 9))
  ) +
  scale_svg_fill_manual(
    aesthetics = &amp;#39;fill_outer&amp;#39;,
    values = c(delta = &amp;#39;grey50&amp;#39;, omicron = &amp;#39;darkred&amp;#39;),
    guide = guide_legend(override.aes = list(size = 9))
  ) + 
  labs(
    title    = &amp;quot;{ggsvg} - Complex SVG with multiple fill aesthetics&amp;quot;,
    subtitle = &amp;quot;Virus body coloured by county\nVirus tendrils coloured by delta/omicron majority status&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-23-ggsvg_files/figure-html/coronavirus-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Lex, Parse and Evaluate a Simple S-Expression with {flexo}</title>
      <link>https://coolbutuseless.github.io/2021/12/09/lex-parse-and-evaluate-a-simple-s-expression-with-flexo/</link>
      <pubDate>Thu, 09 Dec 2021 04:10:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/09/lex-parse-and-evaluate-a-simple-s-expression-with-flexo/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(flexo)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;flexo&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;{flexo}&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/coolbutuseless/flexo&#34;&gt;flexo&lt;/a&gt; is a package containing a simple
lexer (to split text into named tokens) and a TokenStream R6 class for manipulating
the stream (in order to iterate through the stream to parse it).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;lispy-s-expression&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;LISPy S-Expression&lt;/h1&gt;
&lt;p&gt;The following code is an S-Expression which evaluates to &lt;code&gt;21&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sexp &amp;lt;- &amp;quot;(+ (* 2 3) (* 3 5))&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;lex-the-s-expression-into-tokens&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Lex the S-Expression into tokens&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define the regex for each token
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sexp_regexes &amp;lt;- c(
  open       = &amp;quot;\\(&amp;quot;,
  close      = &amp;quot;\\)&amp;quot;,
  num        = &amp;quot;\\d+&amp;quot;,
  whitespace = &amp;quot;\\s+&amp;quot;,
  op         = &amp;quot;.+?&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Split the expression into tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tokens &amp;lt;- lex(sexp, sexp_regexes)
tokens &amp;lt;- tokens[names(tokens) != &amp;#39;whitespace&amp;#39;]

tokens&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  open    op  open    op   num   num close  open    op   num   num close close 
#&amp;gt;   &amp;quot;(&amp;quot;   &amp;quot;+&amp;quot;   &amp;quot;(&amp;quot;   &amp;quot;*&amp;quot;   &amp;quot;2&amp;quot;   &amp;quot;3&amp;quot;   &amp;quot;)&amp;quot;   &amp;quot;(&amp;quot;   &amp;quot;*&amp;quot;   &amp;quot;3&amp;quot;   &amp;quot;5&amp;quot;   &amp;quot;)&amp;quot;   &amp;quot;)&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;evaluate-the-expression-by-interpreting-the-tokens&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Evaluate the expression by interpreting the tokens&lt;/h1&gt;
&lt;p&gt;Recurisve evaulation of the S-Expression by calculating on the stream of tokens.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a token stream
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stream &amp;lt;- TokenStream$new(tokens)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Recursive function to evaluate a TokenStream full of sexp tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval_sexp &amp;lt;- function(stream) {
  name  &amp;lt;- stream$read_names(1)
  
  if (name == &amp;#39;op&amp;#39;) {
    
    # Get the &amp;#39;op&amp;#39;
    op &amp;lt;- stream$consume(1)
    
    # Gather the args
    args &amp;lt;- list()
    while (stream$read_names(1) != &amp;#39;close&amp;#39;) {
      this_arg &amp;lt;- eval_sexp(stream)
      args     &amp;lt;- c(args, this_arg)
    }
    stream$consume(1)           # Consume the &amp;quot;close&amp;quot; bracket
    result &amp;lt;- do.call(op, args) # Eval the &amp;quot;op&amp;quot;
  } else if (name == &amp;quot;open&amp;quot;) {
    stream$consume(1)           # Consume the &amp;quot;open&amp;quot; bracket
    result &amp;lt;- eval_sexp(stream) # Recursive eval
  } else if (name == &amp;#39;num&amp;#39;) {
    result &amp;lt;- as.numeric( stream$consume(1) ) 
  } 
  
  result
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Calculate the result
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eval_sexp(stream)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 21&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;evaluate-the-expression-by-translating-to-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Evaluate the expression by translating to R&lt;/h1&gt;
&lt;p&gt;Translate the S-Expression into a string of R code and then evaluate it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a token stream
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stream &amp;lt;- TokenStream$new(tokens)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Evaluate a TokenStream full of sexp tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
convert_sexp &amp;lt;- function(stream) {
  name  &amp;lt;- stream$read_names(1)
  
  if (name == &amp;#39;op&amp;#39;) {
    
    # Get the &amp;#39;op&amp;#39;
    op &amp;lt;- stream$consume(1)
    
    # Gather the args
    args &amp;lt;- list()
    while (stream$read_names(1) != &amp;#39;close&amp;#39;) {
      this_arg &amp;lt;- convert_sexp(stream)
      args     &amp;lt;- c(args, this_arg)
    }
    stream$consume(1)           # Consume the &amp;quot;close&amp;quot; bracket
    
    # Create some R code
    result &amp;lt;- paste0(&amp;quot;`&amp;quot;, op, &amp;quot;`(&amp;quot;, paste(args, collapse = &amp;quot;, &amp;quot;), &amp;quot;)&amp;quot;)
  } else if (name == &amp;quot;open&amp;quot;) {
    stream$consume(1)           # Consume the &amp;quot;open&amp;quot; bracket
    result &amp;lt;- convert_sexp(stream) # Recursive eval
  } else if (name == &amp;#39;num&amp;#39;) {
    result &amp;lt;- as.numeric( stream$consume(1) ) 
  } 
  
  result
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Calculate the result
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
r_string &amp;lt;- convert_sexp(stream)
r_string&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;`+`(`*`(2, 3), `*`(3, 5))&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(parse(text = r_string))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 21&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Base64 encoding/decoding in plain R</title>
      <link>https://coolbutuseless.github.io/2021/12/04/base64-encoding/decoding-in-plain-r/</link>
      <pubDate>Sat, 04 Dec 2021 05:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/04/base64-encoding/decoding-in-plain-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;As part of working on &lt;a href=&#34;https://github.com/coolbutuseless/svgparser&#34;&gt;{svgparser}&lt;/a&gt;
I am adding support for the &lt;code&gt;&amp;lt;image&amp;gt;&lt;/code&gt; tag in SVGs.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;image&amp;gt;&lt;/code&gt; tags can reference an image as a URL, or they can also contain an
inline copy of the image encoded in an “ASCII-safe” format.&lt;/p&gt;
&lt;p&gt;Base64 encoding is one commonly supported method for converting raw bytes
into ASCII character strings.&lt;/p&gt;
&lt;p&gt;The following code is a mini-exploration into how Base64 encoding/decoding
could be done quickly(?) in base R.&lt;/p&gt;
&lt;p&gt;TL;DR - base64 encoding/decoding can be done easily in base R, but not quickly.&lt;br /&gt;
I’ll be better off using one of the packages with C code for this task.&lt;/p&gt;
&lt;p&gt;Not really a surprising result, but this was a fun diversion.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;base64-encodingdecoding&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base64 Encoding/Decoding&lt;/h2&gt;
&lt;p&gt;A high level description of Base64 encoding:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;View the sequence of raw bytes as a sequence of raw &lt;em&gt;bits&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Group the bits six-at-a-time.&lt;/li&gt;
&lt;li&gt;Interpret each 6-bit grouping as an integer (0-63)&lt;/li&gt;
&lt;li&gt;Use this integer as index to choose from safe ASCII character set
&lt;ul&gt;
&lt;li&gt;26 uppercase letters&lt;/li&gt;
&lt;li&gt;26 lowercase letters&lt;/li&gt;
&lt;li&gt;10 digits&lt;/li&gt;
&lt;li&gt;‘+’ and ‘\’ make up the last to characters&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Combine all these characters in a single string&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Decoding is then just the reverse of this process.&lt;/p&gt;
&lt;p&gt;Note that there is some messy stuff to do with padding that I’m not doing
to describe here, but the code below mostly(?) deals with this.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;base64-encodingdecoding-support-in-existing-r-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base64 encoding/decoding support in existing R packages&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://cran.r-project.org/package=openssl&#34;&gt;{openssl}&lt;/a&gt; package and the
&lt;a href=&#34;https://cran.r-project.org/package=base64enc&#34;&gt;{base64enc}&lt;/a&gt; package both support fast
encoding/decoding of Base64 values&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# input data should be raw bytes
data &amp;lt;- as.raw(sample(1:10))
data&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] 09 04 07 01 02 05 03 0a 06 08&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Encode to a single Base64 encoded string
b64 &amp;lt;- openssl::base64_encode(data)
b64&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;CQQHAQIFAwoGCA==&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Decode the string back into raw data
openssl::base64_decode(b64)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] 09 04 07 01 02 05 03 0a 06 08&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;vanilla-r-code-for-base64-encodingdecoding&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vanilla R code for Base64 Encoding/Decoding&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create lookup table to convert characters to their 6-bit-integer values
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char_to_int &amp;lt;- function(vec) {
  unname(vapply(as.character(vec), utf8ToInt, integer(1)))
}


lookup_names &amp;lt;- c(LETTERS, letters, 0:9, &amp;#39;+&amp;#39;, &amp;#39;/&amp;#39;, &amp;#39;=&amp;#39;)
lookup_values &amp;lt;- c(
  char_to_int(LETTERS) - char_to_int(&amp;#39;A&amp;#39;),
  char_to_int(letters) - char_to_int(&amp;#39;a&amp;#39;) + 26L,
  char_to_int(0:9)     - char_to_int(&amp;#39;0&amp;#39;) + 52L,
  62L,
  63L,
  0L
)

lookup &amp;lt;- setNames(lookup_values, lookup_names)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Decode a base64 string to a vector of raw bytes
#&amp;#39;
#&amp;#39; @param b64 Single character string containing base64 encoded values
#&amp;#39;
#&amp;#39; @return raw vector
#&amp;#39;
#&amp;#39; @example
#&amp;#39; b64 &amp;lt;- &amp;#39;iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=&amp;#39;
#&amp;#39; decode_base64(b64)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
decode_base64 &amp;lt;- function(b64) {
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Get a, integer 6-bit value for each of the characters in the string
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  chars    &amp;lt;- strsplit(b64, &amp;#39;&amp;#39;)[[1]]
  six_bits &amp;lt;- lookup[chars]

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Explode these integers into their individual bit values (32 bits per int)
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bits &amp;lt;- intToBits(six_bits)

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Convert to 32 row matrix
  # Truncate to 6-row matrix (ignoring bits 7-32).
  # Then reshape to 8-row matrix.
  # Note that &amp;#39;intToBits()&amp;#39; output is little-endian, so switch it here to
  # big endian for easier logic
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mat &amp;lt;- matrix(as.integer(bits), nrow = 32)[6:1,]
  N &amp;lt;- length(mat)
  stopifnot(N %% 8 == 0)
  dim(mat) &amp;lt;- c(8, N/8)

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Convert bits to bytes by multiplying out rows by 2^N and summing
  # along columns (i.e. each column is a bit-pattern for an 8-bit number)
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  raw_vec &amp;lt;- as.raw(colSums(mat * c(128L, 64L, 32L, 16L, 8L, 4L, 2L, 1L)))

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Trim padded characters
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (endsWith(b64, &amp;quot;==&amp;quot;)) {
    length(raw_vec) &amp;lt;- length(raw_vec) - 2L
  } else if (endsWith(b64, &amp;quot;=&amp;quot;)) {
    length(raw_vec) &amp;lt;- length(raw_vec) - 1L
  }

  raw_vec
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Encode a raw vector to a base64 encoded character string
#&amp;#39;
#&amp;#39; @param raw_vec raw vector
#&amp;#39;
#&amp;#39; @return single character string containing base64 encoded values
#&amp;#39;
#&amp;#39; @example
#&amp;#39; encode_base64(as.raw(1:20))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
encode_base64 &amp;lt;- function(raw_vec) {
  stopifnot(is.raw(raw_vec))

  # work out if we need to pad the result to an 8-bit boundary
  npad &amp;lt;- 3L - (length(raw_vec) %% 3L)
  if (npad %in% 1:2) {
    length(raw_vec) &amp;lt;- length(raw_vec) + npad
  }

  # Create an 8 row matrix.  Each column is the bit-vector for an 8-bit number
  int &amp;lt;- as.integer(raw_vec)
  res &amp;lt;- as.integer(bitwAnd(rep(int, each = 8),  c(128L, 64L, 32L, 16L, 8L, 4L, 2L, 1L)) &amp;gt; 0)
  mat &amp;lt;- matrix(res, nrow = 8)

  # Reshape to a 6-row matrix (i.e. 6-bit numbers)
  N &amp;lt;- length(mat)
  stopifnot(N %% 6 == 0)
  dim(mat) &amp;lt;- c(6, N/6)

  # Calcualte the 6-bit numbers
  mat &amp;lt;- mat * c(32L, 16L, 8L, 4L, 2L, 1L)
  values &amp;lt;- colSums(mat)

  # Find the letter which is associated with each 6-bit number
  # and paste together into a string
  chars &amp;lt;- lookup_names[values + 1L]
  b64 &amp;lt;- paste(chars, collapse = &amp;quot;&amp;quot;)

  # Replace padding bits with &amp;#39;=&amp;#39; signs
  if (npad == 1) {
    b64 &amp;lt;- gsub(&amp;quot;.$&amp;quot;, &amp;quot;=&amp;quot;, b64)
  } else if (npad == 2) {
    b64 &amp;lt;- gsub(&amp;quot;..$&amp;quot;, &amp;quot;==&amp;quot;, b64)
  }

  b64
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;check-results-agree-with-openssl&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Check results agree with &lt;code&gt;{openssl}&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;for (i in seq(100)) {
  data    &amp;lt;- as.raw(sample(i))
  b64_me  &amp;lt;- encode_base64(data)
  b64_ref &amp;lt;- openssl::base64_encode(data)
  
  # Does my base64 string agree with `openssl`?
  stopifnot(identical(b64_me, b64_ref))
  
  # Does the decoded value match the original data?
  decoded &amp;lt;- decode_base64(b64_ref)
  stopifnot(identical(data, decoded))
}

print(&amp;quot;All good!&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;All good!&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rough-encoding-speed-comparison&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rough encoding speed comparison&lt;/h2&gt;
&lt;p&gt;Simple timing shows that the R code is 2x to 100x slower than the C code. Base
R code is only competitive at really small sizes.&lt;/p&gt;
&lt;p&gt;No real suprises.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- bench::press(
  N = c(10, 100, 10000),
  {
    data &amp;lt;- as.raw(sample(N) %% 256)
    bench::mark(
      openssl::base64_encode(data),
      encode_base64(data)
    )
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-8&#34;&gt;Table 1: &lt;/span&gt;Speed timing&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;openssl::base64_encode(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.31µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27978.7464&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;encode_base64(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48.68µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;59.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14708.8449&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.53KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;openssl::base64_encode(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.6µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.17µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28753.0286&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;192B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;encode_base64(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;91.39µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;122.42µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6996.1620&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25.05KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;openssl::base64_encode(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;57.08µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;74.45µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11249.6782&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.08KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;encode_base64(data)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.17ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.22ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160.5602&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.36MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-04-base64_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {svgparser} - an SVG renderer in plain R</title>
      <link>https://coolbutuseless.github.io/2021/12/02/introducing-svgparser-an-svg-renderer-in-plain-r/</link>
      <pubDate>Thu, 02 Dec 2021 05:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/12/02/introducing-svgparser-an-svg-renderer-in-plain-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;svgparser&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;svgparser&lt;/h1&gt;
&lt;div id=&#34;load-svg-files-as-r-vector-objects-grobs-or-data.frames&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Load SVG files as R vector objects (grobs) or data.frames&lt;/h4&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/svgparser/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/svgparser/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;svgparser&lt;/code&gt; loads vector-based &lt;strong&gt;SVG&lt;/strong&gt; images as R vector objects.&lt;/p&gt;
&lt;p&gt;The vector objects which are created in R are the standard graphics object (‘grob’)
in the base R &lt;code&gt;{grid}&lt;/code&gt; graphics system.&lt;/p&gt;
&lt;p&gt;SVG images can also be imported as data.frames. Each shape, line and point is
represented in the data.frame with copious helpings of metadata to relate
individual coordinates to the original SVG structure.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-load-svg-as-vector-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Load SVG as vector image&lt;/h2&gt;
&lt;p&gt;This example loads an SVG image into a base R &lt;code&gt;grid&lt;/code&gt; graphics object, and
then draws the object using &lt;code&gt;grid.draw&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that this is not a fixed size raster image! This is a vector image
which can be resized without loss of precision.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiger_filename &amp;lt;- system.file(&amp;quot;tiger.svg&amp;quot;, package = &amp;quot;svgparser&amp;quot;)
tiger_grob &amp;lt;- svgparser::read_svg(tiger_filename)
grid::grid.draw(tiger_grob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-02-svgparser_files/figure-html/opener1-1.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-load-svg-as-a-data.frame&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Load SVG as a data.frame&lt;/h2&gt;
&lt;p&gt;This example loads an SVG as a data.frame and then plots the coordinates
using ggplot. The element type from the original SVG is used as the
aesthetic for colouring the lines in the plot.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiger_df &amp;lt;- svgparser::read_svg(tiger_filename, obj_type = &amp;#39;data.frame&amp;#39;)

nrow(tiger_df)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 57117&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;knitr::kable(head(tiger_df, 3))&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
x
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
y
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
name
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
idx
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
path_idx
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
inst_idx
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
path
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
col
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
fill
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
alpha
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
lwd
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
lineend
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
linejoin
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
linemitre
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
fontsize
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
cex
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
fontface
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
fontfamily
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
font
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
xpath
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
tag
&lt;/th&gt;
&lt;th style=&#34;text-align:right;&#34;&gt;
elem_idx
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
-122.3000
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
84.2850
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
move
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
m -122.3 84.285
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#000000FF
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#FFFFFFFF
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
0.172
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
butt
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
mitre
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
4
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
12
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
plain
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
serif
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
/svg/g/g[1]/path
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
path
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
-122.3000
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
84.2850
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
bezier3_reflect
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
2
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
2
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
s 0.1 1.894 -0.73 1.875
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#000000FF
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#FFFFFFFF
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
0.172
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
butt
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
mitre
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
4
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
12
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
plain
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
serif
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
/svg/g/g[1]/path
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
path
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
-122.2997
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
84.2916
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
bezier3_reflect
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
2
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
2
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
s 0.1 1.894 -0.73 1.875
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#000000FF
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
#FFFFFFFF
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
0.172
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
butt
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
mitre
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
4
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
12
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
plain
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
serif
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
/svg/g/g[1]/path
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
path
&lt;/td&gt;
&lt;td style=&#34;text-align:right;&#34;&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There’s enough information in the data.frame to manually recreate most of the
SVG using whatever drawing mechanism you’d like. Here, I’ve used &lt;code&gt;ggplot2&lt;/code&gt; to
draw the outlines from the data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(tiger_df) + 
  geom_path(aes(x, y, colour = name, group = interaction(elem_idx, path_idx))) +
  scale_y_reverse()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-02-svgparser_files/figure-html/opener3-1.png&#34; width=&#34;60%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read_svg()&lt;/code&gt; read SVG into R as a &lt;code&gt;{grid}&lt;/code&gt; graphics object (grob) or data.frame&lt;/li&gt;
&lt;li&gt;&lt;code&gt;load_supertinyicon()&lt;/code&gt; to load an SVG icon from the
&lt;a href=&#34;https://github.com/edent/SuperTinyIcons&#34;&gt;Super Tiny Icons&lt;/a&gt; icon pack
included with this package. See &lt;code&gt;LICENSE-supertinycons.txt&lt;/code&gt; (MIT License)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;This package is available on &lt;a href=&#34;https://github.com/coolbutuseless/svgparser&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cssparser&amp;#39;) # Handles CSS styling
remotes::install_github(&amp;#39;coolbutuseless/svgparser&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;strong&gt;R &amp;gt; v4.1.0&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gradients and clipping paths are rendered as correctly as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With &lt;strong&gt;R &amp;lt; v4.1.0&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;solid colours will be used in place of gradients, and&lt;/li&gt;
&lt;li&gt;any elements which use a clipping path in the SVG will not be properly clipped in R.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/gggrid.html&#34;&gt;SVG in ggplot using gggrid&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/gggrid.html&#34;&gt;&lt;img width=&#34;40%&#34; src=&#34;https://coolbutuseless.github.io/img/svgparser/vignettes/gggrid.png&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/tileable.html&#34;&gt;Creating tileable patterns for R graphics&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/tileable.html&#34;&gt;&lt;img width=&#34;40%&#34; src=&#34;https://coolbutuseless.github.io/img/svgparser/vignettes/seamless3-1.png&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/ggplot2.html&#34;&gt;Add SVG to ggplot2 plots&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/ggplot2.html&#34;&gt;&lt;img width=&#34;40%&#34; src=&#34;https://coolbutuseless.github.io/img/svgparser/vignettes/ggplot.png&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/false-colours.html&#34;&gt;Debugging Issues by Using False Colouring&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/false-colours.html&#34;&gt;&lt;img width=&#34;40%&#34; src=&#34;https://coolbutuseless.github.io/img/svgparser/vignettes/tiger-mont.png&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/css.html&#34;&gt;Customising SVG with CSS&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/svgparser/articles/css.html&#34;&gt;&lt;img width=&#34;40%&#34; src=&#34;https://coolbutuseless.github.io/img/svgparser/vignettes/css-mont.png&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;svg-feature-support&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;SVG Feature Support&lt;/h2&gt;
&lt;table&gt;
&lt;caption&gt;
(#tab:features_svg)SVG Feature Support
&lt;/caption&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
Feature
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
Support
&lt;/th&gt;
&lt;th style=&#34;text-align:left;&#34;&gt;
Notes
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;path&amp;gt; elements
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Working well!
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;rect&amp;gt; &amp;lt;circle&amp;gt; etc
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Working
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;ellipse&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
No rotation yet
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;text&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lemonchiffon !important;&#34;&gt;meh&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Works at a basic level. Don’t expect anything using fancy text effects to work
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
style cascading
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Using &lt;code&gt;{cssparser}&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;linearGradient&amp;gt; &amp;lt;radialGradient&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
converted to R4.1 gradient objects. ‘userSpaceOnUse’ coordinate space only. Send examples!
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
transform presentation attribute
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;defs&amp;gt; &amp;lt;use&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;pattern&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightcoral !important;&#34;&gt;no&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Impossible?
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&amp;lt;filter&amp;gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightcoral !important;&#34;&gt;no&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Impossible?
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
animation
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightcoral !important;&#34;&gt;no&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Impossible?
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
linetypes
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightcoral !important;&#34;&gt;no&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
Planned feature - but R is much more limited compared to SVGs linetype features.
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
masks
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightcoral !important;&#34;&gt;no&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
need example SVG
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
clipping paths
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
&lt;span style=&#34;     border-radius: 4px; padding-right: 4px; padding-left: 4px; background-color: lightgreen !important;&#34;&gt;yes&lt;/span&gt;
&lt;/td&gt;
&lt;td style=&#34;text-align:left;&#34;&gt;
works on the few examples tested
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;svg-icon-pack-supertinyicons-is-included-with-the-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;SVG icon pack &lt;code&gt;SuperTinyIcons&lt;/code&gt; is included with the package&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/edent/SuperTinyIcons&#34;&gt;SuperTinyIcons&lt;/a&gt;
is a set of icons focussed on small representations of logos of some internet companies
and other images.&lt;/p&gt;
&lt;p&gt;These icons can be accessed from this package using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;supertinyicons&lt;/code&gt; (for the names of all the icons), and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;load_supertinyicon()&lt;/code&gt; to load an icon as an R object.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;code&gt;LICENSE-supertinycons.txt&lt;/code&gt; for MIT license information for this icon set.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;supertinyicon_names[1:10]
load_supertinyicon(&amp;#39;twitter&amp;#39;, obj_type = &amp;#39;svg&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;acast&amp;quot;          &amp;quot;access&amp;quot;         &amp;quot;adobe&amp;quot;          &amp;quot;airbnb&amp;quot;        
 [5] &amp;quot;amazon_alexa&amp;quot;   &amp;quot;amazon_s3&amp;quot;      &amp;quot;amazon&amp;quot;         &amp;quot;amberframework&amp;quot;
 [9] &amp;quot;andotp&amp;quot;         &amp;quot;android&amp;quot;       &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;svg xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; aria-label=&amp;quot;Twitter&amp;quot; role=&amp;quot;img&amp;quot; viewBox=&amp;quot;0 0 512 512&amp;quot;&amp;gt;
  &amp;lt;rect width=&amp;quot;512&amp;quot; height=&amp;quot;512&amp;quot; rx=&amp;quot;15%&amp;quot; fill=&amp;quot;#1da1f2&amp;quot;/&amp;gt;
  &amp;lt;path fill=&amp;quot;#fff&amp;quot; d=&amp;quot;M437 152a72 72 0 01-40 12a72 72 0 0032-40a72 72 0 01-45 17a72 72 0 00-122 65a200 200 0 01-145-74a72 72 0 0022 94a72 72 0 01-32-7a72 72 0 0056 69a72 72 0 01-32 1a72 72 0 0067 50a200 200 0 01-105 29a200 200 0 00309-179a200 200 0 0035-37&amp;quot;/&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid.draw(load_supertinyicon(&amp;#39;twitter&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-12-02-svgparser_files/figure-html/icon3-1.png&#34; width=&#34;30%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical bits&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;svgparser&lt;/code&gt; is vanilla R code which walks the XML tree and converts elements (and nested sub-elements) into
a nested set of &lt;code&gt;grid::grobTree()&lt;/code&gt; objects.&lt;/p&gt;
&lt;p&gt;Circles, lines and points are translated to their corresponding &lt;code&gt;grid&lt;/code&gt; object i.e.
&lt;code&gt;grid::circleGrob()&lt;/code&gt;, &lt;code&gt;grid::linesGrob()&lt;/code&gt;, &lt;code&gt;grid::pointsGrob()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Radial and linear gradients are captured as the new objects available in R4.1: &lt;code&gt;grid::radialGradient()&lt;/code&gt; and
&lt;code&gt;grid::linearGradient()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; tags, &lt;code&gt;{svgparser}&lt;/code&gt; extracts &lt;em&gt;xpath&lt;/em&gt; information to retrieve relevant referenced section of the
SVG, parse it into R objects and then insert it at the given location.&lt;/p&gt;
&lt;p&gt;There are only a few dependencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=xml2&#34;&gt;&lt;code&gt;{xml2}&lt;/code&gt;&lt;/a&gt; is used as to parse the SVG into R&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/cssparser&#34;&gt;&lt;code&gt;{cssparser}&lt;/code&gt;&lt;/a&gt; is used to cascade stylesheets within the XML representation. This
was initially built-in to svgparser, but was moved to a separate package as
things got complicated. (Who could have known that parsing and cascading style sheets
could be so complicated!)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=stringi&#34;&gt;&lt;code&gt;{stringi}&lt;/code&gt;&lt;/a&gt; is used as part of the lexer which breaks some of the SVG structures
into smaller objects for parsing e.g. transform strings like &lt;code&gt;translate(10, 10) rotate(50)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=rsvg&#34;&gt;{rsvg}&lt;/a&gt; renders SVG files into bitmaps, and
some other file representations.
&lt;ul&gt;
&lt;li&gt;This package is wraps the C library &lt;a href=&#34;https://github.com/GNOME/librsvg&#34;&gt;librsvg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=grImport2&#34;&gt;{grImport2}&lt;/a&gt; reads SVG files into R
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grImport2&lt;/code&gt; only seems to load SVG created by the Cairo graphics library&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;comparison-to-related-r-packages&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Comparison to related R packages&lt;/h4&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;21%&#34; /&gt;
&lt;col width=&#34;9%&#34; /&gt;
&lt;col width=&#34;35%&#34; /&gt;
&lt;col width=&#34;33%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;svgparser&lt;/th&gt;
&lt;th&gt;rsvg&lt;/th&gt;
&lt;th&gt;grImport2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Loads as Vector Object&lt;/td&gt;
&lt;td&gt;Yes (grob)&lt;/td&gt;
&lt;td&gt;No (bitmap)&lt;/td&gt;
&lt;td&gt;Yes (grob)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Loads as Standard Grob&lt;/td&gt;
&lt;td&gt;Yes (grobTree)&lt;/td&gt;
&lt;td&gt;No (bitmap)&lt;/td&gt;
&lt;td&gt;No (custom PictureGrob)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Exposes coordinates&lt;/td&gt;
&lt;td&gt;Yes (as a data.frame) along with SVG meta-information&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (via grid::grobPoints), but lacks meta-information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Note&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Backed by fast + well tested C library&lt;/td&gt;
&lt;td&gt;Will only load SVG created by Cairo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Thanks to early alpha testers:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/trevorld&#34;&gt;Trevor Davis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/timelyportfolio&#34;&gt;timelyportfolio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/SimonCoulombe&#34;&gt;Simon Coulombe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/mitchelloharawild&#34;&gt;Mitchell O’hara-Wild&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/MayaGans&#34;&gt;Maya Gans&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jthomasmock&#34;&gt;Thomas Mock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jeroen&#34;&gt;Jeroen Ooms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Ijeamakaanyene&#34;&gt;Ijeamakaanyene&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/halian-vilela&#34;&gt;Halian Vilela&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dmi3kno&#34;&gt;Dmytro Perepolkin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/arthurwelle&#34;&gt;arthurwelle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A simple 2048 game engine in R</title>
      <link>https://coolbutuseless.github.io/2021/11/14/a-simple-2048-game-engine-in-r/</link>
      <pubDate>Sun, 14 Nov 2021 19:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/11/14/a-simple-2048-game-engine-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;2048 in R&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;A simple/naive implementation of 2048 in plain R - with &lt;code&gt;{ggplot2}&lt;/code&gt; output
for a little bit of zing.&lt;/li&gt;
&lt;li&gt;Interactive keypress response seems basically impossible from R, so
this uses &lt;code&gt;readline()&lt;/code&gt; and you have to press return to register each
action.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/coolbutuseless/ffc5eef475f4c514731fb72d3d813a2d&#34;&gt;Code in a gist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Motivation:
&lt;ul&gt;
&lt;li&gt;Looking at some game stuff in R and this was the simplest thing I
could think to write&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;There’s an existing package on CRAN: &lt;a href=&#34;https://cran.r-project.org/package=twenty48&#34;&gt;twenty48&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;But I wanted to re-invent the wheel so I could think about the process
of game creation.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#    #####    ###   #        #####
#   #     #  #   #  #    #  #     #
#         # #     # #    #  #     #
#    #####  #     # #    #   #####
#   #       #     # ####### #     #
#   #        #   #       #  #     #
#   #######   ###        #   #####
#
#
#
# Board Size: Default = 4
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library(ggplot2)
N &amp;lt;- 4L

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Collapse a vector in the style of 2048
#
# Collapse vector by removing zeros, then summing pairs of adjacent values
#
# Result is padded with zeros to length of input
#
# @param x vector of integers
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
collapse_vec &amp;lt;- function(x) {
  new  &amp;lt;- x[x &amp;gt; 0]

  i &amp;lt;- 1L
  while (i &amp;lt; length(new)) {
    if (new[i] == new[i + 1L]) {
      new[i] &amp;lt;- new[i] * 2L
      new    &amp;lt;- new[-(i + 1L)]
    }

    i &amp;lt;- i + 1L
  }

  c(new, integer(N - length(new)))
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise game board
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
m       &amp;lt;- matrix(0L, N, N)
init    &amp;lt;- sample(N*N, 2)
m[init] &amp;lt;- 2L
m_prior &amp;lt;- m


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot game board
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_m &amp;lt;- function(m) {
  grid &amp;lt;- expand.grid(1:N, 1:N)
  idx  &amp;lt;- arrayInd(which(m &amp;gt; 0), .dim = c(N, N))
  df   &amp;lt;- cbind(as.data.frame(idx), V3 = factor(m[m &amp;gt; 0], levels = 2^(1:11)))
  ggplot(df, aes(V2, N + 1L - V1)) +
    geom_tile(data = grid, aes(Var1, Var2), fill = &amp;#39;grey90&amp;#39;, width = 0.9, height = 0.9) +
    geom_tile(aes(fill = V3), width = 0.9, height = 0.9) +
    geom_text(aes(label = V3), colour = &amp;#39;white&amp;#39;, size = 10) +
    theme_void() +
    xlim(0, N+1L) + ylim(0, N+1L) +
    coord_equal() +
    theme(legend.position = &amp;#39;none&amp;#39;) +
    scale_fill_viridis_d(option = &amp;#39;D&amp;#39;, drop = FALSE, end = 0.9)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Game loop
#    Use WASD to collapse the board in up/left/down/right directions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print(plot_m(m))

while (max(m) &amp;lt; 2048 &amp;amp;&amp;amp; any(m == 0)) {
  if (!identical(m, m_prior)) {
    # if the board has changed, then add a new &amp;#39;2&amp;#39; tile
    m[sample(which(m == 0), 1)] &amp;lt;- 2L

    print(m)
    print(plot_m(m))
  }

  m_prior &amp;lt;- m
  # cmd &amp;lt;- readline(prompt = &amp;quot;move?: &amp;quot;)
  m &amp;lt;- switch(
    readline(prompt = &amp;quot;move?: &amp;quot;),
    &amp;#39;q&amp;#39; = break,
    &amp;#39;w&amp;#39; = apply(m, 2, collapse_vec),                            # up
    &amp;#39;a&amp;#39; = t(apply(m, 1, collapse_vec)),                         # left
    &amp;#39;s&amp;#39; = apply(m[nrow(m):1,], 2, collapse_vec)[nrow(m):1,]   , # down
    &amp;#39;d&amp;#39; = t(apply(m[,nrow(m):1], 1, collapse_vec))[,nrow(m):1], # right
    m
  )
}

if (max(m) &amp;gt;= 2048) {
  message(&amp;quot;You won!&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;video controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/2048/2048-a.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Custom {ggplot2} point shapes with {gggrid}</title>
      <link>https://coolbutuseless.github.io/2021/11/04/custom-ggplot2-point-shapes-with-gggrid/</link>
      <pubDate>Thu, 04 Nov 2021 19:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/11/04/custom-ggplot2-point-shapes-with-gggrid/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(grid)
library(gggrid)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;use-grobs-as-points-in-ggplot-using-gggrid&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use grobs as points in &lt;code&gt;{ggplot}&lt;/code&gt; using &lt;code&gt;{gggrid}&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I highly recommend reading &lt;a href=&#34;https://www.stat.auckland.ac.nz/~paul/Reports/gggrid/gggrid.html&#34;&gt;Paul Murrel’s Report on {gggrid} and other techniques for getting grobs into ggplots&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# remotes::install_github(&amp;#39;https://github.com/pmur002/gggrid&amp;#39;)
library(grid)
library(gggrid)

hex &amp;lt;- FALSE
if (hex) {
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create the template grob - a hex!
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  r     &amp;lt;- 0.5
  theta &amp;lt;- seq(30, 360, 60) * pi/180
  x     &amp;lt;- r * cos(theta)
  y     &amp;lt;- r * sin(theta)
  g     &amp;lt;- grid::polygonGrob(x = x, y = y, vp = viewport(), gp = gpar())
} else {
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create the template grob - a 5 pointed star
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  r     &amp;lt;- 0.5
  theta &amp;lt;- seq(36, 360, 72) * pi/180
  x     &amp;lt;- r * cos(theta)
  y     &amp;lt;- r * sin(theta)
  g     &amp;lt;- grid::polygonGrob(x = x[c(1,3,5,2,4)], y = y[c(1,3,5,2,4)], vp = viewport(), gp = gpar())
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define the callback function to use within each panel.
# See https://www.stat.auckland.ac.nz/~paul/Reports/gggrid/gggrid.html
#
# @param data data.frame of original data
# @param coords data.frame of values scaled to fit into the desired output units
#               as well as any aesthetic values. 
#               One row per point.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
panel_func &amp;lt;- function(data, coords) {
  
  # Function which will be called for each row in &amp;#39;coords&amp;#39;
  position_grob &amp;lt;- function(point) {
    gnew           &amp;lt;- g
    gnew$gp$fill   &amp;lt;- point$fill
    gnew$gp$col    &amp;lt;- NA  #point$colour
    gnew$gp$alpha  &amp;lt;- point$alpha
    gnew$vp$x      &amp;lt;- unit(point[[&amp;#39;x&amp;#39;]], &amp;#39;npc&amp;#39;)
    gnew$vp$y      &amp;lt;- unit(point[[&amp;#39;y&amp;#39;]], &amp;#39;npc&amp;#39;)
    gnew$vp$width  &amp;lt;- unit(point[[&amp;#39;size&amp;#39;]]/4, &amp;#39;cm&amp;#39;)
    gnew$vp$height &amp;lt;- unit(point[[&amp;#39;size&amp;#39;]]/4, &amp;#39;cm&amp;#39;)
    gnew$name &amp;lt;- strftime(Sys.time(), &amp;quot;%H%M%OS6&amp;quot;) # Enforce unique name per grob. 
    gnew
  }
  
  # For each point, generate a grob
  grobs &amp;lt;- lapply(
    seq(nrow(coords)), 
    function(idx) {
      position_grob(coords[idx, ])
    })
  
  # group all the point grobs into a single grobTree object
  do.call(grid::grobTree, grobs)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot wih a `gggrid::grid_panel()`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(
  data = mtcars, 
  mapping = aes(
    x      = mpg, 
    y      = wt, 
    size   = cyl, 
    fill   = as.factor(cyl)
  )
) + 
  gggrid::grid_panel(panel_func) + 
  theme_bw() +
  labs(title = &amp;quot;{gggrid}: Custom ggplot points&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-11-04-gggrid_files/figure-html/gggrid-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {cssparser} - parse CSS into R lists and apply CSS to html within R</title>
      <link>https://coolbutuseless.github.io/2021/09/29/introducing-cssparser-parse-css-into-r-lists-and-apply-css-to-html-within-r/</link>
      <pubDate>Wed, 29 Sep 2021 21:40:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/29/introducing-cssparser-parse-css-into-r-lists-and-apply-css-to-html-within-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;cssparser&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;cssparser&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/cssparser/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/cssparser/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/cssparser/titlecard.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cssparser&lt;/code&gt; is a CSS parser (written in vanilla R) which can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parse CSS into R lists&lt;/li&gt;
&lt;li&gt;Combine CSS&lt;/li&gt;
&lt;li&gt;Apply CSS to determine final computed styles of elements in an HTML document&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read_css()&lt;/code&gt; read a cascading style sheet consisting of multiple selectors
into an R list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_inline_style()&lt;/code&gt; read a single inline style string into an R list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_apply()&lt;/code&gt; determine the calculated style for each element in an html document&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_apply_inline()&lt;/code&gt; add the calculated style an inline
&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag to every element in an HTML document&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_merge()&lt;/code&gt;, &lt;code&gt;style_merge()&lt;/code&gt; recursively merge multiple style sheets or styles&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_pretty_print()&lt;/code&gt;, &lt;code&gt;style_pretty_print()&lt;/code&gt; helpers to view the R list structures
in a way that may be more meaningful if you are comparing the information to
its original CSS form.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cssparser/articles/read-css.html&#34;&gt;Read CSS from file/string&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cssparser/articles/apply-css.html&#34;&gt;Apply CSS to an HTML document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cssparser/articles/css-merge.html&#34;&gt;Merge multiple CSS stylesheets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cssparser/articles/web-page-render-frames.html&#34;&gt;A toy HTML layout engine in R&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cssparser/articles/another-example.html&#34;&gt;Another &lt;code&gt;read_css()&lt;/code&gt; example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/cssparser&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cssparser&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Shorthand properties. There are many shorthand properties in CSS which
are compact representations of multiple other CSS properties. E.g.
&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/border&#34;&gt;&lt;code&gt;border&lt;/code&gt;&lt;/a&gt; is
is a way of combining &lt;code&gt;border-width&lt;/code&gt;, &lt;code&gt;border-style&lt;/code&gt; and &lt;code&gt;border-color&lt;/code&gt;
in a single property. These shorthand properties have particular
inheritance rules, and currently only the &lt;code&gt;font&lt;/code&gt; shorthand property is
the only one which is expanded and inhertied correctly.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;all&lt;/code&gt; selector is not implemented yet.&lt;/li&gt;
&lt;li&gt;The CSS values like &lt;code&gt;inherit&lt;/code&gt; and &lt;code&gt;unset&lt;/code&gt; are not yet handled.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;@&lt;/code&gt;-prefixed selectors (e.g. &lt;code&gt;@media&lt;/code&gt;) aren’t really handled well. They
exist in the parsed data, but have not been tested&lt;/li&gt;
&lt;li&gt;pseudo-elements and pseudo-classes do not take part in the cascading of styles&lt;/li&gt;
&lt;li&gt;there is no concept of page size, and it is expected that if you want to
calculate the final &lt;code&gt;width&lt;/code&gt; of any particular element, you’ll have to
do your own device-specific shenanigans.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-parse-css&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Parse CSS&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cssparser)

stylesheet &amp;lt;- &amp;#39;
#main {
  background-color: red !important;
  color: blue;
}

.footer {
  border-color: rgb(50 100 255);
  font-weight: lighter;
  margin-left: 1cm;
}

.footer &amp;gt; p {
  background-color: green;
}
&amp;#39;

css &amp;lt;- cssparser::read_css(stylesheet)
css&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; $`#main`
#&amp;gt; $`#main`$`background-color`
#&amp;gt; [1] &amp;quot;red&amp;quot;
#&amp;gt; attr(,&amp;quot;important&amp;quot;)
#&amp;gt; [1] TRUE
#&amp;gt; 
#&amp;gt; $`#main`$color
#&amp;gt; [1] &amp;quot;blue&amp;quot;
#&amp;gt; 
#&amp;gt; 
#&amp;gt; $.footer
#&amp;gt; $.footer$`border-color`
#&amp;gt; [1] &amp;quot;rgb(50 100 255)&amp;quot;
#&amp;gt; 
#&amp;gt; $.footer$`font-weight`
#&amp;gt; [1] &amp;quot;lighter&amp;quot;
#&amp;gt; 
#&amp;gt; $.footer$`margin-left`
#&amp;gt; [1] &amp;quot;1cm&amp;quot;
#&amp;gt; 
#&amp;gt; 
#&amp;gt; $`.footer &amp;gt; p`
#&amp;gt; $`.footer &amp;gt; p`$`background-color`
#&amp;gt; [1] &amp;quot;green&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cssparser::css_pretty_print(css)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; #main {
#&amp;gt;   background-color: red !important;
#&amp;gt;   color: blue;
#&amp;gt; }
#&amp;gt; 
#&amp;gt; .footer {
#&amp;gt;   border-color: rgb(50 100 255);
#&amp;gt;   font-weight: lighter;
#&amp;gt;   margin-left: 1cm;
#&amp;gt; }
#&amp;gt; 
#&amp;gt; .footer &amp;gt; p {
#&amp;gt;   background-color: green;
#&amp;gt; }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-extract-values-from-css-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Extract values from CSS in R&lt;/h2&gt;
&lt;p&gt;The object returned by &lt;code&gt;read_css()&lt;/code&gt; is a nested list of name/value pairs.&lt;/p&gt;
&lt;p&gt;The top-level name is the CSS Selector (e.g. &lt;code&gt;#main&lt;/code&gt;). The value it points
to is another named list - property/value pairs e.g. &lt;code&gt;color = blue&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To extract a single style from the CSS object, just subset it as you would
for any R list&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;css[[&amp;#39;.footer&amp;#39;]][[&amp;#39;font-weight&amp;#39;]]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;lighter&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;css[[&amp;#39;#main&amp;#39;]][[&amp;#39;background-color&amp;#39;]]  # Note the &amp;#39;important&amp;#39; attribute on this CSS declaration&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;red&amp;quot;
#&amp;gt; attr(,&amp;quot;important&amp;quot;)
#&amp;gt; [1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-extractconvert-values&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Extract/Convert values&lt;/h2&gt;
&lt;p&gt;Some tools are included for extracting parsing CSS values into R values e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;css_colour_to_hex()&lt;/code&gt; will convert &lt;code&gt;rgb()&lt;/code&gt; and &lt;code&gt;hsl()&lt;/code&gt; strings to R colours.
As well as CSS colour names and 3 letter hex colours (e.g. &lt;code&gt;#fab&lt;/code&gt; -&amp;gt; &lt;code&gt;#ffaabb&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_string_as_pixels()&lt;/code&gt; has a (naive) go at converting length values to
a number of pixels (assuming 96dpi display). This is a wrapper around two
other functions:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;css_string_as_css_length()&lt;/code&gt; to convert a string to a numeric value,
and include the &lt;code&gt;unit&lt;/code&gt; as an attribute.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;css_length_as_pixels()&lt;/code&gt; to convert a value with a &lt;code&gt;unit&lt;/code&gt; attribute to
a length in pixels&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colour &amp;lt;- css[[&amp;#39;.footer&amp;#39;]][[&amp;#39;border-color&amp;#39;]]
colour&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;rgb(50 100 255)&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cssparser::css_colour_to_hex( colour )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;#3264FFFF&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;value &amp;lt;- css[[&amp;#39;.footer&amp;#39;]][[&amp;#39;margin-left&amp;#39;]]
value&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;1cm&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cssparser::css_string_as_css_length(value)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 1
#&amp;gt; attr(,&amp;quot;unit&amp;quot;)
#&amp;gt; [1] &amp;quot;cm&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cssparser::css_string_as_pixels(value)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 37.79528&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-apply-css-to-html&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Apply CSS to html&lt;/h2&gt;
&lt;p&gt;Given &lt;code&gt;css&lt;/code&gt; and an &lt;code&gt;html/xml&lt;/code&gt; document, &lt;code&gt;cssparser&lt;/code&gt; can produce a named list
containing the computed style for every element.&lt;/p&gt;
&lt;p&gt;The names in this list are the &lt;code&gt;xpaths&lt;/code&gt; for each element, and the values
are the named list of property/value declarations on this element.&lt;/p&gt;
&lt;p&gt;The calculation of the style for each element takes into account:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;tag&amp;gt;&lt;/code&gt;, &lt;code&gt;#id&lt;/code&gt; and &lt;code&gt;.class&lt;/code&gt; selectors&lt;/li&gt;
&lt;li&gt;selector combinators like &lt;code&gt;#main &amp;gt; div&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CSS inheritance from parent elements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the &lt;code&gt;computed_styles&lt;/code&gt; for the following HTML document, note the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; (with &lt;code&gt;id=&#34;main&#34;&lt;/code&gt;) has &lt;code&gt;xpath = &#34;/html/body/div[1]&#34;&lt;/code&gt; has
a &lt;code&gt;background-color&lt;/code&gt; of &lt;code&gt;red&lt;/code&gt; as the &lt;code&gt;!important&lt;/code&gt; flag was set in the
stylesheet and this overrides the inline style &lt;code&gt;background-color: yellow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The CSS selector &lt;code&gt;.footer &amp;gt; p&lt;/code&gt; has correctly applied &lt;code&gt;background-color = &#34;green&#34;&lt;/code&gt; to
only the second &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; in the document (with &lt;code&gt;xpath = &#34;/html/body/div[2]/p&#34;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;border&lt;/code&gt;-related properties on the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements are not evident on the
child &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements as border properties are not inherited.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;html &amp;lt;- xml2::read_html(&amp;#39;
&amp;lt;html&amp;gt;
&amp;lt;div id=&amp;quot;main&amp;quot; class=&amp;quot;thin&amp;quot; style=&amp;quot;border: 2px; background-color: yellow;&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;Lorem Ipsum&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div class=&amp;quot;footer&amp;quot;&amp;gt;
  &amp;lt;p&amp;gt;Goodbye&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;/html&amp;gt;&amp;#39;)


computed_styles &amp;lt;- cssparser::css_apply(html, css)
cssparser::css_pretty_print(computed_styles)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; /html/body/div[2] {
#&amp;gt;   border-color: rgb(50 100 255);
#&amp;gt;   font-weight: lighter;
#&amp;gt;   margin-left: 1cm;
#&amp;gt; }
#&amp;gt; 
#&amp;gt; /html/body/div[2]/p {
#&amp;gt;   font-weight: lighter;
#&amp;gt;   background-color: green;
#&amp;gt; }
#&amp;gt; 
#&amp;gt; /html/body/div[1] {
#&amp;gt;   background-color: red !important;
#&amp;gt;   color: blue;
#&amp;gt;   border: 2px;
#&amp;gt; }
#&amp;gt; 
#&amp;gt; /html {
#&amp;gt; }
#&amp;gt; 
#&amp;gt; /html/body {
#&amp;gt; }
#&amp;gt; 
#&amp;gt; /html/body/div[1]/p {
#&amp;gt;   color: blue;
#&amp;gt; }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-manually-merging-css-styles&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Manually merging CSS styles&lt;/h2&gt;
&lt;p&gt;The following code shows a manual way of combining styles from a number of
different sources using &lt;code&gt;style_merge()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# StyleSheet
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stylesheet &amp;lt;- &amp;#39;
#greg {
  fill: red !important;
  color: blue;
}

.thin {
  border: 1px;
  border-color: hsl(30 50% 40%);
  font-weight: lighter;
}&amp;#39;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example HTML
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
html &amp;lt;- xml2::read_html(&amp;#39;
&amp;lt;div id=&amp;quot;greg&amp;quot; class=&amp;quot;thin&amp;quot; style=&amp;quot;border: 2px; fill: yellow;&amp;quot;&amp;gt;
  Lorem Ipsum
&amp;lt;/div&amp;gt;&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert stylesheet into rulesets (i.e. R lists indexed by selector)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
css &amp;lt;- read_css(stylesheet)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manually calculate style for this element by merging the various styles
# which apply to this element based upon the CSS selectors
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
greg_final &amp;lt;- style_merge(
  css[[&amp;#39;div&amp;#39;]],
  css[[&amp;quot;.thin&amp;quot;]],
  css[[&amp;#39;#greg&amp;#39;]], 
  read_inline_style(&amp;quot;border: 2px; fill: yellow;&amp;quot;)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note: &amp;quot;!important&amp;quot; property carried through.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cssparser::style_pretty_print(greg_final)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; border: 2px;
#&amp;gt; border-color: hsl(30 50% 40%);
#&amp;gt; font-weight: lighter;
#&amp;gt; fill: red !important;
#&amp;gt; color: blue;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cssparser::css_colour_to_hex(greg_final$`border-color`)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;#996633FF&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hackers-painters/katana-parser&#34;&gt;katana&lt;/a&gt; C library for parsing CSS
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hrbrmstr/tsuka&#34;&gt;{tsuka}&lt;/a&gt; a wrapper around katana for R&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {gozer} add destruction artefacts to R objects</title>
      <link>https://coolbutuseless.github.io/2021/09/28/introducing-gozer-add-destruction-artefacts-to-r-objects/</link>
      <pubDate>Tue, 28 Sep 2021 23:10:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/28/introducing-gozer-add-destruction-artefacts-to-r-objects/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;gozer---choose-the-form-of-the-destructor&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;gozer - choose the form of the destructor &lt;img src=&#34;https://coolbutuseless.github.io/img/gozer/logo.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gozer&lt;/code&gt; allows you to attach a ‘destructor’ artefact (either a string or a function)
to an R object.&lt;/p&gt;
&lt;p&gt;When the R object is destroyed (i.e. garbage collected) the ‘destructor’ artefact
is printed or called.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gozer()&lt;/code&gt; to attach a destructor artefact to an object.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/gozer&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/gozer&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;printing-a-string-as-a-destructor-artefact.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Printing a string as a ‘destructor’ artefact.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(gozer)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define an object and add a string destruction artefact
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a &amp;lt;- &amp;#39;hello&amp;#39;
a &amp;lt;- gozer(a, &amp;quot;I was garbage collected! Goodbye ...&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Destructor is added as object attribute as a NULL external pointer on t
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;hello&amp;quot;
#&amp;gt; attr(,&amp;quot;destructor&amp;quot;)
#&amp;gt; &amp;lt;pointer: 0x0&amp;gt;
#&amp;gt; attr(,&amp;quot;class&amp;quot;)
#&amp;gt; [1] &amp;quot;gozer&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Destroy the object and get the destruction artefact
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rm(a)
invisible(gc())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; I was garbage collected! Goodbye ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;calling-a-function-as-a-destructor-artefact.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Calling a function as a ‘destructor’ artefact.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(gozer)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Funciton to call when object is destroyed. 
# Argument will be an external pointer object which is unusable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ff &amp;lt;- function(ext_ptr) {
  print(&amp;quot;There was definitely a garbage collection event&amp;quot;)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define an object and add a function as a destruction artefact
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a &amp;lt;- &amp;#39;hello&amp;#39;
a &amp;lt;- gozer(a, ff)
a&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;hello&amp;quot;
#&amp;gt; attr(,&amp;quot;destructor&amp;quot;)
#&amp;gt; &amp;lt;pointer: 0x0&amp;gt;
#&amp;gt; attr(,&amp;quot;class&amp;quot;)
#&amp;gt; [1] &amp;quot;gozer&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Destroy the object and get the destruction artefact
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rm(a)
invisible(gc())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;There was definitely a garbage collection event&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base::reg.finalizer()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Only works on environments and external pointers&lt;/li&gt;
&lt;li&gt;Object is still active at the time of finalization and is the expected
argument to the finalizer function.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;R6 ‘finalize’ method&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;gozer-the-gozerian&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Gozer the Gozerian&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/gozer/gozer.jpg&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>New {flexo} vignette - parsing subtitles in srt format</title>
      <link>https://coolbutuseless.github.io/2021/09/16/new-flexo-vignette-parsing-subtitles-in-srt-format/</link>
      <pubDate>Thu, 16 Sep 2021 23:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/16/new-flexo-vignette-parsing-subtitles-in-srt-format/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(flexo)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;flexo-simple-lexparse-tools-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;flexo&lt;/code&gt;: Simple Lex/Parse Tools in R &lt;img src=&#34;https://coolbutuseless.github.io/img/flexo/logo.png&#34; align=&#34;right&#34; height=300 /&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/coolbutuseless/flexo&#34;&gt;{flexo}&lt;/a&gt; is a small package containing a
lexer (for splitting text into tokens).&lt;/p&gt;
&lt;p&gt;The v0.2.6 update of &lt;code&gt;flexo&lt;/code&gt; added support for &lt;code&gt;stringi&lt;/code&gt; regex options like &lt;code&gt;multiline&lt;/code&gt; support,
and this vignette is a quick test of this new functionality.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;parsing-subtitles-in-srt-format-with-flexo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Parsing subtitles in srt format with flexo&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.speechpad.com/captions/srt&#34;&gt;srt&lt;/a&gt; subtitle format is a
simple representation of subtitles for video which consists of timestamped
lines of text.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;srt-format-example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;SRT format example&lt;/h1&gt;
&lt;p&gt;The first 10 lines of dialogue from “It’s a Wonderful Life” in &lt;code&gt;srt&lt;/code&gt; format&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;srt &amp;lt;- &amp;quot;
1
00:01:25,210 --&amp;gt; 00:01:28,004
I owe everything to George Bailey.

2
00:01:28,422 --&amp;gt; 00:01:30,298
Help him, dear Father.

3
00:01:30,674 --&amp;gt; 00:01:33,718
Joseph, Jesus and Mary,

4
00:01:33,802 --&amp;gt; 00:01:36,429
help my friend Mr. Bailey.

5
00:01:36,889 --&amp;gt; 00:01:39,515
Help my son George tonight.

6
00:01:40,350 --&amp;gt; 00:01:42,226
He never thinks about himself, God.

7
00:01:42,311 --&amp;gt; 00:01:44,061
That&amp;#39;s why he&amp;#39;s in trouble.

8
00:01:44,146 --&amp;gt; 00:01:45,313
George is a good guy.

9
00:01:46,482 --&amp;gt; 00:01:47,732
Give him a break, God.

10
00:01:47,816 --&amp;gt; 00:01:49,942
I love him, dear Lord.
&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;lex-the-srt-file-into-tokens&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Lex the srt file into tokens&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define the regex for each token
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
srt_regexes &amp;lt;- c(
  time  = &amp;quot;\\d+:\\d+:\\d+,\\d+&amp;quot;,
  link  = &amp;quot;\\s*--&amp;gt;\\s*&amp;quot;,
  index = &amp;quot;^\\d+$&amp;quot;,
  text  = &amp;quot;^.+?$&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Collapse the file into a single string
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
srt &amp;lt;- paste(enc2utf8(srt), collapse = &amp;quot;\n&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Split the file by regex, and drop the &amp;#39;link&amp;#39; between times
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tokens &amp;lt;- lex(srt, multiline = TRUE, srt_regexes)
tokens &amp;lt;- tokens[names(tokens) != &amp;#39;link&amp;#39;]

tokens&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;1&amp;quot;                        &amp;quot;00:01:25,210&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:28,004&amp;quot;  &amp;quot;I owe everything to George Bailey.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;2&amp;quot;                        &amp;quot;00:01:28,422&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:30,298&amp;quot;              &amp;quot;Help him, dear Father.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;3&amp;quot;                        &amp;quot;00:01:30,674&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:33,718&amp;quot;             &amp;quot;Joseph, Jesus and Mary,&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;4&amp;quot;                        &amp;quot;00:01:33,802&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:36,429&amp;quot;          &amp;quot;help my friend Mr. Bailey.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;5&amp;quot;                        &amp;quot;00:01:36,889&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:39,515&amp;quot;         &amp;quot;Help my son George tonight.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;6&amp;quot;                        &amp;quot;00:01:40,350&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:42,226&amp;quot; &amp;quot;He never thinks about himself, God.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;7&amp;quot;                        &amp;quot;00:01:42,311&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:44,061&amp;quot;         &amp;quot;That&amp;#39;s why he&amp;#39;s in trouble.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;8&amp;quot;                        &amp;quot;00:01:44,146&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:45,313&amp;quot;               &amp;quot;George is a good guy.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                   &amp;quot;9&amp;quot;                        &amp;quot;00:01:46,482&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:47,732&amp;quot;              &amp;quot;Give him a break, God.&amp;quot; 
#&amp;gt;                                 index                                  time 
#&amp;gt;                                  &amp;quot;10&amp;quot;                        &amp;quot;00:01:47,816&amp;quot; 
#&amp;gt;                                  time                                  text 
#&amp;gt;                        &amp;quot;00:01:49,942&amp;quot;              &amp;quot;I love him, dear Lord.&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;parse-raw-tokens-into-a-data.frame&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Parse raw tokens into a data.frame&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Merge together runs of text
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rl    &amp;lt;- unclass(rle(names(tokens)))
end   &amp;lt;- cumsum(rl$lengths)[rl$values == &amp;#39;text&amp;#39;]
len   &amp;lt;- rl$lengths[rl$values == &amp;#39;text&amp;#39;]
start &amp;lt;- end - len + 1

text &amp;lt;- mapply(function(start, end) {
  paste(tokens[start:end], collapse = &amp;quot;\n&amp;quot;)
}, start, end)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Extract index and time vectors
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
indices &amp;lt;- as.integer(tokens[names(tokens) == &amp;#39;index&amp;#39;])
times   &amp;lt;- tokens[names(tokens) == &amp;#39;time&amp;#39;]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Munge into data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
data.frame(
  index  = indices,
  start  = times[c(T, F)],
  end    = times[c(F, T)],
  text   = text,
  stringsAsFactors = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;    index        start          end                                text
#&amp;gt; 1      1 00:01:25,210 00:01:28,004  I owe everything to George Bailey.
#&amp;gt; 2      2 00:01:28,422 00:01:30,298              Help him, dear Father.
#&amp;gt; 3      3 00:01:30,674 00:01:33,718             Joseph, Jesus and Mary,
#&amp;gt; 4      4 00:01:33,802 00:01:36,429          help my friend Mr. Bailey.
#&amp;gt; 5      5 00:01:36,889 00:01:39,515         Help my son George tonight.
#&amp;gt; 6      6 00:01:40,350 00:01:42,226 He never thinks about himself, God.
#&amp;gt; 7      7 00:01:42,311 00:01:44,061         That&amp;#39;s why he&amp;#39;s in trouble.
#&amp;gt; 8      8 00:01:44,146 00:01:45,313               George is a good guy.
#&amp;gt; 9      9 00:01:46,482 00:01:47,732              Give him a break, God.
#&amp;gt; 10    10 00:01:47,816 00:01:49,942              I love him, dear Lord.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {priorityqueue} - two simple priority queues. One written in R, the other in C</title>
      <link>https://coolbutuseless.github.io/2021/09/14/introducing-priorityqueue-two-simple-priority-queues.-one-written-in-r-the-other-in-c/</link>
      <pubDate>Tue, 14 Sep 2021 20:13:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/14/introducing-priorityqueue-two-simple-priority-queues.-one-written-in-r-the-other-in-c/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;priorityqueue&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;priorityqueue&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/priorityqueue/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/priorityqueue/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;priorityqueue&lt;/code&gt; is a package with two
&lt;a href=&#34;https://en.wikipedia.org/wiki/Priority_queue&#34;&gt;priority queue&lt;/a&gt; implementations for R:
one written in C, and the other written in plain R.&lt;/p&gt;
&lt;p&gt;Both of these are &lt;em&gt;max-priority-queues&lt;/em&gt; i.e.
“popping” from the queue returns the value with highest priority.&lt;/p&gt;
&lt;p&gt;These priority queues support any R object. The priority can be any finite &lt;code&gt;double()&lt;/code&gt; value.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;p&gt;Two priority queue implementations with identical call APIs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pure R priority queue:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rpq_create()&lt;/code&gt;, &lt;code&gt;rpq_insert(rpq, obj, priority)&lt;/code&gt;, &lt;code&gt;rpq_pop(rpq)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;C-based priority queue:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cpq_create()&lt;/code&gt;, &lt;code&gt;cpq_insert(cpq, obj, priority)&lt;/code&gt;, &lt;code&gt;cpq_pop(cpq)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/priorityqueue&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/priorityqueue&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Priority queues are a data-structure to store objects along with a priority with each object.&lt;/p&gt;
&lt;p&gt;When &lt;em&gt;popping&lt;/em&gt; a value off the queue, the object with the largest priority is
returned.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(priorityqueue)

rpq &amp;lt;- rpq_create()
rpq_is_empty(rpq)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rpq_insert(rpq, obj = &amp;quot;#RStats&amp;quot;, priority = 2)
rpq_insert(rpq, obj = &amp;quot;hello&amp;quot;  , priority = 3)
rpq_insert(rpq, obj = 2 * 2    , priority = 1)

rpq_length(rpq)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Retrieve the objects from largest priority to smallest
rpq_pop(rpq)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;hello&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rpq_pop(rpq)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;#RStats&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rpq_pop(rpq)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rationale&lt;/h2&gt;
&lt;p&gt;I needed a data structure in R which would allow me to insert/pop items based upon
a &lt;em&gt;priority&lt;/em&gt; value - what is known as a &lt;em&gt;priority queue&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I wrote a quick solution in R that met my basic needs i.e. an environment
containing a list of objects and a vector of values, plus some standard functions
to manipulate. This code is the basis of the &lt;code&gt;rpq_*&lt;/code&gt; functions in this package.&lt;/p&gt;
&lt;p&gt;I then wondered how this could be done with C, and as a learning exercise I
wrote a minimal priority queue in C which supported R objects. This was tidied
to be the C prioirty queue (&lt;code&gt;cpq_*&lt;/code&gt;) in this package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;timing&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Timing&lt;/h2&gt;
&lt;p&gt;In general the C implementation is faster and uses less memory than the R
implementation (no surprises there).&lt;/p&gt;
&lt;p&gt;For larger queues, the C implementation can be ~10x faster and use 1/30th the memory.&lt;/p&gt;
&lt;p&gt;This implementation of a priority queue compares favourably with the priority queue
included in the &lt;a href=&#34;https://cran.r-project.org/package=collections&#34;&gt;{collections}&lt;/a&gt; package
on CRAN.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Click to show/hide the timing code
&lt;/summary&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r_priority_queue &amp;lt;- function(N) {
  set.seed(1)
  rpq &amp;lt;- rpq_create()
  
  for (i in 1:(N*2)) {
    rpq_insert(rpq, 1, runif(1))
    rpq_insert(rpq, 1, runif(1))
  }
  
  for (i in 1:N) {
    rpq_insert(rpq, 1, runif(1))
    rpq_insert(rpq, 1, runif(1))
    rpq_pop(rpq)
    rpq_pop(rpq)
    rpq_pop(rpq)
  }
}


cpq_priority_queue &amp;lt;- function(N) {
  set.seed(1)
  cpq &amp;lt;- cpq_create()
  
  for (i in 1:(N*2)) {
    cpq_insert(cpq, 1, runif(1))
    cpq_insert(cpq, 1, runif(1))
  }
  
  for (i in 1:N) {
    cpq_insert(cpq, 1, runif(1))
    cpq_insert(cpq, 1, runif(1))
    cpq_pop(cpq)
    cpq_pop(cpq)
    cpq_pop(cpq)
  }
}



collections_priority_queue &amp;lt;- function(N) {
  set.seed(1)
  colq &amp;lt;- collections::priority_queue()
  
  for (i in 1:(N*2)) {
    colq$push(1, runif(1))
    colq$push(1, runif(1))
  }
  
  for (i in 1:N) {
    colq$push(1, runif(1))
    colq$push(1, runif(1))
    colq$pop()
    colq$pop()
    colq$pop()
  }
}


res &amp;lt;- bench::press(
  N = c(10, 100, 1000),
  bench::mark(
    `Plain R priority queue` = r_priority_queue(N), 
    `C priority queue` = cpq_priority_queue(N),
    `collections::priority_queue()` = collections_priority_queue(N)
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; Warning: Some expressions had a GC in every iteration; so filtering is disabled.&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Plain R priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;774.412196&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;408.02KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;C priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3443.282577&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;226.52KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;collections::priority_queue()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3271.967561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;278.96KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Plain R priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;61.281542&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.94MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;C priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;370.743903&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.48MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;collections::priority_queue()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;317.896057&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.47MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Plain R priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.463592&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;645.93MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;C priority queue&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36.510057&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.73MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;collections::priority_queue()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.865650&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.71MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-09-14-priorityqueue_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical Bits&lt;/h2&gt;
&lt;p&gt;Plain R priority queue&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implemented as an environment with storage for a list of objects and a vector of priorities.&lt;/li&gt;
&lt;li&gt;New objects and their priorities are appended to the list/vector in the environment.&lt;/li&gt;
&lt;li&gt;When a value is &lt;em&gt;popped&lt;/em&gt;, the maximum priority is found (using &lt;code&gt;whichmax()&lt;/code&gt;) and
the matching object is returned&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C priority queue&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A heap-based priority queue.&lt;/li&gt;
&lt;li&gt;Creating a &lt;code&gt;cpq&lt;/code&gt; creates an ExternalPointer to a &lt;code&gt;cpq_t&lt;/code&gt; object which contains
the queue and other information all entirely within C.&lt;/li&gt;
&lt;li&gt;An R list is attached to this ExternalPointer in C (as a &lt;em&gt;protected&lt;/em&gt; item on the pointer).
When new R objects are
added to the priority queue, they are also added to this list to prevent
them from being garbage collected.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=collections&#34;&gt;{collections}&lt;/a&gt; package
already includes a very good priority queue and bunch of other useful stuff.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {typhoid} uint16, fixedpt &amp; numberwang implemented in vctrs</title>
      <link>https://coolbutuseless.github.io/2021/09/09/introducing-typhoid-uint16-fixedpt-numberwang-implemented-in-vctrs/</link>
      <pubDate>Thu, 09 Sep 2021 19:57:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/09/introducing-typhoid-uint16-fixedpt-numberwang-implemented-in-vctrs/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;typhoid---non-standard-numeric-datatypes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;typhoid - non-standard numeric datatypes&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/typhoid/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/typhoid/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;typhoid&lt;/code&gt; provides implementations of some non-standard datatypes using &lt;code&gt;{vctrs}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/typhoid/overview.png&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;numberwang(x)&lt;/code&gt; for creating numeric values which present themselves as words.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uint16(x)&lt;/code&gt; for creating 16-bit unsigned integers, where each value is
stored as a pair of raw bytes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fixedpt(x, decimals = 3)&lt;/code&gt; for creating 32-bit fixed point numeric values.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of the types supports &lt;code&gt;as_&amp;lt;type&amp;gt;()&lt;/code&gt; and &lt;code&gt;is_&amp;lt;type&amp;gt;()&lt;/code&gt;, as well as standard
arithmetic operations (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt; etc) and mathematical functions e.g. &lt;code&gt;abs()&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;These types were created in order to explore the
&lt;a href=&#34;https://vctrs.r-lib.org/index.html&#34;&gt;&lt;code&gt;{vctrs}&lt;/code&gt; package&lt;/a&gt;, and its capabilities
for easily creating new types, with minimal effort, along with broad support
for standard R features.&lt;/p&gt;
&lt;p&gt;These are all pretty naive implementations with ill-defined overflow, and
incomplete implementations.&lt;/p&gt;
&lt;p&gt;They &lt;em&gt;could&lt;/em&gt; be the core of properly useful, robust datatypes - but for now
they merely stand as small tutorials on how new types can be defined with
the &lt;code&gt;{vctrs}&lt;/code&gt; package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/typhoid&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/numberwang&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/typhoid&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/typhoid/overview-numberwang.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;numberwang&lt;/strong&gt; type is backed by the &lt;a href=&#34;https://github.com/coolbutuseless/numberwang&#34;&gt;&lt;code&gt;{numberwang}&lt;/code&gt;&lt;/a&gt; package which provides
functions for converting from numbers to words, and vice versa.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;num &amp;lt;- numberwang(42.123)
num&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  &amp;lt;typ_numberwang[1]&amp;gt;
  [1] &amp;quot;forty-two point one two three&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;num + 5&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  &amp;lt;typ_numberwang[1]&amp;gt;
  [1] &amp;quot;forty-seven point one two three&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;numberwang(1:3) * 10&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  &amp;lt;typ_numberwang[3]&amp;gt;
  [1] &amp;quot;ten&amp;quot;    &amp;quot;twenty&amp;quot; &amp;quot;thirty&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;numberwang(1:3) * as_numberwang(&amp;quot;twenty seven&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  &amp;lt;typ_numberwang[3]&amp;gt;
  [1] &amp;quot;twenty-seven&amp;quot; &amp;quot;fifty-four&amp;quot;   &amp;quot;eighty-one&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/typhoid/overview-uint16.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uint16&lt;/code&gt; values are represented internally as a pair of bytes.&lt;/p&gt;
&lt;p&gt;Since a &lt;code&gt;uint16&lt;/code&gt; takes up only 16bits, it can only hold integers in the range 0-65535.&lt;/p&gt;
&lt;p&gt;This offers space savings compared with R’s standard integer (four bytes), as long
as your numbers fit in the given range.&lt;/p&gt;
&lt;p&gt;Arithmetic operations are performed modulo 65536.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# uint16 doesn&amp;#39;t really behave differently from a small integer
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uint16(42)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; &amp;lt;typ_uint16[1]&amp;gt;
#&amp;gt; [1] 42&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;uint16(c(100, 150)) * 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; &amp;lt;typ_uint16[2]&amp;gt;
#&amp;gt; [1] 200 300&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# uint16 uses only half the memory of a regular integer, but has
# a much reduced range as well
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ints &amp;lt;- sample(65535)
lobstr::obj_size(ints)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 262,192 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(uint16(ints))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 131,904 B&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/typhoid/overview-fixedpt.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Fixed point numbers are implemented as integer values and a divisor which is a
power of 10. For instance &lt;code&gt;12.34&lt;/code&gt; is represented as the integer &lt;code&gt;1234&lt;/code&gt; with a
divisor of 100.&lt;/p&gt;
&lt;p&gt;Fixed point numbers show as many decimal places as
set during initialisation with the &lt;code&gt;fixedpt(x, decimals = 3)&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;When numeric operations are performed on a &lt;code&gt;fixedpt&lt;/code&gt;, the result is also a
fixed point, with the number of decimals set to the be the maximum of decimal
places of the two arguments.&lt;/p&gt;
&lt;p&gt;Numbers are only representable as a &lt;code&gt;fixedpt&lt;/code&gt; if the unscaled number fits into
a normal R integer.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;n1 &amp;lt;- fixedpt(1:5, decimals = 3)
n1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; &amp;lt;typ_fixedpt[5]&amp;gt;
#&amp;gt; [1] 1.000 2.000 3.000 4.000 5.000&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;n2 &amp;lt;- fixedpt(101:105, decimals = 5)
n2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; &amp;lt;typ_fixedpt[5]&amp;gt;
#&amp;gt; [1] 101.00000 102.00000 103.00000 104.00000 105.00000&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;n1 * n2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; &amp;lt;typ_fixedpt[5]&amp;gt;
#&amp;gt; [1] 101.00000 204.00000 309.00000 416.00000 525.00000&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>{smallfactor} update - store factors in bytes and bits rather than integers</title>
      <link>https://coolbutuseless.github.io/2021/09/06/smallfactor-update-store-factors-in-bytes-and-bits-rather-than-integers/</link>
      <pubDate>Mon, 06 Sep 2021 19:30:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/09/06/smallfactor-update-store-factors-in-bytes-and-bits-rather-than-integers/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;smallfactor---store-factors-in-bytes-and-bits-rather-than-an-integer&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;smallfactor - store factors in bytes and bits rather than an &lt;code&gt;integer&lt;/code&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/smallfactor/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/smallfactor/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;smallfactor&lt;/code&gt; is an experiment to see what trade-offs there might be for storing
a factor in bytes or bits instead of an integer.&lt;/p&gt;
&lt;p&gt;An R integer is 4-bytes, meaning it could hold a factor with two billion levels,
which seems like overkill.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bytefactor&lt;/code&gt; targets factors with up to 256 levels.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bitfactor&lt;/code&gt; will choose the fewest bits to store a factor for factors with 2 up to
32768 (2^15) levels.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bytefactor()&lt;/code&gt; store factor values in raw bytes rather than an integer.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bitfactor()&lt;/code&gt; store factor values as bits within integers - with multiple factors
stored in a single integer value.
E.g. a factor with 4 levels could be stored as just 2 bits of information,
meaning 16 values could be stored in a single R integer (16 * 2 bits = 32 bits = 4 bytes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;It seems possible that you could write more methods to make these smaller factors
behave similar to regular R &lt;code&gt;factor&lt;/code&gt; objects, but this package is not attempting
this (yet).&lt;/p&gt;
&lt;p&gt;Internally, there’s currently a lot of transferring back-and-forth between
these small factors and the standard R factor in order to make use of
the printing and subsetting capabilities of the R factor implementation. Much
of this back-and-forth could be avoided if effort was expended to do so.&lt;/p&gt;
&lt;p&gt;Note: &lt;code&gt;bitfactor&lt;/code&gt; uses only 31 bits of a 32-bit integer in order to avoid
issues around &lt;code&gt;NA_integer_&lt;/code&gt; representation. This means, for example, that an
integer can only hold 15 x 2-bit values. In practice the user is never
expected to notice this or care about it.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/smallfactor&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/smallfactor&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;bytefactor&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;bytefactor&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;small &amp;lt;- bytefactor(c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;d&amp;#39;))
small&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bytefactor]
#&amp;gt; [1] a b c a d
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;small[1:3]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bytefactor]
#&amp;gt; [1] a b c
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;bitfactor&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;bitfactor&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;bitfactor()&lt;/code&gt; will choose an appropriate number of bits to store the given
number of levels.&lt;/p&gt;
&lt;p&gt;In the following example, there are 4 levels, so &lt;code&gt;bitfactor()&lt;/code&gt; chooses to
store each value in the factor in 2 bits.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiny &amp;lt;- bitfactor(c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;d&amp;#39;))
tiny&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bitfactor] 5 values @ ~2 bits/value = 1 integer(s)
#&amp;gt; [1] a b c a d
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiny[1:3]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bitfactor] 3 values @ ~2 bits/value = 1 integer(s)
#&amp;gt; [1] a b c
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this next example, there are 100 levels in the factor, so 7 bits are
needed to fully store all the levels&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiny &amp;lt;- bitfactor(sample(100, 10), levels=1:100)
tiny&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bitfactor] 10 values @ ~7 bits/value = 3 integer(s)
#&amp;gt;  [1] 24 77 87 57 33 21 18 2  11 62
#&amp;gt; 100 Levels: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 100&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tiny[4:6]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [bitfactor] 3 values @ ~7 bits/value = 1 integer(s)
#&amp;gt; [1] 57 33 21
#&amp;gt; 100 Levels: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... 100&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;storing-some-dna-in-bytefactor-and-bitfactor-objects.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Storing some DNA in &lt;code&gt;bytefactor&lt;/code&gt; and &lt;code&gt;bitfactor&lt;/code&gt; objects.&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;character&lt;/th&gt;
&lt;th&gt;factor&lt;/th&gt;
&lt;th&gt;bytefactor&lt;/th&gt;
&lt;th&gt;bitfactor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;bits/value&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;total size&lt;/td&gt;
&lt;td&gt;8 MB&lt;/td&gt;
&lt;td&gt;4 MB&lt;/td&gt;
&lt;td&gt;1 MB&lt;/td&gt;
&lt;td&gt;270 kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;size reduction&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2x&lt;/td&gt;
&lt;td&gt;8x&lt;/td&gt;
&lt;td&gt;30x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(smallfactor)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate some random DNA
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
character_vector_dna &amp;lt;- sample(c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;), 1e6, replace = TRUE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a `factor` and a `smallfactor` using the same basic syntax
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
integer_factor &amp;lt;- factor    (character_vector_dna, levels = c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;))
byte_factor    &amp;lt;- bytefactor(character_vector_dna, levels = c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;))
bit_factor     &amp;lt;- bitfactor (character_vector_dna, levels = c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# `smallfactor` is approx 1/4 the size of the regular factor
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lobstr::obj_size(character_vector_dna)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 8,000,272 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(integer_factor)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 4,000,688 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(byte_factor)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 1,000,696 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(bit_factor)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 267,704 B&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;similar-projects&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Similar projects&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/lofi&#34;&gt;{lofi}&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {numberwang} - numbers to words and vice versa)</title>
      <link>https://coolbutuseless.github.io/2021/08/30/introducing-numberwang-numbers-to-words-and-vice-versa/</link>
      <pubDate>Mon, 30 Aug 2021 20:09:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/08/30/introducing-numberwang-numbers-to-words-and-vice-versa/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;numberwang&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;numberwang &lt;img src=&#34;https://coolbutuseless.github.io/img/numberwang/logo.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/test%20coverage-100%25-blue.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/numberwang/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/numberwang/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;numberwang&lt;/code&gt; will convert floating point numbers (and integers) to their
word representations, and vice versa.&lt;/p&gt;
&lt;p&gt;The key differentiator of this package, compared to
&lt;a href=&#34;https://cran.r-project.org/package=nombre&#34;&gt;{nombre}&lt;/a&gt;, is that
it supports decimal representations by listing individual decimal digits.&lt;/p&gt;
&lt;p&gt;See below for a comparison with &lt;code&gt;{nombre}&lt;/code&gt;, &lt;code&gt;{english}&lt;/code&gt;, &lt;code&gt;{spanish}&lt;/code&gt; and &lt;code&gt;{xfun}&lt;/code&gt;.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;num_to_words(num, decimals = 3)&lt;/code&gt; converts numeric vectors to character vectors&lt;/li&gt;
&lt;li&gt;&lt;code&gt;words_to_num(words)&lt;/code&gt; converts character vectors to numeric vectors&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/numberwang&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/numberwang&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;thats-numberwang&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;That’s &lt;code&gt;numberwang&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/numberwang/thats-numberwang.jpg&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(numberwang)

c(12, pi, exp(10))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1]    12.000000     3.141593 22026.465795&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;num_to_words(c(12, pi, exp(10)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;twelve&amp;quot;                                               
#&amp;gt; [2] &amp;quot;three point one four two&amp;quot;                             
#&amp;gt; [3] &amp;quot;twenty-two thousand and twenty-six point four six six&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;words_to_num(c(
  &amp;#39;negative fifteen point seven&amp;#39;,
  &amp;quot;twenty-three point seven zero one&amp;quot;,
  &amp;quot;ten million, two thousand and forty two&amp;quot;
))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1]      -15.700       23.701 10002042.000&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Floating point representation isn’t exact, which means that for very large
numbers or very small numbers, and for lots of numbers inbetween,
all the digits after the first few must often be taken with a grain of salt.&lt;/li&gt;
&lt;li&gt;E.g. &lt;code&gt;formatC(0.3-0.2, format = &#39;f&#39;, digits = 20) = 0.09999999999999997780&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;E.g. &lt;code&gt;1e25&lt;/code&gt; should just be a &lt;code&gt;1&lt;/code&gt; followed by zeros, but in floating point
representation we get: &lt;code&gt;formatC(1e25, format = &#39;f&#39;, digits = 0) = 10000000000000000905969664&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;{english}&lt;/code&gt; and &lt;code&gt;{nombre}&lt;/code&gt; packages will warn you about precision loss
like this,
but &lt;code&gt;{numberwang}&lt;/code&gt; won’t.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;feature-comparison&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Feature comparison&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;numberwang&lt;/th&gt;
&lt;th&gt;nombre&lt;/th&gt;
&lt;th&gt;english&lt;/th&gt;
&lt;th&gt;spanish&lt;/th&gt;
&lt;th&gt;xfun&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;num_to_words&lt;/td&gt;
&lt;td&gt;nom_card&lt;/td&gt;
&lt;td&gt;english&lt;/td&gt;
&lt;td&gt;to_words&lt;/td&gt;
&lt;td&gt;n2w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;working range&lt;/td&gt;
&lt;td&gt;double()&lt;/td&gt;
&lt;td&gt;double()&lt;/td&gt;
&lt;td&gt;+/- 2^90&lt;/td&gt;
&lt;td&gt;[0,999]&lt;/td&gt;
&lt;td&gt;+/- 1e15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;decimals&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;as fractions&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;spanish&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;words-to-numbers&lt;/td&gt;
&lt;td&gt;words_to_num&lt;/td&gt;
&lt;td&gt;nom_uncard (ints only)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;just-for-fun---lets-rotate-the-board&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Just for fun - Let’s rotate the board!&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/numberwang/lets-rotate-the-board.jpg&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;exp(300)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] 1.942426e+130&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;formatC(
  exp(300), format = &amp;#39;f&amp;#39;, digits = 0
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [1] &amp;quot;19424263952412558251527551342607068708348876681949259689720520473778975990853476787505520791207218561168735878224980403355291484160&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;num_to_words(exp(300))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  nineteen duoquadragintillion, four hundred and twenty-four
  unquadragintillion, two hundred and sixty-three quadragintillion, nine
  hundred and fifty-two novemtrigintillion, four hundred and twelve
  octatrigintillion, five hundred and fifty-eight septentrigintillion,
  two hundred and fifty-one sextrigintillion, five hundred and
  twenty-seven quintrigintillion, five hundred and fifty-one
  quattuortrigintillion, three hundred and forty-two tretrigintillion,
  six hundred and seven duotrigintillion, sixty-eight untrigintillion,
  seven hundred and eight trigintillion, three hundred and forty-eight
  novemvigintillion, eight hundred and seventy-six octavigintillion, six
  hundred and eighty-one septenvigintillion, nine hundred and forty-nine
  sexvigintillion, two hundred and fifty-nine quinvigintillion, six
  hundred and eighty-nine quattuorvigintillion, seven hundred and twenty
  trevigintillion, five hundred and twenty duovigintillion, four hundred
  and seventy-three unvigintillion, seven hundred and seventy-eight
  vigintillion, nine hundred and seventy-five novemdecillion, nine
  hundred and ninety octadecillion, eight hundred and fifty-three
  septendecillion, four hundred and seventy-six sexdecillion, seven
  hundred and eighty-seven quindecillion, five hundred and five
  quattuordecillion, five hundred and twenty tredecillion, seven hundred
  and ninety-one duodecillion, two hundred and seven undecillion, two
  hundred and eighteen decillion, five hundred and sixty-one nonillion,
  one hundred and sixty-eight octillion, seven hundred and thirty-five
  septillion, eight hundred and seventy-eight sextillion, two hundred and
  twenty-four quintillion, nine hundred and eighty quadrillion, four
  hundred and three trillion, three hundred and fifty-five billion, two
  hundred and ninety-one million, four hundred and eighty-four thousand,
  one hundred and sixty&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=nombre&#34;&gt;nombre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=english&#34;&gt;english&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=spanish&#34;&gt;spanish&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=xfun&#34;&gt;xfun&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {smallfactor} - a space-saving factor backed by a raw vector (instead of integers)</title>
      <link>https://coolbutuseless.github.io/2021/08/27/introducing-smallfactor-a-space-saving-factor-backed-by-a-raw-vector-instead-of-integers/</link>
      <pubDate>Fri, 27 Aug 2021 15:09:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/08/27/introducing-smallfactor-a-space-saving-factor-backed-by-a-raw-vector-instead-of-integers/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;smallfactor---store-factors-in-raw-rather-than-integer&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;smallfactor - store factors in &lt;code&gt;raw&lt;/code&gt; rather than &lt;code&gt;integer&lt;/code&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;smallfactor&lt;/code&gt; is an experiment to see what tradeoffs there might be for storing
a factor in a raw byte instead of an integer.&lt;/p&gt;
&lt;p&gt;Since an R &lt;code&gt;raw&lt;/code&gt; value is only a single byte, but an &lt;code&gt;integer&lt;/code&gt; is 4 bytes,
there are space saving for large factors if stored in &lt;code&gt;raw&lt;/code&gt; vector -
as long as the number of levels is less than 256.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;smallfactor()&lt;/code&gt; - similar to &lt;code&gt;factor()&lt;/code&gt;, but creates an object backed by
raw bytes rather than an integer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;This package includes creating an object of the &lt;code&gt;smallfactor&lt;/code&gt; class,
and includes a few expected methods for common usage e.g. &lt;code&gt;as.character.smallfactor()&lt;/code&gt;,
&lt;code&gt;as.data.frame.smallfactor()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It seems possible that you could write more methods to make &lt;code&gt;smallfactor&lt;/code&gt; behaviour
almost identical to regular &lt;code&gt;factor&lt;/code&gt; behaviour, but this package is not attempting
this (yet).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/smallfactor&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/smallfactor&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-simple-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example simple usage&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;small &amp;lt;- smallfactor(c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;d&amp;#39;))
small&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [smallfactor]
#&amp;gt; [1] a b c a d
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;small[1:3]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; [smallfactor]
#&amp;gt; [1] a b c
#&amp;gt; Levels: a b c d&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(value = small, y = 1:5)
df&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;   value y
#&amp;gt; 1     a 1
#&amp;gt; 2     b 2
#&amp;gt; 3     c 3
#&amp;gt; 4     a 4
#&amp;gt; 5     d 5&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
df %&amp;gt;%
  filter(value &amp;lt; 3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;   value y
#&amp;gt; 1     a 1
#&amp;gt; 2     b 2
#&amp;gt; 3     a 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---storing-some-dna-in-14-the-space-of-a-regular-factor&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - storing some DNA in 1/4 the space of a regular factor&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(smallfactor)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate some random DNA
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dna &amp;lt;- sample(c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;), 1e6, replace = TRUE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a `factor` and a `smallfactor` using the same basic syntax
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small   &amp;lt;- smallfactor(dna, levels = c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;))
regular &amp;lt;- factor     (dna, levels = c(&amp;#39;A&amp;#39;, &amp;#39;T&amp;#39;, &amp;#39;G&amp;#39;, &amp;#39;C&amp;#39;))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# `smallfactor` is approx 1/4 the size of the regular factor
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lobstr::obj_size(dna)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 8,000,272 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(regular)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 4,000,688 B&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lobstr::obj_size(small)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; 1,000,696 B&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Fast(?) cubic beziers at variable resolution</title>
      <link>https://coolbutuseless.github.io/2021/08/11/fast-cubic-beziers-at-variable-resolution/</link>
      <pubDate>Wed, 11 Aug 2021 22:09:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/08/11/fast-cubic-beziers-at-variable-resolution/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;ul&gt;
&lt;li&gt;I wanted to calculate some points along cubic bezier curves&lt;/li&gt;
&lt;li&gt;Current R grid bezier implementation is not a real bezier! According to docs
for &lt;code&gt;grid::bezierGrob()&lt;/code&gt;: “The curve is currently drawn using an approximation based on X-splines.”&lt;/li&gt;
&lt;li&gt;Code below is the fastest thing I could come up with (I’m only 80% sure it’s correct)&lt;/li&gt;
&lt;li&gt;It vectorized implemntation of the explicit form of the curve
as explained on &lt;a href=&#34;https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves&#34;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I need something that can quickly change between low-complexity and
high-complexity approximations to the curve by changing the number of
line segments generated&lt;/li&gt;
&lt;li&gt;Speed-ups welcomed&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Pre-calculate sets of control-point weights for each for a range of 
# different desired points in the output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bf3s &amp;lt;- lapply(1:100, function(N) {
  t  &amp;lt;- seq.int(0, 1, length.out = N)

  matrix(c(
    1 * t^0 * (1 - t)^3,
    3 * t^1 * (1 - t)^2,
    3 * t^2 * (1 - t)^1,
    1 * t^3 * (1 - t)^0
  ), ncol = 4
  )
})


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Convert cubic  beziers to data.frame of coordinates along curve
#&amp;#39;
#&amp;#39; @param x,y coords of control points
#&amp;#39; @param N Number of output points
#&amp;#39;
#&amp;#39; @return list of coords
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bezier3 &amp;lt;- function(x, y, N = 5) {
  stopifnot(length(x)== 4, length(y) == 4)
  list(
    x = rowSums(bf3s[[N]] * matrix(x, nrow = N, ncol = 4, byrow = TRUE)),
    y = rowSums(bf3s[[N]] * matrix(y, nrow = N, ncol = 4, byrow = TRUE))
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;demo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Demo&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

# Random control points
set.seed(1)
xcp &amp;lt;- runif(4)
ycp &amp;lt;- runif(4)

# Generate low and high complexity approximations
pt_lo &amp;lt;- bezier3(xcp, ycp,  4)
pt_hi &amp;lt;- bezier3(xcp, ycp, 40)

# Draw my approximations
grid.lines(pt_lo$x, pt_lo$y, gp = gpar(col = &amp;#39;red&amp;#39; ))
grid.lines(pt_hi$x, pt_hi$y, gp = gpar(col = &amp;#39;blue&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-08-11-cubic-beziers_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;comparison-to-gridgrid.bezier&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Comparison to &lt;code&gt;grid::grid.bezier()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Overlay the grid version of this bezier 
grid.lines(pt_lo$x, pt_lo$y, gp = gpar(col = &amp;#39;red&amp;#39; ))
grid.lines(pt_hi$x, pt_hi$y, gp = gpar(col = &amp;#39;blue&amp;#39;))
grid.bezier(xcp, ycp)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-08-11-cubic-beziers_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;About 30,000 beziers/second&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bezier3(xcp, ycp, N)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26.9µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;35103.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bezier3(xcp, ycp, N)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.3µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27.5µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31933.63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bezier3(xcp, ycp, N)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27.8µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;33358.24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bezier3(xcp, ycp, N)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30.5µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30847.32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bezier3(xcp, ycp, N)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;100&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;33µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27591.29&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {colourmebad} - find pronounceable colours close to reference colours</title>
      <link>https://coolbutuseless.github.io/2021/07/30/introducing-colourmebad-find-pronounceable-colours-close-to-reference-colours/</link>
      <pubDate>Fri, 30 Jul 2021 21:09:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/30/introducing-colourmebad-find-pronounceable-colours-close-to-reference-colours/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;colourmebad&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;colourmebad &lt;img src=&#34;https://coolbutuseless.github.io/img/colourmebad/logo.png&#34; align=&#34;right&#34; height=&#34;430/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;colourmebad&lt;/code&gt; provides some tools for finding pronounceable approximations to hex colours.&lt;/p&gt;
&lt;p&gt;These tools will be handy if you ever have to memorise a set of hex colours,
or would like to impress people with your recall of a good colour palette as
a party trick. In summary - no one needs these tools.&lt;/p&gt;
&lt;p&gt;This package was inspired by &lt;a href=&#34;https://twitter.com/mdsumner&#34;&gt;mdsumner&lt;/a&gt;’s
&lt;a href=&#34;https://github.com/mdsumner/hexwords&#34;&gt;hexwords&lt;/a&gt; package.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What’s in the box&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;find_best_colour_match()&lt;/code&gt; For each of the reference
colours supplied, this function will find the best match amongst a list of
candidate colours. Where ‘best match’ is defined as the shortest euclidean
distance in &lt;a href=&#34;https://en.wikipedia.org/wiki/Lab_color_space&#34;&gt;Lab&lt;/a&gt; colourspace.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colours_to_words()&lt;/code&gt; and &lt;code&gt;words_to_colours()&lt;/code&gt; to use some digit/letter substitutions
and convert a 6-letter word into a hex colour and vice versa&lt;/li&gt;
&lt;li&gt;&lt;code&gt;show_palette()&lt;/code&gt; to display a single set of colours&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compare_palettes()&lt;/code&gt; to show 2 palettes side-by-side&lt;/li&gt;
&lt;li&gt;Included colour lists
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;colour_words&lt;/code&gt; hex colours which are directly readable as dictionary words&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colour_words_with_substitutions&lt;/code&gt; hex colours which can be converted to
dictionary words if certain digit/letter substitutions are performed
e.g. replay all letter-o with number-0 etc.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nonsense_words&lt;/code&gt; hex colours which could almost be read as a pronounceable
word but with a very high probability of being nonsense/gibberish.
e.g. &lt;code&gt;#elesta&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/colourmebad&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/colourmebad&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;hex-colours-which-are-dictionary-words&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hex colours which are dictionary words&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(colourmebad)

colour_words&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;#accede&amp;quot; &amp;quot;#afaced&amp;quot; &amp;quot;#bacaba&amp;quot; &amp;quot;#baccae&amp;quot; &amp;quot;#baffed&amp;quot; &amp;quot;#beaded&amp;quot; &amp;quot;#bedaff&amp;quot;
#&amp;gt;  [8] &amp;quot;#bedded&amp;quot; &amp;quot;#bedead&amp;quot; &amp;quot;#bedeaf&amp;quot; &amp;quot;#beebee&amp;quot; &amp;quot;#beefed&amp;quot; &amp;quot;#cabbed&amp;quot; &amp;quot;#cadded&amp;quot;
#&amp;gt; [15] &amp;quot;#dabbed&amp;quot; &amp;quot;#daffed&amp;quot; &amp;quot;#decade&amp;quot; &amp;quot;#decede&amp;quot; &amp;quot;#deeded&amp;quot; &amp;quot;#deface&amp;quot; &amp;quot;#defade&amp;quot;
#&amp;gt; [22] &amp;quot;#efface&amp;quot; &amp;quot;#facade&amp;quot; &amp;quot;#feeded&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::colours_to_words(colour_words)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;accede&amp;quot; &amp;quot;afaced&amp;quot; &amp;quot;bacaba&amp;quot; &amp;quot;baccae&amp;quot; &amp;quot;baffed&amp;quot; &amp;quot;beaded&amp;quot; &amp;quot;bedaff&amp;quot; &amp;quot;bedded&amp;quot;
#&amp;gt;  [9] &amp;quot;bedead&amp;quot; &amp;quot;bedeaf&amp;quot; &amp;quot;beebee&amp;quot; &amp;quot;beefed&amp;quot; &amp;quot;cabbed&amp;quot; &amp;quot;cadded&amp;quot; &amp;quot;dabbed&amp;quot; &amp;quot;daffed&amp;quot;
#&amp;gt; [17] &amp;quot;decade&amp;quot; &amp;quot;decede&amp;quot; &amp;quot;deeded&amp;quot; &amp;quot;deface&amp;quot; &amp;quot;defade&amp;quot; &amp;quot;efface&amp;quot; &amp;quot;facade&amp;quot; &amp;quot;feeded&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::show_palette(colour_words)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hex-colours-which-are-dictionary-words-if-you-allow-for-some-digit-letter-subsitutions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hex colours which are dictionary words if you allow for some digit-letter subsitutions&lt;/h2&gt;
&lt;p&gt;In the great tradition of “hacker speak” and customised number plates for cars,
digits can be used in place of letters if they look similar enough.&lt;/p&gt;
&lt;p&gt;The default substitutions this package employs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt; = &lt;code&gt;o&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1&lt;/code&gt; = &lt;code&gt;l&lt;/code&gt; (lower case L)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2&lt;/code&gt; = &lt;code&gt;z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5&lt;/code&gt; = &lt;code&gt;s&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;7&lt;/code&gt; = &lt;code&gt;t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;9&lt;/code&gt; = &lt;code&gt;g&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cols &amp;lt;- sample(colour_words_with_substitutions, 25)
cols&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;#7ea51e&amp;quot; &amp;quot;#9e0da1&amp;quot; &amp;quot;#ba1a7a&amp;quot; &amp;quot;#5099ed&amp;quot; &amp;quot;#de17a5&amp;quot; &amp;quot;#cac7a1&amp;quot; &amp;quot;#b017e1&amp;quot;
#&amp;gt;  [8] &amp;quot;#fe0da1&amp;quot; &amp;quot;#ca77ed&amp;quot; &amp;quot;#add1e5&amp;quot; &amp;quot;#9051e7&amp;quot; &amp;quot;#5ca775&amp;quot; &amp;quot;#d0d1e7&amp;quot; &amp;quot;#5ca1e5&amp;quot;
#&amp;gt; [15] &amp;quot;#c0991e&amp;quot; &amp;quot;#5701e5&amp;quot; &amp;quot;#0b1a7a&amp;quot; &amp;quot;#5add1e&amp;quot; &amp;quot;#501ace&amp;quot; &amp;quot;#ca57e5&amp;quot; &amp;quot;#2abe7a&amp;quot;
#&amp;gt; [22] &amp;quot;#e570c5&amp;quot; &amp;quot;#bab005&amp;quot; &amp;quot;#effe7e&amp;quot; &amp;quot;#e771ed&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::colours_to_words(cols)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;teasle&amp;quot; &amp;quot;geodal&amp;quot; &amp;quot;balata&amp;quot; &amp;quot;sogged&amp;quot; &amp;quot;deltas&amp;quot; &amp;quot;cactal&amp;quot; &amp;quot;boltel&amp;quot; &amp;quot;feodal&amp;quot;
#&amp;gt;  [9] &amp;quot;catted&amp;quot; &amp;quot;addles&amp;quot; &amp;quot;goslet&amp;quot; &amp;quot;scatts&amp;quot; &amp;quot;dodlet&amp;quot; &amp;quot;scales&amp;quot; &amp;quot;coggle&amp;quot; &amp;quot;stoles&amp;quot;
#&amp;gt; [17] &amp;quot;oblata&amp;quot; &amp;quot;saddle&amp;quot; &amp;quot;solace&amp;quot; &amp;quot;castes&amp;quot; &amp;quot;zabeta&amp;quot; &amp;quot;estocs&amp;quot; &amp;quot;baboos&amp;quot; &amp;quot;effete&amp;quot;
#&amp;gt; [25] &amp;quot;ettled&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::show_palette(cols)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hex-colours-which-are-probably-nonsense-words-but-may-be-pronounceable&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hex colours which are probably nonsense words but may be pronounceable&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cols &amp;lt;- sample(nonsense_words, 25)
cols&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;#9e1ae7&amp;quot; &amp;quot;#fa15e5&amp;quot; &amp;quot;#5e7a75&amp;quot; &amp;quot;#91e052&amp;quot; &amp;quot;#b1009b&amp;quot; &amp;quot;#ce7e77&amp;quot; &amp;quot;#09090a&amp;quot;
#&amp;gt;  [8] &amp;quot;#a91e17&amp;quot; &amp;quot;#ede91a&amp;quot; &amp;quot;#75a570&amp;quot; &amp;quot;#77e75e&amp;quot; &amp;quot;#17e7ca&amp;quot; &amp;quot;#0021a7&amp;quot; &amp;quot;#d00d1e&amp;quot;
#&amp;gt; [15] &amp;quot;#1a091a&amp;quot; &amp;quot;#1ee755&amp;quot; &amp;quot;#cac1a7&amp;quot; &amp;quot;#57a7ed&amp;quot; &amp;quot;#05707a&amp;quot; &amp;quot;#07ae15&amp;quot; &amp;quot;#027ee2&amp;quot;
#&amp;gt; [22] &amp;quot;#05c1a5&amp;quot; &amp;quot;#7e0d01&amp;quot; &amp;quot;#51eac1&amp;quot; &amp;quot;#7ee570&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::colours_to_words(cols)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt;  [1] &amp;quot;gelaet&amp;quot; &amp;quot;falses&amp;quot; &amp;quot;setats&amp;quot; &amp;quot;gleosz&amp;quot; &amp;quot;bloogb&amp;quot; &amp;quot;cetett&amp;quot; &amp;quot;ogogoa&amp;quot; &amp;quot;aglelt&amp;quot;
#&amp;gt;  [9] &amp;quot;edegla&amp;quot; &amp;quot;tsasto&amp;quot; &amp;quot;ttetse&amp;quot; &amp;quot;ltetca&amp;quot; &amp;quot;oozlat&amp;quot; &amp;quot;doodle&amp;quot; &amp;quot;laogla&amp;quot; &amp;quot;leetss&amp;quot;
#&amp;gt; [17] &amp;quot;caclat&amp;quot; &amp;quot;stated&amp;quot; &amp;quot;ostota&amp;quot; &amp;quot;otaels&amp;quot; &amp;quot;ozteez&amp;quot; &amp;quot;osclas&amp;quot; &amp;quot;teodol&amp;quot; &amp;quot;sleacl&amp;quot;
#&amp;gt; [25] &amp;quot;teesto&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colourmebad::show_palette(cols)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-pronounceable-palette-similar-to-a-reference-palette&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a pronounceable palette similar to a reference palette&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ref &amp;lt;- RColorBrewer::brewer.pal(8, &amp;#39;Dark2&amp;#39;)

colourmebad::show_palette(ref, labels = ref, title = &amp;quot;Reference Palette&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pronounceable &amp;lt;- colourmebad::find_best_colour_match(ref, colour_words_with_substitutions)
colourmebad::compare_palettes(ref, pronounceable, &amp;quot;ColorBrewer Dark2&amp;quot;, &amp;quot;Words with digit/letter substitutions&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-pronounceable-nonsense-palette-similar-to-a-reference-palette&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a pronounceable nonsense palette similar to a reference palette&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pronounceable &amp;lt;- colourmebad::find_best_colour_match(ref, nonsense_words)
colourmebad::compare_palettes(ref, pronounceable, &amp;quot;ColorBrewer Dark2&amp;quot;, &amp;quot;Nonsense words&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-30-colournames_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-pronounceable-spanish-palette-similar-to-a-reference-palette&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a pronounceable Spanish palette similar to a reference palette&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# http://ftp.icm.edu.pl/packages/wordlists/spanish/
spanish_words_with_substitutions &amp;lt;- system(&amp;#39;grep -i -E &amp;quot;^[abcdeflsotgz]{6}$&amp;quot; ./working/spanish.txt&amp;#39;, intern = TRUE)
cols &amp;lt;- colourmebad::words_to_colours(spanish_words_with_substitutions)
pronounceable_spanish &amp;lt;- colourmebad::find_best_colour_match(ref, cols)
colourmebad::compare_palettes(ref, pronounceable_spanish, &amp;quot;ColorBrewer Dark2&amp;quot;, &amp;quot;Spanish words&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/colourmebad/spanish.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/mdsumner/hexwords&#34;&gt;hexwords&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {ggqr} - A geom for QR codes in ggplot2</title>
      <link>https://coolbutuseless.github.io/2021/07/27/introducing-ggqr-a-geom-for-qr-codes-in-ggplot2/</link>
      <pubDate>Tue, 27 Jul 2021 21:22:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/27/introducing-ggqr-a-geom-for-qr-codes-in-ggplot2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggqr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggqr&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggqr&lt;/code&gt; provides &lt;code&gt;geom_qr()&lt;/code&gt; for inserting &lt;a href=&#34;https://en.wikipedia.org/wiki/QR_code&#34;&gt;QR Codes&lt;/a&gt; into a plot.&lt;/p&gt;
&lt;p&gt;The core QR functionality is provided by &lt;a href=&#34;https://twitter.com/hrbrmstr&#34;&gt;Bob Rudis’s&lt;/a&gt; &lt;a href=&#34;https://cran.r-project.org/package=qrencoder&#34;&gt;qrencoder&lt;/a&gt; package.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What’s in the box&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;geom_qr()&lt;/code&gt; to add QR codes to a plot&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grGrob()&lt;/code&gt; to create a QR grob&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Future Possibilities?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add automatic label positioning to avoid overlap of codes&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/ggqr&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/ggqr&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggqr)

plot_df       &amp;lt;- head(mtcars)
plot_df$car   &amp;lt;- paste0(&amp;quot;https://duckduckgo.com/?q=&amp;quot;, rownames(plot_df))
plot_df$hjust &amp;lt;- c(-0.1, 1.1, 1.1, -0.1,   0,   0)
plot_df$vjust &amp;lt;- c( 1.1, 0.0, 0.0, -0.1, 1.1, 1.1)

ggplot(plot_df) +
  geom_qr(
    aes(
      x     = mpg, 
      y     = wt, 
      label = car, 
      hjust = I(hjust), 
      vjust = I(vjust), 
      col   = as.factor(cyl)
    ), 
    size = 0.8
  ) +
  geom_point(aes(mpg, wt), size = 3) +
  theme_bw() + 
  theme(legend.position = &amp;#39;bottom&amp;#39;) +
  labs(title = &amp;quot;ggqr::geom_qr() - QR codes with search links to car names&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-27-introducing-ggqr_files/figure-html/example-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=qrencoder&#34;&gt;qrencoder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {bdftools} - tools for bitmap fonts in R</title>
      <link>https://coolbutuseless.github.io/2021/07/26/introducing-bdftools-tools-for-bitmap-fonts-in-r/</link>
      <pubDate>Mon, 26 Jul 2021 21:02:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/26/introducing-bdftools-tools-for-bitmap-fonts-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;bdftools&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;bdftools&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/bdftools/header.png&#34; /&gt;&lt;/p&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bdftools&lt;/code&gt; provides some tools for reading, manipulating and outputting BDF bitmap fonts.&lt;/p&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Todo: print header info when printing font
&lt;ul&gt;
&lt;li&gt;Number of characters, width, height, bbox etc&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What’s in the box&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read_bdf(filename)&lt;/code&gt; reads a BDF pixel font file into an R representation
i.e. an object of class &lt;code&gt;bdf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;print.bdf()&lt;/code&gt; prints meta information and a font sample.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bdf_create_df(bdf, text)&lt;/code&gt; Create a data.frame of points for the given string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bdf_create_mat(bdf, text)&lt;/code&gt; Create a matrix representation for the given string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bdfGrob(bdf, text, ...)&lt;/code&gt; create a simple grob representation of the given string using
squares for pixels&lt;/li&gt;
&lt;li&gt;&lt;code&gt;geom_text_bdf()&lt;/code&gt; renders text in a bitmap font - simlar interface to &lt;code&gt;ggplot2::geom_text()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;as.data.frame.bdf(bdf)&lt;/code&gt; converts the full &lt;code&gt;bdf&lt;/code&gt; font into a rectangular
data.frame of all characters and their (x, y) coordinates.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_bdf_builtin()&lt;/code&gt; to read in a font included with this package:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/slavfox/Cozette&#34;&gt;Cozette&lt;/a&gt; License: MIT. See &lt;code&gt;LICENSE-cozette&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/raymond-w-ko/creep2&#34;&gt;Creep2&lt;/a&gt; License: MIT. See &lt;code&gt;LICENSE-creep2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/fcambus/spleen&#34;&gt;Spleen&lt;/a&gt; License: BSD 2-clause. See &lt;code&gt;LICENSE-spleen&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/bdftools&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/bdftools&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;example-loading-and-displaying-a-bdf-bitmap-font.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Loading and displaying a BDF bitmap font.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(ggplot2)
library(bdftools)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Load a BDF font
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fontfile &amp;lt;- system.file(&amp;quot;spleen-5x8.bdf&amp;quot;, package = &amp;quot;bdftools&amp;quot;, mustWork = TRUE)
myfont &amp;lt;- read_bdf(fontfile)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# By default, printing a font will print some header info, and a text 
# sample rendered in that font in the console
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
myfont&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;size=8, bbox=5, pixel_size=8, font_descent=0, font_ascent=-1, default_char=8, line_height=1, bitmap=7, size=32, bbox=8, pixel_size= 

                  #       #                      
#  #              #       #                      
#  #  ##  ###   ###  ###  #    ##  #  #  ###  ###
####    # #  # #  # #  #  #   #  # #  # #  # #   
#  #  ### #  # #  # #  #  #   #  # #  # ####  ## 
#  # #  # #  # #  #  ##   #   #  #  ##  #       #
#  #  ### #  #  ###    #   ##  ##   ##   ### ### 
                    ###                          &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate some sample text in the console
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bdf_print_sample(myfont, &amp;quot;Hello RStats&amp;quot;, wrap = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;           #    #                        #         #       
#  #       #    #             ###   ###  #         #       
#  #  ###  #    #    ##       #  # #    ###   ##  ###   ###
#### #  #  #    #   #  #      #  #  ##   #      #  #   #   
#  # ####  #    #   #  #      ###     #  #    ###  #    ## 
#  # #     #    #   #  #      #  #    #  #   #  #  #      #
#  #  ###   ##   ##  ##       #  # ###    ##  ###   ## ### &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate a graphics grob and draw it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grob &amp;lt;- bdfGrob(myfont, &amp;quot;Hello\nRStats&amp;quot;, size = 10, shrink = 0.8, fill = &amp;#39;lightblue&amp;#39;, col = &amp;#39;blue&amp;#39;)
grid.newpage(); grid.draw(grob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-26-introducing-bdftools_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# View the entire font as a data.frame of coordiantes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
as.data.frame(myfont)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2,385 x 10
   encoding desc    dwidth     x     y  size pixel_size font_ascent font_descent
 *    &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;    &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;      &amp;lt;int&amp;gt;       &amp;lt;int&amp;gt;        &amp;lt;int&amp;gt;
 1       32 SPACE        5    NA    NA     8          8           7            1
 2       33 EXCLAM…      5     3     7     8          8           7            1
 3       33 EXCLAM…      5     3     6     8          8           7            1
 4       33 EXCLAM…      5     3     5     8          8           7            1
 5       33 EXCLAM…      5     3     4     8          8           7            1
 6       33 EXCLAM…      5     3     3     8          8           7            1
 7       33 EXCLAM…      5     3     1     8          8           7            1
 8       34 QUOTAT…      5     4     7     8          8           7            1
 9       34 QUOTAT…      5     2     7     8          8           7            1
10       34 QUOTAT…      5     4     6     8          8           7            1
# … with 2,375 more rows, and 1 more variable: line_height &amp;lt;int&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# View the coordinates of a string rendered in this font
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bdf_create_df(myfont, &amp;quot;abc&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 34 x 3
       x     y   idx
   &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
 1     3     5     1
 2     2     5     1
 3     4     4     1
 4     4     3     1
 5     3     3     1
 6     2     3     1
 7     4     2     1
 8     1     2     1
 9     4     1     1
10     3     1     1
# … with 24 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# View the coordinates of a string rendered in this font
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bdf_create_mat(myfont, &amp;quot;abc&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,]    0    0    0    0    0    1    0    0    0     0     0     0     0     0
[2,]    0    0    0    0    0    1    0    0    0     0     0     0     0     0
[3,]    0    1    1    0    0    1    1    1    0     0     0     1     1     1
[4,]    0    0    0    1    0    1    0    0    1     0     1     0     0     0
[5,]    0    1    1    1    0    1    0    0    1     0     1     0     0     0
[6,]    1    0    0    1    0    1    0    0    1     0     1     0     0     0
[7,]    0    1    1    1    0    1    1    1    0     0     0     1     1     1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;an-example-of-a-larger-font&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;An example of a larger font&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;myfont &amp;lt;- bdftools::read_bdf_builtin(&amp;quot;spleen-16x32.bdf&amp;quot;)
bdf_print_sample(myfont, &amp;quot;Frak&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;    ##########                                     ##         
   ###########                                     ##         
  ###                                              ##         
  ##                                               ##         
  ##                                               ##         
  ##                                               ##         
  ##                ##########     #########       ##     ##  
  ##               ###########     ##########      ##    ###  
  ##              ###       ##             ###     ##   ###   
  #########       ##        ##              ##     ##  ###    
  #########       ##                        ##     ## ###     
  ##              ##                ##########     #####      
  ##              ##               ###########     #####      
  ##              ##              ###       ##     ## ###     
  ##              ##              ##        ##     ##  ###    
  ##              ##              ##        ##     ##   ###   
  ##              ##              ##        ##     ##    ###  
  ##              ##              ###       ##     ##     ### 
  ##              ##               ###########     ##      ###
  ##              ##                ##########     ##       ##&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;ggplot2-example-with-geom_text_bdf&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ggplot2 example with &lt;code&gt;geom_text_bdf()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;geom_text_bdf()&lt;/code&gt; works very similar to &lt;code&gt;geom_text()&lt;/code&gt; but text is rendered from
a bitmap font as a collection of large square pixels. Key things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can set both an outline &lt;code&gt;colour&lt;/code&gt; and a &lt;code&gt;fill&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shrink&lt;/code&gt; argument determines the size of the square pixel. &lt;code&gt;shrink = 1&lt;/code&gt; is
the default. &lt;code&gt;shrink = 0.9&lt;/code&gt; will make the square pixels smaller and not
touching each other.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(bdftools)

fontfile &amp;lt;- system.file(&amp;quot;spleen-5x8.bdf&amp;quot;, package = &amp;quot;bdftools&amp;quot;, mustWork = TRUE)

plot_df &amp;lt;- head(mtcars)
plot_df$car &amp;lt;- rownames(plot_df)
plot_df$cyl &amp;lt;- as.factor(plot_df$cyl)

ggplot(plot_df, aes(mpg, wt)) + 
  geom_point(col = &amp;#39;red&amp;#39;) + 
  geom_text_bdf(
    aes(mpg, wt, label=car, fill = cyl), 
    col          = NA, 
    linewidth    = 0.5,
    bdf_filename = fontfile, 
    shrink       = 1,
    size         = 9,
    hjust        = -0.1
  ) + 
  theme_bw() + 
  scale_fill_brewer(palette = &amp;#39;Dark2&amp;#39;) + 
  labs(title = &amp;quot;geom_text_bdf() - bitmap font rendering in ggplot2&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-26-introducing-bdftools_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;font-sample-sheet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Font sample sheet&lt;/h2&gt;
&lt;p&gt;An example of how the data.frame representation of the font can be plotted
in &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(bdftools)

myfont &amp;lt;- read_bdf_builtin(&amp;quot;cozette.bdf&amp;quot;)

plot_df &amp;lt;- as.data.frame(myfont)
plot_df &amp;lt;- plot_df[plot_df$encoding &amp;gt;= 65 &amp;amp; plot_df$encoding &amp;lt;= 124,]

ggplot(plot_df) +
  geom_tile(aes(x, y), width=0.9, height = 0.9, na.rm = TRUE) +
  facet_wrap(~encoding + desc, ncol = 12)+
  theme_void(10) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-26-introducing-bdftools_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;package-header&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Package Header&lt;/h2&gt;
&lt;p&gt;How the header for this page was created.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Choose some fonts
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
font1 &amp;lt;- bdftools::read_bdf_builtin(&amp;quot;spleen-16x32.bdf&amp;quot;)
font2 &amp;lt;- bdftools::read_bdf_builtin(&amp;quot;spleen-5x8.bdf&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Main header
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
txt1 &amp;lt;- bdfGrob(
  font1, &amp;quot;bdftools&amp;quot;, 
  lwd    = 0.5,
  fill   = &amp;#39;#3D428B&amp;#39;,
  col    = &amp;#39;darkblue&amp;#39;,
  size   = 8, 
  shrink = 0.8
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Subtitle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
txt2 &amp;lt;- bdfGrob(
  font2, &amp;quot;bitmap fonts in R&amp;quot;, 
  lwd    = 0.5,
  col    = &amp;#39;darkblue&amp;#39;,
  size   = 11, 
  shrink = 0.8,
  fill   = viridisLite::inferno(151),
  y      = unit(0.5, &amp;#39;npc&amp;#39;) - unit(50, &amp;#39;mm&amp;#39;)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage(); 
grid.draw(txt1)
grid.draw(txt2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-26-introducing-bdftools_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bdf-bitmap-font-resources&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;BDF Bitmap Font Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Fonts
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://robey.lag.net/2010/01/23/tiny-monospace-font.html&#34;&gt;Tom Thumb tiny font&lt;/a&gt; (License: Dual licensed
CC0 or CC-BY 3.0 license.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/Tecate/bitmap-fonts&#34;&gt;github repo of lots of fonts&lt;/a&gt; (License: Various/unknown)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.unifoundry.com/unifont/index.html&#34;&gt;unifont&lt;/a&gt; a BDF font with glyphs
for every printable codepoint from &lt;code&gt;U+0000&lt;/code&gt; to &lt;code&gt;U+FFFF&lt;/code&gt;. (License: Dual licensed
SIL Open Font License (OFL) version 1.1 and the GNU GPL 2+ with the GNU font embedding exception)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html&#34;&gt;X11 fonts&lt;/a&gt; (License: Public Domain)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;BDF Font Specification
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format&#34;&gt;BDF on Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://adobe-type-tools.github.io/font-tech-notes/pdfs/5005.BDF_Spec.pdf&#34;&gt;BDF Specification Document (Adobe)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;p&gt;Other retro/vector/pixel fonts in R&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/arcadefont&#34;&gt;arcade font&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/gridfont&#34;&gt;gridfont&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/hershey&#34;&gt;hershey&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {facetious} - alternate facets for ggplot2</title>
      <link>https://coolbutuseless.github.io/2021/07/20/introducing-facetious-alternate-facets-for-ggplot2/</link>
      <pubDate>Tue, 20 Jul 2021 19:52:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/20/introducing-facetious-alternate-facets-for-ggplot2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;facetious&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;facetious&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;facetious&lt;/code&gt; is home to some alternate facetting options for &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;facet_wrap_strict()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;respects nrow, ncol and inserts empty grobs to keep the resultant
plot at the given size&lt;/li&gt;
&lt;li&gt;Otherwise works like &lt;code&gt;ggplot2::facet_wrap()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;facet_grid_blank()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;When a factor level doesn’t exist, this facetting approach will insert
a totally empty object, instead of just an empty plot&lt;/li&gt;
&lt;li&gt;Otherwise works like &lt;code&gt;ggplot2::facet_grid()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/facetious&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/facetious&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;facet_wrap_strict&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;facet_wrap_strict&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(patchwork)
library(facetious)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Standard ggplot2 facet_wrap()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot_facet_wrap &amp;lt;- ggplot(mtcars) +
  geom_point(aes(mpg, wt)) + 
  facet_wrap(~cyl, nrow = 3, ncol = 2) + 
  labs(title = &amp;quot;facet_wrap(... nrow=3, ncol=2)&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# facetious::facet_wrap_strict
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
facetious_facet_wrap_strict &amp;lt;- ggplot(mtcars) +
  geom_point(aes(mpg, wt)) + 
  facet_wrap_strict(~cyl, nrow = 3, ncol = 2) + 
  labs(title = &amp;quot;facet_wrap_strict(... nrow=3, ncol=2)&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use &amp;#39;patchwork&amp;#39; to stitch plots side-by-side
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot_facet_wrap + facetious_facet_wrap_strict&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-20-introducing-facetious_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;facet_grid_blank&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;facet_grid_blank&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(ggplot2)
library(patchwork)
library(facetious)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Make some data with some empty factors
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_df &amp;lt;- mtcars %&amp;gt;%
  mutate(
    cyl = as.factor(cyl),
    am = as.factor(am)
  ) %&amp;gt;%
  filter(!(cyl == 4 &amp;amp; am == 1)) %&amp;gt;%
  filter(!(cyl == 8 &amp;amp; am == 0))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Standard ggplot facet_grid()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot_facet_grid &amp;lt;- ggplot(plot_df) +
  geom_point(aes(mpg, wt)) +
  facet_grid(rows = vars(cyl), cols = vars(am), drop = FALSE,
             labeller = label_both) +
  labs(title = &amp;quot;ggplot2::facet_grid()&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# facetious::facet_grid_blank()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
facetious_facet_grid_blank &amp;lt;- ggplot(plot_df) +
  geom_point(aes(mpg, wt)) +
  facet_grid_blank(rows = vars(cyl), cols = vars(am), drop = FALSE, 
                   labeller = label_both) +
  labs(title = &amp;quot;facetious::facet_grid_blank()&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use &amp;#39;patchwork&amp;#39; to stitch plots side-by-side
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot_facet_grid + facetious_facet_grid_blank&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-20-introducing-facetious_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggforce&#34;&gt;ggforce&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {ingrid} - alternate tools for grab creation, manipulation and output</title>
      <link>https://coolbutuseless.github.io/2021/07/15/introducing-ingrid-alternate-tools-for-grab-creation-manipulation-and-output/</link>
      <pubDate>Thu, 15 Jul 2021 19:21:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/15/introducing-ingrid-alternate-tools-for-grab-creation-manipulation-and-output/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ingrid&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ingrid &lt;img src=&#34;https://coolbutuseless.github.io/img/ingrid/logo.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ingrid&lt;/code&gt; provides some tools that I find useful for creating/manipulating &lt;code&gt;grid&lt;/code&gt;/&lt;code&gt;grob&lt;/code&gt;
objects interactively in the console.&lt;/p&gt;
&lt;p&gt;The name &lt;code&gt;ingrid&lt;/code&gt; stands for &lt;strong&gt;IN&lt;/strong&gt;teractive &lt;strong&gt;GRID&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The key benefits I get from &lt;code&gt;ingrid&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;verbose output of grobs, gTrees and polyclipgrobs, with much more output
than their default &lt;code&gt;print&lt;/code&gt; methods from &lt;code&gt;{grid}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a suite of grob creation functions with inline gpar parameter specification.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;default.units&lt;/code&gt; can be set globally to whatever the user wants, but default to ‘mm’&lt;/li&gt;
&lt;li&gt;a consistent set of grob combination functions (e.g. intersection, minus) that
work across single grobs, gTrees and polyclipgrobs&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ingrid/articles/logo.html&#34;&gt;Creating the hex logo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ingrid/articles/verbose.html&#34;&gt;Verbose grob output&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ingrid/articles/grob-creation.html&#34;&gt;Grob creation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ingrid/articles/combine.html&#34;&gt;Combining objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ingrid/articles/pattern.html&#34;&gt;Creating patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box-details-details-details&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box (Details, details, details)&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;14%&#34; /&gt;
&lt;col width=&#34;19%&#34; /&gt;
&lt;col width=&#34;66%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;grid&lt;/th&gt;
&lt;th&gt;ingrid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;grob creation&lt;/td&gt;
&lt;td&gt;circleGrob(), rectGrob(), etc&lt;/td&gt;
&lt;td&gt;circle_grob(), rect_grob(), etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;default.units&lt;/td&gt;
&lt;td&gt;‘npc’&lt;/td&gt;
&lt;td&gt;getOption(‘ingrid.default.units’, ‘mm’)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;unit creation&lt;/td&gt;
&lt;td&gt;unit(10, ‘mm’)&lt;/td&gt;
&lt;td&gt;.mm(10), .npc(), .points() etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;gpar creation&lt;/td&gt;
&lt;td&gt;gpar(fill = ‘red’)&lt;/td&gt;
&lt;td&gt;gp(fill = ‘red’) Has named arguments to support autocompletion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;pattern creation&lt;/td&gt;
&lt;td&gt;pattern() default extend = ‘pad’&lt;/td&gt;
&lt;td&gt;pattern_creation() default extend = ‘repeat’&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;grob combination&lt;/td&gt;
&lt;td&gt;gridGeometry::polyclipgrob()&lt;/td&gt;
&lt;td&gt;grob_stack(), grob_intersect(), grob_union(), grob_minus(), grob_xor() supporting grobs, gTrees, polyclipgrobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;print()&lt;/td&gt;
&lt;td&gt;print.grob() is terse&lt;/td&gt;
&lt;td&gt;verbose printing print.grob(), print.gTree(), print.polyclipgrob()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;enable verbose printing&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;register_verbose_printing(), deregister_verbose_printing()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;grob coord transforms&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;grob_translate(), grob_rotate()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;viewport updates&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;vp_translate(), vp_rotate(), vp_setmask(), vp_setclip()&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;details&gt;
&lt;summary&gt;
Click here to reveal more details on what’s included
&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grob_circle()&lt;/code&gt; etc. Analoges for the the grob creation functions in the
&lt;code&gt;grid&lt;/code&gt; package, but with a slight change in the argument defaults:
&lt;ul&gt;
&lt;li&gt;default.units are now ‘mm’ instead of ‘npc’&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;gp&lt;/code&gt; and &lt;code&gt;vp&lt;/code&gt; objects are both created as fully realised structures,
and no longer left as &lt;code&gt;NULL&lt;/code&gt; if no values are given. This makes manipulation
of grob objects a bit easier after they’ve been created.&lt;/li&gt;
&lt;li&gt;location coordinates (e.g. x, y) are offset from the centre of the viewport
by default. Set &lt;code&gt;centred = FALSE&lt;/code&gt; to disable this behaviour.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Set of functions for combining vanilla grobs, polyclipgrobs and gTree objects.
These functions are mostly extensions of &lt;code&gt;gridGeometry::polyclipgrob()&lt;/code&gt; which
extends the operations to recurse into gTree and polyclipgrob structures to
affect all child objects:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grob_stack()&lt;/code&gt; for simple combination of shapes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grob_intersect()&lt;/code&gt; for shape intersection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grob_union()&lt;/code&gt; for shape union&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grob_minus()&lt;/code&gt; for shape subtraction&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grob_xor()&lt;/code&gt; for shape combination thruogh use of ‘exclusive or’&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Functions for creating units quickly e.g &lt;code&gt;.mm(x)&lt;/code&gt; instead of &lt;code&gt;units(x, &#39;mm&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Verbose printing of vanilla grob, gTree and polyclipgrob objects&lt;/li&gt;
&lt;li&gt;Structured printing of the grid pattern objects available in R4.1.0&lt;/li&gt;
&lt;li&gt;Simple grob coordinate transformations:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grob_translate()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grob_rotate()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Simple viewport transformations:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vp_translate()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vp_rotate()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gp()&lt;/code&gt; is a wrapper around &lt;code&gt;grid::gpar()&lt;/code&gt; which is more friendly for
IDEs which support auto-complete.&lt;/li&gt;
&lt;li&gt;Some helpers for patterns:
&lt;ul&gt;
&lt;li&gt;S3 &lt;code&gt;print&lt;/code&gt; methods with more structured output than &lt;code&gt;grid&lt;/code&gt;’s default&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pattern_create()&lt;/code&gt; is a wrapper around &lt;code&gt;grid::pattern()&lt;/code&gt; where:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;extend = &#39;repeat&#39;&lt;/code&gt; is the default (instead of ‘pad’)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;default.units&lt;/code&gt; are in ‘mm’ (instead of ‘npc’)&lt;/li&gt;
&lt;li&gt;location coordinates (x, y) are offset from the centre of the viewport
by default. Set &lt;code&gt;centred = FALSE&lt;/code&gt; to disable this behaviour.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/ingrid&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/ingrid&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---verbose-grob-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - verbose grob output&lt;/h2&gt;
&lt;p&gt;In the code below, &lt;code&gt;circle&lt;/code&gt; is created with &lt;code&gt;{grid}&lt;/code&gt; and &lt;code&gt;circle2&lt;/code&gt; is created
with &lt;code&gt;{ingrid}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There aren’t any major differences in how this creation works, but look for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;default units for &lt;code&gt;ingrid::circle_grob&lt;/code&gt; are ‘mm’&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpar&lt;/code&gt; parameters are given inline with the grob call (although it is
also possible to pass in a &lt;code&gt;gp&lt;/code&gt; argument)&lt;/li&gt;
&lt;li&gt;by calling &lt;code&gt;ingrid::register_verbose_printing()&lt;/code&gt; the output for &lt;code&gt;circle2&lt;/code&gt;
gives much more detail than the default printing.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(ingrid)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;creating-a-blue-circle-in-grid&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Creating a blue circle in &lt;code&gt;{grid}&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using &amp;#39;grid&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
circle1 &amp;lt;- circleGrob(r = unit(20, &amp;#39;mm&amp;#39;), gp = gpar(fill = &amp;#39;lightblue&amp;#39;))
circle1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; circle[GRID.circle.1]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid.newpage()
grid.draw(circle1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-blue-circle-in-ingrid&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Creating a blue circle in &lt;code&gt;{ingrid}&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using &amp;#39;ingrid&amp;#39; where default units are &amp;#39;mm&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
circle2 &amp;lt;- circle_grob(20, fill = &amp;#39;lightblue&amp;#39;)
circle2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; circle[GRID.circle.2]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enable verbose printing of grobs 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ingrid::register_verbose_printing()
circle2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#&amp;gt; circle [GRID.circle.2]
#&amp;gt;   x=c(sum(0mm, 0.5npc)), y=c(sum(0mm, 0.5npc)), r=c(20mm)
#&amp;gt;   gp: 
#&amp;gt;     fill: lightblue
#&amp;gt;   vp: [GRID.VP.1] default&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid.newpage()
grid.draw(circle2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-and-combining-grobs&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Creating and combining grobs&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(ingrid)
register_verbose_printing()


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create 4 circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c1 &amp;lt;- circle_grob(r = 20, fill = &amp;#39;red&amp;#39;, alpha = 0.3)
grid.newpage(); grid.draw(c1);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c2 &amp;lt;- circle_grob(r = 33, x = 25, fill = &amp;#39;blue&amp;#39;, alpha = 0.3)
grid.newpage(); grid.draw(c2);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c3 &amp;lt;- circle_grob(r = 28, x = -19, y = -20, fill = &amp;#39;lightblue&amp;#39;, col = &amp;#39;transparent&amp;#39;, alpha = 0.3)
grid.newpage(); grid.draw(c3);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-3.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c4 &amp;lt;- circle_grob(r = 2, x = -13, y= 4, fill=&amp;#39;black&amp;#39;, col=&amp;#39;white&amp;#39;)
grid.newpage(); grid.draw(c4);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-4.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Stack some of the circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
i1 &amp;lt;- grob_stack(c1, c2, c4)
grid.newpage(); grid.draw(i1);

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Visualise how the 4th circle overlaps
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage();
grid.draw(i1)
grid.draw(c3)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-5.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Keep just the intersection of the stack of 3 circls and the 4th circle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wug &amp;lt;- ingrid::grob_intersect(i1, c3)
grid.newpage(); grid.draw(wug);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-14-introducing-ingrid_files/figure-html/unnamed-chunk-5-6.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;logo-for-ingrid&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;logo for &lt;code&gt;ingrid&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)
library(ingrid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Parameters for a hex
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
r     &amp;lt;- 100
theta &amp;lt;- seq(30, 360, 60) * pi/180 
x     &amp;lt;- r * cos(theta)
y     &amp;lt;- r * sin(theta)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# a hex polygon
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hex &amp;lt;- polygon_grob(x, y, fill = &amp;#39;black&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an image maskeed by the hex
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
jpg &amp;lt;- jpeg::readJPEG(&amp;quot;./man/figures/ingrid.jpg&amp;quot;)
image &amp;lt;- raster_grob(
  image  = jpg, 
  x      = .mm(-5),
  y      = .mm(-25),
  width  = .mm(2 * 1.0 * r), 
  height = .mm(3 * 1.0 * r),
  mask   = hex
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Position text
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
text &amp;lt;- text_grob(
  label      = &amp;#39;ingrid&amp;#39;,
  x          =  0.25 * r,
  y          = -0.75 * r, 
  rot        = 30,
  just       = 0,
  col        = &amp;#39;white&amp;#39;, 
  fontfamily = &amp;#39;courier&amp;#39;,
  cex        = 4
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw the objects
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid::grid.newpage()
grid::grid.draw(image)
grid::grid.draw(text)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ingrid/logo.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Future&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Include grobs from other sources:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ellipseGrob&lt;/code&gt;, &lt;code&gt;ngonGrob&lt;/code&gt; from &lt;a href=&#34;https://cran.r-project.org/package=gridExtra&#34;&gt;gridExtra&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=gridExtra&#34;&gt;gridExtra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;grid - part of R&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=gridGeometry&#34;&gt;gridGeometry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=polyclip&#34;&gt;polyclip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;sars&#39; - proof-of-concept for running &#39;SAS&#39; DATA and PROC SQL statements in R</title>
      <link>https://coolbutuseless.github.io/2021/07/14/introducing-sars-proof-of-concept-for-running-sas-data-and-proc-sql-statements-in-r/</link>
      <pubDate>Wed, 14 Jul 2021 19:21:50 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/14/introducing-sars-proof-of-concept-for-running-sas-data-and-proc-sql-statements-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;sars&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;sars &lt;img src=&#34;https://coolbutuseless.github.io/img/sars/logo2.png&#34; align=&#34;right&#34; height=&#34;230/&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sars&lt;/code&gt; is an totally useless, very experimental, proof-of-concept, oh-my-god-why package for
executing &lt;a href=&#34;sas.com&#34;&gt;sas&lt;/a&gt; &lt;code&gt;DATA&lt;/code&gt; and &lt;code&gt;PROC SQL&lt;/code&gt; statements in R.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sars::run(code)&lt;/code&gt; to run some code
&lt;ul&gt;
&lt;li&gt;as long as it is only DATA and PROC SQL statements&lt;/li&gt;
&lt;li&gt;and even then, not much of either of those statements is really supported
either.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/sars&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/sars&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(sars)

sars::run(&amp;quot;
  data mytable;
    set &amp;#39;mtcars&amp;#39;;
  run;
  
  
  proc sql;
    SELECT cyl, sum(mpg) as total  FROM mytable
    WHERE am = 1
    GROUP BY cyl
    ORDER BY cyl;
  quit;&amp;quot;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   cyl total
## 1   4 224.6
## 2   6  61.7
## 3   8  30.8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>R v4.1.0 - {grid} graphics new feature - patterns (part 3)</title>
      <link>https://coolbutuseless.github.io/2021/07/03/r-v4.1.0-grid-graphics-new-feature-patterns-part-3/</link>
      <pubDate>Sat, 03 Jul 2021 19:20:10 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/03/r-v4.1.0-grid-graphics-new-feature-patterns-part-3/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduciton&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduciton&lt;/h1&gt;
&lt;p&gt;As of R 4.1.0 there is built-in support for patterns in &lt;code&gt;grid&lt;/code&gt; graphics. There
are 3 types of pattern:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;grid::linearGradient()&lt;/code&gt; for linear colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::radialGradient()&lt;/code&gt; for radial colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::pattern()&lt;/code&gt; repetition of any combination of graphic objects (grobs)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This quick post summarises a few more things which can be done with patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A mask with an alpha channel can be applied to the pattern to create some
softer effects&lt;/li&gt;
&lt;li&gt;Patterns can be defined using:
&lt;ul&gt;
&lt;li&gt;absolute units (like ‘mm’), in which case their rendered size does not
change&lt;/li&gt;
&lt;li&gt;relative units (like ‘npc’) mean that the size and shape of the pattern
renders differently depending on the viewport&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reading list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14 July 2020 &lt;a href=&#34;https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/definitions/definitions.html&#34;&gt;Catching up with R Graphics Gradients, Patterns, Clipping Paths, and Masks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;15 July 2020 &lt;a href=&#34;https://developer.r-project.org/Blog/public/2020/07/15/new-features-in-the-r-graphics-engine/index.html&#34;&gt;New Features in the R Graphics Engine Paul Murrell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ensure that images are rendered using a device which understands patterns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
knitr::opts_chunk$set(dev.args = list(png = list(type = &amp;quot;cairo&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;a-simple-mask&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A simple mask&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create a circle&lt;/li&gt;
&lt;li&gt;use the circl as the mask when drawing a rectangle&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 1. Create a circle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mask &amp;lt;- circleGrob(
  r = unit(23, &amp;#39;mm&amp;#39;),
  gp = gpar(fill=&amp;#39;black&amp;#39;)
)

grid.newpage()
grid.draw(mask)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-03-grid-patterns_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 4. Create a rectangle using the patterned circle as a mask
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(40, &amp;#39;mm&amp;#39;),
  height = unit(40, &amp;#39;mm&amp;#39;),
  gp = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;darkblue&amp;#39;
  ),
  vp = viewport(
    mask = mask
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(small_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-03-grid-patterns_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-mask-can-have-a-pattern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A mask can have a pattern&lt;/h2&gt;
&lt;p&gt;Rather than a mask being just a solid shape or something with an alpha channel,
it is also possible to create a mask which itself contains a pattern.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create a tiny rectangle&lt;/li&gt;
&lt;li&gt;Make a pattern out of the tiny rectangle&lt;/li&gt;
&lt;li&gt;Fill a circle with this tiny rectangle pattern&lt;/li&gt;
&lt;li&gt;Create a rectangle using the patterned circle as a mask&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 1. Create a tiny rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tiny_rect &amp;lt;- rectGrob(
  width  = unit(4, &amp;#39;mm&amp;#39;),
  height = unit(4, &amp;#39;mm&amp;#39;),
  gp = gpar(fill = &amp;#39;pink&amp;#39;)
)

grid.newpage()
grid.draw(tiny_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-03-grid-patterns_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2. Make a pattern out of the tiny rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tiny_rect_pattern &amp;lt;- grid::pattern(
  tiny_rect,
  width  = unit(10, &amp;#39;mm&amp;#39;),
  height = unit(10, &amp;#39;mm&amp;#39;),
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3. Fill a circle with this tiny rectangle pattern 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mask &amp;lt;- circleGrob(
  r = unit(23, &amp;#39;mm&amp;#39;),
  gp = gpar(fill=tiny_rect_pattern)
)

grid.newpage()
grid.draw(mask)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-03-grid-patterns_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 4. Create a rectangle using the patterned circle as a mask
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(40, &amp;#39;mm&amp;#39;),
  height = unit(40, &amp;#39;mm&amp;#39;),
  gp = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;darkblue&amp;#39;
  ),
  vp = viewport(
    mask = mask
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(small_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-03-grid-patterns_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>R v4.1.0 - {grid} graphics new feature - patterns (part 2)</title>
      <link>https://coolbutuseless.github.io/2021/07/02/r-v4.1.0-grid-graphics-new-feature-patterns-part-2/</link>
      <pubDate>Fri, 02 Jul 2021 19:20:10 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/02/r-v4.1.0-grid-graphics-new-feature-patterns-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduciton&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduciton&lt;/h1&gt;
&lt;p&gt;As of R 4.1.0 there is built-in support for patterns in &lt;code&gt;grid&lt;/code&gt; graphics. There
are 3 types of pattern:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;grid::linearGradient()&lt;/code&gt; for linear colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::radialGradient()&lt;/code&gt; for radial colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::pattern()&lt;/code&gt; repetition of any combination of graphic objects (grobs)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This quick post summarises a few things which can be done with patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating a pattern&lt;/li&gt;
&lt;li&gt;a repeating element within a pattern can be masked (another new feature of &lt;code&gt;grid&lt;/code&gt; in R v4.1.0)&lt;/li&gt;
&lt;li&gt;a pattern can itself have a pattern&lt;/li&gt;
&lt;li&gt;a pattern can consist of any objects you can put in a &lt;code&gt;grid::grobTree()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reading list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14 July 2020 &lt;a href=&#34;https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/definitions/definitions.html&#34;&gt;Catching up with R Graphics Gradients, Patterns, Clipping Paths, and Masks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;15 July 2020 &lt;a href=&#34;https://developer.r-project.org/Blog/public/2020/07/15/new-features-in-the-r-graphics-engine/index.html&#34;&gt;New Features in the R Graphics Engine Paul Murrell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ensure that images are rendered using a device which understands patterns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
knitr::opts_chunk$set(dev.args = list(png = list(type = &amp;quot;cairo&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;patterns-can-have-masks-with-an-alpha-channel&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Patterns can have masks with an alpha channel&lt;/h2&gt;
&lt;p&gt;In this example, a simple square is the basis of the repeating pattern.&lt;/p&gt;
&lt;p&gt;The square is then masked with a circle containing a radial gradient which is transparent at the
edges - this has the effect of softening the edges of the square&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a mask
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mask &amp;lt;- circleGrob(
  x = unit(0.5, &amp;#39;npc&amp;#39;) + unit(2.5, &amp;#39;mm&amp;#39;),
  y = unit(0.5, &amp;#39;npc&amp;#39;) + unit(2.5, &amp;#39;mm&amp;#39;),
  r = unit(8, &amp;#39;mm&amp;#39;),
  gp = gpar(fill = radialGradient(c(&amp;#39;black&amp;#39;, &amp;#39;transparent&amp;#39;)), col = &amp;#39;transparent&amp;#39;)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle with some masking
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_with_mask &amp;lt;- rectGrob(
  width  = unit(10, &amp;#39;mm&amp;#39;), 
  height = unit(10, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  ),
  vp = viewport(mask = mask)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Wrap the core element (small_rect_with_mask) inside a pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_with_mask_pattern &amp;lt;- grid::pattern(
  small_rect_with_mask,
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the pattern as a &amp;#39;fill&amp;#39; on another shape
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.5, 
  height = 0.5,
  gp = gpar(fill = small_rect_with_mask_pattern)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-02-grid-patterns_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;patterns-can-be-defined-with-concrete-units&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Patterns can be defined with concrete units&lt;/h2&gt;
&lt;p&gt;When patterns are defined using concrete/absolute units (such as ‘mm’), then
their size is constant regardless of the viewport&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle with size in concrete/absolute units
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(10, &amp;#39;mm&amp;#39;), 
  height = unit(10, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Wrap the core element (small_rect) inside a pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_pattern &amp;lt;- grid::pattern(
  small_rect,
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the pattern as a &amp;#39;fill&amp;#39; on another shape
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.3, 
  height = 0.3,
  gp = gpar(fill = small_rect_pattern),
  vp = viewport(
    x = unit(0.33, &amp;#39;npc&amp;#39;),
    y = unit(0.5 , &amp;#39;npc&amp;#39;)
  )
)

large_rect2 &amp;lt;- rectGrob(
  width  = 0.3, 
  height = 0.6,
  gp = gpar(fill = small_rect_pattern),
  vp = viewport(
    x = unit(0.67, &amp;#39;npc&amp;#39;),
    y = unit(0.5 , &amp;#39;npc&amp;#39;)
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)
grid.draw(large_rect2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-02-grid-patterns_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;patterns-can-be-defined-with-relative-units&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Patterns can be defined with relative units&lt;/h2&gt;
&lt;p&gt;When patterns are defined using relatives units (such as ‘npc’), then
their apparent size depends on the viewport they’re rendered into.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle with size in relative units &amp;#39;npc&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(0.1, &amp;#39;npc&amp;#39;), 
  height = unit(0.1, &amp;#39;npc&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Wrap the core element (small_rect) inside a pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_pattern &amp;lt;- grid::pattern(
  small_rect,
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the pattern as a &amp;#39;fill&amp;#39; on another shape
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.3, 
  height = 0.3,
  gp = gpar(fill = small_rect_pattern),
  vp = viewport(
    x = unit(0.33, &amp;#39;npc&amp;#39;),
    y = unit(0.5 , &amp;#39;npc&amp;#39;)
  )
)

large_rect2 &amp;lt;- rectGrob(
  width  = 0.3, 
  height = 0.6,
  gp = gpar(fill = small_rect_pattern),
  vp = viewport(
    x = unit(0.67, &amp;#39;npc&amp;#39;),
    y = unit(0.5 , &amp;#39;npc&amp;#39;)
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)
grid.draw(large_rect2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-02-grid-patterns_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>R v4.1.0 - {grid} graphics new feature - patterns</title>
      <link>https://coolbutuseless.github.io/2021/07/01/r-v4.1.0-grid-graphics-new-feature-patterns/</link>
      <pubDate>Thu, 01 Jul 2021 21:20:10 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/07/01/r-v4.1.0-grid-graphics-new-feature-patterns/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduciton&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduciton&lt;/h1&gt;
&lt;p&gt;As of R 4.1.0 there is built-in support for patterns in &lt;code&gt;grid&lt;/code&gt; graphics. There
are 3 types of pattern:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;grid::linearGradient()&lt;/code&gt; for linear colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::radialGradient()&lt;/code&gt; for radial colour gradients&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid::pattern()&lt;/code&gt; repetition of any combination of graphic objects (grobs)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This quick post summarises a few things which can be done with patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating a pattern&lt;/li&gt;
&lt;li&gt;a repeating element within a pattern can be masked (another new feature of &lt;code&gt;grid&lt;/code&gt; in R v4.1.0)&lt;/li&gt;
&lt;li&gt;a pattern can itself have a pattern&lt;/li&gt;
&lt;li&gt;a pattern can consist of any objects you can put in a &lt;code&gt;grid::grobTree()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reading list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14 July 2020 &lt;a href=&#34;https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/definitions/definitions.html&#34;&gt;Catching up with R Graphics Gradients, Patterns, Clipping Paths, and Masks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;15 July 2020 &lt;a href=&#34;https://developer.r-project.org/Blog/public/2020/07/15/new-features-in-the-r-graphics-engine/index.html&#34;&gt;New Features in the R Graphics Engine Paul Murrell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(grid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ensure that images are rendered using a device which understands patterns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
knitr::opts_chunk$set(dev.args = list(png = list(type = &amp;quot;cairo&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;define-the-core-element-of-the-pattern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Define the core element of the pattern&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(10, &amp;#39;mm&amp;#39;), 
  height = unit(10, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(small_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-01-grid-patterns_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-pattern-by-wrapping-the-core-element-in-gridpattern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a pattern by wrapping the core element in &lt;code&gt;grid::pattern()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Wrap the core element (small_rect) inside a pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_pattern &amp;lt;- grid::pattern(
  small_rect,
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the pattern as a &amp;#39;fill&amp;#39; on another shape
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.5, 
  height = 0.5,
  gp = gpar(fill = small_rect_pattern)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-01-grid-patterns_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;patterns-can-have-masks&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Patterns can have masks&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a mask
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mask &amp;lt;- circleGrob(
  x = unit(0.5, &amp;#39;npc&amp;#39;) + unit(2.5, &amp;#39;mm&amp;#39;),
  y = unit(0.5, &amp;#39;npc&amp;#39;) + unit(2.5, &amp;#39;mm&amp;#39;),
  r = unit(4, &amp;#39;mm&amp;#39;),
  gp = gpar(fill = &amp;#39;black&amp;#39;)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle with some masking
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_with_mask &amp;lt;- rectGrob(
  width  = unit(10, &amp;#39;mm&amp;#39;), 
  height = unit(10, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  ),
  vp = viewport(mask = mask)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Wrap the core element (small_rect_with_mask) inside a pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect_with_mask_pattern &amp;lt;- grid::pattern(
  small_rect_with_mask,
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the pattern as a &amp;#39;fill&amp;#39; on another shape
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.5, 
  height = 0.5,
  gp = gpar(fill = small_rect_with_mask_pattern)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-01-grid-patterns_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern---patterns-can-have-patterns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pattern - Patterns can have patterns&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define an inner pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
inner_pattern_element &amp;lt;- circleGrob(
  r  = unit(5, &amp;#39;mm&amp;#39;), 
  gp     = gpar(
    fill = &amp;#39;pink&amp;#39;, 
    col  = &amp;#39;red&amp;#39;
  )
)

inner_pattern &amp;lt;- grid::pattern(
  inner_pattern_element,
  width  = unit(12, &amp;#39;mm&amp;#39;),
  height = unit(12, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define an outer pattern which is filled with the inner pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
outer_pattern_element &amp;lt;- polygonGrob(
  x = unit(0.5, &amp;#39;npc&amp;#39;) + unit(c(0, 20, 20) - 10, &amp;#39;mm&amp;#39;),
  y = unit(0.5, &amp;#39;npc&amp;#39;) + unit(c(0,  0, 20) - 10, &amp;#39;mm&amp;#39;),
  gp = gpar(fill = inner_pattern, col = &amp;#39;blue&amp;#39;)
)

outer_pattern &amp;lt;- grid::pattern(
  outer_pattern_element,
  width  = unit(30, &amp;#39;mm&amp;#39;),
  height = unit(30, &amp;#39;mm&amp;#39;), 
  extend = &amp;#39;reflect&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fill a &amp;#39;rect&amp;#39; with the outer pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.5, 
  height = 0.5,
  gp = gpar(fill = outer_pattern)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-01-grid-patterns_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern---patterns-can-contain-multiple-objects&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pattern - Patterns can contain multiple objects&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_rect &amp;lt;- rectGrob(
  width  = unit(10, &amp;#39;mm&amp;#39;), 
  height = unit(10, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;lightblue&amp;#39;, 
    col  = &amp;#39;blue&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a small circle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
small_circle &amp;lt;- circleGrob(
  x = unit(0.5, &amp;#39;npc&amp;#39;) + unit(3, &amp;#39;mm&amp;#39;),
  y = unit(0.5, &amp;#39;npc&amp;#39;) + unit(3, &amp;#39;mm&amp;#39;),
  r  = unit(4, &amp;#39;mm&amp;#39;),
  gp     = gpar(
    fill = &amp;#39;pink&amp;#39;, 
    col  = &amp;#39;red&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Creat a compound pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compound_pattern &amp;lt;- pattern(
  grobTree(small_rect, small_circle),
  width  = unit(15, &amp;#39;mm&amp;#39;),
  height = unit(15, &amp;#39;mm&amp;#39;),
  extend = &amp;#39;repeat&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fill a &amp;#39;rect&amp;#39; with the compound pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
large_rect &amp;lt;- rectGrob(
  width  = 0.5, 
  height = 0.5,
  gp = gpar(fill = compound_pattern)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
grid.draw(large_rect)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-07-01-grid-patterns_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {gluestick} - a simple, base R, single function, glue-like string interpolator</title>
      <link>https://coolbutuseless.github.io/2021/06/04/introducing-gluestick-a-simple-base-r-single-function-glue-like-string-interpolator/</link>
      <pubDate>Fri, 04 Jun 2021 21:22:20 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/06/04/introducing-gluestick-a-simple-base-r-single-function-glue-like-string-interpolator/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;gluestick&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;gluestick&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/gluestick/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/gluestick/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R-CMD-check&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The goal of the &lt;code&gt;gluestick&lt;/code&gt; package is to provide a home for a single, simple function
(also named &lt;code&gt;gluestick&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;gluestick()&lt;/code&gt; function is meant to be an almost drop-in replacement
for 99.9% of the reasons I use the amazing &lt;a href=&#34;https://cran.r-project.org/package=glue&#34;&gt;&lt;code&gt;glue&lt;/code&gt;&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;The idea is that you would just steal the function out of this package and use
it in your own package in order to avoid having &lt;a href=&#34;https://cran.r-project.org/package=glue&#34;&gt;&lt;code&gt;glue&lt;/code&gt;&lt;/a&gt;
as a dependency.&lt;/p&gt;
&lt;div id=&#34;benefits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benefits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Single function&lt;/li&gt;
&lt;li&gt;No dependencies&lt;/li&gt;
&lt;li&gt;No C code&lt;/li&gt;
&lt;li&gt;Vanilla base R code (easy to hack upon)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There is no special handling when delimiters are repeated. This differs from
&lt;code&gt;glue&lt;/code&gt; where doubling the delimiter escpaes it.&lt;/li&gt;
&lt;li&gt;No support for glue’s idea of data transformers&lt;/li&gt;
&lt;li&gt;Far fewer sanity checks than glue&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/gluestick&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/gluestick&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In reality, I can’t see anyone actually wanting to install/use this package
in preference to the glue package.&lt;/p&gt;
&lt;p&gt;What I envisage is that if you want something “glue-like” to include in your
own work, you can just steal the &lt;code&gt;gluestick()&lt;/code&gt; function out of this package
and include it in your own package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic Usage&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(gluestick)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# By default, `src` data is the calling environment
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
name &amp;lt;- &amp;#39;Mike&amp;#39;
gluestick(&amp;quot;Hello {name}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Hello Mike&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# R code will be evaluated
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gluestick(&amp;quot;Hello {name}. Score = {1 + 2}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Hello Mike. Score = 3&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Can pass in a list, data.frame, environment etc as the data source to 
# override the default
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gluestick(&amp;quot;Hello {name}&amp;quot;, src = list(name = &amp;#39;#RStats&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Hello #RStats&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Delimiters are user-definable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gluestick(&amp;quot;Hello ~~!name]]?&amp;quot;, open = &amp;quot;~~!&amp;quot;, close = &amp;quot;]]?&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Hello Mike&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Functionality is heavily modelled on &lt;a href=&#34;https://cran.r-project.org/package=glue&#34;&gt;&lt;code&gt;glue&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Package Development Update</title>
      <link>https://coolbutuseless.github.io/2021/04/01/package-development-update/</link>
      <pubDate>Thu, 01 Apr 2021 21:20:02 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/04/01/package-development-update/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;package-development-update&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Package Development Update&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(x=c(1.8, 4.2), y=c(0, 1), type = &amp;#39;n&amp;#39;, xlab = &amp;#39;Time&amp;#39;, ylab = &amp;#39;Ideas&amp;#39;, axes = F)

N &amp;lt;- 1000
x &amp;lt;- numeric(N)
x[1] &amp;lt;- 0.5

for (r in seq(2.4, 4, length.out = 3000)) {
  for (i in seq(N-1)) {
    x[i+1] &amp;lt;- r * x[i] * (1 - x[i])
  }

  y &amp;lt;- unique(x[900:1000])
  points(rep(r, length(y)), y, pch = &amp;#39;.&amp;#39;, col = &amp;#39;#00000030&amp;#39;)

}

title(&amp;quot;Current Package Project in #RStats&amp;quot;)
text(1.8, 0.58, pos = 4, &amp;quot;How it started&amp;quot;, col = &amp;#39;navy&amp;#39;)
text(4.1, 0.1, pos = 4, srt = 90, &amp;quot;How it&amp;#39;s going&amp;quot;, col = &amp;#39;tomato&amp;#39;, cex = 2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-04-01-bifurcation_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;960&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;fugly&#39; - fast regular expression substring extraction with named capture groups</title>
      <link>https://coolbutuseless.github.io/2021/03/19/introducing-fugly-fast-regular-expression-substring-extraction-with-named-capture-groups/</link>
      <pubDate>Fri, 19 Mar 2021 22:50:02 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/03/19/introducing-fugly-fast-regular-expression-substring-extraction-with-named-capture-groups/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;fugly&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;fugly &lt;img src=&#34;https://coolbutuseless.github.io/img/fugly/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;&lt;/p&gt;
&lt;!-- badges: end --&gt;
&lt;p&gt;This package provides a single function (&lt;code&gt;str_capture&lt;/code&gt;) for using named capture groups to extract values from strings. This function is just a wrapper around &lt;a href=&#34;https://cran.r-project.org/package=stringr&#34;&gt;stringr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fugly::str_capture()&lt;/code&gt; is very similar to both
&lt;a href=&#34;https://cran.r-project.org/web/packages/unglue/index.html&#34;&gt;unglue&lt;/a&gt;
and &lt;code&gt;utils::strcapture()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This package was written because &lt;code&gt;stringr&lt;/code&gt; doesn’t yet do named capture groups
(See issues for &lt;a href=&#34;https://github.com/tidyverse/stringr/issues/71&#34;&gt;stringr&lt;/a&gt; and
&lt;a href=&#34;https://github.com/gagolews/stringi/issues/153&#34;&gt;stringi&lt;/a&gt;), and I needed something
faster than &lt;a href=&#34;https://cran.r-project.org/web/packages/unglue/index.html&#34;&gt;unglue&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;14%&#34; /&gt;
&lt;col width=&#34;26%&#34; /&gt;
&lt;col width=&#34;26%&#34; /&gt;
&lt;col width=&#34;31%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;fugly::str_capture&lt;/th&gt;
&lt;th&gt;unglue:::unglue&lt;/th&gt;
&lt;th&gt;utils::strcapture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Speed&lt;/td&gt;
&lt;td&gt;fastest&lt;/td&gt;
&lt;td&gt;slow&lt;/td&gt;
&lt;td&gt;faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Naming Groups&lt;/td&gt;
&lt;td&gt;inline capture group naming&lt;/td&gt;
&lt;td&gt;inline capture group naming&lt;/td&gt;
&lt;td&gt;use of prototype to define names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Safe + Robust?&lt;/td&gt;
&lt;td&gt;dodgy&lt;/td&gt;
&lt;td&gt;quite safe&lt;/td&gt;
&lt;td&gt;quite safe&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;what-do-i-mean-when-i-say-fuglystr_capture-is-unsafedodgynon-robust&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What do I mean when I say &lt;code&gt;fugly::str_capture()&lt;/code&gt; is unsafe/dodgy/non-robust?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It doesn’t adhere to standard regular expression syntax for named capture
groups as used in perl, python etc.&lt;/li&gt;
&lt;li&gt;It doesn’t really adhere to &lt;code&gt;glue&lt;/code&gt; syntax (although it looks similar at a surface level).&lt;/li&gt;
&lt;li&gt;If you specify delimiters which appear in your string input, then you’re going
to have a bad time.&lt;/li&gt;
&lt;li&gt;It’s generally only been tested on data which is:
&lt;ul&gt;
&lt;li&gt;highly structured&lt;/li&gt;
&lt;li&gt;only ASCII&lt;/li&gt;
&lt;li&gt;non-pathological&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What’s in the box?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fugly::str_capture(string, pattern, delim)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;capture named groups with regular expressions&lt;/li&gt;
&lt;li&gt;returns a data.frame with all columns containing character strings&lt;/li&gt;
&lt;li&gt;can mix-and-match with non-capturing regular expressions&lt;/li&gt;
&lt;li&gt;if no regular expression specified for a named group then &lt;code&gt;.*?&lt;/code&gt; is used.&lt;/li&gt;
&lt;li&gt;does not do any type guessing/conversion.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/fugly&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/fugly&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 1&lt;/h2&gt;
&lt;p&gt;In the following example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Input consists of multiple strings&lt;/li&gt;
&lt;li&gt;capture groups are delimited by &lt;code&gt;{}&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;the regex for the capture group for &lt;code&gt;name&lt;/code&gt; is unspecified, so &lt;code&gt;.*?&lt;/code&gt; will be used&lt;/li&gt;
&lt;li&gt;the regex for the capture group for &lt;code&gt;age&lt;/code&gt; is &lt;code&gt;\d+&lt;/code&gt; i.e. match must consist
of 1-or-more digits&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(fugly)

string &amp;lt;- c(
  &amp;quot;information: Name:greg Age:27 &amp;quot;,
  &amp;quot;information: Name:mary Age:34 &amp;quot;
)

str_capture(string, pattern = &amp;quot;Name:{name} Age:{age=\\d+}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   name age
## 1 greg  27
## 2 mary  34&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 2&lt;/h2&gt;
&lt;p&gt;A more complicated example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Note the mixture of capturing groups and a bare &lt;code&gt;.*?&lt;/code&gt; in the pattern which is not returned as a result&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;string &amp;lt;- c(
&amp;#39;{&amp;quot;type&amp;quot;:&amp;quot;Feature&amp;quot;,&amp;quot;properties&amp;quot;:{&amp;quot;hash&amp;quot;:&amp;quot;1348778913c0224a&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;27&amp;quot;,&amp;quot;street&amp;quot;:&amp;quot;BANAMBILA STREET&amp;quot;,&amp;quot;unit&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;city&amp;quot;:&amp;quot;ARANDA&amp;quot;,&amp;quot;district&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;region&amp;quot;:&amp;quot;ACT&amp;quot;,&amp;quot;postcode&amp;quot;:&amp;quot;2614&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;GAACT714851647&amp;quot;},&amp;quot;geometry&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;Point&amp;quot;,&amp;quot;coordinates&amp;quot;:[149.0826143,-35.2545558]}}&amp;#39;,
&amp;#39;{&amp;quot;type&amp;quot;:&amp;quot;Feature&amp;quot;,&amp;quot;properties&amp;quot;:{&amp;quot;hash&amp;quot;:&amp;quot;dc776871c868bc7e&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;139&amp;quot;,&amp;quot;street&amp;quot;:&amp;quot;BOUVERIE STREET&amp;quot;,&amp;quot;unit&amp;quot;:&amp;quot;UNIT 711&amp;quot;,&amp;quot;city&amp;quot;:&amp;quot;CARLTON&amp;quot;,&amp;quot;district&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;region&amp;quot;:&amp;quot;VIC&amp;quot;,&amp;quot;postcode&amp;quot;:&amp;quot;3053&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;GAVIC423944917&amp;quot;},&amp;quot;geometry&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;Point&amp;quot;,&amp;quot;coordinates&amp;quot;:[144.9617149,-37.8032551]}}&amp;#39;,
&amp;#39;{&amp;quot;type&amp;quot;:&amp;quot;Feature&amp;quot;,&amp;quot;properties&amp;quot;:{&amp;quot;hash&amp;quot;:&amp;quot;8197f34a40ccad47&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;6&amp;quot;,&amp;quot;street&amp;quot;:&amp;quot;MOGRIDGE STREET&amp;quot;,&amp;quot;unit&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;city&amp;quot;:&amp;quot;WARWICK&amp;quot;,&amp;quot;district&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;region&amp;quot;:&amp;quot;QLD&amp;quot;,&amp;quot;postcode&amp;quot;:&amp;quot;4370&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;GAQLD155949502&amp;quot;},&amp;quot;geometry&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;Point&amp;quot;,&amp;quot;coordinates&amp;quot;:[152.0230999,-28.2230133]}}&amp;#39;,
&amp;#39;{&amp;quot;type&amp;quot;:&amp;quot;Feature&amp;quot;,&amp;quot;properties&amp;quot;:{&amp;quot;hash&amp;quot;:&amp;quot;18edc96308fc1a8e&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;22&amp;quot;,&amp;quot;street&amp;quot;:&amp;quot;ORR STREET&amp;quot;,&amp;quot;unit&amp;quot;:&amp;quot;UNIT 507&amp;quot;,&amp;quot;city&amp;quot;:&amp;quot;CARLTON&amp;quot;,&amp;quot;district&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;region&amp;quot;:&amp;quot;VIC&amp;quot;,&amp;quot;postcode&amp;quot;:&amp;quot;3053&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;GAVIC424282716&amp;quot;},&amp;quot;geometry&amp;quot;:{&amp;quot;type&amp;quot;:&amp;quot;Point&amp;quot;,&amp;quot;coordinates&amp;quot;:[144.9653484,-37.8063371]}}&amp;#39;
)


str_capture(string, pattern = &amp;#39;&amp;quot;number&amp;quot;:&amp;quot;{number}&amp;quot;,&amp;quot;street&amp;quot;:&amp;quot;{street}&amp;quot;.*?&amp;quot;coordinates&amp;quot;:\\[{coords}\\]&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   number           street                  coords
## 1     27 BANAMBILA STREET 149.0826143,-35.2545558
## 2    139  BOUVERIE STREET 144.9617149,-37.8032551
## 3      6  MOGRIDGE STREET 152.0230999,-28.2230133
## 4     22       ORR STREET 144.9653484,-37.8063371&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple Benchmark&lt;/h2&gt;
&lt;p&gt;I acknowledge that this isn’t the greatest benchmark, but it is relevant to my
current use-case.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For large inputs (1000+ input strings), &lt;code&gt;fugly&lt;/code&gt; is the fastest&lt;/li&gt;
&lt;li&gt;For small inputs, &lt;code&gt;fugly&lt;/code&gt; and &lt;code&gt;utils::strcapture&lt;/code&gt; are about equivalent&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unglue&lt;/code&gt; is the slowest of the methods.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ore&lt;/code&gt; lies somewhere between &lt;code&gt;unglue&lt;/code&gt; and &lt;code&gt;utils::strcapture&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# remotes::install_github(&amp;quot;jonclayden/ore&amp;quot;)
library(ore)
library(unglue)
library(ggplot2)

# meaningless strings for benchmarking
string &amp;lt;- paste0(&amp;quot;Information name:greg age:&amp;quot;, 1:1000)

res &amp;lt;- bench::mark(
  `fugly::str_capture()` = fugly::str_capture(string, &amp;quot;name:{name} age:{age=\\d+}&amp;quot;),
  `unglue::unglue()` = unglue::unglue_data(string, &amp;quot;Information name:{name} age:{age=\\d+}&amp;quot;),
  `utils::strcapture()` = utils::strcapture(&amp;quot;Information name:(.*?) age:(\\d+)&amp;quot;, string, 
                    proto = data.frame(name=character(), age=character())),
  `ore::ore_search()` = do.call(rbind.data.frame, lapply(ore_search(ore(&amp;#39;name:(?&amp;lt;name&amp;gt;.*?) age:(?&amp;lt;age&amp;gt;\\d+)&amp;#39;, encoding=&amp;#39;utf8&amp;#39;), string, all=TRUE), function(x) {x$groups$matches}))
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-03-19-introducing-fugly_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=stringr&#34;&gt;stringr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;utils::strcapture()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;%5Bunglue%5D(https://cran.r-project.org/web/packages/unglue/index.html)&#34;&gt;unglue::unglue()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jonclayden/ore&#34;&gt;ore&lt;/a&gt;, &lt;a href=&#34;https://cran.r-project.org/package=ore&#34;&gt;ore on CRAN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>On &#39;on.exit()&#39; - Part 2</title>
      <link>https://coolbutuseless.github.io/2021/03/12/on-on.exit-part-2/</link>
      <pubDate>Fri, 12 Mar 2021 08:22:02 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/03/12/on-on.exit-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;on.exit()&lt;/code&gt; is a base R function which records expressions to evaluate when
the current function exits.&lt;/p&gt;
&lt;p&gt;I was wanting to use &lt;code&gt;on.exit()&lt;/code&gt; in a function that was allocating some resources,
and I explicitly wanted these resources freed in the &lt;em&gt;reverse&lt;/em&gt; order.&lt;/p&gt;
&lt;p&gt;Working out how to do what I wanted was easy (discussed below), but it lead
me down a path of discovery as I tried to figure out just exactly where and when
the &lt;code&gt;on.exit()&lt;/code&gt; expressions were being executed.&lt;/p&gt;
&lt;p&gt;Yesterday I &lt;a href=&#34;https://coolbutuseless.github.io/2021/03/12/on-on.exit/&#34;&gt;posted some code snippets&lt;/a&gt;
from this exploration.&lt;/p&gt;
&lt;p&gt;This is a follow-up post with some more notes&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;capture-variable-values-at-time-of-on.exit-creation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Capture variable values at time of &lt;code&gt;on.exit()&lt;/code&gt; creation&lt;/h2&gt;
&lt;p&gt;The following code shows that, by default, values in the &lt;code&gt;on.exit()&lt;/code&gt; expression
are evaluated &lt;em&gt;as the function exits&lt;/em&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(cat(&amp;quot;a =&amp;quot;, a, &amp;quot; b =&amp;quot;, b, &amp;quot;\n&amp;quot;))
  a &amp;lt;- a + 1
  b &amp;lt;- b + 1
  a + b
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## a = 2  b = 3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However sometimes you might like the &lt;code&gt;on.exit()&lt;/code&gt; expression to capture the
current values of the variables at the time the &lt;code&gt;on.exit()&lt;/code&gt; expression was
captured.&lt;/p&gt;
&lt;p&gt;The docs suggest using &lt;code&gt;substitute()&lt;/code&gt; to do this. I’m not sure if the following is
exactly what the docs are suggesting, but this works:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  eval(substitute(on.exit(cat(&amp;quot;a =&amp;quot;, a, &amp;quot; b =&amp;quot;, b, &amp;quot;\n&amp;quot;))))
  a &amp;lt;- a + 1
  b &amp;lt;- b + 1
  a + b
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## a = 1  b = 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;make-a-function-callable-only-once-by-removing-the-function-from-the-calling-environment&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Make a function callable only once by removing the function from the calling environment&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/antoine_fabri&#34;&gt;Antoine Fabri&lt;/a&gt; in his &lt;a href=&#34;https://github.com/moodymudskipper/once/blob/master/R/pb_for.R&#34;&gt;{once}&lt;/a&gt;
package uses &lt;code&gt;on.exit()&lt;/code&gt; to remove some functions from the calling environment
after they are run for the first (and only!) time.&lt;/p&gt;
&lt;p&gt;The following code is a small recreation of this functionality i.e. the
function can be called once, and is then removed from the calling environment.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function() {
  on.exit(rm(&amp;#39;f&amp;#39;, envir = parent.frame()))
  print(&amp;quot;In the function&amp;quot;)
}

f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;In the function&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Error in f(): could not find function &amp;quot;f&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;on.exit-in-nested-functions---abnormal-exit-with-stop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;on.exit()&lt;/code&gt; in nested functions - abnormal exit with &lt;code&gt;stop()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Nested functions - each with their own &lt;code&gt;on.exit()&lt;/code&gt; - will trigger the evaluation
of the captured exit expressions when a &lt;code&gt;stop()&lt;/code&gt; is called in the innermost
function. The &lt;code&gt;on.exit()&lt;/code&gt; expressions are evaluated from most deeply nested function
out to the initial outer function call.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;fa &amp;lt;- function() {on.exit(print(&amp;quot;Exit fa()&amp;quot;)); stop(&amp;quot;Bang!&amp;quot;)}
fb &amp;lt;- function() {on.exit(print(&amp;quot;Exit fb()&amp;quot;)); fa()}
fc &amp;lt;- function() {on.exit(print(&amp;quot;Exit fc()&amp;quot;)); fb()}

fc()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Error in fa(): Bang!&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Exit fa()&amp;quot;
## [1] &amp;quot;Exit fb()&amp;quot;
## [1] &amp;quot;Exit fc()&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;on.exit-in-nested-functions---abnormal-exit-with-kill-signals.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;on.exit()&lt;/code&gt; in nested functions - abnormal exit with &lt;code&gt;kill&lt;/code&gt; signals.&lt;/h2&gt;
&lt;p&gt;For those familiar with sending signals to processes, &lt;code&gt;on.exit()&lt;/code&gt; code
may or may not be run when signals are sent.&lt;/p&gt;
&lt;p&gt;A common way to send a signal on Unix or MacOS is with the &lt;code&gt;kill&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;My tests on MacOS with some common signals, show that R only executes the captured &lt;code&gt;on.exit()&lt;/code&gt; expressions
when sent a SIGINT (equivalent to hitting CTRL-C).&lt;/p&gt;
&lt;p&gt;Many other signals caused R to terminate completely without the &lt;code&gt;on.exit()&lt;/code&gt; registered expressions
being evaluated.&lt;/p&gt;
&lt;p&gt;Other signals had zero noticeable effect.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>On &#39;on.exit()&#39;</title>
      <link>https://coolbutuseless.github.io/2021/03/12/on-on.exit/</link>
      <pubDate>Fri, 12 Mar 2021 08:21:10 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/03/12/on-on.exit/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;on.exit()&lt;/code&gt; is a base R function which records expressions to evaluate when
the current function exits.&lt;/p&gt;
&lt;p&gt;I was wanting to use &lt;code&gt;on.exit()&lt;/code&gt; in a function that was allocating some resources,
and I explicitly wanted these resources freed in the &lt;em&gt;reverse&lt;/em&gt; order.&lt;/p&gt;
&lt;p&gt;Working out how to do what I wanted was easy (discussed below), but it lead
me down a path of discovery as I tried to figure out just exactly where and when
the &lt;code&gt;on.exit()&lt;/code&gt; expressions were being executed.&lt;/p&gt;
&lt;p&gt;Below are some of my code snippets from this exploration.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple usage&lt;/h2&gt;
&lt;p&gt;The following simple code shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;on.exit()&lt;/code&gt; call can appear anywhere in the function&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;on.exit()&lt;/code&gt; expression is evaluated after the function budy is complete
i.e. after the return statement.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(print(&amp;quot;on.exit() called&amp;quot;))
  print(&amp;quot;Function finished, returning value&amp;quot;)
  return(a + b)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Function finished, returning value&amp;quot;
## [1] &amp;quot;on.exit() called&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;multiple-on.exit-statements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Multiple &lt;code&gt;on.exit()&lt;/code&gt; statements&lt;/h2&gt;
&lt;p&gt;The following code shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;on.exit()&lt;/code&gt; call can appear multiple times in the function&lt;/li&gt;
&lt;li&gt;by using &lt;code&gt;add = TRUE&lt;/code&gt;, the expression is added to any prior expressions&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(print(&amp;quot;on.exit() called 1&amp;quot;))
  result &amp;lt;- a + b
  on.exit(print(&amp;quot;on.exit() called 2&amp;quot;), add = TRUE)
  print(&amp;quot;Function finished, returning value&amp;quot;)
  return(result)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Function finished, returning value&amp;quot;
## [1] &amp;quot;on.exit() called 1&amp;quot;
## [1] &amp;quot;on.exit() called 2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;multiple-on.exit-statements-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Multiple &lt;code&gt;on.exit()&lt;/code&gt; statements&lt;/h2&gt;
&lt;p&gt;The following code shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;on.exit()&lt;/code&gt; call can appear multiple times in the function&lt;/li&gt;
&lt;li&gt;by using &lt;code&gt;add = TRUE&lt;/code&gt;, the expression is added to any prior expressions&lt;/li&gt;
&lt;li&gt;by using &lt;code&gt;after = FALSE&lt;/code&gt;, the expression is added &lt;em&gt;before&lt;/em&gt; any any prior expressions&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(print(&amp;quot;on.exit() called 1&amp;quot;))
  result &amp;lt;- a + b
  on.exit(print(&amp;quot;on.exit() called 2&amp;quot;), add = TRUE, after = FALSE)
  print(&amp;quot;Function finished, returning value&amp;quot;)
  return(result)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Function finished, returning value&amp;quot;
## [1] &amp;quot;on.exit() called 2&amp;quot;
## [1] &amp;quot;on.exit() called 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-evaluation-environment-for-on.exit-has-access-to-function-variables&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The evaluation environment for &lt;code&gt;on.exit()&lt;/code&gt; has access to function variables&lt;/h2&gt;
&lt;p&gt;The evaulation environment where the &lt;code&gt;on.exit()&lt;/code&gt; expressions are a run has access
to variables within the function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(cat(&amp;quot;The numbers were &amp;quot;, a, &amp;quot; and &amp;quot;, b, &amp;quot;\n&amp;quot;))
  return(a + b)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## The numbers were  1  and  2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The variables aren’t explicitly captured when then &lt;code&gt;on.exit()&lt;/code&gt; expression is
registered, so the variable values will be those at the end of the function evaluation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(cat(&amp;quot;The numbers were &amp;quot;, a, &amp;quot; and &amp;quot;, b, &amp;quot;\n&amp;quot;))
  a &amp;lt;- a + 1
  b &amp;lt;- b + 1
  return(a + b)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## The numbers were  2  and  3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;viewing-the-expressions-registered-via-on.exit&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Viewing the expressions registered via &lt;code&gt;on.exit()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;It is possible to view the expressions that have been registered with &lt;code&gt;on.exit()&lt;/code&gt; during
a function call by calling &lt;code&gt;sys.on.exit()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(print(&amp;quot;on.exit() called 1&amp;quot;))
  result &amp;lt;- a + b
  on.exit(print(&amp;quot;on.exit() called 2&amp;quot;), add = TRUE, after = FALSE)
  print(sys.on.exit())
  print(&amp;quot;Function finished, returning value&amp;quot;)
  return(result)
}

f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## {
##     print(&amp;quot;on.exit() called 2&amp;quot;)
##     print(&amp;quot;on.exit() called 1&amp;quot;)
## }
## [1] &amp;quot;Function finished, returning value&amp;quot;
## [1] &amp;quot;on.exit() called 2&amp;quot;
## [1] &amp;quot;on.exit() called 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is even possible to return the &lt;code&gt;on.exit()&lt;/code&gt; expressions for later evaluation
in a different context.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit(print(&amp;quot;on.exit() called 1&amp;quot;))
  result &amp;lt;- a + b
  on.exit(print(&amp;quot;on.exit() called 2&amp;quot;), add = TRUE, after = FALSE)
  return(sys.on.exit())
}

# capture the returned on.exit() expressions
exp &amp;lt;- f(1, 2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;on.exit() called 2&amp;quot;
## [1] &amp;quot;on.exit() called 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;exp&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## {
##     print(&amp;quot;on.exit() called 2&amp;quot;)
##     print(&amp;quot;on.exit() called 1&amp;quot;)
## }&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Evaluate the returned on.exit() expressions
eval(exp)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;on.exit() called 2&amp;quot;
## [1] &amp;quot;on.exit() called 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;can-you-use-on.exit-within-an-on.exit-attempt-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Can you use &lt;code&gt;on.exit()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;? Attempt 1&lt;/h2&gt;
&lt;p&gt;In the following code, I attempt to ask &lt;code&gt;on.exit()&lt;/code&gt; to try and execute &lt;em&gt;another&lt;/em&gt;
&lt;code&gt;on.exit()&lt;/code&gt; during the evaluation of the &lt;code&gt;on.exit()&lt;/code&gt; expressions.&lt;/p&gt;
&lt;p&gt;This does not work. Only the first &lt;code&gt;on.exit()&lt;/code&gt; expression is evaluated.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function() {
  on.exit({print(&amp;quot;hello 1&amp;quot;)})
  on.exit(on.exit(print(&amp;#39;hello 2&amp;#39;)), add = TRUE)
}

f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;hello 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;can-you-use-on.exit-within-an-on.exit-attempt-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Can you use &lt;code&gt;on.exit()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;? Attempt 2&lt;/h2&gt;
&lt;p&gt;You can sort of make this work by setting up another function context in the
&lt;code&gt;on.exit()&lt;/code&gt; expression, but nesting &lt;code&gt;on.exit()&lt;/code&gt; calls this way doesn’t really
do anything that regular usage doesn’t already do.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function() {
  on.exit(print(&amp;quot;hello 1&amp;quot;))
  on.exit((function() {on.exit(print(&amp;quot;hello 2&amp;quot;))})(), add = TRUE)
}

f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;hello 1&amp;quot;
## [1] &amp;quot;hello 2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;can-you-use-on.exit-within-an-on.exit-attempt-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Can you use &lt;code&gt;on.exit()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;? Attempt 3&lt;/h2&gt;
&lt;p&gt;It’s interesting to note that &lt;code&gt;on.exit()&lt;/code&gt; expressions are evaluated at the end
of code created via an &lt;code&gt;eval(parse(...))&lt;/code&gt; statement. i.e.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(parse(text=&amp;quot;on.exit(print(&amp;#39;hello&amp;#39;))&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;hello&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So it is possible to get an &lt;code&gt;on.exit()&lt;/code&gt; to evaluate within the context of
a different &lt;code&gt;on.exit()&lt;/code&gt; - but I can’t see an application for this behaviour.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function() {
  on.exit(print(&amp;quot;hello 1&amp;quot;))
  on.exit(eval(parse(text=&amp;quot;on.exit(print(&amp;#39;hello 2&amp;#39;))&amp;quot;)), add = TRUE)
}

f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;hello 1&amp;quot;
## [1] &amp;quot;hello 2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;what-happens-if-you-call-stop-within-an-on.exit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What happens if you call &lt;code&gt;stop()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;If an error occurs during the evaluation of the &lt;code&gt;on.exit()&lt;/code&gt; expressions, then
the return value is never assigned to the variable in the calling environment.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a &amp;lt;- NULL

f &amp;lt;- function() {
  on.exit(stop(&amp;quot;error during on.exit()&amp;quot;))
  return(1)
}

a &amp;lt;- f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Error in f(): error during on.exit()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;print(a)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## NULL&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;what-happens-if-you-call-return-within-an-on.exit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What happens if you call &lt;code&gt;return()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;?&lt;/h1&gt;
&lt;p&gt;If &lt;code&gt;return()&lt;/code&gt; is called within &lt;code&gt;on.exit()&lt;/code&gt; then this will actually override
any return value in the function itself.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function() {
  on.exit(return(2))
  return(1)
}

f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;manipulating-the-return-value-with-on.exit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Manipulating the return value with &lt;code&gt;on.exit()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;on.exit()&lt;/code&gt; evaluation environment has access to the return value of the
function using the &lt;code&gt;returnValue()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;This can then be used to &lt;em&gt;post-process&lt;/em&gt; any return value before it actual
gets to the function calling environment.&lt;/p&gt;
&lt;p&gt;In the following code, the return value of the function is doubled during the
exit process.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function()  {
  on.exit(return(returnValue() * 2))
  return(1)
}

result &amp;lt;- f()
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-recall-within-an-on.exit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Using &lt;code&gt;Recall()&lt;/code&gt; within an &lt;code&gt;on.exit()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In the following code, the return value is evaluated within the &lt;code&gt;on.exit()&lt;/code&gt;
context, and if it does not meet the specified criteria, the function is
called again (via &lt;code&gt;Recall()&lt;/code&gt;) until it passes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)

f &amp;lt;- function() {
  
  on.exit({
    if (returnValue() &amp;lt; 0.9) {
      return(Recall())
    }
    return(x)
  })
  
  x &amp;lt;- runif(1)
  cat(&amp;quot;Returning: &amp;quot;, x, &amp;quot;\n&amp;quot;)
  return(x)
}


result &amp;lt;- f()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Returning:  0.2655087 
## Returning:  0.3721239 
## Returning:  0.5728534 
## Returning:  0.9082078&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0.9082078&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;shift-the-entire-function-body-to-be-evaluated-on.exit&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Shift the entire function body to be evaluated &lt;code&gt;on.exit()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In this code, the entire function body and return statement for this simpl
addition function are within the &lt;code&gt;on.exit()&lt;/code&gt; statement.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a, b) {
  on.exit({
    result &amp;lt;- a + b
    return(result)
  })
  
  
  return(-999)
}



result &amp;lt;- f(1, 2)
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Modifying R6 objects after creation - Part 2</title>
      <link>https://coolbutuseless.github.io/2021/02/20/modifying-r6-objects-after-creation-part-2/</link>
      <pubDate>Sat, 20 Feb 2021 08:17:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/02/20/modifying-r6-objects-after-creation-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;r6-classes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;R6 classes&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;{R6}&lt;/code&gt; package is an implementation of encapsulated object-oriented programming for R, and is a simpler, faster, lighter-weight alternative to R’s built-in reference classes. This style of programming is also sometimes referred to as classical object-oriented programming.&lt;/p&gt;
&lt;p&gt;In this post I’ll be using the word &lt;code&gt;class&lt;/code&gt; to refer to the original class definition
using &lt;code&gt;R6::R6Class()&lt;/code&gt; and &lt;code&gt;object&lt;/code&gt; to refer to an instantiation of that class
e.g. &lt;code&gt;my_object = ClassName$new()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this post, I’m experimenting with overriding the &lt;code&gt;$&lt;/code&gt; operator to automatically
add variables rather than return &lt;code&gt;NULL&lt;/code&gt; when trying to access variables which
do not exist in the class defintion.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;current-r6-behaviour-when-reading-missing-member-variables&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Current R6 Behaviour when Reading Missing Member Variables&lt;/h1&gt;
&lt;p&gt;If you attempt to read a variable which does not exist,
then R6 will return NULL.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;MyClass &amp;lt;- R6::R6Class(
  &amp;quot;MyClass&amp;quot;,
  lock_object = FALSE,
  public = list(height = 100)
)
 
# Create an instance of the class 
myobj &amp;lt;- MyClass$new()

# Call a method on this object
myobj$height&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 100&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Try and call a non-existant method and get a NULL
myobj$name&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## NULL&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;override-the-operator-to-add-missing-variables-rather-than-return-null&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Override the &lt;code&gt;$&lt;/code&gt; operator to add missing variables rather than return NULL&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# OVerride $ to check for existance of element. If not, then add to object
# with a default value of 999
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`$.MyClass` &amp;lt;- function(x, y) {
  if (!y %in% names(x)) {
    x[[y]] &amp;lt;- 999
  }
  NextMethod()
}

myobj$name&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 999&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;automatically-dynamicalliy-creating-nestedlinked-objects&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Automatically, Dynamicalliy creating nested/linked objects&lt;/h1&gt;
&lt;p&gt;This is an experimental node/tree class that automatically creates new node
objects when one doesn’t exist at the named location in an R6 object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A node class
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Node &amp;lt;- R6::R6Class(
  &amp;quot;Node&amp;quot;,
  lock_object = FALSE,
  public = list(
    index      = NULL,
    initialize = function(index = 1L) {self$index = index; self},
    print      = function() {cat(&amp;quot;I am a node at depth:&amp;quot;, self$index, &amp;quot;\n&amp;quot;)}
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# OVerride $ to check for existance of element. If not, then add a new 
# node object at this location
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`$.Node` &amp;lt;- function(x, y) {
  if (!y %in% names(x)) {
    message(&amp;quot;Creating new node at depth: &amp;quot;, x[[&amp;#39;index&amp;#39;]] + 1L)
    x[[y]] &amp;lt;- Node$new(x[[&amp;#39;index&amp;#39;]] + 1L)
  }
  NextMethod()
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a single new object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node &amp;lt;- Node$new(1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Every reference to an unknown variable in that object creates a new 
# &amp;#39;Node&amp;#39; object at that location
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node$node2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Creating new node at depth: 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## I am a node at depth: 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Node creation can be chained together!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node$node2$node3$node4$node5$node6&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Creating new node at depth: 3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Creating new node at depth: 4&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Creating new node at depth: 5&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Creating new node at depth: 6&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## I am a node at depth: 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-next&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What’s next?&lt;/h1&gt;
&lt;p&gt;This means I can establish a base class with a certain set of methods, but
I can now dynamically create a menagerie of slightly different objects which
each have different sets of methods and variables.&lt;/p&gt;
&lt;p&gt;I guess this is sort of similar to perhaps defining a class inheritance hierarchy
except what I want to do is regularly, and dynamically, modify the methods available
on existing objects during runtime.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Modifying R6 objects after creation</title>
      <link>https://coolbutuseless.github.io/2021/02/19/modifying-r6-objects-after-creation/</link>
      <pubDate>Fri, 19 Feb 2021 21:17:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/02/19/modifying-r6-objects-after-creation/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;r6-classes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;R6 classes&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;{R6}&lt;/code&gt; package is an implementation of encapsulated object-oriented programming for R, and is a simpler, faster, lighter-weight alternative to R’s built-in reference classes. This style of programming is also sometimes referred to as classical object-oriented programming.&lt;/p&gt;
&lt;p&gt;In this post I’ll be using the word &lt;code&gt;class&lt;/code&gt; to refer to the original class definition
using &lt;code&gt;R6::R6Class()&lt;/code&gt; and &lt;code&gt;object&lt;/code&gt; to refer to an instantiation of that class
e.g. &lt;code&gt;my_object = ClassName$new()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is possible to add a method to an existing R6 &lt;em&gt;class&lt;/em&gt; after it has been defined,
but I want to add a new method to an &lt;em&gt;object&lt;/em&gt; (i.e. just an instance of this class).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;r6-classes-simple-example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;R6 classes simple example&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;MyClass &amp;lt;- R6::R6Class(
  &amp;quot;MyClass&amp;quot;,
  public = list(
    hello = function(name) { cat(&amp;quot;Hello&amp;quot;, name, &amp;quot;\n&amp;quot;)}
  )
)
 
# Create an instance of the class 
myobj &amp;lt;- MyClass$new()

# Call a method on this object
myobj$hello(&amp;quot;#RStats&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Hello #RStats&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;modifying-a-class&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Modifying a Class&lt;/h1&gt;
&lt;p&gt;It is possible to create a class and then modify the definition of that class
afterwards. &lt;code&gt;lock_class&lt;/code&gt; must be set to FALSE to do this.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Create an empty class
MyClass &amp;lt;- R6::R6Class(
  &amp;quot;MyClass&amp;quot;,
  lock_class = FALSE
)
 
# Create a new method within the class after it was defined
MyClass$set(&amp;quot;public&amp;quot;, &amp;quot;hello&amp;quot;, function(name) { cat(&amp;quot;Hello&amp;quot;, name, &amp;quot;\n&amp;quot;)})

# Create an instance of the class 
myobj &amp;lt;- MyClass$new()

# Call a method on this object
myobj$hello(&amp;quot;#RStats&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Hello #RStats&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;adding-a-new-method-to-an-object-withouth-modifying-the-class&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Adding a new method to an Object (withouth modifying the class)&lt;/h1&gt;
&lt;p&gt;It is possible to create a class, instantiate an object of that class, and
then modify the contents of that object to add a new method not in the
original class definition, but only to this object.&lt;/p&gt;
&lt;p&gt;Requires:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lock_object = FALSE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In order for a new method to behave correctly, is must have the same
environment as other methods in the class. This is so it can look-up public and
private variables in the class. e.g. using &lt;code&gt;self$&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Create an empty class
MyClass &amp;lt;- R6::R6Class(
  &amp;quot;MyClass&amp;quot;,
  lock_object = FALSE,
  public = list(
    line_end = &amp;quot;!!&amp;quot;,
    hello = function(name) { cat(&amp;quot;Hello&amp;quot;, name, self$line_end, &amp;quot;\n&amp;quot;)}
  )
)

# Create an instance of the class 
myobj &amp;lt;- MyClass$new()

# Call a method on this object
myobj$hello(&amp;quot;#RStats&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Hello #RStats !!&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Create a method Ensure it has the right environment
myobj$goodbye &amp;lt;- function(name) { cat(&amp;quot;Goodbye&amp;quot;, name, self$line_end, &amp;quot;\n&amp;quot;)}
environment(myobj$goodbye) &amp;lt;- myobj$.__enclos_env__

myobj$goodbye(&amp;quot;Mike&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Goodbye Mike !!&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-next&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;What’s next?&lt;/h1&gt;
&lt;p&gt;This means I can establish a base class with a certain set of methods, but
I can now dynamically create a menagerie of slightly different objects which each have&lt;br /&gt;
different sets of methods.&lt;/p&gt;
&lt;p&gt;I guess this is sort of similar to perhaps defining a class inheritance hierarchy
except what I want to do is regularly, and dynamically, modify the methods available
on existing objects during runtime.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A Simple Ray-Tracer Written in Base R</title>
      <link>https://coolbutuseless.github.io/2021/02/15/a-simple-ray-tracer-written-in-base-r/</link>
      <pubDate>Mon, 15 Feb 2021 20:17:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/02/15/a-simple-ray-tracer-written-in-base-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This code was a personal challenge to write a simple ray-tracer in pure R.&lt;/p&gt;
&lt;p&gt;Ray tracing is an example of something which is really silly to do in base R,
and I’d be interested to see how others would approach this problem.&lt;/p&gt;
&lt;p&gt;Code is shared in a &lt;a href=&#34;https://gist.github.com/coolbutuseless/2cd4c5c9fe3e602047e5f9882f12cb2a&#34;&gt;public gist&lt;/a&gt;.
Please &lt;a href=&#34;https://hitchhikers.fandom.com/wiki/Share_and_Enjoy&#34;&gt;share and enjoy&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;design&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Design&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Has to be base R only. No other packages allowed&lt;/li&gt;
&lt;li&gt;Supports sphereical objects only. This simplifies object handling.&lt;/li&gt;
&lt;li&gt;Tracing a single eye-ray per pixel only&lt;/li&gt;
&lt;li&gt;Single light probe rays for shadow testing&lt;/li&gt;
&lt;li&gt;Objects represented by signed distance fields.&lt;/li&gt;
&lt;li&gt;Ray-marching/Sphere-tracing is used to move rays through space&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;setting-expectations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Setting expectations&lt;/h2&gt;
&lt;div&gt;
&lt;div style=&#34;width:45%;float:left;&#34;&gt;
&lt;h4&gt;
This is what Blender can do
&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;https://blenderartists.org/t/bed-and-bathroom/1282816&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/raytracer/blender.jpg&#34; width=&#34;100%&#34; /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:40%;float:left;margin-left:3px;&#34;&gt;
&lt;h4&gt;
This is what this code does
&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/raytracer/example2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear:both;&#34;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;data-representation&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Data representation&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;rays&lt;/strong&gt; - a bundle of rays stored as a list of matrices. Stores ray origin,
direction, distance travelled so far, closest object index, distance to
closest object&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sphere&lt;/strong&gt; - a list of information about a spherical object i.e. coordinates
of centre, radius and colour&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;helper-functions&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Helper functions&lt;/h1&gt;
&lt;div id=&#34;normalise-vectors-normalise&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Normalise vectors &lt;code&gt;normalise()&lt;/code&gt;&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Normalise vectors to unit length
#&amp;#39; @param mat a matrix storing multiple vectors i.e. one vector per row
#&amp;#39; @return modified matrix with all vectors normalised to length=1
#-----------------------------------------------------------------------------
normalise &amp;lt;- function(mat) {
  mat / sqrt(rowSums(mat ^ 2))
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-values-associated-with-a-bundle-of-rays---draw&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Plot values associated with a bundle of rays - &lt;code&gt;draw()&lt;/code&gt;&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Draw a ray parameter shading with viridis
#&amp;#39; @param rays list of ray information
#&amp;#39; @param paramter valid ray parameter e.g. &amp;#39;t&amp;#39;, &amp;#39;obj_index&amp;#39;, &amp;#39;dist2obj&amp;#39;
#&amp;#39; @param ... other parameters passed to `viridisLit::viridis()`
#-----------------------------------------------------------------------------
draw &amp;lt;- function(rays, parameter, option = &amp;#39;A&amp;#39;, ...) {
  values &amp;lt;- rays[[parameter]]

  if (length(unique(values)) == 1) {
    values[] &amp;lt;- 0
  } else {
    values &amp;lt;- as.integer(255 * (values - min(values)) / (max(values) - min(values)))
  }

  colours &amp;lt;- viridisLite::viridis(256, option = option, ...)[values + 1L]
  mat &amp;lt;- matrix(colours, N, N)
  mat &amp;lt;- mat[rev(seq(N)),]

  plot(as.raster(mat), interpolate = FALSE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-rays-through-image-plane---create_eye_rays&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Create rays through image plane - &lt;code&gt;create_eye_rays()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Eye rays&lt;/strong&gt; are the rays which are cast from the eye through each pixel in the
screen.&lt;/p&gt;
&lt;p&gt;The colour of the object at the end of this ray is the colour of the pixel in
the final image representation.&lt;/p&gt;
&lt;p&gt;An illustration of these rays is included below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/raytracer/eye-rays.jpg&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Create the initial set of eye rays
#&amp;#39; Image plane is in the x,y plane centered at c(0, 0, 0)
#&amp;#39; @param N pixel width and height of the resulting image
#&amp;#39; @param eye_to_image_plane default: 2
#-----------------------------------------------------------------------------
create_eye_rays &amp;lt;- function(N=5, eye_to_image_plane = 2) {
  eye &amp;lt;- c(0, 0, -eye_to_image_plane)
  mid &amp;lt;- as.integer((N+1)/2)

  col &amp;lt;- rep(1:N, each=N)
  row &amp;lt;- rep(1:N,      N)

  x &amp;lt;- (col - mid) / (mid - 1)
  y &amp;lt;- (row - mid) / (mid - 1)

  ray_origin  &amp;lt;- cbind(x=x, y=y, z=0)

  ray_dir &amp;lt;- ray_origin
  ray_dir[,1] &amp;lt;- ray_origin[,1] - eye[1]
  ray_dir[,2] &amp;lt;- ray_origin[,2] - eye[2]
  ray_dir[,3] &amp;lt;- ray_origin[,3] - eye[3]

  ray_dir &amp;lt;- normalise(ray_dir)

  rays &amp;lt;- list(
    origin    = ray_origin,
    dir       = ray_dir,
    t         = numeric(N*N),
    obj_index = NA,
    steps     = rep(-1L, N*N)
  )

  rays$ray_end &amp;lt;- rays$origin + rays$dir * rays$t

  rays
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;signed-distance-function---calc_distances_to_sphere&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Signed distance function - &lt;code&gt;calc_distances_to_sphere()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This renderer uses signed distance functions to determine the distance from
the position of any point in space to a given object.&lt;/p&gt;
&lt;p&gt;Each ray is tested against each object. The distance to the closet object
determines how far the ray will advance at the next time step (and be guaranteed
to not hit anything else). This is ray-marching with sphere-tracing.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Core function to calculate distance from sphere and a bundle of rays
#-----------------------------------------------------------------------------
calc_distances_to_sphere &amp;lt;- function(sphere, rays) {
  sqrt(colSums( (t(rays$ray_end) - sphere$centre) ^ 2 )) - sphere$radius
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;ray-marching---raymarch&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Ray marching - &lt;code&gt;raymarch()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This function orchestrates the marching of a bundle of rays within a scene
containing a set of objects.&lt;/p&gt;
&lt;p&gt;It proceeds as follows:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;For each ray, find the distance to the nearest object&lt;/li&gt;
&lt;li&gt;Advance the ray that distance&lt;/li&gt;
&lt;li&gt;Repeat.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The sphere-tracing/ray-marching step is illustrated in the figure below
(from &lt;a href=&#34;https://jasmcole.com/2019/10/03/signed-distance-fields/&#34;&gt;hasmcole.com&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/raytracer/sphere-tracing.png&#34; width=&#34;65%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Note: There is no convergence criteria used here to determine if a ray has
actually hit an object. Instead, all rays are marched through the scene a
fixed number of times. This is pretty naive, and there would be speed gains by
stopping the marching of rays which have already intersected an object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; march the rays
#-----------------------------------------------------------------------------
raymarch &amp;lt;- function(rays, objects) {

  #---------------------------------------------------------------------------
  # Naive marching. Just goint to a fixed number of iterations
  #  1. Calc distance from end of each ray to the nearest object
  #  2. Ray march (sphere tracing) to advance the ray this minimum distance
  #  3. Repeat
  #---------------------------------------------------------------------------
  for (step in seq_len(100)) {
    distances      &amp;lt;- lapply(objects, calc_distances_to_sphere, rays)
    rays$dist2obj  &amp;lt;- do.call(pmin.int, distances)
    rays$t         &amp;lt;- rays$t + rays$dist2obj
    rays$ray_end   &amp;lt;- rays$origin + rays$dir * rays$t
    
    # Keep a rough notion of the step number at which the ray converged 
    # on an object
    just_converged &amp;lt;- rays$dist2obj &amp;lt; 0.001 &amp;amp; rays$step &amp;lt; 0
    rays$step[just_converged] &amp;lt;- step
  }

  #---------------------------------------------------------------------------
  # Ray cleanup
  #  - find closest object
  #  - mark objects within a given idstance as &amp;#39;converged&amp;#39;
  #---------------------------------------------------------------------------
  rays$obj_index &amp;lt;- max.col(-do.call(cbind, distances))
  rays$converged &amp;lt;- rays$dist2obj &amp;lt; 0.01
  rays$step[rays$step &amp;lt; 0] &amp;lt;- step

  rays
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;define-the-objects-in-the-scene&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Define the objects in the scene&lt;/h1&gt;
&lt;p&gt;Only spheres are supported, with each object represented as a list of &lt;code&gt;centre&lt;/code&gt;,
&lt;code&gt;radius&lt;/code&gt; and &lt;code&gt;colour&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The back wall and floor are just very large spheres.&lt;/p&gt;
&lt;p&gt;The specifications for the spheres is also stored as matrices to ease the
creation of light probe rays and colour calculations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Place some random spheres
#-----------------------------------------------------------------------------
set.seed(1)
random_spheres &amp;lt;- lapply(1:35, function(x) {
  radius &amp;lt;- runif(1, 0.2, 0.8)
  x      &amp;lt;- runif(1,  -3, 3)
  y      &amp;lt;- runif(1,  -3, 3)
  z      &amp;lt;- runif(1, 3, 6) #- radius
  list(centre = c(x, y, z), radius = radius, colour = runif(3))
})

walls &amp;lt;- list(
  list(centre = c(0  ,    0  , 900), radius = 895  , colour = c(1, 1, 0.9)),  # back wall,
  list(centre = c(0  , -900  ,   0), radius = 897  , colour = c(1, 1, 1  ))   # floor
)

regular_objects &amp;lt;- c(random_spheres, walls)


#-----------------------------------------------------------------------------
# Extract summary representations across all objects of:
#  - colours
#  - centres
#  - radii
#-----------------------------------------------------------------------------
object_colours &amp;lt;- lapply(regular_objects, `[[`, &amp;#39;colour&amp;#39;)
object_colours &amp;lt;- do.call(rbind, object_colours)

object_radii &amp;lt;- vapply(regular_objects, `[[`, numeric(1), &amp;#39;radius&amp;#39;)

object_centres &amp;lt;- lapply(regular_objects, `[[`, &amp;#39;centre&amp;#39;)
object_centres &amp;lt;- do.call(rbind, object_centres)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;render-the-scene&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Render the scene&lt;/h1&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create rays from the eye through each pixel in the output image&lt;/li&gt;
&lt;li&gt;March these rays through the scene, using the sphere objects to define how
far to advance at each step&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Create a bundle of NxN rays and march them into the scene
#-----------------------------------------------------------------------------
N &amp;lt;- 400
eye_rays &amp;lt;- create_eye_rays(N)

print(system.time({
  rays &amp;lt;- raymarch(eye_rays, regular_objects)
}))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##    user  system elapsed 
##  20.802   4.282  25.126&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;information-about-the-render&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Information about the render&lt;/h1&gt;
&lt;p&gt;Each ray retains some information about how it travelled through the scene:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The index of the closest object - &lt;code&gt;obj_index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The number of steps to converge on an object - &lt;code&gt;step&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The distance travelled - &lt;code&gt;t&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;draw(rays, &amp;#39;obj_index&amp;#39;); title(&amp;quot;Index of object closest to end of eye ray&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-02-15-simple-ray-tracer-in-base-r_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;draw(rays, &amp;#39;t&amp;#39;)        ; title(&amp;quot;Distance ray has travelled&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-02-15-simple-ray-tracer-in-base-r_files/figure-html/unnamed-chunk-8-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;draw(rays, &amp;#39;step&amp;#39;)     ; title(&amp;quot;Number of steps to converge&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-02-15-simple-ray-tracer-in-base-r_files/figure-html/unnamed-chunk-8-3.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This last image is interesting as it shows that rays which pass near to the
edge of an object takes more steps to converge.&lt;/p&gt;
&lt;p&gt;As illustrated below, this is because as a ray grazes an object it takes a large
number of very small steps.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/raytracer/convergence.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;shadows&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Shadows&lt;/h1&gt;
&lt;p&gt;To determine which objects are in light and which are in shadow:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Define a light source object&lt;/li&gt;
&lt;li&gt;At the end of each ray, determine the local surface normal and direction
to this light source&lt;/li&gt;
&lt;li&gt;Ray march these new light probe rays&lt;/li&gt;
&lt;li&gt;If they hit the light, then it means there are no objects in the way and it
is fully lit. Otherwise it is in shadow&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Define the position of the light within the scene
#-----------------------------------------------------------------------------
light &amp;lt;- list(centre=c(-1.5, 2.5, 0.2), radius=0.1)


#-----------------------------------------------------------------------------
# Calculate probes from the end of each camera ray to the light source.
#  (1) find object each ray intersects
#  (2) Find the centre of this object and the local normal
#  (3) Calculate the direction from this intersection to the light source
#  (4) Construct set of rays to probe for visibilit of light source
#-----------------------------------------------------------------------------
centres &amp;lt;- object_centres[rays$obj_index,]

normal &amp;lt;- rays$ray_end - centres
normal &amp;lt;- normalise(normal)

radii &amp;lt;- object_radii[rays$obj_index]

# Start light ray from just above surface
intersect &amp;lt;- centres + (radii + 0.001) * normal

# Direction to lightsource (normalised to unit length)
dir &amp;lt;- intersect
dir[,1] &amp;lt;- light$centre[1] - intersect[,1]
dir[,2] &amp;lt;- light$centre[2] - intersect[,2]
dir[,3] &amp;lt;- light$centre[3] - intersect[,3]
dir &amp;lt;- normalise(dir)

# Dot product of local normal with direction to lightsource.
# Clamp negative values (where normal points away from light) to zero
facing_light &amp;lt;- (dir[,1]*normal[,1] + dir[,2]*normal[,2] + dir[,3]*normal[,3])
facing_light &amp;lt;- ifelse(facing_light &amp;gt; 0, facing_light, 0)

# Construct light probes
light_probes &amp;lt;- list(
  origin = intersect,
  dir    = dir,
  t      = numeric(length(radii))
)

light_probes$ray_end &amp;lt;- light_probes$origin + light_probes$dir * light_probes$t


#-----------------------------------------------------------------------------
#&amp;#39; raymarch the light probes
#&amp;#39; If a lightprobe hits the light, then the object can see the light source,
#&amp;#39; otherwise it is in shadow
#-----------------------------------------------------------------------------
objects_with_light &amp;lt;- c(list(light), regular_objects)
light_probes       &amp;lt;- raymarch(light_probes, objects_with_light)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;determine-colour-and-shading-of-each-pixel&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Determine colour and shading of each pixel&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Find the colour of each object at the end of each eye ray
# If ray is not close to any object, set colour to black
#-----------------------------------------------------------------------------
intersect_colour &amp;lt;- object_colours[rays$obj_index,]
intersect_colour[rays$dist2obj &amp;gt; 0.1, ] &amp;lt;- 0

#-----------------------------------------------------------------------------
# If a light probe from this intersection intersects with any object other
# than the light source, then it is in shadow, so darken this colour
#-----------------------------------------------------------------------------
in_shadow &amp;lt;- light_probes$obj_index != 1
intersect_colour[in_shadow] &amp;lt;- 0.3 * intersect_colour[in_shadow]

#-----------------------------------------------------------------------------
# Shade the colour from light-to-dark depending on how close the local normal
# aligns with the direction of the light source.
#-----------------------------------------------------------------------------
final_colour &amp;lt;- intersect_colour * facing_light


#-----------------------------------------------------------------------------
# Convert final colours to a raster for plotting
#-----------------------------------------------------------------------------
colours &amp;lt;- rgb(final_colour[,1], final_colour[,2], final_colour[,3])
image   &amp;lt;- matrix(colours, nrow = N, ncol = N)
image   &amp;lt;- image[rev(seq(nrow(image))),] # flip top-to-bottom
image   &amp;lt;- as.raster(image)

plot(image, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-02-15-simple-ray-tracer-in-base-r_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>From the time before Tetris - &#39;Beat the Computer&#39; puzzles</title>
      <link>https://coolbutuseless.github.io/2021/01/27/from-the-time-before-tetris-beat-the-computer-puzzles/</link>
      <pubDate>Wed, 27 Jan 2021 20:59:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/01/27/from-the-time-before-tetris-beat-the-computer-puzzles/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;in-the-time-before-tetris&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;In the time before ‘Tetris’&lt;/h1&gt;
&lt;p&gt;Before ‘Tetris’, if you wanted to stack smaller pieces into bigger areas, you
could play with the Tenyo puzzles called “Beat the Computer”.&lt;/p&gt;
&lt;p&gt;These puzzles were pocket-sized containers with a bestiary of pre-cut pieces -
you tipped them out and then tried to fit them back in.&lt;/p&gt;
&lt;p&gt;They were really difficult!&lt;/p&gt;
&lt;p&gt;Below are puzzle numbers 783 and 6 in this series.&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/beat-the-computer/puzzle783.jpg&#34; width = &#34;45%&#34; /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/beat-the-computer/puzzle6.jpg&#34; width = &#34;45%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;finding-all-9356-solutions-to-puzzle-no-5&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Finding all 9356 solutions to Puzzle No 5&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/beat-the-computer/puzzle5.jpg&#34; width = &#34;45%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This puzzle challenges you to fit the complete set of 12 &lt;a href=&#34;https://en.wikipedia.org/wiki/Pentomino&#34;&gt;pentominos&lt;/a&gt;
into a 6x10 space.&lt;/p&gt;
&lt;p&gt;According to the instructions for Puzzle No. 5, there are 2339 unique solutions
to this puzzle. If reflections along both axes are considered then there are
2339 * 4 = 9356 solutions.&lt;/p&gt;
&lt;p&gt;The code which follows finds all solutions by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;modelling each piece as a set of indices defining its shape&lt;/li&gt;
&lt;li&gt;using recursive backtracking to try and place each piece in turn&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It takes about 15 minutes to find all solutions - about 10 solutions/second.&lt;/p&gt;
&lt;p&gt;The following 50 minute video shows all the solutions (at a rate of 3 solutions per second)&lt;/p&gt;
&lt;p&gt;&lt;video loop autoplay controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/beat-the-computer/anim3.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;suppressPackageStartupMessages({
  library(dplyr)
  library(purrr)
  library(tidyr)
})


# Reference and naming scheme from:
#  https://en.wikipedia.org/wiki/Pentomino

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
w   &amp;lt;- 10    # width  of space to place pentominos
h   &amp;lt;- 6     # height of space to place pentominos
buf &amp;lt;- 5 - 1 # maximum safety buffer around placement area


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a board to contain the placement area.
# The buffer arund the outside is to ensure that any piece that starts within
# the placement area, will not be out of bounds of the board.
# Use &amp;#39;1&amp;#39; to indicate that the space is occupied.
# Use &amp;#39;0&amp;#39; to indicate an empty space into which a pentomino may be placed
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
board &amp;lt;- matrix(1L, nrow = h + 2 * buf, ncol = w + 2 * buf)

for (i in seq(h)) {
  board[buf + i, buf + seq(w)] &amp;lt;- 0L
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Pentominoes as matrices
# Naming scheme follows wikipedia: https://en.wikipedia.org/wiki/Pentomino
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pent_mats &amp;lt;- list(
  I = matrix(c(
    1, 1, 1, 1, 1
  ), nrow = 1, ncol = 5, byrow = TRUE),

  F = matrix(c(1, 0, 0,
               1, 1, 1,
               0, 1, 0), nrow=3, byrow = TRUE),

  L = matrix(c(1, 1, 1, 1,
               1, 0, 0, 0), nrow = 2, byrow = TRUE),

  P = matrix(c(1, 1, 0,
               1, 1, 1), nrow = 2, byrow = TRUE),

  N = matrix(c(0, 1, 1, 1,
               1, 1, 0, 0), nrow = 2, byrow = TRUE),

  T = matrix(c(1, 1, 1,
               0, 1, 0,
               0, 1, 0), nrow = 3, byrow = TRUE),

  U = matrix(c(1, 0, 1,
               1, 1, 1), nrow =  2, byrow = TRUE),

  V = matrix(c(0, 0, 1,
               0, 0, 1,
               1, 1, 1), nrow = 3, byrow = TRUE),

  W = matrix(c(1, 0, 0,
               1, 1, 0,
               0, 1, 1), nrow = 3, byrow = TRUE),

  X = matrix(c(0, 1, 0,
               1, 1, 1,
               0, 1, 0), nrow = 3, byrow = TRUE),

  Y = matrix(c(0, 0, 1, 0,
               1, 1, 1, 1), nrow = 2, byrow = TRUE),

  Z = matrix(c(1, 0, 0,
               1, 1, 1,
               0, 0, 1), nrow = 3, byrow = TRUE)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check that they&amp;#39;re all pentominoes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stopifnot(all(map_dbl(pent_mats, sum) == 5))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot the board
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_board &amp;lt;- function(x) {
  # trim the board
  x &amp;lt;- x[buf + seq(h), buf + seq(w)]

  image(t(x), asp=6/10, col = RColorBrewer::brewer.pal(12, &amp;#39;Paired&amp;#39;), axes = F, ann = F)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Convert a piece matrix to a vector of indices
#&amp;#39;
#&amp;#39; @param piece_mat integer matrix with values 0/1 to represent piece layout
#&amp;#39; @param rows how many rows are in the matrix this will be superimposed upon?
#&amp;#39; @return integer vetor of offsets of the locations in this piece
#&amp;#39;
#&amp;#39; @examples
#&amp;#39; piece_to_idx(pent_mats[[1]], rows = nrow(board))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
piece_to_idx &amp;lt;- function(piece_mat, rows) {

  # Find all the locations in the matrix as (row, col) coords
  coords &amp;lt;- arrayInd(which(piece_mat &amp;gt; 0), dim(piece_mat))

  # Offset set to first part of piece
  offset &amp;lt;- which(piece_mat &amp;gt;= 1)[1]

  coords[, 1] &amp;lt;- coords[,1] - offset

  idx &amp;lt;- (coords[,2] - 1L) * rows + coords[,1]
  idx
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Matrix manipulation functions. Nothing fancy - only called during setup.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rot90 &amp;lt;- function(x) {
  x &amp;lt;- t(x)
  x &amp;lt;- x[rev(seq(nrow(x))),,drop=FALSE]
  x
}

rot180 &amp;lt;- function(x) rot90(rot90(x))
rot270 &amp;lt;- function(x) rot90(rot90(rot90(x)))

mirror &amp;lt;- function(x) {
  x[rev(seq(nrow(x))), , drop=FALSE]
}



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert the pentomino matrices into lists of indices
#
# Add all rotated versions of all pieces as well.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_pents &amp;lt;- map(pent_mats, function(x) {
  list(
    piece_to_idx(x        , rows = nrow(board)),
    piece_to_idx(rot90(x) , rows = nrow(board)),
    piece_to_idx(rot180(x), rows = nrow(board)),
    piece_to_idx(rot270(x), rows = nrow(board))
  )
})


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Pieces which need to also have mirrored counterparts
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mirror_pieces &amp;lt;- c(&amp;#39;F&amp;#39;, &amp;quot;L&amp;quot;, &amp;#39;P&amp;#39;, &amp;#39;N&amp;#39;, &amp;#39;Y&amp;#39;, &amp;#39;Z&amp;#39;)

for (letter in mirror_pieces) {
  x &amp;lt;- mirror(pent_mats[[letter]])
  all_pents[[letter]][[5]] &amp;lt;- piece_to_idx(  x        , rows = nrow(board))
  all_pents[[letter]][[6]] &amp;lt;- piece_to_idx(  rot90(x) , rows = nrow(board))
  all_pents[[letter]][[7]] &amp;lt;- piece_to_idx(  rot180(x), rows = nrow(board))
  all_pents[[letter]][[8]] &amp;lt;- piece_to_idx(  rot270(x), rows = nrow(board))
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove duplicates.
#  *  &amp;#39;I&amp;#39; piece only exists as horizontal and vertical. Rotated versions are dupes.
#  * &amp;#39;X&amp;#39; only needs a single piece as all rotations are identical
#  * &amp;#39;Z&amp;#39; some rotations are duplicates of existing
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_pents[[&amp;#39;I&amp;#39;]][[4]] &amp;lt;- NULL
all_pents[[&amp;#39;I&amp;#39;]][[3]] &amp;lt;- NULL

all_pents[[&amp;#39;X&amp;#39;]][[4]] &amp;lt;- NULL
all_pents[[&amp;#39;X&amp;#39;]][[3]] &amp;lt;- NULL
all_pents[[&amp;#39;X&amp;#39;]][[2]] &amp;lt;- NULL


all_pents[[&amp;#39;Z&amp;#39;]][[8]] &amp;lt;- NULL
all_pents[[&amp;#39;Z&amp;#39;]][[7]] &amp;lt;- NULL
all_pents[[&amp;#39;Z&amp;#39;]][[4]] &amp;lt;- NULL
all_pents[[&amp;#39;Z&amp;#39;]][[3]] &amp;lt;- NULL


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign a number (&amp;#39;val&amp;#39;) to use for each piece. This is the number that will be
# written to the &amp;#39;board&amp;#39; matrix for this piece.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_pents &amp;lt;- map(1:12, function(x) {
  list(
    val = x,
    piece_indices = all_pents[[x]]
  )
})


#=============================================================================
#=============================================================================
#
# Everything above this comment is just prepping the data structures
#
# Everything below this comment is the recursive backtracking
#
#=============================================================================
#=============================================================================



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Place a piece on the board
#&amp;#39;
#&amp;#39; @param board integer matrix of an appropriate size
#&amp;#39; @param idx location on board to place piece
#&amp;#39; @param piece_indices integer vector of offsets which define the piece
#&amp;#39; @param val integer value to write into the board
#&amp;#39;
#&amp;#39; @return copy of &amp;#39;board&amp;#39; with piece if placement is valid. Otherwise &amp;#39;NULL&amp;#39;
#&amp;#39; @example
#&amp;#39; place_piece(board, 106, all_pents[[12]]$piece_indices[[1]], 99)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
place_piece &amp;lt;- function(board, idx, piece_indices, val) {

  current_vals &amp;lt;- board[idx + piece_indices]
  if (any(current_vals &amp;gt; 0)) {
    return(NULL)
  }

  board[idx + piece_indices] &amp;lt;- val

  board
}


count &amp;lt;- 0L
zz &amp;lt;- NULL

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Fill a board with the given set of pentominos
#&amp;#39;
#&amp;#39; Recursive placement of pentominos with backtracking
#&amp;#39;
#&amp;#39; @param board integer matrix
#&amp;#39; @param pents list of pentoninos i.e. `all_pents`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fill_board &amp;lt;- function(board, pents) {

  # Ran out of pentominos =&amp;gt; must be a solution!
  if (length(pents) == 0L) {
    count &amp;lt;&amp;lt;- count + 1L

    # Save image
    if (FALSE) {
      filename &amp;lt;- sprintf(&amp;quot;images/%04i.png&amp;quot;, count)
      png(filename, width = 480, height = 320)
      par(mar=c(0, 0, 0, 0))
      plot_board(board)
      dev.off()
    }

    # be verbose about number of solutions found so far
    if (count %% 100 == 0) cat(count, &amp;quot;&amp;quot;)

    return()
  }

  # Where&amp;#39;s the next location in the board that we can place a pentomino?
  idx &amp;lt;- which(board == 0)[1]

  # Try and place each pentomino at the current position.
  # If the placement is valid, recursively call &amp;#39;fill_board&amp;#39; with the
  # latest version of the board, and the updated list of pentominos
  for (i in seq_along(pents)) {
    val &amp;lt;- pents[[i]]$val
    all_piece_indices &amp;lt;- pents[[i]]$piece_indices
    for (piece_indices in all_piece_indices) {
      new_board &amp;lt;- place_piece(board, idx, piece_indices, val = val)
      if (!is.null(new_board)) {
        fill_board(new_board, pents[-i])
      }
    }
  }

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# It takes about 15 minutes to generate all 9356 solutions - about 10 solns/second
# Note: Mirrored and flipped solutions are included.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fill_board(board, all_pents)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {wingspan} - data about the cards in the Wingspan boardgame</title>
      <link>https://coolbutuseless.github.io/2021/01/18/introducing-wingspan-data-about-the-cards-in-the-wingspan-boardgame/</link>
      <pubDate>Mon, 18 Jan 2021 20:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2021/01/18/introducing-wingspan-data-about-the-cards-in-the-wingspan-boardgame/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;wingspan&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Wingspan &lt;img src=&#34;https://coolbutuseless.github.io/img/wingspan/wingspan.jpg&#34; align=&#34;right&#34; width=&#34;500&#34; /&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The R &lt;code&gt;{wingspan}&lt;/code&gt; package makes available information about
the birds and bonus cards in the boardgame &lt;a href=&#34;https://stonemaiergames.com/games/wingspan/&#34;&gt;wingspan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wingspan (the boardgame) was designed by Elizabeth Hargrave, with art by
Natalia Rojas, Ana Maria Martinez Jaramillo, and Beth Sobel&lt;/p&gt;
&lt;p&gt;The boardgame is a competitive, medium-weight, card-driven, engine-building board
game, and is absolutely delightful!&lt;/p&gt;
&lt;p&gt;This package just provides stats and data on the cards in the box - it won’t
really help you to play the game, and doesn’t include any of the amazing artwork;
it’s just the facts about all birds and bonus cards as collected by
&lt;a href=&#34;https://boardgamegeek.com/user/TawnyFrogmouth&#34;&gt;TawnyFrogmouth&lt;/a&gt; at
&lt;a href=&#34;https://boardgamegeek.com/boardgame/266192/wingspan&#34;&gt;BoardGameGeek&lt;/a&gt;
(&lt;a href=&#34;https://boardgamegeek.com/filepage/193164/wingspan-bird-card-bonus-card-spreadsheet&#34;&gt;original data&lt;/a&gt;).&lt;/p&gt;
&lt;div style=&#34;clear:both;&#34; /&gt;

&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;birds&lt;/code&gt; a data.frame of information about each of the cards in the base
game and the expansions (europe and oceania)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bonus_cards&lt;/code&gt; information about the cards used to give you a bonus at the
end of the game (based upon the numbers of birds of different types you
accumulate during the game)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/wingspan&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/wingspan&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;example-bird-data&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Example Bird Data&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/wingspan/barn-swallow.jpg&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Some of the stats for the 2 birds at the bottom of this image are shown below.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(wingspan)

wingspan::birds %&amp;gt;% 
  filter(common_name %in% c(&amp;#39;Barn Swallow&amp;#39;, &amp;#39;Peregrine Falcon&amp;#39;)) %&amp;gt;%
  select(common_name, scientific_name, points = victory_points, predator, 
         egg_capacity, nest_type, total_food_cost) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;19%&#34; /&gt;
&lt;col width=&#34;19%&#34; /&gt;
&lt;col width=&#34;7%&#34; /&gt;
&lt;col width=&#34;10%&#34; /&gt;
&lt;col width=&#34;14%&#34; /&gt;
&lt;col width=&#34;11%&#34; /&gt;
&lt;col width=&#34;17%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;common_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;scientific_name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;points&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;predator&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;egg_capacity&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;nest_type&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;total_food_cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Barn Swallow&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hirundo rustica&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wild&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Peregrine Falcon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Falco peregrinus&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Platform&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;example-summary-plot&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Example Summary Plot&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

ggplot(birds, aes(as.factor(total_food_cost), victory_points)) + 
  geom_boxplot() + 
  theme_bw() + 
  labs(
    x = &amp;quot;Total food cost to play bird card&amp;quot;,
    y = &amp;quot;Bird value (Victory points at end of game)&amp;quot;,
    title = &amp;quot;Birds with higher total food cost score more victory points&amp;quot;
  ) + 
  scale_y_continuous(breaks = 0:10)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2021-01-18-wingspan_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://boardgamegeek.com/user/TawnyFrogmouth&#34;&gt;TawnyFrogmouth&lt;/a&gt; at
&lt;a href=&#34;https://boardgamegeek.com/boardgame/266192/wingspan&#34;&gt;BoardGameGeek&lt;/a&gt;
for collating and sharing
&lt;a href=&#34;https://boardgamegeek.com/filepage/193164/wingspan-bird-card-bonus-card-spreadsheet&#34;&gt;the data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stonemaiergames.com/games/wingspan/&#34;&gt;Stonemeier games&lt;/a&gt; for releasing such
a delicious game&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing flexo - simple lex/parse tools in R</title>
      <link>https://coolbutuseless.github.io/2020/12/07/introducing-flexo-simple-lex/parse-tools-in-r/</link>
      <pubDate>Mon, 07 Dec 2020 20:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/12/07/introducing-flexo-simple-lex/parse-tools-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;flexo-simple-lexparse-tools-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;flexo: Simple Lex/Parse Tools in R &lt;img src=&#34;https://coolbutuseless.github.io/img/flexo/logo.png&#34; align=&#34;right&#34; height=300 title=&#34;An homage to the old logo for the Berlin Hilton&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/flexo/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/flexo/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flexo&lt;/code&gt; provides tools for simple tokenising/lexing/parsing of text files.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flexo&lt;/code&gt; aims to be useful in getting otherwise unsupported text data formats into R.&lt;/p&gt;
&lt;p&gt;For complicated parsing (e.g. programming languages) you’ll want to use the more
formally correct lexing/parsing provided by the &lt;a href=&#34;https://cran.r-project.org/package=rly&#34;&gt;&lt;code&gt;rly&lt;/code&gt; package&lt;/a&gt;
or the &lt;a href=&#34;https://cran.r-project.org/package=dparser&#34;&gt;&lt;code&gt;dparser&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flexo&lt;/code&gt; is a replacement for &lt;a href=&#34;https://github.com/coolbutuseless/minilexer&#34;&gt;minilexer&lt;/a&gt;
(which should now be considered abandoned).&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lex(text, regexes)&lt;/code&gt; break a text string into tokens using the supplied
regular expressions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TokenStream&lt;/code&gt; is an R6 class for manipulating a stream of tokens - a
first step for parsing the data into a more useful format&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;flexo&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/flexo&#34;&gt;github coolbutuseless/flexo&lt;/a&gt; with&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/flexo&amp;#39;, ref=&amp;#39;main&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;usage-overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Usage Overview&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Define a set of regular expressions (&lt;code&gt;regexes&lt;/code&gt;) that define the tokens in the data&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;lex()&lt;/code&gt; to use these &lt;code&gt;regexes&lt;/code&gt; to split data into tokens i.e. &lt;code&gt;lex(text, regexes)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lex()&lt;/code&gt; returns a named character vector of tokens. The names of the tokens
correspond to the respective regex which captured it.&lt;/li&gt;
&lt;li&gt;Optionally use the &lt;code&gt;TokenStream&lt;/code&gt; &lt;a href=&#34;https://cran.r-project.org/package=R6&#34;&gt;R6&lt;/a&gt;
class to aid in the manipulation of the raw tokens into more structured data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/packages/chess.html&#34;&gt;Parsing Chess games in PGN format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/packages/articles/parse_obj.html&#34;&gt;Parsing 3d models in OBJ format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/packages/Scrabble.html&#34;&gt;Parsing Scrabble games in GCG format&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-using-lex-to-split-sentence-into-tokens&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Using &lt;code&gt;lex()&lt;/code&gt; to split sentence into tokens&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sentence_regexes &amp;lt;- c(
  word        = &amp;quot;\\w+&amp;quot;, 
  whitespace  = &amp;quot;\\s+&amp;quot;,
  fullstop    = &amp;quot;\\.&amp;quot;,
  comma       = &amp;quot;,&amp;quot;
)

sentence = &amp;quot;Hello there, Rstats.&amp;quot;

flexo::lex(sentence, sentence_regexes)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;      word whitespace       word      comma whitespace       word   fullstop 
   &amp;quot;Hello&amp;quot;        &amp;quot; &amp;quot;    &amp;quot;there&amp;quot;        &amp;quot;,&amp;quot;        &amp;quot; &amp;quot;   &amp;quot;Rstats&amp;quot;        &amp;quot;.&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-using-lex-to-split-some-simplified-r-code-into-tokens&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Using &lt;code&gt;lex()&lt;/code&gt; to split some simplified R code into tokens&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;R_regexes &amp;lt;- c(
  number      = &amp;quot;-?\\d*\\.?\\d+&amp;quot;,
  name        = &amp;quot;\\w+&amp;quot;,
  equals      = &amp;quot;==&amp;quot;,
  assign      = &amp;quot;&amp;lt;-|=&amp;quot;,
  plus        = &amp;quot;\\+&amp;quot;,
  lbracket    = &amp;quot;\\(&amp;quot;,
  rbracket    = &amp;quot;\\)&amp;quot;,
  newline     = &amp;quot;\n&amp;quot;,
  whitespace  = &amp;quot;\\s+&amp;quot;
)

R_code &amp;lt;- &amp;quot;x &amp;lt;- 3 + 4.2 + rnorm(1)&amp;quot;

R_tokens &amp;lt;- flexo::lex(R_code, R_regexes)
R_tokens&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;      name whitespace     assign whitespace     number whitespace       plus 
       &amp;quot;x&amp;quot;        &amp;quot; &amp;quot;       &amp;quot;&amp;lt;-&amp;quot;        &amp;quot; &amp;quot;        &amp;quot;3&amp;quot;        &amp;quot; &amp;quot;        &amp;quot;+&amp;quot; 
whitespace     number whitespace       plus whitespace       name   lbracket 
       &amp;quot; &amp;quot;      &amp;quot;4.2&amp;quot;        &amp;quot; &amp;quot;        &amp;quot;+&amp;quot;        &amp;quot; &amp;quot;    &amp;quot;rnorm&amp;quot;        &amp;quot;(&amp;quot; 
    number   rbracket 
       &amp;quot;1&amp;quot;        &amp;quot;)&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-using-lex-with-tokenstream&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Using &lt;code&gt;lex()&lt;/code&gt; with &lt;code&gt;TokenStream&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Once &lt;code&gt;lex()&lt;/code&gt; is used to create the separate tokens, the next step is to intepret
the token sequence into something much more structured e.g. a data.frame or
matrix.&lt;/p&gt;
&lt;p&gt;The example below shows &lt;code&gt;flexo&lt;/code&gt; being used to to parse a hypothetical tic-tac-toe
game format into a matrix.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A tough game between myself and Kasparov (my pet rock)
# The comment line denotes who the game was between
# Each square is marked with an &amp;#39;X&amp;#39; or &amp;#39;O&amp;#39;
# After each X and O is a number indicating the order in which the mark
# appeared on the board.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
game &amp;lt;- &amp;quot;
# Kasparov(X) vs Coolbutuseless(O)
  X2 | O1 | O5 
  O3 | X4 | X6
  X7 | O8 | X9
&amp;quot;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define all the regexes to split the game into tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
game_regexes &amp;lt;- c(
  comment     = &amp;quot;(#.*?)\n&amp;quot;, 
  whitespace  = &amp;quot;\\s+&amp;quot;,
  sep         = &amp;quot;\\|&amp;quot;,
  mark        = &amp;quot;X|O&amp;quot;,
  order       = flexo::regex$number
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use flexo::lex() to break game into tokens with these regexes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tokens &amp;lt;- flexo::lex(game, game_regexes)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove some tokens that don&amp;#39;t contain actual information
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tokens &amp;lt;- tokens[!names(tokens) %in% c(&amp;#39;whitespace&amp;#39;, &amp;#39;comment&amp;#39;, &amp;#39;sep&amp;#39;)]

tokens&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; mark order  mark order  mark order  mark order  mark order  mark order  mark 
  &amp;quot;X&amp;quot;   &amp;quot;2&amp;quot;   &amp;quot;O&amp;quot;   &amp;quot;1&amp;quot;   &amp;quot;O&amp;quot;   &amp;quot;5&amp;quot;   &amp;quot;O&amp;quot;   &amp;quot;3&amp;quot;   &amp;quot;X&amp;quot;   &amp;quot;4&amp;quot;   &amp;quot;X&amp;quot;   &amp;quot;6&amp;quot;   &amp;quot;X&amp;quot; 
order  mark order  mark order 
  &amp;quot;7&amp;quot;   &amp;quot;O&amp;quot;   &amp;quot;8&amp;quot;   &amp;quot;X&amp;quot;   &amp;quot;9&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a TokenStream object for help in manipulating the tokens
# Obviously there are easier ways to do this on such a simple example, but 
# the below example is hopefully illustrative of the technique
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stream &amp;lt;- TokenStream$new(tokens)

mark  &amp;lt;- c()
order &amp;lt;- c()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Keep processing all the tokens until done.  
# The tokens should exist in pairs of &amp;#39;mark&amp;#39; and &amp;#39;order&amp;#39;, so assert that pairing
# Consume and store the values from the stream into &amp;#39;mark&amp;#39; and &amp;#39;order&amp;#39; vectors
# Bind all the information into a matrix
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
while (!stream$end_of_stream()) {
  stream$assert_name_seq(c(&amp;#39;mark&amp;#39;, &amp;#39;order&amp;#39;))
  mark  &amp;lt;- c(mark , stream$consume(1))
  order &amp;lt;- c(order, stream$consume(1))
}

cbind(mark, order)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     mark order
mark &amp;quot;X&amp;quot;  &amp;quot;2&amp;quot;  
mark &amp;quot;O&amp;quot;  &amp;quot;1&amp;quot;  
mark &amp;quot;O&amp;quot;  &amp;quot;5&amp;quot;  
mark &amp;quot;O&amp;quot;  &amp;quot;3&amp;quot;  
mark &amp;quot;X&amp;quot;  &amp;quot;4&amp;quot;  
mark &amp;quot;X&amp;quot;  &amp;quot;6&amp;quot;  
mark &amp;quot;X&amp;quot;  &amp;quot;7&amp;quot;  
mark &amp;quot;O&amp;quot;  &amp;quot;8&amp;quot;  
mark &amp;quot;X&amp;quot;  &amp;quot;9&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing ggrgl - a 3d extension to ggplot</title>
      <link>https://coolbutuseless.github.io/2020/12/02/introducing-ggrgl-a-3d-extension-to-ggplot/</link>
      <pubDate>Wed, 02 Dec 2020 21:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/12/02/introducing-ggrgl-a-3d-extension-to-ggplot/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;ggrgl&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggrgl &lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/logo.png&#34; align=&#34;right&#34; height=300 title=&#34;An homage to the old logo for the Berlin Hilton&#34;/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggrgl&lt;/code&gt; extends &lt;a href=&#34;https://www.tidyverse.org/ggplot2&#34;&gt;ggplot2&lt;/a&gt; into the third dimension.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggrgl&lt;/code&gt; does this by adding a new &lt;strong&gt;&lt;code&gt;z&lt;/code&gt;&lt;/strong&gt; aesthetic which is respected when a plot
is rendered to the &lt;a href=&#34;https://github.com/coolbutuseless/devoutrgl&#34;&gt;{devoutrgl}&lt;/a&gt; device
which renders to OpenGL via &lt;a href=&#34;https://cran.r-project.org/web/packages/rgl/index.html&#34;&gt;{rgl}&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;{devoutrgl}&lt;/code&gt; is an interactive device, the view of the plot may be
manipulated by the user - zoom, rotate, change field-of-view etc.&lt;/p&gt;
&lt;div id=&#34;slideshow&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Slideshow&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/examples.gif&#34; width=&#34;85%&#34; /&gt;&lt;/p&gt;
&lt;!-- #### Example Gif --&gt;
&lt;!-- &lt;details open&gt; --&gt;
&lt;!-- &lt;summary&gt; Click to hide/reveal an animated gif of a 3d plot &lt;/summary&gt; --&gt;
&lt;!-- &lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/anim1.gif&#34; width=&#34;85%&#34; /&gt; --&gt;
&lt;!-- &lt;/details&gt; --&gt;
&lt;!-- &lt;br/&gt; --&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; interactive 3d plots cannot be displayed in a github README file, and
static images or animated gifs are used here instead.&lt;/p&gt;
&lt;p&gt;Visit the &lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/&#34;&gt;pkgdown online documentation&lt;/a&gt; to view plots
which can be manipulated in the browser.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;A lot of support packages are needed for &lt;code&gt;ggrgl&lt;/code&gt; - most of which should
already be installed if you have &lt;code&gt;ggplot&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Custom packages which are needed (and not currently on CRAN):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;devout&lt;/a&gt; - The core package for
writing graphics devices using R (rather than C).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/devoutrgl&#34;&gt;devoutrgl&lt;/a&gt; - a graphics device
which renders to &lt;code&gt;{rgl}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/triangular&#34;&gt;triangular&lt;/a&gt; - decompaose polygons
into triangles for 3d rendering. Much faster than &lt;code&gt;rgl::triangulate()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/snowcrash&#34;&gt;snowcrash&lt;/a&gt; - a package for
encoding objects as images - needed to circumvent limitations in the
device system provided by R&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/cryogenic&#34;&gt;cryogenic&lt;/a&gt; - a package for
capturing a call to be evaluated later. Calls to generate 3d geometry are
generated when plot object is created, but not executed until later when
the plot is actually rendered to screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/ggrgl&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/devout&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/devoutrgl&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/triangular&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/snowcrash&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cryogenic&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/ggrgl&amp;#39;, ref=&amp;#39;main&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;new-z-aesthetic&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;New &lt;code&gt;z&lt;/code&gt; Aesthetic&lt;/h2&gt;
&lt;p&gt;The new &lt;code&gt;z&lt;/code&gt; aesthetic works the same as the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; aesthetics in &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;z&lt;/code&gt; may be mapped to a data variable or set to a constant.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;new-extrusion-aesthetics&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;New Extrusion Aesthetics&lt;/h2&gt;
&lt;p&gt;When graphical elements have a &lt;code&gt;z&lt;/code&gt; value they are raised above the ground.&lt;/p&gt;
&lt;p&gt;By setting &lt;code&gt;extrude = TRUE&lt;/code&gt; (on geoms which support it), then the raised element
is connected to the ground as if it were extruded from it.&lt;/p&gt;
&lt;p&gt;New aesthetics control the appearance of the extruded faces and edges:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;aesthetic&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;extrude_z&lt;/td&gt;
&lt;td&gt;Lower limit of extrusion&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;extrude_face_fill&lt;/td&gt;
&lt;td&gt;Extruded face colour&lt;/td&gt;
&lt;td&gt;grey20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;extrude_face_alpha&lt;/td&gt;
&lt;td&gt;Extruded face alpha&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;extrude_edge_colour&lt;/td&gt;
&lt;td&gt;Edge colour for extrusion&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;extrude_edge_alpha&lt;/td&gt;
&lt;td&gt;Edge alpha for extrusion&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;extrude_edge_size&lt;/td&gt;
&lt;td&gt;Width of line for extruded edges&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;dimensional-geometry-types-z-and-3d&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;3-dimensional Geometry Types: &lt;code&gt;z&lt;/code&gt; and &lt;code&gt;3d&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ggrgl&lt;/code&gt; defines 2 classes of geoms: &lt;code&gt;z&lt;/code&gt; and &lt;code&gt;3d&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;z&lt;/code&gt; geoms are identical to their &lt;code&gt;ggplot2&lt;/code&gt; counterparts, except the entire
shape may be raised (as a unit) in the z direction. The resulting geometry
will still be planar, and parallel to the original plotting surface.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3d&lt;/code&gt; geoms allow for full specification of (x, y, z) locations. Their orientation
is not constrained to be planar, or parallel to the original plotting surface.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Click on a geom in the following table to view its vignette&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;ggplot2&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Planar Z offset&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;3d&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_bar&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-bar-z.html&#34;&gt;geom_bar_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_contour&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-contour-z.html&#34;&gt;geom_contour_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_contour_filled&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-contour-filled-z.html&#34;&gt;geom_contour_filled_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_density&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-density-z.html&#34;&gt;geom_density_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_line&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-line-3d.html&#34;&gt;geom_line_3d&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_path&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-path-3d.html&#34;&gt;geom_path_3d&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_point&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-point-z.html&#34;&gt;geom_point_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-sphere-3d.html&#34;&gt;geom_sphere_3d&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_polygon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-polygon-z.html&#34;&gt;geom_polygon_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_rect&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-rect-z.html&#34;&gt;geom_rect_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_ribbon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-ribbon-z.html&#34;&gt;geom_ribbon_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_segment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-segment-3d.html&#34;&gt;geom_segment_3d&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_text&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-text-z.html&#34;&gt;geom_text_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;geom_tile&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-tile-z.html&#34;&gt;geom_tile_z&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;p&gt;There are vignettes on all the new geoms in this package, see &lt;strong&gt;links in the table above&lt;/strong&gt; or
&lt;strong&gt;click on an image below&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Some vignettes with some details of the implementation and usage are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/technical-overview.html&#34;&gt;Technical Overview&lt;/a&gt;
gives some details on how the 3d geometry is communicated internally&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/details-z-scaling.html&#34;&gt;Z Scaling&lt;/a&gt; shows examples how
the scaling of the Z coordinate may be controlled.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/details-keep2d.html&#34;&gt;Keep 2d ‘shadows’&lt;/a&gt;
demonstrates how the 2d shadow of 3d geometry may be kept for some supported geoms.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see all vignettes see the &lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/&#34;&gt;online documentation&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/demo-pink-floyd-dark-side-of-the-moon.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/pink-floyd.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/demo-dna-model.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/dna.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-bar-z.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/pie.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-ribbon-z.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/joy-division.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/demo-volcano.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/volcano.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-tile-z.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/terrain.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-segment-3d.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/bunny.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/demo-caffeine-molecule.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/caffeine.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggrgl/articles/geom-polygon-z.html&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/demo/usa.png&#34; width=&#34;80%&#34;&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;example---a-basic-3d-bar-plot-with-geom_bar_z&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - A Basic 3d Bar Plot with &lt;code&gt;geom_bar_z()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use `geom_bar_z` and set `z` to 200 and use extrusion
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot(mpg) +
  geom_bar_z(aes(x=class, fill=class), colour=&amp;#39;black&amp;#39;, z=200, extrude=TRUE)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render Plot in 3d with {devoutrgl}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devoutrgl::rgldev()
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggrgl/readme-example-annotated.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ggplot2.tidyverse.org&#34;&gt;ggplot2&lt;/a&gt; - a grammar of graphics implementation
for 2d plots in R. &lt;code&gt;ggrgl&lt;/code&gt; would be impossible without &lt;code&gt;ggplot2&lt;/code&gt; to
build upon.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hadley Wickham, Thomas Lin Pedersen and others for developing and maintaining &lt;code&gt;ggplot2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Michael Sumner + Tyler Morgan-Wall on twitter for their in-depth technical advice on
graphics and 3d in R&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Demo: Rendering Images in Polygons with {ggplot2} and {ggpattern}</title>
      <link>https://coolbutuseless.github.io/2020/11/18/demo-rendering-images-in-polygons-with-ggplot2-and-ggpattern/</link>
      <pubDate>Wed, 18 Nov 2020 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/18/demo-rendering-images-in-polygons-with-ggplot2-and-ggpattern/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;p&gt;After seeing a &lt;a href=&#34;https://darwinanddavis.github.io/DataPortfolio/30daymapchallenge/#day16&#34;&gt;wonderful plot&lt;/a&gt; by
&lt;a href=&#34;https://twitter.com/darwinanddavis&#34;&gt;darwinanddavis on twitter&lt;/a&gt;, I was reminded
that I need to address some bugs in &lt;a href=&#34;https://github.com/coolbutuseless/ggpattern&#34;&gt;{ggpattern}&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead I made a plot with kittens as the texture for a map of Australia.&lt;/p&gt;
&lt;p&gt;A worthwhile diversion!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(ggplot2)
# remotes::install_github(&amp;quot;coolbutuseless/ggpattern&amp;quot;)
library(ggpattern)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch the map data as a data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
oz_df &amp;lt;- ggplot2::map_data(&amp;#39;world&amp;#39;, &amp;#39;australia&amp;#39;) 
mainland_df &amp;lt;- oz_df %&amp;gt;% filter(
  is.na(subregion)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render the whole of australia (including islands) as a polygon 
# Render mainland australia with kittens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot() + 
  geom_polygon(data = oz_df, mapping = aes(long, lat, group = group)) + 
  geom_polygon_pattern(data = mainland_df, mapping = aes(long, lat, group = group), 
                       pattern = &amp;#39;placeholder&amp;#39;, pattern_type = &amp;#39;kitten&amp;#39;) + 
  coord_equal() + 
  theme_bw() + 
  labs(
    title = &amp;quot;ggpattern::geom_polygon_pattern(..., pattern = &amp;#39;placeholder&amp;#39;)&amp;quot;,
    subtitle = &amp;quot;pattern_type = &amp;#39;kitten&amp;#39;&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-11-18-images-in-polygons_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
</description>

    </item>
    
    <item>
      <title>Play Zork in RStats</title>
      <link>https://coolbutuseless.github.io/2020/11/15/play-zork-in-rstats/</link>
      <pubDate>Sun, 15 Nov 2020 10:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/15/play-zork-in-rstats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;p&gt;&lt;a href=&#34;https://sourceforge.net/projects/frotz/&#34;&gt;Frotz&lt;/a&gt; is an Infocom Z-Machine
interpreter for playing text adventure games (also known as &lt;em&gt;interactive
fiction&lt;/em&gt;) such as Zork and Hitchhiker’s Guide to the Galaxy.&lt;/p&gt;
&lt;p&gt;Here I’m using &lt;a href=&#34;https://cran.r-project.org/package=processx&#34;&gt;{processx}&lt;/a&gt;
to read/write to &lt;em&gt;frotz&lt;/em&gt; on the command line.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Play Zork in the R console with &amp;#39;frotz&amp;#39; + {processx}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
play_zork &amp;lt;- function(game = &amp;quot;../infocom/zork.z3&amp;quot;) {

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Initialise Game
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sf  &amp;lt;- process$new(&amp;#39;dfrotz&amp;#39;, args = c(game),
                     stdin = &amp;#39;|&amp;#39;, stdout = &amp;#39;|&amp;#39;, stderr = &amp;#39;|&amp;#39;)
  Sys.sleep(0.1)
  cat(sf$read_output())

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Game Loop
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  while(TRUE &amp;amp;&amp;amp; sf$is_alive()) {
    cmd &amp;lt;- readline(&amp;quot;&amp;gt;&amp;gt;&amp;gt; &amp;quot;)
    if (cmd == &amp;#39;Q&amp;#39;)  {sf$kill(); break }
    sf$write_input(paste(cmd, &amp;quot;\n&amp;quot;))
    Sys.sleep(0.1)
    cat(gsub(&amp;quot;\\s+&amp;gt;$&amp;quot;, &amp;quot;&amp;quot;, trimws(sf$read_output())), &amp;quot;\n&amp;quot;)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;play_zork()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;video width=&#34;100%&#34; controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/infocom/zork1a.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;&lt;/p&gt;
</description>

    </item>
    
    <item>
      <title>{emphatic} v0.1.3 - highlight data.frame output with ANSI - Added legends &amp; support for vectors</title>
      <link>https://coolbutuseless.github.io/2020/11/11/emphatic-v0.1.3-highlight-data.frame-output-with-ansi-added-legends-support-for-vectors/</link>
      <pubDate>Wed, 11 Nov 2020 07:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/11/emphatic-v0.1.3-highlight-data.frame-output-with-ansi-added-legends-support-for-vectors/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;emphatic&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;emphatic&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/emphatic/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/emphatic/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;div id=&#34;emphatic-augments-the-output-of-data.frames-matrices-and-vectors-in-r-by-adding-user-defined-ansi-highlighting.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;{emphatic}&lt;/code&gt; augments the output of data.frames, matrices and vectors in R by adding user-defined ANSI highlighting.&lt;/h4&gt;
&lt;/div&gt;
&lt;div id=&#34;emphatic-v0.1.3-update&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;{emphatic} v0.1.3 Update&lt;/h2&gt;
&lt;p&gt;This update adds:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support for simple atomic vectors&lt;/li&gt;
&lt;li&gt;option to add legends when colour is applied using ggplot2 colour scales&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;support-for-vectors-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Support for Vectors (1)&lt;/h2&gt;
&lt;div id=&#34;a-simple-random-vector&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;A simple random vector&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v &amp;lt;- sample(letters[1:5], 50, TRUE, (1:5)^2)
v&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;d&amp;quot; &amp;quot;e&amp;quot; &amp;quot;e&amp;quot; &amp;quot;e&amp;quot; &amp;quot;c&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;c&amp;quot; &amp;quot;b&amp;quot; &amp;quot;e&amp;quot; &amp;quot;c&amp;quot; &amp;quot;e&amp;quot; &amp;quot;e&amp;quot; &amp;quot;b&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;b&amp;quot; &amp;quot;d&amp;quot; &amp;quot;b&amp;quot;
[20] &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; &amp;quot;a&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot; &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot; &amp;quot;e&amp;quot; &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot; &amp;quot;b&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot;
[39] &amp;quot;e&amp;quot; &amp;quot;e&amp;quot; &amp;quot;b&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;e&amp;quot; &amp;quot;c&amp;quot; &amp;quot;e&amp;quot; &amp;quot;c&amp;quot; &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; &amp;quot;d&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;highlight-vector-where-a-value-is-the-third-identical-value-in-a-row&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Highlight vector where a value is the third-identical-value-in-a-row&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v %&amp;gt;%
  hl_vec(&amp;#39;red&amp;#39;, .x == lag(.x) &amp;amp; .x == lag(lag(.x)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;[ 1]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#ff0000;&#39;&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;
[20]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;a&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#ff0000;&#39;&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#ff0000;&#39;&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;
[39]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;b&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;e&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;c&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; &#34;d&#34;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;support-for-vectors-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Support for Vectors (2)&lt;/h2&gt;
&lt;div id=&#34;a-simple-random-vector-1&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;A simple random vector&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v &amp;lt;- sample(5, 50, TRUE, (1:5)^2)
v&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 4 5 5 5 3 5 4 3 2 5 3 5 5 2 5 4 2 4 2 3 4 1 4 4 4 3 4 3 4 4 4 5 3 4 4 2 4 4
[39] 5 5 2 5 4 5 3 5 3 3 4 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;highlight-vector-with-a-colour-scale&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Highlight vector with a colour scale&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v %&amp;gt;%
  hl_vec(scale_colour_viridis_c())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;[ 1]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;
[39]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;highlight-vector-with-a-colour-scale.-include-legend&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Highlight vector with a colour scale. Include legend&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v %&amp;gt;%
  hl_vec(scale_colour_viridis_c(), show_legend = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;[ 1]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;
[39]&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;

&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;legend: &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 1.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#452f73;&#39;&gt; 1.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3f5189;&#39;&gt; 2.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#30728d;&#39;&gt; 2.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9089;&#39;&gt; 3.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#36ad7f;&#39;&gt; 3.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#6bc760;&#39;&gt; 4.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#b0da45;&#39;&gt; 4.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 5.0&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;legends&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Legends&lt;/h2&gt;
&lt;p&gt;Legends can be added whenever a ggplot2 colour scale is used to highlight
an object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  head() %&amp;gt;%
  hl(scale_colour_viridis_c(), cols = mpg, dest_cols = .all, show_legend = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span style=&#39;text-decoration:underline;&#39;&gt;                     mpg cyl disp  hp drat    wt  qsec vs am gear carb&lt;/span&gt;
Mazda RX4          &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  160&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 3.90&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 2.620&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 16.46&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;    4&lt;/span&gt;&lt;/span&gt;
Mazda RX4 Wag      &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  160&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 3.90&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 2.875&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 17.02&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt;    4&lt;/span&gt;&lt;/span&gt;
Datsun 710         &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 22.8&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;   4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;  108&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;  93&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 3.85&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 2.320&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 18.61&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt;    1&lt;/span&gt;&lt;/span&gt;
Hornet 4 Drive     &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 21.4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;  258&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 3.08&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 3.215&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 19.44&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt;    1&lt;/span&gt;&lt;/span&gt;
Hornet Sportabout  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 18.7&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;   8&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;  360&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 175&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 3.15&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 3.440&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 17.02&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt;    2&lt;/span&gt;&lt;/span&gt;
Valiant            &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 18.1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;  225&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 105&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 2.76&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 3.460&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 20.22&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt;    1&lt;/span&gt;&lt;/span&gt;

&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;mpg: &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#462369;&#39;&gt; 18.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#424285;&#39;&gt; 19.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3b5e8b;&#39;&gt; 19.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2a798e;&#39;&gt; 20.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9289;&#39;&gt; 20.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#62c167;&#39;&gt; 21.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#91d54c;&#39;&gt; 22.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#d7e138;&#39;&gt; 22.5&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;multiple-legends&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Multiple Legends&lt;/h2&gt;
&lt;p&gt;Multiple legends are possible, but there’s definitely diminishing returns in
interpretability.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  head() %&amp;gt;%
  mutate(cyl = as.factor(cyl)) %&amp;gt;%
  hl(scale_colour_viridis_c(), cols = mpg, show_legend = TRUE) %&amp;gt;%
  hl(scale_colour_discrete(), cols = cyl, show_legend = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span style=&#39;text-decoration:underline;&#39;&gt;     mpg cyl disp  hp drat    wt  qsec vs am gear carb&lt;/span&gt;
1  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#00ba38;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  160&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.90&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 2.620&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 16.46&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    4&lt;/span&gt;&lt;/span&gt;
2  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#00ba38;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  160&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.90&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 2.875&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 17.02&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    4&lt;/span&gt;&lt;/span&gt;
3  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#fde725;&#39;&gt; 22.8&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#f8766d;&#39;&gt;   4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  108&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  93&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.85&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 2.320&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 18.61&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    1&lt;/span&gt;&lt;/span&gt;
4  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#5abd6c;&#39;&gt; 21.4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#00ba38;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  258&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 110&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.08&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.215&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 19.44&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    1&lt;/span&gt;&lt;/span&gt;
5  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#453074;&#39;&gt; 18.7&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#619cff;&#39;&gt;   8&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  360&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 175&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.15&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.440&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 17.02&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    2&lt;/span&gt;&lt;/span&gt;
6  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#440154;&#39;&gt; 18.1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#00ba38;&#39;&gt;   6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  225&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 105&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 2.76&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 3.460&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt; 20.22&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;  0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    3&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;    1&lt;/span&gt;&lt;/span&gt;

&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;mpg: &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#462369;&#39;&gt; 18.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#424285;&#39;&gt; 19.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#3b5e8b;&#39;&gt; 19.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2a798e;&#39;&gt; 20.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#2b9289;&#39;&gt; 20.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#30ab80;&#39;&gt; 21.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#62c167;&#39;&gt; 21.5&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#91d54c;&#39;&gt; 22.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#d7e138;&#39;&gt; 22.5&lt;/span&gt;&lt;/span&gt;
&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span&gt;cyl: &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#f8766d;&#39;&gt; 4&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#00ba38;&#39;&gt; 6&lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#619cff;&#39;&gt; 8&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/emphatic&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/emphatic&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the &lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/index.html&#34;&gt;online documentation&lt;/a&gt; for
vignettes and more examples.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;slideshow&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Slideshow&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/examples.gif&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A Chess Engine  in RStats (Proof-of-Concept using Stockfish)</title>
      <link>https://coolbutuseless.github.io/2020/11/05/a-chess-engine-in-rstats-proof-of-concept-using-stockfish/</link>
      <pubDate>Thu, 05 Nov 2020 20:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/05/a-chess-engine-in-rstats-proof-of-concept-using-stockfish/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-queens-gambit---post-5&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Queen’s Gambit - Post 5&lt;/h1&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://www.netflix.com/title/80234304&#34;&gt;The Queen’s Gambit&lt;/a&gt; on Netflix,
I’m doing a few posts on Chess in R.&lt;/p&gt;
&lt;p&gt;This screenshot from the show explains everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=https://coolbutuseless.github.io/img/8queens/shot.png width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;stockfish&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Stockfish&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://stockfishchess.org/&#34;&gt;stockfish&lt;/a&gt; is a free, open source chess engine
which implements the &lt;a href=&#34;https://en.wikipedia.org/wiki/Universal_Chess_Interface&#34;&gt;UCI (Universal Chess Interface)&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;installation-of-stockfish&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Installation of Stockfish&lt;/h4&gt;
&lt;p&gt;On MacOS (with homebrew installed): &lt;code&gt;brew install stockfish&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&#34;https://stockfishchess.org/&#34;&gt;stockfish website&lt;/a&gt; for more details on installation on your system&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;processx&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;{processx}&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To interface with Stockfish (a command line/terminal program) I’m using
&lt;code&gt;processx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/r-lib/processx&#34;&gt;processx&lt;/a&gt; is a package for executing and controlling
subprocesses (like a command like program) from R. You can write to the program’s &lt;code&gt;stdin&lt;/code&gt;
and then read what it outputs (&lt;code&gt;stdout&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-interfacing-with-stockfish-using-processx&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple interfacing with Stockfish using &lt;code&gt;{processx}&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Run &amp;#39;stockfish&amp;#39; on the command line and set up pipes so we can send and 
# receive messages from stdin and stdou
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf  &amp;lt;- process$new(&amp;#39;stockfish&amp;#39;, stdin = &amp;#39;|&amp;#39;, stdout = &amp;#39;|&amp;#39;, stderr = &amp;#39;|&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# UCI standard says that you should always request &amp;#39;uci&amp;#39; from whatever ches
# ending you&amp;#39;re using.  This outputs the configuration in stockfish
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf$write_input(&amp;#39;uci\n&amp;#39;)
cat(sf$read_output_lines())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Stockfish 12 by the Stockfish developers (see AUTHORS file)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise the board to the opening state and a couple of basic moves.
# There&amp;#39;s no &amp;quot;opening book&amp;quot; in stockfish
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf$write_input(&amp;#39;position startpos moves e2e4 e7e5\n&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ask stockfish to think about this move for 0.1 second (100 ms)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf$write_input(&amp;#39;go movetime 100\n&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# wait for Stockfish to think 
# Need to be certain that it finishes and prints out its move
# Note: probably nicer ways to wait via processx, but haven&amp;#39;t dug deep enough yet
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sys.sleep(1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get all the output that stockfish produces.
# There&amp;#39;s a lot of lines that start with &amp;#39;info&amp;#39; which are steps along its
# thinking process.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf_response &amp;lt;- sf$read_output_lines()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The only line that i&amp;#39;m interested in is the last one which is the 
# description of the &amp;#39;bestmove&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
best_move_line &amp;lt;- tail(sf_response, 1)
best_move      &amp;lt;- strsplit(best_move_line, &amp;quot; &amp;quot;)[[1]][2]
best_move_line&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;bestmove g1f3 ponder g8f6&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;best_move&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;g1f3&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;stockfish-based-chess-game-in-rstats&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Stockfish-based Chess game in RStats&lt;/h2&gt;
&lt;p&gt;The following code is a very rough chess engine in R using Stockfish to
make the computer’s moves.&lt;/p&gt;
&lt;p&gt;Instructions:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Enter &lt;code&gt;Your Move:&lt;/code&gt; in &lt;a href=&#34;https://en.wikipedia.org/wiki/Chess_notation&#34;&gt;Long Algebraic Notation (LAN)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;e2e4&lt;/code&gt; is a valid opening move&lt;/li&gt;
&lt;li&gt;The first 2 symbols are the starting location &lt;code&gt;e2&lt;/code&gt; i.e. White King’s Pawn&lt;/li&gt;
&lt;li&gt;The second 2 symbols are the destination &lt;code&gt;e4&lt;/code&gt; i.e. 
the fourth row in column &lt;code&gt;e&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The computer will make a move (after thinking for 0.1 seconds)&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;q&lt;/code&gt; to quit when it’s your turn to move.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Limitiations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no move validation, so there’s no prevention of impossible moves.
&lt;ul&gt;
&lt;li&gt;What stockfish does with impossible moves is undefined as far as I know.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;No detection of ‘end-of-game’&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;no castling&lt;/li&gt;
&lt;li&gt;I’ve given Stockfish very little thinking time by default (0.1s) - feel
free to make this longer if you need a challenge.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
&lt;summary&gt;
Click to reveal/hide support functions
&lt;/summary&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Convert a FEN string to a char matrix representing the chess board.
#&amp;#39; 
#&amp;#39; @param fen fen string
#&amp;#39; 
#&amp;#39; @return 8x8 character matrix representing the chess board
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fen_to_matrix &amp;lt;- function(fen) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Currently only interested in 1st field in fen i.e. piece placement
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pieces &amp;lt;- strsplit(fen, &amp;#39; &amp;#39;)[[1]][1]
  rows   &amp;lt;- strsplit(pieces, &amp;quot;/&amp;quot;)[[1]]
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Replaces digits with the number of spaces they represent
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i in 1:8) {
    rows &amp;lt;- gsub(i, paste(rep(&amp;#39; &amp;#39;, i), collapse=&amp;#39;&amp;#39;), rows)
  }
  
  matrix(unlist(strsplit(rows, &amp;#39;&amp;#39;)), 8, 8, byrow = TRUE, list(c(8:1), letters[1:8]))
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a plot of the state of a chess board from a FEN string
#&amp;#39;
#&amp;#39; @param fen FEN string
#&amp;#39;
#&amp;#39; @return ggplot2 object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_board &amp;lt;- function(mat) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Unicode chars for chess pieces
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unicode &amp;lt;- c(
    ` ` = &amp;#39;&amp;#39;,
    P=&amp;#39;\u2659&amp;#39;, R=&amp;#39;\u2656&amp;#39;, N=&amp;#39;\u2658&amp;#39;, B=&amp;#39;\u2657&amp;#39;, Q=&amp;#39;\u2655&amp;#39;, K=&amp;#39;\u2654&amp;#39;, # White
    p=&amp;#39;\u265F&amp;#39;, r=&amp;#39;\u265C&amp;#39;, n=&amp;#39;\u265E&amp;#39;, b=&amp;#39;\u265D&amp;#39;, q=&amp;#39;\u265B&amp;#39;, k=&amp;#39;\u265A&amp;#39;  # Black
  )
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Convert the matrix chess board to a data.frame
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  board &amp;lt;- expand.grid(x=1:8, y=1:8) %&amp;gt;%
    mutate(
      tilecol = (x+y)%%2 == 1,
      piece  = as.vector(t(mat[8:1,])),
      colour = piece %in% letters,
      unicode = unicode[piece]
    )
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create plot
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  p &amp;lt;- ggplot(board, aes(x, y)) + 
    geom_tile(aes(fill = tilecol), colour = &amp;#39;black&amp;#39;, show.legend = FALSE) + 
    geom_text(aes(label = unicode), family=&amp;quot;Arial Unicode MS&amp;quot;, size = 8) + 
    coord_equal() + 
    scale_fill_manual(values = c(&amp;#39;grey50&amp;#39;, &amp;#39;grey95&amp;#39;)) +
    scale_y_continuous(breaks = 1:8) + 
    scale_x_continuous(breaks = 1:8, labels = letters[1:8]) +
    theme_bw() +
    theme(
      axis.title      = element_blank(),
      plot.background = element_blank(),
      panel.grid      = element_blank(),
      panel.border    = element_blank(),
      axis.ticks      = element_blank()
    )
  
  plot(p)
  
  invisible()
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Super basic Long Annoation to matrix coordinates
# 
# @param lan e.g. e2e5
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lan_to_coords &amp;lt;- function(lan) {
  stopifnot(nchar(lan) == 4)
  lan &amp;lt;- tolower(lan)
  
  bits &amp;lt;- strsplit(lan, &amp;#39;&amp;#39;)[[1]]
  bits[1] &amp;lt;- match(bits[1], letters[1:8])
  bits[3] &amp;lt;- match(bits[3], letters[1:8])
  bits &amp;lt;- as.integer(bits)
  
  list(
    start = matrix(c(9 - bits[2], bits[1]), nrow = 1),
    end   = matrix(c(9 - bits[4], bits[3]), nrow = 1)
  )
  
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(processx)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Start the Stockfish proces
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sf  &amp;lt;- process$new(&amp;#39;stockfish&amp;#39;, stdin = &amp;#39;|&amp;#39;, stdout = &amp;#39;|&amp;#39;, stderr = &amp;#39;|&amp;#39;)
sf$write_input(&amp;#39;uci\n&amp;#39;)
jnk &amp;lt;- sf$read_output_lines()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise board (i.e. matrix) to opening position
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fen &amp;lt;- &amp;#39;rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1&amp;#39;
board &amp;lt;- fen_to_matrix(fen)
plot_board(board)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Keep track of all the moves played. This list of moves is fed to Stockfish
# every time, and then it decides what the next move should be
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_moves &amp;lt;- c()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Game Loop
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
while(TRUE) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Ask user for a move and add it to the list of all moves
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  move_lan &amp;lt;- readline(&amp;quot;Your move?   : &amp;quot;)
  if (move_lan %in% c(&amp;#39;&amp;#39;, &amp;#39;q&amp;#39;, &amp;#39;Q&amp;#39;, &amp;#39;quit&amp;#39;)) {
    message(&amp;quot;Done&amp;quot;)
    break
  }
  
  all_moves &amp;lt;- c(all_moves, move_lan)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Validate move
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Not done yet
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Move the piece on the local board
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  move_coords &amp;lt;- lan_to_coords(move_lan)
  if (board[move_coords$start] %in% c(NA, &amp;#39; &amp;#39;, &amp;#39;&amp;#39;)) {
    stop(&amp;quot;Bad move given current board state: &amp;quot;, best_move)
  }
  board[move_coords$end  ] &amp;lt;- board[move_coords$start]
  board[move_coords$start] &amp;lt;- &amp;#39; &amp;#39;
  plot_board(board)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Tell stockfish about the move
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  moves &amp;lt;- paste(all_moves, collapse = &amp;quot; &amp;quot;)
  cmd   &amp;lt;- paste(&amp;#39;position startpos moves&amp;#39;, moves, &amp;#39;\n&amp;#39;)
  # print(cmd)
  sf$write_input(cmd)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Ask stockfish to consider the next move for 0.1 seconds
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sf$write_input(&amp;#39;go movetime 100\n&amp;#39;)
  Sys.sleep(0.2)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Extract the best move from output from Stockfish
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sf_response    &amp;lt;- sf$read_output_lines()
  best_move_line &amp;lt;- tail(sf_response, 1)
  best_move      &amp;lt;- strsplit(best_move_line, &amp;quot; &amp;quot;)[[1]][2]
  cat(&amp;quot;Computer move:&amp;quot;, best_move, &amp;quot;\n&amp;quot;)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Add the computers move
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  all_moves &amp;lt;- c(all_moves, best_move)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Move the piece on the local board
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  move_coords &amp;lt;- lan_to_coords(best_move)
  if (board[move_coords$start] %in% c(NA, &amp;#39; &amp;#39;, &amp;#39;&amp;#39;)) {
    stop(&amp;quot;Bad move given current board state: &amp;quot;, best_move)
  }
  board[move_coords$end  ] &amp;lt;- board[move_coords$start]
  board[move_coords$start] &amp;lt;- &amp;#39; &amp;#39;
  plot_board(board)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;video width=&#34;65%&#34; controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/8queens/chess-engine.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Parsing Forsyth Edwards Notation for Chess in RStats</title>
      <link>https://coolbutuseless.github.io/2020/11/05/parsing-forsyth-edwards-notation-for-chess-in-rstats/</link>
      <pubDate>Thu, 05 Nov 2020 06:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/05/parsing-forsyth-edwards-notation-for-chess-in-rstats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-queens-gambit---post-4&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Queen’s Gambit - Post 4&lt;/h1&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://www.netflix.com/title/80234304&#34;&gt;The Queen’s Gambit&lt;/a&gt; on Netflix,
I’m doing a few posts on Chess in R.&lt;/p&gt;
&lt;p&gt;This screenshot from the show explains everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=https://coolbutuseless.github.io/img/8queens/shot.png width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;forsyth-edwards-notation-fen&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Forsyth-Edwards Notation (FEN)&lt;/h2&gt;
&lt;p&gt;Forsyth-Edwards Notation (FEN) is a short ascii description of the state of play of a
game of chess.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&#34;https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation&#34;&gt;the article on wikipedia&lt;/a&gt; for a more complete description.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;examples-of-fen&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Examples of FEN&lt;/h2&gt;
&lt;p&gt;Initial state of a chess game&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an actual board state when opening with the queen’s gambit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR b KQkq c3 0 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;fen-format&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;FEN format&lt;/h2&gt;
&lt;p&gt;A FEN record contains six fields. The separator between fields is a space. The fields are:[5]&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Piece placement (from White’s perspective). Each rank is described, starting with rank 8 and ending with rank 1; within each rank, the contents of each square are described from file “a” through file “h”. Following the Standard Algebraic Notation (SAN), each piece is identified by a single letter taken from the standard English names (pawn = “P”, knight = “N”, bishop = “B”, rook = “R”, queen = “Q” and king = “K”). White pieces are designated using upper-case letters (“PNBRQK”) while black pieces use lowercase (“pnbrqk”). Empty squares are noted using digits 1 through 8 (the number of empty squares), and “/” separates ranks.&lt;/li&gt;
&lt;li&gt;Active color. “w” means White moves next, “b” means Black moves next.&lt;/li&gt;
&lt;li&gt;Castling availability. If neither side can castle, this is “-”. Otherwise, this has one or more letters: “K” (White can castle kingside), “Q” (White can castle queenside), “k” (Black can castle kingside), and/or “q” (Black can castle queenside). A move that temporarily prevents castling does not negate this notation.&lt;/li&gt;
&lt;li&gt;En passant target square in algebraic notation. If there’s no en passant target square, this is “-”. If a pawn has just made a two-square move, this is the position “behind” the pawn. This is recorded regardless of whether there is a pawn in position to make an en passant capture.[6]&lt;/li&gt;
&lt;li&gt;Halfmove clock: This is the number of halfmoves since the last capture or pawn advance. The reason for this field is that the value is used in the fifty-move rule.[7]&lt;/li&gt;
&lt;li&gt;Fullmove number: The number of the full move. It starts at 1, and is incremented after Black’s move.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;parsing-piece-placement-from-a-fen-record&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Parsing Piece Placement from a FEN record&lt;/h2&gt;
&lt;p&gt;The following code is only determining the placement of pieces on the board.
All other information is ignored.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Convert a FEN string to a char matrix representing the chess board.
#&amp;#39; 
#&amp;#39; @param fen fen string
#&amp;#39; 
#&amp;#39; @return 8x8 character matrix representing the chess board
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fen_to_matrix &amp;lt;- function(fen) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Currently only interested in 1st field in fen i.e. piece placement
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pieces &amp;lt;- strsplit(fen, &amp;#39; &amp;#39;)[[1]][1]
  rows   &amp;lt;- strsplit(pieces, &amp;quot;/&amp;quot;)[[1]]
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Replaces digits with the number of spaces they represent
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i in 1:8) {
    rows &amp;lt;- gsub(i, paste(rep(&amp;#39; &amp;#39;, i), collapse=&amp;#39;&amp;#39;), rows)
  }
  
  matrix(unlist(strsplit(rows, &amp;#39;&amp;#39;)), 8, 8, byrow = TRUE, list(c(8:1), letters[1:8]))
}


fen &amp;lt;- &amp;#39;rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR b KQkq c3 0 2&amp;#39;
fen_to_matrix(fen)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   a   b   c   d   e   f   g   h  
## 8 &amp;quot;r&amp;quot; &amp;quot;n&amp;quot; &amp;quot;b&amp;quot; &amp;quot;q&amp;quot; &amp;quot;k&amp;quot; &amp;quot;b&amp;quot; &amp;quot;n&amp;quot; &amp;quot;r&amp;quot;
## 7 &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot; &amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot;
## 6 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 5 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;p&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 4 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 3 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 2 &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot;
## 1 &amp;quot;R&amp;quot; &amp;quot;N&amp;quot; &amp;quot;B&amp;quot; &amp;quot;Q&amp;quot; &amp;quot;K&amp;quot; &amp;quot;B&amp;quot; &amp;quot;N&amp;quot; &amp;quot;R&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;tighter-matrix-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tighter matrix output&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mat &amp;lt;- fen_to_matrix(fen)
mat[mat ==&amp;#39; &amp;#39;] &amp;lt;- &amp;#39;.&amp;#39;
cat(apply(mat, 1, paste, collapse=&amp;#39;&amp;#39;), sep=&amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## rnbqkbnr
## ppp.pppp
## ........
## ...p....
## ..PP....
## ........
## PP..PPPP
## RNBQKBNR&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;add-a-splash-of-colour-with-emphatic&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Add a splash of colour with &lt;code&gt;{emphatic}&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# remotes::install_github(&amp;#39;coolbutuseless/emphatic&amp;#39;)
library(emphatic)
library(dplyr)
hl_opt_global(dark_mode = FALSE)

mat &amp;lt;- fen_to_matrix(fen) 
mat[] &amp;lt;- paste0(mat, &amp;#39; &amp;#39;)

mat %&amp;gt;% 
  hl_matrix(&amp;#39;grey90&amp;#39;) %&amp;gt;% 
  hl_matrix(&amp;#39;grey10&amp;#39;, selection = (row(.x) + col(.x)) %% 2 == 1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span style=&#39;text-decoration:underline;&#39;&gt;     a  b  c  d  e  f  g  h&lt;/span&gt;
8  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; r &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; n &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; b &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; q &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; k &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; b &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; n &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; r &lt;/span&gt;&lt;/span&gt;
7  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;
6  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;
5  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; p &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;
4  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;
3  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;
2  &lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; P &lt;/span&gt;&lt;/span&gt;
1  &lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; R &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; N &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; B &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; Q &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; K &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; B &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#ffffff;&#39;&gt;&lt;span style=&#39;background-color:#1a1a1a;&#39;&gt; N &lt;/span&gt;&lt;/span&gt;&lt;span style=&#39;color:#000000;&#39;&gt;&lt;span style=&#39;background-color:#e5e5e5;&#39;&gt; R &lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;ggplot-of-the-board-state-from-a-fen&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ggplot of the board state from a FEN&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a plot of the state of a chess board from a FEN string
#&amp;#39;
#&amp;#39; @param fen FEN string
#&amp;#39;
#&amp;#39; @return ggplot2 object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_fen_plot &amp;lt;- function(fen) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Convert fen to matrix
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mat &amp;lt;- fen_to_matrix(fen)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Unicode chars for chess pieces
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  unicode &amp;lt;- c(
    ` ` = &amp;#39;&amp;#39;,
    P=&amp;#39;\u2659&amp;#39;, R=&amp;#39;\u2656&amp;#39;, N=&amp;#39;\u2658&amp;#39;, B=&amp;#39;\u2657&amp;#39;, Q=&amp;#39;\u2655&amp;#39;, K=&amp;#39;\u2654&amp;#39;, # White
    p=&amp;#39;\u265F&amp;#39;, r=&amp;#39;\u265C&amp;#39;, n=&amp;#39;\u265E&amp;#39;, b=&amp;#39;\u265D&amp;#39;, q=&amp;#39;\u265B&amp;#39;, k=&amp;#39;\u265A&amp;#39;  # Black
  )
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Convert the matrix chess board to a data.frame
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  board &amp;lt;- expand.grid(x=1:8, y=1:8) %&amp;gt;%
    mutate(
      tilecol = (x+y)%%2 == 1,
      piece  = as.vector(t(mat[8:1,])),
      colour = piece %in% letters,
      unicode = unicode[piece]
    )
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create plot
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ggplot(board, aes(x, y)) + 
    geom_tile(aes(fill = tilecol), colour = &amp;#39;black&amp;#39;, show.legend = FALSE) + 
    geom_text(aes(label = unicode), family=&amp;quot;Arial Unicode MS&amp;quot;, size = 8) + 
    coord_equal() + 
    theme_void() +
    scale_fill_manual(values = c(&amp;#39;grey50&amp;#39;, &amp;#39;grey95&amp;#39;))  +
    labs(
      title = &amp;quot;Forsyth-Edwards Notation of the Queen&amp;#39;s Gambit in #RStats&amp;quot;,
      subtitle = fen
    )
  
}


create_fen_plot(fen)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-11-05-queens-gambit-parsing-forsyth-edwards-chess-notation_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;convert-a-matrix-of-chess-locations-into-fen&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convert a matrix of chess locations into FEN&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Matrix to Forsyth-Edwards Notation notation
#&amp;#39;
#&amp;#39; This function only considers piece positions. All other information is
#&amp;#39; filled in with dummy values e.g. next move is always set to white (0)
#&amp;#39;
#&amp;#39; @param mat 8x8 character matrix of chess locations. 
#&amp;#39;
#&amp;#39; @return Single character string containing board status in Forsyth-Edwards Notation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
matrix_to_fen &amp;lt;- function(mat) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Sanity check board
  # Empty board spaces must be a single blank character
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  stopifnot(is.character(mat))
  stopifnot(nrow(mat) == 8, ncol(mat) == 8)
  mat[is.na(mat) | mat == &amp;#39;&amp;#39;] &amp;lt;- &amp;#39; &amp;#39;
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Collapse each row
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  rows &amp;lt;- apply(mat, 1, paste, collapse=&amp;#39;&amp;#39;)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Replace runs of spaces with the integer count of spaces
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i in 8:1) {
    rows &amp;lt;- gsub(paste(rep(&amp;#39; &amp;#39;, i), collapse=&amp;#39;&amp;#39;), i, rows)
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # piece position is rows concatentated with &amp;quot;/&amp;quot; as dividing character
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pieces &amp;lt;- paste(rows, collapse=&amp;quot;/&amp;quot;)

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  # Remaining information filled out with dummy values
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  move      &amp;lt;- &amp;#39;w&amp;#39;
  castling  &amp;lt;- &amp;#39;KQkq&amp;#39;
  enpassant &amp;lt;- &amp;#39;-&amp;#39;
  halfmove  &amp;lt;- 0
  fullmove  &amp;lt;- 1

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Concatenate all the information together - separated by spaces
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  paste(pieces, move, castling, enpassant, halfmove, fullmove)
}


fen&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR b KQkq c3 0 2&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mat &amp;lt;- fen_to_matrix(fen) 
mat&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##   a   b   c   d   e   f   g   h  
## 8 &amp;quot;r&amp;quot; &amp;quot;n&amp;quot; &amp;quot;b&amp;quot; &amp;quot;q&amp;quot; &amp;quot;k&amp;quot; &amp;quot;b&amp;quot; &amp;quot;n&amp;quot; &amp;quot;r&amp;quot;
## 7 &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot; &amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot; &amp;quot;p&amp;quot;
## 6 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 5 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;p&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 4 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 3 &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;
## 2 &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot; &amp;quot;P&amp;quot;
## 1 &amp;quot;R&amp;quot; &amp;quot;N&amp;quot; &amp;quot;B&amp;quot; &amp;quot;Q&amp;quot; &amp;quot;K&amp;quot; &amp;quot;B&amp;quot; &amp;quot;N&amp;quot; &amp;quot;R&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;matrix_to_fen(mat)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;rnbqkbnr/ppp1pppp/8/3p4/2PP4/8/PP2PPPP/RNBQKBNR w KQkq - 0 1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Parsing Chess PGN files in RStats</title>
      <link>https://coolbutuseless.github.io/2020/11/04/parsing-chess-pgn-files-in-rstats/</link>
      <pubDate>Wed, 04 Nov 2020 20:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/04/parsing-chess-pgn-files-in-rstats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-queens-gambit---post-3&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Queen’s Gambit - Post 3&lt;/h1&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://www.netflix.com/title/80234304&#34;&gt;The Queen’s Gambit&lt;/a&gt; on Netflix,
I’m doing a few posts on Chess in R.&lt;/p&gt;
&lt;p&gt;This screenshot from the show explains everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=https://coolbutuseless.github.io/img/8queens/shot.png width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;chess-game-format-pgn&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Chess game format: pgn&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Portable_Game_Notation&#34;&gt;pgn file format&lt;/a&gt; is a human readable
representation of a chess game.&lt;/p&gt;
&lt;p&gt;In its most basic form, it consists of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a sequence of tags (i.e. comments) surrounded by &lt;code&gt;[]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a sequence of numbers and events representing the moves taken by the players i.e.
&lt;ul&gt;
&lt;li&gt;A number indicating which move this is within the game.&lt;/li&gt;
&lt;li&gt;Moves the for the white and black player represented in &lt;a href=&#34;https://en.wikipedia.org/wiki/Algebraic_notation_(chess)&#34;&gt;Standard Algebraic Notation (SAN)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Comments can be interspersed between/within the moves and are surrounded by “{}”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example &lt;code&gt;pgn&lt;/code&gt; file is show below:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;alekhine_pgn &amp;lt;- r&amp;#39;{[Event &amp;quot;Vilnius All-Russian Masters&amp;quot;]
[Site &amp;quot;Vilna (Vilnius) RUE&amp;quot;]
[Date &amp;quot;1912.08.23&amp;quot;]
[EventDate &amp;quot;1912.08.19&amp;quot;]
[Round &amp;quot;5&amp;quot;]
[Result &amp;quot;0-1&amp;quot;]
[White &amp;quot;Alexander Alekhine&amp;quot;]
[Black &amp;quot;Akiba Rubinstein&amp;quot;]
[ECO &amp;quot;C83&amp;quot;]
[WhiteElo &amp;quot;?&amp;quot;]
[BlackElo &amp;quot;?&amp;quot;]
[PlyCount &amp;quot;54&amp;quot;]

1. e4 {Notes by Dr. Savielly Tartakower.} 1... e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4
Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. dxe5 Be6 9. c3 Be7 10. Nbd2 Nc5 11. Bc2
Bg4 12. h3 {The most reasonable course here is 12.Re1, guarding the e-pawn.}
12... Bh5 13. Qe1 $6 {Here again 13. Re1 ensured a very good game for White.}
13... Ne6 14. Nh2 $6 Bg6 $1 15. Bxg6 fxg6 {! Far seeing strategy! Black
recognizes that the f-file and not the e-file will be needed as a base for
action.} 16. Nb3 {Or 16.f4 d4!.} 16... g5 $1 17. Be3 O-O 18. Nf3 Qd7 19. Qd2
{White pays insufficient attention to the scope of his opponent&amp;#39;s threats. A
better course is 19.Nfd4 (19...Nxe5 20.Bxg5) seeking to establish equality.}
19... Rxf3 $1 20. gxf3 Nxe5 21. Qe2 Rf8 22. Nd2 Ng6 23. Rfe1 Bd6 24. f4 Nexf4
25. Qf1 Nxh3+ 26. Kh1 g4 27. Qe2 Qf5 0-1}&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;use-lex-to-turn-the-text-into-tokens&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use &lt;code&gt;lex()&lt;/code&gt; to turn the text into tokens&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Start by defining the regular expression patterns for each element in the pgn file.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;minilexer::lex()&lt;/code&gt; to turn the &lt;em&gt;pgn&lt;/em&gt; text into tokens&lt;/li&gt;
&lt;li&gt;Throw away whitespace, newlines and tags, since I’m not interested in them.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use the mini-lexer to break text into labelled tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# remotes::install_github(&amp;#39;coolbutuseless/minilexer&amp;#39;)
library(minilexer)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define all the patterns to match as regular expressions.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pgn_patterns &amp;lt;- c(
  tag           = &amp;#39;\\[.*?\\]&amp;#39;,     # Capture tags as a unit
  comment       = &amp;quot;\\{.*?\\}&amp;quot;,     # Capture comments as a unit
  resumption    = &amp;quot;\\d+\\.\\.\\.&amp;quot;, # Resume moves after comment
  move_number   = &amp;quot;\\d+\\.&amp;quot;,
  end_of_game   = &amp;#39;0-1|1-0|0-0|1/2-1/2&amp;#39;,
  nag           = &amp;#39;\\$\\d+&amp;#39;,      # Numeric annotation glyph
  move          = &amp;#39;[-+\\w\\./]+&amp;#39;, # Anything else is a move
  newline       = &amp;#39;\n&amp;#39;,
  whitespace    = &amp;#39;\\s+&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define some different sets of tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chaff     &amp;lt;- c(&amp;#39;whitespace&amp;#39;, &amp;#39;newline&amp;#39;, &amp;#39;tag&amp;#39;)
non_moves &amp;lt;- c(&amp;#39;comment&amp;#39;, &amp;#39;resumption&amp;#39;, &amp;#39;nag&amp;#39;, &amp;#39;end_of_game&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Parse a PGN file to tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pgn_text &amp;lt;- alekhine_pgn
pgn_text &amp;lt;- gsub(&amp;quot;\n&amp;quot;, &amp;#39; &amp;#39;, pgn_text)
tokens   &amp;lt;- minilexer::lex(pgn_text, pgn_patterns)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Tidy the tokens
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tags   &amp;lt;- tokens[names(tokens) == &amp;#39;tag&amp;#39;]
tokens &amp;lt;- tokens[!(names(tokens) %in% chaff)]

head(tokens, 20)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##                           move_number                                  move 
##                                  &amp;quot;1.&amp;quot;                                  &amp;quot;e4&amp;quot; 
##                               comment                            resumption 
## &amp;quot;{Notes by Dr. Savielly Tartakower.}&amp;quot;                                &amp;quot;1...&amp;quot; 
##                                  move                           move_number 
##                                  &amp;quot;e5&amp;quot;                                  &amp;quot;2.&amp;quot; 
##                                  move                                  move 
##                                 &amp;quot;Nf3&amp;quot;                                 &amp;quot;Nc6&amp;quot; 
##                           move_number                                  move 
##                                  &amp;quot;3.&amp;quot;                                 &amp;quot;Bb5&amp;quot; 
##                                  move                           move_number 
##                                  &amp;quot;a6&amp;quot;                                  &amp;quot;4.&amp;quot; 
##                                  move                                  move 
##                                 &amp;quot;Ba4&amp;quot;                                 &amp;quot;Nf6&amp;quot; 
##                           move_number                                  move 
##                                  &amp;quot;5.&amp;quot;                                 &amp;quot;O-O&amp;quot; 
##                                  move                           move_number 
##                                &amp;quot;Nxe4&amp;quot;                                  &amp;quot;6.&amp;quot; 
##                                  move                                  move 
##                                  &amp;quot;d4&amp;quot;                                  &amp;quot;b5&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;final-game-record-after-some-manual-tidying&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Final Game Record (after some manual tidying)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;Tag&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Event&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vilnius All-Russian Masters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Site&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vilna (Vilnius) RUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Date&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1912.08.23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;EventDate&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1912.08.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Round&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Result&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;0-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;White&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Alexander Alekhine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Black&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Akiba Rubinstein&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ECO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;C83&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;WhiteElo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;BlackElo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;PlyCount&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;54&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;2%&#34; /&gt;
&lt;col width=&#34;3%&#34; /&gt;
&lt;col width=&#34;3%&#34; /&gt;
&lt;col width=&#34;90%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;White&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Black&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Comment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;1.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Notes by Dr. Savielly Tartakower.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;2.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nf3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nc6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;3.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bb5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;4.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ba4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nf6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;5.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;O-O&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nxe4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;6.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;d4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;b5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;7.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bb3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;d5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;8.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dxe5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Be6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;9.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Be7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;10.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nbd2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nc5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;11.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bc2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bg4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;12.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;h3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bh5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The most reasonable course here is 12.Re1, guarding the e-pawn.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;13.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qe1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ne6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Here again 13. Re1 ensured a very good game for White.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;14.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nh2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bg6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;15.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bxg6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fxg6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;! Far seeing strategy! Black recognizes that the f-file and not the e-file will be needed as a base for action.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;16.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nb3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;g5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Or 16.f4 d4!.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;17.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Be3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;O-O&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;18.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nf3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qd7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;19.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qd2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rxf3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;White pays insufficient attention to the scope of his opponent’s threats. A better course is 19.Nfd4 (19…Nxe5 20.Bxg5) seeking to establish equality.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;20.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;gxf3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nxe5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;21.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qe2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rf8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;22.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nd2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ng6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;23.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rfe1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bd6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;24.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nexf4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;25.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qf1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nxh3+&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;26.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Kh1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;g4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;27.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qe2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Qf5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Knight&#39;s Tour Problem</title>
      <link>https://coolbutuseless.github.io/2020/11/03/knights-tour-problem/</link>
      <pubDate>Tue, 03 Nov 2020 20:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/03/knights-tour-problem/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-queens-gambit---post-2&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Queen’s Gambit - Post 2&lt;/h1&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://www.netflix.com/title/80234304&#34;&gt;The Queen’s Gambit&lt;/a&gt; on Netflix,
I’m doing a few posts on Chess in R.&lt;/p&gt;
&lt;p&gt;This screenshot from the show explains everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=https://coolbutuseless.github.io/img/8queens/shot.png width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction-to-the-knights-tour-problem&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction to the Knight’s Tour problem&lt;/h1&gt;
&lt;p&gt;The knight’s tour is a sequence of moves of a single knight such that it
visits every square on the board once only.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Knight%27s_tour&#34;&gt;wikipedia page&lt;/a&gt; is a good starting resource.&lt;/p&gt;
&lt;p&gt;This post contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A recursive function for finding a solution given a starting move: &lt;code&gt;move_knight()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A solution to the knight’s tour that fits in a tweet&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;recursive-solution-in-r-for-the-knights-tour-problem&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Recursive solution in R for the Knight’s Tour Problem&lt;/h1&gt;
&lt;p&gt;The following code finds an 8x8 knight’s tour in less than a second.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(purrr)
library(dplyr)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Knight offsets i.e. the possible movements of a knight from the current location
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
knight_offsets &amp;lt;- matrix(c(
    1,    2,
    2,    1,
   -2,    1,
   -1,    2,
    2,   -1,
    1,   -2,
   -1,   -2,
   -2,   -1
), ncol = 2, byrow = TRUE)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Recurisvely calculate moves for a knight to complete a tour
#&amp;#39;
#&amp;#39; @param this_move proposed next move. 2 element numeric vector of (row, col)
#&amp;#39;        position at which to place the knight next
#&amp;#39; @param moves list of vectors. Each vector is length=2 and indicates the 
#&amp;#39;        row/column locations of the knight&amp;#39;s tour so far
#&amp;#39; @param visited 8x8 logical matrix which indicates whether or not a square has been
#&amp;#39;        visited by the knight already. When called by the user, this matrix
#&amp;#39;        must only contain FALSE
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
move_knight &amp;lt;- function(this_move, moves, visited) {

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Mark the move as visited
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  moves &amp;lt;- append(moves, list(this_move))
  visited[this_move[1] + (this_move[2] - 1)*8] &amp;lt;- TRUE

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # termination if all visited
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (all(visited)) {
    return(moves)
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Find all possible moves from this position
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  next_move &amp;lt;- cbind(knight_offsets[,1] + this_move[1], knight_offsets[,2] + this_move[2])
  

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # keep only moves that remain on the board
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  on_board  &amp;lt;- next_move[,1] %in% 1:8 &amp;amp; next_move[,2] %in% 1:8
  next_move &amp;lt;- next_move[on_board,,drop=FALSE]

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Keep only moves that target a location that has not yet been visited
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  not_yet_visited &amp;lt;- !visited[next_move]
  next_move &amp;lt;- next_move[not_yet_visited,, drop = FALSE]

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Recurse over every possible next move
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (i in seq_len(nrow(next_move))) {
    res &amp;lt;- move_knight(next_move[i,, drop = FALSE], moves, visited)
    if (!is.null(res)) {
      return(res)
    }
  }

  NULL
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;find-a-knights-tour-and-plot-it&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Find a knight’s tour and plot it&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Find a tour from the given starting position
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
system.time({
  moves &amp;lt;- move_knight(c(4, 8), moves = list(), visited = matrix(FALSE, 8, 8))
})&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##    user  system elapsed 
##   0.192   0.012   0.204&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Convert results to a data.frame for ggplot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
moves_df &amp;lt;- as.data.frame(do.call(rbind, moves))
moves_df &amp;lt;- set_names(moves_df, c(&amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;))
moves_df$idx &amp;lt;- 1:nrow(moves_df)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot the knight&amp;#39;s tour
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(moves_df, aes(x, y)) + 
  geom_tile(aes(fill=as.logical((x+y)%%2)), colour = &amp;#39;black&amp;#39;) +
  geom_path(alpha = 0.7, linetype = 1, size = 0.25) +
  geom_text(aes(label = idx)) + 
  scale_fill_manual(values = c(&amp;#39;grey70&amp;#39;, &amp;#39;white&amp;#39;)) + 
  theme_void() + 
  theme(legend.position = &amp;#39;none&amp;#39;) + 
  coord_equal() + 
  labs(
    title = &amp;quot;A knight&amp;#39;s tour in #RStats&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-11-03-queens-gambit-knights-tour_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;an-animation-of-the-knights-tour&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;An animation of the Knight’s Tour&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/knightstour/anim.gif&#34; width=&#34;60%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweet-length-knights-tour&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Tweet-length Knight’s Tour&lt;/h1&gt;
&lt;p&gt;The following tweet-able code generates a knight’s tour on an 8x8 chess board.&lt;/p&gt;
&lt;p&gt;The list of values returned is a list of&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#RStats
s=1:2;t=2:1;A=matrix;R=return
f=function(m,M,v){M=rbind(M,m)
v[m]=T
if(all(v))R(M)
N=cbind(c(s,-t,t,-s)+m[1],c(t,s,-s,-t)+m[2])
N=N[N[,1]%in%1:8&amp;amp;N[,2]%in%1:8,,drop=F]
N=N[!v[N],,drop=F]
for(i in row(N)[,1])if(length((r=f(N[i,,drop=F],M,v))))R(r)}
f(A(s*4,1),c(),A(F,8,8))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running this code produces a set of 64 locations which are a knight’s tour
of an 8x8 chess board.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Click to reveal/hide the solution matrix of knight locations
&lt;/summary&gt;
&lt;pre&gt;&lt;code&gt;      [,1] [,2]
 [1,]    4    8
 [2,]    6    7
 [3,]    8    8
 [4,]    7    6
 [5,]    5    7
 [6,]    7    8
 [7,]    8    6
 [8,]    7    4
 [9,]    5    5
[10,]    3    6
[11,]    1    7
[12,]    3    8
[13,]    4    6
[14,]    5    8
[15,]    7    7
[16,]    8    5
[17,]    6    6
[18,]    8    7
[19,]    6    8
[20,]    5    6
[21,]    3    7
[22,]    1    8
[23,]    2    6
[24,]    4    7
[25,]    2    8
[26,]    1    6
[27,]    3    5
[28,]    2    7
[29,]    1    5
[30,]    3    4
[31,]    5    3
[32,]    6    5
[33,]    8    4
[34,]    7    2
[35,]    6    4
[36,]    4    5
[37,]    3    3
[38,]    5    4
[39,]    7    5
[40,]    8    3
[41,]    7    1
[42,]    5    2
[43,]    4    4
[44,]    2    5
[45,]    1    3
[46,]    2    1
[47,]    4    2
[48,]    2    3
[49,]    1    1
[50,]    3    2
[51,]    2    4
[52,]    1    2
[53,]    3    1
[54,]    4    3
[55,]    5    1
[56,]    6    3
[57,]    8    2
[58,]    6    1
[59,]    7    3
[60,]    8    1
[61,]    6    2
[62,]    4    1
[63,]    2    2
[64,]    1    4&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>8 Queens Chess Problem</title>
      <link>https://coolbutuseless.github.io/2020/11/02/8-queens-chess-problem/</link>
      <pubDate>Mon, 02 Nov 2020 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/11/02/8-queens-chess-problem/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;the-queens-gambit---post-1&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;The Queen’s Gambit - Post 1&lt;/h1&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://www.netflix.com/title/80234304&#34;&gt;The Queen’s Gambit&lt;/a&gt; on Netflix,
I’m doing a few posts on Chess in R.&lt;/p&gt;
&lt;p&gt;This screenshot from the show explains everything:&lt;/p&gt;
&lt;p&gt;&lt;img src=https://coolbutuseless.github.io/img/8queens/shot.png width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction-to-the-8-queens-puzzle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction to the 8 queens puzzle&lt;/h1&gt;
&lt;p&gt;The eight queens puzzle is the problem of placing eight chess queens on an 8×8
chessboard so that no two queens threaten each other.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Eight_queens_puzzle&#34;&gt;wikipedia page&lt;/a&gt; is a good starting resource.&lt;/p&gt;
&lt;p&gt;This post contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A recursive function for finding all solutions: &lt;code&gt;place_queen()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A manually minified version that fits in a tweet - this code also generates
a plot of all solutions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;recursive-solution-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Recursive solution in R&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)

#-----------------------------------------------------------------------------
#&amp;#39; Try and place a Queen given a vector of positions of the current Queens
#&amp;#39;
#&amp;#39; This function calls itself recursively for every valid placement of the
#&amp;#39; next queen. 
#&amp;#39;
#&amp;#39; @param queens A vector of integers representing the column placement 
#&amp;#39;               of queens so far. The index within this list
#&amp;#39;               is the row, and the value is the column.  
#&amp;#39;               To generate all solutions, pass in an empty vector (the default)
#&amp;#39;
#&amp;#39;  e.g. queens = c(1, 4, 7) corresponds to queens placed at c(1, 1), c(2, 4) and
#&amp;#39;  c(3, 7)
#&amp;#39;                  
#&amp;#39;
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   | Q |   |    3rd row, 7th column
#&amp;#39;  --------------------------------- 
#&amp;#39;  |   |   |   | Q |   |   |   |   |    2nd row, 4th column
#&amp;#39;  ---------------------------------
#&amp;#39;  | Q |   |   |   |   |   |   |   |    1st row, 1st column
#&amp;#39;  ---------------------------------
#&amp;#39;
#&amp;#39;
#&amp;#39;
#&amp;#39;
#&amp;#39; @return a list where each element is a vector of 8 integers 
#&amp;#39;         i.e. a solution to the 8 queens problem
#-----------------------------------------------------------------------------
place_queen &amp;lt;- function(queens=c()) {
  
  #---------------------------------------------------------------------------
  # If there are 8 queens placed, then this must be a solution.
  #---------------------------------------------------------------------------
  if (length(queens) == 8) {
    return(list(queens))
  }
  
  #---------------------------------------------------------------------------
  # Figure out where a queen can be placed in the next row.
  # Drop all columns that have already been taken - since we 
  # can&amp;#39;t place a queen below an existing queen
  #---------------------------------------------------------------------------
  possible_placements &amp;lt;- setdiff(1:8, queens)
  
  #---------------------------------------------------------------------------
  # For each queen already on the board, find the diagonal 
  # positions that it can see in this row.
  #---------------------------------------------------------------------------
  diag_offsets &amp;lt;- seq.int(length(queens), 1)
  diags &amp;lt;- c(queens + diag_offsets, queens - diag_offsets)
  diags &amp;lt;- diags[diags &amp;gt; 0 &amp;amp; diags &amp;lt; 9]
  
  #---------------------------------------------------------------------------
  # Drop these diagonal columns from possible placements
  #---------------------------------------------------------------------------
  possible_placements &amp;lt;- setdiff(possible_placements, diags)
  
  #---------------------------------------------------------------------------
  # For each possible placement, try and place a queen
  #---------------------------------------------------------------------------
  possible_placements %&amp;gt;% 
    map(~place_queen(c(queens, .x))) %&amp;gt;%
    keep(~length(.x) &amp;gt; 0) %&amp;gt;%
    flatten()
}


#-----------------------------------------------------------------------------
#&amp;#39; Plot a single solution
#&amp;#39; @param queens a vector of 8 integers giving the column positions of 8 queens
#-----------------------------------------------------------------------------
plot_single_8queens &amp;lt;- function(queens, title = NULL) {
  queens_df &amp;lt;- tibble(cols = queens, rows=1:8)
  board_df &amp;lt;- expand.grid(cols = 1:8, rows = 1:8) %&amp;gt;% 
    mutate(check = (cols + rows) %%2 == 1)
  
  p &amp;lt;- ggplot(queens_df, aes(rows, cols)) + 
    geom_tile(data=board_df, aes(fill=check), colour=&amp;#39;black&amp;#39;) +
    geom_text(label=&amp;#39;\u2655&amp;#39;, family=&amp;quot;Arial Unicode MS&amp;quot;, size = 8) + 
    theme_void() + 
    coord_equal() + 
    scale_fill_manual(values = c(&amp;#39;TRUE&amp;#39;=&amp;#39;white&amp;#39;, &amp;#39;FALSE&amp;#39;=&amp;#39;grey70&amp;#39;)) + 
    theme(
      legend.position = &amp;#39;none&amp;#39;
    ) 
  
  if (is.null(title)) {
    p &amp;lt;- p + labs(title = paste(&amp;quot;Queens:&amp;quot;, deparse(as.numeric(queens)))) 
  } else {
    p &amp;lt;- p + labs(title = title)
  }
}


#-----------------------------------------------------------------------------
# Start with no queens placed and generate all solutions.
#-----------------------------------------------------------------------------
solutions &amp;lt;- place_queen()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;First 10 solutions. Each row of this table is a solution
i.e. a vector of 8 numbers where the values are the row position on the chessboard.
The table column indicates which column on the chess board.&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;V1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V2&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V3&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V4&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V5&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V6&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V7&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V8&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#  Plot the first 2 solutions
#-----------------------------------------------------------------------------
plot_single_8queens(solutions[[1]])
plot_single_8queens(solutions[[2]])&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;animation-showing-all-solutions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animation showing all solutions&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8queens/anim.gif&#34; width=&#34;60%&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;queens-solution-in-rstats-compacted-into-a-tweet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;8Queens solution in Rstats Compacted into a tweet&lt;/h2&gt;
&lt;p&gt;This tweet calculates all 92 solutions and plots them on a checkered board -
the bright blue squares on the board represent the locations of the queens.&lt;/p&gt;
&lt;p&gt;This solution fits in a tweet!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
v=1:8
f=function(q){L=length(q)
if(L==8){q}else{flatten(map(setdiff(v,c(q,q+L:1,q-L:1)),~f(c(q,.))))}}
s=data.frame(c=unlist(f(c())),r=v,x=rep(1:92,e=8),z=3)
b=mutate(crossing(c=v,r=v),z=(c+r)%%2)
g=geom_tile
ggplot(s,aes(r,c,fill=z))+g(d=b)+g()+facet_wrap(~x)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8queens/8queens.png&#34; width=&#34;80%&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;extension&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extension&lt;/h2&gt;
&lt;p&gt;Nothing else I want to do :)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;emphatic&#39; - highlight data.frames in the R console</title>
      <link>https://coolbutuseless.github.io/2020/10/30/introducing-emphatic-highlight-data.frames-in-the-r-console/</link>
      <pubDate>Fri, 30 Oct 2020 07:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/10/30/introducing-emphatic-highlight-data.frames-in-the-r-console/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/anchor-sections/anchor-sections.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;emphatic&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;emphatic&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/emphatic/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/emphatic/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;div id=&#34;emphatic-augments-the-output-of-data.frames-and-matrices-in-r-by-adding-user-defined-ansi-highlighting.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;{emphatic}&lt;/code&gt; augments the output of data.frames and matrices in R by adding user-defined ANSI highlighting.&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/examples.gif&#34;/&gt;&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/index.html&#34;&gt;online documentation&lt;/a&gt; for
vignettes and more examples.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;p&gt;There are separate high-level functions for highlighting data.frames and matrices, and
a low-level function which can be used on both.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;hl_&lt;/code&gt; prefix can be read as &lt;code&gt;highlight&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hl()&lt;/code&gt; for highlighting data.frames&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hl_matrix()&lt;/code&gt; for highlighting matrices&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hl_loc()&lt;/code&gt; for low-level control of highlighting of both data.frames and matrices&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hl_opt()&lt;/code&gt; to set some local options on the current &lt;code&gt;emphatic&lt;/code&gt; object
e.g. &lt;code&gt;full_colour&lt;/code&gt; option sets 24-bit colour mode.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hl_opt_global()&lt;/code&gt; sets global options for highlighting. These values will be
the default unless overridden with a call to &lt;code&gt;hl_opt()&lt;/code&gt; for the given
&lt;code&gt;emphatic&lt;/code&gt; object.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;data.frame&lt;/th&gt;
&lt;th&gt;matrix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;High Level&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hl()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hl_matrix()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Low Level&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hl_loc()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hl_loc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/emphatic&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/emphatic&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;warning&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Warning&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This package calls &lt;code&gt;eval()&lt;/code&gt; on user-supplied code and extreme caution should
be taken before exposing functions in this package to the internet (e.g. via &lt;code&gt;shiny&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;p&gt;Intro&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/intro.html&#34;&gt;Guided Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Speicifying rows, columns and colours&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/row-specification.html&#34;&gt;Specifying rows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/col-specification.html&#34;&gt;Specifying columns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/colour-specification.html&#34;&gt;Specifying colours&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Test cases on Real data&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/challenger.html&#34;&gt;Space Shuttle O-ring dataset - Challenger Disaster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/sea-ice.html&#34;&gt;Southern Sea Ice Area&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/volcano.html&#34;&gt;&lt;code&gt;volcano&lt;/code&gt; dataset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/correlation.html&#34;&gt;Correlation matrix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Advanced:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/emphatic/articles/low-level-hl-loc.html&#34;&gt;Low level highlighting with &lt;code&gt;hl_loc()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example---set-alternating-colours-on-a-data.frame&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - set alternating colours on a data.frame&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(emphatic)
emphatic::hl_opt_global(dark_mode = FALSE)

mtcars %&amp;gt;%
  hl(c(&amp;#39;red&amp;#39;, &amp;#39;white&amp;#39;)) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/example1.svg&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2---using-row-and-column-specification&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 2 - using row and column specification&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;{emphatic}&lt;/code&gt; to highlight the &lt;code&gt;mtcars&lt;/code&gt; dataset where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;6 and 8 cylinder cars only&lt;/li&gt;
&lt;li&gt;colour each row to indicate the miles-per-gallon rating&lt;/li&gt;
&lt;li&gt;do not colour the &lt;code&gt;gear&lt;/code&gt; or &lt;code&gt;carb&lt;/code&gt; columns&lt;/li&gt;
&lt;li&gt;highlight the car with the maximum miles per gallon in &lt;code&gt;hotpink&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;de-emphasise the numeric values to focus on the colour highlighting&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  hl(ggplot2::scale_colour_viridis_c(), rows = cyl %in% c(6, 8), 
     cols = mpg, dest_cols = mpg:am) %&amp;gt;%
  hl(&amp;#39;hotpink&amp;#39;, rows = mpg == max(mpg)) %&amp;gt;%
  hl_opt(text_contrast = 0.25)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/example2.svg&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-3---rainbows&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 3 - Rainbows!&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  hl(rainbow(32)) %&amp;gt;%
  hl_opt(text_contrast = 0.5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/example3.svg&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-4-correlation-matrix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 4: Correlation matrix&lt;/h2&gt;
&lt;p&gt;Create a correlation matrix of some of the variables in &lt;code&gt;mtcars&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Colour the values using red for negative correlations and blue for positive
correlations. Values in-between are coloured using a gradient between red
and blue. This colouring is applied using &lt;code&gt;ggplot2::scale_colour_gradient2()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  select(cyl, mpg, hp, disp, vs) %&amp;gt;%
  cor() %&amp;gt;%
  hl_matrix(scale_colour_gradient2(), selection = abs(.x) &amp;gt; 0.7 &amp;amp; row(.x) != col(.x)) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/emphatic/example4.svg&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=crayon&#34;&gt;crayon&lt;/a&gt; Colored terminal output on terminals that support ‘ANSI’ color and highlight codes. It also works in ‘Emacs’ ‘ESS’. ‘ANSI’ color support is automatically detected.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=fansi&#34;&gt;fansi&lt;/a&gt; Counterparts to R string manipulation functions that account for the effects of ANSI text formatting control sequences.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;purler&#39; - fast run-length encoding with data.frame output</title>
      <link>https://coolbutuseless.github.io/2020/10/14/introducing-purler-fast-run-length-encoding-with-data.frame-output/</link>
      <pubDate>Wed, 14 Oct 2020 21:10:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/10/14/introducing-purler-fast-run-length-encoding-with-data.frame-output/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;purler&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;purler&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/dependencies-zero-blue.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/purler/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/purler/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;purler&lt;/code&gt; contains tools for run-length encoding vector data.&lt;/p&gt;
&lt;div id=&#34;key-features&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Key features:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NA&lt;/code&gt; values are considered identical (unlike &lt;code&gt;base::rle()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Results returned as a &lt;code&gt;data.frame&lt;/code&gt; (rather than a list), but still compatible
with &lt;code&gt;base::inverse.rle()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Faster! Includes a C implementation for regular atomic vectors, and an R
version compatible with every input &lt;code&gt;base::rle()&lt;/code&gt; accepts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rlenc()&lt;/code&gt; is C code for run-length encoding of raw, logical, integer, numeric and character vectors.
&lt;ul&gt;
&lt;li&gt;Groups &lt;code&gt;NA&lt;/code&gt; values into a run (unlike &lt;code&gt;base::rle()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Returns a &lt;strong&gt;data.frame&lt;/strong&gt; rather than a list&lt;/li&gt;
&lt;li&gt;Returned object is compatible with &lt;code&gt;base::inverse.rle()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Can be &lt;strong&gt;10x faster&lt;/strong&gt; than &lt;code&gt;base::rle()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rlenc_compat()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;A pure R version of &lt;code&gt;rlenc()&lt;/code&gt; which is compatible with all inputs that
&lt;code&gt;base::rle()&lt;/code&gt; accepts&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rleid()&lt;/code&gt; returns an integer vector numbering the runs of identical values within a
vector of numeric or character data. This is very similar to &lt;code&gt;data.table::rleid()&lt;/code&gt;,
execpt the &lt;code&gt;data.table()&lt;/code&gt; version is much more configurable and flexible. This
version is probably only useful if you wanted to avoid pulling in &lt;code&gt;data.table&lt;/code&gt; as a
dependency.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/purler&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/purler&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Long vector support in &lt;code&gt;rlenc()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;rlenc---run-length-encoding-output-as-a-data.frame&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;rlenc()&lt;/code&gt; - run-length encoding output as a data.frame&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;input &amp;lt;- c(1, 1, 1, 2, 2, 8, 8, 8, 8, 8, NA, NA, NA, NA)

(result &amp;lt;- purler::rlenc(input))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  lengths values start
1       3      1     1
2       2      2     4
3       5      8     6
4       4     NA    11&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;inverse.rle(result)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1  1  1  2  2  8  8  8  8  8 NA NA NA NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rlenc-benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;rlenc()&lt;/code&gt; benchmark&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyr)
library(bench)
library(dplyr)
library(ggplot2)

N &amp;lt;- 1000
M &amp;lt;- 10

zz &amp;lt;- sample(seq_len(M), N, replace = TRUE)

res &amp;lt;- bench::mark(
  rle(zz),
  rlenc(zz),
  rlenc_compat(zz),
  check = FALSE
)

plot(res) + theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-10-14-purler_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;run-length-encoding-with-nas&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Run-length encoding with NAs&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;base::rle()&lt;/code&gt;, runs of NA values are &lt;em&gt;not&lt;/em&gt; treated as a group.&lt;/p&gt;
&lt;p&gt;All functions in &lt;code&gt;purler&lt;/code&gt; do treat NAs as identical for the purpose of creating groups&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;input &amp;lt;- c(1, 1, 2, NA, NA, NA, NA, 4, 4, 4)

base::rle(input)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Run Length Encoding
  lengths: int [1:7] 2 1 1 1 1 1 3
  values : num [1:7] 1 2 NA NA NA NA 4&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;purler::rlenc_compat(input)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  lengths values start
1       2      1     1
2       1      2     3
3       4     NA     4
4       3      4     8&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;purler::rlenc(input)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  lengths values start
1       2      1     1
2       1      2     3
3       4     NA     4
4       3      4     8&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;purler::rlenc_id(input)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 1 1 2 3 3 3 3 4 4 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;run-length-encoded-group-ids&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Run-length encoded group ids&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;rlenc_id()&lt;/code&gt; numbers the runs of identical values in a numeric or character vector.&lt;/p&gt;
&lt;p&gt;For a more complete approach to this problem, see &lt;code&gt;data.table::rleid()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;input &amp;lt;- c(11, 11, 12, 12, 12, NA, NA, NA, NA)

rlenc_id(input)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1 1 2 2 2 3 3 3 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base::rle()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data.table::rleid()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing geomlime</title>
      <link>https://coolbutuseless.github.io/2020/10/13/introducing-geomlime/</link>
      <pubDate>Tue, 13 Oct 2020 20:38:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/10/13/introducing-geomlime/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;geomlime&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;geomlime &lt;img src=&#34;https://coolbutuseless.github.io/img/geomlime/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#questioning&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-questioning-blue.svg&#34; alt=&#34;Lifecycle: questioning&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/geomlime/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/geomlime/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;geomlime&lt;/code&gt; provides a bloody &lt;code&gt;geom_lime()&lt;/code&gt; function for ggplot because of all
the zarking times I frakking type &lt;code&gt;geom_lime()&lt;/code&gt; instead of &lt;code&gt;geom_line()&lt;/code&gt;&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/geomlime&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/geomlime&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example Usage&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(geomlime)

ggplot(mtcars) +
  geom_lime(aes(mpg, wt, size = cyl)) + 
  theme_bw() + 
  theme(legend.position = &amp;#39;none&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-10-13-geomlime_files/figure-html/example-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing devoutrgl - a 3d graphics device targetting rgl</title>
      <link>https://coolbutuseless.github.io/2020/10/06/introducing-devoutrgl-a-3d-graphics-device-targetting-rgl/</link>
      <pubDate>Tue, 06 Oct 2020 20:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/10/06/introducing-devoutrgl-a-3d-graphics-device-targetting-rgl/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglwidgetClass/rgl.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglwidgetClass/rglClass.src.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/CanvasMatrix4/CanvasMatrix.src.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglWebGL-binding/rglWebGL.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/crosstalk/css/crosstalk.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/crosstalk/js/crosstalk.min.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;devoutrgl&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutrgl &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutrgl/logo-new.png&#34; align=&#34;right&#34; height=300/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutrgl::rgldev()&lt;/code&gt; is a graphics device - like &lt;code&gt;pdf()&lt;/code&gt; or &lt;code&gt;png()&lt;/code&gt;. This device
will render a plot as an interactive 3d opengl document using &lt;code&gt;{rgl}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: Since Github does not allow webgl rendering in README files, all plots
on GitHub have been rendered as PNGs or animated gifs. Please
visit &lt;a href=&#34;https://coolbutuseless.github.io/package/devoutrgl&#34;&gt;the package website&lt;/a&gt;
to interact with the generated output in the vignettes&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rgldev()&lt;/code&gt; is the rgl device. Use it like you would use the &lt;code&gt;pdf()&lt;/code&gt; device or the
&lt;code&gt;png()&lt;/code&gt; device.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devoutrgl&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/snowcrash&amp;quot;)  # Store R objects as images
remotes::install_github(&amp;quot;coolbutuseless/cryogenic&amp;quot;)  # Freeze R calls + replay
remotes::install_github(&amp;quot;coolbutuseless/triangular&amp;quot;) # Polygon Triangulation
remotes::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)     # R device framework
remotes::install_github(&amp;quot;coolbutuseless/devoutrgl&amp;quot;)  # This device&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No font selection. Everything will be in the default sans serif!&lt;/li&gt;
&lt;li&gt;Multi-line text in a single string with “” characters does not render well.&lt;/li&gt;
&lt;li&gt;No support for clipping paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;examples&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Examples&lt;/h1&gt;
&lt;div id=&#34;bar-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bar Plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(devoutrgl)

plot_df &amp;lt;- data.frame(x=c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;), y=4:6)
p &amp;lt;- ggplot(plot_df) +
  geom_bar(aes(x, y, fill=x), colour = NA, stat=&amp;#39;identity&amp;#39;) +
  labs(title = &amp;quot;{devoutrgl}&amp;quot;) +
  scale_fill_brewer(type = &amp;#39;seq&amp;#39;, palette = &amp;#39;Blues&amp;#39;) + 
  theme_minimal() + theme_rgl()


devoutrgl::rgldev(fov = 30, view_angle = -30)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;rgl39345&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl39345&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#FFFFFF&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;lines&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:true,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:6,&#34;objects&#34;:{&#34;16&#34;:{&#34;id&#34;:16,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[28.3680686950684,105.974472045898,0],[520.949157714844,105.974472045898,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,105.974472045898,0],[520.949157714844,105.974472045898,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;17&#34;:{&#34;id&#34;:17,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.200000002980232,-0.200000002980232]},&#34;vertices&#34;:[[28.3680686950684,220.192855834961,0],[520.949157714844,220.192855834961,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,220.192855834961,0],[520.949157714844,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;18&#34;:{&#34;id&#34;:18,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.300000011920929,-0.300000011920929]},&#34;vertices&#34;:[[28.3680686950684,334.411254882812,0],[520.949157714844,334.411254882812,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,334.411254882812,0],[520.949157714844,334.411254882812,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;19&#34;:{&#34;id&#34;:19,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464]},&#34;vertices&#34;:[[28.3680686950684,48.8652801513672,0],[520.949157714844,48.8652801513672,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,48.8652801513672,0],[520.949157714844,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;20&#34;:{&#34;id&#34;:20,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.5,-0.5]},&#34;vertices&#34;:[[28.3680686950684,163.08366394043,0],[520.949157714844,163.08366394043,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,163.08366394043,0],[520.949157714844,163.08366394043,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;21&#34;:{&#34;id&#34;:21,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.600000023841858,-0.600000023841858]},&#34;vertices&#34;:[[28.3680686950684,277.302062988281,0],[520.949157714844,277.302062988281,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,277.302062988281,0],[520.949157714844,277.302062988281,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;22&#34;:{&#34;id&#34;:22,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071]},&#34;vertices&#34;:[[28.3680686950684,391.520446777344,0],[520.949157714844,391.520446777344,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[28.3680686950684,391.520446777344,0],[520.949157714844,391.520446777344,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;23&#34;:{&#34;id&#34;:23,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.800000011920929,-0.800000011920929]},&#34;vertices&#34;:[[120.727020263672,31.7325210571289,0],[120.727020263672,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[120.727020263672,31.7325210571289,0],[120.727020263672,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;24&#34;:{&#34;id&#34;:24,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.899999976158142,-0.899999976158142]},&#34;vertices&#34;:[[274.658599853516,31.7325210571289,0],[274.658599853516,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[274.658599853516,31.7325210571289,0],[274.658599853516,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;25&#34;:{&#34;id&#34;:25,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1,-1]},&#34;vertices&#34;:[[428.590179443359,31.7325210571289,0],[428.590179443359,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[428.590179443359,31.7325210571289,0],[428.590179443359,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;26&#34;:{&#34;id&#34;:26,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.10000002384186,-1.10000002384186]},&#34;vertices&#34;:[[51.4578056335449,48.8652801513672,0],[189.996231079102,48.8652801513672,0],[189.996231079102,277.302062988281,0],[51.4578056335449,277.302062988281,0]],&#34;colors&#34;:[[0.87058824300766,0.921568632125854,0.968627452850342,1]],&#34;centers&#34;:[[120.727012634277,163.083679199219,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;27&#34;:{&#34;id&#34;:27,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.20000004768372,-1.20000004768372]},&#34;vertices&#34;:[[205.389389038086,48.8652801513672,0],[343.927825927734,48.8652801513672,0],[343.927825927734,334.411254882812,0],[205.389389038086,334.411254882812,0]],&#34;colors&#34;:[[0.619607865810394,0.792156875133514,0.882352948188782,1]],&#34;centers&#34;:[[274.658599853516,191.638275146484,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;28&#34;:{&#34;id&#34;:28,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.29999995231628,-1.29999995231628]},&#34;vertices&#34;:[[359.320983886719,48.8652801513672,0],[497.859405517578,48.8652801513672,0],[497.859405517578,391.520446777344,0],[359.320983886719,391.520446777344,0]],&#34;colors&#34;:[[0.192156866192818,0.509803950786591,0.74117648601532,1]],&#34;centers&#34;:[[428.590209960938,220.19287109375,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;29&#34;:{&#34;id&#34;:29,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.39999997615814,-1.39999997615814],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABPklEQVQoz63SPUtcQRQA0ONqVrMRi4CF2cIuDyRgE0JAQVII0fD+gbGwUrDyDwTSpohV2DKpQiqLwUISkDQWIthEkEVEEMRGIYou6i6m2Oe+N6TdW83cOfcO80E3oicfpnMWjSs59N3n0PiPpF8soalpAH9MhfP2SikDi5Y0LRtU8c6pF75FXdKyQ1Ufwses4KVtPSbCVt4lVXVn9aEu7NjAfHGjN9gOF4Vj/MLbIhnDfnTSOkbTJzl5huOInICRnAzhKiLXnXxG+nAbkZtOPiMNlCPSz0NZm1zicUQq4CInx6hGpIp7pznZQxKR5zgK1znZxOv2LWQxjd/Fq/vpzICVzqu/Mo1ae9YL9VZyZdZU0kh2k1Yy44dB6+FT9F/Skq/eo+Uu+y+T4W+hC/X7+lpyYNhTjxyoWYgetQvxDygNTp+jPOt3AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[18.5424194335938,45.7092247009277,1],[24.2090873718262,45.7092247009277,1],[24.2090873718262,53.3758926391602,1],[18.5424194335938,53.3758926391602,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[21.37575340271,49.5425567626953,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;30&#34;:{&#34;id&#34;:30,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.5,-1.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAXCAQAAACsCtdvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABKklEQVQoz62Rv0vDUBSFP0NagoW62KFbIYXo4NDROuikONzi5OKokzgIbv4DTkodHVyV4lDKXRSdIkKD4OBenEr9MTooRFsHE2pM0ql3eu/dj/PuuQfGVRPDo+TZYQ0Hixduqet9DJIy15QAn28soM+e1n97RoCYtCjRpUaOHHPcYHAkyxElWafBgKq2g3sGjwquLv5RYhW4CxFQn1OgKgaAGby6fPEYsdQDTLJ8jrAthzKQbmTwGFJkC2iOgCTDGXneOUiFxOScJWBTg+/MGGLRoAbs6kVCLABSoMU8fbb1JDE7EJtLynywoc20gCtcUeANUS+qPwx4FpdpOqxo5/+cYXaTPODwxIL24n5Dd/s4wDG22JG+p36gJFlemUpcfVGfw2XOpCBjrx8xsUmA1h+L6QAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMB6BldgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDBv3C1kAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[18.5424194335938,159.927612304688,1],[24.5424194335938,159.927612304688,1],[24.5424194335938,167.594284057617,1],[18.5424194335938,167.594284057617,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[21.5424194335938,163.760955810547,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;31&#34;:{&#34;id&#34;:31,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.60000002384186,-1.60000002384186],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAXCAQAAACsCtdvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAAzElEQVQoz7WRMQtBURiGH9ztlixWGfwFJvkH3yATmSijjTKZZDZcs5IySOosyl+4f8BmYriZ1FUMLMJ1z7nT9W7fe57evvO98FfJWB6y+cxJDVKhH3RCkGSY/7rhpCk5/EhImtRxWUZAksfhSpO7EZIUc9L01P53g++kAWW2ygn/9w1JiSFnWrq7vSCxWWDRUacIiAkFZmqtbyAJIFXaHOhiUAJAVtQM70XlarszJWWxA+6IBjs6wFHdwAJQHl7g8hfAVwdtLSbFB8WnJ/36KxXzPH3AAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[18.5424194335938,274.14599609375,1],[24.5424194335938,274.14599609375,1],[24.5424194335938,281.812683105469,1],[18.5424194335938,281.812683105469,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[21.5424194335938,277.979339599609,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;32&#34;:{&#34;id&#34;:32,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.70000004768372,-1.70000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABZ0lEQVQoz63SPWgUQRQA4O9yRyBBz3AEtbGxyAYUFIIIioUS0GaQNIIg2ohW2ogIViqoCBZikUiwFg4Ri0HQLv6ChYloQNhKLBQNBIlZEeGIxV6yc9hmmnnM+4aZN29Yj1GrwrDTBYdsVZg1FR/9R8JpUxpY0gTT8WyZ6euCg6Y13LMlbrLZJM6E48lpoRY+hZVwN1l5ElbC8zJugP1G/XA52XXJQ19TchSP43Il4rz51bgkuzAb+p1zwojfXroe362S8rqjKLxx226Dhk14G072kiHcMmbSDsMO+6DuftiTvEvo6MPVeKVbT9Oc7Z7FI8m7YMGNtcsuuYnxsLEiy3gd/yZFv0DdSEW+41dP7xbBQEU+YlsPaYFvFZnBvjCUkANY8LkibX/0u7bWoQEX0Y4dqENeZB3j9matbC4vQqZtzKJjeZH8l1Bzx/ludRvw00ScKXP1csrlT7NXmloGffHAqfjeuo5/JFxeTjGH2bQAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDAegZXYAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwb9wtZAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[18.5424194335938,388.364379882812,1],[24.2090873718262,388.364379882812,1],[24.2090873718262,396.031066894531,1],[18.5424194335938,396.031066894531,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[21.37575340271,392.197692871094,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;33&#34;:{&#34;id&#34;:33,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.79999995231628,-1.79999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABJ0lEQVQoz63SO0ibcRTG4SdtbFovICJUsN4ttEghkKF1UCiu/Q8ScRQENx0km4K7m0Ohk1gcrODg8g0NdCqFguCgQ+MkJZs4OAiShNbLkC8k0dUzHTg/3vfceKxI1NMwYNGUIR0undj3JSrfg0LWjhT+uZECv3yMruFJjPTalvLdWykvDPuKCdlqNRkLzWlzLhuVwN+wYNKIcXuN0Dd/lGIE0U0oGNHRpBQVFWPjdqPGvPcBT5vthKRZ8955+XD2GArdfkjjv4KCIz/lTNfYmtKGtJIlu7W+wlpdMAkhYQbr0VaD1Zu6XXVPzzxHpWH7c/rR0gBFFcdYDhkInWHFJmht7iknr8dhOFP2StKF3z4ZvH+7jFUTulw5lfdZnwO3Xkenj/ZMuAPC3EVKzb/3RQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMB6BldgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDBv3C1kAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[118.27995300293,20.4889049530029,1],[124.27995300293,20.4889049530029,1],[124.27995300293,26.4889049530029,1],[118.27995300293,26.4889049530029,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[121.27995300293,23.4889049530029,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;34&#34;:{&#34;id&#34;:34,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.89999997615814,-1.89999997615814],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAA+klEQVQoz73SsUtCURTH8a8aBS4lYlC4RZsN4h+Q7p2pIJfGhnCLaBCVVkOX/gIHl2gpTv0BUdHU1GCT4PJwaHqET0J7Tcl99xkShGe6cD78uOfcC/9WsiO+jH7rRmcHzI0sGJeOUuKQTVweaOrztJRLLsgwJMUuT3IcJjH2aLOuCdJcEaEh2+GUaz3QPqhDkXsinIVJ7eegX5wDeUkFybu+GvwRgFyQOOag6uIBVoo/ZWOfQbJq9iXJEtAPkjVJG6YAjHmxJypPMhYpAzf6YZMjqcsyyAZ3ZBlQsd/ojR6nnIjLCuCxrx17dWOEKl3iOLTY0ttZP+Bv9Q1fEzvGEwXJfwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMB6BldgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDBv3C1kAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[272.211547851562,20.4889049530029,1],[277.878204345703,20.4889049530029,1],[277.878204345703,28.1555709838867,1],[272.211547851562,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[275.044860839844,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;35&#34;:{&#34;id&#34;:35,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2,-2],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAQAAAD4MpbhAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAA/ElEQVQoz6XRvyvEcRzH8YdzRI66DFdKZKFYvklhJUp9lWSTTP4Bf4TZpBgsFrlFn8FltqjLJArbdVGSTOp0neHb/Sqme0/v3u/n+9frTafWVXfiPru2TRpSUnAQym1APOpShIqKDD6thCKkIE45F3m3JRMGzXmUdRH3NgCbFlSthXz4IRStqxq3DmmwgeukJYSXeF/VfROYxU3r7uGw7iUjcnj7+8wESP+vQ5L6MCDXGo5H8Bpq9Q53WGwrPFJ21hyRx2o806ifsIyrhpJxj1uRsj0FNfNOTHsQhUpT6jEFU/hGP0qWwjN0J8DT1+SpL1nD0l4c26k/q3P7BRRhQJPnK7kgAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[426.390197753906,20.4889049530029,1],[431.723541259766,20.4889049530029,1],[431.723541259766,26.4889049530029,1],[426.390197753906,26.4889049530029,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[429.056884765625,23.4889049530029,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;36&#34;:{&#34;id&#34;:36,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.09999990463257,-2.09999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAWCAQAAACFih+zAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABEUlEQVQoz7XSvUqcYRDF8Z8pxML4iU1ARATxIhTERBCs01nYpBGxs7XyAiwUEQQLO0GbQBqJJjdhI/iBitgEYQVF4T0WeRF3dXchkOnm8GfOzHke/l91uxKxXaX2uRGxWA1Pi4gvr7RdEb98qJ28JeJYW9nPiLg18HaJThcilsEnf0TMvL/xlIhHI/ghYqf+eZsi9s2KuNRTH+1wLuJeFCYbxzZZJhErzTPeE/Gktxk4oFJOXW0MtvgpohCF8UbonIgj30ScaK8HDqqIwigORKzVMz8UsQGGPYjCxHvovIhrXWW/JOL07RJD7kR8fVFaHYlYrzX/LeJ7lTpWJvH5tbggoqK/xuvvnzjzsfnL/Ws9A0+/cexLNIm3AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[271.908599853516,7.91255760192871,1],[278.908599853516,7.91255760192871,1],[278.908599853516,15.2458906173706,1],[271.908599853516,15.2458906173706,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[275.408599853516,11.5792245864868,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;37&#34;:{&#34;id&#34;:37,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.20000004768372,-2.20000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAdCAQAAADvTe9wAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABQElEQVQ4y7XQP0vVYRjG8Q/HU0lIOCQJtraERgSCW7REOLkIppCvoZfQCxBBkOZQEheNoLGhsaYoR8FF1PAQaEpCnK4Gj8fz59f5LXUtz3Pd9/e5/zz8P02K+FqQ2RY/3bgM9DkQMdoBTohYPzcVULcGZjrQWbDaHnwgYrstdt6r5krnVFsixlsij0UsX9hKM7ECnragc0Xt4ba62G0+7nfUNVJT70U8bLhpES+K0XkRLxtuU8SdYnTAqThUxaAz8bE1XWm5n3iDmx5hyrXilS70RMQSNsQvQ39H++yLHVcdi3d6akHEc5G2Py7QfRFH4ofrSvRFRLzqTFS60JXGuVpWkxERe91FuqsOg9d+l1ddFDFWDg6oiU+9kH5VDHkr4lkvdNyZb+oiPqv2Qm81fjO+u1c25QcnajbcLV/oX+oP1Stt8WLcAp4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDAegZXYAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwb9wtZAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[13.3695888519287,217.442855834961,1],[13.3695888519287,224.442855834961,1],[3.70292210578918,224.442855834961,1],[3.70292210578918,217.442855834961,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[8.53625583648682,220.942855834961,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;38&#34;:{&#34;id&#34;:38,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.29999995231628,-2.29999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAWCAQAAACFih+zAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAABEUlEQVQoz7XSvUqcYRDF8Z8pxML4iU1ARATxIhTERBCs01nYpBGxs7XyAiwUEQQLO0GbQBqJJjdhI/iBitgEYQVF4T0WeRF3dXchkOnm8GfOzHke/l91uxKxXaX2uRGxWA1Pi4gvr7RdEb98qJ28JeJYW9nPiLg18HaJThcilsEnf0TMvL/xlIhHI/ghYqf+eZsi9s2KuNRTH+1wLuJeFCYbxzZZJhErzTPeE/Gktxk4oFJOXW0MtvgpohCF8UbonIgj30ScaK8HDqqIwigORKzVMz8UsQGGPYjCxHvovIhrXWW/JOL07RJD7kR8fVFaHYlYrzX/LeJ7lTpWJvH5tbggoqK/xuvvnzjzsfnL/Ws9A0+/cexLNIm3AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[537.387512207031,244.907516479492,1],[544.387512207031,244.907516479492,1],[544.387512207031,252.240859985352,1],[537.387512207031,252.240859985352,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[540.887512207031,248.574188232422,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;39&#34;:{&#34;id&#34;:39,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.40000009536743,-2.40000009536743]},&#34;vertices&#34;:[[538.09619140625,221.640182495117,0],[553.958862304688,221.640182495117,0],[553.958862304688,237.502853393555,0],[538.09619140625,237.502853393555,0]],&#34;colors&#34;:[[0.87058824300766,0.921568632125854,0.968627452850342,1]],&#34;centers&#34;:[[546.027526855469,229.571517944336,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;40&#34;:{&#34;id&#34;:40,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.5,-2.5]},&#34;vertices&#34;:[[538.09619140625,204.36018371582,0],[553.958862304688,204.36018371582,0],[553.958862304688,220.222854614258,0],[538.09619140625,220.222854614258,0]],&#34;colors&#34;:[[0.619607865810394,0.792156875133514,0.882352948188782,1]],&#34;centers&#34;:[[546.027526855469,212.291519165039,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;41&#34;:{&#34;id&#34;:41,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.59999990463257,-2.59999990463257]},&#34;vertices&#34;:[[538.09619140625,187.080184936523,0],[553.958862304688,187.080184936523,0],[553.958862304688,202.942855834961,0],[538.09619140625,202.942855834961,0]],&#34;colors&#34;:[[0.192156866192818,0.509803950786591,0.74117648601532,1]],&#34;centers&#34;:[[546.027526855469,195.011520385742,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;42&#34;:{&#34;id&#34;:42,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.70000004768372,-2.70000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAA+0lEQVQoz7XSwSoEUBTG8d8wRFEWSlKksVBSagprbyBlqXiE2dlYWth4A5GyU0opWZEtzcaslGYlilIyjMmxMDPNZSELZ3PPd/qfc797O/xHjNhw4dG7B+cKun4iC16FUK2f4Ux7igx5Fo6My8gYtSWExRRaFe50N3Wba2HzS2TrxT1XKipN6ENJTm8KlZXrWY8xE2bM0vCUbfZmLVo2aaDFRCaF+p2YQk1JSdGpgvnvH7ArvFhpsX4sbEvGVoS1pK0s7DSeCp268NaCLBlGR3pdUbiVB31WVYVwkEJz9fKtG+/Cg0Oh+N163r57NU8urRs0LXzI/WlFfo1PnORNPjIax7IAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDAegZXYAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwb9wtZAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[560.14697265625,226.415466308594,1],[566.14697265625,226.415466308594,1],[566.14697265625,232.415466308594,1],[560.14697265625,232.415466308594,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[563.14697265625,229.415466308594,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;43&#34;:{&#34;id&#34;:43,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.79999995231628,-2.79999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAA0UlEQVQoz8XSsUoDQRAA0EdALS1E0WCXysLKykpsJb9iY50f8AdsLexMJG0gRSxstVDBwlpRCAQCGhRzk05u706CIDjd7r7dnZld/i6awtdPi7X5+/+F1By6NfGqY7e6oraQGcmEzFGZhHBmHXXnQmavTLq5Ky+FQZls52YOhLCapjt0lyNXYCclz0l2YxOKp0RFOz5TspaAFUt4ScmGzRzZx9R1saKT7/GiG+GiqnXHltHQF95sFcmDnjA1EsK7ZvkB7i1oefThyanG3A/wy5gBRAdHR1WFqegAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDAegZXYAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwb9wtZAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[560.14697265625,209.135467529297,1],[565.813598632812,209.135467529297,1],[565.813598632812,216.802124023438,1],[560.14697265625,216.802124023438,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[562.980285644531,212.968795776367,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;44&#34;:{&#34;id&#34;:44,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.90000009536743,-2.90000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAQAAAD4MpbhAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAA0klEQVQoz63Rv0qCcRTG8Y8vGtHWFBgRRG6NLt1CW2BTXUB7uLR7B91Cc0hbc7QUTpYEQhANUdQiSoZxGgp/b1KC0LM9nO95OH/4P83bd+7ZUNeR5cnyipYQhnpCeFXNlzMXwpOaEqpuhDtzCdgRRrmedSOhBkWwjTNXY6DrwId2SrgVDn+fPQNLeJwGFP/e/gt4+U5JKisrJHsinP4AmsJxsrvCu42xX9MX9hJQ0hIebMkUbGoL1/lDsaojhIGBEO5VJsddUHep501Hw+JMj56qT2zrPTARFwicAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU3KzEwOjAwHoGV2AAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMG/cLWQAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[560.14697265625,191.85546875,1],[565.480285644531,191.85546875,1],[565.480285644531,197.85546875,1],[560.14697265625,197.85546875,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[562.813598632812,194.85546875,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;45&#34;:{&#34;id&#34;:45,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3,-3],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAL8AAAApCAQAAADO3DDTAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDl2xNRhAAAJMUlEQVRo3u2ae3BXxRXHP4GEhATDo+EVIhShQi2BUlBTHgIFhTK8i0XeOnUqtXYctaUMhUE7nWqrgwwwtGMVC4EpYP8oNoUCMoxIKVRECkwsD2sUAoQQCHknhGz/2PO7v9179/coDzND8r1//H579uw5e7+79+zuuRea0YxmNFW0auwO2JjELi5xDUVWDM1XUCgKGrvDN4FWLGXVbbD7IgrFJSlloajnEu8xMVbDl1DedafTP4oTKN68DZaD9IeuX9qKLazSQJY2NidfIl7l3i/d5xIeNIs2/U+QAFxlPj1Ip7BRyblzUEg6WcygAkhgjlmVaCk+AMBK1jd2j+8oKMopZwvZLAEGm1X27L8bgMON3d87FIcA6GyKbPpTAbja2P28Q1EBwF2myKY/CYDrzsZj2chn1FDCh/yUtlEdteXHbKOAaso4xXqm+/xMk33AWGfrzSgUp33SLixmN+eopZT/8DZTSQi0tHccJvQu7ayUpqBQDALgB9KXdgAsQqH4I9CDjRRTxnFW0tewNIZcTlNFGcf4Db2ADLGQEYP+egBSIitUo1AMC8gz2W1snhSKMwyPuPF8iks+bcUxa8VvRYl3m360oRKFYpkhS+LX1ARs/pucm6Lfvmz6u1Fo1D0s7Tqy3deqmmcd9Lv7MVxaRMQ1FCpwUz0447mrEuIUFexy0J/Aak+3ngtcNjo6zdBbg0JRSnKgD3NEv5cnac0HnpUGLlHllWp47IbozyGPPEpRKL4gjzzySLPo32lQXCIblM6cMjyHp9jrcdI/RFiJgBZiZqAlbclBke+WgenEYoMCm/6fi/QksyTKdeVncqNVDPD0ckRvaqAX21Ao9hkD+q7naR7pAGTzBtdRKOr49g3Qr3EIFTh2afrPoVAU8g7buMJa6cce6cc/GEEC0IHnKTOGKRb9g0QvESfaB+YdwBMiXWfF7xzPsUn/ffL8vEcby0YfzqJQsvZrnESh2OzrQ4ZYeMqTTBc/+3zrzaOi+V/jdm4V/Vquo3QbugMwS+SbaGnoZ3Mxbvp7id5X3PT3R6G4Lo9hCB/LTbb2aS9w0L8WhaJI4qiJ8aI9xpMsRaGo9A3Uj+TRbu9JjsutdA7YXCY2590G+j/xbRbgMHpDkOqTT46b/hR5YsMxwHIyWtxUWiP2TQDWBJaMN7nokyQzE4DfUxq4/W18DmDE/1wUkMokS28WAHlckfLX+AYAqykK2HxV/Mzi1uNtGqxyXwnJy6nyaW7l4zht1nAcwJiCBv1deQ7AFw6Ge/T5Uc9ffZLB8rjucTrfb9mDAonv5uJ5N0MByPUk35HfdxwWq8gDYGikaHoT2O8rj5Lfvzh0/xy31U0APE+3kEB3fAgP8AJZQD6rrQZfB6COEw5jR3zl0JK9jmsObf1o3mNI1jMcGEt7b67PJAEoMQa7DwBVfOK8nUPMAdqQyRc3xnJE5PvK/QEo5pxD96O4ra5gJtlk8i9e4yD7Q/S/K8vBTmZTYzXoAsAV51HM35VQ7OsepQOppHgetrCKFFoxjbdEosPIJmP4dL+KfKEghAue1q2lXwXCp06+X3RqXyBeVDOaDTxCJsspIcOO/duY4lgudDMXynzl6Cdh26JuvxVAVgzoK4tSrqGtN5qVEWyF5KncWlQFhjs1Cg+VxI9iJkjIBGz6x3OIr/rU9UxNc5ryH5l05xQpJES5So0WmuiRsquZDcBJDhoaFVH8h/MnUU6SgptdHaL1I+3/sNOVw0wIFzX9vRnHUeA+/u7LSZwHoL1kg2x08JVLAEigR9yd2UER0JLpQGgRzrU0LgPQKbAN1MiU32JL6tJtw81BR4XOzrqOcVtJYif9gKOMo3e4q6XsYBSfAX34odVAL0GJ9HMY6+8rh5bnYbjQwZFgqOdPAEwFBtMbUGxw+E+zkl5h6KRZjfdiSK9QrR2a0dajeHBE7sH1AnZA3FYepx9QwCh26CgQnimXZc8zw2oQ2kROdRgb5yvvk4jp2ocnsJ9qCoXuMPRcf4i2fF9sFFj1H8jvdIfNVMYDcMCL1DoIpQTCQUvud7RXcdMGe+V3gqMu5gt0D5qZlfJM+/AtOXHacfJ9Ocn6j8rfdZx6twfOtmHHuua3gZpjKBSPSTrryUD9UfEfTOcuEZvPeJK5Ipnk03xS5PapV+ey1lqyRZJODEKf/vMDH6Y8SEOcp95EyeUOxImOuL5wGCtSe1W4R7I4Nv0jRVZEtmWjr+RJaxwP70LJBumsaHD3NE9s7vHF74nUoVBcMF5ghLIqH1nzfzhXnPTrFNqOOOkPZWL/YL1n6GZkQWPR3130IqwVyc6MJ2wU+WFG0wJozeMURch4/k6kZSyShSqdp7208yKH10zJhCgUWxz14YznSR6VKdCLFdSjE9CTLe0PvQGYQAZ3cT9rqPNymDb9m0X3JcYwRSxHph8v47lLMr9pzBe7/lSam/5+opdEBGgihvikaez1XJRzhlp03nqVg/5ktnq6DRRxRmjSOdMEp9ddnsYEZ3079nkadZzx3jgo6lng0x0heVD7OssjDvoXWTqDYtLfxZjpFZwXTw1e79Jj0D+IqPl+hNgRAXkKa4w5qodhprwzKvDptmAJ5QECqlgYgfxwxL4YcXfeitelb+aVz0MO3ckU+/T+SU+ZeTb96XxqaM2OST9kGVMl9JTP5Wn5H97ZuenPkQAbEfolykhnXTaryaeacvJ5jZ4QgX6ADJ7lbxRQSQ3n2clCOkV2SpoM10qioQe/4H0KqaWKE6xjYoSzALTjBfZSRC2fk8cMEsFJP2SwglNUUs2nzI2DfoDx5HKKCso5xst0A56TdS0MN/1DY9m+ikJ5WcZmxIcXI05DG8NQKPs7EnsG6Vx2UkxDTQ+JfI8BEc7OOit8MqYNzWudKbLp1yOTHtNQ00MDWzhCufESNITOsvc6ENOGTtJYiUqbfp1CzolpqOmhQVIqC3w5sSTeIhlQgfN8EPrkfTqywq9klzKTLs7MSVPGYtnfHGCicJPMGG9LHv0z9dZkMl82GMsiq90rJ0nX6bepI1lO5kp2NeeME8beqJPV/L6/lp7RnDzjZTCa6fcjnQ2OI901lkf7cBCb/p/EcjKC7RRT30y/E/14mX1cpJZazrOHJXG83chCcY1itjtSkc1oRpPF/wAZu7h9KeGCZQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1NysxMDowMB6BldgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTcrMTA6MDBv3C1kAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[28.3680686950684,417.052398681641,1],[92.0347366333008,417.052398681641,1],[92.0347366333008,430.719055175781,1],[28.3680686950684,430.719055175781,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[60.2014007568359,423.8857421875,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;12&#34;:{&#34;id&#34;:12,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0.32139378786087,0.342020124197006,0.88302218914032]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;9&#34;:{&#34;id&#34;:9,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;back&#34;:&#34;filled&#34;},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;11&#34;:{&#34;id&#34;:11,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;fog&#34;:false},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;13&#34;:{&#34;id&#34;:13,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;6&#34;:{&#34;id&#34;:6,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:1,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:6,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,1359.32861328125],&#34;modelMatrix&#34;:[[0.866025388240814,0,0.5,-247.002243041992],[0,1,0,-219.315811157227],[-0.5,0,0.866025388240814,-1217.29919433594],[0,0,0,1]],&#34;projMatrix&#34;:[[3.49879765510559,0,0,0],[0,4.66506338119507,0,0],[0,0,-3.86370372772217,-4900.22265625],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[0.866025388240814,0,0.5,0],[0,1,0,0],[-0.5,0,0.866025388240814,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:0.800000011920929,&#34;bbox&#34;:[3.70292210578918,566.14697265625,7.91255760192871,430.719055175781,0,1],&#34;windowRect&#34;:[0,0,576,432],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:false,&#34;fontname&#34;:&#34;NULL&#34;,&#34;maxClipPlanes&#34;:2147483647,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[13,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,12],&#34;subscenes&#34;:[],&#34;flags&#34;:17006},&#34;52&#34;:{&#34;id&#34;:52,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:52,&#34;sphereVerts&#34;:{&#34;vb&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.195090322016128,-0.38268343236509,-0.555570233019602,-0.707106781186547,-0.831469612302545,-0.923879532511287,-0.98078528040323,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1],[0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.195090322016128,-0.38268343236509,-0.555570233019602,-0.707106781186547,-0.831469612302545,-0.923879532511287,-0.98078528040323,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0]],&#34;it&#34;:[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270],[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271]],&#34;material&#34;:[],&#34;normals&#34;:null,&#34;texcoords&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1]],&#34;meshColor&#34;:&#34;vertices&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;div id=&#34;base-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutrgl::rgldev(fov = 30, view = &amp;#39;flat&amp;#39;, view_angle = 30, zoom = 0.6) 
pie(c(cool=1, but = 2, use=3, less = 4))
dev.off()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;quartz_off_screen 
                2 &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;rgl39475&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl39475&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#FFFFFF&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;lines&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:true,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:53,&#34;objects&#34;:{&#34;63&#34;:{&#34;id&#34;:63,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[302.399993896484,223.199996948242,0],[401.655303955078,272.743804931641,0],[399.962951660156,275.998443603516,0],[401.655303955078,272.743804931641,0],[302.399993896484,223.199996948242,0],[403.239135742188,269.434997558594,0],[302.399993896484,223.199996948242,0],[404.712677001953,266.075653076172,0],[403.239135742188,269.434997558594,0],[404.712677001953,266.075653076172,0],[302.399993896484,223.199996948242,0],[406.074340820312,262.669403076172,0],[302.399993896484,223.199996948242,0],[407.322662353516,259.220001220703,0],[406.074340820312,262.669403076172,0],[392.146942138672,288.404968261719,0],[302.399993896484,223.199996948242,0],[394.253784179688,285.401977539062,0],[302.399993896484,223.199996948242,0],[398.163909912109,279.1953125,0],[396.260162353516,282.330993652344,0],[394.253784179688,285.401977539062,0],[302.399993896484,223.199996948242,0],[396.260162353516,282.330993652344,0],[399.962951660156,275.998443603516,0],[398.163909912109,279.1953125,0],[302.399993896484,223.199996948242,0],[412.364227294922,237.831237792969,0],[302.399993896484,223.199996948242,0],[412.787872314453,234.187454223633,0],[302.399993896484,223.199996948242,0],[413.272674560547,226.867828369141,0],[413.090789794922,230.531646728516,0],[412.787872314453,234.187454223633,0],[302.399993896484,223.199996948242,0],[413.090789794922,230.531646728516,0],[302.399993896484,223.199996948242,0],[412.364227294922,237.831237792969,0],[411.820343017578,241.459030151367,0],[302.399993896484,223.199996948242,0],[408.456237792969,255.731201171875,0],[407.322662353516,259.220001220703,0],[409.473846435547,252.206848144531,0],[408.456237792969,255.731201171875,0],[302.399993896484,223.199996948242,0],[411.156829833984,245.066848754883,0],[410.374359130859,248.650756835938,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[410.374359130859,248.650756835938,0],[409.473846435547,252.206848144531,0],[411.156829833984,245.066848754883,0],[302.399993896484,223.199996948242,0],[411.820343017578,241.459030151367,0],[413.333343505859,223.199996948242,0],[413.272674560547,226.867828369141,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[368.006103515625,257.314086914062,0],[369.09814453125,255.126266479492,0],[370.117279052734,252.903549194336,0],[371.062347412109,250.648361206055,0],[371.932342529297,248.363128662109,0],[362.93359375,265.669006347656,0],[365.608032226562,261.575439453125,0],[364.304656982422,263.644348144531,0],[366.84228515625,259.464599609375,0],[375.850708007812,231.739562988281,0],[376.254486083984,226.866500854492,0],[376.092895507812,229.306365966797,0],[375.528198242188,234.163436889648,0],[372.726287841797,246.050415039062,0],[373.443359375,243.712692260742,0],[374.643737792969,238.972534179688,0],[374.082733154297,241.3525390625,0],[375.125732421875,236.575302124023,0],[376.335327148438,224.422607421875,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;64&#34;:{&#34;id&#34;:64,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[413.333343505859,223.199996948242,0],[413.272674560547,226.867828369141,0],[413.090789794922,230.531646728516,0],[412.787872314453,234.187454223633,0],[412.364227294922,237.831237792969,0],[411.820343017578,241.459030151367,0],[411.156829833984,245.066848754883,0],[410.374359130859,248.650756835938,0],[409.473846435547,252.206848144531,0],[408.456237792969,255.731201171875,0],[407.322662353516,259.220001220703,0],[406.074340820312,262.669403076172,0],[404.712677001953,266.075653076172,0],[403.239135742188,269.434997558594,0],[401.655303955078,272.743804931641,0],[399.962951660156,275.998443603516,0],[398.163909912109,279.1953125,0],[396.260162353516,282.330993652344,0],[394.253784179688,285.401977539062,0],[392.146942138672,288.404968261719,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[413.333343505859,223.199996948242,0],[413.272674560547,226.867828369141,0],[413.090789794922,230.531646728516,0],[412.787872314453,234.187454223633,0],[412.364227294922,237.831237792969,0],[411.820343017578,241.459030151367,0],[411.156829833984,245.066848754883,0],[410.374359130859,248.650756835938,0],[409.473846435547,252.206848144531,0],[408.456237792969,255.731201171875,0],[407.322662353516,259.220001220703,0],[406.074340820312,262.669403076172,0],[404.712677001953,266.075653076172,0],[403.239135742188,269.434997558594,0],[401.655303955078,272.743804931641,0],[399.962951660156,275.998443603516,0],[398.163909912109,279.1953125,0],[396.260162353516,282.330993652344,0],[394.253784179688,285.401977539062,0],[392.146942138672,288.404968261719,0],[302.399993896484,223.199996948242,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;65&#34;:{&#34;id&#34;:65,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.200000002980232,-0.200000002980232]},&#34;vertices&#34;:[[407.903869628906,257.480285644531,0],[413.179077148438,259.194305419922,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[407.903869628906,257.480285644531,0],[413.179077148438,259.194305419922,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;66&#34;:{&#34;id&#34;:66,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.300000011920929,-0.300000011920929],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAeCAQAAADd02vRAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDrvzYXbAAACa0lEQVRIx+3Wy4sVRxTH8Y+KjoxPEIlxoYIrFQQVUYRE4yIG4krc+EAHIcSl4EI3/gPJXyBuQnQUBEVBJGQpqAsxYYLic0bGF4oJovNijHqy6LK9d7pm7LtSyfx6U3XqW+f+qvtw6jKuT0PnhHAQJn5sL4XGbYzb+KxsTLbDab2GDeh23HeZHW06nNJrUJ+7jtk6ylHqchV9o0eMeH43p4nZ5EGF+cvySq46XEPfeK8t/k14l04ndZez9pLZ5W2Z8oSTbqdZv41NuepxGRsL9QnhlrXl59rrtRB+TpG1yeg1q8t933oohL8tLGN1uYyNw0J4ZG7TqQ4Ioc80cCEZnd3ELPBMCEfLSF2uYmNSQjpGfOF2L4Wn1mB5erEbjVSHEF6bRwtcxsbXQnjVUAXvtNisNNovhDuqavNCCNtb4jJX21Jw3WBla7cXabQCXMqkH3YFrGyJa1Jh4wvw2FgqquZ+du1BA1GXy9goesOgsTQT9GfXBiAVcl0uY6Mw0G4sFYmnZ9dmNPxIXS5j4x/wZWZjmwlp9AwsyKYvok9a4jI2/gTLTK2s/2TILftwFazLWl0FbtACl9F0Q0LYVlm5U/aTFakfbKgwu4TwNp21LpftokeE0JMK7J12py5aRC8K4UbZSQrN90QI58tIXS57pzwXwh+WpcgEO9M7OpQi69Jd0ZV6A6x3TwjPLSpjdbnsDbvZsBDeuOwXneUN+5vJJfOjNyl61a86XUuzAd835arHZW3wVXLc+BwZUbabPaowXZZU6qAON4oNptjjjPuG9LvpcK7tmuoHZ/UaNKzHCVtG+Vf1YW5UG/93/QfSSodfSSgU/wAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1OCsxMDowMOjJ5TEAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTgrMTA6MDCZlF2NAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[418.454254150391,256.718872070312,1],[440.78759765625,256.718872070312,1],[440.78759765625,266.718872070312,1],[418.454254150391,266.718872070312,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[429.620910644531,261.718872070312,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;67&#34;:{&#34;id&#34;:67,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464]},&#34;vertices&#34;:[[302.399993896484,223.199996948242,0],[274.985137939453,330.692474365234,0],[271.536407470703,329.753479003906,0],[274.985137939453,330.692474365234,0],[302.399993896484,223.199996948242,0],[278.462341308594,331.519866943359,0],[281.964385986328,332.234802246094,0],[278.462341308594,331.519866943359,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[271.536407470703,329.753479003906,0],[268.119720458984,328.703857421875,0],[302.399993896484,223.199996948242,0],[331.542999267578,330.236846923828,0],[328.07958984375,331.120178222656,0],[331.542999267578,330.236846923828,0],[302.399993896484,223.199996948242,0],[334.976165771484,329.242431640625,0],[302.399993896484,223.199996948242,0],[324.589508056641,331.891448974609,0],[321.076416015625,332.549865722656,0],[324.589508056641,331.891448974609,0],[302.399993896484,223.199996948242,0],[328.07958984375,331.120178222656,0],[281.964385986328,332.234802246094,0],[302.399993896484,223.199996948242,0],[285.487640380859,332.836578369141,0],[317.543914794922,333.094787597656,0],[302.399993896484,223.199996948242,0],[321.076416015625,332.549865722656,0],[292.583160400391,333.698120117188,0],[289.028472900391,333.324493408203,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[296.148040771484,333.95703125,0],[292.583160400391,333.698120117188,0],[296.148040771484,333.95703125,0],[302.399993896484,223.199996948242,0],[299.719421386719,334.100952148438,0],[289.028472900391,333.324493408203,0],[285.487640380859,332.836578369141,0],[302.399993896484,223.199996948242,0],[313.995697021484,333.525634765625,0],[310.435424804688,333.841918945312,0],[302.399993896484,223.199996948242,0],[303.293609619141,334.129730224609,0],[299.719421386719,334.100952148438,0],[302.399993896484,223.199996948242,0],[303.293609619141,334.129730224609,0],[302.399993896484,223.199996948242,0],[306.866821289062,334.043365478516,0],[310.435424804688,333.841918945312,0],[306.866821289062,334.043365478516,0],[302.399993896484,223.199996948242,0],[317.543914794922,333.094787597656,0],[313.995697021484,333.525634765625,0],[302.399993896484,223.199996948242,0],[375.291137695312,306.824676513672,0],[302.399993896484,223.199996948242,0],[377.947357177734,304.433013916016,0],[372.559265136719,309.129516601562,0],[369.754547119141,311.345153808594,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[375.291137695312,306.824676513672,0],[372.559265136719,309.129516601562,0],[380.525146484375,301.957000732422,0],[377.947357177734,304.433013916016,0],[302.399993896484,223.199996948242,0],[387.761566162109,294.049194335938,0],[385.434783935547,296.762420654297,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[385.434783935547,296.762420654297,0],[383.021820068359,299.399261474609,0],[380.525146484375,301.957000732422,0],[302.399993896484,223.199996948242,0],[383.021820068359,299.399261474609,0],[302.399993896484,223.199996948242,0],[389.999725341797,291.262420654297,0],[387.761566162109,294.049194335938,0],[366.879913330078,313.469299316406,0],[302.399993896484,223.199996948242,0],[369.754547119141,311.345153808594,0],[348.335540771484,324.175903320312,0],[345.058654785156,325.603332519531,0],[302.399993896484,223.199996948242,0],[345.058654785156,325.603332519531,0],[341.737487792969,326.924468994141,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[341.737487792969,326.924468994141,0],[338.375518798828,328.137908935547,0],[334.976165771484,329.242431640625,0],[302.399993896484,223.199996948242,0],[338.375518798828,328.137908935547,0],[302.399993896484,223.199996948242,0],[363.938354492188,315.499694824219,0],[360.932891845703,317.434295654297,0],[360.932891845703,317.434295654297,0],[357.866668701172,319.271087646484,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[354.742858886719,321.008117675781,0],[351.564727783203,322.643615722656,0],[351.564727783203,322.643615722656,0],[348.335540771484,324.175903320312,0],[302.399993896484,223.199996948242,0],[357.866668701172,319.271087646484,0],[354.742858886719,321.008117675781,0],[302.399993896484,223.199996948242,0],[366.879913330078,313.469299316406,0],[363.938354492188,315.499694824219,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[392.146942138672,288.404968261719,0],[389.999725341797,291.262420654297,0]],&#34;colors&#34;:[[0.678431391716003,0.847058832645416,0.901960790157318,1]],&#34;centers&#34;:[[282.973846435547,294.548645019531,0],[285.282501220703,295.137451171875,0],[287.608947753906,295.651550292969,0],[280.685394287109,293.885803222656,0],[320.674194335938,294.852355957031,0],[322.973083496094,294.226440429688,0],[316.02197265625,295.880432128906,0],[318.356384277344,295.403869628906,0],[289.95068359375,296.090454101562,0],[313.673461914062,296.281555175781,0],[294.670532226562,296.740875244141,0],[297.043762207031,296.951721191406,0],[299.422485351562,297.085998535156,0],[292.305389404297,296.453704833984,0],[308.943725585938,296.855865478516,0],[301.804382324219,297.143585205078,0],[304.186828613281,297.124359130859,0],[306.567443847656,297.028442382812,0],[311.313201904297,296.606811523438,0],[351.879516601562,278.152557373047,0],[348.237976074219,281.224914550781,0],[350.08349609375,279.718078613281,0],[353.624206542969,276.530029296875,0],[358.532104492188,271.337219238281,0],[356.952209472656,273.120574951172,0],[355.315673828125,274.852111816406,0],[360.053771972656,269.503875732422,0],[346.344818115234,282.671508789062,0],[331.931396484375,290.993103027344,0],[329.732055664062,291.909301757812,0],[327.504333496094,292.754119873047,0],[325.250579833984,293.526794433594,0],[342.423767089844,285.378021240234,0],[340.399871826172,286.635131835938,0],[336.23583984375,288.950592041016,0],[334.10009765625,290.006530761719,0],[338.336517333984,287.826416015625,0],[344.406097412109,284.056335449219,0],[361.515563964844,267.622497558594,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;68&#34;:{&#34;id&#34;:68,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464]},&#34;vertices&#34;:[[392.146942138672,288.404968261719,0],[389.999725341797,291.262420654297,0],[387.761566162109,294.049194335938,0],[385.434783935547,296.762420654297,0],[383.021820068359,299.399261474609,0],[380.525146484375,301.957000732422,0],[377.947357177734,304.433013916016,0],[375.291137695312,306.824676513672,0],[372.559265136719,309.129516601562,0],[369.754547119141,311.345153808594,0],[366.879913330078,313.469299316406,0],[363.938354492188,315.499694824219,0],[360.932891845703,317.434295654297,0],[357.866668701172,319.271087646484,0],[354.742858886719,321.008117675781,0],[351.564727783203,322.643615722656,0],[348.335540771484,324.175903320312,0],[345.058654785156,325.603332519531,0],[341.737487792969,326.924468994141,0],[338.375518798828,328.137908935547,0],[334.976165771484,329.242431640625,0],[331.542999267578,330.236846923828,0],[328.07958984375,331.120178222656,0],[324.589508056641,331.891448974609,0],[321.076416015625,332.549865722656,0],[317.543914794922,333.094787597656,0],[313.995697021484,333.525634765625,0],[310.435424804688,333.841918945312,0],[306.866821289062,334.043365478516,0],[303.293609619141,334.129730224609,0],[299.719421386719,334.100952148438,0],[296.148040771484,333.95703125,0],[292.583160400391,333.698120117188,0],[289.028472900391,333.324493408203,0],[285.487640380859,332.836578369141,0],[281.964385986328,332.234802246094,0],[278.462341308594,331.519866943359,0],[274.985137939453,330.692474365234,0],[271.536407470703,329.753479003906,0],[268.119720458984,328.703857421875,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[392.146942138672,288.404968261719,0],[389.999725341797,291.262420654297,0],[387.761566162109,294.049194335938,0],[385.434783935547,296.762420654297,0],[383.021820068359,299.399261474609,0],[380.525146484375,301.957000732422,0],[377.947357177734,304.433013916016,0],[375.291137695312,306.824676513672,0],[372.559265136719,309.129516601562,0],[369.754547119141,311.345153808594,0],[366.879913330078,313.469299316406,0],[363.938354492188,315.499694824219,0],[360.932891845703,317.434295654297,0],[357.866668701172,319.271087646484,0],[354.742858886719,321.008117675781,0],[351.564727783203,322.643615722656,0],[348.335540771484,324.175903320312,0],[345.058654785156,325.603332519531,0],[341.737487792969,326.924468994141,0],[338.375518798828,328.137908935547,0],[334.976165771484,329.242431640625,0],[331.542999267578,330.236846923828,0],[328.07958984375,331.120178222656,0],[324.589508056641,331.891448974609,0],[321.076416015625,332.549865722656,0],[317.543914794922,333.094787597656,0],[313.995697021484,333.525634765625,0],[310.435424804688,333.841918945312,0],[306.866821289062,334.043365478516,0],[303.293609619141,334.129730224609,0],[299.719421386719,334.100952148438,0],[296.148040771484,333.95703125,0],[292.583160400391,333.698120117188,0],[289.028472900391,333.324493408203,0],[285.487640380859,332.836578369141,0],[281.964385986328,332.234802246094,0],[278.462341308594,331.519866943359,0],[274.985137939453,330.692474365234,0],[271.536407470703,329.753479003906,0],[268.119720458984,328.703857421875,0],[302.399993896484,223.199996948242,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;69&#34;:{&#34;id&#34;:69,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.5,-0.5]},&#34;vertices&#34;:[[336.680297851562,328.703857421875,0],[338.394287109375,333.979064941406,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[336.680297851562,328.703857421875,0],[338.394287109375,333.979064941406,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;70&#34;:{&#34;id&#34;:70,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.600000023841858,-0.600000023841858],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAeCAQAAADJRvUwAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDrvzYXbAAACHUlEQVRIx93WTYiNcRTH8Q9jDNMgE2YsBolRahpvK4rJikKKnZEaNrKZRE02CqMssLBWFrJQVylhx1BK04gmeV14y7xlpGEymPu3uI/78jzX4ta9mznP4rnn/E7ne/4vz+kyNe2qIDhT5qrNanPO9Aq1XuusfnNzgRkVwdR4YUlhqDIrqo5jKrd1CZv6oDUue+enIT06zYmptwRBV6LKXUHQCdoFY1F8QBBsS4K69OqwVI1FNrvotZ3lWlH+9W63FOPuGbHSRtM0umGvmyVV7HPcTN3glDG8zImZyRAE18yPYq1eCoIvGkraOqiLqjX+74yu2+dr9PuZNiOod6wcW5cPGndYyPMHnQQd5Zgf+aAbRmPqNWnUW1te0KOE+s0bsL68oE9F9AGwsLygH0X0TGx2eUGziuh1kL2J/7Pq0kCLi+hNYDDyMneyKpE1rzRQa0JtsBw8jvw/eavM2TQrSgPtTmzBQfDe68j/BpbFsrYkVpTOtlAU1BR9oP9slRPgUjbyCuyyIC+r1sVE+7+jd3z6Z2dd2mk1UazNZ0HwPO+/TEuU16s5imzyVDAZm3V8FwTnVSk40wzogSAYlnJFX1RyyOqCllJRfFK/Hh+inO4EqDfKmzDhQBy0w4XsFM88TxLHXOdOLOeFFocSoD3S2Yxz8TPiqK1SPvtl0G37bfA2Bvpuu52u+2jCsIeOWKdf0lJ2uW/UHyMFg3oK2V+Qkb4eQsKT3wAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1OCsxMDowMOjJ5TEAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTgrMTA6MDCZlF2NAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[340.108306884766,335.035491943359,1],[357.441650390625,335.035491943359,1],[357.441650390625,345.035491943359,1],[340.108306884766,345.035491943359,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[348.774963378906,340.035491943359,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;71&#34;:{&#34;id&#34;:71,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071]},&#34;vertices&#34;:[[192.697326660156,206.721878051758,0],[302.399993896484,223.199996948242,0],[192.226959228516,210.234512329102,0],[192.697326660156,206.721878051758,0],[193.279678344727,203.226058959961,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[191.472961425781,224.381362915039,0],[191.491821289062,220.837417602539,0],[191.869018554688,213.760375976562,0],[192.226959228516,210.234512329102,0],[302.399993896484,223.199996948242,0],[191.491821289062,220.837417602539,0],[191.623886108398,217.295883178711,0],[302.399993896484,223.199996948242,0],[193.973388671875,199.750625610352,0],[302.399993896484,223.199996948242,0],[193.279678344727,203.226058959961,0],[302.399993896484,223.199996948242,0],[199.083770751953,182.802459716797,0],[200.426910400391,179.522842407227,0],[302.399993896484,223.199996948242,0],[200.426910400391,179.522842407227,0],[201.874130249023,176.287811279297,0],[302.399993896484,223.199996948242,0],[197.846084594727,186.123291015625,0],[199.083770751953,182.802459716797,0],[302.399993896484,223.199996948242,0],[194.777755737305,196.299118041992,0],[195.691970825195,192.875076293945,0],[196.715087890625,189.481979370117,0],[197.846084594727,186.123291015625,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[195.691970825195,192.875076293945,0],[196.715087890625,189.481979370117,0],[193.973388671875,199.750625610352,0],[194.777755737305,196.299118041992,0],[302.399993896484,223.199996948242,0],[191.623886108398,217.295883178711,0],[191.869018554688,213.760375976562,0],[302.399993896484,223.199996948242,0],[191.567306518555,227.924087524414,0],[302.399993896484,223.199996948242,0],[191.774765014648,231.462005615234,0],[193.073150634766,242.010757446289,0],[192.528076171875,238.508941650391,0],[302.399993896484,223.199996948242,0],[192.528076171875,238.508941650391,0],[192.095123291016,234.991485595703,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[193.72981262207,245.493392944336,0],[193.073150634766,242.010757446289,0],[193.72981262207,245.493392944336,0],[302.399993896484,223.199996948242,0],[194.49739074707,248.953262329102,0],[302.399993896484,223.199996948242,0],[191.567306518555,227.924087524414,0],[191.472961425781,224.381362915039,0],[196.362014770508,255.790649414062,0],[195.375091552734,252.386840820312,0],[302.399993896484,223.199996948242,0],[197.457168579102,259.161193847656,0],[302.399993896484,223.199996948242,0],[198.659423828125,262.495025634766,0],[191.774765014648,231.462005615234,0],[302.399993896484,223.199996948242,0],[192.095123291016,234.991485595703,0],[201.380249023438,269.039001464844,0],[199.967559814453,265.788757324219,0],[302.399993896484,223.199996948242,0],[198.659423828125,262.495025634766,0],[302.399993896484,223.199996948242,0],[199.967559814453,265.788757324219,0],[302.399993896484,223.199996948242,0],[195.375091552734,252.386840820312,0],[194.49739074707,248.953262329102,0],[302.399993896484,223.199996948242,0],[197.457168579102,259.161193847656,0],[196.362014770508,255.790649414062,0],[201.380249023438,269.039001464844,0],[302.399993896484,223.199996948242,0],[202.896026611328,272.242492675781,0],[302.399993896484,223.199996948242,0],[201.874130249023,176.287811279297,0],[203.423950195312,173.100646972656,0],[302.399993896484,223.199996948242,0],[204.513366699219,275.395904541016,0],[202.896026611328,272.242492675781,0],[206.824935913086,166.882934570312,0],[302.399993896484,223.199996948242,0],[205.074768066406,169.964630126953,0],[206.230621337891,278.496063232422,0],[204.513366699219,275.395904541016,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[209.957702636719,284.523956298828,0],[208.046020507812,281.539764404297,0],[208.046020507812,281.539764404297,0],[206.230621337891,278.496063232422,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[206.824935913086,166.882934570312,0],[208.672637939453,163.858734130859,0],[302.399993896484,223.199996948242,0],[203.423950195312,173.100646972656,0],[205.074768066406,169.964630126953,0],[302.399993896484,223.199996948242,0],[208.672637939453,163.858734130859,0],[210.616012573242,160.895080566406,0],[209.957702636719,284.523956298828,0],[302.399993896484,223.199996948242,0],[211.963745117188,287.445526123047,0],[212.653045654297,157.995025634766,0],[302.399993896484,223.199996948242,0],[210.616012573242,160.895080566406,0],[211.963745117188,287.445526123047,0],[302.399993896484,223.199996948242,0],[214.062088012695,290.301544189453,0],[214.062088012695,290.301544189453,0],[302.399993896484,223.199996948242,0],[216.250595092773,293.089080810547,0],[216.250595092773,293.089080810547,0],[302.399993896484,223.199996948242,0],[218.52702331543,295.805297851562,0],[302.399993896484,223.199996948242,0],[220.889053344727,298.447387695312,0],[218.52702331543,295.805297851562,0],[302.399993896484,223.199996948242,0],[223.334274291992,301.0126953125,0],[220.889053344727,298.447387695312,0],[223.334274291992,301.0126953125,0],[302.399993896484,223.199996948242,0],[225.86018371582,303.498565673828,0],[231.14372253418,308.222045898438,0],[228.464218139648,305.902526855469,0],[302.399993896484,223.199996948242,0],[239.607238769531,314.650939941406,0],[236.718063354492,312.598480224609,0],[302.399993896484,223.199996948242,0],[233.895935058594,310.454772949219,0],[302.399993896484,223.199996948242,0],[236.718063354492,312.598480224609,0],[231.14372253418,308.222045898438,0],[302.399993896484,223.199996948242,0],[233.895935058594,310.454772949219,0],[302.399993896484,223.199996948242,0],[242.560501098633,316.610046386719,0],[239.607238769531,314.650939941406,0],[225.86018371582,303.498565673828,0],[302.399993896484,223.199996948242,0],[228.464218139648,305.902526855469,0],[245.574829101562,318.473846435547,0],[302.399993896484,223.199996948242,0],[248.647155761719,320.240386962891,0],[248.647155761719,320.240386962891,0],[302.399993896484,223.199996948242,0],[251.774337768555,321.907897949219,0],[245.574829101562,318.473846435547,0],[242.560501098633,316.610046386719,0],[302.399993896484,223.199996948242,0],[258.180480957031,324.939086914062,0],[302.399993896484,223.199996948242,0],[261.452911376953,326.299652099609,0],[258.180480957031,324.939086914062,0],[254.953201293945,323.474639892578,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[254.953201293945,323.474639892578,0],[251.774337768555,321.907897949219,0],[264.76708984375,327.555023193359,0],[261.452911376953,326.299652099609,0],[302.399993896484,223.199996948242,0],[268.119720458984,328.703857421875,0],[264.76708984375,327.555023193359,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[1,0.894117653369904,0.882352948188782,1]],&#34;centers&#34;:[[229.108093261719,213.385467529297,0],[229.458984375,211.04931640625,0],[228.454925537109,222.806259155273,0],[228.832000732422,215.731628417969,0],[228.505249023438,220.444442749023,0],[229.884368896484,208.725570678711,0],[233.97021484375,195.175094604492,0],[234.900360107422,193.003540039062,0],[233.109954833984,197.375244140625,0],[230.956573486328,204.124740600586,0],[232.320404052734,199.601776123047,0],[231.602355957031,201.852355957031,0],[230.383712768555,206.416595458984,0],[228.630981445312,218.085433959961,0],[228.580688476562,227.528686523438,0],[229.333740234375,234.5732421875,0],[229.007736206055,232.233489990234,0],[229.734344482422,236.901397705078,0],[230.209075927734,239.215560913086,0],[228.480087280273,225.168487548828,0],[231.379028320312,243.792510986328,0],[232.8388671875,248.285400390625,0],[228.756637573242,229.884490966797,0],[234.582611083984,252.675933837891,0],[233.675659179688,250.494598388672,0],[230.75749206543,241.513366699219,0],[232.073059082031,246.050628662109,0],[235.55876159668,254.827178955078,0],[235.899353027344,190.862823486328,0],[236.603134155273,256.946136474609,0],[238.099899291992,186.682540893555,0],[237.714660644531,259.030670166016,0],[240.134567260742,263.087890625,0],[238.892211914062,261.07861328125,0],[239.299194335938,184.647216796875,0],[236.966232299805,188.755096435547,0],[240.562896728516,182.651275634766,0],[241.440475463867,265.056488037109,0],[241.889694213867,180.696701049805,0],[242.808624267578,266.982360839844,0],[244.237579345703,268.863525390625,0],[245.725875854492,270.698120117188,0],[247.272033691406,272.484252929688,0],[248.874435424805,274.220031738281,0],[250.531478881836,275.903778076172,0],[254.002655029297,279.108215332031,0],[259.575134277344,283.483154296875,0],[257.671325683594,282.084442138672,0],[255.813217163086,280.625610351562,0],[261.522583007812,284.820343017578,0],[252.241485595703,277.53369140625,0],[265.540679931641,287.304748535156,0],[267.607177734375,288.449432373047,0],[263.511779785156,286.094635009766,0],[274.011108398438,291.479583740234,0],[271.844573974609,290.537902832031,0],[269.709197998047,289.527526855469,0],[276.206665039062,292.3515625,0],[278.428955078125,293.152984619141,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;72&#34;:{&#34;id&#34;:72,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071]},&#34;vertices&#34;:[[268.119720458984,328.703857421875,0],[264.76708984375,327.555023193359,0],[261.452911376953,326.299652099609,0],[258.180480957031,324.939086914062,0],[254.953201293945,323.474639892578,0],[251.774337768555,321.907897949219,0],[248.647155761719,320.240386962891,0],[245.574829101562,318.473846435547,0],[242.560501098633,316.610046386719,0],[239.607238769531,314.650939941406,0],[236.718063354492,312.598480224609,0],[233.895935058594,310.454772949219,0],[231.14372253418,308.222045898438,0],[228.464218139648,305.902526855469,0],[225.86018371582,303.498565673828,0],[223.334274291992,301.0126953125,0],[220.889053344727,298.447387695312,0],[218.52702331543,295.805297851562,0],[216.250595092773,293.089080810547,0],[214.062088012695,290.301544189453,0],[211.963745117188,287.445526123047,0],[209.957702636719,284.523956298828,0],[208.046020507812,281.539764404297,0],[206.230621337891,278.496063232422,0],[204.513366699219,275.395904541016,0],[202.896026611328,272.242492675781,0],[201.380249023438,269.039001464844,0],[199.967559814453,265.788757324219,0],[198.659423828125,262.495025634766,0],[197.457168579102,259.161193847656,0],[196.362014770508,255.790649414062,0],[195.375091552734,252.386840820312,0],[194.49739074707,248.953262329102,0],[193.72981262207,245.493392944336,0],[193.073150634766,242.010757446289,0],[192.528076171875,238.508941650391,0],[192.095123291016,234.991485595703,0],[191.774765014648,231.462005615234,0],[191.567306518555,227.924087524414,0],[191.472961425781,224.381362915039,0],[191.491821289062,220.837417602539,0],[191.623886108398,217.295883178711,0],[191.869018554688,213.760375976562,0],[192.226959228516,210.234512329102,0],[192.697326660156,206.721878051758,0],[193.279678344727,203.226058959961,0],[193.973388671875,199.750625610352,0],[194.777755737305,196.299118041992,0],[195.691970825195,192.875076293945,0],[196.715087890625,189.481979370117,0],[197.846084594727,186.123291015625,0],[199.083770751953,182.802459716797,0],[200.426910400391,179.522842407227,0],[201.874130249023,176.287811279297,0],[203.423950195312,173.100646972656,0],[205.074768066406,169.964630126953,0],[206.824935913086,166.882934570312,0],[208.672637939453,163.858734130859,0],[210.616012573242,160.895080566406,0],[212.653045654297,157.995025634766,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[268.119720458984,328.703857421875,0],[264.76708984375,327.555023193359,0],[261.452911376953,326.299652099609,0],[258.180480957031,324.939086914062,0],[254.953201293945,323.474639892578,0],[251.774337768555,321.907897949219,0],[248.647155761719,320.240386962891,0],[245.574829101562,318.473846435547,0],[242.560501098633,316.610046386719,0],[239.607238769531,314.650939941406,0],[236.718063354492,312.598480224609,0],[233.895935058594,310.454772949219,0],[231.14372253418,308.222045898438,0],[228.464218139648,305.902526855469,0],[225.86018371582,303.498565673828,0],[223.334274291992,301.0126953125,0],[220.889053344727,298.447387695312,0],[218.52702331543,295.805297851562,0],[216.250595092773,293.089080810547,0],[214.062088012695,290.301544189453,0],[211.963745117188,287.445526123047,0],[209.957702636719,284.523956298828,0],[208.046020507812,281.539764404297,0],[206.230621337891,278.496063232422,0],[204.513366699219,275.395904541016,0],[202.896026611328,272.242492675781,0],[201.380249023438,269.039001464844,0],[199.967559814453,265.788757324219,0],[198.659423828125,262.495025634766,0],[197.457168579102,259.161193847656,0],[196.362014770508,255.790649414062,0],[195.375091552734,252.386840820312,0],[194.49739074707,248.953262329102,0],[193.72981262207,245.493392944336,0],[193.073150634766,242.010757446289,0],[192.528076171875,238.508941650391,0],[192.095123291016,234.991485595703,0],[191.774765014648,231.462005615234,0],[191.567306518555,227.924087524414,0],[191.472961425781,224.381362915039,0],[191.491821289062,220.837417602539,0],[191.623886108398,217.295883178711,0],[191.869018554688,213.760375976562,0],[192.226959228516,210.234512329102,0],[192.697326660156,206.721878051758,0],[193.279678344727,203.226058959961,0],[193.973388671875,199.750625610352,0],[194.777755737305,196.299118041992,0],[195.691970825195,192.875076293945,0],[196.715087890625,189.481979370117,0],[197.846084594727,186.123291015625,0],[199.083770751953,182.802459716797,0],[200.426910400391,179.522842407227,0],[201.874130249023,176.287811279297,0],[203.423950195312,173.100646972656,0],[205.074768066406,169.964630126953,0],[206.824935913086,166.882934570312,0],[208.672637939453,163.858734130859,0],[210.616012573242,160.895080566406,0],[212.653045654297,157.995025634766,0],[302.399993896484,223.199996948242,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;73&#34;:{&#34;id&#34;:73,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.800000011920929,-0.800000011920929]},&#34;vertices&#34;:[[196.896133422852,257.480285644531,0],[191.620941162109,259.194305419922,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[196.896133422852,257.480285644531,0],[191.620941162109,259.194305419922,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;74&#34;:{&#34;id&#34;:74,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.899999976158142,-0.899999976158142],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAAXCAQAAAAfQv91AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDrvzYXbAAACzklEQVRIx+XVS2xVVRQG4O+2AooNjRHQASFqTAmkbRDBFwM1RgNRBholhIQB0WDEgEQdWBM1YnREnKhBBzoRU2l0YhQbtWmsSIOPgpbgK1gCBmhTSCgPixWWg27PvffcW5sbh6wzOGf/+df611p777O4+OxjITxTgXcKYVMZ1uQVvU4YM2yftyyvGrHgftsccNoZv3vfSnX/R/Z5YyL37DYn57dAXwWrX3ORcElNXXnSi+Cw75wwU6trcZNuzc5lrNvs0Aj22ifMs1idZrsss6v2ahucSrxCQuo87LwQNmQ+VzkihD1uyLB5vhbCEbNrl71HCN/nOK8K4Yts/UZq6Ywy1qV2C2FL7U2+PAUoiBL0TUcN+CWtGq0FG42U+Y5q04V12ozVVm1TOhzvmTthaiuEMJRtQ9Hq0xbdWmu1v+q0DKut9qPPdOlxNse5Ob23VvH/G7TqrfUkr/G5hcm51dPO6fGRDkMZ42owy6MTxrgS1S7xf9iwJTb4IVtPc7fXHLbF1IQ0ThqjYXLZKVUa9bqFrrPeB4YTNtVT2tP3eNPbFSZ8ni3Kjp/M+gqRiXIfsNVDZrvRZsfAA+5I/YDrJyu5LtWQlV9ihQr3WZam3RtPts8LljgO7gR9YJErqmittdx804qyJ8E1OdrtuWq7DNlpXY71h52Qfg/dLqC+ypG6yzt22G9xEWoTwhkzS2jT7Un3dFNCXhLCQK6SKQ4IkQl1pFgtZazp+oWwv/RGtySBbzUlZKm9Iv1v/5WdY1QIPeZnnjO0C+FklkyTESEc92DGWuCrpHBveQs+TPB5/b50SAiDXs4Nvo0Z6xsd3tbptBAuWFMSa0VKLxy03bt6U/phc77zDT7NzceftHikYt4+4c+KSTpoVS7aLX6uYJ3yuKp2n+0OGTWox3qXUUWWuZ7T7ZhRZx30icdys2bc6q20zW9G/GVIt7aSG3DR2T/t7jjv3gKFFAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1OCsxMDowMOjJ5TEAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTgrMTA6MDCZlF2NAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[166.998092651367,257.808715820312,1],[186.664749145508,257.808715820312,1],[186.664749145508,265.475372314453,1],[166.998092651367,265.475372314453,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[176.831420898438,261.642028808594,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;75&#34;:{&#34;id&#34;:75,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1,-1]},&#34;vertices&#34;:[[302.399993896484,223.199996948242,0],[279.191833496094,114.721496582031,0],[282.654113769531,114.038177490234,0],[289.635040283203,113.003540039062,0],[302.399993896484,223.199996948242,0],[286.136322021484,113.46533203125,0],[286.136322021484,113.46533203125,0],[302.399993896484,223.199996948242,0],[282.654113769531,114.038177490234,0],[302.399993896484,223.199996948242,0],[289.635040283203,113.003540039062,0],[293.146636962891,112.653266906738,0],[275.753082275391,115.514595031738,0],[279.191833496094,114.721496582031,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[272.341278076172,116.416679382324,0],[275.753082275391,115.514595031738,0],[268.959899902344,117.426826477051,0],[272.341278076172,116.416679382324,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[265.612365722656,118.544021606445,0],[268.959899902344,117.426826477051,0],[302.399993896484,223.199996948242,0],[293.146636962891,112.653266906738,0],[296.667633056641,112.41487121582,0],[302.399993896484,223.199996948242,0],[300.194396972656,112.288597106934,0],[303.723419189453,112.274559020996,0],[302.399993896484,223.199996948242,0],[307.251098632812,112.372787475586,0],[310.773834228516,112.583168029785,0],[303.723419189453,112.274559020996,0],[307.251098632812,112.372787475586,0],[302.399993896484,223.199996948242,0],[314.288146972656,112.905502319336,0],[302.399993896484,223.199996948242,0],[310.773834228516,112.583168029785,0],[302.399993896484,223.199996948242,0],[317.790405273438,113.339454650879,0],[321.277069091797,113.884582519531,0],[302.399993896484,223.199996948242,0],[324.744659423828,114.540344238281,0],[328.189605712891,115.30606842041,0],[302.399993896484,223.199996948242,0],[321.277069091797,113.884582519531,0],[324.744659423828,114.540344238281,0],[314.288146972656,112.905502319336,0],[317.790405273438,113.339454650879,0],[302.399993896484,223.199996948242,0],[300.194396972656,112.288597106934,0],[302.399993896484,223.199996948242,0],[296.667633056641,112.41487121582,0],[302.399993896484,223.199996948242,0],[328.189605712891,115.30606842041,0],[331.608489990234,116.180992126465,0],[302.399993896484,223.199996948242,0],[221.65397644043,147.132369995117,0],[224.114410400391,144.602478027344,0],[302.399993896484,223.199996948242,0],[226.654067993164,142.152114868164,0],[229.270385742188,139.783782958984,0],[302.399993896484,223.199996948242,0],[224.114410400391,144.602478027344,0],[226.654067993164,142.152114868164,0],[231.960723876953,137.499877929688,0],[302.399993896484,223.199996948242,0],[229.270385742188,139.783782958984,0],[302.399993896484,223.199996948242,0],[212.653045654297,157.995025634766,0],[214.772521972656,155.173324584961,0],[219.275253295898,149.739242553711,0],[221.65397644043,147.132369995117,0],[302.399993896484,223.199996948242,0],[216.980667114258,152.420471191406,0],[302.399993896484,223.199996948242,0],[214.772521972656,155.173324584961,0],[219.275253295898,149.739242553711,0],[302.399993896484,223.199996948242,0],[216.980667114258,152.420471191406,0],[231.960723876953,137.499877929688,0],[234.72233581543,135.302688598633,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[249.499496459961,125.692352294922,0],[252.627807617188,124.059020996094,0],[302.399993896484,223.199996948242,0],[255.806503295898,122.526023864746,0],[259.032348632812,121.094909667969,0],[302.399993896484,223.199996948242,0],[252.627807617188,124.059020996094,0],[255.806503295898,122.526023864746,0],[262.302062988281,119.767127990723,0],[302.399993896484,223.199996948242,0],[259.032348632812,121.094909667969,0],[237.552429199219,133.194458007812,0],[240.448165893555,131.177322387695,0],[302.399993896484,223.199996948242,0],[243.406585693359,129.253295898438,0],[246.424728393555,127.424362182617,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[246.424728393555,127.424362182617,0],[249.499496459961,125.692352294922,0],[243.406585693359,129.253295898438,0],[302.399993896484,223.199996948242,0],[240.448165893555,131.177322387695,0],[237.552429199219,133.194458007812,0],[302.399993896484,223.199996948242,0],[234.72233581543,135.302688598633,0],[262.302062988281,119.767127990723,0],[265.612365722656,118.544021606445,0],[302.399993896484,223.199996948242,0],[331.608489990234,116.180992126465,0],[334.997802734375,117.164207458496,0],[302.399993896484,223.199996948242,0],[338.354095458984,118.254745483398,0],[341.674041748047,119.451484680176,0],[302.399993896484,223.199996948242,0],[344.954223632812,120.753219604492,0],[348.191345214844,122.158630371094,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[341.674041748047,119.451484680176,0],[344.954223632812,120.753219604492,0],[302.399993896484,223.199996948242,0],[348.191345214844,122.158630371094,0],[351.382110595703,123.666305541992,0],[357.611785888672,126.982200622559,0],[302.399993896484,223.199996948242,0],[354.523315429688,125.274703979492,0],[360.644348144531,128.787078857422,0],[363.617980957031,130.6875,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[357.611785888672,126.982200622559,0],[360.644348144531,128.787078857422,0],[351.382110595703,123.666305541992,0],[354.523315429688,125.274703979492,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[363.617980957031,130.6875,0],[366.529663085938,132.681549072266,0],[369.37646484375,134.767211914062,0],[372.155456542969,136.942352294922,0],[302.399993896484,223.199996948242,0],[374.863861083984,139.204803466797,0],[377.498931884766,141.55224609375,0],[302.399993896484,223.199996948242,0],[374.863861083984,139.204803466797,0],[302.399993896484,223.199996948242,0],[372.155456542969,136.942352294922,0],[302.399993896484,223.199996948242,0],[377.498931884766,141.55224609375,0],[380.058013916016,143.982330322266,0],[382.538482666016,146.492584228516,0],[384.937866210938,149.080459594727,0],[302.399993896484,223.199996948242,0],[389.483673095703,154.478546142578,0],[302.399993896484,223.199996948242,0],[387.253692626953,151.743347167969,0],[302.399993896484,223.199996948242,0],[384.937866210938,149.080459594727,0],[387.253692626953,151.743347167969,0],[382.538482666016,146.492584228516,0],[302.399993896484,223.199996948242,0],[380.058013916016,143.982330322266,0],[366.529663085938,132.681549072266,0],[369.37646484375,134.767211914062,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[389.483673095703,154.478546142578,0],[391.625518798828,157.283294677734,0],[395.63623046875,163.090026855469,0],[302.399993896484,223.199996948242,0],[393.677062988281,160.154754638672,0],[302.399993896484,223.199996948242,0],[397.501037597656,166.086120605469,0],[399.269622802734,169.140014648438,0],[302.399993896484,223.199996948242,0],[395.63623046875,163.090026855469,0],[397.501037597656,166.086120605469,0],[400.940155029297,172.248626708984,0],[302.399993896484,223.199996948242,0],[399.269622802734,169.140014648438,0],[403.98046875,178.617324829102,0],[302.399993896484,223.199996948242,0],[402.510955810547,175.408782958984,0],[406.609649658203,185.166458129883,0],[302.399993896484,223.199996948242,0],[405.34716796875,181.870986938477,0],[302.399993896484,223.199996948242,0],[403.98046875,178.617324829102,0],[405.34716796875,181.870986938477,0],[302.399993896484,223.199996948242,0],[400.940155029297,172.248626708984,0],[402.510955810547,175.408782958984,0],[407.766723632812,188.500427246094,0],[302.399993896484,223.199996948242,0],[406.609649658203,185.166458129883,0],[409.759857177734,195.270309448242,0],[302.399993896484,223.199996948242,0],[408.817138671875,191.869522094727,0],[411.318481445312,202.153228759766,0],[302.399993896484,223.199996948242,0],[410.593902587891,198.699371337891,0],[302.399993896484,223.199996948242,0],[409.759857177734,195.270309448242,0],[410.593902587891,198.699371337891,0],[302.399993896484,223.199996948242,0],[411.318481445312,202.153228759766,0],[411.932830810547,205.628372192383,0],[412.436340332031,209.121322631836,0],[412.828460693359,212.628494262695,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[412.828460693359,212.628494262695,0],[413.108856201172,216.146377563477,0],[413.277191162109,219.671401977539,0],[413.333343505859,223.199996948242,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[413.108856201172,216.146377563477,0],[413.277191162109,219.671401977539,0],[411.932830810547,205.628372192383,0],[412.436340332031,209.121322631836,0],[302.399993896484,223.199996948242,0],[302.399993896484,223.199996948242,0],[407.766723632812,188.500427246094,0],[408.817138671875,191.869522094727,0],[393.677062988281,160.154754638672,0],[302.399993896484,223.199996948242,0],[391.625518798828,157.283294677734,0],[334.997802734375,117.164207458496,0],[338.354095458984,118.254745483398,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[0.878431379795074,1,1,1]],&#34;centers&#34;:[[288.081970214844,150.653228759766,0],[292.723815917969,149.889633178711,0],[290.396820068359,150.234512329102,0],[295.060546875,149.618942260742,0],[285.781677246094,151.145370483398,0],[283.498138427734,151.710418701172,0],[281.233734130859,152.347839355469,0],[278.990753173828,153.056945800781,0],[297.404754638672,149.422714233398,0],[302.105926513672,149.25439453125,0],[306.808319091797,149.385314941406,0],[304.458190917969,149.282455444336,0],[309.153991699219,149.562896728516,0],[313.822509765625,150.141357421875,0],[318.444763183594,151.015472412109,0],[316.140594482422,150.541656494141,0],[311.492858886719,149.814987182617,0],[299.753997802734,149.301147460938,0],[320.732727050781,151.562362670898,0],[249.389450073242,171.644943237305,0],[252.774826049805,168.378631591797,0],[251.05615234375,169.98486328125,0],[254.543701171875,166.827896118164,0],[243.275192260742,178.789459228516,0],[247.776412963867,173.357208251953,0],[244.717742919922,176.931274414062,0],[246.218627929688,175.119918823242,0],[256.361022949219,165.334197998047,0],[268.17578125,157.650451660156,0],[272.412963867188,155.606979370117,0],[270.278137207031,156.595031738281,0],[274.578125,154.687347412109,0],[260.133544921875,162.52392578125,0],[264.077117919922,159.959228515625,0],[266.108093261719,158.772247314453,0],[262.084930419922,161.210205078125,0],[258.224914550781,163.899047851562,0],[276.771484375,153.837066650391,0],[323.002136230469,152.181732177734,0],[327.476043701172,153.63542175293,0],[331.848510742188,155.370620727539,0],[329.676086425781,154.468246459961,0],[333.991149902344,156.341659545898,0],[338.178375244141,158.485641479492,0],[342.220794677734,160.891525268555,0],[340.218719482422,159.656433105469,0],[336.101806640625,157.380340576172,0],[344.182556152344,162.189697265625,0],[347.977294921875,164.969848632812,0],[351.587615966797,167.985687255859,0],[349.806457519531,166.44905090332,0],[353.318969726562,169.578201293945,0],[356.625457763672,172.924362182617,0],[359.712463378906,176.473968505859,0],[358.197204589844,174.674606323242,0],[354.998840332031,171.224975585938,0],[346.10205078125,163.549591064453,0],[361.169738769531,178.320602416992,0],[363.904479980469,182.148284912109,0],[366.390228271484,186.142059326172,0],[365.179138183594,184.125396728516,0],[367.536590576172,188.196212768555,0],[369.630493164062,192.40869140625,0],[371.452270507812,196.745819091797,0],[370.575897216797,194.562774658203,0],[368.617034912109,190.28581237793,0],[372.2587890625,198.955627441406,0],[373.659027099609,203.446624755859,0],[374.770812988281,208.017547607422,0],[374.251281738281,205.723236083984,0],[375.217132568359,210.327194213867,0],[375.888275146484,214.983276367188,0],[376.112426757812,217.324951171875,0],[376.336853027344,222.023803710938,0],[376.262023925781,219.672592163086,0],[375.589721679688,212.64990234375,0],[372.99462890625,201.189987182617,0],[362.567504882812,180.212692260742,0],[325.250671386719,152.872985839844,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;76&#34;:{&#34;id&#34;:76,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1,-1]},&#34;vertices&#34;:[[212.653045654297,157.995025634766,0],[214.772521972656,155.173324584961,0],[216.980667114258,152.420471191406,0],[219.275253295898,149.739242553711,0],[221.65397644043,147.132369995117,0],[224.114410400391,144.602478027344,0],[226.654067993164,142.152114868164,0],[229.270385742188,139.783782958984,0],[231.960723876953,137.499877929688,0],[234.72233581543,135.302688598633,0],[237.552429199219,133.194458007812,0],[240.448165893555,131.177322387695,0],[243.406585693359,129.253295898438,0],[246.424728393555,127.424362182617,0],[249.499496459961,125.692352294922,0],[252.627807617188,124.059020996094,0],[255.806503295898,122.526023864746,0],[259.032348632812,121.094909667969,0],[262.302062988281,119.767127990723,0],[265.612365722656,118.544021606445,0],[268.959899902344,117.426826477051,0],[272.341278076172,116.416679382324,0],[275.753082275391,115.514595031738,0],[279.191833496094,114.721496582031,0],[282.654113769531,114.038177490234,0],[286.136322021484,113.46533203125,0],[289.635040283203,113.003540039062,0],[293.146636962891,112.653266906738,0],[296.667633056641,112.41487121582,0],[300.194396972656,112.288597106934,0],[303.723419189453,112.274559020996,0],[307.251098632812,112.372787475586,0],[310.773834228516,112.583168029785,0],[314.288146972656,112.905502319336,0],[317.790405273438,113.339454650879,0],[321.277069091797,113.884582519531,0],[324.744659423828,114.540344238281,0],[328.189605712891,115.30606842041,0],[331.608489990234,116.180992126465,0],[334.997802734375,117.164207458496,0],[338.354095458984,118.254745483398,0],[341.674041748047,119.451484680176,0],[344.954223632812,120.753219604492,0],[348.191345214844,122.158630371094,0],[351.382110595703,123.666305541992,0],[354.523315429688,125.274703979492,0],[357.611785888672,126.982200622559,0],[360.644348144531,128.787078857422,0],[363.617980957031,130.6875,0],[366.529663085938,132.681549072266,0],[369.37646484375,134.767211914062,0],[372.155456542969,136.942352294922,0],[374.863861083984,139.204803466797,0],[377.498931884766,141.55224609375,0],[380.058013916016,143.982330322266,0],[382.538482666016,146.492584228516,0],[384.937866210938,149.080459594727,0],[387.253692626953,151.743347167969,0],[389.483673095703,154.478546142578,0],[391.625518798828,157.283294677734,0],[393.677062988281,160.154754638672,0],[395.63623046875,163.090026855469,0],[397.501037597656,166.086120605469,0],[399.269622802734,169.140014648438,0],[400.940155029297,172.248626708984,0],[402.510955810547,175.408782958984,0],[403.98046875,178.617324829102,0],[405.34716796875,181.870986938477,0],[406.609649658203,185.166458129883,0],[407.766723632812,188.500427246094,0],[408.817138671875,191.869522094727,0],[409.759857177734,195.270309448242,0],[410.593902587891,198.699371337891,0],[411.318481445312,202.153228759766,0],[411.932830810547,205.628372192383,0],[412.436340332031,209.121322631836,0],[412.828460693359,212.628494262695,0],[413.108856201172,216.146377563477,0],[413.277191162109,219.671401977539,0],[413.333343505859,223.199996948242,0],[302.399993896484,223.199996948242,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[212.653045654297,157.995025634766,0],[214.772521972656,155.173324584961,0],[216.980667114258,152.420471191406,0],[219.275253295898,149.739242553711,0],[221.65397644043,147.132369995117,0],[224.114410400391,144.602478027344,0],[226.654067993164,142.152114868164,0],[229.270385742188,139.783782958984,0],[231.960723876953,137.499877929688,0],[234.72233581543,135.302688598633,0],[237.552429199219,133.194458007812,0],[240.448165893555,131.177322387695,0],[243.406585693359,129.253295898438,0],[246.424728393555,127.424362182617,0],[249.499496459961,125.692352294922,0],[252.627807617188,124.059020996094,0],[255.806503295898,122.526023864746,0],[259.032348632812,121.094909667969,0],[262.302062988281,119.767127990723,0],[265.612365722656,118.544021606445,0],[268.959899902344,117.426826477051,0],[272.341278076172,116.416679382324,0],[275.753082275391,115.514595031738,0],[279.191833496094,114.721496582031,0],[282.654113769531,114.038177490234,0],[286.136322021484,113.46533203125,0],[289.635040283203,113.003540039062,0],[293.146636962891,112.653266906738,0],[296.667633056641,112.41487121582,0],[300.194396972656,112.288597106934,0],[303.723419189453,112.274559020996,0],[307.251098632812,112.372787475586,0],[310.773834228516,112.583168029785,0],[314.288146972656,112.905502319336,0],[317.790405273438,113.339454650879,0],[321.277069091797,113.884582519531,0],[324.744659423828,114.540344238281,0],[328.189605712891,115.30606842041,0],[331.608489990234,116.180992126465,0],[334.997802734375,117.164207458496,0],[338.354095458984,118.254745483398,0],[341.674041748047,119.451484680176,0],[344.954223632812,120.753219604492,0],[348.191345214844,122.158630371094,0],[351.382110595703,123.666305541992,0],[354.523315429688,125.274703979492,0],[357.611785888672,126.982200622559,0],[360.644348144531,128.787078857422,0],[363.617980957031,130.6875,0],[366.529663085938,132.681549072266,0],[369.37646484375,134.767211914062,0],[372.155456542969,136.942352294922,0],[374.863861083984,139.204803466797,0],[377.498931884766,141.55224609375,0],[380.058013916016,143.982330322266,0],[382.538482666016,146.492584228516,0],[384.937866210938,149.080459594727,0],[387.253692626953,151.743347167969,0],[389.483673095703,154.478546142578,0],[391.625518798828,157.283294677734,0],[393.677062988281,160.154754638672,0],[395.63623046875,163.090026855469,0],[397.501037597656,166.086120605469,0],[399.269622802734,169.140014648438,0],[400.940155029297,172.248626708984,0],[402.510955810547,175.408782958984,0],[403.98046875,178.617324829102,0],[405.34716796875,181.870986938477,0],[406.609649658203,185.166458129883,0],[407.766723632812,188.500427246094,0],[408.817138671875,191.869522094727,0],[409.759857177734,195.270309448242,0],[410.593902587891,198.699371337891,0],[411.318481445312,202.153228759766,0],[411.932830810547,205.628372192383,0],[412.436340332031,209.121322631836,0],[412.828460693359,212.628494262695,0],[413.108856201172,216.146377563477,0],[413.277191162109,219.671401977539,0],[413.333343505859,223.199996948242,0],[302.399993896484,223.199996948242,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;77&#34;:{&#34;id&#34;:77,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.10000002384186,-1.10000002384186]},&#34;vertices&#34;:[[336.680297851562,117.696128845215,0],[338.394287109375,112.420936584473,0]],&#34;colors&#34;:[[0,0,0,1]],&#34;centers&#34;:[[336.680297851562,117.696128845215,0],[338.394287109375,112.420936584473,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:64},&#34;78&#34;:{&#34;id&#34;:78,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.20000004768372,-1.20000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAeCAQAAADZJrvsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDrvzYXbAAACfElEQVRIx+2XTUhUURTHf9P0RYUR9LUQoY2hVFAElW2CIJJwEYSE0WIIDMkMWjmBgS1cWbSJCiwo7VOKFhUiDQNmDSOUUVGWZBIx1mRRo9nUqKdFp9e89674XhuJ5jyY4Z77u+/+53/uu3ce5OJ33EQQaqdm8mlT/etzEnIS/hkJAbbTwiuG+Uoflyk30oU0EOMTGQZ5ymlK/44x7QvFPEQc1xNWOEYeJuOi4uT7ZgwSSviscDfNnCfOGIKQoiSLOqjMG67TxA36tN3LLF+MQcISEjr9aiu3nHsIQoLFmpnHkI4LWGXdo1L3+2CMEk6o7Xk2r2YTRxAatb0FQXjgKM0xBOGOd2a6YfHMJwRADSlbPk2YCFBJmAwwV4UFkCzqFAO85oW2vDAGF8oQhKRl3Z8Iqq0bACjUql6ggInCA2NyYZ1+nzT0jQKwihjwkja2AhVU8Jh2InQw4uC9MAYXmlyPkPM6pORCum35NO1UW8vVO+OS0DqphIYsF6t55Oj9TiMzbU5PzjgknEMQLuI9llFFKx+yprjml7FLOIogdPmQ8CsCrKGeAZ1gkz/GLmEXgjDKAsMtQpRSZO1ri9jIUgeRzyCCUO+VMR08UcaBIHtdPZs5y22esRaACEk6qXQwb+kE0G3NA2OSkNAq1bHSlp/DcQCecx9AP0MOt2boqB7PjKEQUEgKQfjIDitXzF2t4DbLzjSC0EGRReVxCUH4opN6YYwSoEyHCv1coZmYHi3CkSyqRnNjdHGVM7QxjCCMs9sXg/n/wnp6XPvBEPscRTvANxf1np2+mQleZYKU00IvKX6QJErYtbIBCqgjyjvSjNDPLaoc56tX5j+Pn4tBzrrxe26MAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU4KzEwOjAw6MnlMQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OCsxMDowMJmUXY0AAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[340.108306884766,102.96215057373,1],[361.774993896484,102.96215057373,1],[361.774993896484,112.96215057373,1],[340.108306884766,112.96215057373,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[350.941650390625,107.96215057373,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;59&#34;:{&#34;id&#34;:59,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0.32139378786087,0.342020124197006,0.88302218914032]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;56&#34;:{&#34;id&#34;:56,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;back&#34;:&#34;filled&#34;},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;58&#34;:{&#34;id&#34;:58,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;fog&#34;:false},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;60&#34;:{&#34;id&#34;:60,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;53&#34;:{&#34;id&#34;:53,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:1,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:53,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,706.014953613281],&#34;modelMatrix&#34;:[[0.866025388240814,-0.5,0,-151.179504394531],[0.353553384542465,0.61237245798111,0.70710676908493,-244.966613769531],[-0.353553384542465,-0.61237245798111,0.70710676908493,-461.755432128906],[0,0,0,1]],&#34;projMatrix&#34;:[[4.66506290435791,0,0,0],[0,6.22008419036865,0,0],[0,0,-3.86370325088501,-2545.10205078125],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[0.866025403784439,-0.5,0,0],[0.353553390593274,0.612372435695795,0.707106781186547,0],[-0.353553390593274,-0.612372435695794,0.707106781186548,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:0.600000023841858,&#34;bbox&#34;:[166.998092651367,440.78759765625,102.96215057373,345.035491943359,0,1],&#34;windowRect&#34;:[0,0,576,432],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:false,&#34;fontname&#34;:&#34;NULL&#34;,&#34;maxClipPlanes&#34;:2147483647,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[60,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,59],&#34;subscenes&#34;:[],&#34;flags&#34;:622},&#34;85&#34;:{&#34;id&#34;:85,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:85,&#34;sphereVerts&#34;:{&#34;reuse&#34;:&#34;rgl39345&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;div id=&#34;polygon-with-a-hole&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Polygon with a hole&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;polygon-with-a-hole-1&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Polygon with a hole&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# polygons_df - data.frame of polygon vertices with group/subgroups
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polygons_df &amp;lt;- df &amp;lt;- data.frame(
  x        = c(4, 8, 8, 4,   6, 7, 7, 6),
  y        = c(4, 4, 8, 8,   6, 6, 7, 7),
  group    = c(1, 1, 1, 1,   1, 1, 1, 1),
  subgroup = c(1, 1, 1, 1,   2, 2, 2, 2)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot(polygons_df) +
  geom_polygon(aes(x, y, group=group, subgroup=subgroup)) +
  geom_path(aes(x, y, group = interaction(group, subgroup)), colour = &amp;#39;red&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;{devoutrgl} polygon with a hole&amp;quot;)

rgldev(fov = 30, view_angle = -30, zoom = 0.8)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;rgl95271&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl95271&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#FFFFFF&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;lines&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:true,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:86,&#34;objects&#34;:{&#34;96&#34;:{&#34;id&#34;:96,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[82.6158981323242,0,0],[493.384094238281,0,0],[493.384094238281,432,0],[82.6158981323242,432,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[287.999969482422,216,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;97&#34;:{&#34;id&#34;:97,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[82.6158981323242,0,0.00999999977648258],[493.384094238281,0,0.00999999977648258],[493.384094238281,432,0.00999999977648258],[82.6158981323242,432,0.00999999977648258],[82.6158981323242,0,0.00999999977648258]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[82.6158981323242,0,0.00999999977648258],[493.384094238281,0,0.00999999977648258],[493.384094238281,432,0.00999999977648258],[82.6158981323242,432,0.00999999977648258],[82.6158981323242,0,0.00999999977648258]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;98&#34;:{&#34;id&#34;:98,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.200000002980232,-0.200000002980232]},&#34;vertices&#34;:[[110.983963012695,31.7325210571289,0],[487.904663085938,31.7325210571289,0],[487.904663085938,408.653198242188,0],[110.983963012695,408.653198242188,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[299.444305419922,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;99&#34;:{&#34;id&#34;:99,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.300000011920929,-0.300000011920929]},&#34;vertices&#34;:[[110.983963012695,91.6971740722656,0],[487.904663085938,91.6971740722656,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,91.6971740722656,0],[487.904663085938,91.6971740722656,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;100&#34;:{&#34;id&#34;:100,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464]},&#34;vertices&#34;:[[110.983963012695,177.360961914062,0],[487.904663085938,177.360961914062,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,177.360961914062,0],[487.904663085938,177.360961914062,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;101&#34;:{&#34;id&#34;:101,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.5,-0.5]},&#34;vertices&#34;:[[110.983963012695,263.024749755859,0],[487.904663085938,263.024749755859,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,263.024749755859,0],[487.904663085938,263.024749755859,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;102&#34;:{&#34;id&#34;:102,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.600000023841858,-0.600000023841858]},&#34;vertices&#34;:[[110.983963012695,348.688537597656,0],[487.904663085938,348.688537597656,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,348.688537597656,0],[487.904663085938,348.688537597656,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;103&#34;:{&#34;id&#34;:103,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071]},&#34;vertices&#34;:[[170.948623657227,31.7325210571289,0],[170.948623657227,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[170.948623657227,31.7325210571289,0],[170.948623657227,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;104&#34;:{&#34;id&#34;:104,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.800000011920929,-0.800000011920929]},&#34;vertices&#34;:[[256.612426757812,31.7325210571289,0],[256.612426757812,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[256.612426757812,31.7325210571289,0],[256.612426757812,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;105&#34;:{&#34;id&#34;:105,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.899999976158142,-0.899999976158142]},&#34;vertices&#34;:[[342.276214599609,31.7325210571289,0],[342.276214599609,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[342.276214599609,31.7325210571289,0],[342.276214599609,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;106&#34;:{&#34;id&#34;:106,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1,-1]},&#34;vertices&#34;:[[427.940002441406,31.7325210571289,0],[427.940002441406,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[427.940002441406,31.7325210571289,0],[427.940002441406,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;107&#34;:{&#34;id&#34;:107,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.10000002384186,-1.10000002384186]},&#34;vertices&#34;:[[110.983963012695,48.8652801513672,0],[487.904663085938,48.8652801513672,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,48.8652801513672,0],[487.904663085938,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;108&#34;:{&#34;id&#34;:108,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.20000004768372,-1.20000004768372]},&#34;vertices&#34;:[[110.983963012695,134.529067993164,0],[487.904663085938,134.529067993164,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,134.529067993164,0],[487.904663085938,134.529067993164,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;109&#34;:{&#34;id&#34;:109,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.29999995231628,-1.29999995231628]},&#34;vertices&#34;:[[110.983963012695,220.192855834961,0],[487.904663085938,220.192855834961,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,220.192855834961,0],[487.904663085938,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;110&#34;:{&#34;id&#34;:110,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.39999997615814,-1.39999997615814]},&#34;vertices&#34;:[[110.983963012695,305.856658935547,0],[487.904663085938,305.856658935547,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,305.856658935547,0],[487.904663085938,305.856658935547,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;111&#34;:{&#34;id&#34;:111,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.5,-1.5]},&#34;vertices&#34;:[[110.983963012695,391.520446777344,0],[487.904663085938,391.520446777344,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[110.983963012695,391.520446777344,0],[487.904663085938,391.520446777344,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;112&#34;:{&#34;id&#34;:112,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.60000002384186,-1.60000002384186]},&#34;vertices&#34;:[[128.116729736328,31.7325210571289,0],[128.116729736328,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[128.116729736328,31.7325210571289,0],[128.116729736328,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;113&#34;:{&#34;id&#34;:113,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.70000004768372,-1.70000004768372]},&#34;vertices&#34;:[[213.780517578125,31.7325210571289,0],[213.780517578125,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[213.780517578125,31.7325210571289,0],[213.780517578125,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;114&#34;:{&#34;id&#34;:114,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.79999995231628,-1.79999995231628]},&#34;vertices&#34;:[[299.444305419922,31.7325210571289,0],[299.444305419922,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[299.444305419922,31.7325210571289,0],[299.444305419922,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;115&#34;:{&#34;id&#34;:115,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.89999997615814,-1.89999997615814]},&#34;vertices&#34;:[[385.108093261719,31.7325210571289,0],[385.108093261719,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[385.108093261719,31.7325210571289,0],[385.108093261719,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;116&#34;:{&#34;id&#34;:116,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2,-2]},&#34;vertices&#34;:[[470.771881103516,31.7325210571289,0],[470.771881103516,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[470.771881103516,31.7325210571289,0],[470.771881103516,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;117&#34;:{&#34;id&#34;:117,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.09999990463257,-2.09999990463257]},&#34;vertices&#34;:[[128.116729736328,48.8652801513672,0],[299.444305419922,220.192855834961,0],[128.116729736328,391.520446777344,0],[299.444305419922,220.192855834961,0],[128.116729736328,48.8652801513672,0],[470.771881103516,48.8652801513672,0],[128.116729736328,391.520446777344,0],[299.444305419922,305.856658935547,0],[470.771881103516,391.520446777344,0],[299.444305419922,305.856658935547,0],[128.116729736328,391.520446777344,0],[299.444305419922,220.192855834961,0],[385.108093261719,220.192855834961,0],[470.771881103516,48.8652801513672,0],[470.771881103516,391.520446777344,0],[470.771881103516,48.8652801513672,0],[385.108093261719,220.192855834961,0],[299.444305419922,220.192855834961,0],[385.108093261719,305.856658935547,0],[470.771881103516,391.520446777344,0],[299.444305419922,305.856658935547,0],[470.771881103516,391.520446777344,0],[385.108093261719,305.856658935547,0],[385.108093261719,220.192855834961,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[185.225921630859,220.19287109375,0],[299.444305419922,105.974472045898,0],[299.444305419922,362.9658203125,0],[242.33512878418,305.856658935547,0],[442.21728515625,220.19287109375,0],[385.108123779297,163.08366394043,0],[385.108123779297,334.411254882812,0],[413.662689208984,305.856658935547,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;118&#34;:{&#34;id&#34;:118,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.20000004768372,-2.20000004768372]},&#34;vertices&#34;:[[128.116729736328,48.8652801513672,0],[470.771881103516,48.8652801513672,0],[470.771881103516,391.520446777344,0],[128.116729736328,391.520446777344,0]],&#34;colors&#34;:[[1,0,0,1]],&#34;centers&#34;:[[128.116729736328,48.8652801513672,0],[470.771881103516,48.8652801513672,0],[470.771881103516,391.520446777344,0],[128.116729736328,391.520446777344,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;119&#34;:{&#34;id&#34;:119,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.29999995231628,-2.29999995231628]},&#34;vertices&#34;:[[299.444305419922,220.192855834961,0],[385.108093261719,220.192855834961,0],[385.108093261719,305.856658935547,0],[299.444305419922,305.856658935547,0]],&#34;colors&#34;:[[1,0,0,1]],&#34;centers&#34;:[[299.444305419922,220.192855834961,0],[385.108093261719,220.192855834961,0],[385.108093261719,305.856658935547,0],[299.444305419922,305.856658935547,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;120&#34;:{&#34;id&#34;:120,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;alpha&#34;:0,&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.40000009536743,-2.40000009536743]},&#34;vertices&#34;:[[110.983963012695,31.7325210571289,0],[487.904663085938,31.7325210571289,0],[487.904663085938,408.653198242188,0],[110.983963012695,408.653198242188,0]],&#34;colors&#34;:[[1,1,1,0]],&#34;centers&#34;:[[299.444305419922,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:42},&#34;121&#34;:{&#34;id&#34;:121,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.40000009536743,-2.40000009536743]},&#34;vertices&#34;:[[110.983963012695,31.7325210571289,0.00999999977648258],[487.904663085938,31.7325210571289,0.00999999977648258],[487.904663085938,408.653198242188,0.00999999977648258],[110.983963012695,408.653198242188,0.00999999977648258],[110.983963012695,31.7325210571289,0.00999999977648258]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[110.983963012695,31.7325210571289,0.00999999977648258],[487.904663085938,31.7325210571289,0.00999999977648258],[487.904663085938,408.653198242188,0.00999999977648258],[110.983963012695,408.653198242188,0.00999999977648258],[110.983963012695,31.7325210571289,0.00999999977648258]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;122&#34;:{&#34;id&#34;:122,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.5,-2.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAXCAQAAACsCtdvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAAAzElEQVQoz7WRMQtBURiGH9ztlixWGfwFJvkH3yATmSijjTKZZDZcs5IySOosyl+4f8BmYriZ1FUMLMJ1z7nT9W7fe57evvO98FfJWB6y+cxJDVKhH3RCkGSY/7rhpCk5/EhImtRxWUZAksfhSpO7EZIUc9L01P53g++kAWW2ygn/9w1JiSFnWrq7vSCxWWDRUacIiAkFZmqtbyAJIFXaHOhiUAJAVtQM70XlarszJWWxA+6IBjs6wFHdwAJQHl7g8hfAVwdtLSbFB8WnJ/36KxXzPH3AAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwTr7uhQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowMD/jVjkAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[101.158317565918,45.7092247009277,1],[107.158317565918,45.7092247009277,1],[107.158317565918,53.3758926391602,1],[101.158317565918,53.3758926391602,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[104.158317565918,49.5425567626953,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;123&#34;:{&#34;id&#34;:123,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.59999990463257,-2.59999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABIElEQVQoz63RvSvFYRwF8M/1FguxYOAOimRwF5EymAw8FuoWg//AxOg/YLQZjJTtiVHJQDfKIoXB5D2syMvguvd3b5ic5fvUOc853xf+A6nvRzjSW8YtxTmoyAuqdf/mUpWvPWp8GPac4C5LJRmcxZ2fXPJBenH4c1BFwuXgz4nCg0ZT+oxr82TXYtwvkYS0C7yoKXz9MB+XkkEZcGNGuxYTTqQshsmky7g5dUbjbT62QU6nCx3xPbHdUoSsNfTHXHGicmyDruTQ5XgCtYXthqy047iZkDSDq+IBZg3ak5SM4M1+MShiIAwXmm2ygI14X5Qsu5SyHrKhljBkR9qj+dIDZGxpxZsXdbgzFnNfXOVXOb3uWvWqUT3OrJiO5/4VnyYeRg2oBKdDAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwTr7uhQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowMD/jVjkAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[101.158317565918,131.373016357422,1],[106.824981689453,131.373016357422,1],[106.824981689453,139.039688110352,1],[101.158317565918,139.039688110352,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[103.991653442383,135.206344604492,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;124&#34;:{&#34;id&#34;:124,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.70000004768372,-2.70000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABZ0lEQVQoz63SPWgUQRQA4O9yRyBBz3AEtbGxyAYUFIIIioUS0GaQNIIg2ohW2ogIViqoCBZikUiwFg4Ri0HQLv6ChYloQNhKLBQNBIlZEeGIxV6yc9hmmnnM+4aZN29Yj1GrwrDTBYdsVZg1FR/9R8JpUxpY0gTT8WyZ6euCg6Y13LMlbrLZJM6E48lpoRY+hZVwN1l5ElbC8zJugP1G/XA52XXJQ19TchSP43Il4rz51bgkuzAb+p1zwojfXroe362S8rqjKLxx226Dhk14G072kiHcMmbSDsMO+6DuftiTvEvo6MPVeKVbT9Oc7Z7FI8m7YMGNtcsuuYnxsLEiy3gd/yZFv0DdSEW+41dP7xbBQEU+YlsPaYFvFZnBvjCUkANY8LkibX/0u7bWoQEX0Y4dqENeZB3j9matbC4vQqZtzKJjeZH8l1Bzx/ludRvw00ScKXP1csrlT7NXmloGffHAqfjeuo5/JFxeTjGH2bQAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[101.158317565918,217.036804199219,1],[106.824981689453,217.036804199219,1],[106.824981689453,224.703475952148,1],[101.158317565918,224.703475952148,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[103.991653442383,220.870147705078,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;125&#34;:{&#34;id&#34;:125,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.79999995231628,-2.79999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAAA10lEQVQoz7XQsSvEYRgH8A9Jd5TlDLfdv8CiZJKF4S3Ff6CuZL6Uv4JMFjcfg/QuJqWUTUZZ6LK4TRZlYMLv/d393olnfJ5P3/d5Xv6ixiBcWxo5XYsXjGcDPmACtM0ko7oTs85d/jxUrnCk7clcfK0gYd2ZT8vxqrBuAmrutRzHre/O8LodLW/2fhslEhp2cRhfKolt094dFFsJCZN20I2DSmJDE/tpcEo2cRsfKkmoW0WvfGIxZcUUTnNkEf34mCMLuBn6yoTM4y5DQk0D/VxKEzz7p/oCJjkoomD5hekAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[101.158317565918,302.700592041016,1],[106.824981689453,302.700592041016,1],[106.824981689453,310.367279052734,1],[101.158317565918,310.367279052734,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[103.991653442383,306.533935546875,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;126&#34;:{&#34;id&#34;:126,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.90000009536743,-2.90000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABZ0lEQVQoz63SP0iVURjH8Y96/8j1ch26gVBKCCHZkEVUIkENbR1pLIOaCmppaGkIZyFqbQxaWiqS42ISQQQ5qTg0SCllGS0FkUVdlIb7vr73dSromc7h+fJ7nt/vHP5HtaWHUHTFeYOKVk27Fd9tQ0KXaSPY8EsF35yJz5u99gS9bcS6iyqqjlhU8zDsaFEJFV+UXY13E81eywrpvanSr4zZdHpctYy+1kFfwfDW6jvtwZsWJH60gIlwNhQIgyaVvPUg72jIjDoafqrZ9Ni1uJZzFBcc9BpFNdBQSscmSDhpzi6X1VWcsuicl6G/1fQ+8zocj4mnUDVrvxhHM5Ubyp7EzPR3N3E69GTIUbzKvd0LtNmbIXV05JAG6MyQDziWQw6ThtdEpjAaDm2l224cc3ElQ+74pOBpGAtlwoBJJ2y4nk/3gCm7semHKn67FO83e8mSS58H7lnXrVvJe49ciM/+4s/+Q/0BhxdZrZ0hg0cAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[101.158317565918,388.364379882812,1],[106.824981689453,388.364379882812,1],[106.824981689453,396.031066894531,1],[101.158317565918,396.031066894531,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[103.991653442383,392.197692871094,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;127&#34;:{&#34;id&#34;:127,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3,-3]},&#34;vertices&#34;:[[108.244239807129,48.8652801513672,0],[110.983963012695,48.8652801513672,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[108.244239807129,48.8652801513672,0],[110.983963012695,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;128&#34;:{&#34;id&#34;:128,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.09999990463257,-3.09999990463257]},&#34;vertices&#34;:[[108.244239807129,134.529067993164,0],[110.983963012695,134.529067993164,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[108.244239807129,134.529067993164,0],[110.983963012695,134.529067993164,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;129&#34;:{&#34;id&#34;:129,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.20000004768372,-3.20000004768372]},&#34;vertices&#34;:[[108.244239807129,220.192855834961,0],[110.983963012695,220.192855834961,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[108.244239807129,220.192855834961,0],[110.983963012695,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;130&#34;:{&#34;id&#34;:130,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.29999995231628,-3.29999995231628]},&#34;vertices&#34;:[[108.244239807129,305.856658935547,0],[110.983963012695,305.856658935547,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[108.244239807129,305.856658935547,0],[110.983963012695,305.856658935547,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;131&#34;:{&#34;id&#34;:131,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.40000009536743,-3.40000009536743]},&#34;vertices&#34;:[[108.244239807129,391.520446777344,0],[110.983963012695,391.520446777344,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[108.244239807129,391.520446777344,0],[110.983963012695,391.520446777344,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;132&#34;:{&#34;id&#34;:132,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.5,-3.5]},&#34;vertices&#34;:[[128.116729736328,28.9927940368652,0],[128.116729736328,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[128.116729736328,28.9927940368652,0],[128.116729736328,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;133&#34;:{&#34;id&#34;:133,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.59999990463257,-3.59999990463257]},&#34;vertices&#34;:[[213.780517578125,28.9927940368652,0],[213.780517578125,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[213.780517578125,28.9927940368652,0],[213.780517578125,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;134&#34;:{&#34;id&#34;:134,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.70000004768372,-3.70000004768372]},&#34;vertices&#34;:[[299.444305419922,28.9927940368652,0],[299.444305419922,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[299.444305419922,28.9927940368652,0],[299.444305419922,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;135&#34;:{&#34;id&#34;:135,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.79999995231628,-3.79999995231628]},&#34;vertices&#34;:[[385.108093261719,28.9927940368652,0],[385.108093261719,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[385.108093261719,28.9927940368652,0],[385.108093261719,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;136&#34;:{&#34;id&#34;:136,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.90000009536743,-3.90000009536743]},&#34;vertices&#34;:[[470.771881103516,28.9927940368652,0],[470.771881103516,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[470.771881103516,28.9927940368652,0],[470.771881103516,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;137&#34;:{&#34;id&#34;:137,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4,-4],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAXCAQAAACsCtdvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAAAzElEQVQoz7WRMQtBURiGH9ztlixWGfwFJvkH3yATmSijjTKZZDZcs5IySOosyl+4f8BmYriZ1FUMLMJ1z7nT9W7fe57evvO98FfJWB6y+cxJDVKhH3RCkGSY/7rhpCk5/EhImtRxWUZAksfhSpO7EZIUc9L01P53g++kAWW2ygn/9w1JiSFnWrq7vSCxWWDRUacIiAkFZmqtbyAJIFXaHOhiUAJAVtQM70XlarszJWWxA+6IBjs6wFHdwAJQHl7g8hfAVwdtLSbFB8WnJ/36KxXzPH3AAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwTr7uhQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowMD/jVjkAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[125.669654846191,20.4889049530029,1],[131.669647216797,20.4889049530029,1],[131.669647216797,28.1555709838867,1],[125.669654846191,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[128.669647216797,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;138&#34;:{&#34;id&#34;:138,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.09999990463257,-4.09999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABIElEQVQoz63RvSvFYRwF8M/1FguxYOAOimRwF5EymAw8FuoWg//AxOg/YLQZjJTtiVHJQDfKIoXB5D2syMvguvd3b5ic5fvUOc853xf+A6nvRzjSW8YtxTmoyAuqdf/mUpWvPWp8GPac4C5LJRmcxZ2fXPJBenH4c1BFwuXgz4nCg0ZT+oxr82TXYtwvkYS0C7yoKXz9MB+XkkEZcGNGuxYTTqQshsmky7g5dUbjbT62QU6nCx3xPbHdUoSsNfTHXHGicmyDruTQ5XgCtYXthqy047iZkDSDq+IBZg3ak5SM4M1+MShiIAwXmm2ygI14X5Qsu5SyHrKhljBkR9qj+dIDZGxpxZsXdbgzFnNfXOVXOb3uWvWqUT3OrJiO5/4VnyYeRg2oBKdDAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwTr7uhQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowMD/jVjkAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[211.333450317383,20.4889049530029,1],[217.000106811523,20.4889049530029,1],[217.000106811523,28.1555709838867,1],[211.333450317383,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[214.166778564453,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;139&#34;:{&#34;id&#34;:139,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.19999980926514,-4.19999980926514],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABZ0lEQVQoz63SPWgUQRQA4O9yRyBBz3AEtbGxyAYUFIIIioUS0GaQNIIg2ohW2ogIViqoCBZikUiwFg4Ri0HQLv6ChYloQNhKLBQNBIlZEeGIxV6yc9hmmnnM+4aZN29Yj1GrwrDTBYdsVZg1FR/9R8JpUxpY0gTT8WyZ6euCg6Y13LMlbrLZJM6E48lpoRY+hZVwN1l5ElbC8zJugP1G/XA52XXJQ19TchSP43Il4rz51bgkuzAb+p1zwojfXroe362S8rqjKLxx226Dhk14G072kiHcMmbSDsMO+6DuftiTvEvo6MPVeKVbT9Oc7Z7FI8m7YMGNtcsuuYnxsLEiy3gd/yZFv0DdSEW+41dP7xbBQEU+YlsPaYFvFZnBvjCUkANY8LkibX/0u7bWoQEX0Y4dqENeZB3j9matbC4vQqZtzKJjeZH8l1Bzx/ludRvw00ScKXP1csrlT7NXmloGffHAqfjeuo5/JFxeTjGH2bQAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[296.997222900391,20.4889049530029,1],[302.663909912109,20.4889049530029,1],[302.663909912109,28.1555709838867,1],[296.997222900391,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[299.83056640625,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;140&#34;:{&#34;id&#34;:140,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.30000019073486,-4.30000019073486],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAAA10lEQVQoz7XQsSvEYRgH8A9Jd5TlDLfdv8CiZJKF4S3Ff6CuZL6Uv4JMFjcfg/QuJqWUTUZZ6LK4TRZlYMLv/d393olnfJ5P3/d5Xv6ixiBcWxo5XYsXjGcDPmACtM0ko7oTs85d/jxUrnCk7clcfK0gYd2ZT8vxqrBuAmrutRzHre/O8LodLW/2fhslEhp2cRhfKolt094dFFsJCZN20I2DSmJDE/tpcEo2cRsfKkmoW0WvfGIxZcUUTnNkEf34mCMLuBn6yoTM4y5DQk0D/VxKEzz7p/oCJjkoomD5hekAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[382.661041259766,20.4889049530029,1],[388.327697753906,20.4889049530029,1],[388.327697753906,28.1555709838867,1],[382.661041259766,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[385.494354248047,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;141&#34;:{&#34;id&#34;:141,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.40000009536743,-4.40000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABZ0lEQVQoz63SP0iVURjH8Y96/8j1ch26gVBKCCHZkEVUIkENbR1pLIOaCmppaGkIZyFqbQxaWiqS42ISQQQ5qTg0SCllGS0FkUVdlIb7vr73dSromc7h+fJ7nt/vHP5HtaWHUHTFeYOKVk27Fd9tQ0KXaSPY8EsF35yJz5u99gS9bcS6iyqqjlhU8zDsaFEJFV+UXY13E81eywrpvanSr4zZdHpctYy+1kFfwfDW6jvtwZsWJH60gIlwNhQIgyaVvPUg72jIjDoafqrZ9Ni1uJZzFBcc9BpFNdBQSscmSDhpzi6X1VWcsuicl6G/1fQ+8zocj4mnUDVrvxhHM5Ubyp7EzPR3N3E69GTIUbzKvd0LtNmbIXV05JAG6MyQDziWQw6ThtdEpjAaDm2l224cc3ElQ+74pOBpGAtlwoBJJ2y4nk/3gCm7semHKn67FO83e8mSS58H7lnXrVvJe49ciM/+4s/+Q/0BhxdZrZ0hg0cAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[468.324829101562,20.4889049530029,1],[473.991485595703,20.4889049530029,1],[473.991485595703,28.1555709838867,1],[468.324829101562,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[471.158142089844,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;142&#34;:{&#34;id&#34;:142,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.5,-4.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAWCAQAAACFih+zAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABEUlEQVQoz7XSvUqcYRDF8Z8pxML4iU1ARATxIhTERBCs01nYpBGxs7XyAiwUEQQLO0GbQBqJJjdhI/iBitgEYQVF4T0WeRF3dXchkOnm8GfOzHke/l91uxKxXaX2uRGxWA1Pi4gvr7RdEb98qJ28JeJYW9nPiLg18HaJThcilsEnf0TMvL/xlIhHI/ghYqf+eZsi9s2KuNRTH+1wLuJeFCYbxzZZJhErzTPeE/Gktxk4oFJOXW0MtvgpohCF8UbonIgj30ScaK8HDqqIwigORKzVMz8UsQGGPYjCxHvovIhrXWW/JOL07RJD7kR8fVFaHYlYrzX/LeJ7lTpWJvH5tbggoqK/xuvvnzjzsfnL/Ws9A0+/cexLNIm3AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwTr7uhQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowMD/jVjkAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[296.694305419922,7.91255760192871,1],[303.694305419922,7.91255760192871,1],[303.694305419922,15.2458906173706,1],[296.694305419922,15.2458906173706,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[300.194305419922,11.5792245864868,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;143&#34;:{&#34;id&#34;:143,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.59999990463257,-4.59999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAdCAQAAADvTe9wAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAABQElEQVQ4y7XQP0vVYRjG8Q/HU0lIOCQJtraERgSCW7REOLkIppCvoZfQCxBBkOZQEheNoLGhsaYoR8FF1PAQaEpCnK4Gj8fz59f5LXUtz3Pd9/e5/zz8P02K+FqQ2RY/3bgM9DkQMdoBTohYPzcVULcGZjrQWbDaHnwgYrstdt6r5krnVFsixlsij0UsX9hKM7ECnragc0Xt4ba62G0+7nfUNVJT70U8bLhpES+K0XkRLxtuU8SdYnTAqThUxaAz8bE1XWm5n3iDmx5hyrXilS70RMQSNsQvQ39H++yLHVcdi3d6akHEc5G2Py7QfRFH4ofrSvRFRLzqTFS60JXGuVpWkxERe91FuqsOg9d+l1ddFDFWDg6oiU+9kH5VDHkr4lkvdNyZb+oiPqv2Qm81fjO+u1c25QcnajbcLV/oX+oP1Stt8WLcAp4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDBOvu6FAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUyOjU5KzEwOjAwP+NWOQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[95.9854888916016,217.442855834961,1],[95.9854888916016,224.442855834961,1],[86.3188171386719,224.442855834961,1],[86.3188171386719,217.442855834961,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[91.1521530151367,220.942855834961,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;144&#34;:{&#34;id&#34;:144,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-4.69999980926514,-4.69999980926514],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAh0AAAApCAQAAAA7HVP+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNDuYyrVNAAARv0lEQVR42u2deZwV1ZXHvw3N2tCCouwyighBQBlwwoAICIr6AbfgAu6fmQkZITEucRjUURPjMpmI4jJJFBNAEzTRCaTBETAgIhBlExgwQJIWwtI0e+9N03f+uKfq1XLfq6r3nv1iU7/3+Yh16tStc06de+695y4NMWLEiBEjRowYMRoCzXMtQIy/OcQ+kRauYQkHOYGiWwDnMygUxbkWOAM051Fe/BLKfRyF4qBcdUNRx0GWMj7XCnskO7XxLRQKRb6L6veJqcKXS3xZMmTgD008108wnzGc4TFn48QoNvN9WjXIu5pyBqNZwPdzrXSMlGhIn/iKwx06BvJorgVqQPyI8xv8nY/w9VyrHSMFcuETX1G4Q8fd5AHHuJMeFLIn18I1EuyhkG7cTDmQx225FidGjGzAHTr+AYCZzGEXZTke3TUeKMrYw9s8D8DgXIsTQ/AT8sgjj7pcC/LVhDt0dAdgfa6FaqRYC0DHXIsRI0Y24A4drQE4lmuhGinKAWibazFixMgG3KGjGQAnjZxjeZO/UM0hPuVBTktZ6mlMYRHFVHGcHcxhguc9N8hU01jj02+hUOz0UDsxnQ/YSw1H+Zyfcz15vieTTzXpieS/ytV1KBSDAPgnkaUdANNQKH4B9OBNSjnOFmbSx1HSGOayk0qOs5ln6Ql0kBI6BNhad4xbhvouejLut0AeE1jILmo4zMdM58ykz4SxkBsDRfLHjXcfQKE46pE4iv5hJNKazgOgPzPYzBEq2MkvuCKEnZahUPzBR/8EhaJCPDqBWSgURYB3cja5TzhxAT9mC8coYxtzGB3qWyZwCU+xki8oo4b9bOTlUDqmK0N0f3AiqA57UIVCcYmP3oUPxJjWbzfDk67rmMxBD7dis2tmoTmH7CrqRRsqUCgec9Ca8RTVvjI/Y4jn2Wihw/1rByRCR1f2OO5dLs+dyXuep6q411B1zHIMlyfCwAod7SjyvPEodxr407XQJhSK7UYZNqBQvOqghNU/ikRW6Mjnh5z0cC+iMMBOOrzVeSp5O+qkhGEefv1VJwPm0GHyCWtNRROe4YSH452ARjSBgaw0vEHxMV1D+0N4GTKtMcF12AMtlLf4Huy2H6+USq8oZ4khdOTxks1bx34OO5zsBgffK1INWvhkuE34e9qUVnxkl1LPQSrtq2puCWUIb+gYQhFFHEWh2EURRRRRACRCx2KHyQ6Jc3Vkh+PNCdPOCBk6hopVwmCqVJ1lovUWPna88SEPd/oWekD4LvZJ0FfuDLcp4fWPIpEVOn5qrFjLA1rKPsJ3vYuaCAMPu+gXClVXVnfoSO4TVrV90yjh+6G+5wiO20+Us89xpdgeoicaTYbMakzYOuxAE2EY6KI25Q9C/0CCyllMdwhT7OL+N9sck2RU35nvyQep5EKbb4jxkwMsQqFY6VBkgf2mO6QV6s/PpIWq5R8DDKHhDh0aa1EoXnPRdOjYi0Kxh1+ziCO8LnIss9uJEeQBp3O/ywWCQscgl6uGcZV6FIoF/B0A+dwun7Gey1yfOn0LdZL2eYZPgqdRKP5sV90o+keRSGt6BIViDTfRmTb0Z4bdA/F7iBs7UShedtFetGVaYvi66+TKtJrU5BNTHTpu4g7OpjnnMl366IqbA79mgTS+1TxMD9vyUymVEr4d0h/CyZBpjQlbhx1oj7e9B7hbqLNdY50httMUO6h9pd+ylDauMnrzVxRK5hg0tqNQvOWRoYOUMNmmTJD3rPR0y24Uzj87Pn22Qoem67agDWcDMEno82jq4O/PgdCho6fwnRHoKE5XmeVqdy8Su29yUDOz0EIJlu6RbB5foFA8YVOi6B9FooSmL7hksHqfXg/x4gUUij+6aFvtsOvOdnyIIpHZiR465rh2t1wt1P8J/JoPCqe3ze4lVX9ZYAlRZMjMH6LUYRsDUChOSjfNwgZ5nXdxrmX4YgftdRSKEkN6yVJxjE15VD6tW8B/lejc3qZsEeX8k5qPSZl3pDCEhaihY5svKbQehWKnzEIlcG3o0NFS4r4xbnsw1ZbDO6SbIncS6bHMLHSTrzyAEUI9Ly39o0hkabrBZ/G1Pv8y4XJ5vrtN6YxCsZFiFIqhNr1QKsUguY4aOrb5tsV9jELxReDXXIVCscJw5x0Uil2BJUSRITN/CF2HnZ9LO896Khy0nlwEwCu+9N5rHPBQWjARgJ9w1PfaRaJcIu7ORQGtucbFNwmAIo7IdS8uAOAlSnxl/kjeMynQ8NHxc+pd131kGPcclR7O+WwIWWY1WwAc4TMYz1LjocwSrW/MkoXmG3n0mtfV9jxXFP3Tk+hVj8XhI4DAeasPZdI7YVXtx8tZA8BIm34F+cDetNctPUeth7IcgC6BTz7JvbzAs4Y7OkHdJrCE8DJk5g8R6nAidHTmPgBPB3G4/ZgXdfzOQxksXXxz92uVqzwolnyGM23TXTLic22KNab/taHESplkG/YlbNZb5bkeJf/+1sD7m9Cl6inI+0Pl1AHqecdHqxb7XpolC9XIF7/B0b9pwQQA5qSlf3oSrfLx7gWCJ7NrWQr4Q8cyX+i4CoDfke4q6WQS5huS/W4sYibfZaHhTgspIXsyZOYPEeqwDh1D+S6f0B3Yyksu5q8BUOsZS2ps9Fxb6dXZ7DT8rgbgXAe/dsyxjsHJRPKAQ45A1VtU3mZURY+72oSI+1Gx1XM9AIBS+VBurAsszcLzbAa68An3OTrSybGdMgN1EwC95PNnbqHZALSTLwQwjnYkgkpU/dOTyN/trwZwZVbM0NUhMeC6DKhnhTj6UDvbcSWAr8ELD/+wwuoRNotUTnN6cRUP8kt2SXPdJPSzwTJk5g8R6rB2vwWSulvMrfLBLHQC4IhxmZjXjayu5dkpVG9NS/sNb/MiLWnODcwSiu5IzeOEza/lKvF1ZjX221zBo8UoUL7umj675ICRez9hUcVo3uAKuvAchwK74iTZgKhHpvm0pzQrFlrNds4HJtnJNj1cSQwbo+mfnkTHfZxheweLUOTRkf5sBnpxNrCRI6zjOIUUMJjVwIV0ASr5fchS/ahI+0mNv+dGBtObrhFCRXQZMvOHCHXYqcQirjOk9oAky5i8Hzvc4piWjufnA8joCvpIAnGug7swpcEsemuyi0qf4VunsEMUlyplnLSSYVBmpFqht0XWLKT7f+NkKq69tC7O7xBF//QkOkm62CfZCz1ksYYrcFKyJSMBa7iyNOSSPBPq034SzmMJ65jGGLrbdU6xzrAONlMZMvOHCHXYGTquZq2sIEhAu2mBsQDvCK9KDNJSdiSaf0cdT2jnHCm54FsB2O4yZ3mK9yf2gwS7Q6bZkFRyFEQopzPrGRea23zkjKV1RdYspFPWLSUBdjPNgYOu/FYU/bP1zcJDZxG8ocP670ggkenIBQawxs7FVPMZ8/gPxnMWgyVPk01kZv0IdViHjvO4kk1AX/7Xk5baB0B742judM/1IQDy7EUvwXifEqCpJOV0wnSui+MwAGcl6eJZI7ZSF9XEGz6HbYbujZl3vZ4ZupRmLKYfsIkrHdOeyWEe0uhBZIUMJ9KxkBe7pJJ9A0C+hnPYGE3/bEgUDbofdynNyGMkif6GHpwMI59ChgLKmKr8stGEX8kw4i2G0paLmMgPKOIgBCZYoyMz60eow/oFR3mfUfwF6M03Xfd1ujCffoZnB3iurVTqJZhwusFMdfwKgOuBwZwHKN4wvL/AtQEtAT1DX23nBHSn19RWpxq7hcFG0cF0XmuYdRoad9EPKGYU7xsmv/zoa0wS6lTW/6VloWTQqdIxtKZQ5m7muO5H0T87EkXBWkqANgyhLx2A9TKY/ozDQAEXy8TsWmkKGxZj6QvAz7iF1Z6NCJ0BIm1LC0Jm1o9QhxOx6bDMrbiX1VqTNKblwFd6rlfKSMw0a5zHKqrYI6EiAd3HuJTTuEnKKHbd/0j+nWAos7WMydfYI0Dd3Wrp6641NezRCJ+GA+zlPKbBRvjDirVlZkrLEIxWrgXnGqczAoAP0rJQMrxDOdCKyxlLM+BzPk1b/+xIFAWK9wC4XCYOLa+t50MARslwZUGIkrIPa0/YjKT30k+b+pGZ9SPUYafQywEY5MoL7BanmexbPn2VrydylMUAjDYseppIb/Lowm4PfT1bgGZcJcFpjuf+VjYDMMXQeb9fkjqJtQ/WIhjvRuS7jV3/ep8FkuMzaXe/41vN93V7hUUQ8uUUtuUh+QG+56M8KBK8mZaFkqGCdwG4VgLBXM/9KPpnR6Jo0EOWMSJLYlWC/r9RoSdmo/hEWFipR3/S+zbZ9BFtcjc1MrN+OnUYOFMWmro7pWOF6s6CnCsr2t0LhUcKrYT+rjL6yH7bakOH9yFZGa935vkzvHdImcs8+Yrx1KJQ7HccnmPtElnn6ncMl81V3oXoejuXe9ehXohebjCqtafiVVf3sqtjN2nQQvSzhS9MbiSxZ+HfXfRxspja2X5GsVDypfqXoVAcoBRFvWGAF0X/KBIl/zMBUf6AQFtqUdRxAMUJx1svkM0VpuXepoXoJp9ILsc/y53UmTRrd/J3PPRhHLNtF5TGjyJDZv6QTh2mhTw00EO3NvquZzRNgFbcRYmtdLGL97+FepxpklQr5B572+40g+pdHKc0vG24n9gHuJ0bJXz15HnZ8VnPtS7uT+3gMY4OtOViXqEWay+sO3S8JbxPMIbrpOTkoQN75+gS6WYWcKeU693WZq6g/YQvTBvj3Ck5h14AdOYpCRzHXEvrolgoeeiwNrwpVJK1D+H1jyJRdkIHLLXlcK+43G/TX/Y8YQodJp/INHT0Eg+v4tt2n60n/+k6d6M9qRFFhkz9IXodBlHRu86xgBW2imXspgaFok62Nhe7eFsw3+atp4Td9qEritlJ0kFLbA7ztGU7xyEptey2TwxR1PEtD+8I30EoOmRcYQgd01w8gxw0c+jo5Ghhy9knb6q3pUscS5Nq032U8zqUbGVSlLJP9oIqquyjh6JbKNWf7HnSfuquDPWPIlG2Qsd99ht+6KLPs+ne3JwpdJh8ItPQATPtEo+zkVXssr+l1dQNCCghmgyZ+UM6dViCwggfvSWveE5wKmOiHKhS7OFtwiOU+SpvJQ8lzSPfLjwHknbbmjNDZHP+thqzDNfapyBYv9WcIy2+O3QU8icH160O1ylPIkc3R5izXOF27pH/T2SfzRV0iFT8MLBcpaPj0Bb92+TrFUaxUKrQ0Uueqkh6fmpY/aNIlK3Q0ct+h3uUPtkOdt4ZPlPoMPlE5qGjKa/6LKE4yhTaSr2aElBCVBky84fodVgO8BlpvNefl9hKFWVs5b84B5KEDoAO3MtCiqmgmn0s5iHOSmGWAhFzZkrj9eBhPmQPNVTyR2YzPmkyqx0PsIISaviCIm4mH4yhAzrwPDuooIo/cTsQFDoArmYuOyinjM08TVes9s65gN/8QYYFlp1AwlWacBtLKaGWPbyb8oTIMBZK/YcCN6BQdgI2ff2jSJSt0GGdAFPjWSlphZR3ffzmPxzp94nMQwfAUGaxjTLqOMLn/Iapsq1dD7SCdvOmI0Nm/hCtDkva5jJiRMHjSUOoG5egUCHPm8/F3zltJSE86lG7YfWP0ajgjkP6LIZsThU1FuTzDS5M0rro3cXbA8vQdq0N5MsVrqENsNu4ODob+sdoVHCHDt0iBp1CfSqinrfZSJnj4EMLHSVjvSawDL1w/3ggX67wLwC8blwulA39YzRi/B6F4se5FuNvEltRKDZ49vg0kz92UC9tbyroQw7DnaDd8AOWW9D5+GTHEGWuf4xGjCclkzqRTkl2bZ66mC6VeQ3jxTYtGGNPW7+W8tlWdOFOySQ8FuZlDRg6nuEepvJLmS5Mrkcm+sdo9Dhf1pvpX7fMC2xEaCErXpXkpPc6VpCsSBlouzmeq+GcUG9ruNCxxSHdgRTHD6Wvf4xTAlPtxSpx6PCikDcMs/MneC7g/Exn6Aj+ixsaDRc6FjrWaIxIyZmu/jFOEYzgPUqpi0OHEf14mpUcoIYa9rGMR0KcbNANxQlKeS/CWegNFzq+yQ6q2c0cOdUy+/rHiBEjRowYMWLEiJE2/h+Jl8Kzj76iZAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1Mjo1OSsxMDowME6+7oUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTI6NTkrMTA6MDA/41Y5AAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[110.983963012695,417.052398681641,1],[291.317291259766,417.052398681641,1],[291.317291259766,430.719055175781,1],[110.983963012695,430.719055175781,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[201.150619506836,423.8857421875,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;92&#34;:{&#34;id&#34;:92,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0.32139378786087,0.342020124197006,0.88302218914032]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;89&#34;:{&#34;id&#34;:89,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;back&#34;:&#34;filled&#34;},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;91&#34;:{&#34;id&#34;:91,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;fog&#34;:false},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;93&#34;:{&#34;id&#34;:93,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;86&#34;:{&#34;id&#34;:86,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:1,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:86,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,1151.60961914062],&#34;modelMatrix&#34;:[[0.866025388240814,0,0.5,-249.665313720703],[0,1,0,-216],[-0.5,0,0.866025388240814,-1008.04260253906],[0,0,0,1]],&#34;projMatrix&#34;:[[3.49879765510559,0,0,0],[0,4.66506338119507,0,0],[0,0,-3.86370301246643,-4151.41943359375],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[0.866025388240814,0,0.5,0],[0,1,0,0],[-0.5,0,0.866025388240814,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:0.800000011920929,&#34;bbox&#34;:[82.6158981323242,493.384094238281,0,432,0,1],&#34;windowRect&#34;:[0,0,576,432],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:false,&#34;fontname&#34;:&#34;NULL&#34;,&#34;maxClipPlanes&#34;:2147483647,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[93,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,92],&#34;subscenes&#34;:[],&#34;flags&#34;:17006},&#34;151&#34;:{&#34;id&#34;:151,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:151,&#34;sphereVerts&#34;:{&#34;reuse&#34;:&#34;rgl39345&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;div id=&#34;density-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Density Plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(devoutrgl)

p &amp;lt;- ggplot(mtcars) +
  geom_density(aes(mpg, fill=as.factor(cyl)), colour = &amp;#39;#ffffff00&amp;#39;) +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  scale_fill_brewer(palette = &amp;#39;Set1&amp;#39;) + 
  theme_bw() +
  labs(title = &amp;quot;{devoutrgl} geom_density()&amp;quot;)


rgldev(fov = 30, view_angle = 30)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;rgl48316&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl48316&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#FFFFFF&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;lines&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:true,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:152,&#34;objects&#34;:{&#34;162&#34;:{&#34;id&#34;:162,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[0,0,0],[576,0,0],[576,432,0],[0,432,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[288,216,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;163&#34;:{&#34;id&#34;:163,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[0,0,0.00999999977648258],[576,0,0.00999999977648258],[576,432,0.00999999977648258],[0,432,0.00999999977648258],[0,0,0.00999999977648258]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0.00999999977648258],[576,0,0.00999999977648258],[576,432,0.00999999977648258],[0,432,0.00999999977648258],[0,0,0.00999999977648258]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;164&#34;:{&#34;id&#34;:164,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.200000002980232,-0.200000002980232]},&#34;vertices&#34;:[[40.6012725830078,31.7325210571289,0],[485.648162841797,31.7325210571289,0],[485.648162841797,408.653198242188,0],[40.6012725830078,408.653198242188,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[263.124725341797,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;165&#34;:{&#34;id&#34;:165,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.300000011920929,-0.300000011920929]},&#34;vertices&#34;:[[40.6012725830078,84.5572052001953,0],[485.648162841797,84.5572052001953,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,84.5572052001953,0],[485.648162841797,84.5572052001953,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;166&#34;:{&#34;id&#34;:166,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464]},&#34;vertices&#34;:[[40.6012725830078,155.941070556641,0],[485.648162841797,155.941070556641,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,155.941070556641,0],[485.648162841797,155.941070556641,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;167&#34;:{&#34;id&#34;:167,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.5,-0.5]},&#34;vertices&#34;:[[40.6012725830078,227.324920654297,0],[485.648162841797,227.324920654297,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,227.324920654297,0],[485.648162841797,227.324920654297,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;168&#34;:{&#34;id&#34;:168,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.600000023841858,-0.600000023841858]},&#34;vertices&#34;:[[40.6012725830078,298.708770751953,0],[485.648162841797,298.708770751953,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,298.708770751953,0],[485.648162841797,298.708770751953,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;169&#34;:{&#34;id&#34;:169,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071]},&#34;vertices&#34;:[[40.6012725830078,370.092620849609,0],[485.648162841797,370.092620849609,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,370.092620849609,0],[485.648162841797,370.092620849609,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;170&#34;:{&#34;id&#34;:170,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.800000011920929,-0.800000011920929]},&#34;vertices&#34;:[[96.9853515625,31.7325210571289,0],[96.9853515625,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[96.9853515625,31.7325210571289,0],[96.9853515625,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;171&#34;:{&#34;id&#34;:171,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.899999976158142,-0.899999976158142]},&#34;vertices&#34;:[[183.067916870117,31.7325210571289,0],[183.067916870117,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[183.067916870117,31.7325210571289,0],[183.067916870117,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;172&#34;:{&#34;id&#34;:172,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1,-1]},&#34;vertices&#34;:[[269.150482177734,31.7325210571289,0],[269.150482177734,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[269.150482177734,31.7325210571289,0],[269.150482177734,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;173&#34;:{&#34;id&#34;:173,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.10000002384186,-1.10000002384186]},&#34;vertices&#34;:[[355.233062744141,31.7325210571289,0],[355.233062744141,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[355.233062744141,31.7325210571289,0],[355.233062744141,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;174&#34;:{&#34;id&#34;:174,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0.711318910121918,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.20000004768372,-1.20000004768372]},&#34;vertices&#34;:[[441.315612792969,31.7325210571289,0],[441.315612792969,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[441.315612792969,31.7325210571289,0],[441.315612792969,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;175&#34;:{&#34;id&#34;:175,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.29999995231628,-1.29999995231628]},&#34;vertices&#34;:[[40.6012725830078,48.8652801513672,0],[485.648162841797,48.8652801513672,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,48.8652801513672,0],[485.648162841797,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;176&#34;:{&#34;id&#34;:176,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.39999997615814,-1.39999997615814]},&#34;vertices&#34;:[[40.6012725830078,120.249137878418,0],[485.648162841797,120.249137878418,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,120.249137878418,0],[485.648162841797,120.249137878418,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;177&#34;:{&#34;id&#34;:177,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.5,-1.5]},&#34;vertices&#34;:[[40.6012725830078,191.632995605469,0],[485.648162841797,191.632995605469,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,191.632995605469,0],[485.648162841797,191.632995605469,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;178&#34;:{&#34;id&#34;:178,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.60000002384186,-1.60000002384186]},&#34;vertices&#34;:[[40.6012725830078,263.016845703125,0],[485.648162841797,263.016845703125,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,263.016845703125,0],[485.648162841797,263.016845703125,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;179&#34;:{&#34;id&#34;:179,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.70000004768372,-1.70000004768372]},&#34;vertices&#34;:[[40.6012725830078,334.400695800781,0],[485.648162841797,334.400695800781,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,334.400695800781,0],[485.648162841797,334.400695800781,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;180&#34;:{&#34;id&#34;:180,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.79999995231628,-1.79999995231628]},&#34;vertices&#34;:[[40.6012725830078,405.784576416016,0],[485.648162841797,405.784576416016,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[40.6012725830078,405.784576416016,0],[485.648162841797,405.784576416016,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;181&#34;:{&#34;id&#34;:181,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-1.89999997615814,-1.89999997615814]},&#34;vertices&#34;:[[53.9440689086914,31.7325210571289,0],[53.9440689086914,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[53.9440689086914,31.7325210571289,0],[53.9440689086914,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;182&#34;:{&#34;id&#34;:182,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2,-2]},&#34;vertices&#34;:[[140.026641845703,31.7325210571289,0],[140.026641845703,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[140.026641845703,31.7325210571289,0],[140.026641845703,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;183&#34;:{&#34;id&#34;:183,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.09999990463257,-2.09999990463257]},&#34;vertices&#34;:[[226.10920715332,31.7325210571289,0],[226.10920715332,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[226.10920715332,31.7325210571289,0],[226.10920715332,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;184&#34;:{&#34;id&#34;:184,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.20000004768372,-2.20000004768372]},&#34;vertices&#34;:[[312.191772460938,31.7325210571289,0],[312.191772460938,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[312.191772460938,31.7325210571289,0],[312.191772460938,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;185&#34;:{&#34;id&#34;:185,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.29999995231628,-2.29999995231628]},&#34;vertices&#34;:[[398.274353027344,31.7325210571289,0],[398.274353027344,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[398.274353027344,31.7325210571289,0],[398.274353027344,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;186&#34;:{&#34;id&#34;:186,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.40000009536743,-2.40000009536743]},&#34;vertices&#34;:[[484.356903076172,31.7325210571289,0],[484.356903076172,408.653198242188,0]],&#34;colors&#34;:[[0.921568632125854,0.921568632125854,0.921568632125854,1]],&#34;centers&#34;:[[484.356903076172,31.7325210571289,0],[484.356903076172,408.653198242188,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;187&#34;:{&#34;id&#34;:187,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.5,-2.5]},&#34;vertices&#34;:[[60.8306732177734,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8681716918945,0],[62.4141883850098,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8686752319336,0],[61.6224327087402,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8684158325195,0],[63.9977035522461,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8692626953125,0],[65.5812225341797,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8699493408203,0],[64.7894592285156,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8696022033691,0],[63.2059478759766,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8689651489258,0],[67.1647338867188,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8707466125488,0],[68.7482528686523,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8716773986816,0],[67.9564895629883,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8712005615234,0],[70.3317642211914,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8727531433105,0],[71.9152755737305,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8739967346191,0],[71.1235198974609,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.873348236084,0],[69.5400085449219,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8721961975098,0],[66.3729782104492,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8703422546387,0],[73.4987945556641,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.875431060791,0],[75.0823059082031,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8770866394043,0],[74.2905502319336,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8762092590332,0],[76.6658248901367,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8789901733398,0],[78.2493362426758,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8811836242676,0],[77.4575805664062,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8800315856934,0],[75.8740692138672,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8779792785645,0],[79.8328552246094,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8836975097656,0],[81.4163665771484,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8865814208984,0],[80.6246109008789,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8850936889648,0],[82.999885559082,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8898811340332,0],[84.5833969116211,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8936538696289,0],[83.7916412353516,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8917427062988,0],[82.2081298828125,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8881950378418,0],[79.0410995483398,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8823890686035,0],[72.7070388793945,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8746757507324,0],[86.1669158935547,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8979797363281,0],[87.7504272460938,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.9029388427734,0],[86.9586715698242,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.9004249572754,0],[89.3339462280273,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.9085884094238,0],[90.9174575805664,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.9150123596191,0],[90.1257019042969,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.9117012023926,0],[88.5421829223633,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.9057006835938,0],[92.5009765625,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.9223098754883,0],[94.0844879150391,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.930591583252,0],[93.2927322387695,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.9262580871582,0],[95.6680068969727,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.9399681091309,0],[97.2515182495117,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.9505729675293,0],[96.4597625732422,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.9449920654297,0],[94.8762435913086,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.9350242614746,0],[91.7092132568359,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.9185218811035,0],[98.8350372314453,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.9625511169434,0],[100.418548583984,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.9760589599609,0],[99.6267929077148,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.9690704345703,0],[102.002059936523,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.9912719726562,0],[103.585578918457,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,49.0083808898926,0],[102.793823242188,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.9996757507324,0],[101.210304260254,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.9834671020508,0],[105.169090270996,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,49.0275993347168,0],[106.75260925293,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,49.0492630004883,0],[105.96085357666,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,49.0383453369141,0],[108.336120605469,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,49.073600769043,0],[109.919639587402,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,49.100830078125,0],[109.127883911133,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,49.0869369506836,0],[107.544364929199,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,49.0612716674805,0],[104.377334594727,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,49.017894744873,0],[98.0432739257812,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.9563026428223,0],[85.3751525878906,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8957977294922,0],[111.503150939941,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,49.1312561035156,0],[113.086669921875,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,49.1652030944824,0],[112.294914245605,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,49.1476440429688,0],[114.670181274414,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,49.2030258178711,0],[116.253700256348,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,49.2451019287109,0],[115.461936950684,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,49.2230606079102,0],[113.878425598145,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,49.1833343505859,0],[117.837211608887,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,49.2918472290039,0],[119.42073059082,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,49.3437080383301,0],[118.628967285156,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,49.3168563842773,0],[121.004241943359,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,49.4011573791504,0],[122.587760925293,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,49.464714050293,0],[121.795997619629,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,49.4322700500488,0],[120.21248626709,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,49.3716239929199,0],[117.045455932617,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,49.267463684082,0],[124.171272277832,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,49.5349235534668,0],[125.754791259766,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,49.6123733520508,0],[124.963027954102,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,49.5733604431152,0],[127.338302612305,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,49.6981735229492,0],[128.921813964844,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,49.7926902770996,0],[128.130065917969,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,49.7448616027832,0],[126.546546936035,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,49.6549911499023,0],[130.505325317383,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,49.8965454101562,0],[132.088851928711,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,50.0105094909668,0],[131.297088623047,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,49.9521522521973,0],[133.67236328125,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,50.1353759765625,0],[135.255874633789,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,50.2720031738281,0],[134.464126586914,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,50.2012786865234,0],[132.880599975586,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,50.0710792541504,0],[129.713577270508,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,49.8436698913574,0],[123.379516601562,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,49.499324798584,0],[136.839385986328,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,50.4212799072266,0],[138.422912597656,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,50.5841445922852,0],[137.631149291992,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,50.4998779296875,0],[140.006423950195,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,50.761589050293,0],[141.589935302734,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,50.9546356201172,0],[140.798187255859,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,50.8559646606445,0],[139.214660644531,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,50.6703491210938,0],[143.173446655273,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,51.164363861084,0],[144.756973266602,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,51.3918952941895,0],[143.965209960938,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,51.2769165039062,0],[146.340484619141,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,51.6383895874023,0],[147.92399597168,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,51.9064865112305,0],[147.132232666016,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,51.7717132568359,0],[145.548721313477,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,51.5144958496094,0],[142.381698608398,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,51.057788848877,0],[149.507507324219,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,52.1961479187012,0],[151.091033935547,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,52.508659362793,0],[150.299270629883,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,52.3499908447266,0],[152.674545288086,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,52.8453407287598,0],[154.258056640625,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,53.2075347900391,0],[153.466293334961,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,53.0219879150391,0],[151.882781982422,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,52.6736106872559,0],[155.841567993164,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,53.5966186523438,0],[157.425079345703,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,54.0139846801758,0],[156.633331298828,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,53.7986335754395,0],[159.008605957031,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,54.4610443115234,0],[160.59211730957,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[159.800354003906,54.6949882507324,0],[159.800354003906,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.008605957031,54.4610443115234,0],[158.216842651367,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,54.2315635681152,0],[155.049819946289,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,53.3964729309082,0],[148.715759277344,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,52.0497894287109,0],[136.047637939453,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,50.343620300293,0],[110.711395263672,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,49.1156234741211,0],[162.175628662109,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[161.383880615234,55.1903381347656,0],[163.759140014648,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[162.967391967773,55.7190437316895,0],[162.967391967773,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.175628662109,55.4499588012695,0],[165.342666625977,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[164.550903320312,56.2825355529785,0],[166.926177978516,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.134414672852,56.8822212219238,0],[166.134414672852,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[165.342666625977,56.5747833251953,0],[164.550903320312,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[163.759140014648,55.9946670532227,0],[168.509689331055,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[166.926177978516,57.1921691894531,0],[170.093200683594,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[168.509689331055,57.8499794006348,0],[169.301452636719,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[167.71794128418,57.5195045471191,0],[171.676727294922,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[170.093200683594,58.5475196838379,0],[173.260238647461,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[171.676727294922,59.2861022949219,0],[172.468475341797,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[170.884963989258,58.9123115539551,0],[170.884963989258,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[169.301452636719,58.1957550048828,0],[167.71794128418,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[166.926177978516,57.1921691894531,0],[174.84375,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[172.468475341797,59.670467376709,0],[176.427261352539,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[174.051986694336,60.4714698791504,0],[175.635513305664,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[173.260238647461,60.0669898986816,0],[178.010787963867,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[175.635513305664,61.3164901733398,0],[179.594299316406,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[176.427261352539,61.7604484558105,0],[178.802536010742,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[175.635513305664,61.3164901733398,0],[177.219024658203,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[174.84375,60.8913917541504,0],[181.177810668945,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[178.010787963867,62.6752281188965,0],[182.761322021484,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[178.802536010742,63.1469955444336,0],[181.969573974609,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[178.802536010742,63.1469955444336,0],[184.344848632812,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[180.386047363281,64.1337280273438,0],[185.928359985352,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[181.177810668945,64.6457672119141,0],[185.136596679688,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[181.177810668945,64.6457672119141,0],[183.553085327148,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[179.594299316406,63.6367034912109,0],[180.386047363281,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[177.219024658203,62.2074737548828,0],[174.051986694336,48.8652801513672,0],[174.84375,48.8652801513672,0],[171.676727294922,59.2861022949219,0],[187.511871337891,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[182.761322021484,65.7031936645508,0],[189.09538269043,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[183.553085327148,66.2520217895508,0],[188.303634643555,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[183.553085327148,66.2520217895508,0],[190.678894042969,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[185.136596679688,67.3848876953125,0],[192.262420654297,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[185.928359985352,67.9656524658203,0],[191.470657348633,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[185.928359985352,67.9656524658203,0],[189.887145996094,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[184.344848632812,66.8096389770508,0],[193.845932006836,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[187.511871337891,69.1728210449219,0],[195.429443359375,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[188.303634643555,69.8003387451172,0],[194.6376953125,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[187.511871337891,69.1728210449219,0],[197.012954711914,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[189.887145996094,71.0834121704102,0],[198.596481323242,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[190.678894042969,71.7423706054688,0],[197.804718017578,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[189.887145996094,71.0834121704102,0],[196.221206665039,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[189.09538269043,70.4324340820312,0],[193.054168701172,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[186.720108032227,68.5675506591797,0],[200.179992675781,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[191.470657348633,72.4168014526367,0],[201.76350402832,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[193.054168701172,73.8003463745117,0],[200.971740722656,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[192.262420654297,73.1025543212891,0],[203.347015380859,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[193.845932006836,74.5127334594727,0],[204.930541992188,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[194.6376953125,75.2337265014648,0],[204.138778686523,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[194.6376953125,75.2337265014648,0],[202.555267333984,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[193.054168701172,73.8003463745117,0],[206.514053344727,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[196.221206665039,76.7164306640625,0],[208.097564697266,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[197.012954711914,77.4811859130859,0],[207.305801391602,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[196.221206665039,76.7164306640625,0],[209.681076049805,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[197.804718017578,78.2491912841797,0],[211.264602661133,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[198.596481323242,79.0380401611328,0],[210.472839355469,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[198.596481323242,79.0380401611328,0],[208.88932800293,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[197.804718017578,78.2491912841797,0],[205.722290039062,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[195.429443359375,75.9724807739258,0],[199.388229370117,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[191.470657348633,72.4168014526367,0],[186.720108032227,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[181.969573974609,65.1685028076172,0],[212.848114013672,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[200.179992675781,80.6420516967773,0],[214.431625366211,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[200.971740722656,81.4601669311523,0],[213.639862060547,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[200.179992675781,80.6420516967773,0],[216.01513671875,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[201.76350402832,82.2920227050781,0],[217.598648071289,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[202.555267333984,83.1341247558594,0],[216.806900024414,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[202.555267333984,83.1341247558594,0],[215.223388671875,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[201.76350402832,82.2920227050781,0],[219.182174682617,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[204.138778686523,84.8517761230469,0],[220.765686035156,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[204.930541992188,85.7240905761719,0],[219.973922729492,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[204.138778686523,84.8517761230469,0],[222.349197387695,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[205.722290039062,86.6114044189453,0],[223.932708740234,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[206.514053344727,87.5027847290039,0],[223.140960693359,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[206.514053344727,87.5027847290039,0],[221.55744934082,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[204.930541992188,85.7240905761719,0],[218.390411376953,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[203.347015380859,83.986572265625,0],[225.516235351562,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[207.305801391602,88.4110946655273,0],[227.099746704102,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[208.88932800293,90.2487258911133,0],[226.307983398438,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[208.097564697266,89.3219528198242,0],[228.683258056641,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[209.681076049805,91.1790466308594,0],[230.26676940918,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[210.472839355469,92.1219711303711,0],[229.475021362305,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[209.681076049805,91.1790466308594,0],[227.891510009766,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[208.88932800293,90.2487258911133,0],[231.850296020508,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[211.264602661133,93.0703811645508,0],[233.433807373047,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[212.056350708008,94.0283279418945,0],[232.642044067383,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[212.056350708008,94.0283279418945,0],[235.017318725586,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[213.639862060547,95.965087890625,0],[236.600830078125,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[214.431625366211,96.9450607299805,0],[235.80908203125,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[213.639862060547,95.965087890625,0],[234.225555419922,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[212.848114013672,94.9933242797852,0],[231.058532714844,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[211.264602661133,93.0703811645508,0],[224.724472045898,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[207.305801391602,88.4110946655273,0],[238.184356689453,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[215.223388671875,97.9293670654297,0],[239.767868041992,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[216.01513671875,98.9225997924805,0],[238.976104736328,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[215.223388671875,97.9293670654297,0],[241.351379394531,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[216.806900024414,99.918083190918,0],[242.93489074707,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[217.598648071289,100.922775268555,0],[242.143142700195,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[217.598648071289,100.922775268555,0],[240.559616088867,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[216.806900024414,99.918083190918,0],[244.518402099609,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[219.182174682617,102.942260742188,0],[246.101928710938,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[219.973922729492,103.957344055176,0],[245.310165405273,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[219.182174682617,102.942260742188,0],[247.685440063477,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[220.765686035156,104.977577209473,0],[249.268951416016,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[221.55744934082,105.999755859375,0],[248.477203369141,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[220.765686035156,104.977577209473,0],[246.893676757812,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[219.973922729492,103.957344055176,0],[243.726654052734,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[218.390411376953,101.928749084473,0],[250.852462768555,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[222.349197387695,107.025115966797,0],[252.435989379883,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[223.140960693359,108.052291870117,0],[251.644226074219,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[223.140960693359,108.052291870117,0],[254.019500732422,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[224.724472045898,110.111145019531,0],[255.603012084961,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[225.516235351562,111.141761779785,0],[254.811264038086,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[224.724472045898,110.111145019531,0],[253.227737426758,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[223.932708740234,109.081123352051,0],[257.1865234375,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[226.307983398438,112.172409057617,0],[258.770050048828,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[227.099746704102,113.203063964844,0],[257.978302001953,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[227.099746704102,113.203063964844,0],[260.353546142578,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[228.683258056641,115.260650634766,0],[261.937072753906,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[229.475021362305,116.286071777344,0],[261.145324707031,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[228.683258056641,115.260650634766,0],[259.561798095703,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[227.891510009766,114.232070922852,0],[256.394775390625,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[225.516235351562,111.141761779785,0],[250.06071472168,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[222.349197387695,107.025115966797,0],[237.392593383789,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[214.431625366211,96.9450607299805,0],[212.056350708008,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[199.388229370117,79.8314208984375,0],[161.383880615234,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[160.59211730957,54.9392242431641,0],[61.6224327087402,48.8684158325195,0],[60.8306732177734,48.8681716918945,0],[61.6224327087402,48.8652801513672,0],[63.2059478759766,48.8689651489258,0],[62.4141883850098,48.8686752319336,0],[63.2059478759766,48.8652801513672,0],[61.6224327087402,48.8684158325195,0],[62.4141883850098,48.8652801513672,0],[62.4141883850098,48.8686752319336,0],[64.7894592285156,48.8696022033691,0],[63.9977035522461,48.8692626953125,0],[64.7894592285156,48.8652801513672,0],[66.3729782104492,48.8703422546387,0],[65.5812225341797,48.8699493408203,0],[66.3729782104492,48.8652801513672,0],[64.7894592285156,48.8696022033691,0],[65.5812225341797,48.8652801513672,0],[65.5812225341797,48.8699493408203,0],[63.2059478759766,48.8689651489258,0],[63.9977035522461,48.8652801513672,0],[63.9977035522461,48.8692626953125,0],[67.9564895629883,48.8712005615234,0],[67.1647338867188,48.8707466125488,0],[67.9564895629883,48.8652801513672,0],[69.5400085449219,48.8721961975098,0],[68.7482528686523,48.8716773986816,0],[69.5400085449219,48.8652801513672,0],[67.9564895629883,48.8712005615234,0],[68.7482528686523,48.8652801513672,0],[68.7482528686523,48.8716773986816,0],[71.1235198974609,48.873348236084,0],[70.3317642211914,48.8727531433105,0],[71.1235198974609,48.8652801513672,0],[72.7070388793945,48.8746757507324,0],[71.9152755737305,48.8739967346191,0],[72.7070388793945,48.8652801513672,0],[71.1235198974609,48.873348236084,0],[71.9152755737305,48.8652801513672,0],[71.9152755737305,48.8739967346191,0],[69.5400085449219,48.8721961975098,0],[70.3317642211914,48.8652801513672,0],[70.3317642211914,48.8727531433105,0],[66.3729782104492,48.8703422546387,0],[67.1647338867188,48.8652801513672,0],[67.1647338867188,48.8707466125488,0],[74.2905502319336,48.8762092590332,0],[73.4987945556641,48.875431060791,0],[74.2905502319336,48.8652801513672,0],[75.8740692138672,48.8779792785645,0],[75.0823059082031,48.8770866394043,0],[75.8740692138672,48.8652801513672,0],[74.2905502319336,48.8762092590332,0],[75.0823059082031,48.8652801513672,0],[75.0823059082031,48.8770866394043,0],[77.4575805664062,48.8800315856934,0],[76.6658248901367,48.8789901733398,0],[77.4575805664062,48.8652801513672,0],[79.0410995483398,48.8823890686035,0],[78.2493362426758,48.8811836242676,0],[79.0410995483398,48.8652801513672,0],[77.4575805664062,48.8800315856934,0],[78.2493362426758,48.8652801513672,0],[78.2493362426758,48.8811836242676,0],[75.8740692138672,48.8779792785645,0],[76.6658248901367,48.8652801513672,0],[76.6658248901367,48.8789901733398,0],[80.6246109008789,48.8850936889648,0],[79.8328552246094,48.8836975097656,0],[80.6246109008789,48.8652801513672,0],[82.2081298828125,48.8881950378418,0],[81.4163665771484,48.8865814208984,0],[82.2081298828125,48.8652801513672,0],[80.6246109008789,48.8850936889648,0],[81.4163665771484,48.8652801513672,0],[81.4163665771484,48.8865814208984,0],[83.7916412353516,48.8917427062988,0],[82.999885559082,48.8898811340332,0],[83.7916412353516,48.8652801513672,0],[85.3751525878906,48.8957977294922,0],[84.5833969116211,48.8936538696289,0],[85.3751525878906,48.8652801513672,0],[83.7916412353516,48.8917427062988,0],[84.5833969116211,48.8652801513672,0],[84.5833969116211,48.8936538696289,0],[82.2081298828125,48.8881950378418,0],[82.999885559082,48.8652801513672,0],[82.999885559082,48.8898811340332,0],[79.0410995483398,48.8823890686035,0],[79.8328552246094,48.8652801513672,0],[79.8328552246094,48.8836975097656,0],[72.7070388793945,48.8746757507324,0],[73.4987945556641,48.8652801513672,0],[73.4987945556641,48.875431060791,0],[86.9586715698242,48.9004249572754,0],[86.1669158935547,48.8979797363281,0],[86.9586715698242,48.8652801513672,0],[88.5421829223633,48.9057006835938,0],[87.7504272460938,48.9029388427734,0],[88.5421829223633,48.8652801513672,0],[86.9586715698242,48.9004249572754,0],[87.7504272460938,48.8652801513672,0],[87.7504272460938,48.9029388427734,0],[90.1257019042969,48.9117012023926,0],[89.3339462280273,48.9085884094238,0],[90.1257019042969,48.8652801513672,0],[91.7092132568359,48.9185218811035,0],[90.9174575805664,48.9150123596191,0],[91.7092132568359,48.8652801513672,0],[90.1257019042969,48.9117012023926,0],[90.9174575805664,48.8652801513672,0],[90.9174575805664,48.9150123596191,0],[88.5421829223633,48.9057006835938,0],[89.3339462280273,48.8652801513672,0],[89.3339462280273,48.9085884094238,0],[93.2927322387695,48.9262580871582,0],[92.5009765625,48.9223098754883,0],[93.2927322387695,48.8652801513672,0],[94.8762435913086,48.9350242614746,0],[94.0844879150391,48.930591583252,0],[94.8762435913086,48.8652801513672,0],[93.2927322387695,48.9262580871582,0],[94.0844879150391,48.8652801513672,0],[94.0844879150391,48.930591583252,0],[96.4597625732422,48.9449920654297,0],[95.6680068969727,48.9399681091309,0],[96.4597625732422,48.8652801513672,0],[98.0432739257812,48.9563026428223,0],[97.2515182495117,48.9505729675293,0],[98.0432739257812,48.8652801513672,0],[96.4597625732422,48.9449920654297,0],[97.2515182495117,48.8652801513672,0],[97.2515182495117,48.9505729675293,0],[94.8762435913086,48.9350242614746,0],[95.6680068969727,48.8652801513672,0],[95.6680068969727,48.9399681091309,0],[91.7092132568359,48.9185218811035,0],[92.5009765625,48.8652801513672,0],[92.5009765625,48.9223098754883,0],[99.6267929077148,48.9690704345703,0],[98.8350372314453,48.9625511169434,0],[99.6267929077148,48.8652801513672,0],[101.210304260254,48.9834671020508,0],[100.418548583984,48.9760589599609,0],[101.210304260254,48.8652801513672,0],[99.6267929077148,48.9690704345703,0],[100.418548583984,48.8652801513672,0],[100.418548583984,48.9760589599609,0],[102.793823242188,48.9996757507324,0],[102.002059936523,48.9912719726562,0],[102.793823242188,48.8652801513672,0],[104.377334594727,49.017894744873,0],[103.585578918457,49.0083808898926,0],[104.377334594727,48.8652801513672,0],[102.793823242188,48.9996757507324,0],[103.585578918457,48.8652801513672,0],[103.585578918457,49.0083808898926,0],[101.210304260254,48.9834671020508,0],[102.002059936523,48.8652801513672,0],[102.002059936523,48.9912719726562,0],[105.96085357666,49.0383453369141,0],[105.169090270996,49.0275993347168,0],[105.96085357666,48.8652801513672,0],[107.544364929199,49.0612716674805,0],[106.75260925293,49.0492630004883,0],[107.544364929199,48.8652801513672,0],[105.96085357666,49.0383453369141,0],[106.75260925293,48.8652801513672,0],[106.75260925293,49.0492630004883,0],[109.127883911133,49.0869369506836,0],[108.336120605469,49.073600769043,0],[109.127883911133,48.8652801513672,0],[110.711395263672,49.1156234741211,0],[109.919639587402,49.100830078125,0],[110.711395263672,48.8652801513672,0],[109.127883911133,49.0869369506836,0],[109.919639587402,48.8652801513672,0],[109.919639587402,49.100830078125,0],[107.544364929199,49.0612716674805,0],[108.336120605469,48.8652801513672,0],[108.336120605469,49.073600769043,0],[104.377334594727,49.017894744873,0],[105.169090270996,48.8652801513672,0],[105.169090270996,49.0275993347168,0],[98.0432739257812,48.9563026428223,0],[98.8350372314453,48.8652801513672,0],[98.8350372314453,48.9625511169434,0],[85.3751525878906,48.8957977294922,0],[86.1669158935547,48.8652801513672,0],[86.1669158935547,48.8979797363281,0],[112.294914245605,49.1476440429688,0],[111.503150939941,49.1312561035156,0],[112.294914245605,48.8652801513672,0],[113.878425598145,49.1833343505859,0],[113.086669921875,49.1652030944824,0],[113.878425598145,48.8652801513672,0],[112.294914245605,49.1476440429688,0],[113.086669921875,48.8652801513672,0],[113.086669921875,49.1652030944824,0],[115.461936950684,49.2230606079102,0],[114.670181274414,49.2030258178711,0],[115.461936950684,48.8652801513672,0],[117.045455932617,49.267463684082,0],[116.253700256348,49.2451019287109,0],[117.045455932617,48.8652801513672,0],[115.461936950684,49.2230606079102,0],[116.253700256348,48.8652801513672,0],[116.253700256348,49.2451019287109,0],[113.878425598145,49.1833343505859,0],[114.670181274414,48.8652801513672,0],[114.670181274414,49.2030258178711,0],[118.628967285156,49.3168563842773,0],[117.837211608887,49.2918472290039,0],[118.628967285156,48.8652801513672,0],[120.21248626709,49.3716239929199,0],[119.42073059082,49.3437080383301,0],[120.21248626709,48.8652801513672,0],[118.628967285156,49.3168563842773,0],[119.42073059082,48.8652801513672,0],[119.42073059082,49.3437080383301,0],[121.795997619629,49.4322700500488,0],[121.004241943359,49.4011573791504,0],[121.795997619629,48.8652801513672,0],[123.379516601562,49.499324798584,0],[122.587760925293,49.464714050293,0],[123.379516601562,48.8652801513672,0],[121.795997619629,49.4322700500488,0],[122.587760925293,48.8652801513672,0],[122.587760925293,49.464714050293,0],[120.21248626709,49.3716239929199,0],[121.004241943359,48.8652801513672,0],[121.004241943359,49.4011573791504,0],[117.045455932617,49.267463684082,0],[117.837211608887,48.8652801513672,0],[117.837211608887,49.2918472290039,0],[124.963027954102,49.5733604431152,0],[124.171272277832,49.5349235534668,0],[124.963027954102,48.8652801513672,0],[126.546546936035,49.6549911499023,0],[125.754791259766,49.6123733520508,0],[126.546546936035,48.8652801513672,0],[124.963027954102,49.5733604431152,0],[125.754791259766,48.8652801513672,0],[125.754791259766,49.6123733520508,0],[128.130065917969,49.7448616027832,0],[127.338302612305,49.6981735229492,0],[128.130065917969,48.8652801513672,0],[129.713577270508,49.8436698913574,0],[128.921813964844,49.7926902770996,0],[129.713577270508,48.8652801513672,0],[128.130065917969,49.7448616027832,0],[128.921813964844,48.8652801513672,0],[128.921813964844,49.7926902770996,0],[126.546546936035,49.6549911499023,0],[127.338302612305,48.8652801513672,0],[127.338302612305,49.6981735229492,0],[131.297088623047,49.9521522521973,0],[130.505325317383,49.8965454101562,0],[131.297088623047,48.8652801513672,0],[132.880599975586,50.0710792541504,0],[132.088851928711,50.0105094909668,0],[132.880599975586,48.8652801513672,0],[131.297088623047,49.9521522521973,0],[132.088851928711,48.8652801513672,0],[132.088851928711,50.0105094909668,0],[134.464126586914,50.2012786865234,0],[133.67236328125,50.1353759765625,0],[134.464126586914,48.8652801513672,0],[136.047637939453,50.343620300293,0],[135.255874633789,50.2720031738281,0],[136.047637939453,48.8652801513672,0],[134.464126586914,50.2012786865234,0],[135.255874633789,48.8652801513672,0],[135.255874633789,50.2720031738281,0],[132.880599975586,50.0710792541504,0],[133.67236328125,48.8652801513672,0],[133.67236328125,50.1353759765625,0],[129.713577270508,49.8436698913574,0],[130.505325317383,48.8652801513672,0],[130.505325317383,49.8965454101562,0],[123.379516601562,49.499324798584,0],[124.171272277832,48.8652801513672,0],[124.171272277832,49.5349235534668,0],[137.631149291992,50.4998779296875,0],[136.839385986328,50.4212799072266,0],[137.631149291992,48.8652801513672,0],[139.214660644531,50.6703491210938,0],[138.422912597656,50.5841445922852,0],[139.214660644531,48.8652801513672,0],[137.631149291992,50.4998779296875,0],[138.422912597656,48.8652801513672,0],[138.422912597656,50.5841445922852,0],[140.798187255859,50.8559646606445,0],[140.006423950195,50.761589050293,0],[140.798187255859,48.8652801513672,0],[142.381698608398,51.057788848877,0],[141.589935302734,50.9546356201172,0],[142.381698608398,48.8652801513672,0],[140.798187255859,50.8559646606445,0],[141.589935302734,48.8652801513672,0],[141.589935302734,50.9546356201172,0],[139.214660644531,50.6703491210938,0],[140.006423950195,48.8652801513672,0],[140.006423950195,50.761589050293,0],[143.965209960938,51.2769165039062,0],[143.173446655273,51.164363861084,0],[143.965209960938,48.8652801513672,0],[145.548721313477,51.5144958496094,0],[144.756973266602,51.3918952941895,0],[145.548721313477,48.8652801513672,0],[143.965209960938,51.2769165039062,0],[144.756973266602,48.8652801513672,0],[144.756973266602,51.3918952941895,0],[147.132232666016,51.7717132568359,0],[146.340484619141,51.6383895874023,0],[147.132232666016,48.8652801513672,0],[148.715759277344,52.0497894287109,0],[147.92399597168,51.9064865112305,0],[148.715759277344,48.8652801513672,0],[147.132232666016,51.7717132568359,0],[147.92399597168,48.8652801513672,0],[147.92399597168,51.9064865112305,0],[145.548721313477,51.5144958496094,0],[146.340484619141,48.8652801513672,0],[146.340484619141,51.6383895874023,0],[142.381698608398,51.057788848877,0],[143.173446655273,48.8652801513672,0],[143.173446655273,51.164363861084,0],[150.299270629883,52.3499908447266,0],[149.507507324219,52.1961479187012,0],[150.299270629883,48.8652801513672,0],[151.882781982422,52.6736106872559,0],[151.091033935547,52.508659362793,0],[151.882781982422,48.8652801513672,0],[150.299270629883,52.3499908447266,0],[151.091033935547,48.8652801513672,0],[151.091033935547,52.508659362793,0],[153.466293334961,53.0219879150391,0],[152.674545288086,52.8453407287598,0],[153.466293334961,48.8652801513672,0],[155.049819946289,53.3964729309082,0],[154.258056640625,53.2075347900391,0],[155.049819946289,48.8652801513672,0],[153.466293334961,53.0219879150391,0],[154.258056640625,48.8652801513672,0],[154.258056640625,53.2075347900391,0],[151.882781982422,52.6736106872559,0],[152.674545288086,48.8652801513672,0],[152.674545288086,52.8453407287598,0],[156.633331298828,53.7986335754395,0],[155.841567993164,53.5966186523438,0],[156.633331298828,48.8652801513672,0],[158.216842651367,54.2315635681152,0],[157.425079345703,54.0139846801758,0],[158.216842651367,48.8652801513672,0],[156.633331298828,53.7986335754395,0],[157.425079345703,48.8652801513672,0],[157.425079345703,54.0139846801758,0],[159.800354003906,54.6949882507324,0],[159.008605957031,54.4610443115234,0],[160.59211730957,48.8652801513672,0],[161.383880615234,55.1903381347656,0],[160.59211730957,54.9392242431641,0],[162.175628662109,48.8652801513672,0],[159.800354003906,54.6949882507324,0],[161.383880615234,48.8652801513672,0],[160.59211730957,54.9392242431641,0],[158.216842651367,54.2315635681152,0],[159.008605957031,48.8652801513672,0],[159.008605957031,54.4610443115234,0],[155.049819946289,53.3964729309082,0],[155.841567993164,48.8652801513672,0],[155.841567993164,53.5966186523438,0],[148.715759277344,52.0497894287109,0],[149.507507324219,48.8652801513672,0],[149.507507324219,52.1961479187012,0],[136.047637939453,50.343620300293,0],[136.839385986328,48.8652801513672,0],[136.839385986328,50.4212799072266,0],[110.711395263672,49.1156234741211,0],[111.503150939941,48.8652801513672,0],[111.503150939941,49.1312561035156,0],[162.967391967773,55.7190437316895,0],[162.175628662109,55.4499588012695,0],[163.759140014648,48.8652801513672,0],[164.550903320312,56.2825355529785,0],[163.759140014648,55.9946670532227,0],[165.342666625977,48.8652801513672,0],[162.967391967773,55.7190437316895,0],[164.550903320312,48.8652801513672,0],[163.759140014648,55.9946670532227,0],[166.134414672852,56.8822212219238,0],[165.342666625977,56.5747833251953,0],[166.926177978516,48.8652801513672,0],[167.71794128418,57.5195045471191,0],[166.926177978516,57.1921691894531,0],[169.301452636719,48.8652801513672,0],[166.134414672852,56.8822212219238,0],[167.71794128418,48.8652801513672,0],[166.926177978516,57.1921691894531,0],[164.550903320312,56.2825355529785,0],[166.134414672852,48.8652801513672,0],[165.342666625977,56.5747833251953,0],[169.301452636719,58.1957550048828,0],[168.509689331055,57.8499794006348,0],[170.884963989258,48.8652801513672,0],[170.884963989258,58.9123115539551,0],[170.093200683594,58.5475196838379,0],[172.468475341797,48.8652801513672,0],[169.301452636719,58.1957550048828,0],[171.676727294922,48.8652801513672,0],[170.093200683594,58.5475196838379,0],[172.468475341797,59.670467376709,0],[171.676727294922,59.2861022949219,0],[174.84375,48.8652801513672,0],[174.051986694336,60.4714698791504,0],[173.260238647461,60.0669898986816,0],[176.427261352539,48.8652801513672,0],[172.468475341797,59.670467376709,0],[175.635513305664,48.8652801513672,0],[173.260238647461,60.0669898986816,0],[170.884963989258,58.9123115539551,0],[173.260238647461,48.8652801513672,0],[171.676727294922,59.2861022949219,0],[167.71794128418,57.5195045471191,0],[170.093200683594,48.8652801513672,0],[168.509689331055,57.8499794006348,0],[175.635513305664,61.3164901733398,0],[174.84375,60.8913917541504,0],[178.010787963867,48.8652801513672,0],[177.219024658203,62.2074737548828,0],[176.427261352539,61.7604484558105,0],[180.386047363281,48.8652801513672,0],[175.635513305664,61.3164901733398,0],[179.594299316406,48.8652801513672,0],[176.427261352539,61.7604484558105,0],[178.802536010742,63.1469955444336,0],[178.010787963867,62.6752281188965,0],[181.969573974609,48.8652801513672,0],[180.386047363281,64.1337280273438,0],[179.594299316406,63.6367034912109,0],[184.344848632812,48.8652801513672,0],[178.802536010742,63.1469955444336,0],[183.553085327148,48.8652801513672,0],[179.594299316406,63.6367034912109,0],[177.219024658203,62.2074737548828,0],[181.177810668945,48.8652801513672,0],[178.010787963867,62.6752281188965,0],[181.969573974609,65.1685028076172,0],[181.177810668945,64.6457672119141,0],[186.720108032227,48.8652801513672,0],[183.553085327148,66.2520217895508,0],[182.761322021484,65.7031936645508,0],[188.303634643555,48.8652801513672,0],[181.969573974609,65.1685028076172,0],[187.511871337891,48.8652801513672,0],[182.761322021484,65.7031936645508,0],[185.136596679688,67.3848876953125,0],[184.344848632812,66.8096389770508,0],[190.678894042969,48.8652801513672,0],[186.720108032227,68.5675506591797,0],[185.928359985352,67.9656524658203,0],[193.054168701172,48.8652801513672,0],[185.136596679688,67.3848876953125,0],[191.470657348633,48.8652801513672,0],[185.928359985352,67.9656524658203,0],[183.553085327148,66.2520217895508,0],[189.887145996094,48.8652801513672,0],[184.344848632812,66.8096389770508,0],[180.386047363281,64.1337280273438,0],[185.136596679688,48.8652801513672,0],[181.177810668945,64.6457672119141,0],[174.051986694336,60.4714698791504,0],[177.219024658203,48.8652801513672,0],[174.84375,60.8913917541504,0],[188.303634643555,69.8003387451172,0],[187.511871337891,69.1728210449219,0],[195.429443359375,48.8652801513672,0],[189.887145996094,71.0834121704102,0],[189.09538269043,70.4324340820312,0],[197.012954711914,48.8652801513672,0],[188.303634643555,69.8003387451172,0],[196.221206665039,48.8652801513672,0],[189.09538269043,70.4324340820312,0],[191.470657348633,72.4168014526367,0],[190.678894042969,71.7423706054688,0],[199.388229370117,48.8652801513672,0],[193.054168701172,73.8003463745117,0],[192.262420654297,73.1025543212891,0],[201.76350402832,48.8652801513672,0],[191.470657348633,72.4168014526367,0],[200.971740722656,48.8652801513672,0],[192.262420654297,73.1025543212891,0],[189.887145996094,71.0834121704102,0],[198.596481323242,48.8652801513672,0],[190.678894042969,71.7423706054688,0],[194.6376953125,75.2337265014648,0],[193.845932006836,74.5127334594727,0],[204.138778686523,48.8652801513672,0],[196.221206665039,76.7164306640625,0],[195.429443359375,75.9724807739258,0],[206.514053344727,48.8652801513672,0],[194.6376953125,75.2337265014648,0],[205.722290039062,48.8652801513672,0],[195.429443359375,75.9724807739258,0],[197.804718017578,78.2491912841797,0],[197.012954711914,77.4811859130859,0],[208.88932800293,48.8652801513672,0],[199.388229370117,79.8314208984375,0],[198.596481323242,79.0380401611328,0],[212.056350708008,48.8652801513672,0],[197.804718017578,78.2491912841797,0],[210.472839355469,48.8652801513672,0],[198.596481323242,79.0380401611328,0],[196.221206665039,76.7164306640625,0],[208.097564697266,48.8652801513672,0],[197.012954711914,77.4811859130859,0],[193.054168701172,73.8003463745117,0],[203.347015380859,48.8652801513672,0],[193.845932006836,74.5127334594727,0],[200.971740722656,81.4601669311523,0],[200.179992675781,80.6420516967773,0],[214.431625366211,48.8652801513672,0],[202.555267333984,83.1341247558594,0],[201.76350402832,82.2920227050781,0],[216.806900024414,48.8652801513672,0],[200.971740722656,81.4601669311523,0],[215.223388671875,48.8652801513672,0],[201.76350402832,82.2920227050781,0],[204.138778686523,84.8517761230469,0],[203.347015380859,83.986572265625,0],[219.182174682617,48.8652801513672,0],[205.722290039062,86.6114044189453,0],[204.930541992188,85.7240905761719,0],[222.349197387695,48.8652801513672,0],[204.138778686523,84.8517761230469,0],[220.765686035156,48.8652801513672,0],[204.930541992188,85.7240905761719,0],[202.555267333984,83.1341247558594,0],[218.390411376953,48.8652801513672,0],[203.347015380859,83.986572265625,0],[206.514053344727,87.5027847290039,0],[224.724472045898,48.8652801513672,0],[207.305801391602,88.4110946655273,0],[208.097564697266,89.3219528198242,0],[227.099746704102,48.8652801513672,0],[208.88932800293,90.2487258911133,0],[226.307983398438,48.8652801513672,0],[208.097564697266,89.3219528198242,0],[207.305801391602,88.4110946655273,0],[209.681076049805,91.1790466308594,0],[230.26676940918,48.8652801513672,0],[210.472839355469,92.1219711303711,0],[211.264602661133,93.0703811645508,0],[232.642044067383,48.8652801513672,0],[212.056350708008,94.0283279418945,0],[231.058532714844,48.8652801513672,0],[211.264602661133,93.0703811645508,0],[210.472839355469,92.1219711303711,0],[228.683258056641,48.8652801513672,0],[209.681076049805,91.1790466308594,0],[208.88932800293,90.2487258911133,0],[205.722290039062,86.6114044189453,0],[223.140960693359,48.8652801513672,0],[206.514053344727,87.5027847290039,0],[199.388229370117,79.8314208984375,0],[212.848114013672,48.8652801513672,0],[200.179992675781,80.6420516967773,0],[186.720108032227,68.5675506591797,0],[193.845932006836,48.8652801513672,0],[187.511871337891,69.1728210449219,0],[212.848114013672,94.9933242797852,0],[235.017318725586,48.8652801513672,0],[213.639862060547,95.965087890625,0],[214.431625366211,96.9450607299805,0],[238.184356689453,48.8652801513672,0],[215.223388671875,97.9293670654297,0],[236.600830078125,48.8652801513672,0],[214.431625366211,96.9450607299805,0],[213.639862060547,95.965087890625,0],[216.01513671875,98.9225997924805,0],[240.559616088867,48.8652801513672,0],[216.806900024414,99.918083190918,0],[217.598648071289,100.922775268555,0],[243.726654052734,48.8652801513672,0],[218.390411376953,101.928749084473,0],[242.143142700195,48.8652801513672,0],[217.598648071289,100.922775268555,0],[216.806900024414,99.918083190918,0],[239.767868041992,48.8652801513672,0],[216.01513671875,98.9225997924805,0],[215.223388671875,97.9293670654297,0],[219.182174682617,102.942260742188,0],[246.101928710938,48.8652801513672,0],[219.973922729492,103.957344055176,0],[222.349197387695,107.025115966797,0],[221.55744934082,105.999755859375,0],[250.06071472168,48.8652801513672,0],[220.765686035156,104.977577209473,0],[249.268951416016,48.8652801513672,0],[221.55744934082,105.999755859375,0],[223.932708740234,109.081123352051,0],[223.140960693359,108.052291870117,0],[253.227737426758,48.8652801513672,0],[225.516235351562,111.141761779785,0],[224.724472045898,110.111145019531,0],[255.603012084961,48.8652801513672,0],[223.932708740234,109.081123352051,0],[254.019500732422,48.8652801513672,0],[224.724472045898,110.111145019531,0],[222.349197387695,107.025115966797,0],[251.644226074219,48.8652801513672,0],[223.140960693359,108.052291870117,0],[244.518402099609,48.8652801513672,0],[219.182174682617,102.942260742188,0],[218.390411376953,101.928749084473,0],[227.891510009766,114.232070922852,0],[260.353546142578,48.8652801513672,0],[228.683258056641,115.260650634766,0],[229.475021362305,116.286071777344,0],[228.683258056641,115.260650634766,0],[261.937072753906,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[227.891510009766,114.232070922852,0],[227.099746704102,113.203063964844,0],[263.520599365234,48.8652801513672,0],[230.26676940918,117.310188293457,0],[229.475021362305,116.286071777344,0],[231.058532714844,118.330291748047,0],[265.895874023438,48.8652801513672,0],[231.850296020508,119.347610473633,0],[264.312347412109,48.8652801513672,0],[231.058532714844,118.330291748047,0],[230.26676940918,117.310188293457,0],[227.099746704102,113.203063964844,0],[226.307983398438,112.172409057617,0],[257.978302001953,48.8652801513672,0],[233.433807373047,121.36873626709,0],[269.062896728516,48.8652801513672,0],[234.225555419922,122.372734069824,0],[270.646392822266,48.8652801513672,0],[235.017318725586,123.369400024414,0],[234.225555419922,122.372734069824,0],[233.433807373047,121.36873626709,0],[232.642044067383,120.360572814941,0],[268.271148681641,48.8652801513672,0],[236.600830078125,125.345443725586,0],[235.80908203125,124.362609863281,0],[272.229919433594,48.8652801513672,0],[235.017318725586,123.369400024414,0],[271.438171386719,48.8652801513672,0],[235.80908203125,124.362609863281,0],[236.600830078125,125.345443725586,0],[273.813446044922,48.8652801513672,0],[237.392593383789,126.326049804688,0],[266.687622070312,48.8652801513672,0],[232.642044067383,120.360572814941,0],[231.850296020508,119.347610473633,0],[226.307983398438,112.172409057617,0],[225.516235351562,111.141761779785,0],[257.1865234375,48.8652801513672,0],[219.973922729492,103.957344055176,0],[247.685440063477,48.8652801513672,0],[220.765686035156,104.977577209473,0],[239.767868041992,129.207183837891,0],[238.976104736328,128.257110595703,0],[276.98046875,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[241.351379394531,131.084808349609,0],[240.559616088867,130.152633666992,0],[241.351379394531,131.084808349609,0],[280.147491455078,48.8652801513672,0],[242.143142700195,132.009094238281,0],[242.93489074707,132.921676635742,0],[281.731018066406,48.8652801513672,0],[243.726654052734,133.822631835938,0],[244.518402099609,134.713989257812,0],[243.726654052734,133.822631835938,0],[282.522766113281,48.8652801513672,0],[242.143142700195,132.009094238281,0],[280.939239501953,48.8652801513672,0],[242.93489074707,132.921676635742,0],[239.767868041992,129.207183837891,0],[277.772216796875,48.8652801513672,0],[240.559616088867,130.152633666992,0],[248.477203369141,138.969192504883,0],[247.685440063477,138.150375366211,0],[286.481567382812,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[246.101928710938,136.458068847656,0],[245.310165405273,135.589538574219,0],[245.310165405273,135.589538574219,0],[244.518402099609,134.713989257812,0],[283.314514160156,48.8652801513672,0],[247.685440063477,138.150375366211,0],[246.893676757812,137.306213378906,0],[285.689788818359,48.8652801513672,0],[309.442535400391,150.57307434082,0],[249.268951416016,139.784088134766,0],[248.477203369141,138.969192504883,0],[309.442535400391,150.57307434082,0],[250.06071472168,140.575210571289,0],[249.268951416016,139.784088134766,0],[246.101928710938,136.458068847656,0],[284.898040771484,48.8652801513672,0],[246.893676757812,137.306213378906,0],[276.188720703125,48.8652801513672,0],[238.976104736328,128.257110595703,0],[238.184356689453,127.292724609375,0],[253.227737426758,143.604217529297,0],[252.435989379883,142.871398925781,0],[305.483734130859,152.350631713867,0],[304.691986083984,152.687484741211,0],[254.019500732422,144.319732666016,0],[253.227737426758,143.604217529297,0],[251.644226074219,142.121185302734,0],[306.275482177734,152.008636474609,0],[252.435989379883,142.871398925781,0],[254.811264038086,145.021636962891,0],[254.019500732422,144.319732666016,0],[303.900207519531,153.015853881836,0],[255.603012084961,145.701034545898,0],[254.811264038086,145.021636962891,0],[303.108459472656,153.336349487305,0],[256.394775390625,146.370986938477,0],[301.524932861328,153.952056884766,0],[257.1865234375,147.012985229492,0],[250.852462768555,141.358596801758,0],[250.06071472168,140.575210571289,0],[307.859008789062,151.302963256836,0],[257.978302001953,147.650039672852,0],[257.1865234375,147.012985229492,0],[258.770050048828,148.253540039062,0],[260.353546142578,149.420837402344,0],[259.561798095703,148.85205078125,0],[258.770050048828,148.253540039062,0],[258.770050048828,148.253540039062,0],[257.1865234375,147.012985229492,0],[299.941436767578,154.531433105469,0],[261.937072753906,150.513305664062,0],[261.145324707031,149.979675292969,0],[296.7744140625,155.568557739258,0],[295.190887451172,156.020080566406,0],[262.728820800781,151.031677246094,0],[261.937072753906,150.513305664062,0],[260.353546142578,149.420837402344,0],[258.770050048828,148.253540039062,0],[298.35791015625,155.071304321289,0],[301.524932861328,153.952056884766,0],[256.394775390625,146.370986938477,0],[255.603012084961,145.701034545898,0],[307.067260742188,151.6572265625,0],[251.644226074219,142.121185302734,0],[250.852462768555,141.358596801758,0],[238.184356689453,127.292724609375,0],[237.392593383789,126.326049804688,0],[274.605194091797,48.8652801513672,0],[212.056350708008,94.0283279418945,0],[234.225555419922,48.8652801513672,0],[212.848114013672,94.9933242797852,0],[260.353546142578,149.420837402344,0],[296.7744140625,155.568557739258,0],[261.145324707031,149.979675292969,0],[161.383880615234,55.1903381347656,0],[162.967391967773,48.8652801513672,0],[162.175628662109,55.4499588012695,0],[229.475021362305,116.286071777344,0],[262.728820800781,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[231.058532714844,118.330291748047,0],[264.312347412109,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[231.850296020508,119.347610473633,0],[265.895874023438,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[231.058532714844,118.330291748047,0],[265.104095458984,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[232.642044067383,120.360572814941,0],[267.479370117188,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[234.225555419922,122.372734069824,0],[269.062896728516,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[233.433807373047,121.36873626709,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[232.642044067383,120.360572814941,0],[266.687622070312,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[235.017318725586,123.369400024414,0],[270.646392822266,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[236.600830078125,125.345443725586,0],[272.229919433594,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[235.80908203125,124.362609863281,0],[271.438171386719,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[237.392593383789,126.326049804688,0],[273.813446044922,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[238.184356689453,127.292724609375,0],[275.396942138672,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[238.184356689453,127.292724609375,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[236.600830078125,125.345443725586,0],[273.021667480469,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[234.225555419922,122.372734069824,0],[269.854644775391,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[239.767868041992,129.207183837891,0],[276.98046875,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[241.351379394531,131.084808349609,0],[278.563995361328,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[240.559616088867,130.152633666992,0],[277.772216796875,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[242.143142700195,132.009094238281,0],[280.147491455078,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[243.726654052734,133.822631835938,0],[281.731018066406,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[242.93489074707,132.921676635742,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[241.351379394531,131.084808349609,0],[279.355743408203,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[245.310165405273,135.589538574219,0],[283.314514160156,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[246.893676757812,137.306213378906,0],[284.898040771484,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[246.101928710938,136.458068847656,0],[284.106292724609,48.8652801513672,0],[248.477203369141,138.969192504883,0],[286.481567382812,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[310.234283447266,150.198379516602,0],[310.234283447266,150.198379516602,0],[248.477203369141,138.969192504883,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[247.685440063477,138.150375366211,0],[285.689788818359,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[244.518402099609,134.713989257812,0],[282.522766113281,48.8652801513672,0],[276.98046875,48.8652801513672,0],[238.976104736328,128.257110595703,0],[276.188720703125,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[312.609558105469,149.053894042969,0],[290.440338134766,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[314.193054199219,148.271667480469,0],[289.648590087891,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[313.401306152344,148.664154052734,0],[292.023864746094,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[315.776580810547,147.478286743164,0],[293.607360839844,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[317.360107421875,146.676666259766,0],[292.815612792969,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[316.568328857422,147.078674316406,0],[291.232086181641,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[314.984832763672,147.876342773438,0],[295.190887451172,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[318.943603515625,145.869583129883,0],[296.7744140625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[320.527130126953,145.059814453125,0],[295.982635498047,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[319.735382080078,145.46501159668,0],[298.35791015625,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[322.110656738281,144.249969482422,0],[299.941436767578,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[322.902404785156,143.845794677734,0],[299.149688720703,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[322.110656738281,144.249969482422,0],[297.566162109375,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[321.318878173828,144.654708862305,0],[294.399139404297,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[318.15185546875,146.273971557617,0],[301.524932861328,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[324.485900878906,143.040786743164,0],[303.108459472656,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[326.069427490234,142.242065429688,0],[302.316711425781,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[325.277679443359,142.640243530273,0],[304.691986083984,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[326.861175537109,141.845184326172,0],[306.275482177734,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[328.444702148438,141.059692382812,0],[305.483734130859,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[327.652954101562,141.451950073242,0],[303.900207519531,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[326.069427490234,142.242065429688,0],[307.859008789062,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[329.236450195312,140.672637939453,0],[309.442535400391,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[330.819976806641,139.906204223633,0],[308.650756835938,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[330.028228759766,140.286468505859,0],[311.026031494141,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[331.611724853516,139.527603149414,0],[312.609558105469,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[333.195251464844,138.78466796875,0],[311.817810058594,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[332.403503417969,139.154632568359,0],[310.234283447266,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[331.611724853516,139.527603149414,0],[307.067260742188,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[328.444702148438,141.059692382812,0],[300.733184814453,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[323.694152832031,143.442626953125,0],[288.065063476562,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[311.817810058594,149.439163208008,0],[314.193054199219,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[333.986999511719,138.419784545898,0],[315.776580810547,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[335.570526123047,137.703399658203,0],[314.984832763672,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[334.778747558594,138.059448242188,0],[317.360107421875,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[336.362274169922,137.353637695312,0],[318.943603515625,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[337.154022216797,137.007110595703,0],[318.15185546875,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[337.154022216797,137.007110595703,0],[316.568328857422,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[335.570526123047,137.703399658203,0],[320.527130126953,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[338.737548828125,136.332412719727,0],[322.110656738281,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[339.529296875,136.006271362305,0],[321.318878173828,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[338.737548828125,136.332412719727,0],[323.694152832031,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[340.321075439453,135.681747436523,0],[325.277679443359,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[341.904571533203,135.056030273438,0],[324.485900878906,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[341.112823486328,135.367477416992,0],[322.902404785156,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[340.321075439453,135.681747436523,0],[319.735382080078,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[337.94580078125,136.668762207031,0],[326.861175537109,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[342.696350097656,134.753570556641,0],[328.444702148438,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[344.279846191406,134.165603637695,0],[327.652954101562,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[343.488098144531,134.455810546875,0],[330.028228759766,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[345.071594238281,133.882064819336,0],[331.611724853516,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[345.863372802734,133.604507446289,0],[330.819976806641,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[345.863372802734,133.604507446289,0],[329.236450195312,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[344.279846191406,134.165603637695,0],[333.195251464844,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[347.446868896484,133.071090698242,0],[334.778747558594,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[348.238647460938,132.817337036133,0],[333.986999511719,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[347.446868896484,133.071090698242,0],[336.362274169922,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[349.030395507812,132.566024780273,0],[337.94580078125,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[350.613922119141,132.09130859375,0],[337.154022216797,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[349.822143554688,132.327682495117,0],[335.570526123047,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[349.030395507812,132.566024780273,0],[332.403503417969,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[346.655120849609,133.335662841797,0],[326.069427490234,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[342.696350097656,134.753570556641,0],[339.529296875,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[351.405670166016,131.867156982422,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[352.197418212891,131.646469116211,0],[340.321075439453,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[352.197418212891,131.646469116211,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[353.780944824219,131.231246948242,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[354.572692871094,131.034744262695,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[353.780944824219,131.231246948242,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[352.989196777344,131.436111450195,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[355.364471435547,130.845748901367,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[356.947967529297,130.490005493164,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[356.156219482422,130.663131713867,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[357.739715576172,130.321212768555,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[358.531494140625,130.163848876953,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[358.531494140625,130.163848876953,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[356.947967529297,130.490005493164,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[355.364471435547,130.845748901367,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[360.114990234375,129.86701965332,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[360.906768798828,129.727172851562,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[360.114990234375,129.86701965332,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[361.698516845703,129.599136352539,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[363.282043457031,129.359664916992,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[362.490264892578,129.474563598633,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[361.698516845703,129.599136352539,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[364.073791503906,129.25,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[365.657318115234,129.052780151367,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[364.865539550781,129.14794921875,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[366.449066162109,128.963195800781,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[367.240814208984,128.882034301758,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[367.240814208984,128.882034301758,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[365.657318115234,129.052780151367,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[364.073791503906,129.25,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[359.3232421875,130.008804321289,0],[338.737548828125,48.8652801513672,0],[339.529296875,48.8652801513672,0],[350.613922119141,132.09130859375,0],[313.401306152344,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[333.195251464844,138.78466796875,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[368.824340820312,128.736785888672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[369.616088867188,128.670883178711,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[369.616088867188,128.670883178711,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[371.199615478516,128.562545776367,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.991363525391,128.518295288086,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[371.199615478516,128.562545776367,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[370.407836914062,128.615951538086,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[373.574890136719,128.442535400391,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,128.412170410156,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,128.442535400391,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,128.367111206055,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[376.741912841797,128.350784301758,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,128.350784301758,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,128.38720703125,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[372.783111572266,128.476806640625,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[378.325408935547,128.331649780273,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.908935546875,128.328079223633,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.1171875,128.329345703125,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,128.33317565918,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,128.349700927734,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,128.339065551758,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,128.328079223633,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,128.376998901367,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[384.659484863281,128.393966674805,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[383.867736816406,128.376998901367,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[386.243011474609,128.433898925781,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[387.826507568359,128.479385375977,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.034759521484,128.455917358398,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[385.451232910156,128.4130859375,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,128.361679077148,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[377.533660888672,128.340072631836,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[389.410034179688,128.5283203125,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[390.993530273438,128.578536987305,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.201782226562,128.553375244141,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[392.577056884766,128.627868652344,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.160583496094,128.674087524414,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[393.368804931641,128.651611328125,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[391.785308837891,128.603561401367,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[395.744079589844,128.71501159668,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,128.760894775391,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[396.535858154297,128.732482910156,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,128.778366088867,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.078155517578,128.780456542969,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[401.286376953125,128.782745361328,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,128.772125244141,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[394.952331542969,128.695327758789,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,128.743774414062,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.828704833984,128.663925170898,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,128.722549438477,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[409.203979492188,128.535568237305,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[411.579223632812,128.34651184082,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[409.995727539062,128.477722167969,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[407.620452880859,128.627532958984,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[414.746276855469,127.999465942383,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[417.913299560547,127.529518127441,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[416.329772949219,127.780555725098,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[420.28857421875,127.086357116699,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[424.247344970703,126.174613952637,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[422.663848876953,126.568237304688,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[418.705047607422,127.389183044434,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[413.162750244141,128.187622070312,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.869903564453,128.771911621094,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[388.618255615234,128.503402709961,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[427.414398193359,125.274726867676,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[430.581420898438,124.221130371094,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[428.997894287109,124.76734161377,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[433.748443603516,123.011421203613,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[436.123718261719,122.001159667969,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[435.331970214844,122.347854614258,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[432.164916992188,123.635856628418,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[439.290740966797,120.516250610352,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[440.874267578125,119.716583251953,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[440.08251953125,120.124588012695,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[443.249542236328,118.449317932129,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[445.624816894531,117.096366882324,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[444.041290283203,118.005859375,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[442.457794189453,118.879539489746,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[437.707244873047,121.277938842773,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[447.208312988281,116.152015686035,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[449.583587646484,114.670013427734,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[448.000091552734,115.665657043457,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[451.167114257812,113.642417907715,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[452.750640869141,112.584205627441,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[451.958862304688,113.119697570801,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[450.375366210938,114.1630859375,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[454.334136962891,111.49674987793,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[455.917663574219,110.381546020508,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[455.125885009766,110.94310760498,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[457.501159667969,109.240142822266,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[459.084686279297,108.074172973633,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[458.292938232422,108.659042358398,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[456.709411621094,109.813720703125,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[453.542388916016,112.045608520508,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[446.416564941406,116.628150939941,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[460.668212890625,106.885314941406,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[462.251708984375,105.674438476562,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[461.4599609375,106.280548095703,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[463.835235595703,104.44401550293,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[464.626983642578,103.821617126465,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[464.626983642578,103.821617126465,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[463.043487548828,105.06022644043,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[465.418731689453,103.196350097656,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[465.418731689453,103.196350097656,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[465.418731689453,103.196350097656,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[465.418731689453,103.196350097656,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[465.418731689453,103.196350097656,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[465.418731689453,103.196350097656,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[465.418731689453,103.196350097656,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[465.418731689453,103.196350097656,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[465.418731689453,103.196350097656,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[465.418731689453,103.196350097656,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[465.418731689453,103.196350097656,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[465.418731689453,103.196350097656,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[465.418731689453,103.196350097656,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[465.418731689453,103.196350097656,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[465.418731689453,103.196350097656,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[465.418731689453,103.196350097656,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[465.418731689453,103.196350097656,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[465.418731689453,103.196350097656,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[465.418731689453,103.196350097656,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[465.418731689453,103.196350097656,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,103.196350097656,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[465.418731689453,103.196350097656,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[465.418731689453,103.196350097656,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[465.418731689453,103.196350097656,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[459.876434326172,107.480743408203,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[425.830871582031,125.74365234375,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[368.032562255859,128.80451965332,0],[329.236450195312,140.672637939453,0],[308.650756835938,48.8652801513672,0],[330.028228759766,140.286468505859,0],[330.819976806641,139.906204223633,0],[310.234283447266,48.8652801513672,0],[331.611724853516,139.527603149414,0],[309.442535400391,48.8652801513672,0],[330.819976806641,139.906204223633,0],[330.028228759766,140.286468505859,0],[326.069427490234,142.242065429688,0],[304.691986083984,48.8652801513672,0],[326.861175537109,141.845184326172,0],[327.652954101562,141.451950073242,0],[306.275482177734,48.8652801513672,0],[328.444702148438,141.059692382812,0],[305.483734130859,48.8652801513672,0],[327.652954101562,141.451950073242,0],[326.861175537109,141.845184326172,0],[328.444702148438,141.059692382812,0],[307.859008789062,48.8652801513672,0],[329.236450195312,140.672637939453,0],[335.570526123047,137.703399658203,0],[317.360107421875,48.8652801513672,0],[336.362274169922,137.353637695312,0],[337.154022216797,137.007110595703,0],[319.735382080078,48.8652801513672,0],[337.94580078125,136.668762207031,0],[318.15185546875,48.8652801513672,0],[337.154022216797,137.007110595703,0],[336.362274169922,137.353637695312,0],[332.403503417969,139.154632568359,0],[312.609558105469,48.8652801513672,0],[333.195251464844,138.78466796875,0],[333.986999511719,138.419784545898,0],[314.984832763672,48.8652801513672,0],[334.778747558594,138.059448242188,0],[314.193054199219,48.8652801513672,0],[333.986999511719,138.419784545898,0],[333.195251464844,138.78466796875,0],[334.778747558594,138.059448242188,0],[315.776580810547,48.8652801513672,0],[335.570526123047,137.703399658203,0],[311.817810058594,48.8652801513672,0],[332.403503417969,139.154632568359,0],[331.611724853516,139.527603149414,0],[317.360107421875,146.676666259766,0],[294.399139404297,48.8652801513672,0],[318.15185546875,146.273971557617,0],[295.190887451172,48.8652801513672,0],[318.943603515625,145.869583129883,0],[318.15185546875,146.273971557617,0],[293.607360839844,48.8652801513672,0],[317.360107421875,146.676666259766,0],[316.568328857422,147.078674316406,0],[314.193054199219,148.271667480469,0],[291.232086181641,48.8652801513672,0],[314.984832763672,147.876342773438,0],[315.776580810547,147.478286743164,0],[314.984832763672,147.876342773438,0],[292.023864746094,48.8652801513672,0],[316.568328857422,147.078674316406,0],[315.776580810547,147.478286743164,0],[292.815612792969,48.8652801513672,0],[318.943603515625,145.869583129883,0],[295.982635498047,48.8652801513672,0],[319.735382080078,145.46501159668,0],[322.902404785156,143.845794677734,0],[300.733184814453,48.8652801513672,0],[323.694152832031,143.442626953125,0],[324.485900878906,143.040786743164,0],[302.316711425781,48.8652801513672,0],[325.277679443359,142.640243530273,0],[301.524932861328,48.8652801513672,0],[324.485900878906,143.040786743164,0],[323.694152832031,143.442626953125,0],[320.527130126953,145.059814453125,0],[319.735382080078,145.46501159668,0],[296.7744140625,48.8652801513672,0],[322.110656738281,144.249969482422,0],[321.318878173828,144.654708862305,0],[298.35791015625,48.8652801513672,0],[320.527130126953,145.059814453125,0],[297.566162109375,48.8652801513672,0],[321.318878173828,144.654708862305,0],[322.902404785156,143.845794677734,0],[322.110656738281,144.249969482422,0],[299.941436767578,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[314.193054199219,148.271667480469,0],[313.401306152344,148.664154052734,0],[325.277679443359,142.640243530273,0],[303.108459472656,48.8652801513672,0],[326.069427490234,142.242065429688,0],[356.156219482422,130.663131713867,0],[355.364471435547,130.845748901367,0],[346.655120849609,48.8652801513672,0],[356.947967529297,130.490005493164,0],[349.030395507812,48.8652801513672,0],[357.739715576172,130.321212768555,0],[347.446868896484,48.8652801513672,0],[356.947967529297,130.490005493164,0],[356.156219482422,130.663131713867,0],[351.405670166016,131.867156982422,0],[340.321075439453,48.8652801513672,0],[352.197418212891,131.646469116211,0],[352.989196777344,131.436111450195,0],[342.696350097656,48.8652801513672,0],[353.780944824219,131.231246948242,0],[341.904571533203,48.8652801513672,0],[352.989196777344,131.436111450195,0],[352.197418212891,131.646469116211,0],[353.780944824219,131.231246948242,0],[344.279846191406,48.8652801513672,0],[354.572692871094,131.034744262695,0],[361.698516845703,129.599136352539,0],[356.156219482422,48.8652801513672,0],[362.490264892578,129.474563598633,0],[363.282043457031,129.359664916992,0],[357.739715576172,48.8652801513672,0],[364.073791503906,129.25,0],[356.947967529297,48.8652801513672,0],[363.282043457031,129.359664916992,0],[362.490264892578,129.474563598633,0],[358.531494140625,130.163848876953,0],[351.405670166016,48.8652801513672,0],[359.3232421875,130.008804321289,0],[360.114990234375,129.86701965332,0],[353.780944824219,48.8652801513672,0],[360.906768798828,129.727172851562,0],[352.197418212891,48.8652801513672,0],[360.114990234375,129.86701965332,0],[359.3232421875,130.008804321289,0],[360.906768798828,129.727172851562,0],[354.572692871094,48.8652801513672,0],[361.698516845703,129.599136352539,0],[349.822143554688,48.8652801513672,0],[358.531494140625,130.163848876953,0],[357.739715576172,130.321212768555,0],[341.904571533203,135.056030273438,0],[326.069427490234,48.8652801513672,0],[342.696350097656,134.753570556641,0],[343.488098144531,134.455810546875,0],[328.444702148438,48.8652801513672,0],[344.279846191406,134.165603637695,0],[327.652954101562,48.8652801513672,0],[343.488098144531,134.455810546875,0],[342.696350097656,134.753570556641,0],[338.737548828125,136.332412719727,0],[322.110656738281,48.8652801513672,0],[339.529296875,136.006271362305,0],[340.321075439453,135.681747436523,0],[324.485900878906,48.8652801513672,0],[341.112823486328,135.367477416992,0],[322.902404785156,48.8652801513672,0],[340.321075439453,135.681747436523,0],[339.529296875,136.006271362305,0],[341.112823486328,135.367477416992,0],[325.277679443359,48.8652801513672,0],[341.904571533203,135.056030273438,0],[348.238647460938,132.817337036133,0],[335.570526123047,48.8652801513672,0],[349.030395507812,132.566024780273,0],[349.822143554688,132.327682495117,0],[337.94580078125,48.8652801513672,0],[350.613922119141,132.09130859375,0],[337.154022216797,48.8652801513672,0],[349.822143554688,132.327682495117,0],[349.030395507812,132.566024780273,0],[345.071594238281,133.882064819336,0],[330.819976806641,48.8652801513672,0],[345.863372802734,133.604507446289,0],[346.655120849609,133.335662841797,0],[333.195251464844,48.8652801513672,0],[347.446868896484,133.071090698242,0],[332.403503417969,48.8652801513672,0],[346.655120849609,133.335662841797,0],[345.863372802734,133.604507446289,0],[347.446868896484,133.071090698242,0],[334.778747558594,48.8652801513672,0],[348.238647460938,132.817337036133,0],[330.028228759766,48.8652801513672,0],[345.071594238281,133.882064819336,0],[344.279846191406,134.165603637695,0],[350.613922119141,132.09130859375,0],[339.529296875,48.8652801513672,0],[351.405670166016,131.867156982422,0],[320.527130126953,48.8652801513672,0],[338.737548828125,136.332412719727,0],[337.94580078125,136.668762207031,0],[269.062896728516,154.464401245117,0],[289.648590087891,157.19221496582,0],[288.065063476562,157.399230957031,0],[265.895874023438,152.904510498047,0],[265.104095458984,152.468780517578,0],[264.312347412109,152.006927490234,0],[269.062896728516,154.464401245117,0],[267.479370117188,153.723785400391,0],[289.648590087891,157.19221496582,0],[266.687622070312,153.329925537109,0],[265.895874023438,152.904510498047,0],[267.479370117188,153.723785400391,0],[269.062896728516,154.464401245117,0],[268.271148681641,154.112335205078,0],[267.479370117188,153.723785400391,0],[288.065063476562,157.399230957031,0],[270.646392822266,155.126235961914,0],[269.062896728516,154.464401245117,0],[265.895874023438,152.904510498047,0],[291.232086181641,156.926239013672,0],[267.479370117188,153.723785400391,0],[274.605194091797,156.435729980469,0],[272.229919433594,155.70947265625,0],[284.898040771484,157.626174926758,0],[272.229919433594,155.70947265625,0],[271.438171386719,155.430755615234,0],[270.646392822266,155.126235961914,0],[269.854644775391,154.810913085938,0],[269.062896728516,154.464401245117,0],[270.646392822266,155.126235961914,0],[273.813446044922,156.214492797852,0],[273.021667480469,155.97216796875,0],[274.605194091797,156.435729980469,0],[274.605194091797,156.435729980469,0],[273.021667480469,155.97216796875,0],[272.229919433594,155.70947265625,0],[272.229919433594,155.70947265625,0],[270.646392822266,155.126235961914,0],[286.481567382812,157.544723510742,0],[276.188720703125,156.822219848633,0],[275.396942138672,156.641983032227,0],[274.605194091797,156.435729980469,0],[292.815612792969,156.604080200195,0],[265.895874023438,152.904510498047,0],[264.312347412109,152.006927490234,0],[276.98046875,156.992828369141,0],[276.188720703125,156.822219848633,0],[277.772216796875,157.132705688477,0],[279.355743408203,157.368438720703,0],[278.563995361328,157.267517089844,0],[277.772216796875,157.132705688477,0],[277.772216796875,157.132705688477,0],[276.188720703125,156.822219848633,0],[280.939239501953,157.530914306641,0],[280.147491455078,157.463836669922,0],[279.355743408203,157.368438720703,0],[280.939239501953,157.530914306641,0],[280.939239501953,157.530914306641,0],[279.355743408203,157.368438720703,0],[277.772216796875,157.132705688477,0],[280.939239501953,157.530914306641,0],[282.522766113281,157.621826171875,0],[281.731018066406,157.587814331055,0],[280.939239501953,157.530914306641,0],[276.188720703125,156.822219848633,0],[282.522766113281,157.621826171875,0],[274.605194091797,156.435729980469,0],[284.898040771484,157.626174926758,0],[282.522766113281,157.621826171875,0],[288.065063476562,157.399230957031,0],[287.273315429688,157.484939575195,0],[286.481567382812,157.544723510742,0],[286.481567382812,157.544723510742,0],[285.689788818359,157.5966796875,0],[284.898040771484,157.626174926758,0],[283.314514160156,157.641250610352,0],[282.522766113281,157.621826171875,0],[284.898040771484,157.626174926758,0],[284.898040771484,157.626174926758,0],[284.106292724609,157.643051147461,0],[283.314514160156,157.641250610352,0],[274.605194091797,156.435729980469,0],[282.522766113281,157.621826171875,0],[276.188720703125,156.822219848633,0],[272.229919433594,155.70947265625,0],[286.481567382812,157.544723510742,0],[284.898040771484,157.626174926758,0],[270.646392822266,155.126235961914,0],[288.065063476562,157.399230957031,0],[286.481567382812,157.544723510742,0],[264.312347412109,152.006927490234,0],[263.520599365234,151.529632568359,0],[293.607360839844,156.422866821289,0],[304.691986083984,152.687484741211,0],[303.900207519531,153.015853881836,0],[254.019500732422,144.319732666016,0],[304.691986083984,152.687484741211,0],[253.227737426758,143.604217529297,0],[305.483734130859,152.350631713867,0],[303.108459472656,153.336349487305,0],[254.811264038086,145.021636962891,0],[303.900207519531,153.015853881836,0],[257.1865234375,147.012985229492,0],[301.524932861328,153.952056884766,0],[300.733184814453,154.248962402344,0],[301.524932861328,153.952056884766,0],[255.603012084961,145.701034545898,0],[302.316711425781,153.649688720703,0],[255.603012084961,145.701034545898,0],[303.108459472656,153.336349487305,0],[302.316711425781,153.649688720703,0],[305.483734130859,152.350631713867,0],[252.435989379883,142.871398925781,0],[306.275482177734,152.008636474609,0],[309.442535400391,150.57307434082,0],[308.650756835938,150.938766479492,0],[250.06071472168,140.575210571289,0],[310.234283447266,150.198379516602,0],[288.065063476562,48.8652801513672,0],[311.026031494141,149.822036743164,0],[248.477203369141,138.969192504883,0],[310.234283447266,150.198379516602,0],[309.442535400391,150.57307434082,0],[306.275482177734,152.008636474609,0],[251.644226074219,142.121185302734,0],[307.067260742188,151.6572265625,0],[250.06071472168,140.575210571289,0],[308.650756835938,150.938766479492,0],[307.859008789062,151.302963256836,0],[307.067260742188,151.6572265625,0],[250.852462768555,141.358596801758,0],[307.859008789062,151.302963256836,0],[311.817810058594,149.439163208008,0],[311.026031494141,149.822036743164,0],[288.065063476562,48.8652801513672,0],[299.941436767578,154.531433105469,0],[257.1865234375,147.012985229492,0],[300.733184814453,154.248962402344,0],[292.815612792969,156.604080200195,0],[291.232086181641,156.926239013672,0],[265.895874023438,152.904510498047,0],[263.520599365234,151.529632568359,0],[294.399139404297,156.228546142578,0],[293.607360839844,156.422866821289,0],[292.815612792969,156.604080200195,0],[292.023864746094,156.773910522461,0],[291.232086181641,156.926239013672,0],[264.312347412109,152.006927490234,0],[293.607360839844,156.422866821289,0],[292.815612792969,156.604080200195,0],[291.232086181641,156.926239013672,0],[290.440338134766,157.070327758789,0],[289.648590087891,157.19221496582,0],[291.232086181641,156.926239013672,0],[289.648590087891,157.19221496582,0],[267.479370117188,153.723785400391,0],[289.648590087891,157.19221496582,0],[288.856842041016,157.309341430664,0],[288.065063476562,157.399230957031,0],[299.149688720703,154.810531616211,0],[298.35791015625,155.071304321289,0],[299.941436767578,154.531433105469,0],[261.937072753906,150.513305664062,0],[296.7744140625,155.568557739258,0],[295.982635498047,155.802581787109,0],[295.190887451172,156.020080566406,0],[261.937072753906,150.513305664062,0],[295.982635498047,155.802581787109,0],[262.728820800781,151.031677246094,0],[295.190887451172,156.020080566406,0],[294.399139404297,156.228546142578,0],[263.520599365234,151.529632568359,0],[262.728820800781,151.031677246094,0],[294.399139404297,156.228546142578,0],[298.35791015625,155.071304321289,0],[297.566162109375,155.329162597656,0],[296.7744140625,155.568557739258,0],[296.7744140625,155.568557739258,0],[260.353546142578,149.420837402344,0],[298.35791015625,155.071304321289,0],[298.35791015625,155.071304321289,0],[258.770050048828,148.253540039062,0],[299.941436767578,154.531433105469,0],[288.856842041016,48.8652801513672,0],[312.609558105469,149.053894042969,0],[311.817810058594,149.439163208008,0],[313.401306152344,148.664154052734,0],[312.609558105469,149.053894042969,0],[289.648590087891,48.8652801513672,0],[354.572692871094,131.034744262695,0],[345.071594238281,48.8652801513672,0],[355.364471435547,130.845748901367,0],[417.913299560547,48.8652801513672,0],[432.164916992188,123.635856628418,0],[431.373168945312,123.937057495117,0],[432.956695556641,123.33088684082,0],[432.164916992188,123.635856628418,0],[418.705047607422,48.8652801513672,0],[431.373168945312,123.937057495117,0],[430.581420898438,124.221130371094,0],[417.913299560547,48.8652801513672,0],[432.956695556641,123.33088684082,0],[418.705047607422,48.8652801513672,0],[433.748443603516,123.011421203613,0],[429.789672851562,124.502578735352,0],[428.997894287109,124.76734161377,0],[417.121551513672,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[430.581420898438,124.221130371094,0],[429.789672851562,124.502578735352,0],[428.997894287109,124.76734161377,0],[428.206146240234,125.028007507324,0],[416.329772949219,48.8652801513672,0],[437.707244873047,121.277938842773,0],[421.8720703125,48.8652801513672,0],[438.498992919922,120.904083251953,0],[436.915466308594,121.645317077637,0],[421.080322265625,48.8652801513672,0],[437.707244873047,121.277938842773,0],[435.331970214844,122.347854614258,0],[420.28857421875,48.8652801513672,0],[436.123718261719,122.001159667969,0],[419.496826171875,48.8652801513672,0],[434.540191650391,122.685554504395,0],[433.748443603516,123.011421203613,0],[419.496826171875,48.8652801513672,0],[435.331970214844,122.347854614258,0],[434.540191650391,122.685554504395,0],[436.123718261719,122.001159667969,0],[421.080322265625,48.8652801513672,0],[436.915466308594,121.645317077637,0],[440.08251953125,120.124588012695,0],[439.290740966797,120.516250610352,0],[422.663848876953,48.8652801513672,0],[427.414398193359,125.274726867676,0],[416.329772949219,48.8652801513672,0],[428.206146240234,125.028007507324,0],[418.705047607422,127.389183044434,0],[412.371002197266,48.8652801513672,0],[419.496826171875,127.245079040527,0],[413.162750244141,48.8652801513672,0],[421.080322265625,126.925277709961,0],[420.28857421875,127.086357116699,0],[412.371002197266,48.8652801513672,0],[420.28857421875,127.086357116699,0],[419.496826171875,127.245079040527,0],[415.538024902344,127.893859863281,0],[409.995727539062,48.8652801513672,0],[416.329772949219,127.780555725098,0],[411.579223632812,48.8652801513672,0],[418.705047607422,127.389183044434,0],[417.913299560547,127.529518127441,0],[417.913299560547,127.529518127441,0],[417.121551513672,127.657943725586,0],[410.787475585938,48.8652801513672,0],[416.329772949219,127.780555725098,0],[410.787475585938,48.8652801513672,0],[417.121551513672,127.657943725586,0],[425.039123535156,125.963394165039,0],[414.746276855469,48.8652801513672,0],[425.830871582031,125.74365234375,0],[426.622619628906,125.514801025391,0],[425.830871582031,125.74365234375,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[425.039123535156,125.963394165039,0],[424.247344970703,126.174613952637,0],[421.8720703125,126.748405456543,0],[413.162750244141,48.8652801513672,0],[422.663848876953,126.568237304688,0],[413.954498291016,48.8652801513672,0],[423.455596923828,126.374359130859,0],[422.663848876953,126.568237304688,0],[424.247344970703,126.174613952637,0],[423.455596923828,126.374359130859,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[421.8720703125,126.748405456543,0],[421.080322265625,126.925277709961,0],[426.622619628906,125.514801025391,0],[415.538024902344,48.8652801513672,0],[427.414398193359,125.274726867676,0],[421.8720703125,48.8652801513672,0],[439.290740966797,120.516250610352,0],[438.498992919922,120.904083251953,0],[436.915466308594,48.8652801513672,0],[456.709411621094,109.813720703125,0],[455.917663574219,110.381546020508,0],[458.292938232422,108.659042358398,0],[457.501159667969,109.240142822266,0],[438.498992919922,48.8652801513672,0],[455.917663574219,110.381546020508,0],[455.125885009766,110.94310760498,0],[436.123718261719,48.8652801513672,0],[453.542388916016,112.045608520508,0],[452.750640869141,112.584205627441,0],[433.748443603516,48.8652801513672,0],[453.542388916016,112.045608520508,0],[434.540191650391,48.8652801513672,0],[454.334136962891,111.49674987793,0],[454.334136962891,111.49674987793,0],[435.331970214844,48.8652801513672,0],[455.125885009766,110.94310760498,0],[457.501159667969,109.240142822266,0],[456.709411621094,109.813720703125,0],[437.707244873047,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[463.043487548828,105.06022644043,0],[462.251708984375,105.674438476562,0],[461.4599609375,106.280548095703,0],[442.457794189453,48.8652801513672,0],[462.251708984375,105.674438476562,0],[440.874267578125,48.8652801513672,0],[460.668212890625,106.885314941406,0],[459.876434326172,107.480743408203,0],[440.08251953125,48.8652801513672,0],[459.876434326172,107.480743408203,0],[459.084686279297,108.074172973633,0],[459.084686279297,108.074172973633,0],[458.292938232422,108.659042358398,0],[439.290740966797,48.8652801513672,0],[460.668212890625,106.885314941406,0],[441.666015625,48.8652801513672,0],[461.4599609375,106.280548095703,0],[463.043487548828,105.06022644043,0],[444.041290283203,48.8652801513672,0],[463.835235595703,104.44401550293,0],[451.958862304688,113.119697570801,0],[432.956695556641,48.8652801513672,0],[452.750640869141,112.584205627441,0],[444.041290283203,118.005859375,0],[443.249542236328,118.449317932129,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[444.833038330078,117.556381225586,0],[444.041290283203,118.005859375,0],[442.457794189453,118.879539489746,0],[441.666015625,119.306060791016,0],[424.247344970703,48.8652801513672,0],[440.874267578125,119.716583251953,0],[424.247344970703,48.8652801513672,0],[441.666015625,119.306060791016,0],[440.874267578125,119.716583251953,0],[440.08251953125,120.124588012695,0],[423.455596923828,48.8652801513672,0],[443.249542236328,118.449317932129,0],[442.457794189453,118.879539489746,0],[425.039123535156,48.8652801513672,0],[445.624816894531,117.096366882324,0],[444.833038330078,117.556381225586,0],[426.622619628906,48.8652801513672,0],[447.208312988281,116.152015686035,0],[428.997894287109,48.8652801513672,0],[448.000091552734,115.665657043457,0],[451.958862304688,113.119697570801,0],[451.167114257812,113.642417907715,0],[432.164916992188,48.8652801513672,0],[450.375366210938,114.1630859375,0],[449.583587646484,114.670013427734,0],[430.581420898438,48.8652801513672,0],[446.416564941406,116.628150939941,0],[445.624816894531,117.096366882324,0],[427.414398193359,48.8652801513672,0],[448.791839599609,115.173873901367,0],[448.000091552734,115.665657043457,0],[429.789672851562,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[447.208312988281,116.152015686035,0],[446.416564941406,116.628150939941,0],[429.789672851562,48.8652801513672,0],[449.583587646484,114.670013427734,0],[448.791839599609,115.173873901367,0],[451.167114257812,113.642417907715,0],[450.375366210938,114.1630859375,0],[431.373168945312,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[464.626983642578,103.821617126465,0],[463.835235595703,104.44401550293,0],[415.538024902344,127.893859863281,0],[414.746276855469,127.999465942383,0],[409.995727539062,48.8652801513672,0],[377.533660888672,128.340072631836,0],[377.533660888672,48.8652801513672,0],[378.325408935547,128.331649780273,0],[379.1171875,48.8652801513672,0],[379.908935546875,128.328079223633,0],[379.1171875,128.329345703125,0],[379.1171875,128.329345703125,0],[378.325408935547,128.331649780273,0],[378.325408935547,48.8652801513672,0],[374.366638183594,128.412170410156,0],[373.574890136719,48.8652801513672,0],[375.158386230469,128.38720703125,0],[375.950164794922,128.367111206055,0],[375.158386230469,48.8652801513672,0],[376.741912841797,128.350784301758,0],[374.366638183594,48.8652801513672,0],[375.950164794922,128.367111206055,0],[375.158386230469,128.38720703125,0],[376.741912841797,128.350784301758,0],[376.741912841797,48.8652801513672,0],[377.533660888672,128.340072631836,0],[381.492462158203,48.8652801513672,0],[381.492462158203,128.339065551758,0],[380.70068359375,128.33317565918,0],[383.075958251953,48.8652801513672,0],[383.075958251953,128.361679077148,0],[382.284210205078,128.349700927734,0],[382.284210205078,128.349700927734,0],[381.492462158203,128.339065551758,0],[382.284210205078,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,128.393966674805,0],[383.867736816406,128.376998901367,0],[387.034759521484,48.8652801513672,0],[386.243011474609,128.433898925781,0],[385.451232910156,128.4130859375,0],[385.451232910156,128.4130859375,0],[384.659484863281,128.393966674805,0],[386.243011474609,48.8652801513672,0],[383.867736816406,128.376998901367,0],[383.075958251953,128.361679077148,0],[383.867736816406,48.8652801513672,0],[380.70068359375,128.33317565918,0],[379.908935546875,128.328079223633,0],[380.70068359375,48.8652801513672,0],[368.032562255859,128.80451965332,0],[364.865539550781,48.8652801513672,0],[368.824340820312,128.736785888672,0],[369.616088867188,128.670883178711,0],[367.240814208984,48.8652801513672,0],[370.407836914062,128.615951538086,0],[365.657318115234,48.8652801513672,0],[369.616088867188,128.670883178711,0],[368.824340820312,128.736785888672,0],[364.865539550781,129.14794921875,0],[360.114990234375,48.8652801513672,0],[365.657318115234,129.052780151367,0],[366.449066162109,128.963195800781,0],[362.490264892578,48.8652801513672,0],[367.240814208984,128.882034301758,0],[361.698516845703,48.8652801513672,0],[366.449066162109,128.963195800781,0],[365.657318115234,129.052780151367,0],[367.240814208984,128.882034301758,0],[364.073791503906,48.8652801513672,0],[368.032562255859,128.80451965332,0],[372.783111572266,128.476806640625,0],[371.199615478516,48.8652801513672,0],[373.574890136719,128.442535400391,0],[388.618255615234,48.8652801513672,0],[387.826507568359,128.479385375977,0],[387.034759521484,128.455917358398,0],[371.199615478516,128.562545776367,0],[369.616088867188,48.8652801513672,0],[371.991363525391,128.518295288086,0],[390.201782226562,48.8652801513672,0],[389.410034179688,128.5283203125,0],[388.618255615234,128.503402709961,0],[388.618255615234,128.503402709961,0],[387.826507568359,128.479385375977,0],[389.410034179688,48.8652801513672,0],[371.991363525391,128.518295288086,0],[370.407836914062,48.8652801513672,0],[372.783111572266,128.476806640625,0],[368.032562255859,48.8652801513672,0],[371.199615478516,128.562545776367,0],[370.407836914062,128.615951538086,0],[387.034759521484,128.455917358398,0],[386.243011474609,128.433898925781,0],[387.826507568359,48.8652801513672,0],[373.574890136719,128.442535400391,0],[372.783111572266,48.8652801513672,0],[374.366638183594,128.412170410156,0],[390.993530273438,128.578536987305,0],[392.577056884766,48.8652801513672,0],[391.785308837891,128.603561401367,0],[394.160583496094,48.8652801513672,0],[393.368804931641,128.651611328125,0],[392.577056884766,128.627868652344,0],[392.577056884766,128.627868652344,0],[391.785308837891,128.603561401367,0],[393.368804931641,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,128.578536987305,0],[390.201782226562,128.553375244141,0],[393.368804931641,128.651611328125,0],[394.952331542969,48.8652801513672,0],[394.160583496094,128.674087524414,0],[408.412200927734,128.582931518555,0],[407.620452880859,128.627532958984,0],[406.036926269531,48.8652801513672,0],[406.828704833984,128.663925170898,0],[405.245178222656,48.8652801513672,0],[407.620452880859,128.627532958984,0],[406.828704833984,128.663925170898,0],[406.036926269531,128.696304321289,0],[404.453430175781,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[413.162750244141,128.187622070312,0],[412.371002197266,128.272476196289,0],[413.954498291016,128.098220825195,0],[413.162750244141,128.187622070312,0],[409.203979492188,48.8652801513672,0],[412.371002197266,128.272476196289,0],[411.579223632812,128.34651184082,0],[408.412200927734,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[409.203979492188,128.535568237305,0],[408.412200927734,128.582931518555,0],[410.787475585938,128.41813659668,0],[409.995727539062,128.477722167969,0],[407.620452880859,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[411.579223632812,128.34651184082,0],[410.787475585938,128.41813659668,0],[409.995727539062,128.477722167969,0],[409.203979492188,128.535568237305,0],[406.828704833984,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,128.553375244141,0],[389.410034179688,128.5283203125,0],[395.744079589844,128.71501159668,0],[397.327606201172,48.8652801513672,0],[396.535858154297,128.732482910156,0],[398.119354248047,48.8652801513672,0],[398.119354248047,128.760894775391,0],[397.327606201172,128.748428344727,0],[396.535858154297,48.8652801513672,0],[395.744079589844,128.71501159668,0],[394.952331542969,128.695327758789,0],[397.327606201172,128.748428344727,0],[396.535858154297,128.732482910156,0],[398.119354248047,48.8652801513672,0],[398.119354248047,128.760894775391,0],[398.9111328125,48.8652801513672,0],[398.9111328125,128.772125244141,0],[399.702880859375,48.8652801513672,0],[399.702880859375,128.778366088867,0],[398.9111328125,128.772125244141,0],[394.952331542969,128.695327758789,0],[394.160583496094,128.674087524414,0],[395.744079589844,48.8652801513672,0],[404.453430175781,128.743774414062,0],[403.661651611328,128.760726928711,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[405.245178222656,128.722549438477,0],[404.453430175781,128.743774414062,0],[402.869903564453,128.771911621094,0],[402.869903564453,48.8652801513672,0],[403.661651611328,128.760726928711,0],[400.49462890625,128.783782958984,0],[399.702880859375,128.778366088867,0],[400.49462890625,48.8652801513672,0],[401.286376953125,128.782745361328,0],[401.286376953125,48.8652801513672,0],[402.078155517578,128.780456542969,0],[402.869903564453,128.771911621094,0],[402.078155517578,128.780456542969,0],[402.078155517578,48.8652801513672,0],[400.49462890625,128.783782958984,0],[400.49462890625,48.8652801513672,0],[401.286376953125,128.782745361328,0],[406.036926269531,128.696304321289,0],[405.245178222656,128.722549438477,0],[404.453430175781,48.8652801513672,0],[414.746276855469,127.999465942383,0],[413.954498291016,128.098220825195,0],[409.203979492188,48.8652801513672,0],[364.865539550781,129.14794921875,0],[364.073791503906,129.25,0],[359.3232421875,48.8652801513672,0],[464.626983642578,103.821617126465,0],[446.416564941406,48.8652801513672,0],[465.418731689453,103.196350097656,0],[264.312347412109,48.8652801513672,0],[230.26676940918,117.310188293457,0],[263.520599365234,48.8652801513672,0]],&#34;colors&#34;:[[0.894117653369904,0.10196078568697,0.109803922474384,1]],&#34;centers&#34;:[[61.094596862793,48.8662414550781,0],[62.678108215332,48.8664169311523,0],[61.8863525390625,48.866325378418,0],[64.2616271972656,48.8666076660156,0],[65.8451385498047,48.8668365478516,0],[65.0533828735352,48.8667221069336,0],[63.4698715209961,48.8665084838867,0],[67.4286499023438,48.8671035766602,0],[69.0121765136719,48.8674125671387,0],[68.2204132080078,48.8672561645508,0],[70.5956878662109,48.8677749633789,0],[72.17919921875,48.8681869506836,0],[71.3874359130859,48.8679733276367,0],[69.8039245605469,48.8675842285156,0],[66.6369018554688,48.8669700622559,0],[73.7627105712891,48.8686637878418,0],[75.3462295532227,48.8692169189453,0],[74.5544738769531,48.8689231872559,0],[76.9297485351562,48.8698539733887,0],[78.5132598876953,48.8705825805664,0],[77.7214965820312,48.8702011108398,0],[76.1379852294922,48.869514465332,0],[80.0967712402344,48.8714218139648,0],[81.680290222168,48.8723831176758,0],[80.8885345458984,48.8718872070312,0],[83.2638092041016,48.8734817504883,0],[84.8473205566406,48.8747367858887,0],[84.0555572509766,48.8740997314453,0],[82.4720458984375,48.8729209899902,0],[79.3050231933594,48.8709831237793,0],[72.9709625244141,48.8684158325195,0],[86.4308319091797,48.8761825561523,0],[88.0143432617188,48.8778343200684,0],[87.2225952148438,48.8769950866699,0],[89.5978698730469,48.8797149658203,0],[91.1813812255859,48.8818588256836,0],[90.3896179199219,48.8807525634766,0],[88.8061065673828,48.8787536621094,0],[92.764892578125,48.8842887878418,0],[94.3484115600586,48.8870506286621,0],[93.5566558837891,48.8856048583984,0],[95.9319305419922,48.8901786804199,0],[97.5154418945312,48.8937149047852,0],[96.7236785888672,48.8918533325195,0],[95.1401672363281,48.8885307312012,0],[91.9731369018555,48.8830261230469,0],[99.0989608764648,48.897705078125,0],[100.682464599609,48.9022064208984,0],[99.8907165527344,48.8998794555664,0],[102.265983581543,48.9072799682617,0],[103.849502563477,48.9129791259766,0],[103.057739257812,48.9100799560547,0],[101.474227905273,48.9046745300293,0],[105.433013916016,48.9193878173828,0],[107.016525268555,48.9266052246094,0],[106.22477722168,48.9229698181152,0],[108.600036621094,48.9347229003906,0],[110.183563232422,48.9437980651855,0],[109.391807556152,48.9391708374023,0],[107.808288574219,48.9306144714355,0],[104.641258239746,48.9161529541016,0],[98.3071899414062,48.895622253418,0],[85.6390838623047,48.8754539489746,0],[111.767074584961,48.9539413452148,0],[113.3505859375,48.9652557373047,0],[112.558837890625,48.9594039916992,0],[114.934104919434,48.9778671264648,0],[116.517623901367,48.9918899536133,0],[115.725860595703,48.9845390319824,0],[114.142349243164,48.9712982177734,0],[118.101135253906,49.0074691772461,0],[119.68465423584,49.0247573852539,0],[118.892883300781,49.0158081054688,0],[121.268157958984,49.0439071655273,0],[122.851684570312,49.0650939941406,0],[122.059921264648,49.0542755126953,0],[120.476409912109,49.034065246582,0],[117.309371948242,48.999340057373,0],[124.435195922852,49.0884971618652,0],[126.018707275391,49.1143112182617,0],[125.226951599121,49.1013107299805,0],[127.602226257324,49.1429138183594,0],[129.185729980469,49.1744194030762,0],[128.393981933594,49.1584739685059,0],[126.810470581055,49.1285209655762,0],[130.769256591797,49.2090377807617,0],[132.352767944336,49.2470245361328,0],[131.561004638672,49.2275695800781,0],[133.936279296875,49.288646697998,0],[135.519805908203,49.3341903686523,0],[134.728057861328,49.3106155395508,0],[133.14453125,49.2672119140625,0],[129.977508544922,49.1914138793945,0],[123.643432617188,49.0766296386719,0],[137.103302001953,49.3839492797852,0],[138.686828613281,49.438232421875,0],[137.895080566406,49.4101486206055,0],[140.270355224609,49.497386932373,0],[141.853851318359,49.5617332458496,0],[141.062103271484,49.5288391113281,0],[139.478576660156,49.4669723510742,0],[143.437377929688,49.6316452026367,0],[145.020904541016,49.7074851989746,0],[144.229125976562,49.6691589355469,0],[146.604400634766,49.7896537780762,0],[148.187927246094,49.879020690918,0],[147.396148681641,49.8340911865234,0],[145.812652587891,49.7483520507812,0],[142.645614624023,49.5961151123047,0],[149.771423339844,49.9755706787109,0],[151.354949951172,50.0797424316406,0],[150.563201904297,50.0268516540527,0],[152.938461303711,50.191967010498,0],[154.52197265625,50.3126983642578,0],[153.730224609375,50.2508506774902,0],[152.146697998047,50.1347274780273,0],[156.105499267578,50.4423942565918,0],[157.688995361328,50.5815124511719,0],[156.897247314453,50.5097312927246,0],[159.272521972656,50.7305374145508,0],[160.592132568359,50.8085174560547,0],[159.800354003906,50.7305374145508,0],[158.480773925781,50.6540451049805,0],[155.313751220703,50.3756790161133,0],[148.979675292969,49.9267845153809,0],[136.311553955078,49.3580627441406,0],[110.975311279297,48.94873046875,0],[162.175628662109,50.9736328125,0],[163.759155273438,51.1498680114746,0],[162.967391967773,51.060173034668,0],[165.342666625977,51.3376998901367,0],[166.926177978516,51.5375938415527,0],[166.134429931641,51.435115814209,0],[164.550903320312,51.2417411804199,0],[168.245788574219,51.6409111022949,0],[169.829284667969,51.860179901123,0],[169.037536621094,51.7500228881836,0],[171.412811279297,52.0926933288574,0],[172.996322631836,52.3388900756836,0],[172.204559326172,52.2142906188965,0],[170.621063232422,51.9754409790039,0],[167.71794128418,51.6409111022949,0],[174.31591796875,52.4670104980469,0],[175.899444580078,52.7340087890625,0],[175.107666015625,52.5991821289062,0],[177.482955932617,53.0156860351562,0],[178.802536010742,53.1636734008789,0],[178.010787963867,53.0156860351562,0],[176.691192626953,52.8739852905273,0],[180.386077880859,53.4685974121094,0],[181.705657958984,53.6258544921875,0],[181.177825927734,53.6258544921875,0],[183.289169311523,53.9547653198242,0],[184.608764648438,54.1254425048828,0],[184.080917358398,54.1254425048828,0],[182.497421264648,53.7890892028809,0],[179.594284057617,53.3126792907715,0],[173.524169921875,52.3388900756836,0],[186.192260742188,54.4779167175293,0],[187.51188659668,54.6608581542969,0],[186.984039306641,54.6608581542969,0],[189.09538269043,55.0384826660156,0],[190.414978027344,55.2320709228516,0],[189.887145996094,55.2320709228516,0],[188.303634643555,54.8467330932617,0],[191.998504638672,55.6344604492188,0],[193.318099975586,55.843635559082,0],[192.526336669922,55.6344604492188,0],[194.901611328125,56.2713241577148,0],[196.22119140625,56.4909782409668,0],[195.429443359375,56.2713241577148,0],[194.109848022461,56.0543327331543,0],[191.206726074219,55.4327049255371,0],[197.540802001953,56.7157897949219,0],[199.124313354492,57.1769714355469,0],[198.332565307617,56.9443740844727,0],[200.443908691406,57.4144287109375,0],[201.763519287109,57.6547660827637,0],[201.235687255859,57.6547660827637,0],[199.652145385742,57.1769714355469,0],[203.347030639648,58.148998260498,0],[204.666610717773,58.4039154052734,0],[203.874862670898,58.148998260498,0],[205.986206054688,58.6599197387695,0],[207.305816650391,58.9228668212891,0],[206.777984619141,58.9228668212891,0],[205.458374023438,58.6599197387695,0],[202.555267333984,57.9010124206543,0],[197.012969970703,56.7157897949219,0],[185.400512695312,54.299690246582,0],[208.88932800293,59.4575424194336,0],[210.208923339844,59.7302474975586,0],[209.41716003418,59.4575424194336,0],[211.528503417969,60.0075302124023,0],[212.848114013672,60.2882308959961,0],[212.320281982422,60.2882308959961,0],[211.000671386719,60.0075302124023,0],[214.431625366211,60.8607788085938,0],[215.751220703125,61.1515502929688,0],[214.95947265625,60.8607788085938,0],[217.070831298828,61.447322845459,0],[218.390411376953,61.7444458007812,0],[217.862579345703,61.7444458007812,0],[216.279052734375,61.1515502929688,0],[213.639862060547,60.572380065918,0],[219.710006713867,62.0472221374512,0],[221.293548583984,62.6597595214844,0],[220.501754760742,62.3508415222168,0],[222.613128662109,62.9698715209961,0],[223.932723999023,63.2841796875,0],[223.140960693359,62.9698715209961,0],[221.821380615234,62.6597595214844,0],[225.252319335938,63.6003112792969,0],[226.571899414062,63.9196281433105,0],[226.044067382812,63.9196281433105,0],[228.15544128418,64.5652160644531,0],[229.475021362305,64.8918762207031,0],[228.68327331543,64.5652160644531,0],[227.363647460938,64.2412948608398,0],[224.724472045898,63.6003112792969,0],[219.182174682617,62.0472221374512,0],[230.794616699219,65.2199783325195,0],[232.114227294922,65.5510559082031,0],[231.322448730469,65.2199783325195,0],[233.433807373047,65.8828887939453,0],[234.753402709961,66.2177810668945,0],[234.225570678711,66.2177810668945,0],[232.905975341797,65.8828887939453,0],[236.3369140625,66.8909454345703,0],[237.656524658203,67.2293014526367,0],[236.864776611328,66.8909454345703,0],[238.976119995117,67.5693817138672,0],[240.295700073242,67.9101104736328,0],[239.503952026367,67.5693817138672,0],[238.184356689453,67.2293014526367,0],[235.545166015625,66.5531005859375,0],[241.615295410156,68.2518920898438,0],[242.934906005859,68.5942840576172,0],[242.407073974609,68.5942840576172,0],[244.518417358398,69.2805709838867,0],[245.838012695312,69.6241073608398,0],[245.046249389648,69.2805709838867,0],[243.726654052734,68.9372253417969,0],[247.157592773438,69.967658996582,0],[248.477203369141,70.3112106323242,0],[247.949371337891,70.3112106323242,0],[250.06071472168,70.9970703125,0],[251.380310058594,71.3388824462891,0],[250.58854675293,70.9970703125,0],[249.268966674805,70.6542129516602,0],[246.365844726562,69.6241073608398,0],[241.087463378906,68.2518920898438,0],[230.002868652344,64.8918762207031,0],[208.097579956055,59.187328338623,0],[161.383880615234,50.8899307250977,0],[61.3585166931152,48.8672904968262,0],[62.9420280456543,48.8676414489746,0],[62.1502685546875,48.8674583435059,0],[64.5255432128906,48.868049621582,0],[66.1090621948242,48.8685264587402,0],[65.3173065185547,48.868278503418,0],[63.7337875366211,48.8678398132324,0],[67.6925659179688,48.8690757751465,0],[69.2760925292969,48.8697204589844,0],[68.4843368530273,48.869384765625,0],[70.8596038818359,48.8704643249512,0],[72.443115234375,48.8713188171387,0],[71.6513595581055,48.8708763122559,0],[70.0678405761719,48.8700790405273,0],[66.9008178710938,48.8687896728516,0],[74.0266342163086,48.8723068237305,0],[75.6101531982422,48.8734512329102,0],[74.8183898925781,48.872859954834,0],[77.1936645507812,48.8747673034668,0],[78.7771835327148,48.8762817382812,0],[77.9854125976562,48.8754997253418,0],[76.4019088745117,48.8740844726562,0],[80.3606872558594,48.8780212402344,0],[81.9442138671875,48.8800201416016,0],[81.1524505615234,48.8789901733398,0],[83.5277252197266,48.8823051452637,0],[85.1112365722656,48.8849105834961,0],[84.3194808959961,48.8835563659668,0],[82.7359619140625,48.8811187744141,0],[79.5689392089844,48.8771209716797,0],[73.2348785400391,48.8717956542969,0],[86.6947555541992,48.8878936767578,0],[88.2782592773438,48.8913078308105,0],[87.4865112304688,48.8895492553711,0],[89.8617858886719,48.8951950073242,0],[91.4452972412109,48.8996086120605,0],[90.6535339355469,48.897331237793,0],[89.0700302124023,48.8931884765625,0],[93.02880859375,48.9046173095703,0],[94.6123275756836,48.9103012084961,0],[93.8205795288086,48.9073753356934,0],[96.1958465576172,48.916748046875,0],[97.7793579101562,48.9240531921387,0],[96.9876022338867,48.9202842712402,0],[95.4040832519531,48.9134292602539,0],[92.237060546875,48.9020385742188,0],[99.3628768920898,48.9323043823242,0],[100.946380615234,48.9416007995605,0],[100.154632568359,48.9368057250977,0],[102.529907226562,48.9520797729492,0],[104.113426208496,48.9638519287109,0],[103.321655273438,48.9577789306641,0],[101.738143920898,48.9466781616211,0],[105.696929931641,48.9770774841309,0],[107.280448913574,48.9919395446777,0],[106.488693237305,48.9842948913574,0],[108.863967895508,49.0086059570312,0],[110.447479248047,49.0272445678711,0],[109.655723571777,49.0176811218262,0],[108.072204589844,49.0000534057617,0],[104.905174255371,48.9702606201172,0],[98.5711212158203,48.9280471801758,0],[85.9029998779297,48.8863525390625,0],[112.03099822998,49.0480613708496,0],[113.614501953125,49.0712738037109,0],[112.82275390625,49.0593795776367,0],[115.198020935059,49.0971221923828,0],[116.781539916992,49.1259460449219,0],[115.989776611328,49.1111450195312,0],[114.406272888184,49.0838851928711,0],[118.365051269531,49.1579971313477,0],[119.948570251465,49.1935386657715,0],[119.156814575195,49.1752853393555,0],[121.532073974609,49.2329025268555,0],[123.115600585938,49.276439666748,0],[122.323844909668,49.2540893554688,0],[120.740325927734,49.2126884460449,0],[117.573295593262,49.1415328979492,0],[124.699119567871,49.3245239257812,0],[126.282623291016,49.3775482177734,0],[125.490867614746,49.350341796875,0],[127.866149902344,49.436107635498,0],[129.449645996094,49.5005493164062,0],[128.657897949219,49.4676132202148,0],[127.07438659668,49.4061508178711,0],[131.033172607422,49.5713272094727,0],[132.616683959961,49.6489562988281,0],[131.824935913086,49.6093139648438,0],[134.2001953125,49.7339782714844,0],[135.783721923828,49.8269653320312,0],[134.991973876953,49.7795219421387,0],[133.408447265625,49.6905784606934,0],[130.241424560547,49.5351676940918,0],[123.907348632812,49.2998466491699,0],[137.367233276367,49.9288139343262,0],[138.950744628906,50.0399284362793,0],[138.158996582031,49.9831047058105,0],[140.534271240234,50.160945892334,0],[142.117782592773,50.2925682067871,0],[141.326019287109,50.2252922058105,0],[139.742492675781,50.0990715026855,0],[143.701293945312,50.4355239868164,0],[145.284820556641,50.5905570983887,0],[144.493041992188,50.5113639831543,0],[146.868316650391,50.7584648132324,0],[148.451843261719,50.9405212402344,0],[147.660079956055,50.8478317260742,0],[146.076568603516,50.672721862793,0],[142.909530639648,50.3624801635742,0],[150.035339355469,51.1371421813965,0],[151.618865966797,51.3491821289062,0],[150.827117919922,51.2413139343262,0],[153.202377319336,51.5775375366211,0],[154.785888671875,51.8230972290039,0],[153.994140625,51.6982688903809,0],[152.410629272461,51.4614105224609,0],[156.369415283203,52.0868453979492,0],[157.952926635742,52.3702774047852,0],[157.161163330078,52.2259635925293,0],[159.800354003906,52.6737747192383,0],[161.383880615234,52.9982833862305,0],[160.592132568359,52.8331680297852,0],[158.744689941406,52.5192985534668,0],[155.577667236328,51.9527893066406,0],[149.243591308594,51.0370750427246,0],[136.575469970703,49.8767318725586,0],[111.239227294922,49.0373840332031,0],[162.967391967773,53.3447647094727,0],[164.550903320312,53.7141647338867,0],[163.759155273438,53.5263290405273,0],[166.134429931641,54.1074295043945,0],[167.981857299805,54.5256500244141,0],[166.926177978516,54.3132247924805,0],[165.342651367188,53.9075317382812,0],[169.565368652344,54.9703369140625,0],[171.148895263672,55.4417037963867,0],[170.357131958008,55.2028503417969,0],[172.996322631836,55.9406204223633,0],[174.579833984375,56.4679183959961,0],[173.7880859375,56.2009124755859,0],[171.940643310547,55.6878967285156,0],[168.773620605469,54.7449188232422,0],[176.163360595703,57.0243911743164,0],[178.010787963867,57.6110687255859,0],[177.219024658203,57.3140716552734,0],[179.594299316406,58.2291679382324,0],[181.441741943359,58.8785705566406,0],[180.649993896484,58.5496635437012,0],[178.802551269531,57.9159965515137,0],[183.289169311523,59.5598526000977,0],[184.872680664062,60.2734985351562,0],[184.080932617188,59.9123229980469,0],[186.720123291016,61.0199356079102,0],[188.56755065918,61.7994956970215,0],[187.511871337891,61.4052734375,0],[185.928375244141,60.6423149108887,0],[182.233489990234,59.2149276733398,0],[175.37158203125,56.7427139282227,0],[190.414978027344,62.6128158569336,0],[191.998504638672,63.4603729248047,0],[191.206756591797,63.0326843261719,0],[193.845932006836,64.3414916992188,0],[195.693359375,65.2560577392578,0],[194.901611328125,64.7948837280273,0],[193.054183959961,63.8970260620117,0],[197.540817260742,66.2039184570312,0],[199.388229370117,67.1847305297852,0],[198.596481323242,66.6904983520508,0],[201.235687255859,68.1985549926758,0],[203.347030639648,69.2449188232422,0],[202.291351318359,68.7175064086914,0],[200.443908691406,67.6876373291016,0],[196.749053955078,65.7261199951172,0],[205.194458007812,70.3225021362305,0],[207.041900634766,71.4304809570312,0],[205.986206054688,70.8724899291992,0],[208.88932800293,72.5678787231445,0],[211.000671386719,73.7335968017578,0],[209.945007324219,73.1470489501953,0],[208.097579956055,71.9953308105469,0],[212.848114013672,74.9263916015625,0],[214.695556640625,76.1453170776367,0],[213.903793334961,75.5327758789062,0],[216.806884765625,77.3887634277344,0],[218.654342651367,78.6546630859375,0],[217.598663330078,78.0192184448242,0],[215.751220703125,76.7643585205078,0],[211.792449951172,74.3264923095703,0],[204.138778686523,69.7795867919922,0],[189.359298706055,62.2018852233887,0],[220.501754760742,79.9412384033203,0],[222.613128662109,81.2465667724609,0],[221.557464599609,80.5918121337891,0],[224.460556030273,82.5686569213867,0],[226.571899414062,83.9056015014648,0],[225.516235351562,83.2353820800781,0],[223.668807983398,81.9057464599609,0],[228.419357299805,85.2549667358398,0],[231.322448730469,87.2967147827148,0],[230.530700683594,86.6142120361328,0],[233.433807373047,88.6662445068359,0],[235.28125,90.0393905639648,0],[234.225570678711,89.3525238037109,0],[232.378143310547,87.9808959960938,0],[227.363647460938,84.5787658691406,0],[238.976119995117,92.786003112793,0],[240.031784057617,93.4706649780273,0],[238.184356689453,92.1001434326172,0],[241.087463378906,94.1538543701172,0],[242.934906005859,95.5143966674805,0],[241.879211425781,94.8352584838867,0],[237.128662109375,91.4135894775391,0],[245.574096679688,97.5355834960938,0],[246.629760742188,98.2024765014648,0],[244.782348632812,96.8648681640625,0],[248.213287353516,99.5244445800781,0],[247.421539306641,98.8657684326172,0],[249.268966674805,100.178924560547,0],[243.726654052734,96.191162109375,0],[236.3369140625,90.7264862060547,0],[229.475021362305,85.9334030151367,0],[251.908142089844,102.10986328125,0],[253.491683959961,103.367576599121,0],[254.547348022461,103.986389160156,0],[256.130859375,105.203201293945,0],[256.922607421875,105.800643920898,0],[255.339096069336,104.598686218262,0],[252.699920654297,102.74169921875,0],[260.881408691406,108.66162109375,0],[258.506164550781,106.970970153809,0],[257.71435546875,106.389610290527,0],[260.089660644531,108.107299804688,0],[269.062927246094,143.108795166016,0],[269.590759277344,143.644134521484,0],[259.297912597656,107.543197631836,0],[251.11637878418,101.471702575684,0],[270.382507324219,146.275421142578,0],[270.646423339844,146.870483398438,0],[270.118560791016,145.667083740234,0],[270.910339355469,147.452423095703,0],[271.174255371094,148.019683837891,0],[271.702087402344,149.112030029297,0],[269.590759277344,144.412261962891,0],[257.978271484375,147.638854980469,0],[259.561828613281,148.842147827148,0],[271.966003417969,149.932662963867,0],[273.285614013672,152.0205078125,0],[273.285583496094,152.521697998047,0],[272.493835449219,150.915222167969,0],[271.174255371094,148.674713134766,0],[269.854675292969,145.045684814453,0],[250.06071472168,100.828025817871,0],[219.710006713867,79.2956466674805,0],[272.757751464844,151.656356811523,0],[162.175628662109,53.168529510498,0],[251.908172607422,71.3388824462891,0],[253.491668701172,72.0202865600586,0],[254.811264038086,72.3593902587891,0],[254.019500732422,72.0202865600586,0],[256.130859375,72.6970520019531,0],[257.71435546875,73.3677673339844,0],[256.922607421875,73.0330963134766,0],[255.603012084961,72.6970520019531,0],[259.033996582031,73.6999893188477,0],[260.617492675781,74.3586730957031,0],[259.825744628906,74.0310592651367,0],[261.937103271484,74.6855392456055,0],[263.256683349609,75.0077667236328,0],[262.728851318359,75.0077667236328,0],[261.145324707031,74.3586730957031,0],[258.2421875,73.3677673339844,0],[264.840209960938,75.6459197998047,0],[266.423706054688,76.2717895507812,0],[265.631958007812,75.961067199707,0],[267.743286132812,76.5798873901367,0],[269.326812744141,77.1844024658203,0],[268.535034179688,76.8840789794922,0],[266.951538085938,76.2717895507812,0],[270.910339355469,77.7733688354492,0],[272.493865966797,78.3455963134766,0],[271.702117919922,78.0628814697266,0],[274.077362060547,78.8999176025391,0],[295.190887451172,82.6429824829102,0],[281.994934082031,112.677612304688,0],[273.285614013672,78.6269836425781,0],[270.118560791016,77.4815216064453,0],[264.048431396484,75.3292236328125,0],[297.038330078125,82.2614898681641,0],[298.621826171875,82.0007476806641,0],[297.830078125,82.1315765380859,0],[300.205383300781,81.7362823486328,0],[301.788879394531,81.4690780639648,0],[300.997131347656,81.6030807495117,0],[299.413635253906,81.8689727783203,0],[303.372375488281,81.2000503540039,0],[304.955902099609,80.9301300048828,0],[304.164154052734,81.0651931762695,0],[306.539428710938,80.6601791381836,0],[307.859008789062,80.5254516601562,0],[307.067260742188,80.6601791381836,0],[305.747650146484,80.7950897216797,0],[302.580627441406,81.334846496582,0],[309.442535400391,80.2571182250977,0],[311.026062011719,79.9908752441406,0],[310.234313964844,80.1236038208008,0],[312.345642089844,79.8585815429688,0],[313.929168701172,79.5967559814453,0],[313.137390136719,79.7275085449219,0],[311.553894042969,79.9908752441406,0],[315.248748779297,79.4677352905273,0],[316.832275390625,79.2122573852539,0],[316.040496826172,79.3390121459961,0],[318.15185546875,79.0860595703125,0],[319.735382080078,78.8384094238281,0],[318.943634033203,78.9617309570312,0],[317.6240234375,79.0860595703125,0],[314.457000732422,79.5967559814453,0],[308.650756835938,80.3910675048828,0],[296.24658203125,82.3899078369141,0],[321.054962158203,78.7167816162109,0],[322.638488769531,78.4779891967773,0],[321.846740722656,78.5966720581055,0],[323.958099365234,78.3614044189453,0],[325.277679443359,78.2458953857422,0],[324.749847412109,78.2458953857422,0],[323.166351318359,78.4779891967773,0],[326.861206054688,78.02099609375,0],[328.180786132812,77.9122772216797,0],[327.389038085938,78.02099609375,0],[329.500366210938,77.8041076660156,0],[331.083923339844,77.5955352783203,0],[330.292114257812,77.699348449707,0],[328.972534179688,77.8041076660156,0],[326.069458007812,78.1331100463867,0],[332.403503417969,77.4947128295898,0],[333.986999511719,77.2987213134766,0],[333.195251464844,77.3954620361328,0],[335.306610107422,77.2042083740234,0],[336.626220703125,77.1116943359375,0],[336.098358154297,77.1116943359375,0],[334.514831542969,77.2987213134766,0],[338.209716796875,76.9338836669922,0],[339.529296875,76.8493041992188,0],[338.737548828125,76.9338836669922,0],[340.848907470703,76.7655334472656,0],[342.432434082031,76.607292175293,0],[341.640686035156,76.6860809326172,0],[340.321075439453,76.7655334472656,0],[337.41796875,77.0220794677734,0],[331.875671386719,77.4947128295898,0],[343.752014160156,76.5325775146484,0],[345.071624755859,76.4590148925781,0],[344.543792724609,76.4590148925781,0],[346.655120849609,76.3206024169922,0],[347.974700927734,76.2551040649414,0],[347.182952880859,76.3206024169922,0],[345.863372802734,76.3888931274414,0],[349.294311523438,76.1921081542969,0],[350.877868652344,76.0735244750977,0],[350.086059570312,76.131233215332,0],[352.197448730469,76.0172576904297,0],[353.517028808594,75.9648056030273,0],[352.989196777344,75.9648056030273,0],[351.405700683594,76.0735244750977,0],[348.766479492188,76.1921081542969,0],[355.100555419922,75.8658599853516,0],[356.420135498047,75.8192443847656,0],[355.628387451172,75.8658599853516,0],[357.73974609375,75.7765655517578,0],[359.3232421875,75.6967468261719,0],[358.531494140625,75.7350463867188,0],[357.211883544922,75.7765655517578,0],[360.642822265625,75.6601867675781,0],[362.226379394531,75.5944519042969,0],[361.4345703125,75.6261749267578,0],[363.545959472656,75.5645904541016,0],[364.865570068359,75.5375366210938,0],[364.337738037109,75.5375366210938,0],[362.754211425781,75.5944519042969,0],[360.114990234375,75.6601867675781,0],[354.308776855469,75.9131240844727,0],[342.960266113281,76.607292175293,0],[320.263214111328,78.8384094238281,0],[366.449066162109,75.4891204833984,0],[367.768646240234,75.4671478271484,0],[367.240814208984,75.4671478271484,0],[369.352172851562,75.431037902832,0],[370.671752929688,75.4162902832031,0],[369.880004882812,75.431037902832,0],[368.560394287109,75.4488372802734,0],[372.255310058594,75.3910369873047,0],[373.574890136719,75.3809127807617,0],[372.783142089844,75.3910369873047,0],[375.158416748047,75.3658905029297,0],[376.477996826172,75.3604507446289,0],[375.950164794922,75.3604507446289,0],[374.366638183594,75.3725891113281,0],[371.463500976562,75.402458190918,0],[378.061492919922,75.3540725708008,0],[379.64501953125,75.3528823852539,0],[378.853271484375,75.3533020019531,0],[380.964599609375,75.3545837402344,0],[382.548156738281,75.3600921630859,0],[381.756408691406,75.3565444946289,0],[380.1728515625,75.3528823852539,0],[384.131683349609,75.3691864013672,0],[385.451263427734,75.3748474121094,0],[384.659515380859,75.3691864013672,0],[387.034759521484,75.3881530761719,0],[388.618286132812,75.4033203125,0],[387.826507568359,75.3954925537109,0],[386.243011474609,75.381217956543,0],[383.339904785156,75.3640823364258,0],[377.269744873047,75.3568801879883,0],[390.201782226562,75.4196319580078,0],[391.785339355469,75.4363708496094,0],[390.993530273438,75.427978515625,0],[393.368835449219,75.4528121948242,0],[394.952331542969,75.4682159423828,0],[394.160583496094,75.4607238769531,0],[392.577087402344,75.444709777832,0],[396.535858154297,75.4818572998047,0],[398.38330078125,75.4971542358398,0],[397.327606201172,75.4876861572266,0],[399.966796875,75.5029754638672,0],[401.814208984375,75.5036773681641,0],[401.0224609375,75.5044403076172,0],[399.175048828125,75.5009002685547,0],[395.744079589844,75.4752960205078,0],[403.661682128906,75.4914474487305,0],[405.509124755859,75.4648284912109,0],[404.453460693359,75.484375,0],[407.356536865234,75.4220428466797,0],[409.203948974609,75.3590240478516,0],[408.148284912109,75.4027633666992,0],[406.300872802734,75.4526977539062,0],[411.315368652344,75.2433471679688,0],[413.426696777344,75.0866928100586,0],[412.371032714844,75.1703720092773,0],[415.274108886719,74.9389801025391,0],[417.649383544922,74.6350631713867,0],[416.593719482422,74.7662658691406,0],[414.218444824219,75.0399169921875,0],[410.259643554688,75.3060607910156,0],[402.606018066406,75.5008239746094,0],[389.410034179688,75.4113235473633,0],[419.7607421875,74.3350982666016,0],[421.8720703125,73.9839019775391,0],[420.81640625,74.1659698486328,0],[423.983459472656,73.5806579589844,0],[425.830902099609,73.2439117431641,0],[425.039154052734,73.3594741821289,0],[422.927734375,73.7888107299805,0],[427.942230224609,72.7489395141602,0],[429.525726318359,72.4823837280273,0],[428.733978271484,72.6183853149414,0],[431.373168945312,72.0599594116211,0],[433.220642089844,71.6089782714844,0],[432.164916992188,71.9121398925781,0],[430.581420898438,72.203369140625,0],[426.886566162109,73.0028381347656,0],[434.804138183594,71.294189453125,0],[436.651580810547,70.8001937866211,0],[435.595916748047,71.1320724487305,0],[438.235076904297,70.4576644897461,0],[439.818603515625,70.1049194335938,0],[439.026824951172,70.2834167480469,0],[437.443328857422,70.631217956543,0],[441.402099609375,69.7424392700195,0],[442.985595703125,69.3707046508789,0],[442.19384765625,69.5578918457031,0],[444.569152832031,68.990234375,0],[446.152679443359,68.6015777587891,0],[445.360900878906,68.7965393066406,0],[443.77734375,69.1814270019531,0],[440.6103515625,69.9253921508789,0],[434.012390136719,71.4529037475586,0],[447.736175537109,68.2052917480469,0],[449.319671630859,67.8016662597656,0],[448.527923583984,68.0037078857422,0],[450.903198242188,67.3915252685547,0],[452.222778320312,67.1840667724609,0],[451.694946289062,67.1840667724609,0],[450.111450195312,67.5969314575195,0],[453.542358398438,66.9756393432617,0],[454.598083496094,66.9756393432617,0],[454.070251464844,66.9756393432617,0],[455.653747558594,66.9756393432617,0],[456.709411621094,66.9756393432617,0],[456.181579589844,66.9756393432617,0],[455.125915527344,66.9756393432617,0],[453.014526367188,66.9756393432617,0],[457.765106201172,66.9756393432617,0],[458.820770263672,66.9756393432617,0],[458.292938232422,66.9756393432617,0],[459.876434326172,66.9756393432617,0],[460.93212890625,66.9756393432617,0],[460.404266357422,66.9756393432617,0],[459.348602294922,66.9756393432617,0],[461.98779296875,66.9756393432617,0],[463.04345703125,66.9756393432617,0],[462.515625,66.9756393432617,0],[464.099182128906,66.9756393432617,0],[465.154846191406,66.9756393432617,0],[464.627014160156,66.9756393432617,0],[463.5712890625,66.9756393432617,0],[461.4599609375,66.9756393432617,0],[457.237274169922,66.9756393432617,0],[446.944427490234,68.4037704467773,0],[418.705078125,74.4914093017578,0],[365.657318115234,75.5116958618164,0],[322.638488769531,109.941467285156,0],[324.222015380859,109.433029174805,0],[323.430267333984,109.685989379883,0],[319.20751953125,110.984176635742,0],[320.791076660156,110.458976745605,0],[319.999328613281,110.720809936523,0],[321.846740722656,110.199203491211,0],[329.764343261719,107.974105834961,0],[331.611755371094,107.513717651367,0],[330.556091308594,107.742004394531,0],[326.069458007812,108.934860229492,0],[327.916870117188,108.448173522949,0],[327.125122070312,108.689910888672,0],[328.708618164062,108.209373474121,0],[325.277679443359,109.182510375977,0],[309.970397949219,113.93864440918,0],[310.762145996094,113.669616699219,0],[309.178588867188,114.206871032715,0],[306.803344726562,115.004440307617,0],[307.595092773438,114.739974975586,0],[308.386840820312,114.474082946777,0],[311.553894042969,113.399963378906,0],[315.776611328125,112.051231384277,0],[317.360107421875,111.515441894531,0],[316.568359375,111.782897949219,0],[312.345642089844,113.13005065918,0],[313.929168701172,112.589988708496,0],[313.137390136719,112.859939575195,0],[314.984832763672,112.320358276367,0],[306.011596679688,115.267028808594,0],[318.15185546875,111.249198913574,0],[352.725280761719,103.458053588867,0],[354.572723388672,103.225509643555,0],[353.517028808594,103.339477539062,0],[347.974731445312,104.126304626465,0],[349.822204589844,103.844223022461,0],[349.030395507812,103.982627868652,0],[350.877868652344,103.710433959961,0],[360.114990234375,102.646324157715,0],[361.698486328125,102.491653442383,0],[360.90673828125,102.566513061523,0],[356.420135498047,103.012649536133,0],[358.267578125,102.81982421875,0],[357.211883544922,102.913696289062,0],[359.059326171875,102.730529785156,0],[355.364471435547,103.11678314209,0],[336.89013671875,106.224960327148,0],[338.737548828125,105.828903198242,0],[337.94580078125,106.024887084961,0],[333.459167480469,107.067993164062,0],[335.306610107422,106.638168334961,0],[334.250946044922,106.851097106934,0],[336.098358154297,106.429595947266,0],[344.279876708984,104.749557495117,0],[346.127288818359,104.428092956543,0],[345.335540771484,104.586326599121,0],[340.585021972656,105.450622558594,0],[342.432434082031,105.090682983398,0],[341.640686035156,105.268486022949,0],[343.488098144531,104.917907714844,0],[339.793243408203,105.637657165527,0],[347.182952880859,104.27458190918,0],[332.403503417969,107.288818359375,0],[282.258850097656,156.351959228516,0],[265.104125976562,152.460083007812,0],[275.396942138672,155.126800537109,0],[266.687622070312,153.319412231445,0],[268.271148681641,154.100173950195,0],[275.924774169922,155.663299560547,0],[274.869110107422,154.518188476562,0],[277.244384765625,156.590454101562,0],[271.438171386719,155.422164916992,0],[269.854675292969,154.800521850586,0],[273.813446044922,156.207458496094,0],[273.285583496094,156.039123535156,0],[276.45263671875,156.126815795898,0],[275.39697265625,156.633316040039,0],[274.341278076172,153.838516235352,0],[276.98046875,156.98258972168,0],[278.563995361328,157.256225585938,0],[278.300048828125,157.161956787109,0],[280.147521972656,157.454406738281,0],[279.355743408203,157.344024658203,0],[281.731018066406,157.580184936523,0],[279.883575439453,157.324996948242,0],[280.675354003906,157.227905273438,0],[287.273315429688,157.476303100586,0],[285.689819335938,157.589202880859,0],[283.578460693359,157.629745483398,0],[284.106292724609,157.636825561523,0],[277.772216796875,156.959930419922,0],[281.203186035156,156.96012878418,0],[281.731018066406,156.690063476562,0],[273.813446044922,153.319808959961,0],[287.537231445312,150.007690429688,0],[287.801147460938,149.547454833984,0],[287.273315429688,150.457946777344,0],[286.481536865234,151.738006591797,0],[286.481567382812,151.100921630859,0],[287.009399414062,150.895690917969,0],[288.065063476562,149.076904296875,0],[289.384674072266,147.362350463867,0],[303.108459472656,116.295227050781,0],[289.384704589844,146.580230712891,0],[288.328979492188,148.595687866211,0],[288.856842041016,147.605651855469,0],[288.592926025391,148.106262207031,0],[303.636322021484,116.04216003418,0],[285.953704833984,151.931137084961,0],[283.314544677734,155.478286743164,0],[283.842376708984,154.727020263672,0],[292.023864746094,156.768081665039,0],[283.578430175781,155.011291503906,0],[290.440368652344,157.062927246094,0],[282.786682128906,155.947418212891,0],[288.856842041016,157.300262451172,0],[299.149658203125,154.804428100586,0],[284.898040771484,153.961486816406,0],[284.370208740234,154.111999511719,0],[284.106292724609,154.426773071289,0],[273.549530029297,152.929962158203,0],[297.566162109375,155.322998046875,0],[285.161956787109,153.353561401367,0],[285.689788818359,152.618759155273,0],[304.428100585938,115.786117553711,0],[305.219818115234,115.527770996094,0],[351.669616699219,103.581932067871,0],[427.150482177734,98.8127288818359,0],[427.942230224609,98.6106796264648,0],[426.622650146484,99.0078277587891,0],[428.470062255859,98.4025268554688,0],[425.303070068359,99.3784027099609,0],[425.830902099609,99.1963348388672,0],[424.511291503906,99.5535507202148,0],[432.692810058594,97.0157699584961,0],[431.901000976562,97.2628402709961,0],[430.581420898438,97.7380981445312,0],[429.261810302734,98.1874237060547,0],[429.789672851562,97.9662322998047,0],[431.373168945312,97.5039215087891,0],[434.012390136719,96.5020370483398,0],[423.983459472656,99.7226791381836,0],[416.857635498047,101.166519165039,0],[418.177215576172,100.958976745605,0],[417.385467529297,101.065574645996,0],[413.954528808594,101.513236999512,0],[416.065887451172,101.261322021484,0],[415.274108886719,101.350914001465,0],[414.746276855469,101.434593200684,0],[421.8720703125,100.190780639648,0],[422.663818359375,100.041244506836,0],[421.34423828125,100.334434509277,0],[419.232879638672,100.727310180664,0],[420.024658203125,100.60262298584,0],[420.552490234375,100.471420288086,0],[418.705047607422,100.846313476562,0],[423.191711425781,99.8849411010742,0],[433.220642089844,96.7618713378906,0],[449.847503662109,89.6868515014648,0],[451.431030273438,88.9214935302734,0],[449.055755615234,90.0633163452148,0],[446.680511474609,91.1650390625,0],[447.472259521484,90.8025512695312,0],[448.264007568359,90.4350509643555,0],[450.639282226562,89.3063812255859,0],[456.181579589844,86.533317565918,0],[455.389831542969,86.9400863647461,0],[453.806335449219,87.7437744140625,0],[453.014587402344,88.1400680541992,0],[452.222778320312,88.5328369140625,0],[454.598083496094,87.3437118530273,0],[456.973358154297,86.1231689453125,0],[445.888732910156,91.523063659668,0],[437.707244873047,95.1068115234375,0],[438.498992919922,94.8091735839844,0],[436.123718261719,95.6836395263672,0],[435.595886230469,95.962646484375,0],[434.804138183594,96.2354888916016,0],[436.915496826172,95.3980560302734,0],[439.02685546875,94.5060043334961,0],[441.402099609375,93.5609893798828,0],[445.096984863281,91.8757934570312,0],[443.513488769531,92.5661239624023,0],[439.818603515625,94.1965942382812,0],[442.19384765625,93.2349472045898,0],[440.6103515625,93.8818206787109,0],[442.721740722656,92.9030609130859,0],[444.305236816406,92.2235946655273,0],[457.765106201172,85.7103118896484,0],[413.426696777344,101.586204528809,0],[377.797576904297,101.845664978027,0],[379.381103515625,101.84090423584,0],[378.58935546875,101.842102050781,0],[374.366638183594,101.888229370117,0],[375.950164794922,101.861068725586,0],[375.158386230469,101.873199462891,0],[377.005828857422,101.85205078125,0],[381.228515625,101.845848083496,0],[382.812072753906,101.85888671875,0],[382.020324707031,101.851364135742,0],[384.659515380859,101.878746032715,0],[386.243011474609,101.904098510742,0],[385.451263427734,101.89079284668,0],[383.603851318359,101.867980957031,0],[380.436767578125,101.842185974121,0],[367.240814208984,102.135528564453,0],[369.088256835938,102.050704956055,0],[368.032592773438,102.09098815918,0],[363.545959472656,102.355339050293,0],[365.393402099609,102.236839294434,0],[364.601654052734,102.293754577637,0],[366.449066162109,102.183944702148,0],[372.519226074219,101.928207397461,0],[387.826507568359,101.933532714844,0],[370.935668945312,101.982040405273,0],[389.410034179688,101.965667724609,0],[388.618255615234,101.949363708496,0],[371.727416992188,101.953460693359,0],[369.880004882812,102.014587402344,0],[387.034759521484,101.918380737305,0],[373.574890136719,101.906661987305,0],[391.785278320312,102.01579284668,0],[393.368835449219,102.048263549805,0],[392.577087402344,102.032249450684,0],[390.993530273438,101.999069213867,0],[394.160583496094,102.063659667969,0],[407.356536865234,102.025253295898,0],[406.564788818359,102.05224609375,0],[405.773040771484,102.075180053711,0],[411.315307617188,101.775131225586,0],[412.107116699219,101.717041015625,0],[410.787475585938,101.828086853027,0],[407.884368896484,101.994590759277,0],[409.467895507812,101.920394897461,0],[409.995727539062,101.876647949219,0],[408.676147460938,101.959533691406,0],[390.201782226562,101.982322692871,0],[396.535858154297,102.104263305664,0],[397.855438232422,102.124870300293,0],[395.744079589844,102.09188079834,0],[397.327606201172,102.11540222168,0],[398.647216796875,102.132774353027,0],[399.43896484375,102.138595581055,0],[394.952331542969,102.078231811523,0],[403.661682128906,102.123275756836,0],[404.453460693359,102.110534667969,0],[403.133850097656,102.13264465332,0],[400.230712890625,102.142478942871,0],[401.55029296875,102.142822265625,0],[402.342102050781,102.139221191406,0],[400.758544921875,102.143943786621,0],[405.245208740234,102.094711303711,0],[412.634948730469,101.654319763184,0],[362.754211425781,102.421081542969,0],[458.820770263672,85.2944183349609,0],[252.699920654297,71.6802520751953,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;188&#34;:{&#34;id&#34;:188,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.5,-2.5]},&#34;vertices&#34;:[[60.8306732177734,48.8681716918945,0],[61.6224327087402,48.8684158325195,0],[62.4141883850098,48.8686752319336,0],[63.2059478759766,48.8689651489258,0],[63.9977035522461,48.8692626953125,0],[64.7894592285156,48.8696022033691,0],[65.5812225341797,48.8699493408203,0],[66.3729782104492,48.8703422546387,0],[67.1647338867188,48.8707466125488,0],[67.9564895629883,48.8712005615234,0],[68.7482528686523,48.8716773986816,0],[69.5400085449219,48.8721961975098,0],[70.3317642211914,48.8727531433105,0],[71.1235198974609,48.873348236084,0],[71.9152755737305,48.8739967346191,0],[72.7070388793945,48.8746757507324,0],[73.4987945556641,48.875431060791,0],[74.2905502319336,48.8762092590332,0],[75.0823059082031,48.8770866394043,0],[75.8740692138672,48.8779792785645,0],[76.6658248901367,48.8789901733398,0],[77.4575805664062,48.8800315856934,0],[78.2493362426758,48.8811836242676,0],[79.0410995483398,48.8823890686035,0],[79.8328552246094,48.8836975097656,0],[80.6246109008789,48.8850936889648,0],[81.4163665771484,48.8865814208984,0],[82.2081298828125,48.8881950378418,0],[82.999885559082,48.8898811340332,0],[83.7916412353516,48.8917427062988,0],[84.5833969116211,48.8936538696289,0],[85.3751525878906,48.8957977294922,0],[86.1669158935547,48.8979797363281,0],[86.9586715698242,48.9004249572754,0],[87.7504272460938,48.9029388427734,0],[88.5421829223633,48.9057006835938,0],[89.3339462280273,48.9085884094238,0],[90.1257019042969,48.9117012023926,0],[90.9174575805664,48.9150123596191,0],[91.7092132568359,48.9185218811035,0],[92.5009765625,48.9223098754883,0],[93.2927322387695,48.9262580871582,0],[94.0844879150391,48.930591583252,0],[94.8762435913086,48.9350242614746,0],[95.6680068969727,48.9399681091309,0],[96.4597625732422,48.9449920654297,0],[97.2515182495117,48.9505729675293,0],[98.0432739257812,48.9563026428223,0],[98.8350372314453,48.9625511169434,0],[99.6267929077148,48.9690704345703,0],[100.418548583984,48.9760589599609,0],[101.210304260254,48.9834671020508,0],[102.002059936523,48.9912719726562,0],[102.793823242188,48.9996757507324,0],[103.585578918457,49.0083808898926,0],[104.377334594727,49.017894744873,0],[105.169090270996,49.0275993347168,0],[105.96085357666,49.0383453369141,0],[106.75260925293,49.0492630004883,0],[107.544364929199,49.0612716674805,0],[108.336120605469,49.073600769043,0],[109.127883911133,49.0869369506836,0],[109.919639587402,49.100830078125,0],[110.711395263672,49.1156234741211,0],[111.503150939941,49.1312561035156,0],[112.294914245605,49.1476440429688,0],[113.086669921875,49.1652030944824,0],[113.878425598145,49.1833343505859,0],[114.670181274414,49.2030258178711,0],[115.461936950684,49.2230606079102,0],[116.253700256348,49.2451019287109,0],[117.045455932617,49.267463684082,0],[117.837211608887,49.2918472290039,0],[118.628967285156,49.3168563842773,0],[119.42073059082,49.3437080383301,0],[120.21248626709,49.3716239929199,0],[121.004241943359,49.4011573791504,0],[121.795997619629,49.4322700500488,0],[122.587760925293,49.464714050293,0],[123.379516601562,49.499324798584,0],[124.171272277832,49.5349235534668,0],[124.963027954102,49.5733604431152,0],[125.754791259766,49.6123733520508,0],[126.546546936035,49.6549911499023,0],[127.338302612305,49.6981735229492,0],[128.130065917969,49.7448616027832,0],[128.921813964844,49.7926902770996,0],[129.713577270508,49.8436698913574,0],[130.505325317383,49.8965454101562,0],[131.297088623047,49.9521522521973,0],[132.088851928711,50.0105094909668,0],[132.880599975586,50.0710792541504,0],[133.67236328125,50.1353759765625,0],[134.464126586914,50.2012786865234,0],[135.255874633789,50.2720031738281,0],[136.047637939453,50.343620300293,0],[136.839385986328,50.4212799072266,0],[137.631149291992,50.4998779296875,0],[138.422912597656,50.5841445922852,0],[139.214660644531,50.6703491210938,0],[140.006423950195,50.761589050293,0],[140.798187255859,50.8559646606445,0],[141.589935302734,50.9546356201172,0],[142.381698608398,51.057788848877,0],[143.173446655273,51.164363861084,0],[143.965209960938,51.2769165039062,0],[144.756973266602,51.3918952941895,0],[145.548721313477,51.5144958496094,0],[146.340484619141,51.6383895874023,0],[147.132232666016,51.7717132568359,0],[147.92399597168,51.9064865112305,0],[148.715759277344,52.0497894287109,0],[149.507507324219,52.1961479187012,0],[150.299270629883,52.3499908447266,0],[151.091033935547,52.508659362793,0],[151.882781982422,52.6736106872559,0],[152.674545288086,52.8453407287598,0],[153.466293334961,53.0219879150391,0],[154.258056640625,53.2075347900391,0],[155.049819946289,53.3964729309082,0],[155.841567993164,53.5966186523438,0],[156.633331298828,53.7986335754395,0],[157.425079345703,54.0139846801758,0],[158.216842651367,54.2315635681152,0],[159.008605957031,54.4610443115234,0],[159.800354003906,54.6949882507324,0],[160.59211730957,54.9392242431641,0],[161.383880615234,55.1903381347656,0],[162.175628662109,55.4499588012695,0],[162.967391967773,55.7190437316895,0],[163.759140014648,55.9946670532227,0],[164.550903320312,56.2825355529785,0],[165.342666625977,56.5747833251953,0],[166.134414672852,56.8822212219238,0],[166.926177978516,57.1921691894531,0],[167.71794128418,57.5195045471191,0],[168.509689331055,57.8499794006348,0],[169.301452636719,58.1957550048828,0],[170.093200683594,58.5475196838379,0],[170.884963989258,58.9123115539551,0],[171.676727294922,59.2861022949219,0],[172.468475341797,59.670467376709,0],[173.260238647461,60.0669898986816,0],[174.051986694336,60.4714698791504,0],[174.84375,60.8913917541504,0],[175.635513305664,61.3164901733398,0],[176.427261352539,61.7604484558105,0],[177.219024658203,62.2074737548828,0],[178.010787963867,62.6752281188965,0],[178.802536010742,63.1469955444336,0],[179.594299316406,63.6367034912109,0],[180.386047363281,64.1337280273438,0],[181.177810668945,64.6457672119141,0],[181.969573974609,65.1685028076172,0],[182.761322021484,65.7031936645508,0],[183.553085327148,66.2520217895508,0],[184.344848632812,66.8096389770508,0],[185.136596679688,67.3848876953125,0],[185.928359985352,67.9656524658203,0],[186.720108032227,68.5675506591797,0],[187.511871337891,69.1728210449219,0],[188.303634643555,69.8003387451172,0],[189.09538269043,70.4324340820312,0],[189.887145996094,71.0834121704102,0],[190.678894042969,71.7423706054688,0],[191.470657348633,72.4168014526367,0],[192.262420654297,73.1025543212891,0],[193.054168701172,73.8003463745117,0],[193.845932006836,74.5127334594727,0],[194.6376953125,75.2337265014648,0],[195.429443359375,75.9724807739258,0],[196.221206665039,76.7164306640625,0],[197.012954711914,77.4811859130859,0],[197.804718017578,78.2491912841797,0],[198.596481323242,79.0380401611328,0],[199.388229370117,79.8314208984375,0],[200.179992675781,80.6420516967773,0],[200.971740722656,81.4601669311523,0],[201.76350402832,82.2920227050781,0],[202.555267333984,83.1341247558594,0],[203.347015380859,83.986572265625,0],[204.138778686523,84.8517761230469,0],[204.930541992188,85.7240905761719,0],[205.722290039062,86.6114044189453,0],[206.514053344727,87.5027847290039,0],[207.305801391602,88.4110946655273,0],[208.097564697266,89.3219528198242,0],[208.88932800293,90.2487258911133,0],[209.681076049805,91.1790466308594,0],[210.472839355469,92.1219711303711,0],[211.264602661133,93.0703811645508,0],[212.056350708008,94.0283279418945,0],[212.848114013672,94.9933242797852,0],[213.639862060547,95.965087890625,0],[214.431625366211,96.9450607299805,0],[215.223388671875,97.9293670654297,0],[216.01513671875,98.9225997924805,0],[216.806900024414,99.918083190918,0],[217.598648071289,100.922775268555,0],[218.390411376953,101.928749084473,0],[219.182174682617,102.942260742188,0],[219.973922729492,103.957344055176,0],[220.765686035156,104.977577209473,0],[221.55744934082,105.999755859375,0],[222.349197387695,107.025115966797,0],[223.140960693359,108.052291870117,0],[223.932708740234,109.081123352051,0],[224.724472045898,110.111145019531,0],[225.516235351562,111.141761779785,0],[226.307983398438,112.172409057617,0],[227.099746704102,113.203063964844,0],[227.891510009766,114.232070922852,0],[228.683258056641,115.260650634766,0],[229.475021362305,116.286071777344,0],[230.26676940918,117.310188293457,0],[231.058532714844,118.330291748047,0],[231.850296020508,119.347610473633,0],[232.642044067383,120.360572814941,0],[233.433807373047,121.36873626709,0],[234.225555419922,122.372734069824,0],[235.017318725586,123.369400024414,0],[235.80908203125,124.362609863281,0],[236.600830078125,125.345443725586,0],[237.392593383789,126.326049804688,0],[238.184356689453,127.292724609375,0],[238.976104736328,128.257110595703,0],[239.767868041992,129.207183837891,0],[240.559616088867,130.152633666992,0],[241.351379394531,131.084808349609,0],[242.143142700195,132.009094238281,0],[242.93489074707,132.921676635742,0],[243.726654052734,133.822631835938,0],[244.518402099609,134.713989257812,0],[245.310165405273,135.589538574219,0],[246.101928710938,136.458068847656,0],[246.893676757812,137.306213378906,0],[247.685440063477,138.150375366211,0],[248.477203369141,138.969192504883,0],[249.268951416016,139.784088134766,0],[250.06071472168,140.575210571289,0],[250.852462768555,141.358596801758,0],[251.644226074219,142.121185302734,0],[252.435989379883,142.871398925781,0],[253.227737426758,143.604217529297,0],[254.019500732422,144.319732666016,0],[254.811264038086,145.021636962891,0],[255.603012084961,145.701034545898,0],[256.394775390625,146.370986938477,0],[257.1865234375,147.012985229492,0],[257.978302001953,147.650039672852,0],[258.770050048828,148.253540039062,0],[259.561798095703,148.85205078125,0],[260.353546142578,149.420837402344,0],[261.145324707031,149.979675292969,0],[261.937072753906,150.513305664062,0],[262.728820800781,151.031677246094,0],[263.520599365234,151.529632568359,0],[264.312347412109,152.006927490234,0],[265.104095458984,152.468780517578,0],[265.895874023438,152.904510498047,0],[266.687622070312,153.329925537109,0],[267.479370117188,153.723785400391,0],[268.271148681641,154.112335205078,0],[269.062896728516,154.464401245117,0],[269.854644775391,154.810913085938,0],[270.646392822266,155.126235961914,0],[271.438171386719,155.430755615234,0],[272.229919433594,155.70947265625,0],[273.021667480469,155.97216796875,0],[273.813446044922,156.214492797852,0],[274.605194091797,156.435729980469,0],[275.396942138672,156.641983032227,0],[276.188720703125,156.822219848633,0],[276.98046875,156.992828369141,0],[277.772216796875,157.132705688477,0],[278.563995361328,157.267517089844,0],[279.355743408203,157.368438720703,0],[280.147491455078,157.463836669922,0],[280.939239501953,157.530914306641,0],[281.731018066406,157.587814331055,0],[282.522766113281,157.621826171875,0],[283.314514160156,157.641250610352,0],[284.106292724609,157.643051147461,0],[284.898040771484,157.626174926758,0],[285.689788818359,157.5966796875,0],[286.481567382812,157.544723510742,0],[287.273315429688,157.484939575195,0],[288.065063476562,157.399230957031,0],[288.856842041016,157.309341430664,0],[289.648590087891,157.19221496582,0],[290.440338134766,157.070327758789,0],[291.232086181641,156.926239013672,0],[292.023864746094,156.773910522461,0],[292.815612792969,156.604080200195,0],[293.607360839844,156.422866821289,0],[294.399139404297,156.228546142578,0],[295.190887451172,156.020080566406,0],[295.982635498047,155.802581787109,0],[296.7744140625,155.568557739258,0],[297.566162109375,155.329162597656,0],[298.35791015625,155.071304321289,0],[299.149688720703,154.810531616211,0],[299.941436767578,154.531433105469,0],[300.733184814453,154.248962402344,0],[301.524932861328,153.952056884766,0],[302.316711425781,153.649688720703,0],[303.108459472656,153.336349487305,0],[303.900207519531,153.015853881836,0],[304.691986083984,152.687484741211,0],[305.483734130859,152.350631713867,0],[306.275482177734,152.008636474609,0],[307.067260742188,151.6572265625,0],[307.859008789062,151.302963256836,0],[308.650756835938,150.938766479492,0],[309.442535400391,150.57307434082,0],[310.234283447266,150.198379516602,0],[311.026031494141,149.822036743164,0],[311.817810058594,149.439163208008,0],[312.609558105469,149.053894042969,0],[313.401306152344,148.664154052734,0],[314.193054199219,148.271667480469,0],[314.984832763672,147.876342773438,0],[315.776580810547,147.478286743164,0],[316.568328857422,147.078674316406,0],[317.360107421875,146.676666259766,0],[318.15185546875,146.273971557617,0],[318.943603515625,145.869583129883,0],[319.735382080078,145.46501159668,0],[320.527130126953,145.059814453125,0],[321.318878173828,144.654708862305,0],[322.110656738281,144.249969482422,0],[322.902404785156,143.845794677734,0],[323.694152832031,143.442626953125,0],[324.485900878906,143.040786743164,0],[325.277679443359,142.640243530273,0],[326.069427490234,142.242065429688,0],[326.861175537109,141.845184326172,0],[327.652954101562,141.451950073242,0],[328.444702148438,141.059692382812,0],[329.236450195312,140.672637939453,0],[330.028228759766,140.286468505859,0],[330.819976806641,139.906204223633,0],[331.611724853516,139.527603149414,0],[332.403503417969,139.154632568359,0],[333.195251464844,138.78466796875,0],[333.986999511719,138.419784545898,0],[334.778747558594,138.059448242188,0],[335.570526123047,137.703399658203,0],[336.362274169922,137.353637695312,0],[337.154022216797,137.007110595703,0],[337.94580078125,136.668762207031,0],[338.737548828125,136.332412719727,0],[339.529296875,136.006271362305,0],[340.321075439453,135.681747436523,0],[341.112823486328,135.367477416992,0],[341.904571533203,135.056030273438,0],[342.696350097656,134.753570556641,0],[343.488098144531,134.455810546875,0],[344.279846191406,134.165603637695,0],[345.071594238281,133.882064819336,0],[345.863372802734,133.604507446289,0],[346.655120849609,133.335662841797,0],[347.446868896484,133.071090698242,0],[348.238647460938,132.817337036133,0],[349.030395507812,132.566024780273,0],[349.822143554688,132.327682495117,0],[350.613922119141,132.09130859375,0],[351.405670166016,131.867156982422,0],[352.197418212891,131.646469116211,0],[352.989196777344,131.436111450195,0],[353.780944824219,131.231246948242,0],[354.572692871094,131.034744262695,0],[355.364471435547,130.845748901367,0],[356.156219482422,130.663131713867,0],[356.947967529297,130.490005493164,0],[357.739715576172,130.321212768555,0],[358.531494140625,130.163848876953,0],[359.3232421875,130.008804321289,0],[360.114990234375,129.86701965332,0],[360.906768798828,129.727172851562,0],[361.698516845703,129.599136352539,0],[362.490264892578,129.474563598633,0],[363.282043457031,129.359664916992,0],[364.073791503906,129.25,0],[364.865539550781,129.14794921875,0],[365.657318115234,129.052780151367,0],[366.449066162109,128.963195800781,0],[367.240814208984,128.882034301758,0],[368.032562255859,128.80451965332,0],[368.824340820312,128.736785888672,0],[369.616088867188,128.670883178711,0],[370.407836914062,128.615951538086,0],[371.199615478516,128.562545776367,0],[371.991363525391,128.518295288086,0],[372.783111572266,128.476806640625,0],[373.574890136719,128.442535400391,0],[374.366638183594,128.412170410156,0],[375.158386230469,128.38720703125,0],[375.950164794922,128.367111206055,0],[376.741912841797,128.350784301758,0],[377.533660888672,128.340072631836,0],[378.325408935547,128.331649780273,0],[379.1171875,128.329345703125,0],[379.908935546875,128.328079223633,0],[380.70068359375,128.33317565918,0],[381.492462158203,128.339065551758,0],[382.284210205078,128.349700927734,0],[383.075958251953,128.361679077148,0],[383.867736816406,128.376998901367,0],[384.659484863281,128.393966674805,0],[385.451232910156,128.4130859375,0],[386.243011474609,128.433898925781,0],[387.034759521484,128.455917358398,0],[387.826507568359,128.479385375977,0],[388.618255615234,128.503402709961,0],[389.410034179688,128.5283203125,0],[390.201782226562,128.553375244141,0],[390.993530273438,128.578536987305,0],[391.785308837891,128.603561401367,0],[392.577056884766,128.627868652344,0],[393.368804931641,128.651611328125,0],[394.160583496094,128.674087524414,0],[394.952331542969,128.695327758789,0],[395.744079589844,128.71501159668,0],[396.535858154297,128.732482910156,0],[397.327606201172,128.748428344727,0],[398.119354248047,128.760894775391,0],[398.9111328125,128.772125244141,0],[399.702880859375,128.778366088867,0],[400.49462890625,128.783782958984,0],[401.286376953125,128.782745361328,0],[402.078155517578,128.780456542969,0],[402.869903564453,128.771911621094,0],[403.661651611328,128.760726928711,0],[404.453430175781,128.743774414062,0],[405.245178222656,128.722549438477,0],[406.036926269531,128.696304321289,0],[406.828704833984,128.663925170898,0],[407.620452880859,128.627532958984,0],[408.412200927734,128.582931518555,0],[409.203979492188,128.535568237305,0],[409.995727539062,128.477722167969,0],[410.787475585938,128.41813659668,0],[411.579223632812,128.34651184082,0],[412.371002197266,128.272476196289,0],[413.162750244141,128.187622070312,0],[413.954498291016,128.098220825195,0],[414.746276855469,127.999465942383,0],[415.538024902344,127.893859863281,0],[416.329772949219,127.780555725098,0],[417.121551513672,127.657943725586,0],[417.913299560547,127.529518127441,0],[418.705047607422,127.389183044434,0],[419.496826171875,127.245079040527,0],[420.28857421875,127.086357116699,0],[421.080322265625,126.925277709961,0],[421.8720703125,126.748405456543,0],[422.663848876953,126.568237304688,0],[423.455596923828,126.374359130859,0],[424.247344970703,126.174613952637,0],[425.039123535156,125.963394165039,0],[425.830871582031,125.74365234375,0],[426.622619628906,125.514801025391,0],[427.414398193359,125.274726867676,0],[428.206146240234,125.028007507324,0],[428.997894287109,124.76734161377,0],[429.789672851562,124.502578735352,0],[430.581420898438,124.221130371094,0],[431.373168945312,123.937057495117,0],[432.164916992188,123.635856628418,0],[432.956695556641,123.33088684082,0],[433.748443603516,123.011421203613,0],[434.540191650391,122.685554504395,0],[435.331970214844,122.347854614258,0],[436.123718261719,122.001159667969,0],[436.915466308594,121.645317077637,0],[437.707244873047,121.277938842773,0],[438.498992919922,120.904083251953,0],[439.290740966797,120.516250610352,0],[440.08251953125,120.124588012695,0],[440.874267578125,119.716583251953,0],[441.666015625,119.306060791016,0],[442.457794189453,118.879539489746,0],[443.249542236328,118.449317932129,0],[444.041290283203,118.005859375,0],[444.833038330078,117.556381225586,0],[445.624816894531,117.096366882324,0],[446.416564941406,116.628150939941,0],[447.208312988281,116.152015686035,0],[448.000091552734,115.665657043457,0],[448.791839599609,115.173873901367,0],[449.583587646484,114.670013427734,0],[450.375366210938,114.1630859375,0],[451.167114257812,113.642417907715,0],[451.958862304688,113.119697570801,0],[452.750640869141,112.584205627441,0],[453.542388916016,112.045608520508,0],[454.334136962891,111.49674987793,0],[455.125885009766,110.94310760498,0],[455.917663574219,110.381546020508,0],[456.709411621094,109.813720703125,0],[457.501159667969,109.240142822266,0],[458.292938232422,108.659042358398,0],[459.084686279297,108.074172973633,0],[459.876434326172,107.480743408203,0],[460.668212890625,106.885314941406,0],[461.4599609375,106.280548095703,0],[462.251708984375,105.674438476562,0],[463.043487548828,105.06022644043,0],[463.835235595703,104.44401550293,0],[464.626983642578,103.821617126465,0],[465.418731689453,103.196350097656,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[60.8306732177734,48.8681716918945,0],[61.6224327087402,48.8684158325195,0],[62.4141883850098,48.8686752319336,0],[63.2059478759766,48.8689651489258,0],[63.9977035522461,48.8692626953125,0],[64.7894592285156,48.8696022033691,0],[65.5812225341797,48.8699493408203,0],[66.3729782104492,48.8703422546387,0],[67.1647338867188,48.8707466125488,0],[67.9564895629883,48.8712005615234,0],[68.7482528686523,48.8716773986816,0],[69.5400085449219,48.8721961975098,0],[70.3317642211914,48.8727531433105,0],[71.1235198974609,48.873348236084,0],[71.9152755737305,48.8739967346191,0],[72.7070388793945,48.8746757507324,0],[73.4987945556641,48.875431060791,0],[74.2905502319336,48.8762092590332,0],[75.0823059082031,48.8770866394043,0],[75.8740692138672,48.8779792785645,0],[76.6658248901367,48.8789901733398,0],[77.4575805664062,48.8800315856934,0],[78.2493362426758,48.8811836242676,0],[79.0410995483398,48.8823890686035,0],[79.8328552246094,48.8836975097656,0],[80.6246109008789,48.8850936889648,0],[81.4163665771484,48.8865814208984,0],[82.2081298828125,48.8881950378418,0],[82.999885559082,48.8898811340332,0],[83.7916412353516,48.8917427062988,0],[84.5833969116211,48.8936538696289,0],[85.3751525878906,48.8957977294922,0],[86.1669158935547,48.8979797363281,0],[86.9586715698242,48.9004249572754,0],[87.7504272460938,48.9029388427734,0],[88.5421829223633,48.9057006835938,0],[89.3339462280273,48.9085884094238,0],[90.1257019042969,48.9117012023926,0],[90.9174575805664,48.9150123596191,0],[91.7092132568359,48.9185218811035,0],[92.5009765625,48.9223098754883,0],[93.2927322387695,48.9262580871582,0],[94.0844879150391,48.930591583252,0],[94.8762435913086,48.9350242614746,0],[95.6680068969727,48.9399681091309,0],[96.4597625732422,48.9449920654297,0],[97.2515182495117,48.9505729675293,0],[98.0432739257812,48.9563026428223,0],[98.8350372314453,48.9625511169434,0],[99.6267929077148,48.9690704345703,0],[100.418548583984,48.9760589599609,0],[101.210304260254,48.9834671020508,0],[102.002059936523,48.9912719726562,0],[102.793823242188,48.9996757507324,0],[103.585578918457,49.0083808898926,0],[104.377334594727,49.017894744873,0],[105.169090270996,49.0275993347168,0],[105.96085357666,49.0383453369141,0],[106.75260925293,49.0492630004883,0],[107.544364929199,49.0612716674805,0],[108.336120605469,49.073600769043,0],[109.127883911133,49.0869369506836,0],[109.919639587402,49.100830078125,0],[110.711395263672,49.1156234741211,0],[111.503150939941,49.1312561035156,0],[112.294914245605,49.1476440429688,0],[113.086669921875,49.1652030944824,0],[113.878425598145,49.1833343505859,0],[114.670181274414,49.2030258178711,0],[115.461936950684,49.2230606079102,0],[116.253700256348,49.2451019287109,0],[117.045455932617,49.267463684082,0],[117.837211608887,49.2918472290039,0],[118.628967285156,49.3168563842773,0],[119.42073059082,49.3437080383301,0],[120.21248626709,49.3716239929199,0],[121.004241943359,49.4011573791504,0],[121.795997619629,49.4322700500488,0],[122.587760925293,49.464714050293,0],[123.379516601562,49.499324798584,0],[124.171272277832,49.5349235534668,0],[124.963027954102,49.5733604431152,0],[125.754791259766,49.6123733520508,0],[126.546546936035,49.6549911499023,0],[127.338302612305,49.6981735229492,0],[128.130065917969,49.7448616027832,0],[128.921813964844,49.7926902770996,0],[129.713577270508,49.8436698913574,0],[130.505325317383,49.8965454101562,0],[131.297088623047,49.9521522521973,0],[132.088851928711,50.0105094909668,0],[132.880599975586,50.0710792541504,0],[133.67236328125,50.1353759765625,0],[134.464126586914,50.2012786865234,0],[135.255874633789,50.2720031738281,0],[136.047637939453,50.343620300293,0],[136.839385986328,50.4212799072266,0],[137.631149291992,50.4998779296875,0],[138.422912597656,50.5841445922852,0],[139.214660644531,50.6703491210938,0],[140.006423950195,50.761589050293,0],[140.798187255859,50.8559646606445,0],[141.589935302734,50.9546356201172,0],[142.381698608398,51.057788848877,0],[143.173446655273,51.164363861084,0],[143.965209960938,51.2769165039062,0],[144.756973266602,51.3918952941895,0],[145.548721313477,51.5144958496094,0],[146.340484619141,51.6383895874023,0],[147.132232666016,51.7717132568359,0],[147.92399597168,51.9064865112305,0],[148.715759277344,52.0497894287109,0],[149.507507324219,52.1961479187012,0],[150.299270629883,52.3499908447266,0],[151.091033935547,52.508659362793,0],[151.882781982422,52.6736106872559,0],[152.674545288086,52.8453407287598,0],[153.466293334961,53.0219879150391,0],[154.258056640625,53.2075347900391,0],[155.049819946289,53.3964729309082,0],[155.841567993164,53.5966186523438,0],[156.633331298828,53.7986335754395,0],[157.425079345703,54.0139846801758,0],[158.216842651367,54.2315635681152,0],[159.008605957031,54.4610443115234,0],[159.800354003906,54.6949882507324,0],[160.59211730957,54.9392242431641,0],[161.383880615234,55.1903381347656,0],[162.175628662109,55.4499588012695,0],[162.967391967773,55.7190437316895,0],[163.759140014648,55.9946670532227,0],[164.550903320312,56.2825355529785,0],[165.342666625977,56.5747833251953,0],[166.134414672852,56.8822212219238,0],[166.926177978516,57.1921691894531,0],[167.71794128418,57.5195045471191,0],[168.509689331055,57.8499794006348,0],[169.301452636719,58.1957550048828,0],[170.093200683594,58.5475196838379,0],[170.884963989258,58.9123115539551,0],[171.676727294922,59.2861022949219,0],[172.468475341797,59.670467376709,0],[173.260238647461,60.0669898986816,0],[174.051986694336,60.4714698791504,0],[174.84375,60.8913917541504,0],[175.635513305664,61.3164901733398,0],[176.427261352539,61.7604484558105,0],[177.219024658203,62.2074737548828,0],[178.010787963867,62.6752281188965,0],[178.802536010742,63.1469955444336,0],[179.594299316406,63.6367034912109,0],[180.386047363281,64.1337280273438,0],[181.177810668945,64.6457672119141,0],[181.969573974609,65.1685028076172,0],[182.761322021484,65.7031936645508,0],[183.553085327148,66.2520217895508,0],[184.344848632812,66.8096389770508,0],[185.136596679688,67.3848876953125,0],[185.928359985352,67.9656524658203,0],[186.720108032227,68.5675506591797,0],[187.511871337891,69.1728210449219,0],[188.303634643555,69.8003387451172,0],[189.09538269043,70.4324340820312,0],[189.887145996094,71.0834121704102,0],[190.678894042969,71.7423706054688,0],[191.470657348633,72.4168014526367,0],[192.262420654297,73.1025543212891,0],[193.054168701172,73.8003463745117,0],[193.845932006836,74.5127334594727,0],[194.6376953125,75.2337265014648,0],[195.429443359375,75.9724807739258,0],[196.221206665039,76.7164306640625,0],[197.012954711914,77.4811859130859,0],[197.804718017578,78.2491912841797,0],[198.596481323242,79.0380401611328,0],[199.388229370117,79.8314208984375,0],[200.179992675781,80.6420516967773,0],[200.971740722656,81.4601669311523,0],[201.76350402832,82.2920227050781,0],[202.555267333984,83.1341247558594,0],[203.347015380859,83.986572265625,0],[204.138778686523,84.8517761230469,0],[204.930541992188,85.7240905761719,0],[205.722290039062,86.6114044189453,0],[206.514053344727,87.5027847290039,0],[207.305801391602,88.4110946655273,0],[208.097564697266,89.3219528198242,0],[208.88932800293,90.2487258911133,0],[209.681076049805,91.1790466308594,0],[210.472839355469,92.1219711303711,0],[211.264602661133,93.0703811645508,0],[212.056350708008,94.0283279418945,0],[212.848114013672,94.9933242797852,0],[213.639862060547,95.965087890625,0],[214.431625366211,96.9450607299805,0],[215.223388671875,97.9293670654297,0],[216.01513671875,98.9225997924805,0],[216.806900024414,99.918083190918,0],[217.598648071289,100.922775268555,0],[218.390411376953,101.928749084473,0],[219.182174682617,102.942260742188,0],[219.973922729492,103.957344055176,0],[220.765686035156,104.977577209473,0],[221.55744934082,105.999755859375,0],[222.349197387695,107.025115966797,0],[223.140960693359,108.052291870117,0],[223.932708740234,109.081123352051,0],[224.724472045898,110.111145019531,0],[225.516235351562,111.141761779785,0],[226.307983398438,112.172409057617,0],[227.099746704102,113.203063964844,0],[227.891510009766,114.232070922852,0],[228.683258056641,115.260650634766,0],[229.475021362305,116.286071777344,0],[230.26676940918,117.310188293457,0],[231.058532714844,118.330291748047,0],[231.850296020508,119.347610473633,0],[232.642044067383,120.360572814941,0],[233.433807373047,121.36873626709,0],[234.225555419922,122.372734069824,0],[235.017318725586,123.369400024414,0],[235.80908203125,124.362609863281,0],[236.600830078125,125.345443725586,0],[237.392593383789,126.326049804688,0],[238.184356689453,127.292724609375,0],[238.976104736328,128.257110595703,0],[239.767868041992,129.207183837891,0],[240.559616088867,130.152633666992,0],[241.351379394531,131.084808349609,0],[242.143142700195,132.009094238281,0],[242.93489074707,132.921676635742,0],[243.726654052734,133.822631835938,0],[244.518402099609,134.713989257812,0],[245.310165405273,135.589538574219,0],[246.101928710938,136.458068847656,0],[246.893676757812,137.306213378906,0],[247.685440063477,138.150375366211,0],[248.477203369141,138.969192504883,0],[249.268951416016,139.784088134766,0],[250.06071472168,140.575210571289,0],[250.852462768555,141.358596801758,0],[251.644226074219,142.121185302734,0],[252.435989379883,142.871398925781,0],[253.227737426758,143.604217529297,0],[254.019500732422,144.319732666016,0],[254.811264038086,145.021636962891,0],[255.603012084961,145.701034545898,0],[256.394775390625,146.370986938477,0],[257.1865234375,147.012985229492,0],[257.978302001953,147.650039672852,0],[258.770050048828,148.253540039062,0],[259.561798095703,148.85205078125,0],[260.353546142578,149.420837402344,0],[261.145324707031,149.979675292969,0],[261.937072753906,150.513305664062,0],[262.728820800781,151.031677246094,0],[263.520599365234,151.529632568359,0],[264.312347412109,152.006927490234,0],[265.104095458984,152.468780517578,0],[265.895874023438,152.904510498047,0],[266.687622070312,153.329925537109,0],[267.479370117188,153.723785400391,0],[268.271148681641,154.112335205078,0],[269.062896728516,154.464401245117,0],[269.854644775391,154.810913085938,0],[270.646392822266,155.126235961914,0],[271.438171386719,155.430755615234,0],[272.229919433594,155.70947265625,0],[273.021667480469,155.97216796875,0],[273.813446044922,156.214492797852,0],[274.605194091797,156.435729980469,0],[275.396942138672,156.641983032227,0],[276.188720703125,156.822219848633,0],[276.98046875,156.992828369141,0],[277.772216796875,157.132705688477,0],[278.563995361328,157.267517089844,0],[279.355743408203,157.368438720703,0],[280.147491455078,157.463836669922,0],[280.939239501953,157.530914306641,0],[281.731018066406,157.587814331055,0],[282.522766113281,157.621826171875,0],[283.314514160156,157.641250610352,0],[284.106292724609,157.643051147461,0],[284.898040771484,157.626174926758,0],[285.689788818359,157.5966796875,0],[286.481567382812,157.544723510742,0],[287.273315429688,157.484939575195,0],[288.065063476562,157.399230957031,0],[288.856842041016,157.309341430664,0],[289.648590087891,157.19221496582,0],[290.440338134766,157.070327758789,0],[291.232086181641,156.926239013672,0],[292.023864746094,156.773910522461,0],[292.815612792969,156.604080200195,0],[293.607360839844,156.422866821289,0],[294.399139404297,156.228546142578,0],[295.190887451172,156.020080566406,0],[295.982635498047,155.802581787109,0],[296.7744140625,155.568557739258,0],[297.566162109375,155.329162597656,0],[298.35791015625,155.071304321289,0],[299.149688720703,154.810531616211,0],[299.941436767578,154.531433105469,0],[300.733184814453,154.248962402344,0],[301.524932861328,153.952056884766,0],[302.316711425781,153.649688720703,0],[303.108459472656,153.336349487305,0],[303.900207519531,153.015853881836,0],[304.691986083984,152.687484741211,0],[305.483734130859,152.350631713867,0],[306.275482177734,152.008636474609,0],[307.067260742188,151.6572265625,0],[307.859008789062,151.302963256836,0],[308.650756835938,150.938766479492,0],[309.442535400391,150.57307434082,0],[310.234283447266,150.198379516602,0],[311.026031494141,149.822036743164,0],[311.817810058594,149.439163208008,0],[312.609558105469,149.053894042969,0],[313.401306152344,148.664154052734,0],[314.193054199219,148.271667480469,0],[314.984832763672,147.876342773438,0],[315.776580810547,147.478286743164,0],[316.568328857422,147.078674316406,0],[317.360107421875,146.676666259766,0],[318.15185546875,146.273971557617,0],[318.943603515625,145.869583129883,0],[319.735382080078,145.46501159668,0],[320.527130126953,145.059814453125,0],[321.318878173828,144.654708862305,0],[322.110656738281,144.249969482422,0],[322.902404785156,143.845794677734,0],[323.694152832031,143.442626953125,0],[324.485900878906,143.040786743164,0],[325.277679443359,142.640243530273,0],[326.069427490234,142.242065429688,0],[326.861175537109,141.845184326172,0],[327.652954101562,141.451950073242,0],[328.444702148438,141.059692382812,0],[329.236450195312,140.672637939453,0],[330.028228759766,140.286468505859,0],[330.819976806641,139.906204223633,0],[331.611724853516,139.527603149414,0],[332.403503417969,139.154632568359,0],[333.195251464844,138.78466796875,0],[333.986999511719,138.419784545898,0],[334.778747558594,138.059448242188,0],[335.570526123047,137.703399658203,0],[336.362274169922,137.353637695312,0],[337.154022216797,137.007110595703,0],[337.94580078125,136.668762207031,0],[338.737548828125,136.332412719727,0],[339.529296875,136.006271362305,0],[340.321075439453,135.681747436523,0],[341.112823486328,135.367477416992,0],[341.904571533203,135.056030273438,0],[342.696350097656,134.753570556641,0],[343.488098144531,134.455810546875,0],[344.279846191406,134.165603637695,0],[345.071594238281,133.882064819336,0],[345.863372802734,133.604507446289,0],[346.655120849609,133.335662841797,0],[347.446868896484,133.071090698242,0],[348.238647460938,132.817337036133,0],[349.030395507812,132.566024780273,0],[349.822143554688,132.327682495117,0],[350.613922119141,132.09130859375,0],[351.405670166016,131.867156982422,0],[352.197418212891,131.646469116211,0],[352.989196777344,131.436111450195,0],[353.780944824219,131.231246948242,0],[354.572692871094,131.034744262695,0],[355.364471435547,130.845748901367,0],[356.156219482422,130.663131713867,0],[356.947967529297,130.490005493164,0],[357.739715576172,130.321212768555,0],[358.531494140625,130.163848876953,0],[359.3232421875,130.008804321289,0],[360.114990234375,129.86701965332,0],[360.906768798828,129.727172851562,0],[361.698516845703,129.599136352539,0],[362.490264892578,129.474563598633,0],[363.282043457031,129.359664916992,0],[364.073791503906,129.25,0],[364.865539550781,129.14794921875,0],[365.657318115234,129.052780151367,0],[366.449066162109,128.963195800781,0],[367.240814208984,128.882034301758,0],[368.032562255859,128.80451965332,0],[368.824340820312,128.736785888672,0],[369.616088867188,128.670883178711,0],[370.407836914062,128.615951538086,0],[371.199615478516,128.562545776367,0],[371.991363525391,128.518295288086,0],[372.783111572266,128.476806640625,0],[373.574890136719,128.442535400391,0],[374.366638183594,128.412170410156,0],[375.158386230469,128.38720703125,0],[375.950164794922,128.367111206055,0],[376.741912841797,128.350784301758,0],[377.533660888672,128.340072631836,0],[378.325408935547,128.331649780273,0],[379.1171875,128.329345703125,0],[379.908935546875,128.328079223633,0],[380.70068359375,128.33317565918,0],[381.492462158203,128.339065551758,0],[382.284210205078,128.349700927734,0],[383.075958251953,128.361679077148,0],[383.867736816406,128.376998901367,0],[384.659484863281,128.393966674805,0],[385.451232910156,128.4130859375,0],[386.243011474609,128.433898925781,0],[387.034759521484,128.455917358398,0],[387.826507568359,128.479385375977,0],[388.618255615234,128.503402709961,0],[389.410034179688,128.5283203125,0],[390.201782226562,128.553375244141,0],[390.993530273438,128.578536987305,0],[391.785308837891,128.603561401367,0],[392.577056884766,128.627868652344,0],[393.368804931641,128.651611328125,0],[394.160583496094,128.674087524414,0],[394.952331542969,128.695327758789,0],[395.744079589844,128.71501159668,0],[396.535858154297,128.732482910156,0],[397.327606201172,128.748428344727,0],[398.119354248047,128.760894775391,0],[398.9111328125,128.772125244141,0],[399.702880859375,128.778366088867,0],[400.49462890625,128.783782958984,0],[401.286376953125,128.782745361328,0],[402.078155517578,128.780456542969,0],[402.869903564453,128.771911621094,0],[403.661651611328,128.760726928711,0],[404.453430175781,128.743774414062,0],[405.245178222656,128.722549438477,0],[406.036926269531,128.696304321289,0],[406.828704833984,128.663925170898,0],[407.620452880859,128.627532958984,0],[408.412200927734,128.582931518555,0],[409.203979492188,128.535568237305,0],[409.995727539062,128.477722167969,0],[410.787475585938,128.41813659668,0],[411.579223632812,128.34651184082,0],[412.371002197266,128.272476196289,0],[413.162750244141,128.187622070312,0],[413.954498291016,128.098220825195,0],[414.746276855469,127.999465942383,0],[415.538024902344,127.893859863281,0],[416.329772949219,127.780555725098,0],[417.121551513672,127.657943725586,0],[417.913299560547,127.529518127441,0],[418.705047607422,127.389183044434,0],[419.496826171875,127.245079040527,0],[420.28857421875,127.086357116699,0],[421.080322265625,126.925277709961,0],[421.8720703125,126.748405456543,0],[422.663848876953,126.568237304688,0],[423.455596923828,126.374359130859,0],[424.247344970703,126.174613952637,0],[425.039123535156,125.963394165039,0],[425.830871582031,125.74365234375,0],[426.622619628906,125.514801025391,0],[427.414398193359,125.274726867676,0],[428.206146240234,125.028007507324,0],[428.997894287109,124.76734161377,0],[429.789672851562,124.502578735352,0],[430.581420898438,124.221130371094,0],[431.373168945312,123.937057495117,0],[432.164916992188,123.635856628418,0],[432.956695556641,123.33088684082,0],[433.748443603516,123.011421203613,0],[434.540191650391,122.685554504395,0],[435.331970214844,122.347854614258,0],[436.123718261719,122.001159667969,0],[436.915466308594,121.645317077637,0],[437.707244873047,121.277938842773,0],[438.498992919922,120.904083251953,0],[439.290740966797,120.516250610352,0],[440.08251953125,120.124588012695,0],[440.874267578125,119.716583251953,0],[441.666015625,119.306060791016,0],[442.457794189453,118.879539489746,0],[443.249542236328,118.449317932129,0],[444.041290283203,118.005859375,0],[444.833038330078,117.556381225586,0],[445.624816894531,117.096366882324,0],[446.416564941406,116.628150939941,0],[447.208312988281,116.152015686035,0],[448.000091552734,115.665657043457,0],[448.791839599609,115.173873901367,0],[449.583587646484,114.670013427734,0],[450.375366210938,114.1630859375,0],[451.167114257812,113.642417907715,0],[451.958862304688,113.119697570801,0],[452.750640869141,112.584205627441,0],[453.542388916016,112.045608520508,0],[454.334136962891,111.49674987793,0],[455.125885009766,110.94310760498,0],[455.917663574219,110.381546020508,0],[456.709411621094,109.813720703125,0],[457.501159667969,109.240142822266,0],[458.292938232422,108.659042358398,0],[459.084686279297,108.074172973633,0],[459.876434326172,107.480743408203,0],[460.668212890625,106.885314941406,0],[461.4599609375,106.280548095703,0],[462.251708984375,105.674438476562,0],[463.043487548828,105.06022644043,0],[463.835235595703,104.44401550293,0],[464.626983642578,103.821617126465,0],[465.418731689453,103.196350097656,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;189&#34;:{&#34;id&#34;:189,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0,&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.59999990463257,-2.59999990463257]},&#34;vertices&#34;:[[60.8306732177734,48.8681716918945,0],[61.6224327087402,48.8684158325195,0],[62.4141883850098,48.8686752319336,0],[63.2059478759766,48.8689651489258,0],[63.9977035522461,48.8692626953125,0],[64.7894592285156,48.8696022033691,0],[65.5812225341797,48.8699493408203,0],[66.3729782104492,48.8703422546387,0],[67.1647338867188,48.8707466125488,0],[67.9564895629883,48.8712005615234,0],[68.7482528686523,48.8716773986816,0],[69.5400085449219,48.8721961975098,0],[70.3317642211914,48.8727531433105,0],[71.1235198974609,48.873348236084,0],[71.9152755737305,48.8739967346191,0],[72.7070388793945,48.8746757507324,0],[73.4987945556641,48.875431060791,0],[74.2905502319336,48.8762092590332,0],[75.0823059082031,48.8770866394043,0],[75.8740692138672,48.8779792785645,0],[76.6658248901367,48.8789901733398,0],[77.4575805664062,48.8800315856934,0],[78.2493362426758,48.8811836242676,0],[79.0410995483398,48.8823890686035,0],[79.8328552246094,48.8836975097656,0],[80.6246109008789,48.8850936889648,0],[81.4163665771484,48.8865814208984,0],[82.2081298828125,48.8881950378418,0],[82.999885559082,48.8898811340332,0],[83.7916412353516,48.8917427062988,0],[84.5833969116211,48.8936538696289,0],[85.3751525878906,48.8957977294922,0],[86.1669158935547,48.8979797363281,0],[86.9586715698242,48.9004249572754,0],[87.7504272460938,48.9029388427734,0],[88.5421829223633,48.9057006835938,0],[89.3339462280273,48.9085884094238,0],[90.1257019042969,48.9117012023926,0],[90.9174575805664,48.9150123596191,0],[91.7092132568359,48.9185218811035,0],[92.5009765625,48.9223098754883,0],[93.2927322387695,48.9262580871582,0],[94.0844879150391,48.930591583252,0],[94.8762435913086,48.9350242614746,0],[95.6680068969727,48.9399681091309,0],[96.4597625732422,48.9449920654297,0],[97.2515182495117,48.9505729675293,0],[98.0432739257812,48.9563026428223,0],[98.8350372314453,48.9625511169434,0],[99.6267929077148,48.9690704345703,0],[100.418548583984,48.9760589599609,0],[101.210304260254,48.9834671020508,0],[102.002059936523,48.9912719726562,0],[102.793823242188,48.9996757507324,0],[103.585578918457,49.0083808898926,0],[104.377334594727,49.017894744873,0],[105.169090270996,49.0275993347168,0],[105.96085357666,49.0383453369141,0],[106.75260925293,49.0492630004883,0],[107.544364929199,49.0612716674805,0],[108.336120605469,49.073600769043,0],[109.127883911133,49.0869369506836,0],[109.919639587402,49.100830078125,0],[110.711395263672,49.1156234741211,0],[111.503150939941,49.1312561035156,0],[112.294914245605,49.1476440429688,0],[113.086669921875,49.1652030944824,0],[113.878425598145,49.1833343505859,0],[114.670181274414,49.2030258178711,0],[115.461936950684,49.2230606079102,0],[116.253700256348,49.2451019287109,0],[117.045455932617,49.267463684082,0],[117.837211608887,49.2918472290039,0],[118.628967285156,49.3168563842773,0],[119.42073059082,49.3437080383301,0],[120.21248626709,49.3716239929199,0],[121.004241943359,49.4011573791504,0],[121.795997619629,49.4322700500488,0],[122.587760925293,49.464714050293,0],[123.379516601562,49.499324798584,0],[124.171272277832,49.5349235534668,0],[124.963027954102,49.5733604431152,0],[125.754791259766,49.6123733520508,0],[126.546546936035,49.6549911499023,0],[127.338302612305,49.6981735229492,0],[128.130065917969,49.7448616027832,0],[128.921813964844,49.7926902770996,0],[129.713577270508,49.8436698913574,0],[130.505325317383,49.8965454101562,0],[131.297088623047,49.9521522521973,0],[132.088851928711,50.0105094909668,0],[132.880599975586,50.0710792541504,0],[133.67236328125,50.1353759765625,0],[134.464126586914,50.2012786865234,0],[135.255874633789,50.2720031738281,0],[136.047637939453,50.343620300293,0],[136.839385986328,50.4212799072266,0],[137.631149291992,50.4998779296875,0],[138.422912597656,50.5841445922852,0],[139.214660644531,50.6703491210938,0],[140.006423950195,50.761589050293,0],[140.798187255859,50.8559646606445,0],[141.589935302734,50.9546356201172,0],[142.381698608398,51.057788848877,0],[143.173446655273,51.164363861084,0],[143.965209960938,51.2769165039062,0],[144.756973266602,51.3918952941895,0],[145.548721313477,51.5144958496094,0],[146.340484619141,51.6383895874023,0],[147.132232666016,51.7717132568359,0],[147.92399597168,51.9064865112305,0],[148.715759277344,52.0497894287109,0],[149.507507324219,52.1961479187012,0],[150.299270629883,52.3499908447266,0],[151.091033935547,52.508659362793,0],[151.882781982422,52.6736106872559,0],[152.674545288086,52.8453407287598,0],[153.466293334961,53.0219879150391,0],[154.258056640625,53.2075347900391,0],[155.049819946289,53.3964729309082,0],[155.841567993164,53.5966186523438,0],[156.633331298828,53.7986335754395,0],[157.425079345703,54.0139846801758,0],[158.216842651367,54.2315635681152,0],[159.008605957031,54.4610443115234,0],[159.800354003906,54.6949882507324,0],[160.59211730957,54.9392242431641,0],[161.383880615234,55.1903381347656,0],[162.175628662109,55.4499588012695,0],[162.967391967773,55.7190437316895,0],[163.759140014648,55.9946670532227,0],[164.550903320312,56.2825355529785,0],[165.342666625977,56.5747833251953,0],[166.134414672852,56.8822212219238,0],[166.926177978516,57.1921691894531,0],[167.71794128418,57.5195045471191,0],[168.509689331055,57.8499794006348,0],[169.301452636719,58.1957550048828,0],[170.093200683594,58.5475196838379,0],[170.884963989258,58.9123115539551,0],[171.676727294922,59.2861022949219,0],[172.468475341797,59.670467376709,0],[173.260238647461,60.0669898986816,0],[174.051986694336,60.4714698791504,0],[174.84375,60.8913917541504,0],[175.635513305664,61.3164901733398,0],[176.427261352539,61.7604484558105,0],[177.219024658203,62.2074737548828,0],[178.010787963867,62.6752281188965,0],[178.802536010742,63.1469955444336,0],[179.594299316406,63.6367034912109,0],[180.386047363281,64.1337280273438,0],[181.177810668945,64.6457672119141,0],[181.969573974609,65.1685028076172,0],[182.761322021484,65.7031936645508,0],[183.553085327148,66.2520217895508,0],[184.344848632812,66.8096389770508,0],[185.136596679688,67.3848876953125,0],[185.928359985352,67.9656524658203,0],[186.720108032227,68.5675506591797,0],[187.511871337891,69.1728210449219,0],[188.303634643555,69.8003387451172,0],[189.09538269043,70.4324340820312,0],[189.887145996094,71.0834121704102,0],[190.678894042969,71.7423706054688,0],[191.470657348633,72.4168014526367,0],[192.262420654297,73.1025543212891,0],[193.054168701172,73.8003463745117,0],[193.845932006836,74.5127334594727,0],[194.6376953125,75.2337265014648,0],[195.429443359375,75.9724807739258,0],[196.221206665039,76.7164306640625,0],[197.012954711914,77.4811859130859,0],[197.804718017578,78.2491912841797,0],[198.596481323242,79.0380401611328,0],[199.388229370117,79.8314208984375,0],[200.179992675781,80.6420516967773,0],[200.971740722656,81.4601669311523,0],[201.76350402832,82.2920227050781,0],[202.555267333984,83.1341247558594,0],[203.347015380859,83.986572265625,0],[204.138778686523,84.8517761230469,0],[204.930541992188,85.7240905761719,0],[205.722290039062,86.6114044189453,0],[206.514053344727,87.5027847290039,0],[207.305801391602,88.4110946655273,0],[208.097564697266,89.3219528198242,0],[208.88932800293,90.2487258911133,0],[209.681076049805,91.1790466308594,0],[210.472839355469,92.1219711303711,0],[211.264602661133,93.0703811645508,0],[212.056350708008,94.0283279418945,0],[212.848114013672,94.9933242797852,0],[213.639862060547,95.965087890625,0],[214.431625366211,96.9450607299805,0],[215.223388671875,97.9293670654297,0],[216.01513671875,98.9225997924805,0],[216.806900024414,99.918083190918,0],[217.598648071289,100.922775268555,0],[218.390411376953,101.928749084473,0],[219.182174682617,102.942260742188,0],[219.973922729492,103.957344055176,0],[220.765686035156,104.977577209473,0],[221.55744934082,105.999755859375,0],[222.349197387695,107.025115966797,0],[223.140960693359,108.052291870117,0],[223.932708740234,109.081123352051,0],[224.724472045898,110.111145019531,0],[225.516235351562,111.141761779785,0],[226.307983398438,112.172409057617,0],[227.099746704102,113.203063964844,0],[227.891510009766,114.232070922852,0],[228.683258056641,115.260650634766,0],[229.475021362305,116.286071777344,0],[230.26676940918,117.310188293457,0],[231.058532714844,118.330291748047,0],[231.850296020508,119.347610473633,0],[232.642044067383,120.360572814941,0],[233.433807373047,121.36873626709,0],[234.225555419922,122.372734069824,0],[235.017318725586,123.369400024414,0],[235.80908203125,124.362609863281,0],[236.600830078125,125.345443725586,0],[237.392593383789,126.326049804688,0],[238.184356689453,127.292724609375,0],[238.976104736328,128.257110595703,0],[239.767868041992,129.207183837891,0],[240.559616088867,130.152633666992,0],[241.351379394531,131.084808349609,0],[242.143142700195,132.009094238281,0],[242.93489074707,132.921676635742,0],[243.726654052734,133.822631835938,0],[244.518402099609,134.713989257812,0],[245.310165405273,135.589538574219,0],[246.101928710938,136.458068847656,0],[246.893676757812,137.306213378906,0],[247.685440063477,138.150375366211,0],[248.477203369141,138.969192504883,0],[249.268951416016,139.784088134766,0],[250.06071472168,140.575210571289,0],[250.852462768555,141.358596801758,0],[251.644226074219,142.121185302734,0],[252.435989379883,142.871398925781,0],[253.227737426758,143.604217529297,0],[254.019500732422,144.319732666016,0],[254.811264038086,145.021636962891,0],[255.603012084961,145.701034545898,0],[256.394775390625,146.370986938477,0],[257.1865234375,147.012985229492,0],[257.978302001953,147.650039672852,0],[258.770050048828,148.253540039062,0],[259.561798095703,148.85205078125,0],[260.353546142578,149.420837402344,0],[261.145324707031,149.979675292969,0],[261.937072753906,150.513305664062,0],[262.728820800781,151.031677246094,0],[263.520599365234,151.529632568359,0],[264.312347412109,152.006927490234,0],[265.104095458984,152.468780517578,0],[265.895874023438,152.904510498047,0],[266.687622070312,153.329925537109,0],[267.479370117188,153.723785400391,0],[268.271148681641,154.112335205078,0],[269.062896728516,154.464401245117,0],[269.854644775391,154.810913085938,0],[270.646392822266,155.126235961914,0],[271.438171386719,155.430755615234,0],[272.229919433594,155.70947265625,0],[273.021667480469,155.97216796875,0],[273.813446044922,156.214492797852,0],[274.605194091797,156.435729980469,0],[275.396942138672,156.641983032227,0],[276.188720703125,156.822219848633,0],[276.98046875,156.992828369141,0],[277.772216796875,157.132705688477,0],[278.563995361328,157.267517089844,0],[279.355743408203,157.368438720703,0],[280.147491455078,157.463836669922,0],[280.939239501953,157.530914306641,0],[281.731018066406,157.587814331055,0],[282.522766113281,157.621826171875,0],[283.314514160156,157.641250610352,0],[284.106292724609,157.643051147461,0],[284.898040771484,157.626174926758,0],[285.689788818359,157.5966796875,0],[286.481567382812,157.544723510742,0],[287.273315429688,157.484939575195,0],[288.065063476562,157.399230957031,0],[288.856842041016,157.309341430664,0],[289.648590087891,157.19221496582,0],[290.440338134766,157.070327758789,0],[291.232086181641,156.926239013672,0],[292.023864746094,156.773910522461,0],[292.815612792969,156.604080200195,0],[293.607360839844,156.422866821289,0],[294.399139404297,156.228546142578,0],[295.190887451172,156.020080566406,0],[295.982635498047,155.802581787109,0],[296.7744140625,155.568557739258,0],[297.566162109375,155.329162597656,0],[298.35791015625,155.071304321289,0],[299.149688720703,154.810531616211,0],[299.941436767578,154.531433105469,0],[300.733184814453,154.248962402344,0],[301.524932861328,153.952056884766,0],[302.316711425781,153.649688720703,0],[303.108459472656,153.336349487305,0],[303.900207519531,153.015853881836,0],[304.691986083984,152.687484741211,0],[305.483734130859,152.350631713867,0],[306.275482177734,152.008636474609,0],[307.067260742188,151.6572265625,0],[307.859008789062,151.302963256836,0],[308.650756835938,150.938766479492,0],[309.442535400391,150.57307434082,0],[310.234283447266,150.198379516602,0],[311.026031494141,149.822036743164,0],[311.817810058594,149.439163208008,0],[312.609558105469,149.053894042969,0],[313.401306152344,148.664154052734,0],[314.193054199219,148.271667480469,0],[314.984832763672,147.876342773438,0],[315.776580810547,147.478286743164,0],[316.568328857422,147.078674316406,0],[317.360107421875,146.676666259766,0],[318.15185546875,146.273971557617,0],[318.943603515625,145.869583129883,0],[319.735382080078,145.46501159668,0],[320.527130126953,145.059814453125,0],[321.318878173828,144.654708862305,0],[322.110656738281,144.249969482422,0],[322.902404785156,143.845794677734,0],[323.694152832031,143.442626953125,0],[324.485900878906,143.040786743164,0],[325.277679443359,142.640243530273,0],[326.069427490234,142.242065429688,0],[326.861175537109,141.845184326172,0],[327.652954101562,141.451950073242,0],[328.444702148438,141.059692382812,0],[329.236450195312,140.672637939453,0],[330.028228759766,140.286468505859,0],[330.819976806641,139.906204223633,0],[331.611724853516,139.527603149414,0],[332.403503417969,139.154632568359,0],[333.195251464844,138.78466796875,0],[333.986999511719,138.419784545898,0],[334.778747558594,138.059448242188,0],[335.570526123047,137.703399658203,0],[336.362274169922,137.353637695312,0],[337.154022216797,137.007110595703,0],[337.94580078125,136.668762207031,0],[338.737548828125,136.332412719727,0],[339.529296875,136.006271362305,0],[340.321075439453,135.681747436523,0],[341.112823486328,135.367477416992,0],[341.904571533203,135.056030273438,0],[342.696350097656,134.753570556641,0],[343.488098144531,134.455810546875,0],[344.279846191406,134.165603637695,0],[345.071594238281,133.882064819336,0],[345.863372802734,133.604507446289,0],[346.655120849609,133.335662841797,0],[347.446868896484,133.071090698242,0],[348.238647460938,132.817337036133,0],[349.030395507812,132.566024780273,0],[349.822143554688,132.327682495117,0],[350.613922119141,132.09130859375,0],[351.405670166016,131.867156982422,0],[352.197418212891,131.646469116211,0],[352.989196777344,131.436111450195,0],[353.780944824219,131.231246948242,0],[354.572692871094,131.034744262695,0],[355.364471435547,130.845748901367,0],[356.156219482422,130.663131713867,0],[356.947967529297,130.490005493164,0],[357.739715576172,130.321212768555,0],[358.531494140625,130.163848876953,0],[359.3232421875,130.008804321289,0],[360.114990234375,129.86701965332,0],[360.906768798828,129.727172851562,0],[361.698516845703,129.599136352539,0],[362.490264892578,129.474563598633,0],[363.282043457031,129.359664916992,0],[364.073791503906,129.25,0],[364.865539550781,129.14794921875,0],[365.657318115234,129.052780151367,0],[366.449066162109,128.963195800781,0],[367.240814208984,128.882034301758,0],[368.032562255859,128.80451965332,0],[368.824340820312,128.736785888672,0],[369.616088867188,128.670883178711,0],[370.407836914062,128.615951538086,0],[371.199615478516,128.562545776367,0],[371.991363525391,128.518295288086,0],[372.783111572266,128.476806640625,0],[373.574890136719,128.442535400391,0],[374.366638183594,128.412170410156,0],[375.158386230469,128.38720703125,0],[375.950164794922,128.367111206055,0],[376.741912841797,128.350784301758,0],[377.533660888672,128.340072631836,0],[378.325408935547,128.331649780273,0],[379.1171875,128.329345703125,0],[379.908935546875,128.328079223633,0],[380.70068359375,128.33317565918,0],[381.492462158203,128.339065551758,0],[382.284210205078,128.349700927734,0],[383.075958251953,128.361679077148,0],[383.867736816406,128.376998901367,0],[384.659484863281,128.393966674805,0],[385.451232910156,128.4130859375,0],[386.243011474609,128.433898925781,0],[387.034759521484,128.455917358398,0],[387.826507568359,128.479385375977,0],[388.618255615234,128.503402709961,0],[389.410034179688,128.5283203125,0],[390.201782226562,128.553375244141,0],[390.993530273438,128.578536987305,0],[391.785308837891,128.603561401367,0],[392.577056884766,128.627868652344,0],[393.368804931641,128.651611328125,0],[394.160583496094,128.674087524414,0],[394.952331542969,128.695327758789,0],[395.744079589844,128.71501159668,0],[396.535858154297,128.732482910156,0],[397.327606201172,128.748428344727,0],[398.119354248047,128.760894775391,0],[398.9111328125,128.772125244141,0],[399.702880859375,128.778366088867,0],[400.49462890625,128.783782958984,0],[401.286376953125,128.782745361328,0],[402.078155517578,128.780456542969,0],[402.869903564453,128.771911621094,0],[403.661651611328,128.760726928711,0],[404.453430175781,128.743774414062,0],[405.245178222656,128.722549438477,0],[406.036926269531,128.696304321289,0],[406.828704833984,128.663925170898,0],[407.620452880859,128.627532958984,0],[408.412200927734,128.582931518555,0],[409.203979492188,128.535568237305,0],[409.995727539062,128.477722167969,0],[410.787475585938,128.41813659668,0],[411.579223632812,128.34651184082,0],[412.371002197266,128.272476196289,0],[413.162750244141,128.187622070312,0],[413.954498291016,128.098220825195,0],[414.746276855469,127.999465942383,0],[415.538024902344,127.893859863281,0],[416.329772949219,127.780555725098,0],[417.121551513672,127.657943725586,0],[417.913299560547,127.529518127441,0],[418.705047607422,127.389183044434,0],[419.496826171875,127.245079040527,0],[420.28857421875,127.086357116699,0],[421.080322265625,126.925277709961,0],[421.8720703125,126.748405456543,0],[422.663848876953,126.568237304688,0],[423.455596923828,126.374359130859,0],[424.247344970703,126.174613952637,0],[425.039123535156,125.963394165039,0],[425.830871582031,125.74365234375,0],[426.622619628906,125.514801025391,0],[427.414398193359,125.274726867676,0],[428.206146240234,125.028007507324,0],[428.997894287109,124.76734161377,0],[429.789672851562,124.502578735352,0],[430.581420898438,124.221130371094,0],[431.373168945312,123.937057495117,0],[432.164916992188,123.635856628418,0],[432.956695556641,123.33088684082,0],[433.748443603516,123.011421203613,0],[434.540191650391,122.685554504395,0],[435.331970214844,122.347854614258,0],[436.123718261719,122.001159667969,0],[436.915466308594,121.645317077637,0],[437.707244873047,121.277938842773,0],[438.498992919922,120.904083251953,0],[439.290740966797,120.516250610352,0],[440.08251953125,120.124588012695,0],[440.874267578125,119.716583251953,0],[441.666015625,119.306060791016,0],[442.457794189453,118.879539489746,0],[443.249542236328,118.449317932129,0],[444.041290283203,118.005859375,0],[444.833038330078,117.556381225586,0],[445.624816894531,117.096366882324,0],[446.416564941406,116.628150939941,0],[447.208312988281,116.152015686035,0],[448.000091552734,115.665657043457,0],[448.791839599609,115.173873901367,0],[449.583587646484,114.670013427734,0],[450.375366210938,114.1630859375,0],[451.167114257812,113.642417907715,0],[451.958862304688,113.119697570801,0],[452.750640869141,112.584205627441,0],[453.542388916016,112.045608520508,0],[454.334136962891,111.49674987793,0],[455.125885009766,110.94310760498,0],[455.917663574219,110.381546020508,0],[456.709411621094,109.813720703125,0],[457.501159667969,109.240142822266,0],[458.292938232422,108.659042358398,0],[459.084686279297,108.074172973633,0],[459.876434326172,107.480743408203,0],[460.668212890625,106.885314941406,0],[461.4599609375,106.280548095703,0],[462.251708984375,105.674438476562,0],[463.043487548828,105.06022644043,0],[463.835235595703,104.44401550293,0],[464.626983642578,103.821617126465,0],[465.418731689453,103.196350097656,0]],&#34;colors&#34;:[[1,1,1,0]],&#34;centers&#34;:[[60.8306732177734,48.8681716918945,0],[61.6224327087402,48.8684158325195,0],[62.4141883850098,48.8686752319336,0],[63.2059478759766,48.8689651489258,0],[63.9977035522461,48.8692626953125,0],[64.7894592285156,48.8696022033691,0],[65.5812225341797,48.8699493408203,0],[66.3729782104492,48.8703422546387,0],[67.1647338867188,48.8707466125488,0],[67.9564895629883,48.8712005615234,0],[68.7482528686523,48.8716773986816,0],[69.5400085449219,48.8721961975098,0],[70.3317642211914,48.8727531433105,0],[71.1235198974609,48.873348236084,0],[71.9152755737305,48.8739967346191,0],[72.7070388793945,48.8746757507324,0],[73.4987945556641,48.875431060791,0],[74.2905502319336,48.8762092590332,0],[75.0823059082031,48.8770866394043,0],[75.8740692138672,48.8779792785645,0],[76.6658248901367,48.8789901733398,0],[77.4575805664062,48.8800315856934,0],[78.2493362426758,48.8811836242676,0],[79.0410995483398,48.8823890686035,0],[79.8328552246094,48.8836975097656,0],[80.6246109008789,48.8850936889648,0],[81.4163665771484,48.8865814208984,0],[82.2081298828125,48.8881950378418,0],[82.999885559082,48.8898811340332,0],[83.7916412353516,48.8917427062988,0],[84.5833969116211,48.8936538696289,0],[85.3751525878906,48.8957977294922,0],[86.1669158935547,48.8979797363281,0],[86.9586715698242,48.9004249572754,0],[87.7504272460938,48.9029388427734,0],[88.5421829223633,48.9057006835938,0],[89.3339462280273,48.9085884094238,0],[90.1257019042969,48.9117012023926,0],[90.9174575805664,48.9150123596191,0],[91.7092132568359,48.9185218811035,0],[92.5009765625,48.9223098754883,0],[93.2927322387695,48.9262580871582,0],[94.0844879150391,48.930591583252,0],[94.8762435913086,48.9350242614746,0],[95.6680068969727,48.9399681091309,0],[96.4597625732422,48.9449920654297,0],[97.2515182495117,48.9505729675293,0],[98.0432739257812,48.9563026428223,0],[98.8350372314453,48.9625511169434,0],[99.6267929077148,48.9690704345703,0],[100.418548583984,48.9760589599609,0],[101.210304260254,48.9834671020508,0],[102.002059936523,48.9912719726562,0],[102.793823242188,48.9996757507324,0],[103.585578918457,49.0083808898926,0],[104.377334594727,49.017894744873,0],[105.169090270996,49.0275993347168,0],[105.96085357666,49.0383453369141,0],[106.75260925293,49.0492630004883,0],[107.544364929199,49.0612716674805,0],[108.336120605469,49.073600769043,0],[109.127883911133,49.0869369506836,0],[109.919639587402,49.100830078125,0],[110.711395263672,49.1156234741211,0],[111.503150939941,49.1312561035156,0],[112.294914245605,49.1476440429688,0],[113.086669921875,49.1652030944824,0],[113.878425598145,49.1833343505859,0],[114.670181274414,49.2030258178711,0],[115.461936950684,49.2230606079102,0],[116.253700256348,49.2451019287109,0],[117.045455932617,49.267463684082,0],[117.837211608887,49.2918472290039,0],[118.628967285156,49.3168563842773,0],[119.42073059082,49.3437080383301,0],[120.21248626709,49.3716239929199,0],[121.004241943359,49.4011573791504,0],[121.795997619629,49.4322700500488,0],[122.587760925293,49.464714050293,0],[123.379516601562,49.499324798584,0],[124.171272277832,49.5349235534668,0],[124.963027954102,49.5733604431152,0],[125.754791259766,49.6123733520508,0],[126.546546936035,49.6549911499023,0],[127.338302612305,49.6981735229492,0],[128.130065917969,49.7448616027832,0],[128.921813964844,49.7926902770996,0],[129.713577270508,49.8436698913574,0],[130.505325317383,49.8965454101562,0],[131.297088623047,49.9521522521973,0],[132.088851928711,50.0105094909668,0],[132.880599975586,50.0710792541504,0],[133.67236328125,50.1353759765625,0],[134.464126586914,50.2012786865234,0],[135.255874633789,50.2720031738281,0],[136.047637939453,50.343620300293,0],[136.839385986328,50.4212799072266,0],[137.631149291992,50.4998779296875,0],[138.422912597656,50.5841445922852,0],[139.214660644531,50.6703491210938,0],[140.006423950195,50.761589050293,0],[140.798187255859,50.8559646606445,0],[141.589935302734,50.9546356201172,0],[142.381698608398,51.057788848877,0],[143.173446655273,51.164363861084,0],[143.965209960938,51.2769165039062,0],[144.756973266602,51.3918952941895,0],[145.548721313477,51.5144958496094,0],[146.340484619141,51.6383895874023,0],[147.132232666016,51.7717132568359,0],[147.92399597168,51.9064865112305,0],[148.715759277344,52.0497894287109,0],[149.507507324219,52.1961479187012,0],[150.299270629883,52.3499908447266,0],[151.091033935547,52.508659362793,0],[151.882781982422,52.6736106872559,0],[152.674545288086,52.8453407287598,0],[153.466293334961,53.0219879150391,0],[154.258056640625,53.2075347900391,0],[155.049819946289,53.3964729309082,0],[155.841567993164,53.5966186523438,0],[156.633331298828,53.7986335754395,0],[157.425079345703,54.0139846801758,0],[158.216842651367,54.2315635681152,0],[159.008605957031,54.4610443115234,0],[159.800354003906,54.6949882507324,0],[160.59211730957,54.9392242431641,0],[161.383880615234,55.1903381347656,0],[162.175628662109,55.4499588012695,0],[162.967391967773,55.7190437316895,0],[163.759140014648,55.9946670532227,0],[164.550903320312,56.2825355529785,0],[165.342666625977,56.5747833251953,0],[166.134414672852,56.8822212219238,0],[166.926177978516,57.1921691894531,0],[167.71794128418,57.5195045471191,0],[168.509689331055,57.8499794006348,0],[169.301452636719,58.1957550048828,0],[170.093200683594,58.5475196838379,0],[170.884963989258,58.9123115539551,0],[171.676727294922,59.2861022949219,0],[172.468475341797,59.670467376709,0],[173.260238647461,60.0669898986816,0],[174.051986694336,60.4714698791504,0],[174.84375,60.8913917541504,0],[175.635513305664,61.3164901733398,0],[176.427261352539,61.7604484558105,0],[177.219024658203,62.2074737548828,0],[178.010787963867,62.6752281188965,0],[178.802536010742,63.1469955444336,0],[179.594299316406,63.6367034912109,0],[180.386047363281,64.1337280273438,0],[181.177810668945,64.6457672119141,0],[181.969573974609,65.1685028076172,0],[182.761322021484,65.7031936645508,0],[183.553085327148,66.2520217895508,0],[184.344848632812,66.8096389770508,0],[185.136596679688,67.3848876953125,0],[185.928359985352,67.9656524658203,0],[186.720108032227,68.5675506591797,0],[187.511871337891,69.1728210449219,0],[188.303634643555,69.8003387451172,0],[189.09538269043,70.4324340820312,0],[189.887145996094,71.0834121704102,0],[190.678894042969,71.7423706054688,0],[191.470657348633,72.4168014526367,0],[192.262420654297,73.1025543212891,0],[193.054168701172,73.8003463745117,0],[193.845932006836,74.5127334594727,0],[194.6376953125,75.2337265014648,0],[195.429443359375,75.9724807739258,0],[196.221206665039,76.7164306640625,0],[197.012954711914,77.4811859130859,0],[197.804718017578,78.2491912841797,0],[198.596481323242,79.0380401611328,0],[199.388229370117,79.8314208984375,0],[200.179992675781,80.6420516967773,0],[200.971740722656,81.4601669311523,0],[201.76350402832,82.2920227050781,0],[202.555267333984,83.1341247558594,0],[203.347015380859,83.986572265625,0],[204.138778686523,84.8517761230469,0],[204.930541992188,85.7240905761719,0],[205.722290039062,86.6114044189453,0],[206.514053344727,87.5027847290039,0],[207.305801391602,88.4110946655273,0],[208.097564697266,89.3219528198242,0],[208.88932800293,90.2487258911133,0],[209.681076049805,91.1790466308594,0],[210.472839355469,92.1219711303711,0],[211.264602661133,93.0703811645508,0],[212.056350708008,94.0283279418945,0],[212.848114013672,94.9933242797852,0],[213.639862060547,95.965087890625,0],[214.431625366211,96.9450607299805,0],[215.223388671875,97.9293670654297,0],[216.01513671875,98.9225997924805,0],[216.806900024414,99.918083190918,0],[217.598648071289,100.922775268555,0],[218.390411376953,101.928749084473,0],[219.182174682617,102.942260742188,0],[219.973922729492,103.957344055176,0],[220.765686035156,104.977577209473,0],[221.55744934082,105.999755859375,0],[222.349197387695,107.025115966797,0],[223.140960693359,108.052291870117,0],[223.932708740234,109.081123352051,0],[224.724472045898,110.111145019531,0],[225.516235351562,111.141761779785,0],[226.307983398438,112.172409057617,0],[227.099746704102,113.203063964844,0],[227.891510009766,114.232070922852,0],[228.683258056641,115.260650634766,0],[229.475021362305,116.286071777344,0],[230.26676940918,117.310188293457,0],[231.058532714844,118.330291748047,0],[231.850296020508,119.347610473633,0],[232.642044067383,120.360572814941,0],[233.433807373047,121.36873626709,0],[234.225555419922,122.372734069824,0],[235.017318725586,123.369400024414,0],[235.80908203125,124.362609863281,0],[236.600830078125,125.345443725586,0],[237.392593383789,126.326049804688,0],[238.184356689453,127.292724609375,0],[238.976104736328,128.257110595703,0],[239.767868041992,129.207183837891,0],[240.559616088867,130.152633666992,0],[241.351379394531,131.084808349609,0],[242.143142700195,132.009094238281,0],[242.93489074707,132.921676635742,0],[243.726654052734,133.822631835938,0],[244.518402099609,134.713989257812,0],[245.310165405273,135.589538574219,0],[246.101928710938,136.458068847656,0],[246.893676757812,137.306213378906,0],[247.685440063477,138.150375366211,0],[248.477203369141,138.969192504883,0],[249.268951416016,139.784088134766,0],[250.06071472168,140.575210571289,0],[250.852462768555,141.358596801758,0],[251.644226074219,142.121185302734,0],[252.435989379883,142.871398925781,0],[253.227737426758,143.604217529297,0],[254.019500732422,144.319732666016,0],[254.811264038086,145.021636962891,0],[255.603012084961,145.701034545898,0],[256.394775390625,146.370986938477,0],[257.1865234375,147.012985229492,0],[257.978302001953,147.650039672852,0],[258.770050048828,148.253540039062,0],[259.561798095703,148.85205078125,0],[260.353546142578,149.420837402344,0],[261.145324707031,149.979675292969,0],[261.937072753906,150.513305664062,0],[262.728820800781,151.031677246094,0],[263.520599365234,151.529632568359,0],[264.312347412109,152.006927490234,0],[265.104095458984,152.468780517578,0],[265.895874023438,152.904510498047,0],[266.687622070312,153.329925537109,0],[267.479370117188,153.723785400391,0],[268.271148681641,154.112335205078,0],[269.062896728516,154.464401245117,0],[269.854644775391,154.810913085938,0],[270.646392822266,155.126235961914,0],[271.438171386719,155.430755615234,0],[272.229919433594,155.70947265625,0],[273.021667480469,155.97216796875,0],[273.813446044922,156.214492797852,0],[274.605194091797,156.435729980469,0],[275.396942138672,156.641983032227,0],[276.188720703125,156.822219848633,0],[276.98046875,156.992828369141,0],[277.772216796875,157.132705688477,0],[278.563995361328,157.267517089844,0],[279.355743408203,157.368438720703,0],[280.147491455078,157.463836669922,0],[280.939239501953,157.530914306641,0],[281.731018066406,157.587814331055,0],[282.522766113281,157.621826171875,0],[283.314514160156,157.641250610352,0],[284.106292724609,157.643051147461,0],[284.898040771484,157.626174926758,0],[285.689788818359,157.5966796875,0],[286.481567382812,157.544723510742,0],[287.273315429688,157.484939575195,0],[288.065063476562,157.399230957031,0],[288.856842041016,157.309341430664,0],[289.648590087891,157.19221496582,0],[290.440338134766,157.070327758789,0],[291.232086181641,156.926239013672,0],[292.023864746094,156.773910522461,0],[292.815612792969,156.604080200195,0],[293.607360839844,156.422866821289,0],[294.399139404297,156.228546142578,0],[295.190887451172,156.020080566406,0],[295.982635498047,155.802581787109,0],[296.7744140625,155.568557739258,0],[297.566162109375,155.329162597656,0],[298.35791015625,155.071304321289,0],[299.149688720703,154.810531616211,0],[299.941436767578,154.531433105469,0],[300.733184814453,154.248962402344,0],[301.524932861328,153.952056884766,0],[302.316711425781,153.649688720703,0],[303.108459472656,153.336349487305,0],[303.900207519531,153.015853881836,0],[304.691986083984,152.687484741211,0],[305.483734130859,152.350631713867,0],[306.275482177734,152.008636474609,0],[307.067260742188,151.6572265625,0],[307.859008789062,151.302963256836,0],[308.650756835938,150.938766479492,0],[309.442535400391,150.57307434082,0],[310.234283447266,150.198379516602,0],[311.026031494141,149.822036743164,0],[311.817810058594,149.439163208008,0],[312.609558105469,149.053894042969,0],[313.401306152344,148.664154052734,0],[314.193054199219,148.271667480469,0],[314.984832763672,147.876342773438,0],[315.776580810547,147.478286743164,0],[316.568328857422,147.078674316406,0],[317.360107421875,146.676666259766,0],[318.15185546875,146.273971557617,0],[318.943603515625,145.869583129883,0],[319.735382080078,145.46501159668,0],[320.527130126953,145.059814453125,0],[321.318878173828,144.654708862305,0],[322.110656738281,144.249969482422,0],[322.902404785156,143.845794677734,0],[323.694152832031,143.442626953125,0],[324.485900878906,143.040786743164,0],[325.277679443359,142.640243530273,0],[326.069427490234,142.242065429688,0],[326.861175537109,141.845184326172,0],[327.652954101562,141.451950073242,0],[328.444702148438,141.059692382812,0],[329.236450195312,140.672637939453,0],[330.028228759766,140.286468505859,0],[330.819976806641,139.906204223633,0],[331.611724853516,139.527603149414,0],[332.403503417969,139.154632568359,0],[333.195251464844,138.78466796875,0],[333.986999511719,138.419784545898,0],[334.778747558594,138.059448242188,0],[335.570526123047,137.703399658203,0],[336.362274169922,137.353637695312,0],[337.154022216797,137.007110595703,0],[337.94580078125,136.668762207031,0],[338.737548828125,136.332412719727,0],[339.529296875,136.006271362305,0],[340.321075439453,135.681747436523,0],[341.112823486328,135.367477416992,0],[341.904571533203,135.056030273438,0],[342.696350097656,134.753570556641,0],[343.488098144531,134.455810546875,0],[344.279846191406,134.165603637695,0],[345.071594238281,133.882064819336,0],[345.863372802734,133.604507446289,0],[346.655120849609,133.335662841797,0],[347.446868896484,133.071090698242,0],[348.238647460938,132.817337036133,0],[349.030395507812,132.566024780273,0],[349.822143554688,132.327682495117,0],[350.613922119141,132.09130859375,0],[351.405670166016,131.867156982422,0],[352.197418212891,131.646469116211,0],[352.989196777344,131.436111450195,0],[353.780944824219,131.231246948242,0],[354.572692871094,131.034744262695,0],[355.364471435547,130.845748901367,0],[356.156219482422,130.663131713867,0],[356.947967529297,130.490005493164,0],[357.739715576172,130.321212768555,0],[358.531494140625,130.163848876953,0],[359.3232421875,130.008804321289,0],[360.114990234375,129.86701965332,0],[360.906768798828,129.727172851562,0],[361.698516845703,129.599136352539,0],[362.490264892578,129.474563598633,0],[363.282043457031,129.359664916992,0],[364.073791503906,129.25,0],[364.865539550781,129.14794921875,0],[365.657318115234,129.052780151367,0],[366.449066162109,128.963195800781,0],[367.240814208984,128.882034301758,0],[368.032562255859,128.80451965332,0],[368.824340820312,128.736785888672,0],[369.616088867188,128.670883178711,0],[370.407836914062,128.615951538086,0],[371.199615478516,128.562545776367,0],[371.991363525391,128.518295288086,0],[372.783111572266,128.476806640625,0],[373.574890136719,128.442535400391,0],[374.366638183594,128.412170410156,0],[375.158386230469,128.38720703125,0],[375.950164794922,128.367111206055,0],[376.741912841797,128.350784301758,0],[377.533660888672,128.340072631836,0],[378.325408935547,128.331649780273,0],[379.1171875,128.329345703125,0],[379.908935546875,128.328079223633,0],[380.70068359375,128.33317565918,0],[381.492462158203,128.339065551758,0],[382.284210205078,128.349700927734,0],[383.075958251953,128.361679077148,0],[383.867736816406,128.376998901367,0],[384.659484863281,128.393966674805,0],[385.451232910156,128.4130859375,0],[386.243011474609,128.433898925781,0],[387.034759521484,128.455917358398,0],[387.826507568359,128.479385375977,0],[388.618255615234,128.503402709961,0],[389.410034179688,128.5283203125,0],[390.201782226562,128.553375244141,0],[390.993530273438,128.578536987305,0],[391.785308837891,128.603561401367,0],[392.577056884766,128.627868652344,0],[393.368804931641,128.651611328125,0],[394.160583496094,128.674087524414,0],[394.952331542969,128.695327758789,0],[395.744079589844,128.71501159668,0],[396.535858154297,128.732482910156,0],[397.327606201172,128.748428344727,0],[398.119354248047,128.760894775391,0],[398.9111328125,128.772125244141,0],[399.702880859375,128.778366088867,0],[400.49462890625,128.783782958984,0],[401.286376953125,128.782745361328,0],[402.078155517578,128.780456542969,0],[402.869903564453,128.771911621094,0],[403.661651611328,128.760726928711,0],[404.453430175781,128.743774414062,0],[405.245178222656,128.722549438477,0],[406.036926269531,128.696304321289,0],[406.828704833984,128.663925170898,0],[407.620452880859,128.627532958984,0],[408.412200927734,128.582931518555,0],[409.203979492188,128.535568237305,0],[409.995727539062,128.477722167969,0],[410.787475585938,128.41813659668,0],[411.579223632812,128.34651184082,0],[412.371002197266,128.272476196289,0],[413.162750244141,128.187622070312,0],[413.954498291016,128.098220825195,0],[414.746276855469,127.999465942383,0],[415.538024902344,127.893859863281,0],[416.329772949219,127.780555725098,0],[417.121551513672,127.657943725586,0],[417.913299560547,127.529518127441,0],[418.705047607422,127.389183044434,0],[419.496826171875,127.245079040527,0],[420.28857421875,127.086357116699,0],[421.080322265625,126.925277709961,0],[421.8720703125,126.748405456543,0],[422.663848876953,126.568237304688,0],[423.455596923828,126.374359130859,0],[424.247344970703,126.174613952637,0],[425.039123535156,125.963394165039,0],[425.830871582031,125.74365234375,0],[426.622619628906,125.514801025391,0],[427.414398193359,125.274726867676,0],[428.206146240234,125.028007507324,0],[428.997894287109,124.76734161377,0],[429.789672851562,124.502578735352,0],[430.581420898438,124.221130371094,0],[431.373168945312,123.937057495117,0],[432.164916992188,123.635856628418,0],[432.956695556641,123.33088684082,0],[433.748443603516,123.011421203613,0],[434.540191650391,122.685554504395,0],[435.331970214844,122.347854614258,0],[436.123718261719,122.001159667969,0],[436.915466308594,121.645317077637,0],[437.707244873047,121.277938842773,0],[438.498992919922,120.904083251953,0],[439.290740966797,120.516250610352,0],[440.08251953125,120.124588012695,0],[440.874267578125,119.716583251953,0],[441.666015625,119.306060791016,0],[442.457794189453,118.879539489746,0],[443.249542236328,118.449317932129,0],[444.041290283203,118.005859375,0],[444.833038330078,117.556381225586,0],[445.624816894531,117.096366882324,0],[446.416564941406,116.628150939941,0],[447.208312988281,116.152015686035,0],[448.000091552734,115.665657043457,0],[448.791839599609,115.173873901367,0],[449.583587646484,114.670013427734,0],[450.375366210938,114.1630859375,0],[451.167114257812,113.642417907715,0],[451.958862304688,113.119697570801,0],[452.750640869141,112.584205627441,0],[453.542388916016,112.045608520508,0],[454.334136962891,111.49674987793,0],[455.125885009766,110.94310760498,0],[455.917663574219,110.381546020508,0],[456.709411621094,109.813720703125,0],[457.501159667969,109.240142822266,0],[458.292938232422,108.659042358398,0],[459.084686279297,108.074172973633,0],[459.876434326172,107.480743408203,0],[460.668212890625,106.885314941406,0],[461.4599609375,106.280548095703,0],[462.251708984375,105.674438476562,0],[463.043487548828,105.06022644043,0],[463.835235595703,104.44401550293,0],[464.626983642578,103.821617126465,0],[465.418731689453,103.196350097656,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16480},&#34;190&#34;:{&#34;id&#34;:190,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.70000004768372,-2.70000004768372]},&#34;vertices&#34;:[[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[99.6267929077148,48.8652839660645,0],[338.737548828125,48.8652839660645,0],[100.418548583984,48.8652877807617,0],[338.737548828125,48.8652839660645,0],[99.6267929077148,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[97.2515182495117,48.8652801513672,0],[340.321075439453,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[102.002059936523,48.865291595459,0],[101.210304260254,48.8652877807617,0],[337.154022216797,48.8652877807617,0],[103.585578918457,48.8653030395508,0],[102.793823242188,48.8652954101562,0],[334.778747558594,48.8653030395508,0],[104.377334594727,48.8653106689453,0],[103.585578918457,48.8653030395508,0],[334.778747558594,48.8653030395508,0],[102.002059936523,48.865291595459,0],[336.362274169922,48.865291595459,0],[102.793823242188,48.8652954101562,0],[105.96085357666,48.8653335571289,0],[105.169090270996,48.8653221130371,0],[333.195251464844,48.8653221130371,0],[107.544364929199,48.8653755187988,0],[106.75260925293,48.8653526306152,0],[331.611724853516,48.8653526306152,0],[108.336120605469,48.865406036377,0],[107.544364929199,48.8653755187988,0],[330.819976806641,48.8653755187988,0],[105.96085357666,48.8653335571289,0],[332.403503417969,48.8653335571289,0],[106.75260925293,48.8653526306152,0],[104.377334594727,48.8653106689453,0],[333.986999511719,48.8653106689453,0],[105.169090270996,48.8653221130371,0],[100.418548583984,48.8652877807617,0],[337.154022216797,48.8652877807617,0],[101.210304260254,48.8652877807617,0],[109.919639587402,48.8654937744141,0],[109.127883911133,48.8654441833496,0],[329.236450195312,48.8654479980469,0],[111.503150939941,48.8656463623047,0],[110.711395263672,48.8655586242676,0],[327.652954101562,48.8655662536621,0],[112.294914245605,48.8657531738281,0],[111.503150939941,48.8656463623047,0],[326.861175537109,48.8656578063965,0],[109.919639587402,48.8654937744141,0],[328.444702148438,48.8655014038086,0],[110.711395263672,48.8655586242676,0],[113.878425598145,48.8660736083984,0],[113.086669921875,48.8658905029297,0],[324.485900878906,48.866096496582,0],[115.461944580078,48.8665924072266,0],[114.670181274414,48.8663024902344,0],[323.694152832031,48.866340637207,0],[116.253700256348,48.866943359375,0],[115.461944580078,48.8665924072266,0],[322.902404785156,48.8666496276855,0],[113.878425598145,48.8660736083984,0],[324.485900878906,48.866096496582,0],[114.670181274414,48.8663024902344,0],[112.294914245605,48.8657531738281,0],[326.069427490234,48.8657722473145,0],[113.086669921875,48.8658905029297,0],[117.837211608887,48.8680267333984,0],[117.045455932617,48.8674240112305,0],[321.318878173828,48.867504119873,0],[119.42073059082,48.8696708679199,0],[118.628967285156,48.868766784668,0],[319.735382080078,48.8689308166504,0],[120.21248626709,48.8708457946777,0],[119.42073059082,48.8696708679199,0],[318.943603515625,48.8699111938477,0],[117.837211608887,48.8680267333984,0],[320.527130126953,48.8681335449219,0],[118.628967285156,48.868766784668,0],[121.795997619629,48.8741569519043,0],[121.004241943359,48.8723335266113,0],[317.360107421875,48.8726463317871,0],[123.379516601562,48.8791236877441,0],[122.587760925293,48.8763694763184,0],[315.776580810547,48.8770141601562,0],[124.171272277832,48.8826522827148,0],[123.379516601562,48.8791236877441,0],[314.984832763672,48.8799324035645,0],[121.795997619629,48.8741569519043,0],[316.568328857422,48.8746109008789,0],[122.587760925293,48.8763694763184,0],[120.21248626709,48.8708457946777,0],[318.15185546875,48.8711128234863,0],[121.004241943359,48.8723335266113,0],[116.253700256348,48.866943359375,0],[321.318878173828,48.867504119873,0],[117.045455932617,48.8674240112305,0],[108.336120605469,48.865406036377,0],[330.028228759766,48.8654098510742,0],[109.127883911133,48.8654441833496,0],[125.754791259766,48.8920974731445,0],[124.963027954102,48.8869361877441,0],[313.401306152344,48.8881530761719,0],[127.338302612305,48.9062843322754,0],[126.546546936035,48.8982849121094,0],[311.817810058594,48.900562286377,0],[128.130065917969,48.9159126281738,0],[127.338302612305,48.9062843322754,0],[311.026031494141,48.9086608886719,0],[125.754791259766,48.8920974731445,0],[312.609558105469,48.8937797546387,0],[126.546546936035,48.8982849121094,0],[129.713577270508,48.941032409668,0],[128.921813964844,48.9274101257324,0],[309.442535400391,48.9316711425781,0],[131.297088623047,48.9787521362305,0],[130.505325317383,48.958080291748,0],[307.859008789062,48.9645843505859,0],[132.088851928711,49.0032196044922,0],[131.297088623047,48.9787521362305,0],[307.067260742188,48.9866256713867,0],[129.713577270508,48.941032409668,0],[308.650756835938,48.9467315673828,0],[130.505325317383,48.958080291748,0],[128.130065917969,48.9159126281738,0],[310.234283447266,48.9190635681152,0],[128.921813964844,48.9274101257324,0],[133.67236328125,49.0666656494141,0],[132.880599975586,49.0319786071777,0],[305.483734130859,49.0456047058105,0],[135.255874633789,49.158805847168,0],[134.464126586914,49.109073638916,0],[303.900207519531,49.128002166748,0],[136.047637939453,49.2167510986328,0],[135.255874633789,49.158805847168,0],[303.108459472656,49.1833190917969,0],[133.67236328125,49.0666656494141,0],[304.691986083984,49.083194732666,0],[134.464126586914,49.109073638916,0],[137.631149291992,49.3674964904785,0],[136.839385986328,49.284366607666,0],[301.524932861328,49.323860168457,0],[139.214660644531,49.5754928588867,0],[138.422912597656,49.4640350341797,0],[299.941436767578,49.5195579528809,0],[140.006423950195,49.7034378051758,0],[139.214660644531,49.5754928588867,0],[299.149688720703,49.6454696655273,0],[137.631149291992,49.3674964904785,0],[300.733184814453,49.411491394043,0],[138.422912597656,49.4640350341797,0],[136.047637939453,49.2167510986328,0],[302.316711425781,49.2482109069824,0],[136.839385986328,49.284366607666,0],[132.088851928711,49.0032196044922,0],[306.275482177734,49.0136299133301,0],[132.880599975586,49.0319786071777,0],[141.589935302734,50.0363273620605,0],[140.798187255859,49.8573837280273,0],[297.566162109375,49.9580116271973,0],[143.173446655273,50.4737358093262,0],[142.381698608398,50.2409515380859,0],[295.982635498047,50.3905982971191,0],[143.965209960938,50.7449493408203,0],[143.173446655273,50.4737358093262,0],[295.190887451172,50.657829284668,0],[141.589935302734,50.0363273620605,0],[296.7744140625,50.1570777893066,0],[142.381698608398,50.2409515380859,0],[145.548721313477,51.4201202392578,0],[144.756973266602,51.0616111755371,0],[293.607360839844,51.3134574890137,0],[147.132232666016,52.281364440918,0],[146.340484619141,51.824089050293,0],[292.815612792969,51.7273368835449,0],[147.92399597168,52.8161659240723,0],[147.132232666016,52.281364440918,0],[291.232086181641,52.7252502441406,0],[145.548721313477,51.4201202392578,0],[293.607360839844,51.3134574890137,0],[146.340484619141,51.824089050293,0],[143.965209960938,50.7449493408203,0],[294.399139404297,50.9620628356934,0],[144.756973266602,51.0616111755371,0],[149.507507324219,54.083911895752,0],[148.715759277344,53.4153900146484,0],[290.440338134766,53.3194198608398,0],[151.091033935547,55.6830787658691,0],[150.299270629883,54.8266944885254,0],[288.856842041016,54.8061447143555,0],[151.882781982422,56.6382141113281,0],[151.091033935547,55.6830787658691,0],[288.065063476562,55.6839256286621,0],[149.507507324219,54.083911895752,0],[289.648590087891,54.0201644897461,0],[150.299270629883,54.8266944885254,0],[153.466293334961,58.8528938293457,0],[152.674545288086,57.6928176879883,0],[286.481567382812,57.7787246704102,0],[155.049819946289,61.6048889160156,0],[154.258056640625,60.1537780761719,0],[284.898040771484,60.4259300231934,0],[155.841567993164,63.1899833679199,0],[155.049819946289,61.6048889160156,0],[284.106292724609,61.9565620422363,0],[153.466293334961,58.8528938293457,0],[285.689788818359,59.0360450744629,0],[154.258056640625,60.1537780761719,0],[151.882781982422,56.6382141113281,0],[287.273315429688,56.6601982116699,0],[152.674545288086,57.6928176879883,0],[147.92399597168,52.8161659240723,0],[290.440338134766,53.3194198608398,0],[148.715759277344,53.4153900146484,0],[140.006423950195,49.7034378051758,0],[298.35791015625,49.7909240722656,0],[140.798187255859,49.8573837280273,0],[124.171272277832,48.8826522827148,0],[314.193054199219,48.8835144042969,0],[124.963027954102,48.8869361877441,0],[157.425094604492,66.8033218383789,0],[156.633331298828,64.9154663085938,0],[282.522766113281,65.5824813842773,0],[159.008605957031,71.171745300293,0],[158.216842651367,68.9032745361328,0],[280.939239501953,69.9681777954102,0],[157.425094604492,66.8033218383789,0],[281.731018066406,67.6809692382812,0],[158.216842651367,68.9032745361328,0],[160.59211730957,76.2368850708008,0],[159.800354003906,73.6144180297852,0],[279.355743408203,75.2499465942383,0],[162.175628662109,82.2107162475586,0],[161.383880615234,79.1220474243164,0],[277.772216796875,81.5232696533203,0],[162.967391967773,85.4992218017578,0],[162.175628662109,82.2107162475586,0],[277.772216796875,81.5232696533203,0],[160.59211730957,76.2368850708008,0],[278.563995361328,78.2685775756836,0],[161.383880615234,79.1220474243164,0],[159.008605957031,71.171745300293,0],[280.147491455078,72.4593353271484,0],[159.800354003906,73.6144180297852,0],[275.396942138672,92.9917755126953,0],[165.342666625977,96.7394561767578,0],[164.550903320312,92.7424850463867,0],[273.813446044922,102.08031463623,0],[166.926177978516,105.359741210938,0],[166.134414672852,100.945457458496,0],[273.021667480469,107.100212097168,0],[167.71794128418,110.00602722168,0],[166.926177978516,105.359741210938,0],[166.134414672852,100.945457458496,0],[165.342666625977,96.7394561767578,0],[274.605194091797,97.3972091674805,0],[271.438171386719,118.139717102051,0],[169.301452636719,120.020172119141,0],[168.509689331055,114.915924072266,0],[270.646392822266,124.089736938477,0],[170.884963989258,130.787979125977,0],[170.093200683594,125.312934875488,0],[269.854644775391,130.340209960938,0],[171.676727294922,136.502426147461,0],[170.884963989258,130.787979125977,0],[170.093200683594,125.312934875488,0],[169.301452636719,120.020172119141,0],[270.646392822266,124.089736938477,0],[168.509689331055,114.915924072266,0],[167.71794128418,110.00602722168,0],[272.229919433594,112.476234436035,0],[164.550903320312,92.7424850463867,0],[163.759140014648,88.9907760620117,0],[276.188720703125,88.8593368530273,0],[268.271148681641,143.874450683594,0],[173.260238647461,148.379653930664,0],[172.468475341797,142.370712280273,0],[266.687622070312,158.444854736328,0],[174.84375,160.798126220703,0],[174.051986694336,154.517883300781,0],[175.635513305664,167.177520751953,0],[265.895874023438,166.168609619141,0],[176.427261352539,173.624633789062,0],[174.051986694336,154.517883300781,0],[173.260238647461,148.379653930664,0],[267.479370117188,151.034591674805,0],[177.219024658203,180.12419128418,0],[264.312347412109,182.25373840332,0],[178.010787963867,186.661285400391,0],[178.802536010742,193.203552246094,0],[262.728820800781,199.049026489258,0],[179.594299316406,199.725006103516,0],[179.594299316406,199.725006103516,0],[262.728820800781,199.049026489258,0],[180.386047363281,206.209075927734,0],[263.520599365234,190.562606811523,0],[178.802536010742,193.203552246094,0],[178.010787963867,186.661285400391,0],[265.104095458984,174.116668701172,0],[177.219024658203,180.12419128418,0],[176.427261352539,173.624633789062,0],[261.145324707031,216.365173339844,0],[182.761322021484,225.150573730469,0],[181.969573974609,218.949417114258,0],[260.353546142578,225.115921020508,0],[183.553085327148,231.226837158203,0],[182.761322021484,225.150573730469,0],[183.553085327148,231.226837158203,0],[259.561798095703,233.894592285156,0],[184.344848632812,237.163757324219,0],[181.177810668945,212.638122558594,0],[261.145324707031,216.365173339844,0],[181.969573974609,218.949417114258,0],[185.136596679688,242.890838623047,0],[258.770050048828,242.646850585938,0],[185.928359985352,248.414215087891,0],[187.511871337891,258.869110107422,0],[186.720108032227,253.74348449707,0],[257.978302001953,251.336441040039,0],[186.720108032227,253.74348449707,0],[185.928359985352,248.414215087891,0],[257.978302001953,251.336441040039,0],[184.344848632812,237.163757324219,0],[259.561798095703,233.894592285156,0],[185.136596679688,242.890838623047,0],[180.386047363281,206.209075927734,0],[261.937072753906,207.668258666992,0],[181.177810668945,212.638122558594,0],[265.895874023438,166.168609619141,0],[175.635513305664,167.177520751953,0],[174.84375,160.798126220703,0],[172.468475341797,142.370712280273,0],[171.676727294922,136.502426147461,0],[269.062896728516,136.973510742188,0],[190.678894042969,276.805847167969,0],[255.603012084961,276.680541992188,0],[191.470657348633,280.677154541016,0],[193.054168701172,287.514343261719,0],[192.262420654297,284.214385986328,0],[254.811264038086,284.722106933594,0],[191.470657348633,280.677154541016,0],[255.603012084961,276.680541992188,0],[192.262420654297,284.214385986328,0],[256.394775390625,268.419677734375,0],[190.678894042969,276.805847167969,0],[189.887145996094,272.6865234375,0],[254.811264038086,284.722106933594,0],[194.6376953125,293.415374755859,0],[193.845932006836,290.580169677734,0],[195.429443359375,295.953002929688,0],[254.019500732422,292.528167724609,0],[196.221206665039,298.258178710938,0],[254.019500732422,292.528167724609,0],[195.429443359375,295.953002929688,0],[194.6376953125,293.415374755859,0],[254.811264038086,284.722106933594,0],[193.845932006836,290.580169677734,0],[193.054168701172,287.514343261719,0],[189.09538269043,268.3310546875,0],[256.394775390625,268.419677734375,0],[189.887145996094,272.6865234375,0],[197.012954711914,300.360198974609,0],[210.472839355469,314.785491943359,0],[197.804718017578,302.266967773438,0],[199.388229370117,305.432434082031,0],[198.596481323242,303.953186035156,0],[208.88932800293,314.082916259766,0],[198.596481323242,303.953186035156,0],[197.804718017578,302.266967773438,0],[209.681076049805,314.433868408203,0],[211.264602661133,315.144653320312,0],[197.012954711914,300.360198974609,0],[196.221206665039,298.258178710938,0],[207.305801391602,313.332305908203,0],[200.971755981445,307.937683105469,0],[200.179992675781,306.757354736328,0],[200.971755981445,307.937683105469,0],[202.555267333984,309.854919433594,0],[201.76350402832,308.975830078125,0],[206.514053344727,312.910369873047,0],[202.555267333984,309.854919433594,0],[200.971755981445,307.937683105469,0],[208.097564697266,313.721160888672,0],[200.179992675781,306.757354736328,0],[199.388229370117,305.432434082031,0],[196.221206665039,298.258178710938,0],[254.019500732422,292.528167724609,0],[211.264602661133,315.144653320312,0],[188.303634643555,263.742523193359,0],[257.1865234375,259.936401367188,0],[189.09538269043,268.3310546875,0],[204.138778686523,311.322357177734,0],[203.347015380859,310.633911132812,0],[205.722290039062,312.447174072266,0],[204.138778686523,311.322357177734,0],[205.722290039062,312.447174072266,0],[204.930541992188,311.929718017578,0],[205.722290039062,312.447174072266,0],[203.347015380859,310.633911132812,0],[206.514053344727,312.910369873047,0],[202.555267333984,309.854919433594,0],[206.514053344727,312.910369873047,0],[203.347015380859,310.633911132812,0],[200.971755981445,307.937683105469,0],[207.305801391602,313.332305908203,0],[206.514053344727,312.910369873047,0],[200.179992675781,306.757354736328,0],[208.097564697266,313.721160888672,0],[207.305801391602,313.332305908203,0],[199.388229370117,305.432434082031,0],[208.88932800293,314.082916259766,0],[208.097564697266,313.721160888672,0],[209.681076049805,314.433868408203,0],[208.88932800293,314.082916259766,0],[198.596481323242,303.953186035156,0],[210.472839355469,314.785491943359,0],[209.681076049805,314.433868408203,0],[197.804718017578,302.266967773438,0],[210.472839355469,314.785491943359,0],[197.012954711914,300.360198974609,0],[211.264602661133,315.144653320312,0],[254.019500732422,292.528167724609,0],[213.639862060547,316.380187988281,0],[212.848114013672,315.93212890625,0],[253.227737426758,300.074066162109,0],[214.431625366211,316.870635986328,0],[213.639862060547,316.380187988281,0],[211.264602661133,315.144653320312,0],[254.019500732422,292.528167724609,0],[212.056350708008,315.5205078125,0],[253.227737426758,300.074066162109,0],[216.01513671875,318.027954101562,0],[215.223388671875,317.409362792969,0],[252.435989379883,307.255310058594,0],[217.598648071289,319.477447509766,0],[216.806900024414,318.716583251953,0],[252.435989379883,307.255310058594,0],[218.390411376953,320.315216064453,0],[217.598648071289,319.477447509766,0],[216.806900024414,318.716583251953,0],[216.01513671875,318.027954101562,0],[252.435989379883,307.255310058594,0],[215.223388671875,317.409362792969,0],[214.431625366211,316.870635986328,0],[253.227737426758,300.074066162109,0],[212.056350708008,315.5205078125,0],[254.019500732422,292.528167724609,0],[212.848114013672,315.93212890625,0],[187.511871337891,258.869110107422,0],[257.1865234375,259.936401367188,0],[188.303634643555,263.742523193359,0],[163.759140014648,88.9907760620117,0],[162.967391967773,85.4992218017578,0],[276.98046875,85.0218887329102,0],[155.841567993164,63.1899833679199,0],[283.314514160156,63.6638336181641,0],[156.633331298828,64.9154663085938,0],[302.316711425781,49.2482109069824,0],[301.524932861328,49.323860168457,0],[136.839385986328,49.284366607666,0],[303.900207519531,49.128002166748,0],[303.108459472656,49.1833190917969,0],[135.255874633789,49.158805847168,0],[302.316711425781,49.2482109069824,0],[136.047637939453,49.2167510986328,0],[303.108459472656,49.1833190917969,0],[298.35791015625,49.7909240722656,0],[297.566162109375,49.9580116271973,0],[140.798187255859,49.8573837280273,0],[299.941436767578,49.5195579528809,0],[299.149688720703,49.6454696655273,0],[139.214660644531,49.5754928588867,0],[300.733184814453,49.411491394043,0],[299.941436767578,49.5195579528809,0],[138.422912597656,49.4640350341797,0],[298.35791015625,49.7909240722656,0],[140.006423950195,49.7034378051758,0],[299.149688720703,49.6454696655273,0],[301.524932861328,49.323860168457,0],[300.733184814453,49.411491394043,0],[137.631149291992,49.3674964904785,0],[309.442535400391,48.9316711425781,0],[308.650756835938,48.9467315673828,0],[129.713577270508,48.941032409668,0],[311.026031494141,48.9086608886719,0],[310.234283447266,48.9190635681152,0],[128.130065917969,48.9159126281738,0],[311.817810058594,48.900562286377,0],[311.026031494141,48.9086608886719,0],[127.338302612305,48.9062843322754,0],[309.442535400391,48.9316711425781,0],[128.921813964844,48.9274101257324,0],[310.234283447266,48.9190635681152,0],[305.483734130859,49.0456047058105,0],[304.691986083984,49.083194732666,0],[133.67236328125,49.0666656494141,0],[307.067260742188,48.9866256713867,0],[306.275482177734,49.0136299133301,0],[132.088851928711,49.0032196044922,0],[307.859008789062,48.9645843505859,0],[307.067260742188,48.9866256713867,0],[131.297088623047,48.9787521362305,0],[305.483734130859,49.0456047058105,0],[132.880599975586,49.0319786071777,0],[306.275482177734,49.0136299133301,0],[308.650756835938,48.9467315673828,0],[307.859008789062,48.9645843505859,0],[130.505325317383,48.958080291748,0],[303.900207519531,49.128002166748,0],[134.464126586914,49.109073638916,0],[304.691986083984,49.083194732666,0],[286.481567382812,57.7787246704102,0],[285.689788818359,59.0360450744629,0],[153.466293334961,58.8528938293457,0],[288.065063476562,55.6839256286621,0],[287.273315429688,56.6601982116699,0],[151.882781982422,56.6382141113281,0],[288.856842041016,54.8061447143555,0],[288.065063476562,55.6839256286621,0],[151.091033935547,55.6830787658691,0],[286.481567382812,57.7787246704102,0],[152.674545288086,57.6928176879883,0],[287.273315429688,56.6601982116699,0],[282.522766113281,65.5824813842773,0],[281.731018066406,67.6809692382812,0],[157.425094604492,66.8033218383789,0],[284.106292724609,61.9565620422363,0],[283.314514160156,63.6638336181641,0],[155.841567993164,63.1899833679199,0],[284.898040771484,60.4259300231934,0],[284.106292724609,61.9565620422363,0],[155.049819946289,61.6048889160156,0],[282.522766113281,65.5824813842773,0],[156.633331298828,64.9154663085938,0],[283.314514160156,63.6638336181641,0],[285.689788818359,59.0360450744629,0],[284.898040771484,60.4259300231934,0],[154.258056640625,60.1537780761719,0],[294.399139404297,50.9620628356934,0],[293.607360839844,51.3134574890137,0],[144.756973266602,51.0616111755371,0],[295.982635498047,50.3905982971191,0],[295.190887451172,50.657829284668,0],[143.173446655273,50.4737358093262,0],[296.7744140625,50.1570777893066,0],[295.982635498047,50.3905982971191,0],[142.381698608398,50.2409515380859,0],[294.399139404297,50.9620628356934,0],[143.965209960938,50.7449493408203,0],[295.190887451172,50.657829284668,0],[290.440338134766,53.3194198608398,0],[289.648590087891,54.0201644897461,0],[149.507507324219,54.083911895752,0],[292.023864746094,52.1963233947754,0],[291.232086181641,52.7252502441406,0],[147.132232666016,52.281364440918,0],[292.815612792969,51.7273368835449,0],[292.023864746094,52.1963233947754,0],[147.132232666016,52.281364440918,0],[290.440338134766,53.3194198608398,0],[147.92399597168,52.8161659240723,0],[291.232086181641,52.7252502441406,0],[293.607360839844,51.3134574890137,0],[292.815612792969,51.7273368835449,0],[146.340484619141,51.824089050293,0],[288.856842041016,54.8061447143555,0],[150.299270629883,54.8266944885254,0],[289.648590087891,54.0201644897461,0],[297.566162109375,49.9580116271973,0],[296.7744140625,50.1570777893066,0],[141.589935302734,50.0363273620605,0],[333.195251464844,48.8653221130371,0],[332.403503417969,48.8653335571289,0],[105.96085357666,48.8653335571289,0],[334.778747558594,48.8653030395508,0],[333.986999511719,48.8653106689453,0],[104.377334594727,48.8653106689453,0],[335.570526123047,48.8652992248535,0],[334.778747558594,48.8653030395508,0],[102.793823242188,48.8652954101562,0],[333.195251464844,48.8653221130371,0],[105.169090270996,48.8653221130371,0],[333.986999511719,48.8653106689453,0],[329.236450195312,48.8654479980469,0],[328.444702148438,48.8655014038086,0],[109.919639587402,48.8654937744141,0],[330.819976806641,48.8653755187988,0],[330.028228759766,48.8654098510742,0],[108.336120605469,48.865406036377,0],[331.611724853516,48.8653526306152,0],[330.819976806641,48.8653755187988,0],[107.544364929199,48.8653755187988,0],[329.236450195312,48.8654479980469,0],[109.127883911133,48.8654441833496,0],[330.028228759766,48.8654098510742,0],[332.403503417969,48.8653335571289,0],[331.611724853516,48.8653526306152,0],[106.75260925293,48.8653526306152,0],[343.488098144531,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[337.154022216797,48.8652877807617,0],[336.362274169922,48.865291595459,0],[102.002059936523,48.865291595459,0],[338.737548828125,48.8652839660645,0],[337.94580078125,48.8652877807617,0],[100.418548583984,48.8652877807617,0],[340.321075439453,48.8652839660645,0],[338.737548828125,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[337.154022216797,48.8652877807617,0],[100.418548583984,48.8652877807617,0],[337.94580078125,48.8652877807617,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652839660645,0],[97.2515182495117,48.8652801513672,0],[335.570526123047,48.8652992248535,0],[102.793823242188,48.8652954101562,0],[336.362274169922,48.865291595459,0],[317.360107421875,48.8726463317871,0],[316.568328857422,48.8746109008789,0],[121.795997619629,48.8741569519043,0],[318.943603515625,48.8699111938477,0],[318.15185546875,48.8711128234863,0],[120.21248626709,48.8708457946777,0],[319.735382080078,48.8689308166504,0],[318.943603515625,48.8699111938477,0],[119.42073059082,48.8696708679199,0],[317.360107421875,48.8726463317871,0],[121.004241943359,48.8723335266113,0],[318.15185546875,48.8711128234863,0],[313.401306152344,48.8881530761719,0],[312.609558105469,48.8937797546387,0],[125.754791259766,48.8920974731445,0],[314.984832763672,48.8799324035645,0],[314.193054199219,48.8835144042969,0],[124.171272277832,48.8826522827148,0],[315.776580810547,48.8770141601562,0],[314.984832763672,48.8799324035645,0],[123.379516601562,48.8791236877441,0],[313.401306152344,48.8881530761719,0],[124.963027954102,48.8869361877441,0],[314.193054199219,48.8835144042969,0],[316.568328857422,48.8746109008789,0],[315.776580810547,48.8770141601562,0],[122.587760925293,48.8763694763184,0],[325.277679443359,48.8659172058105,0],[324.485900878906,48.866096496582,0],[113.086669921875,48.8658905029297,0],[326.861175537109,48.8656578063965,0],[326.069427490234,48.8657722473145,0],[112.294914245605,48.8657531738281,0],[327.652954101562,48.8655662536621,0],[326.861175537109,48.8656578063965,0],[111.503150939941,48.8656463623047,0],[325.277679443359,48.8659172058105,0],[113.086669921875,48.8658905029297,0],[326.069427490234,48.8657722473145,0],[321.318878173828,48.867504119873,0],[320.527130126953,48.8681335449219,0],[117.837211608887,48.8680267333984,0],[322.902404785156,48.8666496276855,0],[322.110656738281,48.8670310974121,0],[116.253700256348,48.866943359375,0],[323.694152832031,48.866340637207,0],[322.902404785156,48.8666496276855,0],[115.461944580078,48.8665924072266,0],[321.318878173828,48.867504119873,0],[116.253700256348,48.866943359375,0],[322.110656738281,48.8670310974121,0],[324.485900878906,48.866096496582,0],[323.694152832031,48.866340637207,0],[114.670181274414,48.8663024902344,0],[319.735382080078,48.8689308166504,0],[118.628967285156,48.868766784668,0],[320.527130126953,48.8681335449219,0],[328.444702148438,48.8655014038086,0],[327.652954101562,48.8655662536621,0],[110.711395263672,48.8655586242676,0],[311.817810058594,48.900562286377,0],[126.546546936035,48.8982849121094,0],[312.609558105469,48.8937797546387,0],[251.644226074219,314.041931152344,0],[220.765686035156,323.446166992188,0],[219.973922729492,322.304840087891,0],[250.852462768555,320.471893310547,0],[222.349197387695,326.029479980469,0],[221.55744934082,324.683227539062,0],[221.55744934082,324.683227539062,0],[220.765686035156,323.446166992188,0],[251.644226074219,314.041931152344,0],[250.06071472168,326.528106689453,0],[223.932708740234,329.080413818359,0],[223.140960693359,327.506164550781,0],[250.06071472168,326.528106689453,0],[225.516235351562,332.512420654297,0],[224.724472045898,330.750030517578,0],[249.268951416016,332.150177001953,0],[225.516235351562,332.512420654297,0],[250.06071472168,326.528106689453,0],[224.724472045898,330.750030517578,0],[223.932708740234,329.080413818359,0],[250.06071472168,326.528106689453,0],[223.140960693359,327.506164550781,0],[222.349197387695,326.029479980469,0],[250.852462768555,320.471893310547,0],[227.099746704102,336.352783203125,0],[226.307983398438,334.394927978516,0],[249.268951416016,332.150177001953,0],[227.099746704102,336.352783203125,0],[248.477203369141,337.22216796875,0],[227.891510009766,338.375549316406,0],[248.477203369141,337.22216796875,0],[227.099746704102,336.352783203125,0],[249.268951416016,332.150177001953,0],[227.891510009766,338.375549316406,0],[248.477203369141,337.22216796875,0],[228.683258056641,340.4541015625,0],[226.307983398438,334.394927978516,0],[225.516235351562,332.512420654297,0],[249.268951416016,332.150177001953,0],[229.475021362305,342.583435058594,0],[228.683258056641,340.4541015625,0],[247.685440063477,341.865234375,0],[230.26676940918,344.732452392578,0],[247.685440063477,341.865234375,0],[246.893676757812,346.073364257812,0],[247.685440063477,341.865234375,0],[230.26676940918,344.732452392578,0],[229.475021362305,342.583435058594,0],[230.26676940918,344.732452392578,0],[246.893676757812,346.073364257812,0],[231.058532714844,346.879364013672,0],[228.683258056641,340.4541015625,0],[248.477203369141,337.22216796875,0],[247.685440063477,341.865234375,0],[219.973922729492,322.304840087891,0],[219.182174682617,321.257019042969,0],[251.644226074219,314.041931152344,0],[232.642044067383,351.092010498047,0],[246.101928710938,349.841461181641,0],[233.433807373047,353.08251953125,0],[235.017318725586,356.734161376953,0],[234.225555419922,354.97021484375,0],[244.518417358398,355.684478759766,0],[234.225555419922,354.97021484375,0],[233.433807373047,353.08251953125,0],[245.310165405273,352.988800048828,0],[246.101928710938,349.841461181641,0],[232.642044067383,351.092010498047,0],[231.850296020508,349.008087158203,0],[243.726654052734,357.947692871094,0],[236.600830078125,359.708374023438,0],[235.80908203125,358.352355957031,0],[237.392593383789,360.842071533203,0],[242.143142700195,361.101409912109,0],[238.184356689453,361.731781005859,0],[236.600830078125,359.708374023438,0],[242.93489074707,359.785400390625,0],[237.392593383789,360.842071533203,0],[243.726654052734,357.947692871094,0],[235.80908203125,358.352355957031,0],[235.017318725586,356.734161376953,0],[231.058532714844,346.879364013672,0],[246.893676757812,346.073364257812,0],[231.850296020508,349.008087158203,0],[242.93489074707,359.785400390625,0],[236.600830078125,359.708374023438,0],[243.726654052734,357.947692871094,0],[235.017318725586,356.734161376953,0],[244.518417358398,355.684478759766,0],[243.726654052734,357.947692871094,0],[244.518417358398,355.684478759766,0],[234.225555419922,354.97021484375,0],[245.310165405273,352.988800048828,0],[237.392593383789,360.842071533203,0],[242.93489074707,359.785400390625,0],[242.143142700195,361.101409912109,0],[239.767868041992,362.593139648438,0],[238.976104736328,362.35595703125,0],[240.559616088867,362.454956054688,0],[238.976104736328,362.35595703125,0],[241.351379394531,361.963195800781,0],[240.559616088867,362.454956054688,0],[238.976104736328,362.35595703125,0],[238.184356689453,361.731781005859,0],[241.351379394531,361.963195800781,0],[242.143142700195,361.101409912109,0],[241.351379394531,361.963195800781,0],[238.184356689453,361.731781005859,0],[245.310165405273,352.988800048828,0],[233.433807373047,353.08251953125,0],[246.101928710938,349.841461181641,0],[246.893676757812,346.073364257812,0],[246.101928710938,349.841461181641,0],[231.850296020508,349.008087158203,0],[269.062896728516,136.973510742188,0],[171.676727294922,136.502426147461,0],[269.854644775391,130.340209960938,0],[270.646392822266,124.089736938477,0],[169.301452636719,120.020172119141,0],[271.438171386719,118.139717102051,0],[271.438171386719,118.139717102051,0],[168.509689331055,114.915924072266,0],[272.229919433594,112.476234436035,0],[170.884963989258,130.787979125977,0],[270.646392822266,124.089736938477,0],[269.854644775391,130.340209960938,0],[265.104095458984,174.116668701172,0],[176.427261352539,173.624633789062,0],[265.895874023438,166.168609619141,0],[266.687622070312,158.444854736328,0],[174.051986694336,154.517883300781,0],[267.479370117188,151.034591674805,0],[267.479370117188,151.034591674805,0],[173.260238647461,148.379653930664,0],[268.271148681641,143.874450683594,0],[174.84375,160.798126220703,0],[266.687622070312,158.444854736328,0],[265.895874023438,166.168609619141,0],[268.271148681641,143.874450683594,0],[172.468475341797,142.370712280273,0],[269.062896728516,136.973510742188,0],[276.98046875,85.0218887329102,0],[162.967391967773,85.4992218017578,0],[277.772216796875,81.5232696533203,0],[280.147491455078,72.4593353271484,0],[279.355743408203,75.2499465942383,0],[159.800354003906,73.6144180297852,0],[280.939239501953,69.9681777954102,0],[280.147491455078,72.4593353271484,0],[159.008605957031,71.171745300293,0],[278.563995361328,78.2685775756836,0],[160.59211730957,76.2368850708008,0],[279.355743408203,75.2499465942383,0],[273.021667480469,107.100212097168,0],[166.926177978516,105.359741210938,0],[273.813446044922,102.08031463623,0],[274.605194091797,97.3972091674805,0],[165.342666625977,96.7394561767578,0],[275.396942138672,92.9917755126953,0],[275.396942138672,92.9917755126953,0],[164.550903320312,92.7424850463867,0],[276.188720703125,88.8593368530273,0],[166.134414672852,100.945457458496,0],[274.605194091797,97.3972091674805,0],[273.813446044922,102.08031463623,0],[276.188720703125,88.8593368530273,0],[163.759140014648,88.9907760620117,0],[276.98046875,85.0218887329102,0],[167.71794128418,110.00602722168,0],[273.021667480469,107.100212097168,0],[272.229919433594,112.476234436035,0],[213.639862060547,316.380187988281,0],[254.019500732422,292.528167724609,0],[253.227737426758,300.074066162109,0],[254.811264038086,284.722106933594,0],[254.019500732422,292.528167724609,0],[194.6376953125,293.415374755859,0],[192.262420654297,284.214385986328,0],[255.603012084961,276.680541992188,0],[254.811264038086,284.722106933594,0],[253.227737426758,300.074066162109,0],[252.435989379883,307.255310058594,0],[216.01513671875,318.027954101562,0],[250.06071472168,326.528106689453,0],[223.140960693359,327.506164550781,0],[250.852462768555,320.471893310547,0],[251.644226074219,314.041931152344,0],[250.852462768555,320.471893310547,0],[221.55744934082,324.683227539062,0],[218.390411376953,320.315216064453,0],[251.644226074219,314.041931152344,0],[219.182174682617,321.257019042969,0],[251.644226074219,314.041931152344,0],[218.390411376953,320.315216064453,0],[252.435989379883,307.255310058594,0],[256.394775390625,268.419677734375,0],[255.603012084961,276.680541992188,0],[190.678894042969,276.805847167969,0],[182.761322021484,225.150573730469,0],[261.145324707031,216.365173339844,0],[260.353546142578,225.115921020508,0],[180.386047363281,206.209075927734,0],[262.728820800781,199.049026489258,0],[261.937072753906,207.668258666992,0],[178.802536010742,193.203552246094,0],[263.520599365234,190.562606811523,0],[262.728820800781,199.049026489258,0],[261.937072753906,207.668258666992,0],[261.145324707031,216.365173339844,0],[181.177810668945,212.638122558594,0],[257.1865234375,259.936401367188,0],[256.394775390625,268.419677734375,0],[189.09538269043,268.3310546875,0],[257.978302001953,251.336441040039,0],[257.1865234375,259.936401367188,0],[187.511871337891,258.869110107422,0],[258.770050048828,242.646850585938,0],[257.978302001953,251.336441040039,0],[185.928359985352,248.414215087891,0],[258.770050048828,242.646850585938,0],[185.136596679688,242.890838623047,0],[259.561798095703,233.894592285156,0],[183.553085327148,231.226837158203,0],[260.353546142578,225.115921020508,0],[259.561798095703,233.894592285156,0],[264.312347412109,182.25373840332,0],[263.520599365234,190.562606811523,0],[178.010787963867,186.661285400391,0],[264.312347412109,182.25373840332,0],[177.219024658203,180.12419128418,0],[265.104095458984,174.116668701172,0],[161.383880615234,79.1220474243164,0],[278.563995361328,78.2685775756836,0],[277.772216796875,81.5232696533203,0],[281.731018066406,67.6809692382812,0],[280.939239501953,69.9681777954102,0],[158.216842651367,68.9032745361328,0]],&#34;colors&#34;:[[0.215686276555061,0.494117647409439,0.721568644046783,1]],&#34;centers&#34;:[[178.010787963867,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[179.594299316406,48.8652877807617,0],[179.066467285156,48.8652877807617,0],[178.802551269531,48.8652801513672,0],[177.482955932617,48.8652801513672,0],[180.122131347656,48.8652877807617,0],[180.386047363281,48.8653030395508,0],[180.913909912109,48.865306854248,0],[180.386047363281,48.8652954101562,0],[181.441741943359,48.8653259277344,0],[181.969573974609,48.865364074707,0],[182.233489990234,48.8653869628906,0],[181.705657958984,48.8653411865234,0],[181.177795410156,48.8653182983398,0],[179.594299316406,48.8652877807617,0],[182.761322021484,48.8654632568359,0],[183.289169311523,48.865592956543,0],[183.553085327148,48.8656883239746,0],[183.025253295898,48.8655204772949,0],[183.817001342773,48.8660202026367,0],[184.608764648438,48.8664169311523,0],[184.872680664062,48.8667297363281,0],[184.344833374023,48.8661613464355,0],[183.817016601562,48.8658065795898,0],[185.400512695312,48.8676528930664,0],[185.928375244141,48.8691215515137,0],[186.192260742188,48.8701438903809,0],[185.664428710938,48.8683090209961,0],[186.720123291016,48.873046875,0],[187.247970581055,48.8775024414062,0],[187.51188659668,48.8805694580078,0],[186.984039306641,48.8750457763672,0],[186.456207275391,48.8714294433594,0],[184.872680664062,48.8672904968262,0],[182.497421264648,48.8654251098633,0],[188.03971862793,48.8890647888184,0],[188.56755065918,48.9017105102539,0],[188.831466674805,48.9102897644043,0],[188.303634643555,48.8947219848633,0],[189.359298706055,48.9333724975586,0],[189.887145996094,48.9671401977539,0],[190.151062011719,48.9895324707031,0],[189.62321472168,48.948616027832,0],[189.09538269043,48.9207992553711,0],[190.678924560547,49.0480880737305,0],[191.206756591797,49.131965637207,0],[191.470672607422,49.1862907409668,0],[190.942840576172,49.086311340332,0],[191.998504638672,49.3252410888672,0],[192.526336669922,49.5196952819824,0],[192.790252685547,49.641471862793,0],[192.262420654297,49.4143447875977,0],[191.734588623047,49.2497787475586,0],[190.414978027344,49.0162773132324,0],[193.318099975586,49.9505729675293,0],[193.845932006836,50.3684310913086,0],[194.10986328125,50.6255111694336,0],[193.582015991211,50.1447868347168,0],[194.6376953125,51.2650680541992,0],[195.429443359375,51.9442672729492,0],[195.429443359375,52.6075973510742,0],[195.16552734375,51.5192260742188,0],[194.373779296875,50.9228782653809,0],[196.22119140625,53.6062431335449,0],[196.749069213867,55.1053085327148,0],[197.012969970703,56.0017395019531,0],[196.485137939453,54.3102569580078,0],[197.540817260742,58.1081466674805,0],[198.068649291992,60.7282028198242,0],[198.332565307617,62.2504806518555,0],[197.804718017578,59.3475761413574,0],[197.276885986328,56.9970817565918,0],[195.693359375,53.1836624145508,0],[193.054168701172,49.7839164733887,0],[187.775787353516,48.8843688964844,0],[198.860397338867,65.76708984375,0],[199.388229370117,70.0143966674805,0],[199.124328613281,67.7958526611328,0],[199.916061401367,75.0337524414062,0],[200.443908691406,80.9520111083984,0],[200.971740722656,83.0777359008789,0],[200.180023193359,77.8758392333984,0],[199.652145385742,72.4151611328125,0],[201.763519287109,94.1579132080078,0],[202.291351318359,102.795181274414,0],[202.555267333984,107.488662719727,0],[202.027435302734,98.360710144043,0],[203.083114624023,117.691940307617,0],[203.874862670898,126.73021697998,0],[204.138778686523,132.543548583984,0],[203.347015380859,123.140953063965,0],[202.819183349609,112.466064453125,0],[201.499603271484,90.1975326538086,0],[204.666625976562,144.874938964844,0],[205.194458007812,157.920288085938,0],[205.986206054688,168.990264892578,0],[204.930541992188,151.31071472168,0],[206.514068603516,183.013061523438,0],[207.041900634766,197.32585144043,0],[207.569732666016,201.661056518555,0],[206.777984619141,190.142501831055,0],[206.250122070312,175.955169677734,0],[208.625411987305,220.155059814453,0],[208.88932800293,227.164459228516,0],[209.153244018555,234.095062255859,0],[208.097579956055,215.984237670898,0],[209.945007324219,244.650634765625,0],[210.736785888672,254.649688720703,0],[210.208923339844,251.16471862793,0],[209.681076049805,237.98307800293,0],[207.833648681641,208.838485717773,0],[205.458374023438,164.714752197266,0],[204.402709960938,138.61555480957,0],[212.584197998047,278.054534912109,0],[213.375961303711,285.483642578125,0],[213.112030029297,280.524017333984,0],[212.320281982422,272.637359619141,0],[214.431640625,289.572570800781,0],[215.223388671875,295.579803466797,0],[214.695556640625,293.965545654297,0],[213.903793334961,287.605529785156,0],[211.792449951172,269.812438964844,0],[201.763519287109,305.804229736328,0],[202.291351318359,307.822845458984,0],[202.027435302734,306.884704589844,0],[201.499603271484,304.587707519531,0],[202.819183349609,309.342468261719,0],[201.763519287109,308.922821044922,0],[203.347030639648,310.234313964844,0],[202.555267333984,308.636993408203,0],[220.501770019531,301.977020263672,0],[211.528533935547,264.003356933594,0],[204.402694702148,311.467834472656,0],[204.930541992188,311.899749755859,0],[205.194458007812,311.997161865234,0],[204.138793945312,311.133056640625,0],[204.930541992188,311.393493652344,0],[205.194458007812,311.270263671875,0],[205.458374023438,311.078857421875,0],[205.722290039062,310.823333740234,0],[205.986206054688,310.495452880859,0],[206.250122070312,310.096801757812,0],[226.835815429688,308.280151367188,0],[227.099731445312,311.108306884766,0],[225.780151367188,307.731140136719,0],[228.155426025391,311.837158203125,0],[228.947189331055,315.149780273438,0],[229.475021362305,315.682678222656,0],[228.419342041016,314.666625976562,0],[227.627593994141,311.451385498047,0],[226.307983398438,307.993621826172,0],[211.000671386719,260.849365234375,0],[201.235687255859,86.5039596557617,0],[198.596481323242,63.923095703125,0],[246.893676757812,49.2854766845703,0],[247.421508789062,49.1567077636719,0],[247.157592773438,49.2160949707031,0],[245.574096679688,49.8687744140625,0],[246.101928710938,49.5801696777344,0],[246.365844726562,49.4650268554688,0],[245.838012695312,49.7132797241211,0],[246.629760742188,49.3676147460938,0],[249.268951416016,48.939811706543,0],[249.796798706055,48.9145469665527,0],[250.060729980469,48.9051666259766,0],[249.53288269043,48.9260520935059,0],[247.949371337891,49.0651550292969,0],[248.47721862793,49.0011596679688,0],[248.741134643555,48.9766540527344,0],[248.213256835938,49.0304069519043,0],[249.005035400391,48.9564666748047,0],[247.685424804688,49.1067581176758,0],[241.879241943359,58.5558891296387,0],[242.407073974609,56.3274459838867,0],[242.670989990234,55.3910484313965,0],[242.143157958984,57.3772506713867,0],[240.559631347656,66.6889266967773,0],[241.087448120117,62.9367942810059,0],[241.351379394531,61.3291282653809,0],[240.823532104492,64.7205963134766,0],[241.615295410156,59.8719177246094,0],[244.254486083984,51.112377166748,0],[244.782333374023,50.5073928833008,0],[245.046264648438,50.2628784179688,0],[244.518417358398,50.7882804870605,0],[243.198822021484,53.8078308105469,0],[243.462738037109,52.4009819030762,0],[243.990570068359,52.0683403015137,0],[243.198822021484,52.95361328125,0],[244.254486083984,51.6216278076172,0],[242.934906005859,54.5510063171387,0],[245.310180664062,50.0504722595215,0],[257.186553955078,48.8653259277344,0],[257.71435546875,48.865306854248,0],[257.71435546875,48.8653030395508,0],[257.450439453125,48.8653182983398,0],[255.866928100586,48.865478515625,0],[256.394775390625,48.8653984069824,0],[256.65869140625,48.8653678894043,0],[256.130859375,48.8654403686523,0],[256.922637939453,48.865348815918,0],[260.089660644531,48.8652801513672,0],[260.617492675781,48.8652801513672,0],[258.506134033203,48.865291595459,0],[259.033996582031,48.8652877807617,0],[259.297882080078,48.8652877807617,0],[258.506134033203,48.8652877807617,0],[259.561828613281,48.8652801513672,0],[258.242218017578,48.8652954101562,0],[251.908172607422,48.8738059997559,0],[252.435974121094,48.8706283569336,0],[252.699890136719,48.8695068359375,0],[252.172088623047,48.8720321655273,0],[250.58854675293,48.8913497924805,0],[251.11637878418,48.8820304870605,0],[251.380310058594,48.8786888122559,0],[250.852462768555,48.8861999511719,0],[251.644226074219,48.8759994506836,0],[254.283416748047,48.865966796875,0],[255.075180053711,48.8657302856445,0],[255.339111328125,48.8656234741211,0],[254.811264038086,48.8658599853516,0],[253.227752685547,48.8678894042969,0],[253.755599975586,48.8668746948242,0],[254.019500732422,48.866527557373,0],[253.227752685547,48.8671646118164,0],[254.283416748047,48.8662490844727,0],[252.963836669922,48.8686141967773,0],[255.60302734375,48.8655395507812,0],[250.324630737305,48.8975448608398,0],[230.794616699219,319.930999755859,0],[231.586364746094,323.728210449219,0],[231.322448730469,320.723785400391,0],[232.378143310547,327.704895019531,0],[233.433822631836,329.93017578125,0],[241.615295410156,330.396911621094,0],[232.905975341797,328.786193847656,0],[232.114227294922,324.669189453125,0],[234.225555419922,334.299285888672,0],[234.489501953125,337.316833496094,0],[241.615325927734,335.24169921875,0],[235.017333984375,338.683959960938,0],[233.697723388672,333.019165039062,0],[235.281234741211,341.63427734375,0],[241.615295410156,344.223693847656,0],[235.80908203125,343.060394287109,0],[236.072998046875,345.895080566406,0],[241.615295410156,339.84716796875,0],[230.26676940918,319.201293945312,0],[237.392578125,351.338684082031,0],[237.920440673828,355.796264648438,0],[237.656524658203,353.680511474609,0],[236.86474609375,349.980529785156,0],[238.712203979492,358.669494628906,0],[239.240036010742,361.22509765625,0],[238.976104736328,360.111938476562,0],[238.184356689453,357.678070068359,0],[236.600830078125,347.320281982422,0],[241.087448120117,359.147155761719,0],[241.087463378906,356.788787841797,0],[241.351379394531,354.547821044922,0],[240.823547363281,360.576293945312,0],[239.767868041992,362.468017578125,0],[240.295700073242,362.258056640625,0],[239.503952026367,362.017028808594,0],[240.559616088867,361.598815917969,0],[241.615295410156,351.970916748047,0],[241.615295410156,348.3076171875,0],[236.86474609375,134.605392456055,0],[237.128662109375,120.749877929688,0],[237.392608642578,115.177291870117,0],[237.128662109375,128.405975341797,0],[235.80908203125,171.303314208984,0],[236.072998046875,154.665771484375,0],[236.3369140625,147.762908935547,0],[235.80908203125,161.803863525391,0],[236.600830078125,141.072906494141,0],[239.240036010742,84.0148010253906,0],[239.767868041992,73.7745666503906,0],[240.031784057617,71.1997604370117,0],[239.503952026367,76.5851364135742,0],[237.920440673828,104.84676361084,0],[238.448287963867,95.70947265625,0],[238.712203979492,91.5312042236328,0],[238.184371948242,100.140991210938,0],[238.976119995117,87.6240081787109,0],[237.656524658203,109.860824584961,0],[240.295700073242,302.994140625,0],[234.489486694336,290.221893310547,0],[234.225570678711,281.872344970703,0],[240.559616088867,308.452453613281,0],[241.351379394531,324.835418701172,0],[241.351379394531,319.732360839844,0],[229.73893737793,318.5380859375,0],[240.823547363281,313.870849609375,0],[234.225570678711,273.968688964844,0],[234.753402709961,222.210556030273,0],[235.017318725586,204.308807373047,0],[235.017318725586,194.271728515625,0],[234.753402709961,212.223861694336,0],[234.225570678711,265.562377929688,0],[234.225555419922,256.713989257812,0],[234.225570678711,247.4658203125,0],[234.489486694336,239.810760498047,0],[234.489471435547,230.079132080078,0],[235.28125,186.492553710938,0],[235.545166015625,178.83154296875,0],[239.240036010742,79.6379699707031,0],[240.295715332031,68.8508071899414,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;191&#34;:{&#34;id&#34;:191,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.70000004768372,-2.70000004768372]},&#34;vertices&#34;:[[60.8306732177734,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[98.0432739257812,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[99.6267929077148,48.8652839660645,0],[100.418548583984,48.8652877807617,0],[101.210304260254,48.8652877807617,0],[102.002059936523,48.865291595459,0],[102.793823242188,48.8652954101562,0],[103.585578918457,48.8653030395508,0],[104.377334594727,48.8653106689453,0],[105.169090270996,48.8653221130371,0],[105.96085357666,48.8653335571289,0],[106.75260925293,48.8653526306152,0],[107.544364929199,48.8653755187988,0],[108.336120605469,48.865406036377,0],[109.127883911133,48.8654441833496,0],[109.919639587402,48.8654937744141,0],[110.711395263672,48.8655586242676,0],[111.503150939941,48.8656463623047,0],[112.294914245605,48.8657531738281,0],[113.086669921875,48.8658866882324,0],[113.878425598145,48.8660736083984,0],[114.670181274414,48.8663024902344,0],[115.461936950684,48.8665924072266,0],[116.253700256348,48.866943359375,0],[117.045455932617,48.8674240112305,0],[117.837211608887,48.8680267333984,0],[118.628967285156,48.868766784668,0],[119.42073059082,48.8696708679199,0],[120.21248626709,48.8708457946777,0],[121.004241943359,48.8723335266113,0],[121.795997619629,48.8741569519043,0],[122.587760925293,48.8763694763184,0],[123.379516601562,48.8791236877441,0],[124.171272277832,48.8826522827148,0],[124.963027954102,48.8869361877441,0],[125.754791259766,48.8920936584473,0],[126.546546936035,48.8982849121094,0],[127.338302612305,48.9062843322754,0],[128.130065917969,48.9159126281738,0],[128.921813964844,48.9274101257324,0],[129.713577270508,48.941032409668,0],[130.505325317383,48.958080291748,0],[131.297088623047,48.9787521362305,0],[132.088851928711,49.0032196044922,0],[132.880599975586,49.0319786071777,0],[133.67236328125,49.0666656494141,0],[134.464126586914,49.109073638916,0],[135.255874633789,49.158805847168,0],[136.047637939453,49.2167510986328,0],[136.839385986328,49.284366607666,0],[137.631149291992,49.3674964904785,0],[138.422912597656,49.4640350341797,0],[139.214660644531,49.5754890441895,0],[140.006423950195,49.7034378051758,0],[140.798187255859,49.8573837280273,0],[141.589935302734,50.0363273620605,0],[142.381698608398,50.2409515380859,0],[143.173446655273,50.4737358093262,0],[143.965209960938,50.7449493408203,0],[144.756973266602,51.0616111755371,0],[145.548721313477,51.4201202392578,0],[146.340484619141,51.824089050293,0],[147.132232666016,52.281364440918,0],[147.92399597168,52.8161659240723,0],[148.715759277344,53.4153900146484,0],[149.507507324219,54.083911895752,0],[150.299270629883,54.8266944885254,0],[151.091033935547,55.6830787658691,0],[151.882781982422,56.6382141113281,0],[152.674545288086,57.6928176879883,0],[153.466293334961,58.8528938293457,0],[154.258056640625,60.1537780761719,0],[155.049819946289,61.6048889160156,0],[155.841567993164,63.1899833679199,0],[156.633331298828,64.9154663085938,0],[157.425079345703,66.8033218383789,0],[158.216842651367,68.9032745361328,0],[159.008605957031,71.171745300293,0],[159.800354003906,73.6144180297852,0],[160.59211730957,76.2368850708008,0],[161.383880615234,79.1220474243164,0],[162.175628662109,82.2107162475586,0],[162.967391967773,85.4992218017578,0],[163.759140014648,88.9907760620117,0],[164.550903320312,92.7424850463867,0],[165.342666625977,96.7394561767578,0],[166.134414672852,100.945457458496,0],[166.926177978516,105.359741210938,0],[167.71794128418,110.00602722168,0],[168.509689331055,114.915924072266,0],[169.301452636719,120.020172119141,0],[170.093200683594,125.312934875488,0],[170.884963989258,130.787979125977,0],[171.676727294922,136.502426147461,0],[172.468475341797,142.370712280273,0],[173.260238647461,148.379653930664,0],[174.051986694336,154.517883300781,0],[174.84375,160.798126220703,0],[175.635513305664,167.177520751953,0],[176.427261352539,173.624633789062,0],[177.219024658203,180.12419128418,0],[178.010787963867,186.661285400391,0],[178.802536010742,193.203552246094,0],[179.594299316406,199.725006103516,0],[180.386047363281,206.209075927734,0],[181.177810668945,212.638122558594,0],[181.969573974609,218.949417114258,0],[182.761322021484,225.150573730469,0],[183.553085327148,231.226837158203,0],[184.344848632812,237.163757324219,0],[185.136596679688,242.890838623047,0],[185.928359985352,248.414215087891,0],[186.720108032227,253.74348449707,0],[187.511871337891,258.869110107422,0],[188.303634643555,263.742523193359,0],[189.09538269043,268.3310546875,0],[189.887145996094,272.6865234375,0],[190.678894042969,276.805847167969,0],[191.470657348633,280.677154541016,0],[192.262420654297,284.214385986328,0],[193.054168701172,287.514343261719,0],[193.845932006836,290.580169677734,0],[194.6376953125,293.415374755859,0],[195.429443359375,295.953002929688,0],[196.221206665039,298.258178710938,0],[197.012954711914,300.360198974609,0],[197.804718017578,302.266967773438,0],[198.596481323242,303.953186035156,0],[199.388229370117,305.432434082031,0],[200.179992675781,306.757354736328,0],[200.971740722656,307.937683105469,0],[201.76350402832,308.975830078125,0],[202.555267333984,309.854919433594,0],[203.347015380859,310.633911132812,0],[204.138778686523,311.322357177734,0],[204.930541992188,311.929718017578,0],[205.722290039062,312.447174072266,0],[206.514053344727,312.910369873047,0],[207.305801391602,313.332305908203,0],[208.097564697266,313.721160888672,0],[208.88932800293,314.082916259766,0],[209.681076049805,314.433868408203,0],[210.472839355469,314.785491943359,0],[211.264602661133,315.144653320312,0],[212.056350708008,315.5205078125,0],[212.848114013672,315.93212890625,0],[213.639862060547,316.380187988281,0],[214.431625366211,316.870635986328,0],[215.223388671875,317.409362792969,0],[216.01513671875,318.027954101562,0],[216.806900024414,318.716583251953,0],[217.598648071289,319.477447509766,0],[218.390411376953,320.315216064453,0],[219.182174682617,321.257019042969,0],[219.973922729492,322.304840087891,0],[220.765686035156,323.446166992188,0],[221.55744934082,324.683227539062,0],[222.349197387695,326.029479980469,0],[223.140960693359,327.506164550781,0],[223.932708740234,329.080413818359,0],[224.724472045898,330.750030517578,0],[225.516235351562,332.512420654297,0],[226.307983398438,334.394927978516,0],[227.099746704102,336.352783203125,0],[227.891510009766,338.375549316406,0],[228.683258056641,340.4541015625,0],[229.475021362305,342.583435058594,0],[230.26676940918,344.732452392578,0],[231.058532714844,346.879364013672,0],[231.850296020508,349.008087158203,0],[232.642044067383,351.092010498047,0],[233.433807373047,353.08251953125,0],[234.225555419922,354.97021484375,0],[235.017318725586,356.734161376953,0],[235.80908203125,358.352355957031,0],[236.600830078125,359.708374023438,0],[237.392593383789,360.842071533203,0],[238.184356689453,361.731781005859,0],[238.976104736328,362.35595703125,0],[239.767868041992,362.593139648438,0],[240.559616088867,362.454956054688,0],[241.351379394531,361.963195800781,0],[242.143142700195,361.101409912109,0],[242.93489074707,359.785400390625,0],[243.726654052734,357.947692871094,0],[244.518402099609,355.684478759766,0],[245.310165405273,352.988800048828,0],[246.101928710938,349.841461181641,0],[246.893676757812,346.073364257812,0],[247.685440063477,341.865234375,0],[248.477203369141,337.22216796875,0],[249.268951416016,332.150177001953,0],[250.06071472168,326.528106689453,0],[250.852462768555,320.471893310547,0],[251.644226074219,314.041931152344,0],[252.435989379883,307.255310058594,0],[253.227737426758,300.074066162109,0],[254.019500732422,292.528167724609,0],[254.811264038086,284.722106933594,0],[255.603012084961,276.680541992188,0],[256.394775390625,268.419677734375,0],[257.1865234375,259.936401367188,0],[257.978302001953,251.336441040039,0],[258.770050048828,242.646850585938,0],[259.561798095703,233.894592285156,0],[260.353546142578,225.115921020508,0],[261.145324707031,216.365173339844,0],[261.937072753906,207.668258666992,0],[262.728820800781,199.049026489258,0],[263.520599365234,190.562606811523,0],[264.312347412109,182.25373840332,0],[265.104095458984,174.116668701172,0],[265.895874023438,166.168609619141,0],[266.687622070312,158.444854736328,0],[267.479370117188,151.034591674805,0],[268.271148681641,143.874450683594,0],[269.062896728516,136.973510742188,0],[269.854644775391,130.340209960938,0],[270.646392822266,124.089736938477,0],[271.438171386719,118.139717102051,0],[272.229919433594,112.476234436035,0],[273.021667480469,107.100212097168,0],[273.813446044922,102.08031463623,0],[274.605194091797,97.3972091674805,0],[275.396942138672,92.9917755126953,0],[276.188720703125,88.8593368530273,0],[276.98046875,85.0218887329102,0],[277.772216796875,81.5232696533203,0],[278.563995361328,78.2685775756836,0],[279.355743408203,75.2499465942383,0],[280.147491455078,72.4593353271484,0],[280.939239501953,69.9681777954102,0],[281.731018066406,67.6809692382812,0],[282.522766113281,65.5824813842773,0],[283.314514160156,63.6638336181641,0],[284.106292724609,61.9565620422363,0],[284.898040771484,60.4259262084961,0],[285.689788818359,59.0360450744629,0],[286.481567382812,57.7787246704102,0],[287.273315429688,56.6601982116699,0],[288.065063476562,55.6839256286621,0],[288.856842041016,54.8061447143555,0],[289.648590087891,54.0201644897461,0],[290.440338134766,53.3194198608398,0],[291.232086181641,52.7252502441406,0],[292.023864746094,52.1963195800781,0],[292.815612792969,51.7273368835449,0],[293.607360839844,51.3134574890137,0],[294.399139404297,50.9620628356934,0],[295.190887451172,50.657829284668,0],[295.982635498047,50.3905982971191,0],[296.7744140625,50.1570777893066,0],[297.566162109375,49.9580116271973,0],[298.35791015625,49.7909240722656,0],[299.149688720703,49.6454696655273,0],[299.941436767578,49.5195579528809,0],[300.733184814453,49.411491394043,0],[301.524932861328,49.323860168457,0],[302.316711425781,49.2482109069824,0],[303.108459472656,49.1833190917969,0],[303.900207519531,49.128002166748,0],[304.691986083984,49.083194732666,0],[305.483734130859,49.0456008911133,0],[306.275482177734,49.0136299133301,0],[307.067260742188,48.9866256713867,0],[307.859008789062,48.9645843505859,0],[308.650756835938,48.9467315673828,0],[309.442535400391,48.9316711425781,0],[310.234283447266,48.9190635681152,0],[311.026031494141,48.9086608886719,0],[311.817810058594,48.900562286377,0],[312.609558105469,48.8937797546387,0],[313.401306152344,48.8881492614746,0],[314.193054199219,48.8835144042969,0],[314.984832763672,48.8799324035645,0],[315.776580810547,48.8770141601562,0],[316.568328857422,48.8746109008789,0],[317.360107421875,48.8726463317871,0],[318.15185546875,48.8711128234863,0],[318.943603515625,48.8699111938477,0],[319.735382080078,48.8689308166504,0],[320.527130126953,48.8681335449219,0],[321.318878173828,48.867504119873,0],[322.110656738281,48.8670310974121,0],[322.902404785156,48.8666496276855,0],[323.694152832031,48.866340637207,0],[324.485900878906,48.866096496582,0],[325.277679443359,48.8659133911133,0],[326.069427490234,48.8657722473145,0],[326.861175537109,48.8656578063965,0],[327.652954101562,48.8655662536621,0],[328.444702148438,48.8655014038086,0],[329.236450195312,48.8654479980469,0],[330.028228759766,48.8654098510742,0],[330.819976806641,48.8653755187988,0],[331.611724853516,48.8653526306152,0],[332.403503417969,48.8653335571289,0],[333.195251464844,48.8653221130371,0],[333.986999511719,48.8653106689453,0],[334.778747558594,48.8653030395508,0],[335.570526123047,48.8652954101562,0],[336.362274169922,48.865291595459,0],[337.154022216797,48.8652877807617,0],[337.94580078125,48.8652877807617,0],[338.737548828125,48.8652839660645,0],[339.529296875,48.8652839660645,0],[340.321075439453,48.8652839660645,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[60.8306732177734,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[98.0432739257812,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[99.6267929077148,48.8652839660645,0],[100.418548583984,48.8652877807617,0],[101.210304260254,48.8652877807617,0],[102.002059936523,48.865291595459,0],[102.793823242188,48.8652954101562,0],[103.585578918457,48.8653030395508,0],[104.377334594727,48.8653106689453,0],[105.169090270996,48.8653221130371,0],[105.96085357666,48.8653335571289,0],[106.75260925293,48.8653526306152,0],[107.544364929199,48.8653755187988,0],[108.336120605469,48.865406036377,0],[109.127883911133,48.8654441833496,0],[109.919639587402,48.8654937744141,0],[110.711395263672,48.8655586242676,0],[111.503150939941,48.8656463623047,0],[112.294914245605,48.8657531738281,0],[113.086669921875,48.8658866882324,0],[113.878425598145,48.8660736083984,0],[114.670181274414,48.8663024902344,0],[115.461936950684,48.8665924072266,0],[116.253700256348,48.866943359375,0],[117.045455932617,48.8674240112305,0],[117.837211608887,48.8680267333984,0],[118.628967285156,48.868766784668,0],[119.42073059082,48.8696708679199,0],[120.21248626709,48.8708457946777,0],[121.004241943359,48.8723335266113,0],[121.795997619629,48.8741569519043,0],[122.587760925293,48.8763694763184,0],[123.379516601562,48.8791236877441,0],[124.171272277832,48.8826522827148,0],[124.963027954102,48.8869361877441,0],[125.754791259766,48.8920936584473,0],[126.546546936035,48.8982849121094,0],[127.338302612305,48.9062843322754,0],[128.130065917969,48.9159126281738,0],[128.921813964844,48.9274101257324,0],[129.713577270508,48.941032409668,0],[130.505325317383,48.958080291748,0],[131.297088623047,48.9787521362305,0],[132.088851928711,49.0032196044922,0],[132.880599975586,49.0319786071777,0],[133.67236328125,49.0666656494141,0],[134.464126586914,49.109073638916,0],[135.255874633789,49.158805847168,0],[136.047637939453,49.2167510986328,0],[136.839385986328,49.284366607666,0],[137.631149291992,49.3674964904785,0],[138.422912597656,49.4640350341797,0],[139.214660644531,49.5754890441895,0],[140.006423950195,49.7034378051758,0],[140.798187255859,49.8573837280273,0],[141.589935302734,50.0363273620605,0],[142.381698608398,50.2409515380859,0],[143.173446655273,50.4737358093262,0],[143.965209960938,50.7449493408203,0],[144.756973266602,51.0616111755371,0],[145.548721313477,51.4201202392578,0],[146.340484619141,51.824089050293,0],[147.132232666016,52.281364440918,0],[147.92399597168,52.8161659240723,0],[148.715759277344,53.4153900146484,0],[149.507507324219,54.083911895752,0],[150.299270629883,54.8266944885254,0],[151.091033935547,55.6830787658691,0],[151.882781982422,56.6382141113281,0],[152.674545288086,57.6928176879883,0],[153.466293334961,58.8528938293457,0],[154.258056640625,60.1537780761719,0],[155.049819946289,61.6048889160156,0],[155.841567993164,63.1899833679199,0],[156.633331298828,64.9154663085938,0],[157.425079345703,66.8033218383789,0],[158.216842651367,68.9032745361328,0],[159.008605957031,71.171745300293,0],[159.800354003906,73.6144180297852,0],[160.59211730957,76.2368850708008,0],[161.383880615234,79.1220474243164,0],[162.175628662109,82.2107162475586,0],[162.967391967773,85.4992218017578,0],[163.759140014648,88.9907760620117,0],[164.550903320312,92.7424850463867,0],[165.342666625977,96.7394561767578,0],[166.134414672852,100.945457458496,0],[166.926177978516,105.359741210938,0],[167.71794128418,110.00602722168,0],[168.509689331055,114.915924072266,0],[169.301452636719,120.020172119141,0],[170.093200683594,125.312934875488,0],[170.884963989258,130.787979125977,0],[171.676727294922,136.502426147461,0],[172.468475341797,142.370712280273,0],[173.260238647461,148.379653930664,0],[174.051986694336,154.517883300781,0],[174.84375,160.798126220703,0],[175.635513305664,167.177520751953,0],[176.427261352539,173.624633789062,0],[177.219024658203,180.12419128418,0],[178.010787963867,186.661285400391,0],[178.802536010742,193.203552246094,0],[179.594299316406,199.725006103516,0],[180.386047363281,206.209075927734,0],[181.177810668945,212.638122558594,0],[181.969573974609,218.949417114258,0],[182.761322021484,225.150573730469,0],[183.553085327148,231.226837158203,0],[184.344848632812,237.163757324219,0],[185.136596679688,242.890838623047,0],[185.928359985352,248.414215087891,0],[186.720108032227,253.74348449707,0],[187.511871337891,258.869110107422,0],[188.303634643555,263.742523193359,0],[189.09538269043,268.3310546875,0],[189.887145996094,272.6865234375,0],[190.678894042969,276.805847167969,0],[191.470657348633,280.677154541016,0],[192.262420654297,284.214385986328,0],[193.054168701172,287.514343261719,0],[193.845932006836,290.580169677734,0],[194.6376953125,293.415374755859,0],[195.429443359375,295.953002929688,0],[196.221206665039,298.258178710938,0],[197.012954711914,300.360198974609,0],[197.804718017578,302.266967773438,0],[198.596481323242,303.953186035156,0],[199.388229370117,305.432434082031,0],[200.179992675781,306.757354736328,0],[200.971740722656,307.937683105469,0],[201.76350402832,308.975830078125,0],[202.555267333984,309.854919433594,0],[203.347015380859,310.633911132812,0],[204.138778686523,311.322357177734,0],[204.930541992188,311.929718017578,0],[205.722290039062,312.447174072266,0],[206.514053344727,312.910369873047,0],[207.305801391602,313.332305908203,0],[208.097564697266,313.721160888672,0],[208.88932800293,314.082916259766,0],[209.681076049805,314.433868408203,0],[210.472839355469,314.785491943359,0],[211.264602661133,315.144653320312,0],[212.056350708008,315.5205078125,0],[212.848114013672,315.93212890625,0],[213.639862060547,316.380187988281,0],[214.431625366211,316.870635986328,0],[215.223388671875,317.409362792969,0],[216.01513671875,318.027954101562,0],[216.806900024414,318.716583251953,0],[217.598648071289,319.477447509766,0],[218.390411376953,320.315216064453,0],[219.182174682617,321.257019042969,0],[219.973922729492,322.304840087891,0],[220.765686035156,323.446166992188,0],[221.55744934082,324.683227539062,0],[222.349197387695,326.029479980469,0],[223.140960693359,327.506164550781,0],[223.932708740234,329.080413818359,0],[224.724472045898,330.750030517578,0],[225.516235351562,332.512420654297,0],[226.307983398438,334.394927978516,0],[227.099746704102,336.352783203125,0],[227.891510009766,338.375549316406,0],[228.683258056641,340.4541015625,0],[229.475021362305,342.583435058594,0],[230.26676940918,344.732452392578,0],[231.058532714844,346.879364013672,0],[231.850296020508,349.008087158203,0],[232.642044067383,351.092010498047,0],[233.433807373047,353.08251953125,0],[234.225555419922,354.97021484375,0],[235.017318725586,356.734161376953,0],[235.80908203125,358.352355957031,0],[236.600830078125,359.708374023438,0],[237.392593383789,360.842071533203,0],[238.184356689453,361.731781005859,0],[238.976104736328,362.35595703125,0],[239.767868041992,362.593139648438,0],[240.559616088867,362.454956054688,0],[241.351379394531,361.963195800781,0],[242.143142700195,361.101409912109,0],[242.93489074707,359.785400390625,0],[243.726654052734,357.947692871094,0],[244.518402099609,355.684478759766,0],[245.310165405273,352.988800048828,0],[246.101928710938,349.841461181641,0],[246.893676757812,346.073364257812,0],[247.685440063477,341.865234375,0],[248.477203369141,337.22216796875,0],[249.268951416016,332.150177001953,0],[250.06071472168,326.528106689453,0],[250.852462768555,320.471893310547,0],[251.644226074219,314.041931152344,0],[252.435989379883,307.255310058594,0],[253.227737426758,300.074066162109,0],[254.019500732422,292.528167724609,0],[254.811264038086,284.722106933594,0],[255.603012084961,276.680541992188,0],[256.394775390625,268.419677734375,0],[257.1865234375,259.936401367188,0],[257.978302001953,251.336441040039,0],[258.770050048828,242.646850585938,0],[259.561798095703,233.894592285156,0],[260.353546142578,225.115921020508,0],[261.145324707031,216.365173339844,0],[261.937072753906,207.668258666992,0],[262.728820800781,199.049026489258,0],[263.520599365234,190.562606811523,0],[264.312347412109,182.25373840332,0],[265.104095458984,174.116668701172,0],[265.895874023438,166.168609619141,0],[266.687622070312,158.444854736328,0],[267.479370117188,151.034591674805,0],[268.271148681641,143.874450683594,0],[269.062896728516,136.973510742188,0],[269.854644775391,130.340209960938,0],[270.646392822266,124.089736938477,0],[271.438171386719,118.139717102051,0],[272.229919433594,112.476234436035,0],[273.021667480469,107.100212097168,0],[273.813446044922,102.08031463623,0],[274.605194091797,97.3972091674805,0],[275.396942138672,92.9917755126953,0],[276.188720703125,88.8593368530273,0],[276.98046875,85.0218887329102,0],[277.772216796875,81.5232696533203,0],[278.563995361328,78.2685775756836,0],[279.355743408203,75.2499465942383,0],[280.147491455078,72.4593353271484,0],[280.939239501953,69.9681777954102,0],[281.731018066406,67.6809692382812,0],[282.522766113281,65.5824813842773,0],[283.314514160156,63.6638336181641,0],[284.106292724609,61.9565620422363,0],[284.898040771484,60.4259262084961,0],[285.689788818359,59.0360450744629,0],[286.481567382812,57.7787246704102,0],[287.273315429688,56.6601982116699,0],[288.065063476562,55.6839256286621,0],[288.856842041016,54.8061447143555,0],[289.648590087891,54.0201644897461,0],[290.440338134766,53.3194198608398,0],[291.232086181641,52.7252502441406,0],[292.023864746094,52.1963195800781,0],[292.815612792969,51.7273368835449,0],[293.607360839844,51.3134574890137,0],[294.399139404297,50.9620628356934,0],[295.190887451172,50.657829284668,0],[295.982635498047,50.3905982971191,0],[296.7744140625,50.1570777893066,0],[297.566162109375,49.9580116271973,0],[298.35791015625,49.7909240722656,0],[299.149688720703,49.6454696655273,0],[299.941436767578,49.5195579528809,0],[300.733184814453,49.411491394043,0],[301.524932861328,49.323860168457,0],[302.316711425781,49.2482109069824,0],[303.108459472656,49.1833190917969,0],[303.900207519531,49.128002166748,0],[304.691986083984,49.083194732666,0],[305.483734130859,49.0456008911133,0],[306.275482177734,49.0136299133301,0],[307.067260742188,48.9866256713867,0],[307.859008789062,48.9645843505859,0],[308.650756835938,48.9467315673828,0],[309.442535400391,48.9316711425781,0],[310.234283447266,48.9190635681152,0],[311.026031494141,48.9086608886719,0],[311.817810058594,48.900562286377,0],[312.609558105469,48.8937797546387,0],[313.401306152344,48.8881492614746,0],[314.193054199219,48.8835144042969,0],[314.984832763672,48.8799324035645,0],[315.776580810547,48.8770141601562,0],[316.568328857422,48.8746109008789,0],[317.360107421875,48.8726463317871,0],[318.15185546875,48.8711128234863,0],[318.943603515625,48.8699111938477,0],[319.735382080078,48.8689308166504,0],[320.527130126953,48.8681335449219,0],[321.318878173828,48.867504119873,0],[322.110656738281,48.8670310974121,0],[322.902404785156,48.8666496276855,0],[323.694152832031,48.866340637207,0],[324.485900878906,48.866096496582,0],[325.277679443359,48.8659133911133,0],[326.069427490234,48.8657722473145,0],[326.861175537109,48.8656578063965,0],[327.652954101562,48.8655662536621,0],[328.444702148438,48.8655014038086,0],[329.236450195312,48.8654479980469,0],[330.028228759766,48.8654098510742,0],[330.819976806641,48.8653755187988,0],[331.611724853516,48.8653526306152,0],[332.403503417969,48.8653335571289,0],[333.195251464844,48.8653221130371,0],[333.986999511719,48.8653106689453,0],[334.778747558594,48.8653030395508,0],[335.570526123047,48.8652954101562,0],[336.362274169922,48.865291595459,0],[337.154022216797,48.8652877807617,0],[337.94580078125,48.8652877807617,0],[338.737548828125,48.8652839660645,0],[339.529296875,48.8652839660645,0],[340.321075439453,48.8652839660645,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;192&#34;:{&#34;id&#34;:192,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0,&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-2.79999995231628,-2.79999995231628]},&#34;vertices&#34;:[[60.8306732177734,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[98.0432739257812,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[99.6267929077148,48.8652839660645,0],[100.418548583984,48.8652877807617,0],[101.210304260254,48.8652877807617,0],[102.002059936523,48.865291595459,0],[102.793823242188,48.8652954101562,0],[103.585578918457,48.8653030395508,0],[104.377334594727,48.8653106689453,0],[105.169090270996,48.8653221130371,0],[105.96085357666,48.8653335571289,0],[106.75260925293,48.8653526306152,0],[107.544364929199,48.8653755187988,0],[108.336120605469,48.865406036377,0],[109.127883911133,48.8654441833496,0],[109.919639587402,48.8654937744141,0],[110.711395263672,48.8655586242676,0],[111.503150939941,48.8656463623047,0],[112.294914245605,48.8657531738281,0],[113.086669921875,48.8658866882324,0],[113.878425598145,48.8660736083984,0],[114.670181274414,48.8663024902344,0],[115.461936950684,48.8665924072266,0],[116.253700256348,48.866943359375,0],[117.045455932617,48.8674240112305,0],[117.837211608887,48.8680267333984,0],[118.628967285156,48.868766784668,0],[119.42073059082,48.8696708679199,0],[120.21248626709,48.8708457946777,0],[121.004241943359,48.8723335266113,0],[121.795997619629,48.8741569519043,0],[122.587760925293,48.8763694763184,0],[123.379516601562,48.8791236877441,0],[124.171272277832,48.8826522827148,0],[124.963027954102,48.8869361877441,0],[125.754791259766,48.8920936584473,0],[126.546546936035,48.8982849121094,0],[127.338302612305,48.9062843322754,0],[128.130065917969,48.9159126281738,0],[128.921813964844,48.9274101257324,0],[129.713577270508,48.941032409668,0],[130.505325317383,48.958080291748,0],[131.297088623047,48.9787521362305,0],[132.088851928711,49.0032196044922,0],[132.880599975586,49.0319786071777,0],[133.67236328125,49.0666656494141,0],[134.464126586914,49.109073638916,0],[135.255874633789,49.158805847168,0],[136.047637939453,49.2167510986328,0],[136.839385986328,49.284366607666,0],[137.631149291992,49.3674964904785,0],[138.422912597656,49.4640350341797,0],[139.214660644531,49.5754890441895,0],[140.006423950195,49.7034378051758,0],[140.798187255859,49.8573837280273,0],[141.589935302734,50.0363273620605,0],[142.381698608398,50.2409515380859,0],[143.173446655273,50.4737358093262,0],[143.965209960938,50.7449493408203,0],[144.756973266602,51.0616111755371,0],[145.548721313477,51.4201202392578,0],[146.340484619141,51.824089050293,0],[147.132232666016,52.281364440918,0],[147.92399597168,52.8161659240723,0],[148.715759277344,53.4153900146484,0],[149.507507324219,54.083911895752,0],[150.299270629883,54.8266944885254,0],[151.091033935547,55.6830787658691,0],[151.882781982422,56.6382141113281,0],[152.674545288086,57.6928176879883,0],[153.466293334961,58.8528938293457,0],[154.258056640625,60.1537780761719,0],[155.049819946289,61.6048889160156,0],[155.841567993164,63.1899833679199,0],[156.633331298828,64.9154663085938,0],[157.425079345703,66.8033218383789,0],[158.216842651367,68.9032745361328,0],[159.008605957031,71.171745300293,0],[159.800354003906,73.6144180297852,0],[160.59211730957,76.2368850708008,0],[161.383880615234,79.1220474243164,0],[162.175628662109,82.2107162475586,0],[162.967391967773,85.4992218017578,0],[163.759140014648,88.9907760620117,0],[164.550903320312,92.7424850463867,0],[165.342666625977,96.7394561767578,0],[166.134414672852,100.945457458496,0],[166.926177978516,105.359741210938,0],[167.71794128418,110.00602722168,0],[168.509689331055,114.915924072266,0],[169.301452636719,120.020172119141,0],[170.093200683594,125.312934875488,0],[170.884963989258,130.787979125977,0],[171.676727294922,136.502426147461,0],[172.468475341797,142.370712280273,0],[173.260238647461,148.379653930664,0],[174.051986694336,154.517883300781,0],[174.84375,160.798126220703,0],[175.635513305664,167.177520751953,0],[176.427261352539,173.624633789062,0],[177.219024658203,180.12419128418,0],[178.010787963867,186.661285400391,0],[178.802536010742,193.203552246094,0],[179.594299316406,199.725006103516,0],[180.386047363281,206.209075927734,0],[181.177810668945,212.638122558594,0],[181.969573974609,218.949417114258,0],[182.761322021484,225.150573730469,0],[183.553085327148,231.226837158203,0],[184.344848632812,237.163757324219,0],[185.136596679688,242.890838623047,0],[185.928359985352,248.414215087891,0],[186.720108032227,253.74348449707,0],[187.511871337891,258.869110107422,0],[188.303634643555,263.742523193359,0],[189.09538269043,268.3310546875,0],[189.887145996094,272.6865234375,0],[190.678894042969,276.805847167969,0],[191.470657348633,280.677154541016,0],[192.262420654297,284.214385986328,0],[193.054168701172,287.514343261719,0],[193.845932006836,290.580169677734,0],[194.6376953125,293.415374755859,0],[195.429443359375,295.953002929688,0],[196.221206665039,298.258178710938,0],[197.012954711914,300.360198974609,0],[197.804718017578,302.266967773438,0],[198.596481323242,303.953186035156,0],[199.388229370117,305.432434082031,0],[200.179992675781,306.757354736328,0],[200.971740722656,307.937683105469,0],[201.76350402832,308.975830078125,0],[202.555267333984,309.854919433594,0],[203.347015380859,310.633911132812,0],[204.138778686523,311.322357177734,0],[204.930541992188,311.929718017578,0],[205.722290039062,312.447174072266,0],[206.514053344727,312.910369873047,0],[207.305801391602,313.332305908203,0],[208.097564697266,313.721160888672,0],[208.88932800293,314.082916259766,0],[209.681076049805,314.433868408203,0],[210.472839355469,314.785491943359,0],[211.264602661133,315.144653320312,0],[212.056350708008,315.5205078125,0],[212.848114013672,315.93212890625,0],[213.639862060547,316.380187988281,0],[214.431625366211,316.870635986328,0],[215.223388671875,317.409362792969,0],[216.01513671875,318.027954101562,0],[216.806900024414,318.716583251953,0],[217.598648071289,319.477447509766,0],[218.390411376953,320.315216064453,0],[219.182174682617,321.257019042969,0],[219.973922729492,322.304840087891,0],[220.765686035156,323.446166992188,0],[221.55744934082,324.683227539062,0],[222.349197387695,326.029479980469,0],[223.140960693359,327.506164550781,0],[223.932708740234,329.080413818359,0],[224.724472045898,330.750030517578,0],[225.516235351562,332.512420654297,0],[226.307983398438,334.394927978516,0],[227.099746704102,336.352783203125,0],[227.891510009766,338.375549316406,0],[228.683258056641,340.4541015625,0],[229.475021362305,342.583435058594,0],[230.26676940918,344.732452392578,0],[231.058532714844,346.879364013672,0],[231.850296020508,349.008087158203,0],[232.642044067383,351.092010498047,0],[233.433807373047,353.08251953125,0],[234.225555419922,354.97021484375,0],[235.017318725586,356.734161376953,0],[235.80908203125,358.352355957031,0],[236.600830078125,359.708374023438,0],[237.392593383789,360.842071533203,0],[238.184356689453,361.731781005859,0],[238.976104736328,362.35595703125,0],[239.767868041992,362.593139648438,0],[240.559616088867,362.454956054688,0],[241.351379394531,361.963195800781,0],[242.143142700195,361.101409912109,0],[242.93489074707,359.785400390625,0],[243.726654052734,357.947692871094,0],[244.518402099609,355.684478759766,0],[245.310165405273,352.988800048828,0],[246.101928710938,349.841461181641,0],[246.893676757812,346.073364257812,0],[247.685440063477,341.865234375,0],[248.477203369141,337.22216796875,0],[249.268951416016,332.150177001953,0],[250.06071472168,326.528106689453,0],[250.852462768555,320.471893310547,0],[251.644226074219,314.041931152344,0],[252.435989379883,307.255310058594,0],[253.227737426758,300.074066162109,0],[254.019500732422,292.528167724609,0],[254.811264038086,284.722106933594,0],[255.603012084961,276.680541992188,0],[256.394775390625,268.419677734375,0],[257.1865234375,259.936401367188,0],[257.978302001953,251.336441040039,0],[258.770050048828,242.646850585938,0],[259.561798095703,233.894592285156,0],[260.353546142578,225.115921020508,0],[261.145324707031,216.365173339844,0],[261.937072753906,207.668258666992,0],[262.728820800781,199.049026489258,0],[263.520599365234,190.562606811523,0],[264.312347412109,182.25373840332,0],[265.104095458984,174.116668701172,0],[265.895874023438,166.168609619141,0],[266.687622070312,158.444854736328,0],[267.479370117188,151.034591674805,0],[268.271148681641,143.874450683594,0],[269.062896728516,136.973510742188,0],[269.854644775391,130.340209960938,0],[270.646392822266,124.089736938477,0],[271.438171386719,118.139717102051,0],[272.229919433594,112.476234436035,0],[273.021667480469,107.100212097168,0],[273.813446044922,102.08031463623,0],[274.605194091797,97.3972091674805,0],[275.396942138672,92.9917755126953,0],[276.188720703125,88.8593368530273,0],[276.98046875,85.0218887329102,0],[277.772216796875,81.5232696533203,0],[278.563995361328,78.2685775756836,0],[279.355743408203,75.2499465942383,0],[280.147491455078,72.4593353271484,0],[280.939239501953,69.9681777954102,0],[281.731018066406,67.6809692382812,0],[282.522766113281,65.5824813842773,0],[283.314514160156,63.6638336181641,0],[284.106292724609,61.9565620422363,0],[284.898040771484,60.4259262084961,0],[285.689788818359,59.0360450744629,0],[286.481567382812,57.7787246704102,0],[287.273315429688,56.6601982116699,0],[288.065063476562,55.6839256286621,0],[288.856842041016,54.8061447143555,0],[289.648590087891,54.0201644897461,0],[290.440338134766,53.3194198608398,0],[291.232086181641,52.7252502441406,0],[292.023864746094,52.1963195800781,0],[292.815612792969,51.7273368835449,0],[293.607360839844,51.3134574890137,0],[294.399139404297,50.9620628356934,0],[295.190887451172,50.657829284668,0],[295.982635498047,50.3905982971191,0],[296.7744140625,50.1570777893066,0],[297.566162109375,49.9580116271973,0],[298.35791015625,49.7909240722656,0],[299.149688720703,49.6454696655273,0],[299.941436767578,49.5195579528809,0],[300.733184814453,49.411491394043,0],[301.524932861328,49.323860168457,0],[302.316711425781,49.2482109069824,0],[303.108459472656,49.1833190917969,0],[303.900207519531,49.128002166748,0],[304.691986083984,49.083194732666,0],[305.483734130859,49.0456008911133,0],[306.275482177734,49.0136299133301,0],[307.067260742188,48.9866256713867,0],[307.859008789062,48.9645843505859,0],[308.650756835938,48.9467315673828,0],[309.442535400391,48.9316711425781,0],[310.234283447266,48.9190635681152,0],[311.026031494141,48.9086608886719,0],[311.817810058594,48.900562286377,0],[312.609558105469,48.8937797546387,0],[313.401306152344,48.8881492614746,0],[314.193054199219,48.8835144042969,0],[314.984832763672,48.8799324035645,0],[315.776580810547,48.8770141601562,0],[316.568328857422,48.8746109008789,0],[317.360107421875,48.8726463317871,0],[318.15185546875,48.8711128234863,0],[318.943603515625,48.8699111938477,0],[319.735382080078,48.8689308166504,0],[320.527130126953,48.8681335449219,0],[321.318878173828,48.867504119873,0],[322.110656738281,48.8670310974121,0],[322.902404785156,48.8666496276855,0],[323.694152832031,48.866340637207,0],[324.485900878906,48.866096496582,0],[325.277679443359,48.8659133911133,0],[326.069427490234,48.8657722473145,0],[326.861175537109,48.8656578063965,0],[327.652954101562,48.8655662536621,0],[328.444702148438,48.8655014038086,0],[329.236450195312,48.8654479980469,0],[330.028228759766,48.8654098510742,0],[330.819976806641,48.8653755187988,0],[331.611724853516,48.8653526306152,0],[332.403503417969,48.8653335571289,0],[333.195251464844,48.8653221130371,0],[333.986999511719,48.8653106689453,0],[334.778747558594,48.8653030395508,0],[335.570526123047,48.8652954101562,0],[336.362274169922,48.865291595459,0],[337.154022216797,48.8652877807617,0],[337.94580078125,48.8652877807617,0],[338.737548828125,48.8652839660645,0],[339.529296875,48.8652839660645,0],[340.321075439453,48.8652839660645,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0]],&#34;colors&#34;:[[1,1,1,0]],&#34;centers&#34;:[[60.8306732177734,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[98.0432739257812,48.8652839660645,0],[98.8350372314453,48.8652839660645,0],[99.6267929077148,48.8652839660645,0],[100.418548583984,48.8652877807617,0],[101.210304260254,48.8652877807617,0],[102.002059936523,48.865291595459,0],[102.793823242188,48.8652954101562,0],[103.585578918457,48.8653030395508,0],[104.377334594727,48.8653106689453,0],[105.169090270996,48.8653221130371,0],[105.96085357666,48.8653335571289,0],[106.75260925293,48.8653526306152,0],[107.544364929199,48.8653755187988,0],[108.336120605469,48.865406036377,0],[109.127883911133,48.8654441833496,0],[109.919639587402,48.8654937744141,0],[110.711395263672,48.8655586242676,0],[111.503150939941,48.8656463623047,0],[112.294914245605,48.8657531738281,0],[113.086669921875,48.8658866882324,0],[113.878425598145,48.8660736083984,0],[114.670181274414,48.8663024902344,0],[115.461936950684,48.8665924072266,0],[116.253700256348,48.866943359375,0],[117.045455932617,48.8674240112305,0],[117.837211608887,48.8680267333984,0],[118.628967285156,48.868766784668,0],[119.42073059082,48.8696708679199,0],[120.21248626709,48.8708457946777,0],[121.004241943359,48.8723335266113,0],[121.795997619629,48.8741569519043,0],[122.587760925293,48.8763694763184,0],[123.379516601562,48.8791236877441,0],[124.171272277832,48.8826522827148,0],[124.963027954102,48.8869361877441,0],[125.754791259766,48.8920936584473,0],[126.546546936035,48.8982849121094,0],[127.338302612305,48.9062843322754,0],[128.130065917969,48.9159126281738,0],[128.921813964844,48.9274101257324,0],[129.713577270508,48.941032409668,0],[130.505325317383,48.958080291748,0],[131.297088623047,48.9787521362305,0],[132.088851928711,49.0032196044922,0],[132.880599975586,49.0319786071777,0],[133.67236328125,49.0666656494141,0],[134.464126586914,49.109073638916,0],[135.255874633789,49.158805847168,0],[136.047637939453,49.2167510986328,0],[136.839385986328,49.284366607666,0],[137.631149291992,49.3674964904785,0],[138.422912597656,49.4640350341797,0],[139.214660644531,49.5754890441895,0],[140.006423950195,49.7034378051758,0],[140.798187255859,49.8573837280273,0],[141.589935302734,50.0363273620605,0],[142.381698608398,50.2409515380859,0],[143.173446655273,50.4737358093262,0],[143.965209960938,50.7449493408203,0],[144.756973266602,51.0616111755371,0],[145.548721313477,51.4201202392578,0],[146.340484619141,51.824089050293,0],[147.132232666016,52.281364440918,0],[147.92399597168,52.8161659240723,0],[148.715759277344,53.4153900146484,0],[149.507507324219,54.083911895752,0],[150.299270629883,54.8266944885254,0],[151.091033935547,55.6830787658691,0],[151.882781982422,56.6382141113281,0],[152.674545288086,57.6928176879883,0],[153.466293334961,58.8528938293457,0],[154.258056640625,60.1537780761719,0],[155.049819946289,61.6048889160156,0],[155.841567993164,63.1899833679199,0],[156.633331298828,64.9154663085938,0],[157.425079345703,66.8033218383789,0],[158.216842651367,68.9032745361328,0],[159.008605957031,71.171745300293,0],[159.800354003906,73.6144180297852,0],[160.59211730957,76.2368850708008,0],[161.383880615234,79.1220474243164,0],[162.175628662109,82.2107162475586,0],[162.967391967773,85.4992218017578,0],[163.759140014648,88.9907760620117,0],[164.550903320312,92.7424850463867,0],[165.342666625977,96.7394561767578,0],[166.134414672852,100.945457458496,0],[166.926177978516,105.359741210938,0],[167.71794128418,110.00602722168,0],[168.509689331055,114.915924072266,0],[169.301452636719,120.020172119141,0],[170.093200683594,125.312934875488,0],[170.884963989258,130.787979125977,0],[171.676727294922,136.502426147461,0],[172.468475341797,142.370712280273,0],[173.260238647461,148.379653930664,0],[174.051986694336,154.517883300781,0],[174.84375,160.798126220703,0],[175.635513305664,167.177520751953,0],[176.427261352539,173.624633789062,0],[177.219024658203,180.12419128418,0],[178.010787963867,186.661285400391,0],[178.802536010742,193.203552246094,0],[179.594299316406,199.725006103516,0],[180.386047363281,206.209075927734,0],[181.177810668945,212.638122558594,0],[181.969573974609,218.949417114258,0],[182.761322021484,225.150573730469,0],[183.553085327148,231.226837158203,0],[184.344848632812,237.163757324219,0],[185.136596679688,242.890838623047,0],[185.928359985352,248.414215087891,0],[186.720108032227,253.74348449707,0],[187.511871337891,258.869110107422,0],[188.303634643555,263.742523193359,0],[189.09538269043,268.3310546875,0],[189.887145996094,272.6865234375,0],[190.678894042969,276.805847167969,0],[191.470657348633,280.677154541016,0],[192.262420654297,284.214385986328,0],[193.054168701172,287.514343261719,0],[193.845932006836,290.580169677734,0],[194.6376953125,293.415374755859,0],[195.429443359375,295.953002929688,0],[196.221206665039,298.258178710938,0],[197.012954711914,300.360198974609,0],[197.804718017578,302.266967773438,0],[198.596481323242,303.953186035156,0],[199.388229370117,305.432434082031,0],[200.179992675781,306.757354736328,0],[200.971740722656,307.937683105469,0],[201.76350402832,308.975830078125,0],[202.555267333984,309.854919433594,0],[203.347015380859,310.633911132812,0],[204.138778686523,311.322357177734,0],[204.930541992188,311.929718017578,0],[205.722290039062,312.447174072266,0],[206.514053344727,312.910369873047,0],[207.305801391602,313.332305908203,0],[208.097564697266,313.721160888672,0],[208.88932800293,314.082916259766,0],[209.681076049805,314.433868408203,0],[210.472839355469,314.785491943359,0],[211.264602661133,315.144653320312,0],[212.056350708008,315.5205078125,0],[212.848114013672,315.93212890625,0],[213.639862060547,316.380187988281,0],[214.431625366211,316.870635986328,0],[215.223388671875,317.409362792969,0],[216.01513671875,318.027954101562,0],[216.806900024414,318.716583251953,0],[217.598648071289,319.477447509766,0],[218.390411376953,320.315216064453,0],[219.182174682617,321.257019042969,0],[219.973922729492,322.304840087891,0],[220.765686035156,323.446166992188,0],[221.55744934082,324.683227539062,0],[222.349197387695,326.029479980469,0],[223.140960693359,327.506164550781,0],[223.932708740234,329.080413818359,0],[224.724472045898,330.750030517578,0],[225.516235351562,332.512420654297,0],[226.307983398438,334.394927978516,0],[227.099746704102,336.352783203125,0],[227.891510009766,338.375549316406,0],[228.683258056641,340.4541015625,0],[229.475021362305,342.583435058594,0],[230.26676940918,344.732452392578,0],[231.058532714844,346.879364013672,0],[231.850296020508,349.008087158203,0],[232.642044067383,351.092010498047,0],[233.433807373047,353.08251953125,0],[234.225555419922,354.97021484375,0],[235.017318725586,356.734161376953,0],[235.80908203125,358.352355957031,0],[236.600830078125,359.708374023438,0],[237.392593383789,360.842071533203,0],[238.184356689453,361.731781005859,0],[238.976104736328,362.35595703125,0],[239.767868041992,362.593139648438,0],[240.559616088867,362.454956054688,0],[241.351379394531,361.963195800781,0],[242.143142700195,361.101409912109,0],[242.93489074707,359.785400390625,0],[243.726654052734,357.947692871094,0],[244.518402099609,355.684478759766,0],[245.310165405273,352.988800048828,0],[246.101928710938,349.841461181641,0],[246.893676757812,346.073364257812,0],[247.685440063477,341.865234375,0],[248.477203369141,337.22216796875,0],[249.268951416016,332.150177001953,0],[250.06071472168,326.528106689453,0],[250.852462768555,320.471893310547,0],[251.644226074219,314.041931152344,0],[252.435989379883,307.255310058594,0],[253.227737426758,300.074066162109,0],[254.019500732422,292.528167724609,0],[254.811264038086,284.722106933594,0],[255.603012084961,276.680541992188,0],[256.394775390625,268.419677734375,0],[257.1865234375,259.936401367188,0],[257.978302001953,251.336441040039,0],[258.770050048828,242.646850585938,0],[259.561798095703,233.894592285156,0],[260.353546142578,225.115921020508,0],[261.145324707031,216.365173339844,0],[261.937072753906,207.668258666992,0],[262.728820800781,199.049026489258,0],[263.520599365234,190.562606811523,0],[264.312347412109,182.25373840332,0],[265.104095458984,174.116668701172,0],[265.895874023438,166.168609619141,0],[266.687622070312,158.444854736328,0],[267.479370117188,151.034591674805,0],[268.271148681641,143.874450683594,0],[269.062896728516,136.973510742188,0],[269.854644775391,130.340209960938,0],[270.646392822266,124.089736938477,0],[271.438171386719,118.139717102051,0],[272.229919433594,112.476234436035,0],[273.021667480469,107.100212097168,0],[273.813446044922,102.08031463623,0],[274.605194091797,97.3972091674805,0],[275.396942138672,92.9917755126953,0],[276.188720703125,88.8593368530273,0],[276.98046875,85.0218887329102,0],[277.772216796875,81.5232696533203,0],[278.563995361328,78.2685775756836,0],[279.355743408203,75.2499465942383,0],[280.147491455078,72.4593353271484,0],[280.939239501953,69.9681777954102,0],[281.731018066406,67.6809692382812,0],[282.522766113281,65.5824813842773,0],[283.314514160156,63.6638336181641,0],[284.106292724609,61.9565620422363,0],[284.898040771484,60.4259262084961,0],[285.689788818359,59.0360450744629,0],[286.481567382812,57.7787246704102,0],[287.273315429688,56.6601982116699,0],[288.065063476562,55.6839256286621,0],[288.856842041016,54.8061447143555,0],[289.648590087891,54.0201644897461,0],[290.440338134766,53.3194198608398,0],[291.232086181641,52.7252502441406,0],[292.023864746094,52.1963195800781,0],[292.815612792969,51.7273368835449,0],[293.607360839844,51.3134574890137,0],[294.399139404297,50.9620628356934,0],[295.190887451172,50.657829284668,0],[295.982635498047,50.3905982971191,0],[296.7744140625,50.1570777893066,0],[297.566162109375,49.9580116271973,0],[298.35791015625,49.7909240722656,0],[299.149688720703,49.6454696655273,0],[299.941436767578,49.5195579528809,0],[300.733184814453,49.411491394043,0],[301.524932861328,49.323860168457,0],[302.316711425781,49.2482109069824,0],[303.108459472656,49.1833190917969,0],[303.900207519531,49.128002166748,0],[304.691986083984,49.083194732666,0],[305.483734130859,49.0456008911133,0],[306.275482177734,49.0136299133301,0],[307.067260742188,48.9866256713867,0],[307.859008789062,48.9645843505859,0],[308.650756835938,48.9467315673828,0],[309.442535400391,48.9316711425781,0],[310.234283447266,48.9190635681152,0],[311.026031494141,48.9086608886719,0],[311.817810058594,48.900562286377,0],[312.609558105469,48.8937797546387,0],[313.401306152344,48.8881492614746,0],[314.193054199219,48.8835144042969,0],[314.984832763672,48.8799324035645,0],[315.776580810547,48.8770141601562,0],[316.568328857422,48.8746109008789,0],[317.360107421875,48.8726463317871,0],[318.15185546875,48.8711128234863,0],[318.943603515625,48.8699111938477,0],[319.735382080078,48.8689308166504,0],[320.527130126953,48.8681335449219,0],[321.318878173828,48.867504119873,0],[322.110656738281,48.8670310974121,0],[322.902404785156,48.8666496276855,0],[323.694152832031,48.866340637207,0],[324.485900878906,48.866096496582,0],[325.277679443359,48.8659133911133,0],[326.069427490234,48.8657722473145,0],[326.861175537109,48.8656578063965,0],[327.652954101562,48.8655662536621,0],[328.444702148438,48.8655014038086,0],[329.236450195312,48.8654479980469,0],[330.028228759766,48.8654098510742,0],[330.819976806641,48.8653755187988,0],[331.611724853516,48.8653526306152,0],[332.403503417969,48.8653335571289,0],[333.195251464844,48.8653221130371,0],[333.986999511719,48.8653106689453,0],[334.778747558594,48.8653030395508,0],[335.570526123047,48.8652954101562,0],[336.362274169922,48.865291595459,0],[337.154022216797,48.8652877807617,0],[337.94580078125,48.8652877807617,0],[338.737548828125,48.8652839660645,0],[339.529296875,48.8652839660645,0],[340.321075439453,48.8652839660645,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16480},&#34;193&#34;:{&#34;id&#34;:193,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.90000009536743,-2.90000009536743]},&#34;vertices&#34;:[[60.8306732177734,48.8652801513672,0],[79.0410995483398,90.5942916870117,0],[78.2493362426758,93.859245300293,0],[79.0410995483398,90.5942916870117,0],[60.8306732177734,48.8652801513672,0],[79.8328552246094,87.5317230224609,0],[80.6246109008789,84.6853332519531,0],[79.8328552246094,87.5317230224609,0],[60.8306732177734,48.8652801513672,0],[60.8306732177734,48.8652801513672,0],[81.4163665771484,82.1370239257812,0],[80.6246109008789,84.6853332519531,0],[75.8740692138672,104.749923706055,0],[75.0823059082031,108.667381286621,0],[60.8306732177734,48.8652801513672,0],[77.4575805664062,97.3114013671875,0],[76.6658248901367,100.940643310547,0],[60.8306732177734,48.8652801513672,0],[78.2493362426758,93.859245300293,0],[77.4575805664062,97.3114013671875,0],[60.8306732177734,48.8652801513672,0],[75.8740692138672,104.749923706055,0],[60.8306732177734,48.8652801513672,0],[76.6658248901367,100.940643310547,0],[60.8306732177734,48.8652801513672,0],[75.0823059082031,108.667381286621,0],[74.2905502319336,112.668449401855,0],[86.1669158935547,72.4051818847656,0],[85.3751602172852,73.3145599365234,0],[60.8306732177734,48.8652801513672,0],[87.7504272460938,71.3678741455078,0],[86.9586715698242,71.7570877075195,0],[60.8306732177734,48.8652801513672,0],[86.1669158935547,72.4051818847656,0],[60.8306732177734,48.8652801513672,0],[86.9586715698242,71.7570877075195,0],[82.2081298828125,79.8457336425781,0],[81.4163665771484,82.1370239257812,0],[60.8306732177734,48.8652801513672,0],[83.7916412353516,76.0231094360352,0],[82.999885559082,77.8061370849609,0],[60.8306732177734,48.8652801513672,0],[84.5833969116211,74.5003814697266,0],[83.7916412353516,76.0231094360352,0],[60.8306732177734,48.8652801513672,0],[82.2081298828125,79.8457336425781,0],[60.8306732177734,48.8652801513672,0],[82.999885559082,77.8061370849609,0],[85.3751602172852,73.3145599365234,0],[84.5833969116211,74.5003814697266,0],[60.8306732177734,48.8652801513672,0],[60.8306732177734,48.8652801513672,0],[88.5421829223633,71.2344512939453,0],[87.7504272460938,71.3678741455078,0],[66.3729782104492,149.740203857422,0],[65.5812225341797,152.342651367188,0],[60.8306732177734,159.882751464844,0],[60.8306732177734,159.882751464844,0],[67.1647338867188,146.846633911133,0],[66.3729782104492,149.740203857422,0],[60.8306732177734,159.882751464844,0],[65.5812225341797,152.342651367188,0],[64.7894592285156,154.616241455078,0],[61.6224327087402,159.628890991211,0],[60.8306732177734,159.882751464844,0],[62.4141883850098,158.957458496094,0],[60.8306732177734,159.882751464844,0],[63.2059478759766,157.890960693359,0],[62.4141883850098,158.957458496094,0],[63.2059478759766,157.890960693359,0],[60.8306732177734,159.882751464844,0],[63.9977035522461,156.439666748047,0],[60.8306732177734,159.882751464844,0],[64.7894592285156,154.616241455078,0],[63.9977035522461,156.439666748047,0],[67.1647338867188,146.846633911133,0],[60.8306732177734,159.882751464844,0],[67.9564895629883,143.687698364258,0],[60.8306732177734,48.8652801513672,0],[71.915283203125,124.88858795166,0],[71.1235198974609,128.903381347656,0],[60.8306732177734,48.8652801513672,0],[72.7070388793945,120.816917419434,0],[71.915283203125,124.88858795166,0],[60.8306732177734,159.882751464844,0],[60.8306732177734,48.8652801513672,0],[71.1235198974609,128.903381347656,0],[67.9564895629883,143.687698364258,0],[60.8306732177734,159.882751464844,0],[68.7482528686523,140.290451049805,0],[69.5400085449219,136.639221191406,0],[68.7482528686523,140.290451049805,0],[60.8306732177734,159.882751464844,0],[60.8306732177734,159.882751464844,0],[70.3317642211914,132.830535888672,0],[69.5400085449219,136.639221191406,0],[71.1235198974609,128.903381347656,0],[70.3317642211914,132.830535888672,0],[60.8306732177734,159.882751464844,0],[60.8306732177734,48.8652801513672,0],[73.4987945556641,116.727432250977,0],[72.7070388793945,120.816917419434,0],[60.8306732177734,48.8652801513672,0],[74.2905502319336,112.668449401855,0],[73.4987945556641,116.727432250977,0],[89.3339462280273,71.4204864501953,0],[88.5421829223633,71.2344512939453,0],[60.8306732177734,48.8652801513672,0],[90.9174575805664,72.5376892089844,0],[90.1257019042969,71.861457824707,0],[238.976104736328,56.0229187011719,0],[89.3339462280273,71.4204864501953,0],[60.8306732177734,48.8652801513672,0],[90.1257019042969,71.861457824707,0],[233.433807373047,66.1767501831055,0],[93.2927322387695,75.9648971557617,0],[92.5009765625,74.5691375732422,0],[231.058532714844,72.7599411010742,0],[94.8762435913086,79.3661270141602,0],[94.0844879150391,77.5706939697266,0],[230.26676940918,75.3057403564453,0],[95.6680068969727,81.3425674438477,0],[94.8762435913086,79.3661270141602,0],[94.0844879150391,77.5706939697266,0],[93.2927322387695,75.9648971557617,0],[232.642044067383,68.211181640625,0],[90.9174575805664,72.5376892089844,0],[236.600830078125,59.556453704834,0],[91.7092132568359,73.4425811767578,0],[228.683258056641,80.8521347045898,0],[97.2515182495117,85.8434906005859,0],[96.4597625732422,83.4912719726562,0],[227.099746704102,86.9987945556641,0],[98.8350372314453,90.9958267211914,0],[98.0432739257812,88.3509826660156,0],[98.0432739257812,88.3509826660156,0],[97.2515182495117,85.8434906005859,0],[227.891510009766,83.8458862304688,0],[225.516235351562,93.7243804931641,0],[100.418548583984,96.6647567749023,0],[99.6267929077148,93.7697601318359,0],[187.511871337891,139.361694335938,0],[102.002059936523,102.843063354492,0],[101.210304260254,99.7003784179688,0],[187.511871337891,139.361694335938,0],[102.793823242188,106.08073425293,0],[102.002059936523,102.843063354492,0],[101.210304260254,99.7003784179688,0],[100.418548583984,96.6647567749023,0],[187.511871337891,139.361694335938,0],[99.6267929077148,93.7697601318359,0],[98.8350372314453,90.9958267211914,0],[226.307983398438,90.3038482666016,0],[96.4597625732422,83.4912719726562,0],[95.6680068969727,81.3425674438477,0],[229.475021362305,78.0041122436523,0],[186.720108032227,139.912567138672,0],[104.377334594727,112.823310852051,0],[103.585578918457,109.408782958984,0],[185.928359985352,140.655776977539,0],[105.96085357666,119.949729919434,0],[105.169090270996,116.343048095703,0],[105.169090270996,116.343048095703,0],[104.377334594727,112.823310852051,0],[186.720108032227,139.912567138672,0],[185.136596679688,141.589599609375,0],[107.544364929199,127.413642883301,0],[106.75260925293,123.639228820801,0],[183.553085327148,144.041168212891,0],[109.127883911133,135.258117675781,0],[108.336120605469,131.276016235352,0],[182.761322021484,145.591033935547,0],[109.919639587402,139.351440429688,0],[109.127883911133,135.258117675781,0],[108.336120605469,131.276016235352,0],[107.544364929199,127.413642883301,0],[184.344848632812,142.711959838867,0],[106.75260925293,123.639228820801,0],[105.96085357666,119.949729919434,0],[185.136596679688,141.589599609375,0],[180.386047363281,151.297561645508,0],[111.503150939941,147.886474609375,0],[110.711395263672,143.557922363281,0],[178.010787963867,158.68782043457,0],[113.086669921875,156.991333007812,0],[112.294914245605,152.346603393555,0],[112.294914245605,152.346603393555,0],[111.503150939941,147.886474609375,0],[179.594299316406,153.564697265625,0],[175.635513305664,167.701385498047,0],[114.670181274414,166.803436279297,0],[113.878425598145,161.809921264648,0],[174.051986694336,174.738983154297,0],[116.253700256348,177.358489990234,0],[115.461944580078,171.982757568359,0],[173.260238647461,178.551681518555,0],[116.253700256348,177.358489990234,0],[174.051986694336,174.738983154297,0],[115.461944580078,171.982757568359,0],[114.670181274414,166.803436279297,0],[174.84375,171.124069213867,0],[113.878425598145,161.809921264648,0],[113.086669921875,156.991333007812,0],[177.219024658203,161.5087890625,0],[110.711395263672,143.557922363281,0],[109.919639587402,139.351440429688,0],[181.177810668945,149.221374511719,0],[103.585578918457,109.408782958984,0],[102.793823242188,106.08073425293,0],[186.720108032227,139.912567138672,0],[60.8306732177734,48.8652801513672,0],[240.559616088867,54.2581596374512,0],[90.1257019042969,71.861457824707,0],[117.837211608887,188.877578735352,0],[117.045455932617,182.998962402344,0],[171.676727294922,186.81706237793,0],[168.509689331055,206.261199951172,0],[120.21248626709,207.903076171875,0],[119.42073059082,201.325942993164,0],[119.42073059082,201.325942993164,0],[118.628967285156,194.985107421875,0],[169.301452636719,201.052536010742,0],[166.926177978516,217.497482299805,0],[121.795997619629,221.900665283203,0],[121.004241943359,214.777709960938,0],[164.550903320312,236.200271606445,0],[123.379516601562,236.804550170898,0],[122.587760925293,229.246337890625,0],[163.759140014648,242.907562255859,0],[124.171272277832,244.562911987305,0],[123.379516601562,236.804550170898,0],[122.587760925293,229.246337890625,0],[121.795997619629,221.900665283203,0],[166.134414672852,223.499771118164,0],[121.004241943359,214.777709960938,0],[120.21248626709,207.903076171875,0],[167.71794128418,211.732528686523,0],[162.175628662109,257.010437011719,0],[125.754791259766,260.683380126953,0],[124.963027954102,252.544296264648,0],[160.59211730957,271.783569335938,0],[127.338302612305,277.2890625,0],[126.546546936035,268.940887451172,0],[126.546546936035,268.940887451172,0],[125.754791259766,260.683380126953,0],[161.383880615234,264.322570800781,0],[128.921813964844,294.126617431641,0],[158.216842651367,294.833984375,0],[129.713577270508,302.512786865234,0],[131.297088623047,318.996490478516,0],[130.505325317383,310.816162109375,0],[155.841567993164,318.029815673828,0],[130.505325317383,310.816162109375,0],[129.713577270508,302.512786865234,0],[156.633331298828,310.346435546875,0],[159.008605957031,287.083953857422,0],[128.921813964844,294.126617431641,0],[128.130065917969,285.6982421875,0],[128.130065917969,285.6982421875,0],[127.338302612305,277.2890625,0],[159.800354003906,279.380798339844,0],[124.963027954102,252.544296264648,0],[124.171272277832,244.562911987305,0],[162.967391967773,249.866317749023,0],[134.464126586914,349.274505615234,0],[133.67236328125,342.179229736328,0],[152.674545288086,347.033630371094,0],[135.255874633789,355.995391845703,0],[134.464126586914,349.274505615234,0],[151.882781982422,353.630401611328,0],[132.880599975586,334.750671386719,0],[153.466293334961,340.114349365234,0],[133.67236328125,342.179229736328,0],[136.047637939453,362.301544189453,0],[150.299270629883,365.536712646484,0],[136.839385986328,368.024536132812,0],[138.422912597656,377.788269042969,0],[137.631149291992,373.183837890625,0],[148.715759277344,375.662322998047,0],[137.631149291992,373.183837890625,0],[136.839385986328,368.024536132812,0],[149.507507324219,370.840270996094,0],[135.255874633789,355.995391845703,0],[151.091033935547,359.787628173828,0],[136.047637939453,362.301544189453,0],[154.258056640625,332.946990966797,0],[132.880599975586,334.750671386719,0],[132.088851928711,327.012573242188,0],[140.006423950195,385.222137451172,0],[146.340484619141,386.41748046875,0],[140.798187255859,387.84033203125,0],[140.798187255859,387.84033203125,0],[145.548721313477,388.744079589844,0],[141.589935302734,389.740173339844,0],[147.132232666016,383.467529296875,0],[140.006423950195,385.222137451172,0],[139.214660644531,381.809631347656,0],[142.381698608398,390.968658447266,0],[141.589935302734,389.740173339844,0],[144.756973266602,390.428283691406,0],[142.381698608398,390.968658447266,0],[143.965209960938,391.393402099609,0],[143.173446655273,391.520446777344,0],[143.965209960938,391.393402099609,0],[142.381698608398,390.968658447266,0],[144.756973266602,390.428283691406,0],[144.756973266602,390.428283691406,0],[141.589935302734,389.740173339844,0],[145.548721313477,388.744079589844,0],[147.92399597168,379.916015625,0],[139.214660644531,381.809631347656,0],[138.422912597656,377.788269042969,0],[155.049819946289,325.572082519531,0],[132.088851928711,327.012573242188,0],[131.297088623047,318.996490478516,0],[118.628967285156,194.985107421875,0],[117.837211608887,188.877578735352,0],[170.884963989258,191.334594726562,0],[162.967391967773,249.866317749023,0],[124.171272277832,244.562911987305,0],[163.759140014648,242.907562255859,0],[166.134414672852,223.499771118164,0],[165.342666625977,229.735763549805,0],[122.587760925293,229.246337890625,0],[123.379516601562,236.804550170898,0],[164.550903320312,236.200271606445,0],[163.759140014648,242.907562255859,0],[159.008605957031,287.083953857422,0],[128.130065917969,285.6982421875,0],[159.800354003906,279.380798339844,0],[160.59211730957,271.783569335938,0],[126.546546936035,268.940887451172,0],[161.383880615234,264.322570800781,0],[161.383880615234,264.322570800781,0],[125.754791259766,260.683380126953,0],[162.175628662109,257.010437011719,0],[127.338302612305,277.2890625,0],[160.59211730957,271.783569335938,0],[159.800354003906,279.380798339844,0],[162.175628662109,257.010437011719,0],[124.963027954102,252.544296264648,0],[162.967391967773,249.866317749023,0],[171.676727294922,186.81706237793,0],[170.884963989258,191.334594726562,0],[117.837211608887,188.877578735352,0],[172.468475341797,182.567886352539,0],[117.045455932617,182.998962402344,0],[116.253700256348,177.358489990234,0],[171.676727294922,186.81706237793,0],[117.045455932617,182.998962402344,0],[172.468475341797,182.567886352539,0],[167.71794128418,211.732528686523,0],[166.926177978516,217.497482299805,0],[121.004241943359,214.777709960938,0],[169.301452636719,201.052536010742,0],[168.509689331055,206.261199951172,0],[119.42073059082,201.325942993164,0],[170.093200683594,196.078277587891,0],[169.301452636719,201.052536010742,0],[118.628967285156,194.985107421875,0],[167.71794128418,211.732528686523,0],[120.21248626709,207.903076171875,0],[168.509689331055,206.261199951172,0],[170.884963989258,191.334594726562,0],[170.093200683594,196.078277587891,0],[118.628967285156,194.985107421875,0],[166.134414672852,223.499771118164,0],[121.795997619629,221.900665283203,0],[166.926177978516,217.497482299805,0],[149.507507324219,370.840270996094,0],[136.839385986328,368.024536132812,0],[150.299270629883,365.536712646484,0],[151.091033935547,359.787628173828,0],[150.299270629883,365.536712646484,0],[136.047637939453,362.301544189453,0],[149.507507324219,370.840270996094,0],[148.715759277344,375.662322998047,0],[137.631149291992,373.183837890625,0],[145.548721313477,388.744079589844,0],[140.798187255859,387.84033203125,0],[146.340484619141,386.41748046875,0],[147.132232666016,383.467529296875,0],[146.340484619141,386.41748046875,0],[140.006423950195,385.222137451172,0],[139.214660644531,381.809631347656,0],[147.92399597168,379.916015625,0],[147.132232666016,383.467529296875,0],[148.715759277344,375.662322998047,0],[147.92399597168,379.916015625,0],[138.422912597656,377.788269042969,0],[135.255874633789,355.995391845703,0],[151.882781982422,353.630401611328,0],[151.091033935547,359.787628173828,0],[130.505325317383,310.816162109375,0],[156.633331298828,310.346435546875,0],[155.841567993164,318.029815673828,0],[129.713577270508,302.512786865234,0],[157.425094604492,302.599212646484,0],[156.633331298828,310.346435546875,0],[131.297088623047,318.996490478516,0],[155.841567993164,318.029815673828,0],[155.049819946289,325.572082519531,0],[134.464126586914,349.274505615234,0],[152.674545288086,347.033630371094,0],[151.882781982422,353.630401611328,0],[152.674545288086,347.033630371094,0],[133.67236328125,342.179229736328,0],[153.466293334961,340.114349365234,0],[154.258056640625,332.946990966797,0],[153.466293334961,340.114349365234,0],[132.880599975586,334.750671386719,0],[154.258056640625,332.946990966797,0],[132.088851928711,327.012573242188,0],[155.049819946289,325.572082519531,0],[129.713577270508,302.512786865234,0],[158.216842651367,294.833984375,0],[157.425094604492,302.599212646484,0],[159.008605957031,287.083953857422,0],[158.216842651367,294.833984375,0],[128.921813964844,294.126617431641,0],[164.550903320312,236.200271606445,0],[122.587760925293,229.246337890625,0],[165.342666625977,229.735763549805,0],[116.253700256348,177.358489990234,0],[173.260238647461,178.551681518555,0],[172.468475341797,182.567886352539,0],[92.5009765625,74.5691375732422,0],[91.7092132568359,73.4425811767578,0],[235.017318725586,62.5514831542969,0],[250.852462768555,49.4529991149902,0],[250.06071472168,49.5802001953125,0],[60.8306732177734,48.8652801513672,0],[252.435989379883,49.2619667053223,0],[251.644226074219,49.348316192627,0],[60.8306732177734,48.8652801513672,0],[250.852462768555,49.4529991149902,0],[60.8306732177734,48.8652801513672,0],[251.644226074219,49.348316192627,0],[246.893676757812,50.3497772216797,0],[246.101928710938,50.6363639831543,0],[60.8306732177734,48.8652801513672,0],[248.477203369141,49.9049186706543,0],[247.685440063477,50.1084480285645,0],[60.8306732177734,48.8652801513672,0],[249.268951416016,49.7298736572266,0],[248.477203369141,49.9049186706543,0],[60.8306732177734,48.8652801513672,0],[246.893676757812,50.3497772216797,0],[60.8306732177734,48.8652801513672,0],[247.685440063477,50.1084480285645,0],[250.06071472168,49.5802001953125,0],[249.268951416016,49.7298736572266,0],[60.8306732177734,48.8652801513672,0],[257.978302001953,48.9530601501465,0],[257.1865234375,48.9755973815918,0],[60.8306732177734,48.8652801513672,0],[259.561798095703,48.9201774597168,0],[258.770050048828,48.9346542358398,0],[60.8306732177734,48.8652801513672,0],[257.978302001953,48.9530601501465,0],[60.8306732177734,48.8652801513672,0],[258.770050048828,48.9346542358398,0],[254.019500732422,49.1279449462891,0],[253.227737426758,49.1890754699707,0],[60.8306732177734,48.8652801513672,0],[255.603012084961,49.0360488891602,0],[254.811264038086,49.077018737793,0],[60.8306732177734,48.8652801513672,0],[256.394775390625,49.0029945373535,0],[255.603012084961,49.0360488891602,0],[60.8306732177734,48.8652801513672,0],[254.019500732422,49.1279449462891,0],[60.8306732177734,48.8652801513672,0],[254.811264038086,49.077018737793,0],[257.1865234375,48.9755973815918,0],[256.394775390625,49.0029945373535,0],[60.8306732177734,48.8652801513672,0],[252.435989379883,49.2619667053223,0],[60.8306732177734,48.8652801513672,0],[253.227737426758,49.1890754699707,0],[91.7092132568359,73.4425811767578,0],[235.80908203125,60.9777717590332,0],[235.017318725586,62.5514831542969,0],[238.184356689453,57.0851135253906,0],[237.392593383789,58.2609024047852,0],[90.9174575805664,72.5376892089844,0],[91.7092132568359,73.4425811767578,0],[236.600830078125,59.556453704834,0],[235.80908203125,60.9777717590332,0],[94.0844879150391,77.5706939697266,0],[231.850296020508,70.3973617553711,0],[231.058532714844,72.7599411010742,0],[232.642044067383,68.211181640625,0],[93.2927322387695,75.9648971557617,0],[233.433807373047,66.1767501831055,0],[92.5009765625,74.5691375732422,0],[234.225555419922,64.2912979125977,0],[233.433807373047,66.1767501831055,0],[94.0844879150391,77.5706939697266,0],[232.642044067383,68.211181640625,0],[231.850296020508,70.3973617553711,0],[234.225555419922,64.2912979125977,0],[92.5009765625,74.5691375732422,0],[235.017318725586,62.5514831542969,0],[243.726654052734,51.7783813476562,0],[242.93489074707,52.2798080444336,0],[60.8306732177734,48.8652801513672,0],[245.310165405273,50.9668655395508,0],[244.518417358398,51.3459167480469,0],[60.8306732177734,48.8652801513672,0],[243.726654052734,51.7783813476562,0],[60.8306732177734,48.8652801513672,0],[244.518417358398,51.3459167480469,0],[239.767868041992,55.0853805541992,0],[238.976104736328,56.0229187011719,0],[90.1257019042969,71.861457824707,0],[241.351379394531,53.518970489502,0],[240.559616088867,54.2581596374512,0],[60.8306732177734,48.8652801513672,0],[242.143142700195,52.8615646362305,0],[241.351379394531,53.518970489502,0],[60.8306732177734,48.8652801513672,0],[239.767868041992,55.0853805541992,0],[90.1257019042969,71.861457824707,0],[240.559616088867,54.2581596374512,0],[242.93489074707,52.2798080444336,0],[242.143142700195,52.8615646362305,0],[60.8306732177734,48.8652801513672,0],[238.184356689453,57.0851135253906,0],[90.9174575805664,72.5376892089844,0],[238.976104736328,56.0229187011719,0],[246.101928710938,50.6363639831543,0],[245.310165405273,50.9668655395508,0],[60.8306732177734,48.8652801513672,0],[279.355743408203,48.8653259277344,0],[278.563995361328,48.8653411865234,0],[60.8306732177734,48.8652801513672,0],[280.939239501953,48.8653030395508,0],[280.147491455078,48.8653106689453,0],[60.8306732177734,48.8652801513672,0],[279.355743408203,48.8653259277344,0],[60.8306732177734,48.8652801513672,0],[280.147491455078,48.8653106689453,0],[275.396942138672,48.8655052185059,0],[274.605194091797,48.8655853271484,0],[60.8306732177734,48.8652801513672,0],[276.98046875,48.8653984069824,0],[276.188720703125,48.8654441833496,0],[60.8306732177734,48.8652801513672,0],[277.772216796875,48.8653678894043,0],[276.98046875,48.8653984069824,0],[60.8306732177734,48.8652801513672,0],[275.396942138672,48.8655052185059,0],[60.8306732177734,48.8652801513672,0],[276.188720703125,48.8654441833496,0],[278.563995361328,48.8653411865234,0],[277.772216796875,48.8653678894043,0],[60.8306732177734,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[60.8306732177734,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[60.8306732177734,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[282.522766113281,48.865291595459,0],[281.731018066406,48.8652954101562,0],[60.8306732177734,48.8652801513672,0],[284.898040771484,48.8652839660645,0],[283.314514160156,48.8652877807617,0],[60.8306732177734,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652839660645,0],[60.8306732177734,48.8652801513672,0],[282.522766113281,48.865291595459,0],[60.8306732177734,48.8652801513672,0],[283.314514160156,48.8652877807617,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[60.8306732177734,48.8652801513672,0],[280.939239501953,48.8653030395508,0],[60.8306732177734,48.8652801513672,0],[281.731018066406,48.8652954101562,0],[265.104095458984,48.8749008178711,0],[264.312347412109,48.8777503967285,0],[60.8306732177734,48.8652801513672,0],[266.687622070312,48.8708686828613,0],[265.895874023438,48.8726425170898,0],[60.8306732177734,48.8652801513672,0],[265.104095458984,48.8749008178711,0],[60.8306732177734,48.8652801513672,0],[265.895874023438,48.8726425170898,0],[261.145324707031,48.8994522094727,0],[260.353546142578,48.9087524414062,0],[60.8306732177734,48.8652801513672,0],[262.728820800781,48.8859405517578,0],[261.937072753906,48.8919486999512,0],[60.8306732177734,48.8652801513672,0],[263.520599365234,48.8813209533691,0],[262.728820800781,48.8859405517578,0],[60.8306732177734,48.8652801513672,0],[261.145324707031,48.8994522094727,0],[60.8306732177734,48.8652801513672,0],[261.937072753906,48.8919486999512,0],[264.312347412109,48.8777503967285,0],[263.520599365234,48.8813209533691,0],[60.8306732177734,48.8652801513672,0],[272.229919433594,48.8660469055176,0],[271.438171386719,48.8663063049316,0],[60.8306732177734,48.8652801513672,0],[273.813446044922,48.8656997680664,0],[273.021667480469,48.865852355957,0],[60.8306732177734,48.8652801513672,0],[272.229919433594,48.8660469055176,0],[60.8306732177734,48.8652801513672,0],[273.021667480469,48.865852355957,0],[268.271148681641,48.8685302734375,0],[267.479370117188,48.8695373535156,0],[60.8306732177734,48.8652801513672,0],[269.854644775391,48.8671264648438,0],[269.062896728516,48.8677406311035,0],[60.8306732177734,48.8652801513672,0],[270.646392822266,48.8666534423828,0],[269.854644775391,48.8671264648438,0],[60.8306732177734,48.8652801513672,0],[268.271148681641,48.8685302734375,0],[60.8306732177734,48.8652801513672,0],[269.062896728516,48.8677406311035,0],[271.438171386719,48.8663063049316,0],[270.646392822266,48.8666534423828,0],[60.8306732177734,48.8652801513672,0],[266.687622070312,48.8708686828613,0],[60.8306732177734,48.8652801513672,0],[267.479370117188,48.8695373535156,0],[274.605194091797,48.8655853271484,0],[273.813446044922,48.8656997680664,0],[60.8306732177734,48.8652801513672,0],[259.561798095703,48.9201774597168,0],[60.8306732177734,48.8652801513672,0],[260.353546142578,48.9087524414062,0],[186.720108032227,139.912567138672,0],[102.793823242188,106.08073425293,0],[187.511871337891,139.361694335938,0],[189.09538269043,138.944610595703,0],[188.303634643555,139.045700073242,0],[222.349197387695,108.32820892334,0],[187.511871337891,139.361694335938,0],[224.724472045898,97.2489700317383,0],[188.303634643555,139.045700073242,0],[183.553085327148,144.041168212891,0],[182.761322021484,145.591033935547,0],[109.127883911133,135.258117675781,0],[107.544364929199,127.413642883301,0],[185.136596679688,141.589599609375,0],[184.344848632812,142.711959838867,0],[105.96085357666,119.949729919434,0],[185.928359985352,140.655776977539,0],[185.136596679688,141.589599609375,0],[183.553085327148,144.041168212891,0],[108.336120605469,131.276016235352,0],[184.344848632812,142.711959838867,0],[105.169090270996,116.343048095703,0],[186.720108032227,139.912567138672,0],[185.928359985352,140.655776977539,0],[190.678894042969,139.305938720703,0],[189.887145996094,139.032699584961,0],[219.182174682617,123.455596923828,0],[192.262420654297,140.418807983398,0],[191.470657348633,139.759078979492,0],[217.598648071289,130.704742431641,0],[190.678894042969,139.305938720703,0],[218.390411376953,127.126640319824,0],[191.470657348633,139.759078979492,0],[193.845932006836,142.228546142578,0],[193.054168701172,141.253082275391,0],[216.01513671875,137.499069213867,0],[195.429443359375,144.545364379883,0],[194.6376953125,143.331100463867,0],[215.223388671875,140.649337768555,0],[196.221206665039,145.867233276367,0],[195.429443359375,144.545364379883,0],[214.431625366211,143.576766967773,0],[193.845932006836,142.228546142578,0],[216.01513671875,137.499069213867,0],[194.6376953125,143.331100463867,0],[192.262420654297,140.418807983398,0],[216.806900024414,134.169052124023,0],[193.054168701172,141.253082275391,0],[189.09538269043,138.944610595703,0],[220.765686035156,115.917106628418,0],[189.887145996094,139.032699584961,0],[178.802536010742,156.040344238281,0],[178.010787963867,158.68782043457,0],[112.294914245605,152.346603393555,0],[180.386047363281,151.297561645508,0],[179.594299316406,153.564697265625,0],[111.503150939941,147.886474609375,0],[178.802536010742,156.040344238281,0],[112.294914245605,152.346603393555,0],[179.594299316406,153.564697265625,0],[174.84375,171.124069213867,0],[174.051986694336,174.738983154297,0],[115.461944580078,171.982757568359,0],[176.427261352539,164.50553894043,0],[175.635513305664,167.701385498047,0],[113.878425598145,161.809921264648,0],[177.219024658203,161.5087890625,0],[176.427261352539,164.50553894043,0],[113.878425598145,161.809921264648,0],[174.84375,171.124069213867,0],[114.670181274414,166.803436279297,0],[175.635513305664,167.701385498047,0],[178.010787963867,158.68782043457,0],[177.219024658203,161.5087890625,0],[113.086669921875,156.991333007812,0],[181.969573974609,147.318542480469,0],[181.177810668945,149.221374511719,0],[109.919639587402,139.351440429688,0],[212.848114013672,148.793151855469,0],[198.596481323242,150.116363525391,0],[197.804718017578,148.680023193359,0],[212.056350708008,151.053634643555,0],[200.179992675781,152.919815063477,0],[199.388229370117,151.542617797852,0],[200.971755981445,154.211547851562,0],[210.472839355469,154.69189453125,0],[201.76350402832,155.399795532227,0],[200.179992675781,152.919815063477,0],[211.264602661133,153.030502319336,0],[200.971755981445,154.211547851562,0],[212.848114013672,148.793151855469,0],[199.388229370117,151.542617797852,0],[198.596481323242,150.116363525391,0],[213.639862060547,146.296340942383,0],[197.804718017578,148.680023193359,0],[197.012954711914,147.256271362305,0],[180.386047363281,151.297561645508,0],[110.711395263672,143.557922363281,0],[181.177810668945,149.221374511719,0],[197.012954711914,147.256271362305,0],[196.221206665039,145.867233276367,0],[214.431625366211,143.576766967773,0],[182.761322021484,145.591033935547,0],[181.969573974609,147.318542480469,0],[109.919639587402,139.351440429688,0],[221.55744934082,112.118041992188,0],[220.765686035156,115.917106628418,0],[189.09538269043,138.944610595703,0],[222.349197387695,108.32820892334,0],[188.303634643555,139.045700073242,0],[223.140960693359,104.566413879395,0],[221.55744934082,112.118041992188,0],[189.09538269043,138.944610595703,0],[222.349197387695,108.32820892334,0],[217.598648071289,130.704742431641,0],[191.470657348633,139.759078979492,0],[218.390411376953,127.126640319824,0],[190.678894042969,139.305938720703,0],[219.182174682617,123.455596923828,0],[218.390411376953,127.126640319824,0],[219.182174682617,123.455596923828,0],[189.887145996094,139.032699584961,0],[219.973922729492,119.706001281738,0],[189.887145996094,139.032699584961,0],[220.765686035156,115.917106628418,0],[219.973922729492,119.706001281738,0],[216.806900024414,134.169052124023,0],[192.262420654297,140.418807983398,0],[217.598648071289,130.704742431641,0],[98.0432739257812,88.3509826660156,0],[227.891510009766,83.8458862304688,0],[227.099746704102,86.9987945556641,0],[96.4597625732422,83.4912719726562,0],[229.475021362305,78.0041122436523,0],[228.683258056641,80.8521347045898,0],[227.891510009766,83.8458862304688,0],[97.2515182495117,85.8434906005859,0],[228.683258056641,80.8521347045898,0],[223.932708740234,100.865119934082,0],[188.303634643555,139.045700073242,0],[224.724472045898,97.2489700317383,0],[187.511871337891,139.361694335938,0],[100.418548583984,96.6647567749023,0],[225.516235351562,93.7243804931641,0],[99.6267929077148,93.7697601318359,0],[226.307983398438,90.3038482666016,0],[225.516235351562,93.7243804931641,0],[187.511871337891,139.361694335938,0],[225.516235351562,93.7243804931641,0],[224.724472045898,97.2489700317383,0],[98.8350372314453,90.9958267211914,0],[227.099746704102,86.9987945556641,0],[226.307983398438,90.3038482666016,0],[188.303634643555,139.045700073242,0],[223.932708740234,100.865119934082,0],[223.140960693359,104.566413879395,0],[208.88932800293,157.203643798828,0],[203.347015380859,157.376327514648,0],[209.681076049805,156.083648681641,0],[203.347015380859,157.376327514648,0],[208.88932800293,157.203643798828,0],[204.138778686523,158.079879760742,0],[203.347015380859,157.376327514648,0],[202.555267333984,156.462036132812,0],[209.681076049805,156.083648681641,0],[204.138778686523,158.079879760742,0],[208.88932800293,157.203643798828,0],[208.097564697266,158.051528930664,0],[204.138778686523,158.079879760742,0],[208.097564697266,158.051528930664,0],[204.930541992188,158.554763793945,0],[205.722290039062,158.807876586914,0],[207.305801391602,158.594940185547,0],[206.514053344727,158.82536315918,0],[205.722290039062,158.807876586914,0],[204.930541992188,158.554763793945,0],[208.097564697266,158.051528930664,0],[207.305801391602,158.594940185547,0],[205.722290039062,158.807876586914,0],[208.097564697266,158.051528930664,0],[197.804718017578,148.680023193359,0],[213.639862060547,146.296340942383,0],[212.848114013672,148.793151855469,0],[214.431625366211,143.576766967773,0],[213.639862060547,146.296340942383,0],[197.012954711914,147.256271362305,0],[195.429443359375,144.545364379883,0],[215.223388671875,140.649337768555,0],[214.431625366211,143.576766967773,0],[212.848114013672,148.793151855469,0],[212.056350708008,151.053634643555,0],[199.388229370117,151.542617797852,0],[202.555267333984,156.462036132812,0],[201.76350402832,155.399795532227,0],[209.681076049805,156.083648681641,0],[209.681076049805,156.083648681641,0],[201.76350402832,155.399795532227,0],[210.472839355469,154.69189453125,0],[211.264602661133,153.030502319336,0],[210.472839355469,154.69189453125,0],[200.971755981445,154.211547851562,0],[211.264602661133,153.030502319336,0],[200.179992675781,152.919815063477,0],[212.056350708008,151.053634643555,0],[194.6376953125,143.331100463867,0],[216.01513671875,137.499069213867,0],[215.223388671875,140.649337768555,0],[216.806900024414,134.169052124023,0],[216.01513671875,137.499069213867,0],[193.054168701172,141.253082275391,0],[95.6680068969727,81.3425674438477,0],[230.26676940918,75.3057403564453,0],[229.475021362305,78.0041122436523,0],[231.058532714844,72.7599411010742,0],[230.26676940918,75.3057403564453,0],[94.8762435913086,79.3661270141602,0],[236.600830078125,59.556453704834,0],[90.9174575805664,72.5376892089844,0],[237.392593383789,58.2609024047852,0]],&#34;colors&#34;:[[0.301960796117783,0.686274528503418,0.290196090936661,1]],&#34;centers&#34;:[[72.70703125,77.7729415893555,0],[73.2348785400391,75.6637649536133,0],[73.7627105712891,73.6941146850586,0],[74.2905502319336,71.895881652832,0],[70.5956878662109,87.4275360107422,0],[71.6513671875,82.372444152832,0],[72.17919921875,80.0119781494141,0],[71.1235275268555,84.8519515991211,0],[70.0678405761719,90.0670394897461,0],[77.4575881958008,64.8616790771484,0],[78.5132598876953,63.9967498779297,0],[77.9854278564453,64.3425216674805,0],[74.8183898925781,70.2826843261719,0],[75.8740692138672,67.5648498535156,0],[76.4019012451172,66.4629287719727,0],[75.3462371826172,68.8390502929688,0],[76.9297485351562,65.5600738525391,0],[79.0410995483398,63.8225364685059,0],[64.2616271972656,153.988540649414,0],[64.7894592285156,152.156524658203,0],[63.7337875366211,155.613891601562,0],[61.6224327087402,159.489715576172,0],[62.1502685546875,158.910400390625,0],[62.6781120300293,158.071136474609,0],[63.2059440612793,156.979553222656,0],[65.3173065185547,150.139022827148,0],[67.9564971923828,100.885757446289,0],[68.4843368530273,98.1902618408203,0],[64.2616271972656,112.550476074219,0],[65.8451461791992,147.953643798828,0],[66.3729858398438,145.604156494141,0],[66.9008178710938,143.11750793457,0],[67.4286575317383,140.53889465332,0],[69.0121688842773,95.4698791503906,0],[69.5400085449219,92.7537231445312,0],[79.5689392089844,63.8400726318359,0],[140.006423950195,66.8073577880859,0],[80.0967712402344,64.049072265625,0],[139.74250793457,72.236930847168,0],[140.006439208984,76.5655899047852,0],[140.270355224609,78.6714782714844,0],[140.006439208984,73.9155883789062,0],[139.742492675781,68.5122451782227,0],[140.798187255859,83.3956298828125,0],[141.326019287109,88.7818756103516,0],[141.062103271484,86.0134506225586,0],[141.853866577148,94.7196273803711,0],[130.241409301758,113.968383789062,0],[130.769256591797,116.095169067383,0],[129.713577270508,111.908950805664,0],[141.589935302734,91.6898193359375,0],[140.534271240234,80.9459838867188,0],[131.561004638672,120.714889526367,0],[132.352783203125,125.649520874023,0],[132.088851928711,123.026306152344,0],[133.14453125,130.880828857422,0],[133.67236328125,136.858444213867,0],[133.936279296875,140.066864013672,0],[133.408447265625,133.800537109375,0],[132.61669921875,128.392852783203,0],[134.2001953125,147.580657958984,0],[134.464141845703,156.008590698242,0],[134.464126586914,151.265930175781,0],[134.728042602539,165.438262939453,0],[135.255889892578,174.693405151367,0],[154.52197265625,176.883056640625,0],[134.991973876953,169.970092773438,0],[134.728042602539,160.103363037109,0],[133.936279296875,144.043579101562,0],[131.033172607422,118.46736907959,0],[130.505340576172,58.3283004760742,0],[135.519805908203,186.231201171875,0],[136.047637939453,205.163421630859,0],[135.783721923828,199.121200561523,0],[136.575469970703,218.058624267578,0],[136.839401245117,234.083724975586,0],[137.103317260742,241.425018310547,0],[136.839401245117,224.882263183594,0],[136.311569213867,211.471115112305,0],[137.631149291992,256.746063232422,0],[138.158996582031,272.671203613281,0],[137.895080566406,264.648956298828,0],[138.950744628906,297.157806396484,0],[139.214660644531,315.947479248047,0],[138.950744628906,307.891815185547,0],[138.686828613281,288.969604492188,0],[138.422912597656,280.789367675781,0],[137.367233276367,248.991180419922,0],[140.270355224609,346.162445068359,0],[140.534271240234,352.966766357422,0],[140.006423950195,339.014739990234,0],[141.062103271484,365.28759765625,0],[141.589950561523,375.544799804688,0],[141.326019287109,370.682861328125,0],[140.798187255859,359.361541748047,0],[139.742523193359,331.570068359375,0],[142.381713867188,386.493347167969,0],[142.645629882812,388.774871826172,0],[142.117782592773,383.499755859375,0],[142.909530639648,390.379089355469,0],[143.173461914062,391.294189453125,0],[143.701293945312,390.930114746094,0],[143.965209960938,389.637542724609,0],[141.853866577148,379.837982177734,0],[139.478591918945,323.860412597656,0],[135.783721923828,191.732421875,0],[150.299285888672,245.778930664062,0],[151.354949951172,227.493957519531,0],[150.563201904297,238.637451171875,0],[148.979675292969,284.054351806641,0],[149.507522583008,268.349029541016,0],[149.771438598633,260.672149658203,0],[149.243591308594,276.151153564453,0],[150.035369873047,253.140365600586,0],[153.46630859375,189.009750366211,0],[135.255874633789,180.97509765625,0],[153.730224609375,184.127975463867,0],[151.882781982422,214.669235229492,0],[152.410629272461,202.8798828125,0],[152.674545288086,197.371978759766,0],[152.146713256836,208.632293701172,0],[153.202377319336,194.132659912109,0],[151.618865966797,220.96598815918,0],[145.548736572266,368.133850097656,0],[145.812652587891,362.541961669922,0],[145.284820556641,373.228820800781,0],[144.229141235352,387.667327880859,0],[144.493041992188,385.035736083984,0],[144.756973266602,381.731048583984,0],[145.020904541016,377.788909912109,0],[146.076568603516,356.471160888672,0],[147.660079956055,313.064147949219,0],[147.924011230469,305.15283203125,0],[147.39616394043,320.866149902344,0],[146.340484619141,349.9794921875,0],[146.604415893555,343.109100341797,0],[146.86833190918,335.937347412109,0],[147.132247924805,328.510559082031,0],[148.451843261719,299.982025146484,0],[148.715759277344,292.014862060547,0],[150.827117919922,231.727462768555,0],[153.994140625,179.49267578125,0],[139.74250793457,70.1877365112305,0],[187.247955322266,49.2994956970215,0],[188.303634643555,49.158519744873,0],[187.775802612305,49.2221984863281,0],[184.608764648438,49.9504776000977,0],[185.664459228516,49.6262168884277,0],[186.192291259766,49.5000267028809,0],[185.136596679688,49.7745018005371,0],[186.720123291016,49.3917846679688,0],[191.998504638672,48.9313163757324,0],[193.054183959961,48.9067039489746,0],[192.526336669922,48.9176635742188,0],[189.359313964844,49.0607681274414,0],[190.414978027344,48.9927825927734,0],[190.942840576172,48.9681091308594,0],[189.887145996094,49.0234184265137,0],[191.470672607422,48.9479598999023,0],[188.831466674805,49.1054382324219,0],[187.51188659668,65.6572799682617,0],[188.831481933594,62.6278991699219,0],[188.03971862793,64.658935546875,0],[185.664428710938,73.5760040283203,0],[186.456207275391,70.1176147460938,0],[186.720123291016,68.3457336425781,0],[186.192291259766,72.0597457885742,0],[187.247955322266,67.1373138427734,0],[182.497421264648,50.9744873046875,0],[183.553085327148,50.392692565918,0],[183.025253295898,50.6631927490234,0],[189.62321472168,60.9899215698242,0],[180.913909912109,52.2141380310059,0],[181.441741943359,51.748607635498,0],[190.151062011719,60.401668548584,0],[181.969573974609,51.3355522155762,0],[189.359298706055,61.881908416748,0],[184.080932617188,50.1561698913574,0],[206.250152587891,48.8653182983398,0],[207.305816650391,48.8652954101562,0],[206.777954101562,48.865306854248,0],[203.610946655273,48.8654594421387,0],[204.666625976562,48.8653793334961,0],[205.194458007812,48.865348815918,0],[204.138778686523,48.8654136657715,0],[205.722290039062,48.8653335571289,0],[212.056365966797,48.8652801513672,0],[289.648620605469,48.8652801513672,0],[213.375946044922,48.8652801513672,0],[208.36149597168,48.865291595459,0],[209.681076049805,48.8652877807617,0],[210.472839355469,48.8652801513672,0],[208.88932800293,48.8652877807617,0],[211.000701904297,48.8652801513672,0],[207.833648681641,48.8652954101562,0],[196.749053955078,48.8726463317871,0],[197.804733276367,48.8695983886719,0],[197.276885986328,48.8709411621094,0],[194.10986328125,48.8911666870117,0],[195.16552734375,48.8810577392578,0],[195.693359375,48.877513885498,0],[194.6376953125,48.8855590820312,0],[196.221221923828,48.8747863769531,0],[201.499603271484,48.8658752441406,0],[202.555267333984,48.8656120300293,0],[202.027435302734,48.86572265625,0],[198.860397338867,48.8677825927734,0],[199.916076660156,48.8667144775391,0],[200.443908691406,48.8663558959961,0],[199.388229370117,48.8671836853027,0],[200.971771240234,48.866081237793,0],[198.332565307617,48.8685607910156,0],[203.083114624023,48.8655204772949,0],[193.582000732422,48.8980712890625,0],[159.008605957031,128.45166015625,0],[199.916076660156,128.772842407227,0],[200.179992675781,125.218795776367,0],[158.480758666992,141.630111694336,0],[159.008605957031,137.238403320312,0],[159.008605957031,134.065032958984,0],[158.744689941406,139.343063354492,0],[159.272521972656,132.303802490234,0],[199.916076660156,133.931411743164,0],[200.443908691406,136.960876464844,0],[200.179992675781,135.397216796875,0],[200.971740722656,140.326904296875,0],[201.763519287109,142.841949462891,0],[202.027435302734,144.663131713867,0],[201.499603271484,141.019577026367,0],[200.707855224609,138.613647460938,0],[199.916076660156,131.298141479492,0],[156.369415283203,155.691589355469,0],[157.161163330078,150.916244506836,0],[156.897247314453,153.98388671875,0],[154.785903930664,172.615280151367,0],[155.313735961914,164.672286987305,0],[155.841583251953,162.608093261719,0],[155.0498046875,168.54296875,0],[156.105499267578,159.062652587891,0],[157.689025878906,145.297119140625,0],[203.083099365234,149.196517944336,0],[203.874862670898,151.838684082031,0],[204.402694702148,154.76774597168,0],[204.138778686523,153.387298583984,0],[203.610946655273,150.15071105957,0],[202.819183349609,147.410888671875,0],[157.425094604492,148.025619506836,0],[202.555267333984,145.566757202148,0],[158.216857910156,144.087005615234,0],[210.472839355469,122.326591491699,0],[211.264617919922,117.313438415527,0],[211.000671386719,119.79695892334,0],[209.153244018555,132.530151367188,0],[209.41716003418,129.962738037109,0],[209.681091308594,127.398094177246,0],[210.208923339844,124.885269165039,0],[208.88932800293,135.097534179688,0],[184.344848632812,86.3985595703125,0],[184.872680664062,80.7825164794922,0],[184.608764648438,83.5138397216797,0],[212.320281982422,112.386596679688,0],[171.148895263672,109.916954040527,0],[183.817016601562,92.5993270874023,0],[212.584197998047,110.111686706543,0],[184.080932617188,89.4328231811523,0],[211.792449951172,114.825744628906,0],[207.305816650391,156.887878417969,0],[205.458374023438,157.553283691406,0],[205.194458007812,156.640686035156,0],[207.041900634766,157.778350830078,0],[205.722290039062,158.228729248047,0],[206.514038085938,158.742736816406,0],[206.250122070312,158.471405029297,0],[207.041870117188,158.484786987305,0],[208.097579956055,147.923187255859,0],[208.361480712891,145.709808349609,0],[208.36149597168,142.923828125,0],[208.097579956055,150.463134765625,0],[204.666625976562,155.981826782227,0],[207.305816650391,155.391784667969,0],[207.569732666016,153.977996826172,0],[207.833648681641,152.334655761719,0],[208.625411987305,140.4931640625,0],[208.625411987305,137.640411376953,0],[185.136596679688,78.2174835205078,0],[185.400512695312,75.8106002807617,0],[188.303634643555,63.4516830444336,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;194&#34;:{&#34;id&#34;:194,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:0,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-2.90000009536743,-2.90000009536743]},&#34;vertices&#34;:[[60.8306732177734,159.882751464844,0],[61.6224327087402,159.628890991211,0],[62.4141883850098,158.957458496094,0],[63.2059478759766,157.890960693359,0],[63.9977035522461,156.439666748047,0],[64.7894592285156,154.616241455078,0],[65.5812225341797,152.342651367188,0],[66.3729782104492,149.740203857422,0],[67.1647338867188,146.846633911133,0],[67.9564895629883,143.687698364258,0],[68.7482528686523,140.290451049805,0],[69.5400085449219,136.639221191406,0],[70.3317642211914,132.830535888672,0],[71.1235198974609,128.903381347656,0],[71.9152755737305,124.88858795166,0],[72.7070388793945,120.816917419434,0],[73.4987945556641,116.727432250977,0],[74.2905502319336,112.668449401855,0],[75.0823059082031,108.667381286621,0],[75.8740692138672,104.749923706055,0],[76.6658248901367,100.940643310547,0],[77.4575805664062,97.3114013671875,0],[78.2493362426758,93.859245300293,0],[79.0410995483398,90.5942916870117,0],[79.8328552246094,87.5317230224609,0],[80.6246109008789,84.6853332519531,0],[81.4163665771484,82.1370239257812,0],[82.2081298828125,79.8457336425781,0],[82.999885559082,77.8061370849609,0],[83.7916412353516,76.0231094360352,0],[84.5833969116211,74.5003814697266,0],[85.3751525878906,73.3145599365234,0],[86.1669158935547,72.4051818847656,0],[86.9586715698242,71.7570877075195,0],[87.7504272460938,71.3678741455078,0],[88.5421829223633,71.2344512939453,0],[89.3339462280273,71.4204864501953,0],[90.1257019042969,71.861457824707,0],[90.9174575805664,72.5376892089844,0],[91.7092132568359,73.4425811767578,0],[92.5009765625,74.5691299438477,0],[93.2927322387695,75.9648971557617,0],[94.0844879150391,77.5706939697266,0],[94.8762435913086,79.3661270141602,0],[95.6680068969727,81.3425674438477,0],[96.4597625732422,83.4912719726562,0],[97.2515182495117,85.8434906005859,0],[98.0432739257812,88.3509826660156,0],[98.8350372314453,90.9958267211914,0],[99.6267929077148,93.7697601318359,0],[100.418548583984,96.6647567749023,0],[101.210304260254,99.7003784179688,0],[102.002059936523,102.843063354492,0],[102.793823242188,106.08073425293,0],[103.585578918457,109.408782958984,0],[104.377334594727,112.823310852051,0],[105.169090270996,116.343048095703,0],[105.96085357666,119.949729919434,0],[106.75260925293,123.639228820801,0],[107.544364929199,127.413642883301,0],[108.336120605469,131.276016235352,0],[109.127883911133,135.258117675781,0],[109.919639587402,139.351440429688,0],[110.711395263672,143.557922363281,0],[111.503150939941,147.886474609375,0],[112.294914245605,152.346603393555,0],[113.086669921875,156.991333007812,0],[113.878425598145,161.809921264648,0],[114.670181274414,166.803436279297,0],[115.461936950684,171.982757568359,0],[116.253700256348,177.358489990234,0],[117.045455932617,182.998962402344,0],[117.837211608887,188.877578735352,0],[118.628967285156,194.985107421875,0],[119.42073059082,201.325942993164,0],[120.21248626709,207.903076171875,0],[121.004241943359,214.777709960938,0],[121.795997619629,221.900665283203,0],[122.587760925293,229.246337890625,0],[123.379516601562,236.804550170898,0],[124.171272277832,244.562911987305,0],[124.963027954102,252.544296264648,0],[125.754791259766,260.683380126953,0],[126.546546936035,268.940887451172,0],[127.338302612305,277.2890625,0],[128.130065917969,285.6982421875,0],[128.921813964844,294.126617431641,0],[129.713577270508,302.512786865234,0],[130.505325317383,310.816192626953,0],[131.297088623047,318.996490478516,0],[132.088851928711,327.012573242188,0],[132.880599975586,334.750671386719,0],[133.67236328125,342.179229736328,0],[134.464126586914,349.274505615234,0],[135.255874633789,355.995391845703,0],[136.047637939453,362.301544189453,0],[136.839385986328,368.024536132812,0],[137.631149291992,373.183837890625,0],[138.422912597656,377.788269042969,0],[139.214660644531,381.809631347656,0],[140.006423950195,385.222137451172,0],[140.798187255859,387.84033203125,0],[141.589935302734,389.740173339844,0],[142.381698608398,390.968658447266,0],[143.173446655273,391.520446777344,0],[143.965209960938,391.393402099609,0],[144.756973266602,390.428283691406,0],[145.548721313477,388.744079589844,0],[146.340484619141,386.41748046875,0],[147.132232666016,383.467529296875,0],[147.92399597168,379.916015625,0],[148.715759277344,375.662322998047,0],[149.507507324219,370.840270996094,0],[150.299270629883,365.536712646484,0],[151.091033935547,359.787628173828,0],[151.882781982422,353.630401611328,0],[152.674545288086,347.033630371094,0],[153.466293334961,340.114349365234,0],[154.258056640625,332.946990966797,0],[155.049819946289,325.572082519531,0],[155.841567993164,318.029815673828,0],[156.633331298828,310.346435546875,0],[157.425079345703,302.599212646484,0],[158.216842651367,294.833984375,0],[159.008605957031,287.083953857422,0],[159.800354003906,279.380798339844,0],[160.59211730957,271.783569335938,0],[161.383880615234,264.322570800781,0],[162.175628662109,257.010437011719,0],[162.967391967773,249.866317749023,0],[163.759140014648,242.907562255859,0],[164.550903320312,236.200271606445,0],[165.342666625977,229.735763549805,0],[166.134414672852,223.499771118164,0],[166.926177978516,217.497482299805,0],[167.71794128418,211.732528686523,0],[168.509689331055,206.261199951172,0],[169.301452636719,201.052536010742,0],[170.093200683594,196.078277587891,0],[170.884963989258,191.334594726562,0],[171.676727294922,186.81706237793,0],[172.468475341797,182.567886352539,0],[173.260238647461,178.551681518555,0],[174.051986694336,174.738983154297,0],[174.84375,171.124069213867,0],[175.635513305664,167.701385498047,0],[176.427261352539,164.50553894043,0],[177.219024658203,161.5087890625,0],[178.010787963867,158.68782043457,0],[178.802536010742,156.040344238281,0],[179.594299316406,153.564697265625,0],[180.386047363281,151.297561645508,0],[181.177810668945,149.221374511719,0],[181.969573974609,147.318542480469,0],[182.761322021484,145.591033935547,0],[183.553085327148,144.041168212891,0],[184.344848632812,142.711959838867,0],[185.136596679688,141.589599609375,0],[185.928359985352,140.655776977539,0],[186.720108032227,139.912567138672,0],[187.511871337891,139.361694335938,0],[188.303634643555,139.045700073242,0],[189.09538269043,138.944595336914,0],[189.887145996094,139.032699584961,0],[190.678894042969,139.305938720703,0],[191.470657348633,139.759078979492,0],[192.262420654297,140.418807983398,0],[193.054168701172,141.253082275391,0],[193.845932006836,142.228546142578,0],[194.6376953125,143.331100463867,0],[195.429443359375,144.545364379883,0],[196.221206665039,145.867233276367,0],[197.012954711914,147.256271362305,0],[197.804718017578,148.680023193359,0],[198.596481323242,150.116363525391,0],[199.388229370117,151.542617797852,0],[200.179992675781,152.919815063477,0],[200.971740722656,154.211547851562,0],[201.76350402832,155.399795532227,0],[202.555267333984,156.462036132812,0],[203.347015380859,157.376327514648,0],[204.138778686523,158.079879760742,0],[204.930541992188,158.554763793945,0],[205.722290039062,158.807876586914,0],[206.514053344727,158.82536315918,0],[207.305801391602,158.594940185547,0],[208.097564697266,158.051528930664,0],[208.88932800293,157.203643798828,0],[209.681076049805,156.083648681641,0],[210.472839355469,154.691879272461,0],[211.264602661133,153.030502319336,0],[212.056350708008,151.053634643555,0],[212.848114013672,148.793151855469,0],[213.639862060547,146.296340942383,0],[214.431625366211,143.576766967773,0],[215.223388671875,140.649337768555,0],[216.01513671875,137.499069213867,0],[216.806900024414,134.169052124023,0],[217.598648071289,130.704742431641,0],[218.390411376953,127.126640319824,0],[219.182174682617,123.455596923828,0],[219.973922729492,119.706001281738,0],[220.765686035156,115.917106628418,0],[221.55744934082,112.118034362793,0],[222.349197387695,108.32820892334,0],[223.140960693359,104.566413879395,0],[223.932708740234,100.865119934082,0],[224.724472045898,97.2489700317383,0],[225.516235351562,93.7243804931641,0],[226.307983398438,90.3038482666016,0],[227.099746704102,86.9987945556641,0],[227.891510009766,83.8458862304688,0],[228.683258056641,80.8521347045898,0],[229.475021362305,78.0041122436523,0],[230.26676940918,75.3057403564453,0],[231.058532714844,72.7599411010742,0],[231.850296020508,70.3973617553711,0],[232.642044067383,68.211181640625,0],[233.433807373047,66.1767501831055,0],[234.225555419922,64.2912979125977,0],[235.017318725586,62.5514831542969,0],[235.80908203125,60.9777717590332,0],[236.600830078125,59.556453704834,0],[237.392593383789,58.2609024047852,0],[238.184356689453,57.0851135253906,0],[238.976104736328,56.0229187011719,0],[239.767868041992,55.0853805541992,0],[240.559616088867,54.2581596374512,0],[241.351379394531,53.518970489502,0],[242.143142700195,52.8615646362305,0],[242.93489074707,52.2798080444336,0],[243.726654052734,51.7783813476562,0],[244.518402099609,51.3459167480469,0],[245.310165405273,50.9668617248535,0],[246.101928710938,50.6363639831543,0],[246.893676757812,50.3497734069824,0],[247.685440063477,50.1084480285645,0],[248.477203369141,49.9049186706543,0],[249.268951416016,49.7298736572266,0],[250.06071472168,49.5802001953125,0],[250.852462768555,49.4529991149902,0],[251.644226074219,49.348316192627,0],[252.435989379883,49.2619667053223,0],[253.227737426758,49.1890754699707,0],[254.019500732422,49.1279411315918,0],[254.811264038086,49.0770149230957,0],[255.603012084961,49.0360488891602,0],[256.394775390625,49.0029945373535,0],[257.1865234375,48.9755973815918,0],[257.978302001953,48.9530601501465,0],[258.770050048828,48.9346542358398,0],[259.561798095703,48.9201774597168,0],[260.353546142578,48.9087524414062,0],[261.145324707031,48.8994522094727,0],[261.937072753906,48.8919486999512,0],[262.728820800781,48.8859405517578,0],[263.520599365234,48.8813209533691,0],[264.312347412109,48.8777503967285,0],[265.104095458984,48.8749008178711,0],[265.895874023438,48.8726425170898,0],[266.687622070312,48.8708686828613,0],[267.479370117188,48.8695373535156,0],[268.271148681641,48.8685302734375,0],[269.062896728516,48.8677406311035,0],[269.854644775391,48.8671264648438,0],[270.646392822266,48.8666534423828,0],[271.438171386719,48.8663063049316,0],[272.229919433594,48.8660469055176,0],[273.021667480469,48.865852355957,0],[273.813446044922,48.8656997680664,0],[274.605194091797,48.8655853271484,0],[275.396942138672,48.8655052185059,0],[276.188720703125,48.8654441833496,0],[276.98046875,48.8653984069824,0],[277.772216796875,48.8653678894043,0],[278.563995361328,48.8653411865234,0],[279.355743408203,48.8653221130371,0],[280.147491455078,48.8653106689453,0],[280.939239501953,48.8653030395508,0],[281.731018066406,48.8652954101562,0],[282.522766113281,48.865291595459,0],[283.314514160156,48.8652877807617,0],[284.106292724609,48.8652839660645,0],[284.898040771484,48.8652839660645,0],[285.689788818359,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[339.529296875,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[60.8306732177734,159.882751464844,0],[61.6224327087402,159.628890991211,0],[62.4141883850098,158.957458496094,0],[63.2059478759766,157.890960693359,0],[63.9977035522461,156.439666748047,0],[64.7894592285156,154.616241455078,0],[65.5812225341797,152.342651367188,0],[66.3729782104492,149.740203857422,0],[67.1647338867188,146.846633911133,0],[67.9564895629883,143.687698364258,0],[68.7482528686523,140.290451049805,0],[69.5400085449219,136.639221191406,0],[70.3317642211914,132.830535888672,0],[71.1235198974609,128.903381347656,0],[71.9152755737305,124.88858795166,0],[72.7070388793945,120.816917419434,0],[73.4987945556641,116.727432250977,0],[74.2905502319336,112.668449401855,0],[75.0823059082031,108.667381286621,0],[75.8740692138672,104.749923706055,0],[76.6658248901367,100.940643310547,0],[77.4575805664062,97.3114013671875,0],[78.2493362426758,93.859245300293,0],[79.0410995483398,90.5942916870117,0],[79.8328552246094,87.5317230224609,0],[80.6246109008789,84.6853332519531,0],[81.4163665771484,82.1370239257812,0],[82.2081298828125,79.8457336425781,0],[82.999885559082,77.8061370849609,0],[83.7916412353516,76.0231094360352,0],[84.5833969116211,74.5003814697266,0],[85.3751525878906,73.3145599365234,0],[86.1669158935547,72.4051818847656,0],[86.9586715698242,71.7570877075195,0],[87.7504272460938,71.3678741455078,0],[88.5421829223633,71.2344512939453,0],[89.3339462280273,71.4204864501953,0],[90.1257019042969,71.861457824707,0],[90.9174575805664,72.5376892089844,0],[91.7092132568359,73.4425811767578,0],[92.5009765625,74.5691299438477,0],[93.2927322387695,75.9648971557617,0],[94.0844879150391,77.5706939697266,0],[94.8762435913086,79.3661270141602,0],[95.6680068969727,81.3425674438477,0],[96.4597625732422,83.4912719726562,0],[97.2515182495117,85.8434906005859,0],[98.0432739257812,88.3509826660156,0],[98.8350372314453,90.9958267211914,0],[99.6267929077148,93.7697601318359,0],[100.418548583984,96.6647567749023,0],[101.210304260254,99.7003784179688,0],[102.002059936523,102.843063354492,0],[102.793823242188,106.08073425293,0],[103.585578918457,109.408782958984,0],[104.377334594727,112.823310852051,0],[105.169090270996,116.343048095703,0],[105.96085357666,119.949729919434,0],[106.75260925293,123.639228820801,0],[107.544364929199,127.413642883301,0],[108.336120605469,131.276016235352,0],[109.127883911133,135.258117675781,0],[109.919639587402,139.351440429688,0],[110.711395263672,143.557922363281,0],[111.503150939941,147.886474609375,0],[112.294914245605,152.346603393555,0],[113.086669921875,156.991333007812,0],[113.878425598145,161.809921264648,0],[114.670181274414,166.803436279297,0],[115.461936950684,171.982757568359,0],[116.253700256348,177.358489990234,0],[117.045455932617,182.998962402344,0],[117.837211608887,188.877578735352,0],[118.628967285156,194.985107421875,0],[119.42073059082,201.325942993164,0],[120.21248626709,207.903076171875,0],[121.004241943359,214.777709960938,0],[121.795997619629,221.900665283203,0],[122.587760925293,229.246337890625,0],[123.379516601562,236.804550170898,0],[124.171272277832,244.562911987305,0],[124.963027954102,252.544296264648,0],[125.754791259766,260.683380126953,0],[126.546546936035,268.940887451172,0],[127.338302612305,277.2890625,0],[128.130065917969,285.6982421875,0],[128.921813964844,294.126617431641,0],[129.713577270508,302.512786865234,0],[130.505325317383,310.816192626953,0],[131.297088623047,318.996490478516,0],[132.088851928711,327.012573242188,0],[132.880599975586,334.750671386719,0],[133.67236328125,342.179229736328,0],[134.464126586914,349.274505615234,0],[135.255874633789,355.995391845703,0],[136.047637939453,362.301544189453,0],[136.839385986328,368.024536132812,0],[137.631149291992,373.183837890625,0],[138.422912597656,377.788269042969,0],[139.214660644531,381.809631347656,0],[140.006423950195,385.222137451172,0],[140.798187255859,387.84033203125,0],[141.589935302734,389.740173339844,0],[142.381698608398,390.968658447266,0],[143.173446655273,391.520446777344,0],[143.965209960938,391.393402099609,0],[144.756973266602,390.428283691406,0],[145.548721313477,388.744079589844,0],[146.340484619141,386.41748046875,0],[147.132232666016,383.467529296875,0],[147.92399597168,379.916015625,0],[148.715759277344,375.662322998047,0],[149.507507324219,370.840270996094,0],[150.299270629883,365.536712646484,0],[151.091033935547,359.787628173828,0],[151.882781982422,353.630401611328,0],[152.674545288086,347.033630371094,0],[153.466293334961,340.114349365234,0],[154.258056640625,332.946990966797,0],[155.049819946289,325.572082519531,0],[155.841567993164,318.029815673828,0],[156.633331298828,310.346435546875,0],[157.425079345703,302.599212646484,0],[158.216842651367,294.833984375,0],[159.008605957031,287.083953857422,0],[159.800354003906,279.380798339844,0],[160.59211730957,271.783569335938,0],[161.383880615234,264.322570800781,0],[162.175628662109,257.010437011719,0],[162.967391967773,249.866317749023,0],[163.759140014648,242.907562255859,0],[164.550903320312,236.200271606445,0],[165.342666625977,229.735763549805,0],[166.134414672852,223.499771118164,0],[166.926177978516,217.497482299805,0],[167.71794128418,211.732528686523,0],[168.509689331055,206.261199951172,0],[169.301452636719,201.052536010742,0],[170.093200683594,196.078277587891,0],[170.884963989258,191.334594726562,0],[171.676727294922,186.81706237793,0],[172.468475341797,182.567886352539,0],[173.260238647461,178.551681518555,0],[174.051986694336,174.738983154297,0],[174.84375,171.124069213867,0],[175.635513305664,167.701385498047,0],[176.427261352539,164.50553894043,0],[177.219024658203,161.5087890625,0],[178.010787963867,158.68782043457,0],[178.802536010742,156.040344238281,0],[179.594299316406,153.564697265625,0],[180.386047363281,151.297561645508,0],[181.177810668945,149.221374511719,0],[181.969573974609,147.318542480469,0],[182.761322021484,145.591033935547,0],[183.553085327148,144.041168212891,0],[184.344848632812,142.711959838867,0],[185.136596679688,141.589599609375,0],[185.928359985352,140.655776977539,0],[186.720108032227,139.912567138672,0],[187.511871337891,139.361694335938,0],[188.303634643555,139.045700073242,0],[189.09538269043,138.944595336914,0],[189.887145996094,139.032699584961,0],[190.678894042969,139.305938720703,0],[191.470657348633,139.759078979492,0],[192.262420654297,140.418807983398,0],[193.054168701172,141.253082275391,0],[193.845932006836,142.228546142578,0],[194.6376953125,143.331100463867,0],[195.429443359375,144.545364379883,0],[196.221206665039,145.867233276367,0],[197.012954711914,147.256271362305,0],[197.804718017578,148.680023193359,0],[198.596481323242,150.116363525391,0],[199.388229370117,151.542617797852,0],[200.179992675781,152.919815063477,0],[200.971740722656,154.211547851562,0],[201.76350402832,155.399795532227,0],[202.555267333984,156.462036132812,0],[203.347015380859,157.376327514648,0],[204.138778686523,158.079879760742,0],[204.930541992188,158.554763793945,0],[205.722290039062,158.807876586914,0],[206.514053344727,158.82536315918,0],[207.305801391602,158.594940185547,0],[208.097564697266,158.051528930664,0],[208.88932800293,157.203643798828,0],[209.681076049805,156.083648681641,0],[210.472839355469,154.691879272461,0],[211.264602661133,153.030502319336,0],[212.056350708008,151.053634643555,0],[212.848114013672,148.793151855469,0],[213.639862060547,146.296340942383,0],[214.431625366211,143.576766967773,0],[215.223388671875,140.649337768555,0],[216.01513671875,137.499069213867,0],[216.806900024414,134.169052124023,0],[217.598648071289,130.704742431641,0],[218.390411376953,127.126640319824,0],[219.182174682617,123.455596923828,0],[219.973922729492,119.706001281738,0],[220.765686035156,115.917106628418,0],[221.55744934082,112.118034362793,0],[222.349197387695,108.32820892334,0],[223.140960693359,104.566413879395,0],[223.932708740234,100.865119934082,0],[224.724472045898,97.2489700317383,0],[225.516235351562,93.7243804931641,0],[226.307983398438,90.3038482666016,0],[227.099746704102,86.9987945556641,0],[227.891510009766,83.8458862304688,0],[228.683258056641,80.8521347045898,0],[229.475021362305,78.0041122436523,0],[230.26676940918,75.3057403564453,0],[231.058532714844,72.7599411010742,0],[231.850296020508,70.3973617553711,0],[232.642044067383,68.211181640625,0],[233.433807373047,66.1767501831055,0],[234.225555419922,64.2912979125977,0],[235.017318725586,62.5514831542969,0],[235.80908203125,60.9777717590332,0],[236.600830078125,59.556453704834,0],[237.392593383789,58.2609024047852,0],[238.184356689453,57.0851135253906,0],[238.976104736328,56.0229187011719,0],[239.767868041992,55.0853805541992,0],[240.559616088867,54.2581596374512,0],[241.351379394531,53.518970489502,0],[242.143142700195,52.8615646362305,0],[242.93489074707,52.2798080444336,0],[243.726654052734,51.7783813476562,0],[244.518402099609,51.3459167480469,0],[245.310165405273,50.9668617248535,0],[246.101928710938,50.6363639831543,0],[246.893676757812,50.3497734069824,0],[247.685440063477,50.1084480285645,0],[248.477203369141,49.9049186706543,0],[249.268951416016,49.7298736572266,0],[250.06071472168,49.5802001953125,0],[250.852462768555,49.4529991149902,0],[251.644226074219,49.348316192627,0],[252.435989379883,49.2619667053223,0],[253.227737426758,49.1890754699707,0],[254.019500732422,49.1279411315918,0],[254.811264038086,49.0770149230957,0],[255.603012084961,49.0360488891602,0],[256.394775390625,49.0029945373535,0],[257.1865234375,48.9755973815918,0],[257.978302001953,48.9530601501465,0],[258.770050048828,48.9346542358398,0],[259.561798095703,48.9201774597168,0],[260.353546142578,48.9087524414062,0],[261.145324707031,48.8994522094727,0],[261.937072753906,48.8919486999512,0],[262.728820800781,48.8859405517578,0],[263.520599365234,48.8813209533691,0],[264.312347412109,48.8777503967285,0],[265.104095458984,48.8749008178711,0],[265.895874023438,48.8726425170898,0],[266.687622070312,48.8708686828613,0],[267.479370117188,48.8695373535156,0],[268.271148681641,48.8685302734375,0],[269.062896728516,48.8677406311035,0],[269.854644775391,48.8671264648438,0],[270.646392822266,48.8666534423828,0],[271.438171386719,48.8663063049316,0],[272.229919433594,48.8660469055176,0],[273.021667480469,48.865852355957,0],[273.813446044922,48.8656997680664,0],[274.605194091797,48.8655853271484,0],[275.396942138672,48.8655052185059,0],[276.188720703125,48.8654441833496,0],[276.98046875,48.8653984069824,0],[277.772216796875,48.8653678894043,0],[278.563995361328,48.8653411865234,0],[279.355743408203,48.8653221130371,0],[280.147491455078,48.8653106689453,0],[280.939239501953,48.8653030395508,0],[281.731018066406,48.8652954101562,0],[282.522766113281,48.865291595459,0],[283.314514160156,48.8652877807617,0],[284.106292724609,48.8652839660645,0],[284.898040771484,48.8652839660645,0],[285.689788818359,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[339.529296875,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[465.418731689453,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[441.666015625,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[379.1171875,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[339.529296875,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[285.689788818359,48.8652801513672,0],[284.898040771484,48.8652801513672,0],[284.106292724609,48.8652801513672,0],[283.314514160156,48.8652801513672,0],[282.522766113281,48.8652801513672,0],[281.731018066406,48.8652801513672,0],[280.939239501953,48.8652801513672,0],[280.147491455078,48.8652801513672,0],[279.355743408203,48.8652801513672,0],[278.563995361328,48.8652801513672,0],[277.772216796875,48.8652801513672,0],[276.98046875,48.8652801513672,0],[276.188720703125,48.8652801513672,0],[275.396942138672,48.8652801513672,0],[274.605194091797,48.8652801513672,0],[273.813446044922,48.8652801513672,0],[273.021667480469,48.8652801513672,0],[272.229919433594,48.8652801513672,0],[271.438171386719,48.8652801513672,0],[270.646392822266,48.8652801513672,0],[269.854644775391,48.8652801513672,0],[269.062896728516,48.8652801513672,0],[268.271148681641,48.8652801513672,0],[267.479370117188,48.8652801513672,0],[266.687622070312,48.8652801513672,0],[265.895874023438,48.8652801513672,0],[265.104095458984,48.8652801513672,0],[264.312347412109,48.8652801513672,0],[263.520599365234,48.8652801513672,0],[262.728820800781,48.8652801513672,0],[261.937072753906,48.8652801513672,0],[261.145324707031,48.8652801513672,0],[260.353546142578,48.8652801513672,0],[259.561798095703,48.8652801513672,0],[258.770050048828,48.8652801513672,0],[257.978302001953,48.8652801513672,0],[257.1865234375,48.8652801513672,0],[256.394775390625,48.8652801513672,0],[255.603012084961,48.8652801513672,0],[254.811264038086,48.8652801513672,0],[254.019500732422,48.8652801513672,0],[253.227737426758,48.8652801513672,0],[252.435989379883,48.8652801513672,0],[251.644226074219,48.8652801513672,0],[250.852462768555,48.8652801513672,0],[250.06071472168,48.8652801513672,0],[249.268951416016,48.8652801513672,0],[248.477203369141,48.8652801513672,0],[247.685440063477,48.8652801513672,0],[246.893676757812,48.8652801513672,0],[246.101928710938,48.8652801513672,0],[245.310165405273,48.8652801513672,0],[244.518402099609,48.8652801513672,0],[243.726654052734,48.8652801513672,0],[242.93489074707,48.8652801513672,0],[242.143142700195,48.8652801513672,0],[241.351379394531,48.8652801513672,0],[240.559616088867,48.8652801513672,0],[239.767868041992,48.8652801513672,0],[238.976104736328,48.8652801513672,0],[238.184356689453,48.8652801513672,0],[237.392593383789,48.8652801513672,0],[236.600830078125,48.8652801513672,0],[235.80908203125,48.8652801513672,0],[235.017318725586,48.8652801513672,0],[234.225555419922,48.8652801513672,0],[233.433807373047,48.8652801513672,0],[232.642044067383,48.8652801513672,0],[231.850296020508,48.8652801513672,0],[231.058532714844,48.8652801513672,0],[230.26676940918,48.8652801513672,0],[229.475021362305,48.8652801513672,0],[228.683258056641,48.8652801513672,0],[227.891510009766,48.8652801513672,0],[227.099746704102,48.8652801513672,0],[226.307983398438,48.8652801513672,0],[225.516235351562,48.8652801513672,0],[224.724472045898,48.8652801513672,0],[223.932708740234,48.8652801513672,0],[223.140960693359,48.8652801513672,0],[222.349197387695,48.8652801513672,0],[221.55744934082,48.8652801513672,0],[220.765686035156,48.8652801513672,0],[219.973922729492,48.8652801513672,0],[219.182174682617,48.8652801513672,0],[218.390411376953,48.8652801513672,0],[217.598648071289,48.8652801513672,0],[216.806900024414,48.8652801513672,0],[216.01513671875,48.8652801513672,0],[215.223388671875,48.8652801513672,0],[214.431625366211,48.8652801513672,0],[213.639862060547,48.8652801513672,0],[212.848114013672,48.8652801513672,0],[212.056350708008,48.8652801513672,0],[211.264602661133,48.8652801513672,0],[210.472839355469,48.8652801513672,0],[209.681076049805,48.8652801513672,0],[208.88932800293,48.8652801513672,0],[208.097564697266,48.8652801513672,0],[207.305801391602,48.8652801513672,0],[206.514053344727,48.8652801513672,0],[205.722290039062,48.8652801513672,0],[204.930541992188,48.8652801513672,0],[204.138778686523,48.8652801513672,0],[203.347015380859,48.8652801513672,0],[202.555267333984,48.8652801513672,0],[201.76350402832,48.8652801513672,0],[200.971740722656,48.8652801513672,0],[200.179992675781,48.8652801513672,0],[199.388229370117,48.8652801513672,0],[198.596481323242,48.8652801513672,0],[197.804718017578,48.8652801513672,0],[197.012954711914,48.8652801513672,0],[196.221206665039,48.8652801513672,0],[195.429443359375,48.8652801513672,0],[194.6376953125,48.8652801513672,0],[193.845932006836,48.8652801513672,0],[193.054168701172,48.8652801513672,0],[192.262420654297,48.8652801513672,0],[191.470657348633,48.8652801513672,0],[190.678894042969,48.8652801513672,0],[189.887145996094,48.8652801513672,0],[189.09538269043,48.8652801513672,0],[188.303634643555,48.8652801513672,0],[187.511871337891,48.8652801513672,0],[186.720108032227,48.8652801513672,0],[185.928359985352,48.8652801513672,0],[185.136596679688,48.8652801513672,0],[184.344848632812,48.8652801513672,0],[183.553085327148,48.8652801513672,0],[182.761322021484,48.8652801513672,0],[181.969573974609,48.8652801513672,0],[181.177810668945,48.8652801513672,0],[180.386047363281,48.8652801513672,0],[179.594299316406,48.8652801513672,0],[178.802536010742,48.8652801513672,0],[178.010787963867,48.8652801513672,0],[177.219024658203,48.8652801513672,0],[176.427261352539,48.8652801513672,0],[175.635513305664,48.8652801513672,0],[174.84375,48.8652801513672,0],[174.051986694336,48.8652801513672,0],[173.260238647461,48.8652801513672,0],[172.468475341797,48.8652801513672,0],[171.676727294922,48.8652801513672,0],[170.884963989258,48.8652801513672,0],[170.093200683594,48.8652801513672,0],[169.301452636719,48.8652801513672,0],[168.509689331055,48.8652801513672,0],[167.71794128418,48.8652801513672,0],[166.926177978516,48.8652801513672,0],[166.134414672852,48.8652801513672,0],[165.342666625977,48.8652801513672,0],[164.550903320312,48.8652801513672,0],[163.759140014648,48.8652801513672,0],[162.967391967773,48.8652801513672,0],[162.175628662109,48.8652801513672,0],[161.383880615234,48.8652801513672,0],[160.59211730957,48.8652801513672,0],[159.800354003906,48.8652801513672,0],[159.008605957031,48.8652801513672,0],[158.216842651367,48.8652801513672,0],[157.425079345703,48.8652801513672,0],[156.633331298828,48.8652801513672,0],[155.841567993164,48.8652801513672,0],[155.049819946289,48.8652801513672,0],[154.258056640625,48.8652801513672,0],[153.466293334961,48.8652801513672,0],[152.674545288086,48.8652801513672,0],[151.882781982422,48.8652801513672,0],[151.091033935547,48.8652801513672,0],[150.299270629883,48.8652801513672,0],[149.507507324219,48.8652801513672,0],[148.715759277344,48.8652801513672,0],[147.92399597168,48.8652801513672,0],[147.132232666016,48.8652801513672,0],[146.340484619141,48.8652801513672,0],[145.548721313477,48.8652801513672,0],[144.756973266602,48.8652801513672,0],[143.965209960938,48.8652801513672,0],[143.173446655273,48.8652801513672,0],[142.381698608398,48.8652801513672,0],[141.589935302734,48.8652801513672,0],[140.798187255859,48.8652801513672,0],[140.006423950195,48.8652801513672,0],[139.214660644531,48.8652801513672,0],[138.422912597656,48.8652801513672,0],[137.631149291992,48.8652801513672,0],[136.839385986328,48.8652801513672,0],[136.047637939453,48.8652801513672,0],[135.255874633789,48.8652801513672,0],[134.464126586914,48.8652801513672,0],[133.67236328125,48.8652801513672,0],[132.880599975586,48.8652801513672,0],[132.088851928711,48.8652801513672,0],[131.297088623047,48.8652801513672,0],[130.505325317383,48.8652801513672,0],[129.713577270508,48.8652801513672,0],[128.921813964844,48.8652801513672,0],[128.130065917969,48.8652801513672,0],[127.338302612305,48.8652801513672,0],[126.546546936035,48.8652801513672,0],[125.754791259766,48.8652801513672,0],[124.963027954102,48.8652801513672,0],[124.171272277832,48.8652801513672,0],[123.379516601562,48.8652801513672,0],[122.587760925293,48.8652801513672,0],[121.795997619629,48.8652801513672,0],[121.004241943359,48.8652801513672,0],[120.21248626709,48.8652801513672,0],[119.42073059082,48.8652801513672,0],[118.628967285156,48.8652801513672,0],[117.837211608887,48.8652801513672,0],[117.045455932617,48.8652801513672,0],[116.253700256348,48.8652801513672,0],[115.461936950684,48.8652801513672,0],[114.670181274414,48.8652801513672,0],[113.878425598145,48.8652801513672,0],[113.086669921875,48.8652801513672,0],[112.294914245605,48.8652801513672,0],[111.503150939941,48.8652801513672,0],[110.711395263672,48.8652801513672,0],[109.919639587402,48.8652801513672,0],[109.127883911133,48.8652801513672,0],[108.336120605469,48.8652801513672,0],[107.544364929199,48.8652801513672,0],[106.75260925293,48.8652801513672,0],[105.96085357666,48.8652801513672,0],[105.169090270996,48.8652801513672,0],[104.377334594727,48.8652801513672,0],[103.585578918457,48.8652801513672,0],[102.793823242188,48.8652801513672,0],[102.002059936523,48.8652801513672,0],[101.210304260254,48.8652801513672,0],[100.418548583984,48.8652801513672,0],[99.6267929077148,48.8652801513672,0],[98.8350372314453,48.8652801513672,0],[98.0432739257812,48.8652801513672,0],[97.2515182495117,48.8652801513672,0],[96.4597625732422,48.8652801513672,0],[95.6680068969727,48.8652801513672,0],[94.8762435913086,48.8652801513672,0],[94.0844879150391,48.8652801513672,0],[93.2927322387695,48.8652801513672,0],[92.5009765625,48.8652801513672,0],[91.7092132568359,48.8652801513672,0],[90.9174575805664,48.8652801513672,0],[90.1257019042969,48.8652801513672,0],[89.3339462280273,48.8652801513672,0],[88.5421829223633,48.8652801513672,0],[87.7504272460938,48.8652801513672,0],[86.9586715698242,48.8652801513672,0],[86.1669158935547,48.8652801513672,0],[85.3751525878906,48.8652801513672,0],[84.5833969116211,48.8652801513672,0],[83.7916412353516,48.8652801513672,0],[82.999885559082,48.8652801513672,0],[82.2081298828125,48.8652801513672,0],[81.4163665771484,48.8652801513672,0],[80.6246109008789,48.8652801513672,0],[79.8328552246094,48.8652801513672,0],[79.0410995483398,48.8652801513672,0],[78.2493362426758,48.8652801513672,0],[77.4575805664062,48.8652801513672,0],[76.6658248901367,48.8652801513672,0],[75.8740692138672,48.8652801513672,0],[75.0823059082031,48.8652801513672,0],[74.2905502319336,48.8652801513672,0],[73.4987945556641,48.8652801513672,0],[72.7070388793945,48.8652801513672,0],[71.9152755737305,48.8652801513672,0],[71.1235198974609,48.8652801513672,0],[70.3317642211914,48.8652801513672,0],[69.5400085449219,48.8652801513672,0],[68.7482528686523,48.8652801513672,0],[67.9564895629883,48.8652801513672,0],[67.1647338867188,48.8652801513672,0],[66.3729782104492,48.8652801513672,0],[65.5812225341797,48.8652801513672,0],[64.7894592285156,48.8652801513672,0],[63.9977035522461,48.8652801513672,0],[63.2059478759766,48.8652801513672,0],[62.4141883850098,48.8652801513672,0],[61.6224327087402,48.8652801513672,0],[60.8306732177734,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;195&#34;:{&#34;id&#34;:195,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0,&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3,-3]},&#34;vertices&#34;:[[60.8306732177734,159.882751464844,0],[61.6224327087402,159.628890991211,0],[62.4141883850098,158.957458496094,0],[63.2059478759766,157.890960693359,0],[63.9977035522461,156.439666748047,0],[64.7894592285156,154.616241455078,0],[65.5812225341797,152.342651367188,0],[66.3729782104492,149.740203857422,0],[67.1647338867188,146.846633911133,0],[67.9564895629883,143.687698364258,0],[68.7482528686523,140.290451049805,0],[69.5400085449219,136.639221191406,0],[70.3317642211914,132.830535888672,0],[71.1235198974609,128.903381347656,0],[71.9152755737305,124.88858795166,0],[72.7070388793945,120.816917419434,0],[73.4987945556641,116.727432250977,0],[74.2905502319336,112.668449401855,0],[75.0823059082031,108.667381286621,0],[75.8740692138672,104.749923706055,0],[76.6658248901367,100.940643310547,0],[77.4575805664062,97.3114013671875,0],[78.2493362426758,93.859245300293,0],[79.0410995483398,90.5942916870117,0],[79.8328552246094,87.5317230224609,0],[80.6246109008789,84.6853332519531,0],[81.4163665771484,82.1370239257812,0],[82.2081298828125,79.8457336425781,0],[82.999885559082,77.8061370849609,0],[83.7916412353516,76.0231094360352,0],[84.5833969116211,74.5003814697266,0],[85.3751525878906,73.3145599365234,0],[86.1669158935547,72.4051818847656,0],[86.9586715698242,71.7570877075195,0],[87.7504272460938,71.3678741455078,0],[88.5421829223633,71.2344512939453,0],[89.3339462280273,71.4204864501953,0],[90.1257019042969,71.861457824707,0],[90.9174575805664,72.5376892089844,0],[91.7092132568359,73.4425811767578,0],[92.5009765625,74.5691299438477,0],[93.2927322387695,75.9648971557617,0],[94.0844879150391,77.5706939697266,0],[94.8762435913086,79.3661270141602,0],[95.6680068969727,81.3425674438477,0],[96.4597625732422,83.4912719726562,0],[97.2515182495117,85.8434906005859,0],[98.0432739257812,88.3509826660156,0],[98.8350372314453,90.9958267211914,0],[99.6267929077148,93.7697601318359,0],[100.418548583984,96.6647567749023,0],[101.210304260254,99.7003784179688,0],[102.002059936523,102.843063354492,0],[102.793823242188,106.08073425293,0],[103.585578918457,109.408782958984,0],[104.377334594727,112.823310852051,0],[105.169090270996,116.343048095703,0],[105.96085357666,119.949729919434,0],[106.75260925293,123.639228820801,0],[107.544364929199,127.413642883301,0],[108.336120605469,131.276016235352,0],[109.127883911133,135.258117675781,0],[109.919639587402,139.351440429688,0],[110.711395263672,143.557922363281,0],[111.503150939941,147.886474609375,0],[112.294914245605,152.346603393555,0],[113.086669921875,156.991333007812,0],[113.878425598145,161.809921264648,0],[114.670181274414,166.803436279297,0],[115.461936950684,171.982757568359,0],[116.253700256348,177.358489990234,0],[117.045455932617,182.998962402344,0],[117.837211608887,188.877578735352,0],[118.628967285156,194.985107421875,0],[119.42073059082,201.325942993164,0],[120.21248626709,207.903076171875,0],[121.004241943359,214.777709960938,0],[121.795997619629,221.900665283203,0],[122.587760925293,229.246337890625,0],[123.379516601562,236.804550170898,0],[124.171272277832,244.562911987305,0],[124.963027954102,252.544296264648,0],[125.754791259766,260.683380126953,0],[126.546546936035,268.940887451172,0],[127.338302612305,277.2890625,0],[128.130065917969,285.6982421875,0],[128.921813964844,294.126617431641,0],[129.713577270508,302.512786865234,0],[130.505325317383,310.816192626953,0],[131.297088623047,318.996490478516,0],[132.088851928711,327.012573242188,0],[132.880599975586,334.750671386719,0],[133.67236328125,342.179229736328,0],[134.464126586914,349.274505615234,0],[135.255874633789,355.995391845703,0],[136.047637939453,362.301544189453,0],[136.839385986328,368.024536132812,0],[137.631149291992,373.183837890625,0],[138.422912597656,377.788269042969,0],[139.214660644531,381.809631347656,0],[140.006423950195,385.222137451172,0],[140.798187255859,387.84033203125,0],[141.589935302734,389.740173339844,0],[142.381698608398,390.968658447266,0],[143.173446655273,391.520446777344,0],[143.965209960938,391.393402099609,0],[144.756973266602,390.428283691406,0],[145.548721313477,388.744079589844,0],[146.340484619141,386.41748046875,0],[147.132232666016,383.467529296875,0],[147.92399597168,379.916015625,0],[148.715759277344,375.662322998047,0],[149.507507324219,370.840270996094,0],[150.299270629883,365.536712646484,0],[151.091033935547,359.787628173828,0],[151.882781982422,353.630401611328,0],[152.674545288086,347.033630371094,0],[153.466293334961,340.114349365234,0],[154.258056640625,332.946990966797,0],[155.049819946289,325.572082519531,0],[155.841567993164,318.029815673828,0],[156.633331298828,310.346435546875,0],[157.425079345703,302.599212646484,0],[158.216842651367,294.833984375,0],[159.008605957031,287.083953857422,0],[159.800354003906,279.380798339844,0],[160.59211730957,271.783569335938,0],[161.383880615234,264.322570800781,0],[162.175628662109,257.010437011719,0],[162.967391967773,249.866317749023,0],[163.759140014648,242.907562255859,0],[164.550903320312,236.200271606445,0],[165.342666625977,229.735763549805,0],[166.134414672852,223.499771118164,0],[166.926177978516,217.497482299805,0],[167.71794128418,211.732528686523,0],[168.509689331055,206.261199951172,0],[169.301452636719,201.052536010742,0],[170.093200683594,196.078277587891,0],[170.884963989258,191.334594726562,0],[171.676727294922,186.81706237793,0],[172.468475341797,182.567886352539,0],[173.260238647461,178.551681518555,0],[174.051986694336,174.738983154297,0],[174.84375,171.124069213867,0],[175.635513305664,167.701385498047,0],[176.427261352539,164.50553894043,0],[177.219024658203,161.5087890625,0],[178.010787963867,158.68782043457,0],[178.802536010742,156.040344238281,0],[179.594299316406,153.564697265625,0],[180.386047363281,151.297561645508,0],[181.177810668945,149.221374511719,0],[181.969573974609,147.318542480469,0],[182.761322021484,145.591033935547,0],[183.553085327148,144.041168212891,0],[184.344848632812,142.711959838867,0],[185.136596679688,141.589599609375,0],[185.928359985352,140.655776977539,0],[186.720108032227,139.912567138672,0],[187.511871337891,139.361694335938,0],[188.303634643555,139.045700073242,0],[189.09538269043,138.944595336914,0],[189.887145996094,139.032699584961,0],[190.678894042969,139.305938720703,0],[191.470657348633,139.759078979492,0],[192.262420654297,140.418807983398,0],[193.054168701172,141.253082275391,0],[193.845932006836,142.228546142578,0],[194.6376953125,143.331100463867,0],[195.429443359375,144.545364379883,0],[196.221206665039,145.867233276367,0],[197.012954711914,147.256271362305,0],[197.804718017578,148.680023193359,0],[198.596481323242,150.116363525391,0],[199.388229370117,151.542617797852,0],[200.179992675781,152.919815063477,0],[200.971740722656,154.211547851562,0],[201.76350402832,155.399795532227,0],[202.555267333984,156.462036132812,0],[203.347015380859,157.376327514648,0],[204.138778686523,158.079879760742,0],[204.930541992188,158.554763793945,0],[205.722290039062,158.807876586914,0],[206.514053344727,158.82536315918,0],[207.305801391602,158.594940185547,0],[208.097564697266,158.051528930664,0],[208.88932800293,157.203643798828,0],[209.681076049805,156.083648681641,0],[210.472839355469,154.691879272461,0],[211.264602661133,153.030502319336,0],[212.056350708008,151.053634643555,0],[212.848114013672,148.793151855469,0],[213.639862060547,146.296340942383,0],[214.431625366211,143.576766967773,0],[215.223388671875,140.649337768555,0],[216.01513671875,137.499069213867,0],[216.806900024414,134.169052124023,0],[217.598648071289,130.704742431641,0],[218.390411376953,127.126640319824,0],[219.182174682617,123.455596923828,0],[219.973922729492,119.706001281738,0],[220.765686035156,115.917106628418,0],[221.55744934082,112.118034362793,0],[222.349197387695,108.32820892334,0],[223.140960693359,104.566413879395,0],[223.932708740234,100.865119934082,0],[224.724472045898,97.2489700317383,0],[225.516235351562,93.7243804931641,0],[226.307983398438,90.3038482666016,0],[227.099746704102,86.9987945556641,0],[227.891510009766,83.8458862304688,0],[228.683258056641,80.8521347045898,0],[229.475021362305,78.0041122436523,0],[230.26676940918,75.3057403564453,0],[231.058532714844,72.7599411010742,0],[231.850296020508,70.3973617553711,0],[232.642044067383,68.211181640625,0],[233.433807373047,66.1767501831055,0],[234.225555419922,64.2912979125977,0],[235.017318725586,62.5514831542969,0],[235.80908203125,60.9777717590332,0],[236.600830078125,59.556453704834,0],[237.392593383789,58.2609024047852,0],[238.184356689453,57.0851135253906,0],[238.976104736328,56.0229187011719,0],[239.767868041992,55.0853805541992,0],[240.559616088867,54.2581596374512,0],[241.351379394531,53.518970489502,0],[242.143142700195,52.8615646362305,0],[242.93489074707,52.2798080444336,0],[243.726654052734,51.7783813476562,0],[244.518402099609,51.3459167480469,0],[245.310165405273,50.9668617248535,0],[246.101928710938,50.6363639831543,0],[246.893676757812,50.3497734069824,0],[247.685440063477,50.1084480285645,0],[248.477203369141,49.9049186706543,0],[249.268951416016,49.7298736572266,0],[250.06071472168,49.5802001953125,0],[250.852462768555,49.4529991149902,0],[251.644226074219,49.348316192627,0],[252.435989379883,49.2619667053223,0],[253.227737426758,49.1890754699707,0],[254.019500732422,49.1279411315918,0],[254.811264038086,49.0770149230957,0],[255.603012084961,49.0360488891602,0],[256.394775390625,49.0029945373535,0],[257.1865234375,48.9755973815918,0],[257.978302001953,48.9530601501465,0],[258.770050048828,48.9346542358398,0],[259.561798095703,48.9201774597168,0],[260.353546142578,48.9087524414062,0],[261.145324707031,48.8994522094727,0],[261.937072753906,48.8919486999512,0],[262.728820800781,48.8859405517578,0],[263.520599365234,48.8813209533691,0],[264.312347412109,48.8777503967285,0],[265.104095458984,48.8749008178711,0],[265.895874023438,48.8726425170898,0],[266.687622070312,48.8708686828613,0],[267.479370117188,48.8695373535156,0],[268.271148681641,48.8685302734375,0],[269.062896728516,48.8677406311035,0],[269.854644775391,48.8671264648438,0],[270.646392822266,48.8666534423828,0],[271.438171386719,48.8663063049316,0],[272.229919433594,48.8660469055176,0],[273.021667480469,48.865852355957,0],[273.813446044922,48.8656997680664,0],[274.605194091797,48.8655853271484,0],[275.396942138672,48.8655052185059,0],[276.188720703125,48.8654441833496,0],[276.98046875,48.8653984069824,0],[277.772216796875,48.8653678894043,0],[278.563995361328,48.8653411865234,0],[279.355743408203,48.8653221130371,0],[280.147491455078,48.8653106689453,0],[280.939239501953,48.8653030395508,0],[281.731018066406,48.8652954101562,0],[282.522766113281,48.865291595459,0],[283.314514160156,48.8652877807617,0],[284.106292724609,48.8652839660645,0],[284.898040771484,48.8652839660645,0],[285.689788818359,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[339.529296875,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0]],&#34;colors&#34;:[[1,1,1,0]],&#34;centers&#34;:[[60.8306732177734,159.882751464844,0],[61.6224327087402,159.628890991211,0],[62.4141883850098,158.957458496094,0],[63.2059478759766,157.890960693359,0],[63.9977035522461,156.439666748047,0],[64.7894592285156,154.616241455078,0],[65.5812225341797,152.342651367188,0],[66.3729782104492,149.740203857422,0],[67.1647338867188,146.846633911133,0],[67.9564895629883,143.687698364258,0],[68.7482528686523,140.290451049805,0],[69.5400085449219,136.639221191406,0],[70.3317642211914,132.830535888672,0],[71.1235198974609,128.903381347656,0],[71.9152755737305,124.88858795166,0],[72.7070388793945,120.816917419434,0],[73.4987945556641,116.727432250977,0],[74.2905502319336,112.668449401855,0],[75.0823059082031,108.667381286621,0],[75.8740692138672,104.749923706055,0],[76.6658248901367,100.940643310547,0],[77.4575805664062,97.3114013671875,0],[78.2493362426758,93.859245300293,0],[79.0410995483398,90.5942916870117,0],[79.8328552246094,87.5317230224609,0],[80.6246109008789,84.6853332519531,0],[81.4163665771484,82.1370239257812,0],[82.2081298828125,79.8457336425781,0],[82.999885559082,77.8061370849609,0],[83.7916412353516,76.0231094360352,0],[84.5833969116211,74.5003814697266,0],[85.3751525878906,73.3145599365234,0],[86.1669158935547,72.4051818847656,0],[86.9586715698242,71.7570877075195,0],[87.7504272460938,71.3678741455078,0],[88.5421829223633,71.2344512939453,0],[89.3339462280273,71.4204864501953,0],[90.1257019042969,71.861457824707,0],[90.9174575805664,72.5376892089844,0],[91.7092132568359,73.4425811767578,0],[92.5009765625,74.5691299438477,0],[93.2927322387695,75.9648971557617,0],[94.0844879150391,77.5706939697266,0],[94.8762435913086,79.3661270141602,0],[95.6680068969727,81.3425674438477,0],[96.4597625732422,83.4912719726562,0],[97.2515182495117,85.8434906005859,0],[98.0432739257812,88.3509826660156,0],[98.8350372314453,90.9958267211914,0],[99.6267929077148,93.7697601318359,0],[100.418548583984,96.6647567749023,0],[101.210304260254,99.7003784179688,0],[102.002059936523,102.843063354492,0],[102.793823242188,106.08073425293,0],[103.585578918457,109.408782958984,0],[104.377334594727,112.823310852051,0],[105.169090270996,116.343048095703,0],[105.96085357666,119.949729919434,0],[106.75260925293,123.639228820801,0],[107.544364929199,127.413642883301,0],[108.336120605469,131.276016235352,0],[109.127883911133,135.258117675781,0],[109.919639587402,139.351440429688,0],[110.711395263672,143.557922363281,0],[111.503150939941,147.886474609375,0],[112.294914245605,152.346603393555,0],[113.086669921875,156.991333007812,0],[113.878425598145,161.809921264648,0],[114.670181274414,166.803436279297,0],[115.461936950684,171.982757568359,0],[116.253700256348,177.358489990234,0],[117.045455932617,182.998962402344,0],[117.837211608887,188.877578735352,0],[118.628967285156,194.985107421875,0],[119.42073059082,201.325942993164,0],[120.21248626709,207.903076171875,0],[121.004241943359,214.777709960938,0],[121.795997619629,221.900665283203,0],[122.587760925293,229.246337890625,0],[123.379516601562,236.804550170898,0],[124.171272277832,244.562911987305,0],[124.963027954102,252.544296264648,0],[125.754791259766,260.683380126953,0],[126.546546936035,268.940887451172,0],[127.338302612305,277.2890625,0],[128.130065917969,285.6982421875,0],[128.921813964844,294.126617431641,0],[129.713577270508,302.512786865234,0],[130.505325317383,310.816192626953,0],[131.297088623047,318.996490478516,0],[132.088851928711,327.012573242188,0],[132.880599975586,334.750671386719,0],[133.67236328125,342.179229736328,0],[134.464126586914,349.274505615234,0],[135.255874633789,355.995391845703,0],[136.047637939453,362.301544189453,0],[136.839385986328,368.024536132812,0],[137.631149291992,373.183837890625,0],[138.422912597656,377.788269042969,0],[139.214660644531,381.809631347656,0],[140.006423950195,385.222137451172,0],[140.798187255859,387.84033203125,0],[141.589935302734,389.740173339844,0],[142.381698608398,390.968658447266,0],[143.173446655273,391.520446777344,0],[143.965209960938,391.393402099609,0],[144.756973266602,390.428283691406,0],[145.548721313477,388.744079589844,0],[146.340484619141,386.41748046875,0],[147.132232666016,383.467529296875,0],[147.92399597168,379.916015625,0],[148.715759277344,375.662322998047,0],[149.507507324219,370.840270996094,0],[150.299270629883,365.536712646484,0],[151.091033935547,359.787628173828,0],[151.882781982422,353.630401611328,0],[152.674545288086,347.033630371094,0],[153.466293334961,340.114349365234,0],[154.258056640625,332.946990966797,0],[155.049819946289,325.572082519531,0],[155.841567993164,318.029815673828,0],[156.633331298828,310.346435546875,0],[157.425079345703,302.599212646484,0],[158.216842651367,294.833984375,0],[159.008605957031,287.083953857422,0],[159.800354003906,279.380798339844,0],[160.59211730957,271.783569335938,0],[161.383880615234,264.322570800781,0],[162.175628662109,257.010437011719,0],[162.967391967773,249.866317749023,0],[163.759140014648,242.907562255859,0],[164.550903320312,236.200271606445,0],[165.342666625977,229.735763549805,0],[166.134414672852,223.499771118164,0],[166.926177978516,217.497482299805,0],[167.71794128418,211.732528686523,0],[168.509689331055,206.261199951172,0],[169.301452636719,201.052536010742,0],[170.093200683594,196.078277587891,0],[170.884963989258,191.334594726562,0],[171.676727294922,186.81706237793,0],[172.468475341797,182.567886352539,0],[173.260238647461,178.551681518555,0],[174.051986694336,174.738983154297,0],[174.84375,171.124069213867,0],[175.635513305664,167.701385498047,0],[176.427261352539,164.50553894043,0],[177.219024658203,161.5087890625,0],[178.010787963867,158.68782043457,0],[178.802536010742,156.040344238281,0],[179.594299316406,153.564697265625,0],[180.386047363281,151.297561645508,0],[181.177810668945,149.221374511719,0],[181.969573974609,147.318542480469,0],[182.761322021484,145.591033935547,0],[183.553085327148,144.041168212891,0],[184.344848632812,142.711959838867,0],[185.136596679688,141.589599609375,0],[185.928359985352,140.655776977539,0],[186.720108032227,139.912567138672,0],[187.511871337891,139.361694335938,0],[188.303634643555,139.045700073242,0],[189.09538269043,138.944595336914,0],[189.887145996094,139.032699584961,0],[190.678894042969,139.305938720703,0],[191.470657348633,139.759078979492,0],[192.262420654297,140.418807983398,0],[193.054168701172,141.253082275391,0],[193.845932006836,142.228546142578,0],[194.6376953125,143.331100463867,0],[195.429443359375,144.545364379883,0],[196.221206665039,145.867233276367,0],[197.012954711914,147.256271362305,0],[197.804718017578,148.680023193359,0],[198.596481323242,150.116363525391,0],[199.388229370117,151.542617797852,0],[200.179992675781,152.919815063477,0],[200.971740722656,154.211547851562,0],[201.76350402832,155.399795532227,0],[202.555267333984,156.462036132812,0],[203.347015380859,157.376327514648,0],[204.138778686523,158.079879760742,0],[204.930541992188,158.554763793945,0],[205.722290039062,158.807876586914,0],[206.514053344727,158.82536315918,0],[207.305801391602,158.594940185547,0],[208.097564697266,158.051528930664,0],[208.88932800293,157.203643798828,0],[209.681076049805,156.083648681641,0],[210.472839355469,154.691879272461,0],[211.264602661133,153.030502319336,0],[212.056350708008,151.053634643555,0],[212.848114013672,148.793151855469,0],[213.639862060547,146.296340942383,0],[214.431625366211,143.576766967773,0],[215.223388671875,140.649337768555,0],[216.01513671875,137.499069213867,0],[216.806900024414,134.169052124023,0],[217.598648071289,130.704742431641,0],[218.390411376953,127.126640319824,0],[219.182174682617,123.455596923828,0],[219.973922729492,119.706001281738,0],[220.765686035156,115.917106628418,0],[221.55744934082,112.118034362793,0],[222.349197387695,108.32820892334,0],[223.140960693359,104.566413879395,0],[223.932708740234,100.865119934082,0],[224.724472045898,97.2489700317383,0],[225.516235351562,93.7243804931641,0],[226.307983398438,90.3038482666016,0],[227.099746704102,86.9987945556641,0],[227.891510009766,83.8458862304688,0],[228.683258056641,80.8521347045898,0],[229.475021362305,78.0041122436523,0],[230.26676940918,75.3057403564453,0],[231.058532714844,72.7599411010742,0],[231.850296020508,70.3973617553711,0],[232.642044067383,68.211181640625,0],[233.433807373047,66.1767501831055,0],[234.225555419922,64.2912979125977,0],[235.017318725586,62.5514831542969,0],[235.80908203125,60.9777717590332,0],[236.600830078125,59.556453704834,0],[237.392593383789,58.2609024047852,0],[238.184356689453,57.0851135253906,0],[238.976104736328,56.0229187011719,0],[239.767868041992,55.0853805541992,0],[240.559616088867,54.2581596374512,0],[241.351379394531,53.518970489502,0],[242.143142700195,52.8615646362305,0],[242.93489074707,52.2798080444336,0],[243.726654052734,51.7783813476562,0],[244.518402099609,51.3459167480469,0],[245.310165405273,50.9668617248535,0],[246.101928710938,50.6363639831543,0],[246.893676757812,50.3497734069824,0],[247.685440063477,50.1084480285645,0],[248.477203369141,49.9049186706543,0],[249.268951416016,49.7298736572266,0],[250.06071472168,49.5802001953125,0],[250.852462768555,49.4529991149902,0],[251.644226074219,49.348316192627,0],[252.435989379883,49.2619667053223,0],[253.227737426758,49.1890754699707,0],[254.019500732422,49.1279411315918,0],[254.811264038086,49.0770149230957,0],[255.603012084961,49.0360488891602,0],[256.394775390625,49.0029945373535,0],[257.1865234375,48.9755973815918,0],[257.978302001953,48.9530601501465,0],[258.770050048828,48.9346542358398,0],[259.561798095703,48.9201774597168,0],[260.353546142578,48.9087524414062,0],[261.145324707031,48.8994522094727,0],[261.937072753906,48.8919486999512,0],[262.728820800781,48.8859405517578,0],[263.520599365234,48.8813209533691,0],[264.312347412109,48.8777503967285,0],[265.104095458984,48.8749008178711,0],[265.895874023438,48.8726425170898,0],[266.687622070312,48.8708686828613,0],[267.479370117188,48.8695373535156,0],[268.271148681641,48.8685302734375,0],[269.062896728516,48.8677406311035,0],[269.854644775391,48.8671264648438,0],[270.646392822266,48.8666534423828,0],[271.438171386719,48.8663063049316,0],[272.229919433594,48.8660469055176,0],[273.021667480469,48.865852355957,0],[273.813446044922,48.8656997680664,0],[274.605194091797,48.8655853271484,0],[275.396942138672,48.8655052185059,0],[276.188720703125,48.8654441833496,0],[276.98046875,48.8653984069824,0],[277.772216796875,48.8653678894043,0],[278.563995361328,48.8653411865234,0],[279.355743408203,48.8653221130371,0],[280.147491455078,48.8653106689453,0],[280.939239501953,48.8653030395508,0],[281.731018066406,48.8652954101562,0],[282.522766113281,48.865291595459,0],[283.314514160156,48.8652877807617,0],[284.106292724609,48.8652839660645,0],[284.898040771484,48.8652839660645,0],[285.689788818359,48.8652801513672,0],[286.481567382812,48.8652801513672,0],[287.273315429688,48.8652801513672,0],[288.065063476562,48.8652801513672,0],[288.856842041016,48.8652801513672,0],[289.648590087891,48.8652801513672,0],[290.440338134766,48.8652801513672,0],[291.232086181641,48.8652801513672,0],[292.023864746094,48.8652801513672,0],[292.815612792969,48.8652801513672,0],[293.607360839844,48.8652801513672,0],[294.399139404297,48.8652801513672,0],[295.190887451172,48.8652801513672,0],[295.982635498047,48.8652801513672,0],[296.7744140625,48.8652801513672,0],[297.566162109375,48.8652801513672,0],[298.35791015625,48.8652801513672,0],[299.149688720703,48.8652801513672,0],[299.941436767578,48.8652801513672,0],[300.733184814453,48.8652801513672,0],[301.524932861328,48.8652801513672,0],[302.316711425781,48.8652801513672,0],[303.108459472656,48.8652801513672,0],[303.900207519531,48.8652801513672,0],[304.691986083984,48.8652801513672,0],[305.483734130859,48.8652801513672,0],[306.275482177734,48.8652801513672,0],[307.067260742188,48.8652801513672,0],[307.859008789062,48.8652801513672,0],[308.650756835938,48.8652801513672,0],[309.442535400391,48.8652801513672,0],[310.234283447266,48.8652801513672,0],[311.026031494141,48.8652801513672,0],[311.817810058594,48.8652801513672,0],[312.609558105469,48.8652801513672,0],[313.401306152344,48.8652801513672,0],[314.193054199219,48.8652801513672,0],[314.984832763672,48.8652801513672,0],[315.776580810547,48.8652801513672,0],[316.568328857422,48.8652801513672,0],[317.360107421875,48.8652801513672,0],[318.15185546875,48.8652801513672,0],[318.943603515625,48.8652801513672,0],[319.735382080078,48.8652801513672,0],[320.527130126953,48.8652801513672,0],[321.318878173828,48.8652801513672,0],[322.110656738281,48.8652801513672,0],[322.902404785156,48.8652801513672,0],[323.694152832031,48.8652801513672,0],[324.485900878906,48.8652801513672,0],[325.277679443359,48.8652801513672,0],[326.069427490234,48.8652801513672,0],[326.861175537109,48.8652801513672,0],[327.652954101562,48.8652801513672,0],[328.444702148438,48.8652801513672,0],[329.236450195312,48.8652801513672,0],[330.028228759766,48.8652801513672,0],[330.819976806641,48.8652801513672,0],[331.611724853516,48.8652801513672,0],[332.403503417969,48.8652801513672,0],[333.195251464844,48.8652801513672,0],[333.986999511719,48.8652801513672,0],[334.778747558594,48.8652801513672,0],[335.570526123047,48.8652801513672,0],[336.362274169922,48.8652801513672,0],[337.154022216797,48.8652801513672,0],[337.94580078125,48.8652801513672,0],[338.737548828125,48.8652801513672,0],[339.529296875,48.8652801513672,0],[340.321075439453,48.8652801513672,0],[341.112823486328,48.8652801513672,0],[341.904571533203,48.8652801513672,0],[342.696350097656,48.8652801513672,0],[343.488098144531,48.8652801513672,0],[344.279846191406,48.8652801513672,0],[345.071594238281,48.8652801513672,0],[345.863372802734,48.8652801513672,0],[346.655120849609,48.8652801513672,0],[347.446868896484,48.8652801513672,0],[348.238647460938,48.8652801513672,0],[349.030395507812,48.8652801513672,0],[349.822143554688,48.8652801513672,0],[350.613922119141,48.8652801513672,0],[351.405670166016,48.8652801513672,0],[352.197418212891,48.8652801513672,0],[352.989196777344,48.8652801513672,0],[353.780944824219,48.8652801513672,0],[354.572692871094,48.8652801513672,0],[355.364471435547,48.8652801513672,0],[356.156219482422,48.8652801513672,0],[356.947967529297,48.8652801513672,0],[357.739715576172,48.8652801513672,0],[358.531494140625,48.8652801513672,0],[359.3232421875,48.8652801513672,0],[360.114990234375,48.8652801513672,0],[360.906768798828,48.8652801513672,0],[361.698516845703,48.8652801513672,0],[362.490264892578,48.8652801513672,0],[363.282043457031,48.8652801513672,0],[364.073791503906,48.8652801513672,0],[364.865539550781,48.8652801513672,0],[365.657318115234,48.8652801513672,0],[366.449066162109,48.8652801513672,0],[367.240814208984,48.8652801513672,0],[368.032562255859,48.8652801513672,0],[368.824340820312,48.8652801513672,0],[369.616088867188,48.8652801513672,0],[370.407836914062,48.8652801513672,0],[371.199615478516,48.8652801513672,0],[371.991363525391,48.8652801513672,0],[372.783111572266,48.8652801513672,0],[373.574890136719,48.8652801513672,0],[374.366638183594,48.8652801513672,0],[375.158386230469,48.8652801513672,0],[375.950164794922,48.8652801513672,0],[376.741912841797,48.8652801513672,0],[377.533660888672,48.8652801513672,0],[378.325408935547,48.8652801513672,0],[379.1171875,48.8652801513672,0],[379.908935546875,48.8652801513672,0],[380.70068359375,48.8652801513672,0],[381.492462158203,48.8652801513672,0],[382.284210205078,48.8652801513672,0],[383.075958251953,48.8652801513672,0],[383.867736816406,48.8652801513672,0],[384.659484863281,48.8652801513672,0],[385.451232910156,48.8652801513672,0],[386.243011474609,48.8652801513672,0],[387.034759521484,48.8652801513672,0],[387.826507568359,48.8652801513672,0],[388.618255615234,48.8652801513672,0],[389.410034179688,48.8652801513672,0],[390.201782226562,48.8652801513672,0],[390.993530273438,48.8652801513672,0],[391.785308837891,48.8652801513672,0],[392.577056884766,48.8652801513672,0],[393.368804931641,48.8652801513672,0],[394.160583496094,48.8652801513672,0],[394.952331542969,48.8652801513672,0],[395.744079589844,48.8652801513672,0],[396.535858154297,48.8652801513672,0],[397.327606201172,48.8652801513672,0],[398.119354248047,48.8652801513672,0],[398.9111328125,48.8652801513672,0],[399.702880859375,48.8652801513672,0],[400.49462890625,48.8652801513672,0],[401.286376953125,48.8652801513672,0],[402.078155517578,48.8652801513672,0],[402.869903564453,48.8652801513672,0],[403.661651611328,48.8652801513672,0],[404.453430175781,48.8652801513672,0],[405.245178222656,48.8652801513672,0],[406.036926269531,48.8652801513672,0],[406.828704833984,48.8652801513672,0],[407.620452880859,48.8652801513672,0],[408.412200927734,48.8652801513672,0],[409.203979492188,48.8652801513672,0],[409.995727539062,48.8652801513672,0],[410.787475585938,48.8652801513672,0],[411.579223632812,48.8652801513672,0],[412.371002197266,48.8652801513672,0],[413.162750244141,48.8652801513672,0],[413.954498291016,48.8652801513672,0],[414.746276855469,48.8652801513672,0],[415.538024902344,48.8652801513672,0],[416.329772949219,48.8652801513672,0],[417.121551513672,48.8652801513672,0],[417.913299560547,48.8652801513672,0],[418.705047607422,48.8652801513672,0],[419.496826171875,48.8652801513672,0],[420.28857421875,48.8652801513672,0],[421.080322265625,48.8652801513672,0],[421.8720703125,48.8652801513672,0],[422.663848876953,48.8652801513672,0],[423.455596923828,48.8652801513672,0],[424.247344970703,48.8652801513672,0],[425.039123535156,48.8652801513672,0],[425.830871582031,48.8652801513672,0],[426.622619628906,48.8652801513672,0],[427.414398193359,48.8652801513672,0],[428.206146240234,48.8652801513672,0],[428.997894287109,48.8652801513672,0],[429.789672851562,48.8652801513672,0],[430.581420898438,48.8652801513672,0],[431.373168945312,48.8652801513672,0],[432.164916992188,48.8652801513672,0],[432.956695556641,48.8652801513672,0],[433.748443603516,48.8652801513672,0],[434.540191650391,48.8652801513672,0],[435.331970214844,48.8652801513672,0],[436.123718261719,48.8652801513672,0],[436.915466308594,48.8652801513672,0],[437.707244873047,48.8652801513672,0],[438.498992919922,48.8652801513672,0],[439.290740966797,48.8652801513672,0],[440.08251953125,48.8652801513672,0],[440.874267578125,48.8652801513672,0],[441.666015625,48.8652801513672,0],[442.457794189453,48.8652801513672,0],[443.249542236328,48.8652801513672,0],[444.041290283203,48.8652801513672,0],[444.833038330078,48.8652801513672,0],[445.624816894531,48.8652801513672,0],[446.416564941406,48.8652801513672,0],[447.208312988281,48.8652801513672,0],[448.000091552734,48.8652801513672,0],[448.791839599609,48.8652801513672,0],[449.583587646484,48.8652801513672,0],[450.375366210938,48.8652801513672,0],[451.167114257812,48.8652801513672,0],[451.958862304688,48.8652801513672,0],[452.750640869141,48.8652801513672,0],[453.542388916016,48.8652801513672,0],[454.334136962891,48.8652801513672,0],[455.125885009766,48.8652801513672,0],[455.917663574219,48.8652801513672,0],[456.709411621094,48.8652801513672,0],[457.501159667969,48.8652801513672,0],[458.292938232422,48.8652801513672,0],[459.084686279297,48.8652801513672,0],[459.876434326172,48.8652801513672,0],[460.668212890625,48.8652801513672,0],[461.4599609375,48.8652801513672,0],[462.251708984375,48.8652801513672,0],[463.043487548828,48.8652801513672,0],[463.835235595703,48.8652801513672,0],[464.626983642578,48.8652801513672,0],[465.418731689453,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16480},&#34;196&#34;:{&#34;id&#34;:196,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;alpha&#34;:0,&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.09999990463257,-3.09999990463257]},&#34;vertices&#34;:[[40.6012725830078,31.7325210571289,0],[485.648162841797,31.7325210571289,0],[485.648162841797,408.653198242188,0],[40.6012725830078,408.653198242188,0]],&#34;colors&#34;:[[1,1,1,0]],&#34;centers&#34;:[[263.124725341797,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:42},&#34;197&#34;:{&#34;id&#34;:197,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.09999990463257,-3.09999990463257]},&#34;vertices&#34;:[[40.6012725830078,31.7325210571289,0.00999999977648258],[485.648162841797,31.7325210571289,0.00999999977648258],[485.648162841797,408.653198242188,0.00999999977648258],[40.6012725830078,408.653198242188,0.00999999977648258],[40.6012725830078,31.7325210571289,0.00999999977648258]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[40.6012725830078,31.7325210571289,0.00999999977648258],[485.648162841797,31.7325210571289,0.00999999977648258],[485.648162841797,408.653198242188,0.00999999977648258],[40.6012725830078,408.653198242188,0.00999999977648258],[40.6012725830078,31.7325210571289,0.00999999977648258]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;198&#34;:{&#34;id&#34;:198,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.20000004768372,-3.20000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAABsUlEQVRIx92VzSsEYRyAn11f6yMH5cAe3LwlcZEUtTls+ZqLq4+Dky0H+QeU3Bw4yZFScpLeHETJxWFTLpQmbWpLe6Gs2LAbh3csr9n5rbPfZaf5Pe/zNIedgf82oe9LZ5JZugmTYodVnQs+JJFBu2LIWScB5MkTAS6J6YeAjEAG78IeMEuCPHM0UMcoGTrZCsgIpLQLATjVpIiyqJe8Az0kCdGvz3wZgZQt5okcoryz9qXT5xwC06UeSCBFiwkNAkmd/SE8BoZKhCRStJhQB3BtCV2gzan3hSRStJhQK5C2kDsAWnwhiRQtJtQIPFvIS/G+PRIpWkyoEnizkNfifXskUrSYUA6otpAa8B0rR4oWE3oCai2kDoAsv0ciRYsJpYGohUSBDzK+kESKFhO6ApSFtAO3+sUXkkjRYkInQJ/1r4kDp/hHIkWLCR1xT4SFr73TSxzYKBGSSNFSAeAW1DMjxFROXaiCGmaXBg70incgoebVmLtfjpQt3vfICbPJFFDg3fuSDOhHb7fNBK868gdS2FWYH/fD3VM3NNNEFTdsMPP9clTjdFFwl8uT0u7/zSdIBvTgkstyPQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMHwEzgwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDANWXawAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[18.5424194335938,45.7092247009277,1],[35.8757553100586,45.7092247009277,1],[35.8757553100586,53.3758926391602,1],[18.5424194335938,53.3758926391602,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,49.5425567626953,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;199&#34;:{&#34;id&#34;:199,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.29999995231628,-3.29999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACfElEQVRIx93VW4hVVRjA8d+MOs2YDCiU2kAGwWyocOZBYkTFfJDKcb1o0IOV0ZMDEmrhi1QQvYi36CF8CJogsGAwclEQ3YhA4mBUUBTbSUJBxy6m42UYZ07Tw7nuOefsmWe/DXtv1vf/1n+ttVl7cadFW+01PGOXPu3OOeFYnGhd1JoMP+qbBR+JL2dE4W1DmDatEz/bGK+00LQkwyI3dDQXtZeRXYZM222JxQaNecR7LTR55MM6zHjM2rrrrbqlCx3O6fFafL3c2RoFbdbF0w2aXDI8711pTJoNsDSjoMeUNyuN8YzP8FyzCeWSffi++UqURJtQiON17V/giSZ8PtmPM3mih/Bbpj3FqnB3A59P9uFSOBpGw2S4HEbCwGzRfbiQKb8IVjaIcsiwylIM2+tBHe613enwUlbUjZuZ8lvV9mzkkf3gsp3ut8J2v2pzODxVwhZW77cz5ZN12frII2d8q8tg/BOcDF8q6HUonIz/VbqaYNZGu4uGLucg4ymn6hPxWnjVBx6wRqGydNfRlSlfDMYbRPMn4SuQ1L7RBfRkkB7MGGsonT8JV0FnTfRLxVuNXvwRbzWU5pDh6bA/DGZyy8GlmuhrDGR2zWZ802SMeeSLDjqQoR9H0Xc10ef+0WlfJR8etRnHm4jyyIiBsKmaW+YVjMS/YQGkxeSmLTYmE8kPSTF50oeW+CQeKhcMJXuSrenHc5HJT3bqtiU5n/yeTocNRvT617Z0nOp5FNoNexZFU+VTZn28Vs69b4fJ2DkPst+nVqLoti78ZWsslHILSo90Jv0oGXWPZRYZddwLtR9nss1qxfSNucl0LBk2ZalunPWOHXHUHRv/AxsE90+WTZBbAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[18.5424194335938,117.093078613281,1],[35.8757553100586,117.093078613281,1],[35.8757553100586,124.759750366211,1],[18.5424194335938,124.759750366211,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,120.926422119141,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;200&#34;:{&#34;id&#34;:200,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.40000009536743,-3.40000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAAB1klEQVRIx93VzUtUYRTH8c8MYmYWtIqahQhREEEEaZGLaCEIdaF1ioErhVb9A0a0alMLqXYaLWobTwa9YEQQJa3CojcsEMJNQYovmViLO07ecXzGgTZ1VsM5v/P9crjMvfxvlfvzM+nW54C8CbdcDvPVVpPdXnkQTpV116GURMlV/ViypAHjjoVvUU2TUa3uZEXrU/LFQJ9+S85q0uiEKfvdiGq2u6t1TTdCyUFSb0LBQLhQXDhkTE57eLaOps1tLbD6ojglvShR8NOVlZXw0n30VJRsTYY91+KT0fJRjJKKjmMsTK9aeoTOiuc0O4MhB30om0QpqWgf3maW3qM52VJBtGzE4dAbvq+ZRCl1YBcmM5EvYKeP5bTwxsnKTy5OSS/ahtlMZK7U33hFKamoDouZyI9Sf+MVpaSiedRnIptYs1atopRUNIPNmUgjmFZLRSmpaBKFTKSAX6ZqEkUpqeg19mYie/A5zNUkilJS0WMcyfxrOvCkJk0VSip66KsG51bmSZsOXK9RFKXUQVhMBgw6nywYtKDTkJyR8KK40K/dYuit5olTip8J19yUd8mMOffsMK6rRGjX5fSGbopQiqKwHHp0e2pW3jsXHa3wLqtaf4fyr9RvQU+4M9rApyMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDB8BM4MAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwDVl2sAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[18.5424194335938,188.476943969727,1],[35.8757553100586,188.476943969727,1],[35.8757553100586,196.143600463867,1],[18.5424194335938,196.143600463867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,192.310272216797,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;201&#34;:{&#34;id&#34;:201,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.5,-3.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACkUlEQVRIx93VX2jVdRjH8dc52NrUAoVSG3oSwjAXM0gRpYtdiBP9RqggpOit3oREu7KsKBH/1o3ZhZZh6AQx2JcJ+adYg1hHA8k/pUYJA1dqpC4nW7V5cXbOzm87c2d0lZ+r3+/zfZ7n/TzPlx8/HjalBh7DauvUSvvFIR/EeyOlhmf84Hh8JeGdVTsobGd8A9KFkI8csECltBqbZcPEETDjHVQ1yHvEzOHix/SHrLPePzbYq8di+9T4THgAZoIvzBliz1KhT53uIu9aEShUeBPvxd3gWAiylob58dthMHM1ml7iYDauxJZSObnVBdX+9mHejGd8iTUlIY+F/dpM96uvhhzW4vvSzeVAdcjGO0X+SdSXzMhYi0+94ErJic486I6ew08J/zIyYVy8OySjV7N342mlrrAWHWGXl011S6sdsS0JegrtiZTcFU7x8+Ba8aKlpXsOGROwXwV40nLLQkPcWby6x5Hsvavgl6/Z4HdrTTPZcj9K2RFWFE80Bj2JpO6i03LVp1WVJfE6OBpOyZphezgae/Ol7tE/cF6PMgQ+gmKTpsT77bBJo6e9KJtfXSeDvvKx4E55iGGV+wCeJQ9qR3UipBp9fvuPoFugkvzqLqjPcQuagauxazRVw0oZF2JzkTUJdAxM9DXmhXFFIQvRUh6goNdstTHhLMK/2gZAJ/yh0uuF3uZaiI9HCYqYF+oKVSZ6C0fizQIo9ngb74SGUBVSYbEmKc3xu/6E9eHz8EkZoN2uSTkcVoZKwktaZPypIXeY/x/tcUDaNp26HDPJeasKBRZY5dUyBuq0RIcnNPordPlGjRvqY3sCFHvjGqu1uivtkvfNj7dHuTjEs5632Tnd+ly0xcyYHX2V/4vuA3VXs37CrmscAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[18.5424194335938,259.860809326172,1],[35.8757553100586,259.860809326172,1],[35.8757553100586,267.527465820312,1],[18.5424194335938,267.527465820312,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,263.694152832031,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;202&#34;:{&#34;id&#34;:202,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.59999990463257,-3.59999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACYklEQVRIx93VT2jXdRzH8cd+zPVzi3VJZO7goNEsihBE2pbMHRaL+koH6ZLuUB1ceRh6EToEMvCmHkQSiimIwzqM8aFDKUQbzaZ1U7BgFsjWShTcmPvzm7PD97uf+26/3+9LV9+n7/fzfr2fz+/nwxc+PGtV9fQxOuCQN+TcMehUmC83EtU77H0t8v4x6nS4keqWoRRF0Vm9WLYsj5s6woOSmmZXNKHgsTxWHA2nsym5JHBIr2WHPa/Wu6a95kJJTbVhTSbtU6fO667KORm9nU2pgqjGHY2+CMeTgV2uq9IexjaIPnDZE23hl+R9k3E7jYSOLEq8o0ijguIBhF99j54SW3oHP69qCAVfoy3KZVFiUSeuh5k1wKvoLiEa8ZVvUit/o1pNFqUavIrbqfE/sD2qC3NpTxgwsE7djqmwkEWJd7QNd1ORKdAgo6IGn2AomxKL6pH+9kfF9UqaTS6pN+tENiVXPMClVGRxzcGW01QbtBcfh8lsSoyaR00q8hwbxtKavMv2oS98myxVpMSiWWxORWrBTFnNFsNarfg0nCsuVqTER3cXjalII56YLqN5yZhW8/av0WRQYtEttKQiL+Ov8KikZqdrmt3TGYZSjYqUWPQj3ozq1kS68FNJzSt+sMWE1jC+rlWREouuuC/vSBG2Wxe+LKGpNeRFf9oTJjY0K1KSayL6zBkrjjljQbcBW30X3kt6vdothY8g6vc5+vy2TjIeCpUpq6Kc8w7isUJyk7wVHia9iz60GPJENf71Qsn/oyFMV6Yk91FYCT0OGDUn53f92lYDqdpRRuN/UZ6R+g/uN+qDVrSbFAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMHwEzgwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDANWXawAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[18.5424194335938,331.244659423828,1],[35.8757553100586,331.244659423828,1],[35.8757553100586,338.911315917969,1],[18.5424194335938,338.911315917969,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,335.078002929688,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;203&#34;:{&#34;id&#34;:203,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-3.70000004768372,-3.70000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAQAAADuSaT4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAADD0lEQVRIx93VX2iWZRjH8Y9jvr1ztShaNkdtYLgsZQoSuiXqgbXQewRKHWQW1cFGFpYdBFJBGBKZrRCpg5hBZFIoemNgmpEjcctAKssELRj+749/0k33r4O977v32d6tc+/n5OF3/Z7re1/Xxf3cXG9r3NBrWKZJrSLHbfZu7Brtk1BmhUfUSDujTUv8Pi92SO0w+zvx5QQobNSMXr3S+Nm8+HdBzN12q0aPPmn0WxVbMrHx/pUqDCrKWJo067XCjSZY5LRpPi6IKbZdtRMalSo13R5F1ocHM+H7pAyYb07e835e60LKcZVej29k0s3SYZz6uH8E6FFbDKiLB3I1tJtpX5wH4SmtjsaaQlscrCio1KMlK8aDdmF5Af/D+C6LIfb4CHVhME8tfig82WKwAB3xYp6+R4OGAv59ev2YUE6hWEo3ZuDgWKB7cSShH0VVKI2Xk/bYqnVYhnqcjN25ik6F9Rrd6bw264ZqHyx5EjoTn58EFf5nhQrPYhuEKrdgkxdNlnK7JfaHVUlQGZJ7v5LTx8KM96kyl6wl0zjOeNJd7rDEr8ZZF5bmt64Y1xI5ruZFR8MU22w+noknwIA2JRbFs2Br+FqHKd4OW2N/NlUXww7aDYyAJzFpWzRiZfw8M78ddiTmeSG85jPVZunItu4SShJ5JoCLo2LK7dWoX1N8b4yi94KaoRl1ojJhqcSA06NgJttvji5L44djDvE8SA9N4bAGyfM8BX/EKwUxM+1S7pwQ2xP6Y6ocjjvzpIkYPGmZir7B7FCaZ1mIbwtipvpKuWPmJDF4wVtWJ5SH0OfAEGi3v6S9lEt2v4X4oABmgm1u87u58diIYMTssCDnvdWr+CL+Se6aCM/ZoN8rNujWoNVEO+PiTKxZvWvxaQhrrMbKEX+09tgTbnLEJOc8b3vsDnNtNM0/amNnPqjIJk+gT0/mPnogXsjEPvG4qzFNSDnr5oJjr4inCTN8qQJ9rinBOYtjx6Ahcx/F/rjcMm0uK/KbNeqymMS6ZxRMtneHTPemn1w14BdrTc1irsf1Hxfi8Eeas9e/AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[18.5424194335938,402.628509521484,1],[35.8757553100586,402.628509521484,1],[35.8757553100586,410.295166015625,1],[18.5424194335938,410.295166015625,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[27.2090873718262,406.461853027344,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;204&#34;:{&#34;id&#34;:204,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.79999995231628,-3.79999995231628]},&#34;vertices&#34;:[[37.8615455627441,48.8652801513672,0],[40.6012725830078,48.8652801513672,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,48.8652801513672,0],[40.6012725830078,48.8652801513672,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;205&#34;:{&#34;id&#34;:205,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-3.90000009536743,-3.90000009536743]},&#34;vertices&#34;:[[37.8615455627441,120.249137878418,0],[40.6012725830078,120.249137878418,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,120.249137878418,0],[40.6012725830078,120.249137878418,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;206&#34;:{&#34;id&#34;:206,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4,-4]},&#34;vertices&#34;:[[37.8615455627441,191.632995605469,0],[40.6012725830078,191.632995605469,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,191.632995605469,0],[40.6012725830078,191.632995605469,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;207&#34;:{&#34;id&#34;:207,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.09999990463257,-4.09999990463257]},&#34;vertices&#34;:[[37.8615455627441,263.016845703125,0],[40.6012725830078,263.016845703125,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,263.016845703125,0],[40.6012725830078,263.016845703125,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;208&#34;:{&#34;id&#34;:208,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.19999980926514,-4.19999980926514]},&#34;vertices&#34;:[[37.8615455627441,334.400695800781,0],[40.6012725830078,334.400695800781,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,334.400695800781,0],[40.6012725830078,334.400695800781,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;209&#34;:{&#34;id&#34;:209,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.30000019073486,-4.30000019073486]},&#34;vertices&#34;:[[37.8615455627441,405.784576416016,0],[40.6012725830078,405.784576416016,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[37.8615455627441,405.784576416016,0],[40.6012725830078,405.784576416016,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;210&#34;:{&#34;id&#34;:210,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.40000009536743,-4.40000009536743]},&#34;vertices&#34;:[[53.9440689086914,28.9927940368652,0],[53.9440689086914,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[53.9440689086914,28.9927940368652,0],[53.9440689086914,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;211&#34;:{&#34;id&#34;:211,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.5,-4.5]},&#34;vertices&#34;:[[140.026641845703,28.9927940368652,0],[140.026641845703,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[140.026641845703,28.9927940368652,0],[140.026641845703,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;212&#34;:{&#34;id&#34;:212,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.59999990463257,-4.59999990463257]},&#34;vertices&#34;:[[226.10920715332,28.9927940368652,0],[226.10920715332,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[226.10920715332,28.9927940368652,0],[226.10920715332,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;213&#34;:{&#34;id&#34;:213,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.69999980926514,-4.69999980926514]},&#34;vertices&#34;:[[312.191772460938,28.9927940368652,0],[312.191772460938,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[312.191772460938,28.9927940368652,0],[312.191772460938,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;214&#34;:{&#34;id&#34;:214,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.80000019073486,-4.80000019073486]},&#34;vertices&#34;:[[398.274353027344,28.9927940368652,0],[398.274353027344,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[398.274353027344,28.9927940368652,0],[398.274353027344,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;215&#34;:{&#34;id&#34;:215,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-4.90000009536743,-4.90000009536743]},&#34;vertices&#34;:[[484.356903076172,28.9927940368652,0],[484.356903076172,31.7325210571289,0]],&#34;colors&#34;:[[0.200000002980232,0.200000002980232,0.200000002980232,1]],&#34;centers&#34;:[[484.356903076172,28.9927940368652,0],[484.356903076172,31.7325210571289,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;216&#34;:{&#34;id&#34;:216,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5,-5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAXCAQAAAC2NjfhAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAABiklEQVQ4y8XTzUtUYRTH8c9cBjOzoDZSsxAhCkKIoExy1UIQ6oH2iUErg1b9A0bUpk0tpNpZCNU2ngx6oYggamgVFb1hgRBuWqQ4moW1GGeae2dsZlVndX/f536fc+Dcy/+qXDqG7V66F49k6LBRuyWm3XAhLlZ4knqp03Xrs/eHSyYNaJfodU4xbGkgh81u21enjjrhp5M6dThkVq9rdWOHPjf1gFt/xg5tphWMxTOrea+inIH4tNo5bAxXPdPjk4fZxgp+uFiJ8YW7GKkdu9sxTNjjQ0Y+iGKcqyEPMFQrr5iyPx6P3+q2sQtvU+Q9usMGyEN84/Aaq9yGmRT5Arb6mFlVg9qEhRQpVXlTOY/lFPle5U3lRbSlyDoqFzaT58l8cx1grhV5BoUUKeCX2Vbk19iZIjvwOZZakR+hv7zV1RrE4/JjM/m+r9qdqsTQZxBXyin/dzcuhzHjTocl45YMmZAzFZ+31pnLJiXOm1dyR5dXjlaOmspxJY4Y9sSCxDtnHWjwB/zz+g1Bk2E+Ym50GAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMHwEzgwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDANWXawAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[49.0499267578125,20.4889049530029,1],[59.0499267578125,20.4889049530029,1],[59.0499267578125,28.1555709838867,1],[49.0499267578125,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[54.0499267578125,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;217&#34;:{&#34;id&#34;:217,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.09999990463257,-5.09999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAXCAQAAAC2NjfhAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAABgElEQVQ4y8XRMUjUYRgG8N+FiUINBVFLXUEUUnEGJRE02FIgXwQFbjm2NeVY0BANaUsEbW1yQSj64RIUqENyFUhRDQ4GgUcaZBSBQV6DZP/7/++6/xI92/u+z/O9z/O9/C8U6suw3yuP4/m63pxSSjUcr8KmOtoWIzpTz23W1WxzW4K2zZjjGcYh7Wp6rSZ6iylx6FG2r8Hz3ZiPU003h63uuqRgwYLTKUYJLxvbXs9cNIAHjppvuPnF3zKvmXQjPidkGSVUwx3n7LZixlCc/T1Kn+q+y8b/nCoUvccP7RuUmsE4nLTdHN3gowF77HLBOwVD4WLmVA1RM6NTX1wCo+GJigNuh9G41lIcJ0zU1V/CdWV7HVNpbTuLp+BgnsxZrICOHJlDv6I3cTLR2gmqeT7sipOeSYrP4KfZPLYjToTeDSfbXcOj+CmP+J5FBQ9Df+ggnDKl6LPB9WELcfyqT9UOZd/Cd9MOW3Y2fsglJs454qbXVtW8dUtXrOS4yT/GL6AKY5iyp+HGAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[135.13249206543,20.4889049530029,1],[145.13249206543,20.4889049530029,1],[145.13249206543,28.1555709838867,1],[135.13249206543,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[140.13249206543,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;218&#34;:{&#34;id&#34;:218,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.19999980926514,-5.19999980926514],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAXCAQAAADADIVqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACFUlEQVQ4y83US4jNURwH8M/crnHNaGxMGrOgTAaRlGQGYTEacSYLWWHDwmshNspCSdlhIbHQsCFZTDpZeJSMPGawEYXyKA2DKDRmuPOwuI+5/ztjzW91zvf1P7/f6fz511Uxugw19tigUcZHd5yID0uFYbMdFkp57aLjsX9MQGhww0xkDclg2P54osieshODBmXw1Mr4Ncek8oK0K2bq0aZatQVuSjkW1uTZHXYatMdkVdbpNd/5shOETS4Z0Rwf5PcTdFmkM64kVHqt3qF4OM8t1q3Csniv5ATW4m7BTsw6i+aQQlAvq9hOfOQatuZ26TzaadCTxHg/IK3SgNXojt9LuJtatSYCYrv2svtZhvdxAPPwPMG9xIxQHftGWyirUGc7OsB0vEvQ70Fd6QyS9gkuqPHDUVCDvoTgZxEfLyCkXbQK22JPsc3fCcmv0fbTY+wZl7Rhb7ych/pRmRBNpBBaFhBqXdFk2K54pgj+wKSErAp8H9NCmOWeJv02lthzA6xPBNRjRG9ZQFjkvgafrY4dCfkzNCaQ2XgbfyYCwlzX1XqlKXaVjeUWlobqEqQFt3PLwmOq0mGqN1bEV2Ou5YYvMvYVP7VEC07ndoXHdMRB7PW4zNwVs4TdThp2wEkDWrWb5mpcXxIQKn0yxXhVF3sJKedswZBs/n+wPH4rbWHOX+z5isNxq83u6JPywhHNBfv/UH8AWrGY8GPlvd0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDB8BM4MAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwDVl2sAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[221.215072631836,20.4889049530029,1],[231.881729125977,20.4889049530029,1],[231.881729125977,28.1555709838867,1],[221.215072631836,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[226.548400878906,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;219&#34;:{&#34;id&#34;:219,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.30000019073486,-5.30000019073486],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAXCAQAAADADIVqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACAElEQVQ4y83SP0gVUBgF8J+hokFGYZSFFSiVVpiDFIFDEEh/rkRKgQ2tBRUSNklb0aL9GWprjaIg4lKYQ1ARqRXYPxMiCiLLjBIaUkttePp8T3011jdd7vnOued83+VfV9bUMRQ4ZJfV8vS772x8lIJ1q5jGbI1NMCfZUuqpk6rkG1OsQUdoTGI5yjI5yJ5oyXbDSh8c1GZUuTO2Oh16YjtYK9e4LYZTmH1pAnYrN64+doAXYbtOlZolBDbgdbw7m4PJCNvwYIKO+NNFbA4JvAJP/hjBPb88S0M+IluuoQkHj/+6hfQKrY7qi8sgfLVAgyq1ig26r2XKawaBUKRXgfPxEGGFdxiRm4THHYut6TNIp+e4pMB3p5IjpN9+yy1R55UsLaE+o4OQ7bI67IlXIdRqkm9H/DyBz9dllXdK4tgsAiHPFbVojOcyzmevy9gYu2ZECIvcUWvMgcx03AGrU9eYoJdoU+qHffG6P9UgyJsmECrdtsiAEDunGV7hZbyZcrUYiZ8yJRDKtCv0Rk18M+29IzZ7KFWgBqM6UtYY5rqu0FvVM+hEbApbkk8tdBzX4peUNYYTmtE448d3xp9hnl5LDTjsRhwK1S5Y55uK+D4pEHJ9Nn/WcRXFT4QNbinCqBH5GLAzdiUaEhHWZKBPZui23knPDRvX45SySfr/UL8BDbKXqC6YR1IAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDB8BM4MAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwDVl2sAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[307.297637939453,20.4889049530029,1],[317.964294433594,20.4889049530029,1],[317.964294433594,28.1555709838867,1],[307.297637939453,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[312.630981445312,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;220&#34;:{&#34;id&#34;:220,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.40000009536743,-5.40000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAXCAQAAABZ9FzfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACRElEQVQ4y8XTTWidRRTG8V9umphPKSld2EvtwtiXlNBQlFCIUEspRmU2YkDQZNGFNNCFJCKFLgpuXLio3YSAKE0QtLRQyqgoiuKiBRtFUCPhGkrEENNFlDYmIZ/t4r73zX0LXWdWM/M8/3NmzsxhJ0dNZRJaDXvVU1b8YczHcbPaFt5wWpeC2z51Ia48hIf9vtOOVQV1uKE3/p/BIwaxYUMDfncs/ltWChBqXNHuH0GLZn3+02Mkg08btOGMFk1eNq/TWC57eMFXeD7+kAKv+8SWA3GWUO+2ovPx3VR71i01euLNLLsTmKzAiCg4UvYrWvdBJv3kawxUHT6+o6ivqlK1YBUcx614r0r9Fr3l6a405py5KsObWPQjOISp3GuVcCA0x6UMz8rUpMOgUxiOd8E+/J0zlRM9YfohPHSnGdf1x8vp5uNYyuHL2X5ausp40pTfrKrzYThr+3prOdfq9rVzeLwaO+Jhe1zU6r0wBFZQn8MfoxIyn70cZCm+ZRznQgMW0ZgzNIF7j8DBR2jTnpatmNOKuG8+u0E46qDJ+HOVZQHswaReSQ4/iJm4vJ39gjFv5yydYAbf42hortJOIv2hZfxzvBKezh6w0TlMxL/wjQUNhqoe9yRGy6taSH41YLeQ/JnMlLZCt888Y81rpVlKm8mSlxxLVpJfks3kRZe1+CK+X8Yr/d7lS/uwYV0jFvXH66lWcEk/Nq2n/f5c+iPT5lC6k1yyps1uTBvXHycqxy3dL11Lpu3Vps60UadyDbSD4wHTTqqeCu7GogAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMHwEzgwAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDANWXawAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[393.380187988281,20.4889049530029,1],[403.713531494141,20.4889049530029,1],[403.713531494141,28.1555709838867,1],[393.380187988281,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[398.546875,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;221&#34;:{&#34;id&#34;:221,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.5,-5.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAXCAQAAABZ9FzfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAACKElEQVQ4y83SS4iOYRgG4OsfjBmnGAtns3D4k8OMzRikSFHyUg6NSShqygblsCBZ2TksHBZOIQtioxfJQk3kTDZj6h8LSjOEiCYZprH4v/nnMzNsuVfv+z33/b33/TwP/xKZzkMYbLtVJvjmhXPOxPYuUniuopvuYNwBRQlhnGf2mSpjkLlOqA+DCuJ+pvzp9b4QMi6bqEWdmzKWO2Gu49YnnKmKdVjge0rXnJJbZBZqYz24Evq7YG3YHd+ASjQltW7Im1+IhhQhosjM5FaBp72bL4K4yxirU1/7QMFsJZ78JTuxuTMNqMNXD1Ovt4RDlhnnszsOxAc9Bpd0eYApNtsooy6ehFDuFdoUF0gddsaD6eyd4iqtntjkpzV5cWKddzYYb6SVGmUcCKvSKRNkZ5uhxVDFFmc7cnchmzXWe/PjvdyXXGuuMXvBCsNVZY/kOnqYhzDQfluxPR7qrV2hxkXMio+6mU/a2Bq3OY89oaTXdt/OW+2RPYXTKDOx19pnUFIYXKg2WUNMr8ZHMJxQo1xDvJ6qjQAtXXM/rNpFtSnKNPAKW8xxX1q+GO0edJm/hhVhUqE5pfbgcXwtv8DVYUGhVmYvrsQPXfKjmhW7FZaEfoQqt03XZis4plnGpVATSgjz1Cv3yc78z5LBhQo3jMZPP5Tiq3XxalKrdMMotGtTiveWxke/rU3uXfasNmWG4qXz1sXHnXZzb7Nn/TDMEDQ5ZW186b/AL7cGn0cgBQrWAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[479.462768554688,20.4889049530029,1],[489.796112060547,20.4889049530029,1],[489.796112060547,28.1555709838867,1],[479.462768554688,28.1555709838867,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[484.629455566406,24.3222370147705,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;222&#34;:{&#34;id&#34;:222,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.59999990463257,-5.59999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAdCAQAAACwcKJ8AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAADA0lEQVRIx+3WTWhdRRgG4CcxWr1JvbG2SPwpKmoE66KW4kpwY/3JQu1GoUoFRRB0pYgW1IsKdqEgBg10o2JAUVSo0ktFCwaRhv5Q2zS2pVqbBptqapuUNM3NNePint6eOfcaUpO66ns2Z9753pn3mzPzneE8oE/wA1o8a5sRx2z1jHmg0WN6HDXuZ2styKh2oM2b9hk3arPnNNeM3uhR3xg2YcCHlmGtILgha6DdHiH1bJKTtzHiftWWMbDcUBRxwI3R9Hk9UX/Z8/UN9NkvOGmDbruT4JcVE+59WxLu00g1aEjwu9esVnBQEBxxXTXmEtsFwYTPFHQmEQfqGQiCjRaCBm8JgilBTzXnx5MMWjOqTVWmRVEQfFkduZCs281Je56u6lrUGBhwcZVpdjzJpvVMmF5BcGekOuTSVMR8g4JgGVhgTHCqOn0F69MGGlMdnU5V38f0gW7HUxHbwaJouDeMplondIIHQYccPrInUrwQ79Az2ByFDYEtETeSLGMaX4hRBHeB+5KMY/TbW9/AYBRWBsN1uNjmUIapZLsYkq+8u0a1s76BMbUomx5Ha5iSk1ikEVeAY9Op0gamnD3+rsM1oWyKainLoqG+gf+C1hqm2UVO76C/wGXTqWZr4BotGeZW8AvoB7fUqFLMbA00uCfD3A++At+DjkzEtXNpgBc1pVpXegrl5HB+rIRVro8UhbncA9ymWy55X6woj7cNgD91ImdDtexe4FWr0/KmGU/0b5j0kDt87oh2KzXjJ4VUtndbot0u6/XL63CTYFxOdOoqVX1hNPAnUd2v4HVB8EikethI9Lstmh9p2myN+kuetE0QXDU3n+BbS7zrNyXDvrbSvU5E/Yfd7gnf+UPJoA8stc6FqF/4zgr11m1mOCiYqLzOfg9Mh6VW2KvX4Yi93NWkf0jnbgVWZO5QFbwkCN77PwzklQSTHkhxq0wKSknFPMcGJFe7oNc7XtFlZ9JeM/vpZ2agybroEFYuqE/PxfQzPwXLddllVMkhP1pTOf/ncRr/AJ1xUxEs3XOoAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[252.425491333008,7.91255760192871,1],[273.758819580078,7.91255760192871,1],[273.758819580078,17.5792236328125,1],[252.425491333008,17.5792236328125,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[263.092163085938,12.7458906173706,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;223&#34;:{&#34;id&#34;:223,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.69999980926514,-5.69999980926514],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGsAAAAkCAQAAAAkuAw+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAAFDElEQVRYw+3Ya4xdVRUH8N90al/WQosNmIbKQyGiILGCVfGRSBGJA4NRQCS+Er9gKYloREUxgkJkUkjTGohRRFuLGlqgItU6tsaGtiTGqYyifWiJraUyTOnU0pnpDMsPd/fO2efe0jt0kqlN/+fDPWvttdZe/3v2Xnudw3Ecx8jjVSMXqkvoHQUKHUI4pUDpK+YPJ8CYUUh6uDhDh++YdKzROsc5w3UZO9o518VdpqPnlQc4OmktOdIA/w+L8AjR7DPadeu11T1OVb8SnqXNRrvt94yfu7I02imsx3hzrfWc/bb6vreWrMa42kP+pc8emz2gpTQ+VAnniuy63WVCeKpO/luE/abkypOszwLsdnENrSa3OVCaaK3X1dA6zcbMZtBNBZvp1pVihLWmNUir2bNCeEuJ1Gwh/CxXTva0EF601K0W2SHs1Vui9YMUfI1v+5of6RbCNtMzWp06hT7tfuhxfcnnvVWb1UL4t/t81W2WGxDCqrq0TtfqdiGs1KrVm3B3IphjgRDl536nEP7uzCRPsjilM0TrU0LYVUhwqoeF8GhGK4R2pybNzKRbnuSLhLDBq6s+s/QI4cI6tODDQri3Ovo2IWzJ8q88w668F5mWnstZ2fp/IqPV7Blh0DuycONsFsKsjNbm7PB8lxD2JOkLQrgui3KrMGBug7QOznJBQXOJEBYNJQ+XGo9f2FQwfMk3s6nnmIkVNmTafm3g2kx7nxcL0jo9mGIiGADvzOwXONtECzWKn4CPFzSfAItzWnPAypJzu30FqbL0VtdMsR68O9M9kUnhP2AC+AO43jKXVxfibpscaJgUS7yEq6rH0wSt2GpdTuv14OmS86C/FqRKA3NPTQ3rADMzzx2lSPsKc/3JUnClR3Rb7cs1Ne3w2G4NZnhPkltMkR3ilalOBi/UuHcV7qe+7ET56L66Nk3p97MWGATjvN+dnrLJzcNrZf0YXJOkyhZYPDRcaZ7iEM79ypaLbKtrOTCMlHrdqM01rjBbM3ijO3zO+2xvOMZDvmeSj7rBgBN9CE/aXDZqF8Lba5xXFyrhL4XwkcNMV6lRry1pO+pqmaLFAtvScv51yf7QlRCWCGEOPi2EG4qDlUVYeQLn1kx7duH+H5AV1QrGOqHh/7iMHivMc3pK6ZK0GRpDpRq24HIMeLCW1q/AFSXH87K2qFLBrkrLZgjXekG3+xtOZ6ENns/+irAwlasZdT3qb5FVnkWLcS7GbzxXS+txe9Fidub4jUx6zPM4w7xMO8nXMVVnw7Te4ELTfCzTjXESaitoBQfLS1n7U5zm814jKxdF3CiEndX91eyOmubpi0I44PpqTZtmRfKbnDSH31tXC6HHRdXRJneldje3P7i3Kl3KX9K5N4TzU/cS9h6qjo6xKiW9zC2+629Cn20ZrSaPJKqd2tzifnuE0O8DVZvD02qyJkX5nfluNj/57C+0ZTmtU5L9Tn/0rSzun9PIA4deHOMtzY7ZPtdZWergx1posHQc7/LBgkUjlXBqldjQtdOlNfZDX56WV+1WZXG/lLRzvCwu87Bd+m232PnU0II3u9tG3Q7ossZNTsxGGyvwTVo9aIt9+u3wW/NKL39lWhO1+ac+PR7L7GakV5xj7B1/lhCp2T6GUHmhPPfIAx1NmKxLeHK00xgpTDAW0z0qhE+OdjojhQv02pUqcsdR+qXzFeDkarnvdt5oJzOS+L3/6rJs+N/mj+NoxP8A5NBL9k+MxaYAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDArMTA6MDB8BM4MAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwDVl2sAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[13.3695888519287,202.766342163086,1],[13.3695888519287,238.433013916016,1],[1.36958873271942,238.433013916016,1],[1.36958873271942,202.766342163086,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[7.36958885192871,220.599670410156,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;224&#34;:{&#34;id&#34;:224,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-5.80000019073486,-5.80000019073486]},&#34;vertices&#34;:[[496.607055664062,180.892059326172,0],[570.520568847656,180.892059326172,0],[570.520568847656,259.49365234375,0],[496.607055664062,259.49365234375,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[533.563842773438,220.192855834961,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;225&#34;:{&#34;id&#34;:225,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-5.90000009536743,-5.90000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAL8AAAAkCAQAAAByQiMNAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQAw2m0oAAAIGUlEQVRo3u3ae7DVVRUH8M/lIRdBQoxR8YkP0EpNUNHGd0plSpexMrWyB+M0PidnKLMhFR0tdXBkfBuOjxTUUZQkbeyB76Bx0kB8XSMEJAxQLsi9XC6s/vj9zrnn/M659/yww6DF9/y192/ttdbvu9fee+31O2zFVmzFJxG9t7QDnwQcb4Yl2rWY56C6ae3tZybV2dN7hIl11LdYCL3S1hPCeXX2uCZOt0EUf7vUSeteXhVuraunpwpL9KujxnL697feWsPr6nNOF9q95Fmz66b1ZFFn+gdaJvxgM7x7r2L7FuE5DXW10S0GCWGtYXXWW3/6bxRe07OuXmbp39la4aw6c9ENdhfCnLrrrTf9w3QI366zl1n6uUFYorHQ7FF3YsqR6F+7ma3895igpxUe3Ox2bsYQZ1d71NM33eV1K6233Fw3GZmR6OE0D1tknVXecrdTujX1aMmRm/x2ym0JDnaz+dZq809THV/sPy+j9cqSMYe41XyrtVpgqqaMxmZhFk72slbvmOYzYDcdwvWb4MNJQphbZUSz0GoAqkU/zwsLK8N+hDcr6Iqy1G6wFyueP2fQJtNf2xKNplRI3JPm+V3Rv517K8Y8X5ZrJfSPLsnF9gMThXB4xv/ufOjpX0L4XGbM4UJ4IG1Vo/98IbKBO0yLEBa5wy9c5m7LU4NnFGX+LIR33eYSV5iuQwhPdUn/KE3OFsI8TZo06ZPTUg9PFKf3KhPNTFt3g6GaXCmEJzVpsj/o45lU6hm/NNFj1glhcckENAtzLCqSOS/tXyAsz0Rk9z5wfcXKg8ll5Fajf5gQHqoWqffbptjTz3QhPJu2jxTC7JK8eGRK5GG6xp4iXfD5LRUiZLWTiz0naBPCsWm78uidJIQVJRvEcPPT6SilP1kTR9vD2HTCD6xGSE0fRgihuWxMsiaWF2/j1ejnHaGl5P0N0iGs1L9MbBchfJi2LhIVucGlQke3N7ks/XksJQ6GU8tkxqfTVp3+IVqFDY4sGzPECiF8uYz+hRnrFwphQhWSuvdhnhAOLXk+Wgg3FdvV6X9cCEdQyEx6G+8mV1hTJrbEcmybynRAMqiIyYbr60b5kcfSwXbDXA+XydxpvseL20UWYzXiMc+V9b7rOvD9st4pGeuHpGSWIo8P94LTS56fCX5Tg4Nk/GE1pOyexk6f1KFk4T5izCZczCs3n9qWkhi7qtsR2eh/qMrahH3S8ypBEv0nZGTmCJHmQAXk8WFXG4TFxTOj0arMdlQ9+s/qXCPZR4MNs4+9fdYIe6Z9ySX5b6Y6HWON1e4FT5rZZSzmQdeWdgOvbpK2oeCViv5mH+pnZ43ain1vZ2R2ByvL+vL4sNgsx9vFUZ4GpxiA+2r6urLEahE7usbCKglhFO9ojW5Is53C700X27ZbU9Wiv5alaUI4qVu92ehfoKuCXrKH75xORgjbZyRahci8Rx4fCnF8S9pKEoh9yyaoWvQfI0QyZYWFc6zXjU9nJCw0w08dYFnZsDYXGuonnrch7dnX1ebateZ8l6K2pV6bpC9BQ6qvEj0rnqzPSGyDyNzM8/nwsLX4ul4Y6CuY462ao5KTp0+nmSGmG4h57vCi+cUcpLFi6CLXutYAxzjRGHtgL1N8KTdNeSx9AAbm1gkr7YEdirt8AQ1prK/qZmyrfhr0LpuWfD6s8agzfNpxnkpvNbWO3c53baUQ/ecaiBeMNNlfi5T0Tq/OlQXSFr91gaHOB6PtmJumPJb+Ael9tBSXm+xC21XVmxx4B1b0D9MXS5OX7QItkNGb14ck+zkFY9BhWg4O+pdYReE+e2ZG7Kh0R07ynBvNtsKnMjLJxWZEl6aye38eS8cJ4S8ZmV5WCG3pdeWrmb3/AiEyaSJcUtaf7P39MzJJKaV86vL4AD0tFRbYRoswMyNffe//oRBuoBD9ScJXvtX0KH52S+5w+zjMIN/IyOwAlsiLPJaetQijSu6v8C2D8HvtkJ4+nTQ8YB2+lrmX7OQiqBGTb6CQOxWQx4fEj/uxp3NtJ9/WU7D0RmfHbUJ4peT0H+DBYj4yBJwmhJaSe2WDa9OaSCfGGWdcmrZRGf15LHGOEN4rKYKN8r6w0VFp+wtCeLVkIpMazL8dXezZ29w0xygkGNWj/0dCuCzTW9uHBJ8XwiphdUUWWD36Z2Z3jIPShHKhS33HOW7zgRDahXBASvaslKQ/meRik9JLd6tRJaoTic46SZb+PJZoSCtDGzzhMhPMSGuUnVXRnVJLS72Urp0+6Say0R9dYYKH0grN0pJgqE7/fkL4Xaa3tg8F/F15Ma57+hu8J7xfXuAbZ30mB2/38zS6v5fKbF+cgM7f0mI9JR/9+SzR2+02lklt9KuyJGB68Umh5trP1Ar/ZhW/MXRNP68Ja0qLYDl9SDA+fXpiLvqT1XJXVvQgUzRrtc4yz7jaUHyx7PVo0GSaZh9qt8QfXJBmLJtCfz5LJJ9O3rBGm7f92sEZS31dZ4F1WsoOvCPc7nWrtVvoAWMyZHVF/wQhjFaJ7n1IkBQM363y5bAa/UkycIKtKGKIduHOjzh6pBBpca825gpvbvaPvJ8w3COsqrIu8uD6snOreyRTdc6Wft2PG4brEM79CCP7Wy7/fznuEhZVqSb83+MOoXkT6k2NemGwGUL4bq4xu2oTxm3pV/04YrAVZblXLRyqzbI0GX0557TdLMzeuu9Xx1nCQn1zSu9YTEdXVqk1VcMw66yr45+M/+dwn3B5bumnrbHcI5nvZF1jpvDjLf2KW7EVHxf8B/fdilV+ega8AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAwKzEwOjAwfATODAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMCsxMDowMA1ZdrAAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[502.086517333984,244.907516479492,1],[565.753173828125,244.907516479492,1],[565.753173828125,256.907531738281,1],[502.086517333984,256.907531738281,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[533.919860839844,250.907516479492,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;226&#34;:{&#34;id&#34;:226,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6,-6]},&#34;vertices&#34;:[[502.086517333984,220.931518554688,0],[519.366516113281,220.931518554688,0],[519.366516113281,238.211517333984,0],[502.086517333984,238.211517333984,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[510.726531982422,229.571533203125,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;227&#34;:{&#34;id&#34;:227,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6.09999990463257,-6.09999990463257]},&#34;vertices&#34;:[[502.795166015625,221.640182495117,0],[518.657836914062,221.640182495117,0],[518.657836914062,237.502853393555,0],[502.795166015625,237.502853393555,0]],&#34;colors&#34;:[[0.894117653369904,0.10196078568697,0.109803922474384,1]],&#34;centers&#34;:[[510.726501464844,229.571517944336,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;228&#34;:{&#34;id&#34;:228,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6.19999980926514,-6.19999980926514]},&#34;vertices&#34;:[[502.086517333984,203.651519775391,0],[519.366516113281,203.651519775391,0],[519.366516113281,220.931518554688,0],[502.086517333984,220.931518554688,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[510.726531982422,212.291519165039,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;229&#34;:{&#34;id&#34;:229,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6.30000019073486,-6.30000019073486]},&#34;vertices&#34;:[[502.795166015625,204.36018371582,0],[518.657836914062,204.36018371582,0],[518.657836914062,220.222854614258,0],[502.795166015625,220.222854614258,0]],&#34;colors&#34;:[[0.215686276555061,0.494117647409439,0.721568644046783,1]],&#34;centers&#34;:[[510.726501464844,212.291519165039,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;230&#34;:{&#34;id&#34;:230,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6.40000009536743,-6.40000009536743]},&#34;vertices&#34;:[[502.086517333984,186.371520996094,0],[519.366516113281,186.371520996094,0],[519.366516113281,203.651519775391,0],[502.086517333984,203.651519775391,0]],&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[510.726531982422,195.011505126953,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;231&#34;:{&#34;id&#34;:231,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-6.5,-6.5]},&#34;vertices&#34;:[[502.795166015625,187.080184936523,0],[518.657836914062,187.080184936523,0],[518.657836914062,202.942855834961,0],[502.795166015625,202.942855834961,0]],&#34;colors&#34;:[[0.301960796117783,0.686274528503418,0.290196090936661,1]],&#34;centers&#34;:[[510.726501464844,195.011520385742,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;232&#34;:{&#34;id&#34;:232,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-6.59999990463257,-6.59999990463257],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAXCAQAAACsCtdvAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQFH3V2+AAAAwUlEQVQoz7WRMQrCQBBFn5ouKDYWNmLhEcRKvIOlkjqVF/AAYm0RSSkEwULEUvAKXsBKKy1iJ0QwSKwi2WSyVfzT7A5vZ3b+wH81J2KvRwZ8VKicQep46WwWWtIi0EMWI05sdFAbhxcWoQoZiXMFjxoTzukfJCtN6XPA0Q3eI+RBEwBXtsBkjYHNXXofQws6rNjpWg2JuFD93V1pLVuinOjKjgsqAdDAVLIzxhyxgRvv2EwfX4GeQMBVXkuOioOK0xfNATM9klQkHAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMSsxMDowMNpzxbgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDErMTA6MDCrLn0EAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[524.845947265625,226.415466308594,1],[530.845947265625,226.415466308594,1],[530.845947265625,234.082122802734,1],[524.845947265625,234.082122802734,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[527.845947265625,230.248809814453,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;233&#34;:{&#34;id&#34;:233,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-6.69999980926514,-6.69999980926514],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQFH3V2+AAABCklEQVQoz63RPSuGARQG4AulFBJ5TcpESRlkEUXKHzBJyeAfWIx2k68w+QdMymBA2UQysCik9BLylW/HIs/zvLE52zldw33O4b+rxaITL66t6f8NjHgTwq0QwkIh6PEpzMmh1qwQBtKgyIEwlZqsCBtp0inklWdyDetLkwlh/q8tikErdpQatevRpSVthfBUGLT9vUsI74ay5E44E2Y1q9FnT3jVniYfQhj/6SsdCauF5EJp5pDhXUUS9wFbXlNkEyUaE5LHfSbdNShLyD7qM6QanCdkHR2qUqQLl46TQc5T5kdlDoXp7GXGhDCpDk02hCu5LCky+X3XeyHc6P7tX72W5T07MqPBP9cXxIhg2lurlz4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDErMTA6MDDac8W4AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAxKzEwOjAwqy59BAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[524.845947265625,209.135467529297,1],[530.512634277344,209.135467529297,1],[530.512634277344,216.802124023438,1],[524.845947265625,216.802124023438,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[527.679321289062,212.968795776367,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;234&#34;:{&#34;id&#34;:234,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-6.80000019073486,-6.80000019073486],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAXCAQAAABHPWxsAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQFH3V2+AAABJUlEQVQoz63QPS+eYRQH8J+nRb1EGjRpJC2RCLpUhaiNxAcwNgZbhy4+gdFHMEhMZhsfQCJNaUJUIhZiIQYvKR6ShxvHwv3cN6uzXPnn+l1Xzjm8blWa8FdRyY5prS9Bnd9CuHUlhHPDz8mMcGlclQr9NoVTTVlQqyT8SvMnSTkXQLtqrKZk3x4+Z8l/MJiSD9qwm+9lQ7jww1t88UfYVZsnPY6FcONcuDOv5emq8Hj+8802KjWARNXzoYcdOfNTkxojNoQD7VnQrSTxPc31toSFLJkT5nO/jgr3PpZ7GcBKjiyjQkeZNONNjiTgXZkckOkE+sgvb0pI9Ka5YElYz75pdCicGFONTovCraH8Xr7aF8KdohCujXtR701aU3Rtz6wur1wPVnxafjI5U0UAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDErMTA6MDDac8W4AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAxKzEwOjAwqy59BAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[524.845947265625,191.85546875,1],[530.512634277344,191.85546875,1],[530.512634277344,199.522125244141,1],[524.845947265625,199.522125244141,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[527.679321289062,195.688781738281,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;235&#34;:{&#34;id&#34;:235,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-6.90000009536743,-6.90000009536743],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdoAAAApCAQAAAA4nCAnAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQFH3V2+AAAQ00lEQVR42u2de5xUxZXHv8NjgIHwMIg8hYCPgUAMwbciKAhCQBFRBBXxs58EoySumjWswaj5JNFEV1zkgxiMEZBdEEmWLGJ4GIwQRSRggEUcQAaQ95thhnkxtX/U6dt1763bfW/TPTOB/vUf3ffcc+tx6py6VadOVUMWWWSRRRZZZJFF5pBb0wXI4qxBjenSrSzlEBUo2ifhfB6ForCmCpoG5PIUr2Qg3WdQKA7JVXsUlRxiGUNrusL/hKh9WvYgCoWinouaHl26gdMoBsnVaBRlfDvZQ89KgdQ5YLQ38gWK1zOQst9oY5+f13Sl/+lQ+7TMZrTp0aXm7ECx0KCsRLGJRm62Oq6rnjxV0xKpRrzAJdWe50SuqulqZ5EBpEeXJnMhlfzYoDyKoivPudncRvsAOcBx7qcjTdld05I4S7CbprRnJCeBHO6t6eJkUUvRl/uA6Ww2aJ8yBxhPT5PRbbRXAjCZmeykCFXTtThLoChiN2/zMgCX13RxsjhDTCOHHHKoTGuq9ZgKnPJNoH7GaeryKjlxkttoOwCwtqalcpZiDQAX1HQxsqiVGEtX4Hfs89C3Mhe4iuFxktto8wA4XtPlP0txEoCv1XQxsqiFyGUiANMs914F4Jm4rbqNtj4Ap63JDmQ22ynlMJ/yY5olLEIzHmYRhZziBFuYyQhPPsPF/zbQ+vRcFIqtHmprnuR99lDGMTbze243BwwCt9fWhPZBfiVXw1AoegHwL1KW5gBMQKF4E+jIbA5ygo1MJt9IqT+z2EoJJ9jAr+kCtJQUWiZpGD2cahiuFVPILZnUo0pzPArFWwBcwRtspoQDrOYJWjg8vXidzZRwjDU8bdBTRTq1LF6HOQD0YBIbOEoxW3mTAdY06zKUN9lMEWXsYTW/5mofj9t7bNelnvLrGWsuj6NQHDN0YRQdgY/5Pwv3Sj4HuvNduxhOoVBc76O35X1j2UKh2EXvQGf8OA55uBUbXF7TXA47xuFFE4pRKJ42aPX5FaW+NP/hE2g0o3V/mgNxo23HbuPezfLc+bzneeoUj1jMyF6O3vJEWITNLazUo0ozZrS5TPbw7iQfqMvzVLnou/lW6Nr5kW4ti9dhDvX4Jac93Ito6uHOZ71FMxbT1sVlM1q/LumUCqw1XYdCMd2grEKh+EGAZP4dheI9+80KFMrXeB3Z5RSnRMxNcZKlFnHmMMXhrWQfRwyFM0blTJW+poGvDPcKfxeH0ogVTipVHKLEuSrlbtezYY32ahaykGOigAtZyEIaA3GjXWI0wWFpngvYYuQcV5lJIY32WpFKOITPLbzUo0kzZrRvW9RyO7m8YaF/KXKMjkxoWdxoX7OUVfGBa3zRwZDyYXZT6Vxt5TyDz220Qbr0uHBd4atpN7nT26H0EErHANn0lNa60H+rjjzqci9Tl0+E/r6YcyueNJraLc6fCLWA0TJ7a8O/SZVKuMzhu1r4bveVYhEKxUqjgf7k5DRG+sYe/Fb6zXKuMZ4Na7Qaa1B4F8S10e6R98Y8FnGUN6Qcy6Ucf6MPOcB5PMYJQwWSGW0vV2MnRpTcwks9mjS1whehUCxjEBfQjEFslue16c/leprRilF8JfQHQ9TOj8xoWawOR1EoVnEXbWhCDyY5b11T/+ajUBTzQ74OQD2u5S/C94LBZwuu8OtSazH6Sb66PifdW7zD0PpiGxrHWm0fCsWP/Lda+N5xAA8IdYZrxnC1o0CmOLvJu3oZTVxpXCpNusagFUiju9FSUhjnUEZIPis9M5w7hfNLQ3jpMlpN1zOOJtK/jRb6HOoa/D04ENpouwjf10mOKLlFkXoUaY538ppkKNiFMolSKB41Uugs9P8NUTs/MqVl8Tr8pyvl2Hgurn/NJVX3OnouH6FQHDAkEM5o4V15Abhn2jnsQKF41vf0dILxBxSKpf4b30KhOO0Z4KyTxvSEUjlFN8WpB0z7ZX5oYrBw93coT0m/5hb8D9ADtbhLY6MYgH+p5GlJc4xDSZ/Rfu5zaqxFD5TyPPTbQhttQ+nfLyM5ouQWRepRpDnekYV7bPCO0L0qNMfyTgyLTGlZrA7rfO25xpPud4Szg4dvBIpDrDbmtWGN9i7h6+ei9hHqRQ6lsbyTH0kgn2dl1FMX3N5jnfhaig1aFwlXnupzoLzOAQ+lAaMAmMYxX6aL2AFgzDhmoYA8bnXxjQZgIUfl+mK+CcAU9vvSfEHyGU368XuqXNf5Mml4iRIP5wLWhUyzlI0AhkoFIUpuUaSemjSneObhn8n37zx8XwCk5EHOnJbFMN3TnrACwOj6Tsj3SA/fAprRkivZE7lWC6wS1W/yj43Vke/IaGpDgrTWA9CEbmAabRsZ7LgHrLHJ8iJfMpW+gdDlMqBcbs32I1d6UCjzVtP50YHrAJjlUG6S73mWFEsktPq6ULPEaPjIc32jfP+Phfed0KnqpYfHaJeEL0puUaSemjRXea6PyPdqD12rvd+1mByZ0zI33YQ2wviiy3YJ2/0NM+hjyKDCMeeoKBNbGm7IpAEjAJhp8MWiljcnSCs2370YkMJdy5U8TntgE1NczF0BKJde1I3PPNcxB9YMKizcuk/rbFBm0hsYSAvnvTqKHOCw0XiXAlDC59aqrOFeoAlt2ZmiYIOwyXOtlzIOWvvbv4dO9WVG0YO2rOZFPrEoUiq5RZF6atLc4eGLvbO870D7+n4YZFLL7HWAUgDDY3CaXzIVyGEMYzjOcpaymG0p10mXcRzQnMH8UShDaE7cnDU6yfeRBCkdMXm10f5JnCNLuEcqE0NrAI5aG8SrUrGhhsUx7SCPhk4Ob/MKDclluDPQ0gOJOUZz6HLt9w1uNPY5XOk1WuUbeultiges3PsIi1P04y0G0JaXOJwgGCNKblGknpo0gyLkSkkXMqllGv63pT+y/lXaM0HGns0YxjCggD8yO+HANRE+poBLgNGO0erBcXz6B8hyUnlCecbaoAW457SLGGZxngABAQFeQSSOX3GnqJ9fACBzFMgXF80sg1svShQHpBWj55FelPjUOi+BHIoJj4MMce2XtCNKblGknpo0K8g0MqllGuFGAT/lGt5xGc8l/IT1zKdNijXTw+AhsjDVgsGAW8Nj8k48CC+jDEA7iU2jHcwa51UdQ2mc1Qfv7EULXdFQdkHYP8eMJ3Th+4ov8x4ACvjE4DiZIP94HG/yKKMznfUmKkeUcII2rGVIWnOLIvV0STPdyKyWRcFq7qQVI3id7QZ1OO+nGKKp3a0NxTU2klzgkGfurt/5ybqVqjivNtqLuIX1QDf+7Omj9gLQQqKS3TjPc30YgJzAuA4/FrMfqCuT87ulmib0WL5VQBRtzA1/0EW18TbhzKBHIPYdOueHTqU+S+gOrOcWw+V/ZrlFkXoq0qwOZFbLoqKI+XyPznTmQZaIsXR1bU0Pj53iMLsDQPR8jmfsorvSxKPFHLHLIogp+DEWcyPbgUv5votZO2Tq0d2SkDfONOZGuB4bzrP4FSv5bwBuBy7nIiAWoO7Ov7ErZD8OHaZd6mzX171VIwtnohlQGHwmdbAdwRNm3VVjLN2BQm5kccJ3QZTcokg9mjSrD5nVslSxndcYSF9ZdhuRYiozAOhPHk25AXB7jgGZ3zZOOBpsKsEdx8B8Kx0Rv7F7nSrmWL/dktAtnuuV0ivZ1k1z+IhT7BYjjUO/V2+gGXdJGoWu+yvk2yayPJkhrHJmoHro1NA30KpriQC1uSKC8aF824a24Y9r05KZnNBPGDW3KFKPJs3qQ6a1LAy+xzw2WhbDVogTqUPCp4N1aT4ngUbczEDqA5v51MPxJQB1Ei4ExsYV2zRrHB8A0Mtl8btEgcb5gu8G+frFYywBoJ8lfGAUl5JDW3Z56GvZCNRnkDSYtxfaJJ67hy2+1sfEKTHfocRCBvp5OB+wemqr8EogGP+Qt9+PfMdkXiX9Z3LUk5NBPkhrblGkHk2a1YdMa1kYdGME32SwJc6qHEi2RhCsS8X8AYDbpLud5eOIjR06E4xO8u3bNXS+BFi5B2UDheqe7XZ2AsQLDWpfoe2nhyuNfNm1UWoZ8D0h8aJ6j4bfNzhG0lzumZcOpRyFYp+xrTwW3ft317u2twSMe8MYdUj+YhdNhzGetIgtFq063bUzpJ2xFydZGOOFwhdmDhwltyhSjyLNWAigF/YjROFfJbdUkCktC6qD/05sC8tMz87iThxHoQxjs9Xfpksx3CTRywex79TJE9k/SjB0kOlRf7fQQArT00OfLfS19KMO0Iix7HeUp9DF+6pQTzBBHClNecjZOjXBUpy2xj7Hty334/tSCrhTmrQLL0u8ZhW3ubg/dcx2CC35GlcwlXJi+3bcRjtXeJ+lP8Mk5WCjxdl3s1T2oTTmfknXuxHAbrTdha8+YRA+tyhSjyLN6jTaTGlZeKPF2c27iGsk6CKPkexER+THOwhb/W26FJf5Dqcef7HWfaWnW/BDt9oC2y1tPtd6qI350Mm0iF2UoVBU8opFnA1Y4PBWsZ9dxq7EGZbTEQDZMalQAYshzaVSCkU5u5y9lopK30awPrJXw/35igEWo53g4ull0OxG29p4z51kr+RU5ZQuvqU60da8sPtpw+cWTerhpVm9RpsZLYtitJ3Y66RSwg7Xjlpze7qt/jZdiuMXzp2x1rr/zKKdJurKWPFh200tqD4+ekOmevb9FzFK9uwXenjrMFH2YJqfEp4IMFm4T3gOBPrPcpkkZTM/m6yzyds46OH7mG/IW84tlqZsM7juMYR/MqAc7Y0OJtbX38dD8jvut7QbrR6AhV8FDZtbVKmHlWb1Gm1mtCyK0cLFcoKE+7PHcziArf42XTLT1fTigBPCYve7Y4c+PqHCPrHSm477Wh/swRQ2cYoiNvEi34AAcQK05BHepZBiStnLEp6gVYLGaizin5ywSTvyU/7Kbsoo4QtmMDTQhdScx/mQ/ZSxg4WMpB5YjRZa8jJbKOYU27gPSGa0AIOZxRZOUsQGnqMd+kBpt7Lajfa6pGmnllsqUg8jzeo2Wki/lkUzWshhINNZyxEqOE4B8xnrMzR7/f26ZGIdCsXswHrrzmJiwN0XUATuVNZT7pvIIgqeCVQrN65Hoc74rMuwuWVRe9BIXksDAjnuQaECNnLUEXfcgDjBhF5GDucoObdQjzu4LCCuSu9RKUiahpZreTXllkXtwa00AXaxLJBjLjuBfMvZj3Az7YD1stTlgz7/586armMtRB2ZbY3z3blATjZM/tdad6BQoTZ7pSO3LGoPlqEIOk41Bj3otoWF6DM57wh6UB9j9R81XcdaiU0oFOs87vz6LBQfZtekKegjbxYn5UtPblnUFtyN9tQnPvqgHgUoKnzruN2oQvkOHDDwC/HBjaK1NYL3XMaT4n5YxVCRTQP6O8sUif/ksBFtuV/mNU+HyeyMcsuiduB5HmI8/yVnQydvsyEoFK95qPNQVMmJLgK3g/wSNhoz2g4JVo7OPTTgb8b622HKOd/xH65gYIKlnPZGWF05+a5NX+nPrTbgVgnYDIcXU95IV7uxUU7kAjhIN+uBg27MYwQV5Es0MsC3WUsO0wKPMQdgvHFmfLI/lT7X0JS3LKt4FbyU5K8+zD+V/mHGc6sNmGYpefCnU00XN0N411hf7xPqiVbsRTmnXAB8gGKb758QfOjDexykMmu0VnTnOVZygDLK2MtyJobY19keRQUHeS/EOYxnnlttQNZoAb7PFkrZxUw5mysMbuI08f+4uhtFefbPUbPIIossssiievH/0aXDhm99LjMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDErMTA6MDDac8W4AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAxKzEwOjAwqy59BAAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[40.6012725830078,417.052398681641,1],[198.601272583008,417.052398681641,1],[198.601272583008,430.719055175781,1],[40.6012725830078,430.719055175781,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[119.601272583008,423.8857421875,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;158&#34;:{&#34;id&#34;:158,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0.32139378786087,0.342020124197006,0.88302218914032]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;155&#34;:{&#34;id&#34;:155,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;back&#34;:&#34;filled&#34;},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;157&#34;:{&#34;id&#34;:157,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;fog&#34;:false},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;159&#34;:{&#34;id&#34;:159,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;152&#34;:{&#34;id&#34;:152,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:1,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:152,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,1390.93444824219],&#34;modelMatrix&#34;:[[0.866025388240814,0,-0.5,-249.165313720703],[0,1,0,-216],[0.5,0,0.866025388240814,-1535.36743164062],[0,0,0,1]],&#34;projMatrix&#34;:[[3.49879765510559,0,0,0],[0,4.66506385803223,0,0],[0,0,-3.86370277404785,-5014.1572265625],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[0.866025388240814,0,-0.5,0],[0,1,0,0],[0.5,0,0.866025388240814,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:0.800000011920929,&#34;bbox&#34;:[0,576,0,432,0,1],&#34;windowRect&#34;:[0,0,576,432],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:false,&#34;fontname&#34;:&#34;NULL&#34;,&#34;maxClipPlanes&#34;:2147483647,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[159,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,158],&#34;subscenes&#34;:[],&#34;flags&#34;:17006},&#34;242&#34;:{&#34;id&#34;:242,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:242,&#34;sphereVerts&#34;:{&#34;reuse&#34;:&#34;rgl39345&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;div id=&#34;generating-the-logo-for-this-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Generating the logo for this package&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(dplyr)

hex_df &amp;lt;- tibble(
  rad = seq(0, 2*pi, pi/3),
  x   = sin(rad),
  y   = cos(rad)
)

p &amp;lt;- ggplot(hex_df) +
  geom_polygon(aes(x, y), fill = &amp;#39;#002366&amp;#39;, colour = &amp;#39;#436B9530&amp;#39;) +
  annotate(&amp;#39;text&amp;#39;, x = 0, y = 0, label = &amp;quot;/dev/out/\nrgl&amp;quot;, size = 20, color = &amp;#39;grey90&amp;#39;) +
  coord_fixed() +
  theme_minimal(25) + 
  theme(panel.grid = element_blank())

devoutrgl::rgldev(
  width       = 5.5,
  fov         = 30,
  view3d_args = list(-45, 0, zoom = 0.8)
)

p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;rgl88643&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl88643&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#FFFFFF&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;lines&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:true,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:243,&#34;objects&#34;:{&#34;253&#34;:{&#34;id&#34;:253,&#34;type&#34;:&#34;triangles&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[217.679718017578,109.50804901123,0],[99.6188125610352,313.995513916016,0],[99.6188125610352,177.670547485352,0],[217.679718017578,109.50804901123,0],[335.740600585938,177.670547485352,0],[335.740600585938,313.995513916016,0],[335.740600585938,313.995513916016,0],[217.679718017578,382.158020019531,0],[217.679718017578,109.50804901123,0],[217.679718017578,109.50804901123,0],[217.679718017578,382.158020019531,0],[99.6188125610352,313.995513916016,0]],&#34;colors&#34;:[[0,0.137254908680916,0.400000005960464,1]],&#34;centers&#34;:[[138.972442626953,200.391387939453,0],[296.386962890625,200.391357421875,0],[257.033325195312,268.553894042969,0],[178.326095581055,268.553894042969,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:2},&#34;254&#34;:{&#34;id&#34;:254,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;lwd&#34;:1.42263782024384,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;polygon_offset&#34;:[-0.100000001490116,-0.100000001490116]},&#34;vertices&#34;:[[217.679718017578,382.158020019531,0],[335.740600585938,313.995513916016,0],[335.740600585938,177.670547485352,0],[217.679718017578,109.50804901123,0],[99.6188125610352,177.670547485352,0],[99.6188125610352,313.995513916016,0],[217.679718017578,382.158020019531,0]],&#34;colors&#34;:[[0.26274511218071,0.419607847929001,0.584313750267029,1]],&#34;centers&#34;:[[217.679718017578,382.158020019531,0],[335.740600585938,313.995513916016,0],[335.740600585938,177.670547485352,0],[217.679718017578,109.50804901123,0],[99.6188125610352,177.670547485352,0],[99.6188125610352,313.995513916016,0],[217.679718017578,382.158020019531,0]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:16448},&#34;255&#34;:{&#34;id&#34;:255,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.200000002980232,-0.200000002980232],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAApIAAACCCAQAAABfyOBfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAkeUlEQVR42u2dd6BVxbWHP7p0VLCNUkQBCQgWEFFjQVAQe0PFiOYZn928GJNYosZnSYwao+apUSkWLBARRY2CIgqJGrEBNkAUlgo25AJS731/IHCBs2dmTznnXu98/yTemTMze/M760xba0EikUgkEolEIuFCrXBNyZmoggV3qC9L/ZiJmkHSYMIFvW6CGUnZjG9oWKDgO1qqVaV+CYmaQNJgwgWTbuoG6+mAgt3A+KohTxnInpriEWp2qUeY8KaKazBRRTHoJpyRPDTj78+W+g38wEDO0pS+QjKS1Z+qrsFE1cSgm9rF6iiRiE7SYMKF4hhJaUvHggXT1bxSv4FEzSBp8MeENJez/Fux6smom1AzySxb/M/iPGgikTT440FO5QPOLFJnRt2E2pNMC51EqUka/FEgXbiDnwLFmv8bdRPESEo9DipYsJRJRXrQRA0nafDHgDTlKi4IeJxs7tFCN2GGsw9NC/59olpevMdN1GiSBqs9chJ/Zrsid2qhmzBGMi10EqUmabBaI7twBweWoGML3cQ1kmnLPFEskgarLdKY3/NL6pWkcwvdBDCSsg27Fiz4WH1YksdO1DiSBqsvcjw3s32J+rbSTYiZ5KEZHuBpoZMoFkmD1RLpwO30LeEArHQTxkgWJgk0USySBqsh0pB3qV/SIVjpxvsyudTO+CVYwQslffxEjSFpsJpSp7Qm0lY3/h43Pdmi4N8nq8WlfAGJGkTSYMIFS934G8l0qpgoNUmDCRcsdRPPSKbdoESxSBpMuGCpG08jKVvQo2DB5+rtUr+BRM0gaTDhgr1ufGeS/TJaSAudRLFIGky4YK0bXyOZFjqJUpM0mHDBWjf+M8lClPN8qd9AosaQNJhwwVo3XkZSurNtwYLX1TelfgOJmkHSYMKFPLrxm0mmhU6i1CQNJlzIoZtkJBPVm6TBhAvFMZLSlN4FC77htVK/gUTNIGkw4UI+3fjMJPtkRIAbr8pL/RISNYSkwYQLuXTjYyTTQidRapIGEy7k0o2PkTwk4+/pEm+iWCQNJlzIpRtnIymdaFuw4B31WanfQKJmkDSYcCGvbtxnklm2OC10EsUiaTDhQk7duBvJFJ4qUWqSBhMu5NSNo5GUzdi/YMFiXin1G0jUDJIGEy7k141rjpv9aVjw7y+qFVEerCF70pWutGU7tqYRm1FBGYtYxCdMYxpvqxkx+g36DLXpQifa054daUUTGtOYBnzPYpawmE+ZxSxm8R/1ZalHWk0osgbXIM3Yg660pg2taUkjGtGICpawhCUsYg6zmc0s/qMWlvr1JDLIrRtXI1m0qxeyC8fRj54FsmFsyZZAN44AkLmMZSwvqFWhRxDgGXrSh33Zh+YFCpvQBIBu62q/zyReYpz6rtTjruIU9fqPNKc//dmLDgXz67WgBQB7/vDfFTKdybzMuGQsqxy5dVMLJ+Q9OhUsaK9mh3oWac5pnEmXXB/6lL9wjyor0NqdnKX5XF81PtS4N+i1MydzEjs6fHQ543iQcWq59xge5kRNcQVt1acxnr3SCK7nt5riaaqrU6tF0CCANOFkTuSnThOKFTzPIzyhFoUcEYC05WNN8duqe/Ae9d+gk9TDms/WZWXg4UxX+SzD+rHk1o3TnqS0yejmo1DylG3kFoRbc5pIaM3NzJUrpEGYcXg9wwCZzHQuczKR0IBjGM08uVSaeQ7kPm1pLU6J/B5MPdxn2dCGrUbXIIB0kb/xGXdxkOOaqz6HMYLP5BbZIdyoEu646Mbt4CbqqaI0kRuYzUU0dmygOX9gmhzq+OkgyHHyJuMy/EPz0JJr+UT+4GUoxzNXWz448ss4EJ2BWMmDTq1GP9mWTvII73A2Tb2basxFzJLh0j7U2BLOOOgmrJEMsBskx/E+v8nYWrVnJ56R4dLIfzwOT9BJJvIY3YM12IIrmCHHuH5clTNcW6Gz7Bb1hZyqLR2nFji1GnVHUlrJvUzjBNftqALU42dMlz+Ir7ITfjjoxsFISj0OKliwnBf9xi/N5H4eQwV6HT/jVekYqC3bJ9hMruHtjCsGPihGy1jZ3vHTQ6nQlkecS0ojjjWMzaXVaBoEkMG8xxnUCf4yGnAFM+Sw4O0mLHHTjctMsjeFF38vq6VeD9CFtwJ/XbvwuhwYtEX9E7RjCpcXOIcPw+FMdXsaNZtJ2goniX9q4SyO0i5XF/C0U6uRNAjSSp7mfraM9j7a8pTcLPX8G0o44KQbly9HlIWOHMYU2gV/KU0ZJ4f4N2P1BIfyH+IuXFvxvPzK6ZP6w5Ft6RNtzD/Tlt7veGUr0mJbejKV/tHexVp+ySRpHb2XxKY46SakkfTYMpeTeSLABnkhGvJEMcykXMw4tojeTR3+LEMl/0JwFGXa8kgLbtmGg7UVnBbbRDq2kTN5GdctjXz04g3Zoyg9JSrjpJvcRlK2Xn/teQPmqWmuI5fB3B9hB2gtDXhUOvk3o32CK7nRO/OkLUN4QHJeSFFLeURb4ehIh1wna/9dX1fTXRqNoUGQ33B3tK2STWnJCxJ+7zqhwVU3+b/Yh2ac+Dn/hks/hkY2MM0Y+4NHRBTkBq6KOv6NGcQjuXe19HO2phwZZaT6xbb7PDKwBkEu44YobyCbZjwrA4vcZ83GUTf5r8gG3g2SLozKNYoFvM0M5lLGEhrTlB3oTDe2MnxqZ3Z2G5/FE/wvv8n1gTJe4wNm8wVL+J6GNGVzOtKRPXIY8mO4z3C1ZiPUFHkf3Xx6MCODv5muGb/ca1jm3GPwHUm5MvfP3BfM4EPmsJgyatGEZrSjI11ybblsxijpq152HXUiJ466yWkkpTZ9CxasxsmtTxozynovci738hRT1SbXWaQW3TmM0x19W7yQU7jMuvJMHuFx3lKrC7ZUhx705zTaWLU1WKapP+Ya6jDtXKmftAoeWkM/j3zcza85tAZBTs9lIl/hESao9zLGtht9OcXaU6wBY6S3+sBt3NWIcu4t8Ne6nKb5zFc8oSmVvENw103Oy7KyF/8uWDBF7ZN30AAywnI+9B6X80Rh41LpJfTnqnUhBvLh6LstvZiInQvkBP6knrNosTb9uMLKV6eco9STOca6LXO1O4QXqNtc3oHmSeaynaZCP/W8U7uhNbg7k9nMqupy7uQO9ZFFmz35H+ur6LPplf/nqXr5bme02ER7nPiGcvsuZ/XmrJu8e4FBFzoy0MpELuF8dlX/0JtIUOVqHD0ZwlcuY3Ea/9aMsTKR0+mjDrYxkaDK1bNqH47RfgXWUJsHxW7Wuablz3lGWyH0CffBWhM5lwmO7YbV4BaMtjSRQ9lJXWRjIkG9pgaxOy9YtbsjD0g4z55EFs66KaGRlCbcYVHtLfZQt9veplMVajjdLMXpz9/Y2linnGvornKOSD1ON4MzIUBT/p6rWf1BSU8Ju2+r/wEc7pz0NeyO5PCMfCcb8in91BlqXp6G1VuqD2ez2KJqP85xfBcJe4pjJGVzehQs+Io3HAZ9KeYLtePYJ++OjfqMvgRdOGa8jRMx+1N/xcHq9y4XplWZGsIZmD7ZV87I0eiT6Jd1AeeS0pijtRWGObYbVINyNDbny8/TzW1rQN3Jnsy0qPgn6eD2PhJ2+Ogm30yyX8ae1nP5ZwWyLRcaKz3IUS5uZqpcXZDjOMUJaWlhiD9hX+XhS6yGcjhLDJVukm2s2zNF3AkZNO1YbRSnSWqWY7shNdiQWyyq3ckA99C56gP2MjiFAjRyvg6VsMNDN/mMZEg/h8sxXV8exxD3OOPqOq5x/awVV9PKUGNO/lnwJk/xLEeiT0bQgstzNKh3T2wvvYK9H/1i290khNTg7yxuEtymzvaLdq++oT8vGav1lmMtGku44qGbvDPJQlTkF6i0wrRMnMoJnuL8PXf7fF47/jb8l6HKl/RTua8pFHiKCQxG/1t3pn1AV/WuYXERaMEtKiPayhoWM8q56XAaVPzaWOkei/WOEbWUgRknq5W5Lq8fVSIHHrrJYSSlW8Zp5Vtqfu4hn2M4UVzCSb7xXIDznPZKbbjC4MC2muPszkHNqMe4VluhfsC55ImBvqinaJX1mLI5zihAUA2ebzzVfoWzVYVVWwbUYo7iM0OlDvw8RF+JTfHTTZ6ZZLBTRanLfxuqXKQ+9H81aiUnG/f0HJD22kuwAFcq8z6UPVcb5iGn54g0+RDLNKUtCRPRvdiL7fwabMQvDFW+8F3LVEbN53hjnpffRQxZV7Px0k1JjCT90R82TC14P98B9WEUr+pzDZ5KU7k+ZHdqNedql9z1ON26rYWM0VYIsOCW3bQeJzM9HPHCaXAImxtqnKs+938X61FTMHlItWFAyB4T6yiOkZQmGV4gZUzJPWTTV/rXYRY5ANzGnGBtrXkT9Q3zpArOdb4DmIGaykPaCmfkuI6sn8cdIf4h6yLNI4Nq0LTX+Kz6h/d72JhrMSUpOzt4nwlv3djPJPtk7MJNyLskkaaG38tX8l691qGWc0W41gA4gpba8lHKvEmfnxu0KRjaag9KNmQ8uhSyDfE8ZZU6nKQpLmeEc9PhNLgH+nuJq0Mc2GyMWsYvDVUOlbbh+63xeOrG3kiGW+gMMLjy2fjh5OFhgi6bjOfaQZfaa1HTmaitYL/gNiUG811w99Nupjyfz29lA8Jp8GhD+T9C7IlvihrLu9oKtTk5Rr81HE/d2BvJrOjeoQU6n9EBXksl1KqQV4Fkc0Os7RfVm2HHvw79uXT/HJv+w7Sz0gNlO+uWChEnhiQUT4PwJ683oMO0L5kiTIbHUzeWXyzpmJF/5n31Sb7xZgYsWstoZToDzM/dhNsj7GuIoW72uHblCe218i3s4x+p2drLzV6zGdGH7/3WcGykazmcBjvQWVvh3+o/7m/AwCPoL53sJS0tW0pY4a8b29lHuN/w3QxhSccGejeVUJ/xarDG9Fdkvg89D670FGXoT4XzXN7Rz+d8FtzHa3Omj1TLnVsOp0HTbC130C971Coe1VaoXYREZDULb93YGslwzmD6pKhlIfImF2BMsJb0ScVedr0mbYU+yEKedGejWKQp7Sa2QWM3JdYNyZAa1DtflvOYxyjNPGgo72fVSsIWb91YGUlpQOGURcssfFI3Ri/QyWqFZTv5CDQ/lc7o9+scY2Nbor+w0EOs01ippYb5jONcUlqjS241zX0ZG1SDPbSlrymTb4wX6lWD703QULM1nRC6sZtJ7p8RjOIl9X3uUesFGuPyDKDeJ0xqApOAQ/rZbMrr6AIP12OXHG3pj4FOdgwDO1gbjdtnHhlMg9LSEEFyosco7dD30EGaRB9BzSGAbuyMZDhnsFaGGJKRjCQE2pXspi0txyOlqRm1zBCbsHuOtv7F+5riHXBLd6pbbK/iAY+HD3f9p4ehPP/MNC/6LaXa7B59BDWHALopspE0nCoSLSBFKPPbXVs6W0XwFN+AGR6j2xj9vM4htqT00OZjHKcWeDx5OA3uoS2tYLLHKO0wuWXuYdVKwobiGElpnbGM+0S9b/70RugXhN+qePlpwtxe1M8kTU5n/ugjC+2aq60R2rjnx4ldgrPK6A9t7rNspQBBNajPqfmJKrNsx52Z6M/4d4o+ghpCGN3YzCRDhjntqC0NFFwsVtuyFVtqK0Td8Adgrra0bZ6m1BfaX9MWea81S10GaYoX8LTHc4fUoH7D5z3LVjxQq9F/Ra3jgyYMBNGNTfTAkImX9JGgbbKBuPIxq/JmGd8Ek3gbysFW7bijv2ic11PmPq0hHJzzzmd/baz2+73CjoXUYMmNJDBduyZJRjIUQXRjNBtSlz4FC1Y5pQTVxz0MEMk7C7VK5ngvY5Sh/EROjPcEFmwmW6qvc9R/ii81hm2AbK6+zdGafrE9zP2xiqrB+FsmgDbEiGmECUtC6ca83O5Ns4J/n6IWGT+7KXozE+aaThb+JthkJEtPrhGqldrz5vqcYN+WNOdwTfHryufcP6AGpZXWIwjyRzh34QttaUuH/eDEpgTSjdlIhtwNwrCnF+/YBkKY4KpvJPMvuHXkuVJ+gjYZgl8uwJAaNKVvK46RNPXiH9MzEUw37kbSYTdIGhqCpFV1I7l11PGFIOeXS01D5wOzT47ohrrYP8sY6fVUIXckGxrKq4aRNI0yYUMg3RiMpGydcfduvtOVmhaG8ri3DP2NpCkJbunJ/+XSzfFq2d6WlHbsoyke4563OrgGTW/IZRMpP6Ykd8lIehNON6aZ5CEZbmbPOSVYMBkZ9wgxNviHnjBl1ys9+UeoTwxmu+A+NZo7YmgNmsxPXA2uZZmhvOr/HFd9gunGZCRDLnSgnqE8TnCLtfjLv+r/vuc2kobEYJ3EzvtDZ0zneYb9CKvBqmEkTb1UfaVVfYLpRmskMwPkVhiCdmVRWiPp33rVn0m6fLm8D2+kFztriof7pEULrsGqYSRNWgycSK7mEVI3+pnknhmXl99QcS7rhMuRWAh/I1n1L2bUcfjMBO2tvUFibjNewobwGnSLbhQa03QhfHT+mkZA3eiNZNiFjvmfPq4R8k80v9q7hdg4jNCQGGwbQ04fpL72Cv0kNcvriUJr0LQbWJwfQlMvyUj6ElA3NclIWoekzSR/9Mxi4zZbHqqdw5sW3IdpE3L4zSN/rEbStHGTjKQvxTGSsjk9CxYsdA47ZjIy/mZMh7/8f6RGUn2sjaF4lOjPWnXuiIsZ5fM4JdBg1ZhJxg6550LV2KiwIqxudL7bWXkBxyvXZedCQ3lcPwN/+etnIc+oAVHHH5P7OCCzrAlH8VBWoWzBYZp2H/PM+RNeg6aZZFODy2AYtjSULyzCGPLiGx6mmATVjW65HdYhEVBLDRLdyvfdaGns3YJ+FlL1/XGyGa29RK1bcJ+onf/HWmw7a9B4W3YbzxHbodfK6gB3esPjcihYKoLqRmcks7K2ue4GAXyjLY1rJP1bL+Xoo6KW8oimuK9kP5tusT1TmWJwmwivwc8N5cX5qdP3ssjpmnxlYiyNq9PdzaC6yTSSsmtGOIfpap7H4PWfjStQfyOmH/1WYpugtyqim/NlhtOVndhb87lhfkOKoUH1TZVYD+jnq/4L/hhGstqkJwutm+yvdehTxTV8oi1tY9mKG7GNZP3I44+KITFY1oJbN48sZ4TnoOJoUB8/fkfLVvzYWVvqMw1ZQ4z9w+oTmSiwboptJOdoSzvZNeJIa+8WTBEp86R0rXro5pI9pLDx0O1Wjlf6ZBNm4mhQ/69YnH9DfS9V00i29G+iSBTHSErjjKguS42Z3vToc3vsKCZPBGekQb4MMAUxfenjGvnY6BODFQjAK7218y7PQ5toGtRHBS+CkZSmhsikn1o2lE2My3TVxEiG103WTLJPxmueqPx8W9/VltY1LEN86GCZPlfHPMOpY0/LdqokhsRghaKU6+aR+sAZNpRGg20k/rLSlNXSJpOf/mgneJQBqV9djGR43WQZjjgLHZhucN3f27Kd/JgyflugKnhbW2HfaKMvDrpQF7vJRj9gUk+b3uEhZbqRaCKWBt/Sltait2f7ZvYzlNskI9N/j8KHYtmh2lwmD66bLCN5SOiO1qCWMl1bwSQfd/bxbwJT9m6VI5J3VeQpbWDijU3iodor0b43JKNp0GAkYX/vkZvQq7ycDy3a0F+KDn8SXX1ygQfXTUEjKTtn7DXNVv7ZqydrS+MZyTCzPFNM4/7Rxl8EDInBNg5jcbKm7jSlSwthQTwNqgWGKzYH+LVvfLK6hh/s95SN+6veAbWOhA7b+5O4byUUMXRTeCYZ3s9hPa9oS3eUKBvn0sy4D2SH6at/bIzRV3qO7WQHi9Bl7ugW3F2l0sGUNNJmR/SfR8bU4Kva0r1k2wB9ZHMQzbXl/7JqxbS/1iLwqLv5N1EUIugmn5H0XegAPG/Ycj4uQB+bcnggp6p3DbOQ/SXu9vYDfMoymS0vyFC5UobIAdJOAl73MCQGqzyXHKhx81ylnZHaEVOD+i9M7UgaXIspN/sUq1ZMs02Td3he4p0WhCWCbgoYSWmQseBYwQv+z6AWGGZjx/v3UYBAslcVhpddlzOijB8A2ZEDgLq040CGcBVDeZHZLJNPZJKMkGvkZ749oJ9LVn6LgzT1xqkFnk8aVYM8YygfZNWK25PV5yhDlZds2lGrDAvuoD7ooiLeOwk5zii6KTST/GlGGqLJnhFd1vKktrSr9ArSSyWkWeZmbn6eNpSfHdE58dyCJ4x1aM1+nMrlDAnQx0hNEJIu0m7N/5Gm2t1X/8V2VA2qOXygrdBbdvPvJYPB2uib8IGabdnSd9pSf9eJysSJbxU+E0EU3RT6Qsdc6AA8bCj/n0D9rOfMgM75zxkinLflmODjB0Cac6ahyhj/XtRCHtcUD1z3v9mXTBYYf0jMxNagaYSXBOpnI6SWUd3jrBvTh1sJO/MzbRG4ob/G5HLlKIpu8hjJEFvmgPqI17UVjlk7XwmD1OH8cK2p73jKUOXakLuElbjA6D07Nkg/unngWiOp+yF4QPnH1Y6sQe43lB8v7QP1tCEDjafE/7Bu6ytt6Z7hBi3tOTDK29AbSZcVWRTdbDIQ2SHj2vXn6m1ja7bol2N1+FOwngAGBw488XdDeQd+EbQ/AGRLLjZUmaLmBOlKlxjsAGkC0jDuYju+BtWbhstcdfhLmJ42eK763GSoMlNNtmoKTIE69pPmlu2YuTKAt1oh9Guy3K6VsXSz6cPH/g0HuN+wn3KcBLvQK024PuDIAZ41+tZeJzsE7hOuoZmhxj1hOtImBqtPP+AQzcn262qa9xCKoUHT2xooA63aycOvjIvg4VbtrGGOtrQ+gcYvnbQ3Yj1Qq7VX4vMHyY6kG3sjGWo3CFCLjbONu8Q/jvgariTwrTdVzr2GKs0ZJkGduGQvzjJUKePRYN3pEoMdDhyp/aw/RdAgD7LUUOP/pFXA/pBducJQZZlxlVIZk19OiLsOSG1uixiTXHfbM/9MOJJuNjKSUpc+BeuVO6aCz+IWwwWGjtwZohvpG+EYCO7QJjsAOIg/hOtOGjPCuOD5uwqWPEp9zMTMwgFSV3PWucx4LGd+2qJoUH3H3wxVtmdkuJsK0ozRxuPDYWp+jiZN3l/9JISX2WWmlMJe6H6oWkguD/R4utlYBHtn2O/X1DfmxuxRn2rv4wEMlvN8exHFAzF2U9TX3GysdLkMCdbhnXQw1FjOn4M+YvZ8cCvO04QvHqO+9e67SBrkBsoMNfpY/DtbIfUYafR+XsmNuRp9y/hTfZ33uA/myjBvIAP9v0C+AMjRdLOxCSnGbtAarjX6DNwqJ/l0IFvyz2h5Z242nC0C3C0nWLRkfo5LjZmv4T5lyt2Sj1GaL+DVms/FXGwH1qD6mluMlS6Ua/17kjo8ZHHT8HbrG5Jrxr8a0yHPfvJrr3EfwtjI6b/0Zj7fjelourE1kiF3gwBQ84y/m7UZLs7+N9KCZ+M55asyrjFWqsdI+S/fnuQ8zF/TspCLewD1vSYxWPYB0jzGB+i8aBrkJsyeQZfKH/32l2UzRlp4fH3l8G84wVjjenG+vCPHMDZ68i/9HO/8XJfpoulmAyMpW1HY0+AbXgv7bgC4wZDxBurxsFzg0rS0YUrIm2IFuN0iEEFt/i63ukdbl1pyBbdZVLxahc8VbdoOKcRwVe7wqQ2fuYgaVIs4x6LaJYxyj6kjWzPRytX2QrUwd+OPGX1W6jBGHPYUpZHcxqgo8c03RP8j1Z3fWo84om42nEkeknHL/Xl/8W+K+t7iPmFtbpWheU+6pS+vxg7Dr8oZYtwwALiASZWj5+R4ii0YZTW7mMFfIzzfv61Cv27IsAAdF1eDo7WpdNdyDG+IU9R5Gchb7GVRcYx6yGH0nxpiagE04+m8u+OyH29yXlGC7Jo2ia6RP1oenkXUzYYDKN5CBwD1HHdZVBvCVDnAtk1pKrfwz2IkBlUfcqlVxV68Lf8rucKgSi0ZxHQrB8cVDA7g4VKIvPuLL6uZAXotsgY5F5sT5U5MkRtl8zwNy/YynCetAk3MdXY/GGZRpx5D5UlbLzbZW/7JJONBYShMa0m4hHfkfOkiDX4YXz3ZTvaUY+XnG9WLqJtK1ldqMZ/CN8O2C3wssL7PxrxquXP4OFeqdw2tNeQMrsTldltf5bCbJrV41Dq+0Lf8lTvUl+aKUpsj+R09LNu9ROU7E7V/um2Ymyvr3hnK39emFBo8gOew2xL5jpu50ybCkbThAs6xTKKwgv2U45JQ6jPbkFRsLd9zL/foPE9kc45lsDYu+2hNvNSTlMPlLxloCHezngqWsIIG666Yr6CxWuexE1c3lY1kj4zV+zsqYsBN2ZnXra+NTuRenlFfF2ilNj05gSHk+q2vhJORBGnIxBzpv1bxHA/zgspIaip16MFRnJQjgssTHK3Cx1JZO56x2sC6G7KYbf0j9JRIg0NyzJpX8hSPMiHr504UfTiZvtZXzyo4TZk8yXVjvzCXA+VUnudVXueztYtQqc027M4e9OIgwx7k++xN9gUvNyPZlo+dH72TWhfLKa5uKs8Uir3QAUB9JIN40nLGcgAHUC5v8DYzmM8iVtGEFuxMZ3obAlDBZ/wrfNxw9b0cwWvWRq0uAxgAMps3mcVsFv7w69iUbWlDV3Y3uh5uyFROiWcigaE5jORjQQLplUaDw2QnLrOsXI+jOZoKmc40PuQTylhMLZrQlLZ0ZFc65uz8Eh8TCdzF+dgH49id3QGokEV8Sy1a0Mxy73EJxxImVGIl1BxZ4HxNr3OlgHdRdVNyIwnqWTmD4dbbxLXpYb0UXU85pxLk1uImo58vfRlPPl/tHXNeky3MxxwezsumIE9hL+EQNyRLpkGuoAXn5qhfiy50CdDv75WnE4BaJmc5XLyqRfNcbn8V/FzNiBLd6gXnEMedKwX1i6qbdYsCaZFxCrfYeGXVG3U/50UIwFmZP6oQEa0Lj/5D9iPEkUU+ZrK/+sy/Ge2TrbROwzBLOSZ+r0zpNKgq1Hn+/ik5qeAiZb5tax77BKvjTz/OUTa3AFx40PmT6yL+xNbN+p2Tvhl3619UK2wbc0f9jTMMSTJ9GGMMLeA3+k/Yz5DyPjQz2F/NLUI/tvPDMPPI0mrwslihdguyhOPVrYHaOp8Xo471lypIJIWCjOMNx0+uD4sWWTfrjWSpFjo/oIZxhNEX1Y0XGaTiGeA1o/+C3jjcdHNkHHvHnkX+8FzTDAGS11DOiCDdlVqDN3Ik/r7nNsyitxodbNwrORb/AHWFqeA36i/xXoSq4GLHVWTHdTcoI+tmvZGMlQreGvU0vQy5R1z4F0cqU/rNEKNfrE7hLE1+mFCUcz1HqDg/J4WwmSOODzSrLb0Gx7K71c+CH/fQXb0TdNzfsp+Fk2J+lnCcChsCe9OxT3Tc6GjI2rufkXXzg5GUrhm3rT7K53Tvh3qP3bk7aJMPcpAyxXoJN/676WmZENSV2eyvLo3he5LJSAvDH2SxXUU0OId9udaY1dqdmfRXZwZKqVd53AvpHya8YCU+Zm9ln07Cnd8zyulznaEYuinShNUWtVSdxQDCPFw5l6rBKv7crvL432VfTiO8JzXAcm5kV2V2RAv7RPrEYAALQyQgo+pocIW6nK7GtLMuLOJyuqhY/msr1dkcYuHDYssw9jS5bwQaeTmDcoUbXsuaXcnoujEZyfAh0oyoZ/gJV3vfyXqTXip04gab0VeoEXTgaotQanko5yE6qksiX/kpjCnUxchAP0RVSYMfqQEczqsBm1zMDbRT18bd+lHP0YUbjTHXzbzH/ur0wPE7deNerX7BmbnPJNbEZ4ium9oA0pjCMYyXRz41y0AtU1fRjj8bg6Jm8Q2/ooeKv7eUNf4ydRWt+e9AO6xl/JWd1Skq3BwhHxMMs5Mwi+0qpkFQT6le7M9TAS6nfczFbK9+VwyjoxarS2jHTR6Gcjbn011Nij/WjUZ+Dz9hBHniEHQujm7WzCSzHJJeVv6/SY6or9Sv2Z4LmZ7zgzM5jx3UzbHPs43j/17dxS7sy19wP9RYydOchlIXFnNXbpMnqdCmp5oe6MeoCmoQ1CR1OO35LVMdG/iOofRhJ3WT+s6xBZdRL1AXsz3nOYz63xxPB3V7Ma5cFRj3PHUa7bjO8jpdGV9TFN3UApA7MuLqXaxMKTCLgPyE4zmEPY2uix8xjieZWNRjDZvx16InfejFXtbeKxXMYCIv8kKAZAjVhKqtQZD2DGAfelv6Vq3gTSbyDJPVKqv6sUbdlSPpw940MFRcyUs8yVhTUmKNz83qkA6ysg0Hsgs70Z5WNKYRjVjNMsqYz3w+ZSYfMZ2ZqqI4ulljJGdmeH92UXnncdGQpvSkG11og6IlDdmM5ZRRxnfMYgbTeTNIoK64z9CerrSjLW3ZgaY0ohGNqMsKlvE9C/mczxHeZzozwp9+VnWqgwYBZHt2Y0fa0Y7WNKURjWlELZazjG/5gi+YyQfM4K1iXDuzHnNDetKZjnSkNU1pQhMqKGMRi/iSGUxjGu9WV8VVF90kEolEIpFIJGoi/w/NxyMUpGm9GQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMOub3yUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDIrMTA6MDCaxmeZAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[108.536720275879,266.396270751953,1],[327.870056152344,266.396270751953,1],[327.870056152344,309.729583740234,1],[108.536720275879,309.729583740234,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[218.203399658203,288.062927246094,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;256&#34;:{&#34;id&#34;:256,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.300000011920929,-0.300000011920929],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKsAAACiCAQAAACU7vVaAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAMIklEQVR42u2deZBVxRWHvwFkdNhGEBEbDKI4IOIWNWwKCkrQmBg1osGFiiXGRAnRYJRoYjSKUSKCaFwwhQtYxgSRFOCCiAgplIriwuKMg+tRQEaQGURgxpc/BkeZedPd977uvk+4H39B9zvnnl819/Z6GlJSvisUJP0A3z2kmNGa4jXq3lTWGEgX3tUUv66OhCZJP+SuSSqrF1JZvZDK6oVUVi+ksnohldULqaxeSGX1QiqrF1JZvZDK6oVUVi+ksnohldULqaxeSGX1QiqrF1JZvZDK6oVUVi+ksnohldULqaxeSGX1QiqrF1JZvZDK6oVUVi+ksnqhWfyfynGcSF9KaEcx26hEKOc1Xmax2ur2IWUPjuAwDqMrHelIK/aikC1UsokNlLKClSxVHycr5M4UAEjTRve51qhMljD35BIupWcjv/mCeUxnltqS++PJwZzFyfShyFj1DeYyW72ksdWk8f+bqjrCM1nsb62VtYoWjVS6Xv2lgdkzuIMDjd4rmMKk+G1IWnMhF3NkxJ+t4u88pD7PanEKFzf6u17qLesnc79tWIrkUZ60EBXa8XvKZaLsG1EYQDrIBIS7IosK3ZmIyJ+lReRfOiWSrFLMcwyP8IM9GUWZ/CaSjxZyC6sZTcvYMbXgj5TKRZLgBv4IskoRc+gb2UNrjo/g43RWcK3Fm9TE/kzlaengQqI4WMsqBUynTywfD1l6KJL7mcUBzmI7hdflZGfWImHfWm/gJ7E8fMpcm2pyMEu5xHF0HXhGRju2aYWlrHIS18X0MM2m8yInsIRDPcRXwAS52YNdA1aySjEPxx6PWbwC5DSepZ23GMfKfaE/X3Zi3YmKaf8NtcxURU5jBoVeoxzJLV7tN8Bi8CqDuSi2fWNbld78i+be47xGPvLu41sYZZVC7oltvZppButdmcWeESxWsYyVlLOJSprTmvb0oCeHWPxyEuWONLPA3FqvpFts68+otbpiKeTftLe0tZFHmMkitS2LnU4MYTgnan/fJIc4ImOSdb8cXgDmV8AEy+Hpx9zIw41P3aiPeJAHpYQxjKCpF50iYppq2ar5mGRYzhLWsJ7mtGNfvk/PnYLaQEfdFKEM4WmLJ6xmHLeqL+zCkZ5M4qQYOjieajG11sZEXc1kHlYV9Ry25AQu4Iwdb8vHtaIWca9FDGUMV0vt1VHLZTCjGee5Z2EkTm+0kivopibUFxVUlZqjzqMDY1gPTNVauZ4uRk/zOTaKqAAqoyYwkE/9SWZDdFmXcqiarL7SBLZJjacrl6uXG68jnbQZJGp5nKHZZ05NqCX05h3nWkUgqqyzGagseoCqUt2trXCjsVv1FOdn++rboVYziA8caRSDaLIu5kzbj4cO+R4XGKosYliUhZCGqA8YlNyrIIqswlnx289OXGX4VK7jnNyXGdU7/JyvcrUSjyiyjtJ37m2RNpo1pVqGq09ceFLzuMGFnejYy/qimuHI5/mG2f9H1Txn8Y3Duj/qEntZb3TmUz9ZXcXV7sJT1fzanTV7bGUt5wU3DuVwjtBWmOzmBfA1aiEzXdqzw1bWqdm2YcTiHG3pNiY5j/Gvzi0asZXVZvRux8+0pY+5basAagmLXNs0YSfrZ7zqxp10M8yNPuIlyilerGqwk3W+ctX/G6ItXccCL1E+iePNdibsZH3emb9T9OGrGh9Bqk3M8WG3cexkdfQKAPppS+d7i/MZb5azYiPrV6661FJCW22Fhd7ifNGb5azYyPqOi+kVAH6gLS1Ta3yFqVbhZOBti42sbzjz1iuQn2xEnA7PDRtZ3S0EH6YtXek1Ur/W62Ejqzjz1iPBwFd4tV6PgLJKUzppK7xraSgeq7xar0fI1qoMa/jePlgAOB8U67CRdZ0jX50M5X6/1XnXE3BwEAiAfbSlm51147KiviTWKm48bGT90pEv/VBgs/dYP/PuoY6QrbVYW+p/MiTgdItZ1oyzo5b6nQG7mazuloT1m4PdLJXryCtZ3dEsh1IXBNwzEFLW7dpS/3v8Au4iDCmr/tPn//yAfw91hJRV31HzH/Ru2VqLvZ+din84OTIhZdWPcpqyt0/nUmAY5TklpKymKRvbMy/xaBugr1FHPskaI6FDBPxar0dIWT829By7evXeOWCkIWVV1YY5T5uzgPHpHi7S0Hmw9AvjqawxWaYt9ZFP4Bt65G7CnrCyvq4PXIp9OZamHBMy0HxqrQUxc8HYcFTIwUBoWU17S/p789wvdxNRCCqryqA/bHG6N9f+LGcldEbMZ7WlveQgH05lHwaEDTO0rM+hP4NwlhevPw05cIXgsqpPDPv4R4qPJ/pl2CiTSIurPx1wEKe5digDOTp0kOFlfcKwVOfwsNsOxgSPMbysaiNPaSv0lzNd+pMhnBo6xmRyY08wlI8XZ8sjsgcTE4gwCVnVEsMZgQO5w5mz2ykJH2FSmdxvM5T/Soa5cCNnEyklrzuSkXUO/zPU+IfkPNyUfoYkPB5JRFaV4beGKkXMlpy6RXIMc0gsQ3ZC1zmol3jCUKUNL8gpVsayIKcyn9bJxAZJ3pJxtXHfbGtmyxXRDUuBXMUsWiUWGQnKqt5jrLFSMybJ0xIpd6x0YT7jk840mOSdLndanXEdQqncLG1sDEpbuZ2VDEwwph0kKKvKMMJqP38RY/lQ7hXNsokUSG+Zwgf8LlI2WG8EnjDbGfWhjGAGNnuvWnEpl8onzOMVVlHO51RSQEva0I3u9GZQ2O0VJhKVFdRMuSZCLpWOXGDM95adGsPb1vGW4sTvy1K38aB3JxnjjQaO00MkLitwmfeUSqN41FAjp3yGDckDWdV2zvY6zLxGTTbW2QVbK6qGXzictfo22xmhbN7du6KsoDLqKi6k0rHZzxmqatOem4YHjo8v5YmsAOoRjnKao2IhR6ivcyKZZHV8NDSPZAVVTj/GsMGBqa1cy4nq/bq/m2R1fIw5r2QFtV2Npyu353R8OcM0uqtbd0qJpl/G2eIsfdoO8kxWALVRXU0XxsbKEbONf3K0Ol+9V+/f9bI6Px2eh7ICqLVqHN0YzAMRUo28xbV0VsOy3nmknylw8drZiYQHrzpUhud5HuRABnEMJRzC/lmqVfE2b7GAZ7WXn+rXCda7fvYEb5eMjrSgE61oSUv2YguVVLJWWWWSkb4s1hT/R/3Y7ZPmcWttiNrM2zF/qj9KV2FpxZo8fbc6Ry+r8/u3dxdZ9ScUnd+nsbvIur+29H1LK9bsLrLqL+VNW2tMdBfm1bi/pTB4T0B60YJSFTAnFUghPTXFZc5yJ9URvoM1jD+AVFBa96dMucq01RiDtbk1lrt3GF7W2pnNdvSpO9yWkY/qJJ7r7NqIb3OetnSZe4fhZW2YX6iAznRmEAAllLp2KEWGS9X/6z7I8J+sjdrS4zx4PFt7MLOal60tWRNeVn0f0bms0pw/aSssVR6SRuabrGeI601plxmyaszyEWR4WVdr1+Q7M9SlM2nPdYYqM30EGf4A0RZe01a43J0vacbjhjRNryovObOTGGXpj2cOkXOdebrNcF053G1lJzJJyPqcofwu2c+FG7nSeEJhLY/5CTEZWfXJGvZhgeSYXkmayET+Zqx2k6/xXRLH3aqNbaSERXJUfA/SlhmMMlYr435fMSYzg3W3cYfeAbwit0iMsyrSVC5ihWFcBZBhpNpuYTAWCS0Ryv3GHacAFUziAfvbCaU1wxllmfHqHuXxqtKkZO3EKsvDaNUs4CkWsLzxSRhpQg/6cyons5flA7xGX+Uq8X8WElvQlpHcF+kHm1hJKcI6NrGVGppTSDH7ojiYkoinsNbRW3m9QSbBfQIy0+IN6IMqBirTmdscSXLR5ULDeMsPlfzIt6gJ72qR9izynLCxPhUMVQHueUt0iVB9ygAfs52N8ibHhhA18ZVXtYYBnm4ibshU+vj9UH1DXmxtk+FMpJ1XF2u5TD0ZLqK82CegpnEo0/GxOAhQzZ2UhBQ1T1prLXIk4/ihY6M1TOcmVRY6ljySFUCO5nLOtR4r6fmMqdyjnO9YsSHPZAWQtpzDmQxkj9gmNjOXJ5jlc3iqJw9lrUX2ZjDH05/DI2SyqGIZC3mBxd73yRjIW1m/RooooQclHEAHOtCeIgoppBnVbONLNlDBej7kXVbzJmWuDwKlpOz6/B+0lNxKVHUtDgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMOub3yUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDIrMTA6MDCaxmeZAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[186.059371948242,184.452331542969,1],[243.059371948242,184.452331542969,1],[243.059371948242,238.452331542969,1],[186.059371948242,238.452331542969,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[214.559371948242,211.452331542969,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;257&#34;:{&#34;id&#34;:257,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.400000005960464,-0.400000005960464],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAwCAQAAABXyPewAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAD+UlEQVRo3u2aXWxURRTHf1vbLWoBaYyt1voRjVayQuMHDdhERa1J5bzoA2hCIiESrRqxMQZiePGBBI0vRoWoBK3gJ0aTgw+KbdRgamK0WqhpMEaMSisU3VpaLWVbH3Z7dna33bt2p3JjOPtw/2fmP3f315l778zcwukId0T8nk5W8iYAq3Wnx7NWs5JGFnMu8xihnx7aeVf7Zh1I5rOfWr9AUsXTrKIsp2KMnWzU37KLS3wCsT2F4+9PtILvWD0FDpSxhl5pnkUg2cxdnnFW8R6VeQznoHJPZlGpty9/nI2ecZbR5vy+v9nDAQaoYQnL7VIp4VX5ST/3DiRPsskzznzedobaK7TqH1Z3GS9zkxHskoU6MlnnYcjJHHndNw6wiRrTG3RNGgf0B25hm6UXu2OjaCC5ik7u9k0jNTxsSZtuya7XcR5CLV0vC7wASam08hX1vnGAdURTaojWqQyaYC3xVFLBOg9AspwunuFMK/iVv/zQSIS1luzQY1O79CgvWnJvkUASkw7aiTlFX7OUkZmdLSeuca6fXXl8r5mqk1hRQKzgZieb4FmW6c+ecKDJ1FG+nN6mB0h/5x3Jg4/bdi/366feYABuMNWpE3mdnTY3SbUp9i43wKMs9owDV5vqCnB+a+r65KGYHhrkOZ7SPz3DIHO5yJLeAPP3pqplrg7NHOhHHqRNj/uGAeASRx8K8LrX7aV0zxhI35oVlGRUOfpwgNddE11At+/lg5+odvSxAO/vjq6EcALZNIaEDgd4jzOR2S6MQOWmgnDQCWd2Mif8QCcLcCdMlf0/gMbCDzRuqpAtnDRBIqxAJ0wV8lBJe0YtlXIkoNkH6mlpUECMmooW4I5mtkvyLeCdgGa1/PKfAcVNnSUlOp7PKlEHaBjCOeTSD9MIFQHeeY4+ElYgdze0KsDrzir6wwp0aJofHATUF1Ig7XOW8pcHmNP1g3oYUjcF7ff9FqLI2E9DStUFOK801ZM8hLCHwNlHuC7AucTUN2EG+sxUg5RPb5MKrrVkb5iB9tos7mxuy+NrtnnfSTpCDKRx2i15II+xxdSeyb2NUAIBL5lqlqapLXInN1pie6je3g/9u8iYsozqWI7hfQ5yRUq/IUv1YM4ZYuywpIsPJ+Wp6qHNDNnnkdxqTfCEJZV8LA2Z9dLIR86057H0jC+sQw7dzW5Latknz8siiYBEpF628gnnW+027Ui3O0VDrqC4jzp7HVBKCy2ckCOcl7Wo+IL1bhraHgKN0zT5uExFlAuzcPZxu466BSEGAu2jka1MtyJKsIVbs7eiQw0EOqwtLGI7g1kVcV4gphsyewe8/2vMbIWcQT0LqaacIQbopif/SvZ0hDf+AQfX+h9FuxtcAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[42.1418647766113,102.33519744873,1],[76.8085327148438,102.33519744873,1],[76.8085327148438,118.33519744873,1],[42.1418647766113,118.33519744873,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[59.4751968383789,110.33519744873,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;258&#34;:{&#34;id&#34;:258,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.5,-0.5],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAwCAQAAABXyPewAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAFxElEQVRo3u2aaWxVRRTHfw+6ILRCC10AqxIIFKz4AggqVZTNUBhDiAlgIi4saoMpEDSgYuIHETRBjUEISsTKkrDEmGELCBIogUgEZRchokXLUuqrlbJ0eX7gMXfe0nffzG0TPnD6of9z5z/33P+9M3PPnPvgjt3e5vN6ApHLeAp5iE7cTS3nOcYONsiK5rg48R7vJki9ItOaQZDI4SMmkBzVUMdK5soLngV9xzOmglp5CDeG4zwfQw4k8xInRZFXQfjNu1gLEhP4lsw4hA5I8ZwXNSKDe817JVkGe4xSre81NnKUSroykKFqGLfia/GH3GutyG/TyUqQaM9abaitYJb8R7V150ueVGdfJfrIWs+CdvCsCzfoSRDz6KrwHLlQb5JnxDAW82rIvY+5zPMs6EcZSLSTxRwSXXldOaXhcgBkI9ORyp0hMjwL+inxTjaLwjRSQqiGWbEIsoHJBEJOGtNs1IgUeivnYAsKEj4mK+creTk2S15imXJetBHEA2qWVsnfW1AQ/bT5syoO7xuF8kWBhSC/QgbPx0bQSIUucaBpmjxKuXJGexJkMINsBA1WaJ8MxmXui9HnNhT0oEKHXJi/KPSwhaC+ChkNOcP3kEjX0pGTLuTfFMoV6bLGKE43OoRgQJ4BkcRohjOYLmQS4AKn2cIm+ZdnQdyv4bMu3HINd+OwURy/QgdFKjOZri1FWWRRwFgaxUrekeXhHU2HXI6G/3bh6nuiLoZxHEGpHOUDTY5+7ZM4JV7xJihXw5dduFUazsTMHEGD6RGH14al4hOhqTAdck4a0yCvuHD/I6gyb9P0xx91pJHT/Ek92XSnfVhLCXW8ccsxfUKpCrnJQQa5qpw2JkGidkLnKCFX9pIj5CjZn048zjr0V8ZsZ+dl+oQcQfUJsBsUSk6A7Zg/zFvLNFmt3ah6yigTT7CBTurgUrFVVoGXJ5SIoLpmELRAjtflKFm7eUSbxem3Bp2poEaFEimvOGdvSIDt2FamMp817Gc1bzVFkmfQt/jTRTswH3I3FEqkp8O5bhJEnuBEQrxtYgujQk4aQ9gcCilSES59N8mrEReWgrs5HCNBBvaxEgQjlCAyWOfSMY9zAGrbBm1FK9kYr4tI0QS5romWtofral73A/M55ExDH2ku3Ls1fLFl9MhrWgqcZSNIr4bmuHD1rOJ8ywgCLnkTdLaJC3YT1Cy17pjmLOlJFoJkBU6VrYcL2Wmvlm6JrL2lK1SpVMnzBkX7IwwKoXwXZi+Fjtldq0iWda4kJ1u4rAQZ2QElaIALc6BCPxvJGMUUsskmiw4iX56Ky22NU4A5AjZb8N0KDRKpTdNEGv2Vs90oQlvGUUhPMvBpNyW2+bUht8dO0HaVxbVjRBxekXo/1LPTKIK+tx3rwn1ZoUZ+sBIkA+xQzmtxiMUKbZT/GoU4jVNYHCPirKUiVytibrq5GbcpBX+hUJEYGZsixjFEOcvcThhxy4KUKieV95uU42MFbZX76c1/Fp8kRWuO0zPkVPFo9LQVBexVecIhBkSnSGFp0fXItUzk8St3KfcFWUqUCR+LmKHczTJUzLR4QrKBt5WTyfdiUHi7KGSblvbMjpnxzadG/ZVERShnvuYuFzOj5GSySpNT7XwQsPokKdezXjl5lInFoq/wgfAJv1jCLjqr1qXSbEG4ZR9qZeYkFokDYqIIFVpEbzGPU0xU7UGmOBU6y0+STCVfvQGSKKaYG+Ii2RGbiv3aXTS7ZTdEEXu0V/cAVhMUVdSSExEjSIl0bq/tR2MZYGTE6zKFeyJClfG0tN4HyUqGsivskI+O5EXEqGWS/Ew/YP0VXFZQyBKa2hE1sJDhhst1dIRhzCXeOXbSX64MP+ThdwryiiymL8uJLGEE+JwCOcf+6agIjXIBebzJwagbV80anpLDZFR93fNPY0C0xk8fckmlhkoOcyz+TtYqRnsG0pmOtKOWCk5yWJqVXe7YbWP/A8c6gtAtjnM1AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[42.1418647766113,170.497695922852,1],[76.8085327148438,170.497695922852,1],[76.8085327148438,186.497695922852,1],[42.1418647766113,186.497695922852,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[59.4751968383789,178.497695922852,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;259&#34;:{&#34;id&#34;:259,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.600000023841858,-0.600000023841858],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFMAAAAwCAQAAADH245/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAADzElEQVRYw+2YSWgUQRSG/5mYiZhFDGJGo1FRTJAYg1vQBAwuEdS6eFHxoCIK5qIEDwbxKohnF1xwPwgRDy94UCNBIgoe4hYRN5SAUeMyMYtmmeihp1/XdM9Md1UFT75c6tWr/r9/Xqa7ahr4H2MXodTTIorNqMFCTEYBBvAJHWjBdeoaS7QKI4VNUYRj2IJsT2EYV9BIn8fEoiLDY1NsxEUUptWPYRvdNDapzMhyCWzBNeRmIIzH1tI3r54ZmdRgJHVTrECr9I/4jWY8x1cUYxlWSStHUEv3tU1qMSSbYiI6UMzpBTTQD67NwVnUcu0D5tOAlklNRljSOCwJHKSdjgBAb7EapzidiUbNZmoyuJuiGO8QSSSXaHuKTmThBkQi6UOJjAjYS22G0809LNCLhlQQimMXYokkD3s0eqnNSNgUIezitefpW2oKdeM0JzuUe2nAsLu5SPrOXM3AusyjMlGu6NOAYdus41I3HqVXoOfo5GSDok0Dhm2zmgsP6E9G2AMeVUMtDBi2zQVcaPeBPeHRUkWbBowwAIh8lHDhpY/Eax5FRX5wj2YMq5uzpCXvfSQ6pfHs4DbNGJbNImn6o4+EfB6cpmDTiGHZjErT33wkvkvjQgQPI4ZlcxJPxqnfR6IPzl06CcHDiGHZzOFJPwHQH/ziZLyCTSOG2+ZIAGCcR9kBVnttajB0bA7/A5suhmVzlCdDASScU1U8wGo7jBhWOsST4wJIOGsGFWwaMcIuXCSARCRZImAYMSybMZ6cIMKZrxcRScL3npXCiGFd4DxuQ8jzwRVI4y8KNo0Ylk35LUORj4S8m3xSsGnEsGy+T7PET0LlnZIRIwwA1AXnV/dcHwmn3kN+RwgpzBj2l9l5FVLmI1HKo47gJk0Ztk3nt8kSH4llPHqsaNOAYdu8x4UqkZP+epGHxZzcVrRpwAhzau+0uVibAbWe9+YR3FW0acBI2KQYWnjZ3gwS9Txqpp9qLk0Yzn5wxvk0oi719WITVnJyGuqhzXBedWXhBeYlku9YTq88AuW4z/tDO5bQqGeFvMkN0rCnrs3gblIch3h1Ie6IKpdADW5Jm9gBr0kAR9DLf/u8ZX2GdAigJjRxMgNt4rioECFAhESlOIlWTOXqKVK9fQwZyWe/3ShDOVfqUY8h8QVTXEevh9ivZ1KfkXSkohjqXA/tCKa7BNqwjlTOme5+ajFcJz/qQg1OYhSpI46jWKP6IPIY1WB4DqjUT/WowDn0uAoxnEA5HTTppD4j7c8nkYVKzEcUOejFVzxFB6X7/NrxLxj/wxt/AbLlhcX82jseAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[48.8020210266113,238.660186767578,1],[76.4686889648438,238.660186767578,1],[76.4686889648438,254.660186767578,1],[48.8020210266113,254.660186767578,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[62.6353530883789,246.660186767578,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;260&#34;:{&#34;id&#34;:260,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.699999988079071,-0.699999988079071],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFMAAAAwCAQAAADH245/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAFl0lEQVRYw+2ZaWxUVRSAv4GhVWgFCl0AqxIIFKw4AQS1VZTNsFxDiAlgIi4saoMpEDSgYuIPETRBjUEISsTKkiDEmMMWECRQApEIyi5CRKuWpdTWSgXazvij03vvrG/eTPnH6Y+ec+65937vvPvuNnBLWk880d0qj0kUcz9duYN6LnCCXWySytboUr3NWwmGXpWMmJgql/eZTLuIggbWsEAupoz5DU+6xWwT0ch4TvJMFEhox/OcVmNTxcTnvkoYpprM12TFie+EqKdTYVSduct9LW9IEw9TZnmusZnjVNGDIQzXw6MNX6jfZH/SnL5kKlmYqiMbrJe9mrnyty7rxWc8puusVf2lPmXMXTzlEBuIls2F9ND6fFlix8s5NYJlvBQ072YBC1PG/F5qEq2kx6bqwSvaWxYKCSB+ZiHanK06p4z5Q+KVzCc0k7SgVsfcaKHSxDRanj+DmckwqjT6aeOwa0zlYZr2fS5XogfLZVZq47lkMLlXj/5q+dU1JgOtcbk2TvyXWitQhUlg+rTmIpcGc7T2XOZQ7HA5ToU2xqWE6WJkGswi7Tkggbg1DmitCPeSIuZ92nPEocZPWnsgCcwBWnP10r0AKtNawE471PhFa3kqU+rcdKZ60imo1sg5UF7GMZIiupNFDRc5yza2yJ8xMLnH8px36KvC0nty1FUufSaXKp05zLI+3GyyKWQCfrWGN6UitGLzS8+1PH85dGXvObu7grQx0znOuxakTTSVM+rFaJh5lifGnKml2tKzcCcGs4jeceJuY4X6UFm7t+aXbha+Jrnq0NW/BPRuye2C6Yvw+DnL7zSSQy86hpSU0sCrLUYzcboudIJEAvxnPbULidhp/kEpedJXRskYGURXHuEr7MlwntnZesMwGxPor0lr7RKIjpXLDcyUWuvxGymnXD3KJrpq5wq1XaqjZTMRzIZWwFwsk2xIDbuXB62vI7PltTdj+nVBjJNmiJih3ZRAtJHtzGAR6znIOl6PFSTnsA8xs1QHaHnpN7Tbi7OYmOtuKOUUpxKK26G2MSZoZDCMrS2ZMd2lJdCOiXGF6UI+sPRR0IJZo53tVZv4Lag0C9NxXkhS9lkJGGgwzaD1kOHQxB2WfunmUMo1a4OTbTDtm4xchzbsFevCzcEELkfDPB8DwwmzVe6UooqZrLwaUyoxp+7eDg2Y8lpx2qYkL5laq9KYwDHtLnBooK/WTiRHoBJZFMxKdAXMHHiIoUFtsEMDQ7T2oyu4MUwnhxyy6aQK5Ezc2LaY4+AxMNncq91DVXqcBjIYpI2drpLYnokU04fOeKxHjS4+66XvszF36tW8Q/OEGkPG6vW/kd2uMO19/gSH2Be05uc7C1Nq2KWLXo7TQInWNss/rjDPYq4Pxqs484nKs64qtjQfN8ya86nJmBodo4GJDNPGSlyJBCjTRjrvxIT0sJr22vyo+Z/eEam2nKRP0KjmochBrgrZr9egIwwWf0SEvZBel4aw0nx+5nZtPitlRIjysJTZ2twqwSsLnU1p4g1dnMW3amhYA8XssBbKeZGQwCLq9F9pRD4rWGSZq9ScCMgs1lqQteY6zdpoyEY2aiOfcrVMDVAeUB7lU8vZQzddukLcfT4t8p518eNlqTqkpqjgsU/1Uws5wxRdHmC6ObGH7i9nUKBnLC8llHBDXSInbHt30HpiVyI31Fj2WQvIYNYRUNXUkxvWR4BSMUkL/YlAahgdNmmncWdYA+U8IUnvM6WK4ewJcXnoQn5YH/VMlY9tR9juUiopZjl+oksTSxjpciIKB61kBAuI18ZuBsmaUFfEJliuSgkDWEX4gaqGTyiU+clnUvfgl8Xk8xqHI9JRy3oelxEScY8V84im2uKjP3mkU0cVRzkhsXKctKiODKEbXehAPZWc5qi4OwTekqTkf3Cad9WSHYKSAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[48.8020210266113,306.822662353516,1],[76.4686889648438,306.822662353516,1],[76.4686889648438,322.822662353516,1],[48.8020210266113,322.822662353516,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[62.6353530883789,314.822662353516,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;261&#34;:{&#34;id&#34;:261,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.800000011920929,-0.800000011920929],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAAAwCAQAAAD6Se8ZAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAADyklEQVRYw+2YXWxURRTHf4vtFrWANsZWK34Eo5VUaPyAgE1U1Jog50UfQBMSCZFo1YiNMRDDiw8kaHwxKkQlaAW/gtHk8ILYBg2mJkarhZoGY8QYKULRraXVUrb1obvnzn5076rTiQ+cfbj/c+c/d345c/fOnQtn499HolSjrORdAFbrTn9DSh0raWYhFzGbEY7RSwcfaP8/xJM5HGSuXzyp5XlWUVnQMMZONuqv+adnlLjW9gycv7qt4DtWF4GDStbQJ8vLxpPN3OcZbhUfUlPCcAEqD+SeqpjiUk+z0TPcUtqd0f5iD4cYoJ5FLLNbbAZvyk/6eQyePMsmz3BzeN+Z1Ddo09+tbR6vc5vx7JL5OpJtK5hcmSlv+4YDNlFveoOuieBAf+AOtll6hTtveXhyHV3c75tN6nncknbdkt+u4zyGWrpeLiyCJxXSxlc0ea8crCOZUUO0FTNomrWkMkk16wrwZBndvMC51uMX/vRUuwRrLdmhJ4u79ASvWvJgDp40SicdNDrur1nCCH7iBue+21XC95apBml0q7eC2x3bBC+yVH/2BActpk7w5dQ2PUQ05j2Th8IHSx8P66fe0ABuMdWlEyWdXbZOZfrk/nMHeJKFnuHgelPdMc5vTd08eYiqN8hLPKd/eEZDZnG5JX0x5u9N1cksHcri/cijtOsp32gAXOnoIzFe936/ip4Mnr43LWCTUevoozFe953vUnpKv1D5iTpHn4zx/uboGgiBZwsUaR2O8Z5iIrff9ONVmYqDQyeclWpmaLwzZbjTpir/j3hjofHGTSXKcEc86TB4p01VlOGOPKNh8EZNJctwJ3P7TT9eytR5EjOaJB284TB40aM4QXWMd7ajj4fBc3f+tTFed4U5FgbvyBTDx+H1B8HTfmdTcHWMOWof1KNB8ICDphpinNea6p08hMCL9hc3xTgXmfomHN5nphZL1dQ2qeZGS/aFw9tnq+353FXCt9zW5zN0BsPTFB2WPFLC2GpqT3bPE6J68FpUIWkpbpF7udUS+15QzjIdGzmL0aiOFRg+4jDXZPQ7skQPF1yhkR2WdLM3K/1UbzND9nuisFnTPGNJDZ/I4jy4Zj52FrSn1F7CwkwuupvdlszlgLwsCyQBkpAm2cp+LrHWbdoZ9fMyuWXFQzTYR6YKWmnltBzn4rzXrC9Y76aBqgeaoiX7sM1Eksvy4A5wt466J4LhgfbTzFbn5T430mzhzvyPKAHxQIe1lQVsZzCvIcUrNOqG3MpBedsT7yHn0MR86qhiiAF66NXx/37Vs5EffwN/lvHYgUz1UQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMOub3yUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMTAtMDZUMjA6NTM6MDIrMTA6MDCaxmeZAAAAAElFTkSuQmCC&#34;},&#34;vertices&#34;:[[48.8020210266113,374.985168457031,1],[75.1353530883789,374.985168457031,1],[75.1353530883789,390.985168457031,1],[48.8020210266113,390.985168457031,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[61.9686851501465,382.985168457031,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;262&#34;:{&#34;id&#34;:262,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-0.899999976158142,-0.899999976158142],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAwCAQAAABXyPewAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAFxElEQVRo3u2aaWxVRRTHfw+6ILRCC10AqxIIFKz4AggqVZTNUBhDiAlgIi4saoMpEDSgYuIHETRBjUEISsTKkrDEmGELCBIogUgEZRchokXLUuqrlbJ0eX7gMXfe0nffzG0TPnD6of9z5z/33P+9M3PPnPvgjt3e5vN6ApHLeAp5iE7cTS3nOcYONsiK5rg48R7vJki9ItOaQZDI4SMmkBzVUMdK5soLngV9xzOmglp5CDeG4zwfQw4k8xInRZFXQfjNu1gLEhP4lsw4hA5I8ZwXNSKDe817JVkGe4xSre81NnKUSroykKFqGLfia/GH3GutyG/TyUqQaM9abaitYJb8R7V150ueVGdfJfrIWs+CdvCsCzfoSRDz6KrwHLlQb5JnxDAW82rIvY+5zPMs6EcZSLSTxRwSXXldOaXhcgBkI9ORyp0hMjwL+inxTjaLwjRSQqiGWbEIsoHJBEJOGtNs1IgUeivnYAsKEj4mK+creTk2S15imXJetBHEA2qWVsnfW1AQ/bT5syoO7xuF8kWBhSC/QgbPx0bQSIUucaBpmjxKuXJGexJkMINsBA1WaJ8MxmXui9HnNhT0oEKHXJi/KPSwhaC+ChkNOcP3kEjX0pGTLuTfFMoV6bLGKE43OoRgQJ4BkcRohjOYLmQS4AKn2cIm+ZdnQdyv4bMu3HINd+OwURy/QgdFKjOZri1FWWRRwFgaxUrekeXhHU2HXI6G/3bh6nuiLoZxHEGpHOUDTY5+7ZM4JV7xJihXw5dduFUazsTMHEGD6RGH14al4hOhqTAdck4a0yCvuHD/I6gyb9P0xx91pJHT/Ek92XSnfVhLCXW8ccsxfUKpCrnJQQa5qpw2JkGidkLnKCFX9pIj5CjZn048zjr0V8ZsZ+dl+oQcQfUJsBsUSk6A7Zg/zFvLNFmt3ah6yigTT7CBTurgUrFVVoGXJ5SIoLpmELRAjtflKFm7eUSbxem3Bp2poEaFEimvOGdvSIDt2FamMp817Gc1bzVFkmfQt/jTRTswH3I3FEqkp8O5bhJEnuBEQrxtYgujQk4aQ9gcCilSES59N8mrEReWgrs5HCNBBvaxEgQjlCAyWOfSMY9zAGrbBm1FK9kYr4tI0QS5romWtofral73A/M55ExDH2ku3Ls1fLFl9MhrWgqcZSNIr4bmuHD1rOJ8ywgCLnkTdLaJC3YT1Cy17pjmLOlJFoJkBU6VrYcL2Wmvlm6JrL2lK1SpVMnzBkX7IwwKoXwXZi+Fjtldq0iWda4kJ1u4rAQZ2QElaIALc6BCPxvJGMUUsskmiw4iX56Ky22NU4A5AjZb8N0KDRKpTdNEGv2Vs90oQlvGUUhPMvBpNyW2+bUht8dO0HaVxbVjRBxekXo/1LPTKIK+tx3rwn1ZoUZ+sBIkA+xQzmtxiMUKbZT/GoU4jVNYHCPirKUiVytibrq5GbcpBX+hUJEYGZsixjFEOcvcThhxy4KUKieV95uU42MFbZX76c1/Fp8kRWuO0zPkVPFo9LQVBexVecIhBkSnSGFp0fXItUzk8St3KfcFWUqUCR+LmKHczTJUzLR4QrKBt5WTyfdiUHi7KGSblvbMjpnxzadG/ZVERShnvuYuFzOj5GSySpNT7XwQsPokKdezXjl5lInFoq/wgfAJv1jCLjqr1qXSbEG4ZR9qZeYkFokDYqIIFVpEbzGPU0xU7UGmOBU6y0+STCVfvQGSKKaYG+Ii2RGbiv3aXTS7ZTdEEXu0V/cAVhMUVdSSExEjSIl0bq/tR2MZYGTE6zKFeyJClfG0tN4HyUqGsivskI+O5EXEqGWS/Ew/YP0VXFZQyBKa2hE1sJDhhst1dIRhzCXeOXbSX64MP+ThdwryiiymL8uJLGEE+JwCOcf+6agIjXIBebzJwagbV80anpLDZFR93fNPY0C0xk8fckmlhkoOcyz+TtYqRnsG0pmOtKOWCk5yWJqVXe7YbWP/A8c6gtAtjnM1AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[132.285781860352,70.3218765258789,1],[166.952438354492,70.3218765258789,1],[166.952438354492,86.3218765258789,1],[132.285781860352,86.3218765258789,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[149.619110107422,78.3218765258789,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;263&#34;:{&#34;id&#34;:263,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1,-1],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFMAAAAwCAQAAADH245/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAADzElEQVRYw+2YSWgUQRSG/5mYiZhFDGJGo1FRTJAYg1vQBAwuEdS6eFHxoCIK5qIEDwbxKohnF1xwPwgRDy94UCNBIgoe4hYRN5SAUeMyMYtmmeihp1/XdM9Md1UFT75c6tWr/r9/Xqa7ahr4H2MXodTTIorNqMFCTEYBBvAJHWjBdeoaS7QKI4VNUYRj2IJsT2EYV9BIn8fEoiLDY1NsxEUUptWPYRvdNDapzMhyCWzBNeRmIIzH1tI3r54ZmdRgJHVTrECr9I/4jWY8x1cUYxlWSStHUEv3tU1qMSSbYiI6UMzpBTTQD67NwVnUcu0D5tOAlklNRljSOCwJHKSdjgBAb7EapzidiUbNZmoyuJuiGO8QSSSXaHuKTmThBkQi6UOJjAjYS22G0809LNCLhlQQimMXYokkD3s0eqnNSNgUIezitefpW2oKdeM0JzuUe2nAsLu5SPrOXM3AusyjMlGu6NOAYdus41I3HqVXoOfo5GSDok0Dhm2zmgsP6E9G2AMeVUMtDBi2zQVcaPeBPeHRUkWbBowwAIh8lHDhpY/Eax5FRX5wj2YMq5uzpCXvfSQ6pfHs4DbNGJbNImn6o4+EfB6cpmDTiGHZjErT33wkvkvjQgQPI4ZlcxJPxqnfR6IPzl06CcHDiGHZzOFJPwHQH/ziZLyCTSOG2+ZIAGCcR9kBVnttajB0bA7/A5suhmVzlCdDASScU1U8wGo7jBhWOsST4wJIOGsGFWwaMcIuXCSARCRZImAYMSybMZ6cIMKZrxcRScL3npXCiGFd4DxuQ8jzwRVI4y8KNo0Ylk35LUORj4S8m3xSsGnEsGy+T7PET0LlnZIRIwwA1AXnV/dcHwmn3kN+RwgpzBj2l9l5FVLmI1HKo47gJk0Ztk3nt8kSH4llPHqsaNOAYdu8x4UqkZP+epGHxZzcVrRpwAhzau+0uVibAbWe9+YR3FW0acBI2KQYWnjZ3gwS9Txqpp9qLk0Yzn5wxvk0oi719WITVnJyGuqhzXBedWXhBeYlku9YTq88AuW4z/tDO5bQqGeFvMkN0rCnrs3gblIch3h1Ie6IKpdADW5Jm9gBr0kAR9DLf/u8ZX2GdAigJjRxMgNt4rioECFAhESlOIlWTOXqKVK9fQwZyWe/3ShDOVfqUY8h8QVTXEevh9ivZ1KfkXSkohjqXA/tCKa7BNqwjlTOme5+ajFcJz/qQg1OYhSpI46jWKP6IPIY1WB4DqjUT/WowDn0uAoxnEA5HTTppD4j7c8nkYVKzEcUOejFVzxFB6X7/NrxLxj/wxt/AbLlhcX82jseAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[203.778350830078,70.3218765258789,1],[231.445007324219,70.3218765258789,1],[231.445007324219,86.3218765258789,1],[203.778350830078,86.3218765258789,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[217.611663818359,78.3218765258789,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;264&#34;:{&#34;id&#34;:264,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.10000002384186,-1.10000002384186],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFMAAAAwCAQAAADH245/AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAAFl0lEQVRYw+2ZaWxUVRSAv4GhVWgFCl0AqxIIFKw4AQS1VZTNsFxDiAlgIi4saoMpEDSgYuIPETRBjUEISsTKkiDEmMMWECRQApEIyi5CRKuWpdTWSgXazvij03vvrG/eTPnH6Y+ec+65937vvPvuNnBLWk880d0qj0kUcz9duYN6LnCCXWySytboUr3NWwmGXpWMmJgql/eZTLuIggbWsEAupoz5DU+6xWwT0ch4TvJMFEhox/OcVmNTxcTnvkoYpprM12TFie+EqKdTYVSduct9LW9IEw9TZnmusZnjVNGDIQzXw6MNX6jfZH/SnL5kKlmYqiMbrJe9mrnyty7rxWc8puusVf2lPmXMXTzlEBuIls2F9ND6fFlix8s5NYJlvBQ072YBC1PG/F5qEq2kx6bqwSvaWxYKCSB+ZiHanK06p4z5Q+KVzCc0k7SgVsfcaKHSxDRanj+DmckwqjT6aeOwa0zlYZr2fS5XogfLZVZq47lkMLlXj/5q+dU1JgOtcbk2TvyXWitQhUlg+rTmIpcGc7T2XOZQ7HA5ToU2xqWE6WJkGswi7Tkggbg1DmitCPeSIuZ92nPEocZPWnsgCcwBWnP10r0AKtNawE471PhFa3kqU+rcdKZ60imo1sg5UF7GMZIiupNFDRc5yza2yJ8xMLnH8px36KvC0nty1FUufSaXKp05zLI+3GyyKWQCfrWGN6UitGLzS8+1PH85dGXvObu7grQx0znOuxakTTSVM+rFaJh5lifGnKml2tKzcCcGs4jeceJuY4X6UFm7t+aXbha+Jrnq0NW/BPRuye2C6Yvw+DnL7zSSQy86hpSU0sCrLUYzcboudIJEAvxnPbULidhp/kEpedJXRskYGURXHuEr7MlwntnZesMwGxPor0lr7RKIjpXLDcyUWuvxGymnXD3KJrpq5wq1XaqjZTMRzIZWwFwsk2xIDbuXB62vI7PltTdj+nVBjJNmiJih3ZRAtJHtzGAR6znIOl6PFSTnsA8xs1QHaHnpN7Tbi7OYmOtuKOUUpxKK26G2MSZoZDCMrS2ZMd2lJdCOiXGF6UI+sPRR0IJZo53tVZv4Lag0C9NxXkhS9lkJGGgwzaD1kOHQxB2WfunmUMo1a4OTbTDtm4xchzbsFevCzcEELkfDPB8DwwmzVe6UooqZrLwaUyoxp+7eDg2Y8lpx2qYkL5laq9KYwDHtLnBooK/WTiRHoBJZFMxKdAXMHHiIoUFtsEMDQ7T2oyu4MUwnhxyy6aQK5Ezc2LaY4+AxMNncq91DVXqcBjIYpI2drpLYnokU04fOeKxHjS4+66XvszF36tW8Q/OEGkPG6vW/kd2uMO19/gSH2Be05uc7C1Nq2KWLXo7TQInWNss/rjDPYq4Pxqs484nKs64qtjQfN8ya86nJmBodo4GJDNPGSlyJBCjTRjrvxIT0sJr22vyo+Z/eEam2nKRP0KjmochBrgrZr9egIwwWf0SEvZBel4aw0nx+5nZtPitlRIjysJTZ2twqwSsLnU1p4g1dnMW3amhYA8XssBbKeZGQwCLq9F9pRD4rWGSZq9ScCMgs1lqQteY6zdpoyEY2aiOfcrVMDVAeUB7lU8vZQzddukLcfT4t8p518eNlqTqkpqjgsU/1Uws5wxRdHmC6ObGH7i9nUKBnLC8llHBDXSInbHt30HpiVyI31Fj2WQvIYNYRUNXUkxvWR4BSMUkL/YlAahgdNmmncWdYA+U8IUnvM6WK4ewJcXnoQn5YH/VMlY9tR9juUiopZjl+oksTSxjpciIKB61kBAuI18ZuBsmaUFfEJliuSgkDWEX4gaqGTyiU+clnUvfgl8Xk8xqHI9JRy3oelxEScY8V84im2uKjP3mkU0cVRzkhsXKctKiODKEbXehAPZWc5qi4OwTekqTkf3Cad9WSHYKSAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAw65vfJQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0xMC0wNlQyMDo1MzowMisxMDowMJrGZ5kAAAAASUVORK5CYII=&#34;},&#34;vertices&#34;:[[271.940826416016,70.3218765258789,1],[299.607513427734,70.3218765258789,1],[299.607513427734,86.3218765258789,1],[271.940826416016,86.3218765258789,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[285.774169921875,78.3218765258789,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;265&#34;:{&#34;id&#34;:265,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.20000004768372,-1.20000004768372],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAAsCAQAAABSpFnOAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAACVElEQVRIx9WWzUtUYRTGf2NjA2nkwtCiLKhsINKoRR+06GPTTmoXuAoCK4JKKEUIymxT/gMhRFCtC/qg6IM2RZpggpuyDyqiLEgky6bRaTNO85x57zt37mzq3MUw5zzPb+658573vfA/RCz7WcVCyaf5EMK9LOd3eGp4TybvmmFbUeB+cWQ4bgU7mBHBKPO8wEa+i/6u3HE2es2v9nqAcfpF+5l6lyzBsMim2RiI7DGPaVeQsIkpkY4w16nbyrTozvmeULtpvtuhWcBb0QxQ6UPGeCDyFM0FmsuimGAlRWIp38QySFzqe00frcWALlNHXq2BcaldCgMEuCq2n7nWKngklRdUh0XW8E6s97L5Tsn+Yn1YIMB2M0utQDMpyR0pBQhwXuyfqGVIMjddA+iPBM8FoWvxo9m5QsZaM0v5o7ozChDgWACyJyoQYtx3AJ+YxV9iLDGzlGGc5eUAAQ4b5LVygZUMFjS+pzzkWcez/Mqi6EC71c5et6MC5/M6YBFlOBQNeVEgb+TbD5KlA3cLYookVyTzzH88FEY9XwRwAqhlTHJnSkPeEnM/cwC736fZEh540Gy1a3KV61J5FXZXX82kGLvyaovNgPaFAcYZ8J6Q+8xyaimO7BZDiqYCxR1RjFHnB24mLYaTDk0DE+bI8EQ1oyIeClh7B0zzbcHIPhH+Zl2ALsZDUU7S6Ba2mN8+7elnhVkVT107fZ2ZjeGAF8HZOGpu4FSh5IZpeoP/f6SCx2aWNqmgLcIZmDSH8kuq/hZXmVf5ERIhkNBhbuRCKNc/EX8AKBc0vnq7zakAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDIrMTA6MDDrm98lAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAwmsZnmQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[211.429718017578,41.7392730712891,1],[225.096374511719,41.7392730712891,1],[225.096374511719,56.4059371948242,1],[211.429718017578,56.4059371948242,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[218.263031005859,49.0726089477539,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;266&#34;:{&#34;id&#34;:266,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;specular&#34;:&#34;#000000&#34;,&#34;textype&#34;:&#34;rgba&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;point_antialias&#34;:true,&#34;line_antialias&#34;:true,&#34;isTransparent&#34;:true,&#34;polygon_offset&#34;:[-1.29999995231628,-1.29999995231628],&#34;uri&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAA7CAQAAACjtQDTAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfkCgcGNQLe1AwEAAACwElEQVRYw9WYb2hNcRjHP7u7d1tkZDT5k5YX1EqRv8UbCQuj5H9qiuUFL4gXCq+8IC9ItlJ0Z0SStZpSe4OUkRJaGWLZGK01srZ2d91dL1x3z3PPPef3O+e84Tlvznme7/M5z++c83t+v3vh/7ArpMVx0jovSq/IuzUWWKGAHdbADSpvnQy9U6FFlsDbIqeHQoBIJnRNCXdb4SZSLa5ukJLBWaTE3b7+uZvB9qlRVeaGW1V4jQXwkdA/d4Z3KWCjETebUaE/6BSU8EMIBhhnAJ4Q6hHK8kkuqxp3GoAdQtuUX7JMAe954pYo7SY32RshSjLFA3hJKHuJjQUiStYgzqNsd8XFVOwmSTfhdH6JOz9xBVarAS/wejb3lXSOi+qO0Lz2fNZss+g7kxgWmiPewGL6jX2nVr26cgxWZ+w7j60/LgAWK+AFR7xCTbmtZiC0i4Rvjr5zSkT7KbYBHlU1rs2JylZcb4ODcpKufUdPz6V2QGhx7Tv1gdYetqg6dmT9MfqE/7g9sEglNmf964U3xUx7IFwUqcOUZrwNwtvqBwcL1aD3ZOr+Lnx2K6OwVyK5xTHgn8YlwmGHRXqC8egNy1W/OJjKiABsBLrF9Ur/QGgWgDoqxdUHCtySIh7AuDivUkt/I+kgFcbUZm1sDo9SEQQHcF59PH+Ph0FxMD8vcG9wILxw4AaZ4JUQMQDjDk8TA2EqLCORU+HqMDiAuwrXZRqTaci5g77OaNgK56kK55rk5gplm2rjbdj6Cvgo6tsfFqd/Eg1lO3cIiwtgPDxuMoMCuDw88LTAvQyPW6X2szXhYIXUMiRwn+22RRDNnhXRyTPe00cpM6himtKdIeG/qp683S9NmnZxYx/21AWX9PN+5dTrctEcoy1IfXAub332/0A47JAD1s1mvxC5g+7kE0lilJDiCw84ywHag9f3r9pv6dIs5/H/kV0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMDZUMjA6NTM6MDIrMTA6MDDrm98lAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTA2VDIwOjUzOjAyKzEwOjAwmsZnmQAAAABJRU5ErkJggg==&#34;},&#34;vertices&#34;:[[30.3854293823242,239.583038330078,1],[30.3854293823242,252.916366577148,1],[10.7187623977661,252.916366577148,1],[10.7187623977661,239.583038330078,1]],&#34;colors&#34;:[[1,1,1,1]],&#34;texcoords&#34;:[[0,0],[1,0],[1,1],[0,1]],&#34;centers&#34;:[[20.5520973205566,246.249694824219,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:46},&#34;249&#34;:{&#34;id&#34;:249,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0.32139378786087,0.342020124197006,0.88302218914032]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;246&#34;:{&#34;id&#34;:246,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;back&#34;:&#34;filled&#34;},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;248&#34;:{&#34;id&#34;:248,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;fog&#34;:false},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;250&#34;:{&#34;id&#34;:250,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;243&#34;:{&#34;id&#34;:243,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:1,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:243,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,921.663146972656],&#34;modelMatrix&#34;:[[0.70710676908493,0,0.70710676908493,-122.845428466797],[0,1,0,-216.362213134766],[-0.70710676908493,0,0.70710676908493,-799.524841308594],[0,0,0,1]],&#34;projMatrix&#34;:[[4.66506338119507,0,0,0],[0,3.88755249977112,0,0],[0,0,-3.86370348930359,-3322.48901367188],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[0.70710676908493,0,0.70710676908493,0],[0,1,0,0],[-0.70710676908493,0,0.70710676908493,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:0.800000011920929,&#34;bbox&#34;:[10.7187623977661,335.740600585938,41.7392730712891,390.985168457031,0,1],&#34;windowRect&#34;:[0,0,360,432],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:false,&#34;fontname&#34;:&#34;NULL&#34;,&#34;maxClipPlanes&#34;:2147483647,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[250,253,254,255,256,257,258,259,260,261,262,263,264,265,266,249],&#34;subscenes&#34;:[],&#34;flags&#34;:17006},&#34;273&#34;:{&#34;id&#34;:273,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:273,&#34;sphereVerts&#34;:{&#34;reuse&#34;:&#34;rgl39345&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A level 3 menger sponge in R</title>
      <link>https://coolbutuseless.github.io/2020/09/27/a-level-3-menger-sponge-in-r/</link>
      <pubDate>Sun, 27 Sep 2020 18:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/27/a-level-3-menger-sponge-in-r/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;level-3-menger-sponge-in-rgl&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Level 3 menger sponge in &lt;code&gt;{rgl}&lt;/code&gt;&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(rgl)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The base cube
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sl  &amp;lt;- shapelist3d(cube3d(alpha = 1, color = &amp;#39;grey90&amp;#39;, specular = &amp;#39;black&amp;#39;, lit = TRUE), plot = FALSE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Given a shapelist, calculate the next level of the sponge
#&amp;#39; @param sl shapelist3d() object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_next_level &amp;lt;- function(sl, level) {

  scale &amp;lt;- 1/2
  sla &amp;lt;- scale3d(sl, scale, scale, scale)

  x &amp;lt;- 1.5^(level-1)
  shapelist3d(
    list(
      translate3d(sla, -x, -x, -x),
      translate3d(sla,  0, -x, -x),
      translate3d(sla,  x, -x, -x),

      translate3d(sla, -x,  0, -x),
      translate3d(sla,  x,  0, -x),

      translate3d(sla, -x,  x, -x),
      translate3d(sla,  0,  x, -x),
      translate3d(sla,  x,  x, -x),

      translate3d(sla, -x, -x,  0),
      translate3d(sla,  x, -x,  0),

      translate3d(sla, -x,  x,  0),
      translate3d(sla,  x,  x,  0),

      translate3d(sla, -x, -x,  x),
      translate3d(sla,  0, -x,  x),
      translate3d(sla,  x, -x,  x),

      translate3d(sla, -x,  0,  x),
      translate3d(sla,  x,  0,  x),

      translate3d(sla, -x,  x,  x),
      translate3d(sla,  0,  x,  x),
      translate3d(sla,  x,  x,  x)
    ),
    plot = FALSE
  )
}

rgl::clear3d()
sl &amp;lt;- create_next_level(sl, level = 1)
sl &amp;lt;- create_next_level(sl, level = 2)
sl &amp;lt;- create_next_level(sl, level = 3)

shade3d(sl)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/menger/menger.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the {triangular} package for decomposing complex polygons to triangles</title>
      <link>https://coolbutuseless.github.io/2020/09/26/introducing-the-triangular-package-for-decomposing-complex-polygons-to-triangles/</link>
      <pubDate>Sat, 26 Sep 2020 20:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/26/introducing-the-triangular-package-for-decomposing-complex-polygons-to-triangles/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;triangular&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;triangular&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;triangular&lt;/code&gt; decomposes complex polygons into sets of triangles and works with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;polygons with holes&lt;/li&gt;
&lt;li&gt;self-intersecting polygons&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/triangular&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/triangular&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;This is a basic example which shows you how to solve a common problem:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(triangular)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;polygon-with-a-hole-in-it&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Polygon with a Hole in it&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# polygons_df - data.frame of polygon vertices with group/subgroups
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polygons_df &amp;lt;- df &amp;lt;- data.frame(
  x        = c(4, 8, 8, 4,   6, 7, 7, 6),
  y        = c(4, 4, 8, 8,   6, 6, 7, 7),
  group    = c(1, 1, 1, 1,   1, 1, 1, 1),
  subgroup = c(1, 1, 1, 1,   2, 2, 2, 2)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# How &amp;#39;ggplot2&amp;#39; handles this case
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(polygons_df) +
  geom_polygon(aes(x, y, group=group, subgroup=subgroup)) +
  geom_path(aes(x, y, group = interaction(group, subgroup)), colour = &amp;#39;red&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;ggplot2 rendering of original polygon(s)&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Turn the polygon data.frame into individual triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res &amp;lt;- triangular::decompose(polygons_df)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove the triangles which are &amp;#39;interior&amp;#39; according to the even-odd rule
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tri_df &amp;lt;- res$plot_df %&amp;gt;%
  filter(interior)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot the triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(tri_df) +
  geom_polygon(aes(x, y, group = idx), alpha = 0.3, colour = &amp;#39;blue&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;Decomposition into simple tris with {triangular}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-2-2.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;polygon-with-two-holes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Polygon with Two Holes&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
poly &amp;lt;- df &amp;lt;- data.frame(
  x        = c(4, 8, 8, 4,   6, 7, 7, 6,  4.5,   5, 5, 4.5),
  y        = c(4, 4, 8, 8,   6, 6, 7, 7,  4.5, 4.5, 5, 5),
  group    = c(1, 1, 1, 1,   1, 1, 1, 1,    1,   1, 1, 1),
  subgroup = c(1, 1, 1, 1,   2, 2, 2, 2,    3,   3, 3, 3)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;quot;Native&amp;quot; ggplot2 rendering
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(df) +
  geom_polygon(aes(x, y, subgroup = subgroup), colour = &amp;#39;red&amp;#39;) + 
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;ggplot2 rendering of original polygon(s)&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Decompose into triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res &amp;lt;- triangular::decompose(poly)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove the triangles which are &amp;#39;interior&amp;#39; according to the even-odd rule
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tri_df &amp;lt;- res$plot_df %&amp;gt;%
  filter(interior)

ggplot(tri_df) +
  geom_polygon(aes(x, y, group = idx), alpha = 0.3, colour = &amp;#39;blue&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;Decomposition into simple tris with {triangular}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-3-2.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;two-polygons-with-one-hole-each&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Two Polygons with One Hole Each&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Two polygons with one hole each
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
poly &amp;lt;- df &amp;lt;- data.frame(
  x        = c(1, 4, 4, 1,  2, 3, 3, 2,      5, 8, 8, 5,  6, 7, 7, 6),
  y        = c(1, 1, 4, 4,  2, 2, 3, 3,      5, 5, 8, 8,  6, 6, 7, 7),
  group    = c(1, 1, 1, 1,  1, 1, 1, 1,      1, 1, 1, 1,  1, 1, 1, 1),
  subgroup = c(1, 1, 1, 1,  2, 2, 2, 2,      3, 3, 3, 3,  4, 4, 4, 4)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;quot;Native&amp;quot; ggplot2 rendering
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(df) +
  geom_polygon(aes(x, y, subgroup = subgroup), colour = &amp;#39;red&amp;#39;) + 
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;ggplot2 rendering of original polygon(s)&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Decompose into triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res &amp;lt;- triangular::decompose(poly)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove the triangles which are &amp;#39;interior&amp;#39; according to the even-odd rule
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tri_df &amp;lt;- res$plot_df %&amp;gt;%
  filter(interior)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manual rendering of triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(tri_df) +
  geom_polygon(aes(x, y, group = idx), alpha = 0.3, colour = &amp;#39;blue&amp;#39;) +
  theme_bw() +
  coord_equal() + 
  labs(title = &amp;quot;Decomposition into simple tris with {triangular}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-4-2.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;polygon-from-random-points&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Polygon from Random Points&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 10 random points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
poly &amp;lt;- df &amp;lt;- data.frame(
  x        = runif(10),
  y        = runif(10),
  group    = 1,
  subgroup = 1
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;quot;Native&amp;quot; ggplot2 rendering
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(df) +
  geom_polygon(aes(x, y)) +
  geom_path(aes(x, y, group = interaction(group, subgroup)), colour = &amp;#39;red&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;ggplot2 rendering of original polygon(s)&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Decompose into triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res &amp;lt;- triangular::decompose(poly)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Remove the triangles which are &amp;#39;interior&amp;#39; according to the even-odd rule
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tri_df &amp;lt;- res$plot_df %&amp;gt;%
  filter(interior)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manual rendering of triangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(tri_df) +
  geom_polygon(aes(x, y, group = idx), alpha = 0.3, colour = &amp;#39;blue&amp;#39;) +
  theme_bw() + 
  coord_equal() + 
  labs(title = &amp;quot;Decomposition into simple tris with {triangular}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-26-triangular-complex-polygon-decomposition_files/figure-html/unnamed-chunk-5-2.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>What&#39;s the upper limit on serialization speed in R?</title>
      <link>https://coolbutuseless.github.io/2020/09/22/whats-the-upper-limit-on-serialization-speed-in-r/</link>
      <pubDate>Tue, 22 Sep 2020 17:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/22/whats-the-upper-limit-on-serialization-speed-in-r/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;serializer&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;{serializer}&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;serializer&lt;/code&gt; is a package which demonstrates how to use R’s internal
serialization interface from C. The code is the minimum amount of code
required to do this, and I’ve inserted plenty of comments for guidance.&lt;/p&gt;
&lt;p&gt;This package was developed to help me figure out the serialization process in R.
It is perhaps only really interesting if you want to look at and/or steal the C
code. It’s under the &lt;a href=&#34;https://mit-license.org/&#34;&gt;MIT license&lt;/a&gt;, so please feel
free to re-use in your own projects.&lt;/p&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/serializer&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/serializer&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(serializer)

robj &amp;lt;- sample(10)
v1 &amp;lt;- serializer::marshall(robj)
v1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 42 0a 03 00 00 00 02 00 04 00 00 05 03 00 05 00 00 00 55 54 46 2d 38 0d 00
[26] 00 00 0a 00 00 00 09 00 00 00 04 00 00 00 07 00 00 00 01 00 00 00 02 00 00
[51] 00 05 00 00 00 03 00 00 00 0a 00 00 00 06 00 00 00 08 00 00 00&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;serializer::unmarshall(v1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  9  4  7  1  2  5  3 10  6  8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-the-upper-bound-on-serialization-speed&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s the upper bound on serialization speed?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;calc_marshalled_size()&lt;/code&gt; can be used to calculate the size of a serialized object,
but does not actually try and create the serialized object.&lt;/p&gt;
&lt;p&gt;Because this does not do any memory allocation, or copying of bytes, the speed
of &lt;code&gt;calc_marshalled_size()&lt;/code&gt; should give an approximation of the maximum
throughput of the serialization process when using R’s internal serialization
mechanism.&lt;/p&gt;
&lt;p&gt;The speeds below seem ridiculous, because at its core, serialization is just passing
&lt;em&gt;pointers&lt;/em&gt; + &lt;em&gt;lengths&lt;/em&gt; to an output stream, and doing very very little actual
memory allocation or copying.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 1e7
obj1 &amp;lt;- data.frame(
  x = sample(N),
  y = runif(N)
)

obj2 &amp;lt;- do.call(rbind, replicate(1000, iris, simplify = FALSE))
obj3 &amp;lt;- sample(N)
obj4 &amp;lt;- sample(10)

n1 &amp;lt;- lobstr::obj_size(obj1)
n2 &amp;lt;- lobstr::obj_size(obj2)
n3 &amp;lt;- lobstr::obj_size(obj3)
n4 &amp;lt;- lobstr::obj_size(obj4)

res &amp;lt;- bench::mark(
  calc_marshalled_size(obj1),
  calc_marshalled_size(obj2),
  calc_marshalled_size(obj3),
  calc_marshalled_size(obj4),
  check = FALSE
)


res %&amp;gt;% 
  mutate(MB = round(c(n1, n2, n3, n4)/1024/1024)) %&amp;gt;%
  mutate(`GB/s` = round(MB/1024 / as.numeric(median), 1)) %&amp;gt;%
  mutate(`itr/sec` = round(`itr/sec`)) %&amp;gt;%
  select(expression, median, `itr/sec`, MB, `GB/s`) %&amp;gt;%
  knitr::kable(caption = &amp;quot;Maximum possible throughput of serialization&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;Maximum possible throughput of serialization&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;GB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;calc_marshalled_size(obj1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.42µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;84786&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;114&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9746.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;calc_marshalled_size(obj2)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.23µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;163324&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;783.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;calc_marshalled_size(obj3)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.36µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;137883&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5043.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;calc_marshalled_size(obj4)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.52µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;298593&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;R’s process of chopping up an object for serialization is fast.&lt;/p&gt;
&lt;p&gt;The limiting factor in the speed of serialization is whatever the actual output stream does
with the description of the bytes.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>xxhashlite - hash arbitrary R objects as fast as possible</title>
      <link>https://coolbutuseless.github.io/2020/09/22/xxhashlite-hash-arbitrary-r-objects-as-fast-as-possible/</link>
      <pubDate>Tue, 22 Sep 2020 06:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/22/xxhashlite-hash-arbitrary-r-objects-as-fast-as-possible/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;xxhashlite&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;xxhashlite&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#maturing&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-maturing-blue.svg&#34; alt=&#34;Lifecycle: maturing&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/xxhashlite/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/xxhashlite/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xxhashlite&lt;/code&gt; provides simple access to the &lt;em&gt;extremely&lt;/em&gt; fast hashing functions
in &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt; for in-memory hashing
of R objects.&lt;/p&gt;
&lt;p&gt;This new version of &lt;code&gt;xxhashlite&lt;/code&gt; (v0.2.0) is a major update which now offers fast
hashing of &lt;em&gt;any&lt;/em&gt; R object by internally leveraging R’s serialization capabilities.&lt;/p&gt;
&lt;p&gt;This package is a wrapper around &lt;a href=&#34;https://github.com/Cyan4973/xxHash&#34;&gt;xxHash v0.8.0&lt;/a&gt;.&lt;br /&gt;
See &lt;code&gt;LICENSE-xxHash&lt;/code&gt;
for the copyright and licensing information for that code. With this latest
version of xxHash, the new (even faster) hash functions, &lt;code&gt;xxh3_64bits&lt;/code&gt; and
&lt;code&gt;xxhash128&lt;/code&gt;, are considered stable.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;xxhash(robj, algo)&lt;/code&gt; calculates the hash of any R object understood by
&lt;code&gt;base::serialize()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/xxhashlite&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/xxhashlite)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;installation---set-cflags-for-optimised-executable&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Installation - set CFLAGs for optimised executable&lt;/h4&gt;
&lt;p&gt;To get the most out of what &lt;code&gt;xxHash&lt;/code&gt; offers, it will be important to set
some optimization flags for your machine. The important compiler flags to set
are &lt;code&gt;-O3&lt;/code&gt; and &lt;code&gt;-march=native&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here are 2 possible ways to do this:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Copy &lt;code&gt;src/Makevars.custom&lt;/code&gt; to &lt;code&gt;src/Makevars&lt;/code&gt; re-build package.&lt;/li&gt;
&lt;li&gt;Edit your &lt;code&gt;~/.R/Makevars&lt;/code&gt; to include &lt;code&gt;CFLAGS = -O3 -march=native&lt;/code&gt; (this will
change flags for all future compilation, and should probably be used with caution)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;why-use-a-hash&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why use a hash?&lt;/h2&gt;
&lt;p&gt;A hash is a way of succinctly summarising the contents of an object in a compact format.&lt;/p&gt;
&lt;p&gt;If there are changes to the object (no matter how small) then the hash should change as
well.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(xxhashlite)
xxhash(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;2c8a35b061878544&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Small changes results in a different hash
mtcars$cyl[1] &amp;lt;- 0
xxhash(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;06a3bba3891cfe7e&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;timing-for-hashing-arbitrary-r-objects&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Timing for hashing arbitrary R objects&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;xxhashlite&lt;/code&gt; uses the &lt;a href=&#34;https://github.com/Cyan4973/xxHash&#34;&gt;xxHash&lt;/a&gt; family
of hash functions to provide very fast hashing of R objects.&lt;/p&gt;
&lt;p&gt;For the test case shown below, &lt;code&gt;xxhashlite&lt;/code&gt; is faster at calculating a hash
than all other methods I could find, with a maximum hashing speed in this
specific case of 20 GB/s.&lt;/p&gt;
&lt;p&gt;Note: actual hashing speed will still depend on R’s serialization functions
e.g. small complex data.frames might have a lot of serialization overhead compared
to long numeric vectors.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide the benchmarking code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(xxhashlite)
library(digest)
library(fastdigest)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Simple data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N   &amp;lt;- 1e5
df  &amp;lt;- data.frame(
  x = runif(N),
  y = sample(N)
)

size &amp;lt;- pryr::object_size(df)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Registered S3 method overwritten by &amp;#39;pryr&amp;#39;:
  method      from
  print.bytes Rcpp&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;size&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;1.2 MB&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- bench::mark(
  # {xxhashlite}
  xxhash(df, &amp;#39;xxhash32&amp;#39;),
  xxhash(df, &amp;#39;xxhash64&amp;#39;),
  xxhash(df, &amp;#39;xxhash128&amp;#39;),
  xxhash(df, &amp;#39;xxh3_64bits&amp;#39;),
  
  # {digest}
  digest(df, algo = &amp;#39;xxhash32&amp;#39;),
  digest(df, algo = &amp;#39;xxhash64&amp;#39;),
  digest(df, algo = &amp;#39;murmur32&amp;#39;),
  digest(df, algo = &amp;#39;spookyhash&amp;#39;),
  
  # {fastdigest}
  fastdigest(df),
  
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-3&#34;&gt;Table 1: &lt;/span&gt;Hashing a simple data.frame&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhashlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;xxhash(df, “xxhash32”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;193.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4966&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5921.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhashlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;xxhash(df, “xxhash64”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;198.13µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4856&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5780.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhashlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;xxhash(df, “xxhash128”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;52.68µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18247&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21737.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhashlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;xxhash(df, “xxh3_64bits”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;51.24µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18628&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22348.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;digest(df, algo = “xxhash32”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.38ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;227&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;261.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;digest(df, algo = “xxhash64”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.04ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;242&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;283.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;digest(df, algo = “murmur32”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.58ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;216&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;250.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;digest(df, algo = “spookyhash”)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;168.88µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5643&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6781.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;fastdigest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fastdigest(df)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;201.69µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4741&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5678.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-22-xxhashlite_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The original &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt; software.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=digest&#34;&gt;&lt;code&gt;digest&lt;/code&gt;&lt;/a&gt; package is
a much more comprehensive approach to hashing from within R - multiple
hashing functions and much more configurability&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=hashFunction&#34;&gt;&lt;code&gt;hashFunction&lt;/code&gt;&lt;/a&gt; package offers
some hasing functions that work directly on character or integer values.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=fastdigest&#34;&gt;&lt;code&gt;fastdigest&lt;/code&gt;&lt;/a&gt; offers
the fast non-cryptographic ‘SpookyHash’ and will hash anything that
serialize knows about.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yann Collett for releasing, maintaining and advancing &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining such a great language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing serializer - a demonstration pkg illustrating how to use R&#39;s serialiation from C</title>
      <link>https://coolbutuseless.github.io/2020/09/18/introducing-serializer-a-demonstration-pkg-illustrating-how-to-use-rs-serialiation-from-c/</link>
      <pubDate>Fri, 18 Sep 2020 08:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/18/introducing-serializer-a-demonstration-pkg-illustrating-how-to-use-rs-serialiation-from-c/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;serializer&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;serializer&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/serializer/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/serializer/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;serializer&lt;/code&gt; is a package which demonstrates how to use R’s internal
serialization interface from C. The code is the minimum amount of code
required to do this, and I’ve inserted plenty of comments for guidance.&lt;/p&gt;
&lt;p&gt;This package was developed to help me figure out the serialization process in R.
It is perhaps only really interesting if you want to look at and/or steal the C
code. It’s under the &lt;a href=&#34;https://mit-license.org/&#34;&gt;MIT license&lt;/a&gt;, so please feel
free to re-use in your own projects.&lt;/p&gt;
&lt;p&gt;If you want a rock solid version of this package that already exists, use &lt;a href=&#34;https://cran.r-project.org/web/packages/RApiSerialize/index.html&#34;&gt;RApiSerialize&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/serializer&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/serializer&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Using R’s serialization infrastructure from C involves 2 main parts:
&lt;ul&gt;
&lt;li&gt;a buffer (which could be memory, a file, a pipe, etc) with accompanying
functions for reading and writing bytes to/from the buffer&lt;/li&gt;
&lt;li&gt;input/output stream wrappers around this buffer initialised and created
using R internals
&lt;ul&gt;
&lt;li&gt;Input stream: &lt;code&gt;R_inpstream_st&lt;/code&gt;, &lt;code&gt;R_InitInPStream()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Output stream: &lt;code&gt;R_outpstream_st&lt;/code&gt;, &lt;code&gt;R_InitOutPStream()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(serializer)

v1 &amp;lt;- serializer::pack(mtcars)
v2 &amp;lt;- base::serialize(mtcars, NULL, xdr = FALSE)

identical(v1, v2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;code-for-serializing-r-object-within-c&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code for serializing R object within C&lt;/h2&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide for serialization &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Serialize an R object
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEXP pack_(SEXP robj) {

  // Create the buffer for the serialized representation
  // See also: `expand_buffer()` which re-allocates the memory buffer if
  // it runs out of space
  buffer *buf = init_buffer(16384);

  // Create the output stream structure
  struct R_outpstream_st output_stream;

  // Initialise the output stream structure
  R_InitOutPStream(
    &amp;amp;output_stream,          // The stream object which wraps everything
    (R_pstream_data_t) buf,  // The actual data
    R_pstream_binary_format, // Store as binary
    3,                       // Version = 3 for R &amp;gt;3.5.0 See `?base::serialize`
    write_byte,              // Function to write single byte to buffer
    write_bytes,             // Function for writing multiple bytes to buffer
    NULL,                    // Func for special handling of reference data.
    R_NilValue               // Data related to reference data handling
  );

  // Serialize the object into the output_stream
  R_Serialize(robj, &amp;amp;output_stream);

  // Copy just the valid bytes to return to the user
  SEXP res_ = PROTECT(allocVector(RAWSXP, buf-&amp;gt;pos));
  memcpy(RAW(res_), buf-&amp;gt;data, buf-&amp;gt;pos);

  // Free all the memory
  free(buf-&amp;gt;data);
  free(buf);
  UNPROTECT(1);
  return res_;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide for unserialization &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Unpack a raw vector to an R object
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEXP unpack_(SEXP vec_) {

  if (TYPEOF(vec_) != RAWSXP) {
    error(&amp;quot;unpack(): Only raw vectors can be unserialized&amp;quot;);
  }

  // Unpack the raw vector into a C void *
  void *vec = RAW(vec_);
  R_xlen_t len = XLENGTH(vec_);

  // Create a buffer object which points to the raw data
  buffer *buf = malloc(sizeof(buffer));
  if (buf == NULL) {
    error(&amp;quot;&amp;#39;buf&amp;#39; malloc failed!&amp;quot;);
  }
  buf-&amp;gt;length = len;
  buf-&amp;gt;pos    = 0;
  buf-&amp;gt;data   = vec;

  // Treat the data buffer as an input stream
  struct R_inpstream_st input_stream;

  R_InitInPStream(
    &amp;amp;input_stream,           // Stream object wrapping data buffer
    (R_pstream_data_t) buf,  // Actual data buffer
    R_pstream_any_format,    // Unpack all serialized types
    read_byte,               // Function to read single byte from buffer
    read_bytes,              // Function for reading multiple bytes from buffer
    NULL,                    // Func for special handling of reference data.
    NULL                     // Data related to reference data handling
  );

  // Unserialize the input_stream into an R object
  SEXP res_  = PROTECT(R_Unserialize(&amp;amp;input_stream));

  free(buf);
  UNPROTECT(1);
  return res_;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code for the memory buffer &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The data buffer.
// Needs total length and pos to keep track of how much data it contains
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef struct {
  R_xlen_t length;
  R_xlen_t pos;
  unsigned char *data;
} buffer;



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialise an empty buffer to hold &amp;#39;nbytes&amp;#39;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buffer *init_buffer(int nbytes) {
  buffer *buf = (buffer *)malloc(sizeof(buffer));
  if (buf == NULL) {
    error(&amp;quot;init_buffer(): cannot malloc buffer&amp;quot;);
  }

  buf-&amp;gt;data = (unsigned char *)malloc(nbytes * sizeof(unsigned char));
  if (buf-&amp;gt;data == NULL) {
    error(&amp;quot;init_buffer(): cannot malloc buffer data&amp;quot;);
  }

  buf-&amp;gt;length = nbytes;
  buf-&amp;gt;pos = 0;

  return buf;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Naive buffer expansion - double it every time space runs out
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void expand_buffer(buffer *buf) {

  double factor = 2;
  buf-&amp;gt;length = (R_xlen_t)(factor * buf-&amp;gt;length);

  if (buf-&amp;gt;length &amp;gt; R_XLEN_T_MAX) {
    error(&amp;quot;Requested buffer expandsion too large: %td\n&amp;quot;, buf-&amp;gt;length);
  }

  unsigned char *new_data = (unsigned char *)realloc((void *)buf-&amp;gt;data, buf-&amp;gt;length);

  if (new_data == NULL) {
    free(buf-&amp;gt;data);
    free(buf);
    error(&amp;quot;Couldn&amp;#39;t expand buffer to reallocate: %td\n&amp;quot;, buf-&amp;gt;length);
  }

  buf-&amp;gt;data = new_data;

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write a byte into the buffer at the current location.
// The actual buffer is encapsulated as part of the stream structure, so you
// have to extract it first
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void write_byte(R_outpstream_t stream, int c) {
  buffer *buf = (buffer *)stream-&amp;gt;data;

  // Expand the buffer if it&amp;#39;s out space
  while (buf-&amp;gt;pos &amp;gt;= buf-&amp;gt;length) {
    expand_buffer(buf);
  }

  buf-&amp;gt;data[buf-&amp;gt;pos++] = (unsigned char)c;
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write multiple bytes into the buffer at the current location.
// The actual buffer is encapsulated as part of the stream structure, so you
// have to extract it first
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void write_bytes(R_outpstream_t stream, void *src, int length) {
  buffer *buf = (buffer *)stream-&amp;gt;data;

  // Expand the buffer if it&amp;#39;s out space
  while (buf-&amp;gt;pos + length &amp;gt; buf-&amp;gt;length) {
    expand_buffer(buf);
  }

  memcpy(buf-&amp;gt;data + buf-&amp;gt;pos, src, length);

  buf-&amp;gt;pos += length;
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read a byte from the serialized stream
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int read_byte(R_inpstream_t stream) {
  buffer *buf = (buffer *)stream-&amp;gt;data;

  if (buf-&amp;gt;pos &amp;gt;= buf-&amp;gt;length) {
    error(&amp;quot;read_byte(): overflow&amp;quot;);
  }

  return buf-&amp;gt;data[buf-&amp;gt;pos++];
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read multiple bytes from the serialized stream
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void read_bytes(R_inpstream_t stream, void *dst, int length) {
  buffer *buf = (buffer *)stream-&amp;gt;data;

  if (buf-&amp;gt;pos + length &amp;gt; buf-&amp;gt;length) {
    error(&amp;quot;read_bytes(): overflow&amp;quot;);
  }

  memcpy(dst, buf-&amp;gt;data + buf-&amp;gt;pos, length);

  buf-&amp;gt;pos += length;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/RApiSerialize/index.html&#34;&gt;RApiSerialize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/qs/index.html&#34;&gt;qs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/fst/index.html&#34;&gt;fst&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Creating a data.frame in C</title>
      <link>https://coolbutuseless.github.io/2020/09/16/creating-a-data.frame-in-c/</link>
      <pubDate>Wed, 16 Sep 2020 19:55:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/16/creating-a-data.frame-in-c/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;simplecall---demo-package-for-calling-c-code-with-.call&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;simplecall - demo package for calling C code with &lt;code&gt;.Call()&lt;/code&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;simplecall&lt;/code&gt; is a small demo package showing how C code could be included
in a package and called with &lt;code&gt;.Call()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This package now includes demo code for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;creating a list in C&lt;/li&gt;
&lt;li&gt;creating a data.frame in C&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are probably more succinct ways of doing this, and if you know such a way,
please hit me up &lt;a href=&#34;https://twitter.com/coolbutuseless&#34;&gt;on twitter&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/simplecall&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/simplecall)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-r-list-within-c&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a R List within C&lt;/h2&gt;
&lt;p&gt;Example code is included to create a list completely within C and return it to R&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Creating a list within C and returning it to R
//
//  1. Create individual integer/real/whatever vectors
//  2. allocate a VECSXP of the correct size
//  3. assign each member into the list
//  4. create names and assign them to the list
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEXP create_list_in_c_() {


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Each member of the list gets allocated separately
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  int n = 10;

  SEXP idx_ = PROTECT(allocVector(INTSXP , n));
  SEXP x_   = PROTECT(allocVector(REALSXP, n));
  SEXP y_   = PROTECT(allocVector(REALSXP, n));


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Assign some dummy values into the members
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (int i = 0; i &amp;lt; n; i++) {
    INTEGER(idx_)[i] = i + 1;
    REAL(x_)[i] = i + 10;
    REAL(y_)[i] = i + 100;
  }

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Allocate a list with 3 members
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SEXP list_ = PROTECT(allocVector(VECSXP, 3));

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Add members to the list
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SET_VECTOR_ELT(list_,  0, idx_);
  SET_VECTOR_ELT(list_,  1, x_);
  SET_VECTOR_ELT(list_,  2, y_);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Set the names on the list.
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SEXP names = PROTECT(allocVector(STRSXP, 3));
  SET_STRING_ELT(names,  0, mkChar(&amp;quot;idx&amp;quot;));
  SET_STRING_ELT(names,  1, mkChar(&amp;quot;x&amp;quot;));
  SET_STRING_ELT(names,  2, mkChar(&amp;quot;y&amp;quot;));
  setAttrib(list_, R_NamesSymbol, names);

  UNPROTECT(5);
  return list_;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;simplecall::create_list_in_c()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$idx
 [1]  1  2  3  4  5  6  7  8  9 10

$x
 [1] 10 11 12 13 14 15 16 17 18 19

$y
 [1] 100 101 102 103 104 105 106 107 108 109&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-r-data.frame-within-c&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a R data.frame within C&lt;/h2&gt;
&lt;p&gt;Example code is included to create a data.frame completely within C and return it to R&lt;/p&gt;
&lt;pre class=&#34;c&#34;&gt;&lt;code&gt;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Creating a data.frame within C and returning it to R
//
//  1. Create individual integer/real/whatever vectors
//  2. allocate a VECSXP of the correct size
//  3. assign each member into the data.frame
//  4. create names and assign them to the data.frame
//  5. set the class to &amp;quot;data.frame&amp;quot;
//  6. set rownames on the data.frame
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEXP create_data_frame_in_c_() {


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Each member of the list gets allocated separately
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  int n = 10;

  SEXP idx_ = PROTECT(allocVector(INTSXP , n));
  SEXP x_   = PROTECT(allocVector(REALSXP, n));
  SEXP y_   = PROTECT(allocVector(REALSXP, n));


  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Assign some dummy values into the members
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (int i = 0; i &amp;lt; n; i++) {
    INTEGER(idx_)[i] = i + 1;
    REAL(x_)[i] = i + 10;
    REAL(y_)[i] = i + 100;
  }

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Allocate a data.frame
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SEXP df_ = PROTECT(allocVector(VECSXP, 3));

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Add columns to the data.frame
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SET_VECTOR_ELT(df_,  0, idx_);
  SET_VECTOR_ELT(df_,  1, x_);
  SET_VECTOR_ELT(df_,  2, y_);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Treat the VECSXP as a data.frame rather than a list
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SET_CLASS(df_, mkString(&amp;quot;data.frame&amp;quot;));

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Set the names on the list.
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SEXP names = PROTECT(allocVector(STRSXP, 3));
  SET_STRING_ELT(names,  0, mkChar(&amp;quot;idx&amp;quot;));
  SET_STRING_ELT(names,  1, mkChar(&amp;quot;x&amp;quot;));
  SET_STRING_ELT(names,  2, mkChar(&amp;quot;y&amp;quot;));
  setAttrib(df_, R_NamesSymbol, names);

  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // Set the row.names on the list.
  // Use the shortcut as used in .set_row_names() in R
  // i.e. set rownames to c(NA_integer, -len) and it will
  // take care of the rest. This is equivalent to rownames(x) &amp;lt;- NULL
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SEXP rownames = PROTECT(allocVector(INTSXP, 2));
  SET_INTEGER_ELT(rownames, 0, NA_INTEGER);
  SET_INTEGER_ELT(rownames, 1, -n);
  setAttrib(df_, R_RowNamesSymbol, rownames);

  UNPROTECT(6);
  return df_;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;simplecall::create_data_frame_in_c()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;   idx  x   y
1    1 10 100
2    2 11 101
3    3 12 102
4    4 13 103
5    5 14 104
6    6 15 105
7    7 16 106
8    8 17 107
9    9 18 108
10  10 19 109&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;similar-packages&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Similar packages&lt;/h3&gt;
&lt;p&gt;This is one of a series of small demo packages for&lt;br /&gt;
calling other languages from R:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplec&#34;&gt;{simplec}&lt;/a&gt; - calling C with &lt;code&gt;.C()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplecall&#34;&gt;{simplecall}&lt;/a&gt; - calling C with &lt;code&gt;.Call()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplercpp&#34;&gt;{simplercpp}&lt;/a&gt; - calling C++ with &lt;code&gt;{Rcpp}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplefortran&#34;&gt;{simplefortran}&lt;/a&gt; - calling Fortran with &lt;code&gt;.Fortran()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&#34;resources&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.davisvaughan.com/2019/03/02/now-you-c-me/&#34;&gt;David Vaughan’s post - Now you C me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.ci.tuwien.ac.at/Conferences/useR-2004/Keynotes/Dalgaard.pdf&#34;&gt;Peter Dalgaard’s Keynote from UseR 2004&lt;/a&gt;
discusses R’s language interfaces&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://mazamascience.com/WorkingWithData/?p=1067&#34;&gt;Using R — Calling C Code ‘Hello World’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://adv-r.had.co.nz/C-interface.html&#34;&gt;Hadley’s Advanced R book chapter - ‘Rs C interface’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=Rcpp&#34;&gt;Rcpp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;snowcrash&#39; - a package to encode arbitrary R objects into image representations</title>
      <link>https://coolbutuseless.github.io/2020/09/11/introducing-snowcrash-a-package-to-encode-arbitrary-r-objects-into-image-representations/</link>
      <pubDate>Fri, 11 Sep 2020 06:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/11/introducing-snowcrash-a-package-to-encode-arbitrary-r-objects-into-image-representations/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;snowcrash&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;snowcrash &lt;img src=&#34;https://coolbutuseless.github.io/img/snowcrash/logo.png&#34; align=&#34;right&#34; height=330/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/snowcrash/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/snowcrash/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;snowcrash&lt;/code&gt; is a package for encoding arbitrary R objects as rasters, PNGs
and rasterGrobs.&lt;/p&gt;
&lt;div id=&#34;why&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Why?&lt;/h4&gt;
&lt;p&gt;Although this may seem like a frivolous package, encoding data as images is
one way to transmit information to a graphics device through an otherwise impenetrable
barrier. This package is needed to enable extra data to pass to a graphics
device when using devices based upon &lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;devout&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;encode_robj_to_bytes()&lt;/code&gt;/&lt;code&gt;decode_bytes_to_robj&lt;/code&gt; encode an arbitrary R object to bytes using &lt;code&gt;base::serialize()&lt;/code&gt;.
This will also compress the data if &lt;a href=&#34;https://github.com/coolbutuseless/zstdlite&#34;&gt;zstdlite&lt;/a&gt;
is installed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encode_robj_to_png()&lt;/code&gt;/&lt;code&gt;decode_png_to_robj&lt;/code&gt; encode an arbitrary R object as a png&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encode_robj_to_raster()&lt;/code&gt;/&lt;code&gt;decode_raster_to_robj&lt;/code&gt; encode as a raster image&lt;/li&gt;
&lt;li&gt;&lt;code&gt;encode_robj_to_rasterGrob()&lt;/code&gt;/&lt;code&gt;decode_rasterGrob_to_robj()&lt;/code&gt; encode as a &lt;code&gt;grid::rasterGrob()&lt;/code&gt; object&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/snowcrash&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/zstdlite&amp;#39;) # suggested. but not mandatory.
remotes::install_github(&amp;#39;coolbutuseless/snowcrash&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;encoding-a-small-vector-as-bytes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding a small vector as bytes&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;bytes &amp;lt;- encode_robj_to_bytes(c(1, 2, 3))
bytes&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 5a 53 54 18 28 b5 2f fd 20 37 a5 01 00 74 02 58 0a 00 00 00 03 00 04 00 02
[26] 00 03 05 00 00 00 00 05 55 54 46 2d 38 00 00 00 0e 3f f0 00 00 40 08 00 00
[51] 00 00 00 00 04 04 01 2b 00 65 dc c4 f3 1c 03&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;decode_bytes_to_robj(bytes)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;encoding-a-data.frame-as-an-image-raster&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding a &lt;code&gt;data.frame&lt;/code&gt; as an Image Raster&lt;/h2&gt;
&lt;p&gt;This example encodes the head of the &lt;code&gt;mtcars&lt;/code&gt; data.frame into a raster image.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ras &amp;lt;- encode_robj_to_raster(head(mtcars), alpha = 1)
head(ras)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1]        [,2]        [,3]        [,4]        [,5]        [,6]       
[1,] &amp;quot;#5A550CFF&amp;quot; &amp;quot;#0064BDFF&amp;quot; &amp;quot;#5260D0FF&amp;quot; &amp;quot;#104EE6FF&amp;quot; &amp;quot;#5EE176FF&amp;quot; &amp;quot;#9D371CFF&amp;quot;
[2,] &amp;quot;#53C640FF&amp;quot; &amp;quot;#364065FF&amp;quot; &amp;quot;#5AD887FF&amp;quot; &amp;quot;#4BE71CFF&amp;quot; &amp;quot;#8C98EBFF&amp;quot; &amp;quot;#9A32C1FF&amp;quot;
[3,] &amp;quot;#543F18FF&amp;quot; &amp;quot;#1341E5FF&amp;quot; &amp;quot;#68CB46FF&amp;quot; &amp;quot;#C1EDF4FF&amp;quot; &amp;quot;#5E92DDFF&amp;quot; &amp;quot;#6C4279FF&amp;quot;
[4,] &amp;quot;#18834BFF&amp;quot; &amp;quot;#4B1695FF&amp;quot; &amp;quot;#B801FFFF&amp;quot; &amp;quot;#304003FF&amp;quot; &amp;quot;#96D4E9FF&amp;quot; &amp;quot;#6C28A9FF&amp;quot;
[5,] &amp;quot;#28392FFF&amp;quot; &amp;quot;#3E0CE2FF&amp;quot; &amp;quot;#A042E3FF&amp;quot; &amp;quot;#62B7B9FF&amp;quot; &amp;quot;#C7939FFF&amp;quot; &amp;quot;#014293FF&amp;quot;
[6,] &amp;quot;#B54CE0FF&amp;quot; &amp;quot;#207639FF&amp;quot; &amp;quot;#C0F068FF&amp;quot; &amp;quot;#8AC390FF&amp;quot; &amp;quot;#16DA0DFF&amp;quot; &amp;quot;#FD4B12FF&amp;quot;
     [,7]        [,8]        [,9]        [,10]       [,11]       [,12]      
[1,] &amp;quot;#24FF9CFF&amp;quot; &amp;quot;#32FEC7FF&amp;quot; &amp;quot;#B8A9D0FF&amp;quot; &amp;quot;#7F886CFF&amp;quot; &amp;quot;#FB2A00FF&amp;quot; &amp;quot;#904700FF&amp;quot;
[2,] &amp;quot;#3CEEF6FF&amp;quot; &amp;quot;#598FA3FF&amp;quot; &amp;quot;#306627FF&amp;quot; &amp;quot;#C7187CFF&amp;quot; &amp;quot;#7F1600FF&amp;quot; &amp;quot;#508100FF&amp;quot;
[3,] &amp;quot;#36DBAEFF&amp;quot; &amp;quot;#D465DBFF&amp;quot; &amp;quot;#688F62FF&amp;quot; &amp;quot;#FF4D3FFF&amp;quot; &amp;quot;#4E0100FF&amp;quot; &amp;quot;#906D00FF&amp;quot;
[4,] &amp;quot;#001585FF&amp;quot; &amp;quot;#23DFA5FF&amp;quot; &amp;quot;#E1C85BFF&amp;quot; &amp;quot;#EFA33BFF&amp;quot; &amp;quot;#7BD600FF&amp;quot; &amp;quot;#3F1100FF&amp;quot;
[5,] &amp;quot;#40FF8EFF&amp;quot; &amp;quot;#8A10A0FF&amp;quot; &amp;quot;#C276E1FF&amp;quot; &amp;quot;#BFBBE6FF&amp;quot; &amp;quot;#F62C00FF&amp;quot; &amp;quot;#131500FF&amp;quot;
[6,] &amp;quot;#00B355FF&amp;quot; &amp;quot;#F6A58AFF&amp;quot; &amp;quot;#A1C042FF&amp;quot; &amp;quot;#84B1DEFF&amp;quot; &amp;quot;#EDA500FF&amp;quot; &amp;quot;#2E5400FF&amp;quot;
     [,13]      
[1,] &amp;quot;#7DA000FF&amp;quot;
[2,] &amp;quot;#DCC800FF&amp;quot;
[3,] &amp;quot;#922500FF&amp;quot;
[4,] &amp;quot;#A8F000FF&amp;quot;
[5,] &amp;quot;#340200FF&amp;quot;
[6,] &amp;quot;#242900FF&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(ras, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-11-snowcrash_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;decode_raster_to_robj(ras)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;encoding-a-function-as-a-gridrastergrob&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding a Function as a &lt;code&gt;grid::rasterGrob()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This example encodes the &lt;code&gt;rle()&lt;/code&gt; function into a &lt;code&gt;rasterGrob()&lt;/code&gt; object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;raster_grob &amp;lt;- encode_robj_to_rasterGrob(rle, alpha = 1)
grid::grid.draw(raster_grob)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-11-snowcrash_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;decode_rasterGrob_to_robj(raster_grob)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;function (x) 
{
    if (!is.vector(x) &amp;amp;&amp;amp; !is.list(x)) 
        stop(&amp;quot;&amp;#39;x&amp;#39; must be a vector of an atomic type&amp;quot;)
    n &amp;lt;- length(x)
    if (n == 0L) 
        return(structure(list(lengths = integer(), values = x), 
            class = &amp;quot;rle&amp;quot;))
    y &amp;lt;- x[-1L] != x[-n]
    i &amp;lt;- c(which(y | is.na(y)), n)
    structure(list(lengths = diff(c(0L, i)), values = x[i]), 
        class = &amp;quot;rle&amp;quot;)
}
&amp;lt;bytecode: 0x7fe06c1e3bf0&amp;gt;
&amp;lt;environment: namespace:base&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;encoding-a-ggplot2-object-as-a-png-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding a &lt;code&gt;ggplot2&lt;/code&gt; Object as a PNG image&lt;/h2&gt;
&lt;p&gt;This example encodes a full &lt;code&gt;ggplot&lt;/code&gt; code object in a PNG image file.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a plot ojbect
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library(ggplot2)
p &amp;lt;- ggplot(mtcars) + 
  geom_point(aes(mpg, wt))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save the ggplot2 object as a PNG image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
png_file &amp;lt;- &amp;quot;/tmp/test.png&amp;quot;
encode_robj_to_png(p, filename = png_file, alpha = 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/snowcrash/test.png&#34; width=&#34;30%&#34; style=&#34;image-rendering: pixelated;&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;- decode_png_to_robj(&amp;quot;/tmp/test.png&amp;quot;) 

p + 
  theme_bw() + 
  labs(title = &amp;quot;Decoded plot object&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-11-snowcrash_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;80%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;snowcrash---by-neal-stephenson&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;snowcrash&lt;/code&gt; - by Neal Stephenson&lt;/h2&gt;
&lt;p&gt;This package is named after &lt;a href=&#34;https://en.wikipedia.org/wiki/Snow_Crash&#34;&gt;Snow Crash&lt;/a&gt;,
a sci-fi book by Neal Stephenson where events are set in motion by someone viewing an image
of encoded information.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“You saw the whole thing,” Da5id says. “A fixed pattern of black-and-white pixels, fairly high-resolution. Just a few hundred thousand ones and zeroes for me to look at.”&lt;/p&gt;
&lt;p&gt;“So in other words, someone just exposed your optic nerve to what, maybe a hundred thousand bytes of information,” Hiro says.&lt;/p&gt;
&lt;p&gt;“Noise, is more like it.”&lt;/p&gt;
&lt;p&gt;“Well, all information looks like noise until you break the code,” Hiro says.&lt;/p&gt;
&lt;p&gt;“Why would anyone show me information in binary code? I’m not a computer. I can’t read a bitmap.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base::serialize()&lt;/code&gt; and &lt;code&gt;base::unserialize()&lt;/code&gt; are the built-in functions for
serializing/unserializing any R object. These functions are used internally
in &lt;code&gt;{snowcrash}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;cryogenic&#39; - a package to freeze function calls to modify and evaluate later</title>
      <link>https://coolbutuseless.github.io/2020/09/09/introducing-cryogenic-a-package-to-freeze-function-calls-to-modify-and-evaluate-later/</link>
      <pubDate>Wed, 09 Sep 2020 21:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/09/introducing-cryogenic-a-package-to-freeze-function-calls-to-modify-and-evaluate-later/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;cryogenic&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;cryogenic&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/cryogenic/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/cryogenic/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cryogenic&lt;/code&gt; is a package for freezing a function call, modifying its arguments
and then evaluating later.&lt;/p&gt;
&lt;p&gt;This package is written for a particular use case I have in mind, and may not
be generally applicable. The functions are all in base R and quite small, and the
reasoning for having this in a package is &lt;em&gt;consistency&lt;/em&gt; of the interface.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&#34;https://cran.r-project.org/package=rlang&#34;&gt;rlang&lt;/a&gt;
for a much more comprehensive and generalisable approach.&lt;/p&gt;
&lt;div id=&#34;my-use-case&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My Use Case&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Both the calling environment and evaluation environment are under my control.
&lt;ul&gt;
&lt;li&gt;I am not executing captured calls based on user input.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Need an R package for this as I need to use this code across multiple packages&lt;/li&gt;
&lt;li&gt;Need eager evaluation of arguments when call is captured&lt;/li&gt;
&lt;li&gt;Need to be able to update any arguments
&lt;ul&gt;
&lt;li&gt;Need to be able to update an argument to have a value of &lt;code&gt;NULL&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Need to be able to set arguments to a default value if they aren’t already present&lt;/li&gt;
&lt;li&gt;Nearly everything is in lists&lt;/li&gt;
&lt;li&gt;Need to be able to consistently add arbitrary &lt;code&gt;meta&lt;/code&gt; information as an attribute
on the call&lt;/li&gt;
&lt;li&gt;There are probably other constraints which I’ll add as I think of them&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;capture_call()&lt;/code&gt; to capture a call without evaluating it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;modify_call()&lt;/code&gt; to modify call arguments&lt;/li&gt;
&lt;li&gt;&lt;code&gt;evaluate_call()&lt;/code&gt; to evaluate a call - and optionally modify the call arguments
just prior to the evaluation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/cryogenic&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cryogenic&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example 1&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;capture a call&lt;/li&gt;
&lt;li&gt;modify the call&lt;/li&gt;
&lt;li&gt;evaluate the call&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cryogenic)

cc &amp;lt;- capture_call(runif(n = 10, min=-3))
cc&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;runif(n = 10, min = -3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;cc &amp;lt;- modify_call(cc, defaults = list(min=0, max=5), update = list(n = 5))
cc&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;runif(n = 5, min = -3, max = 5)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;evaluate_call(cc)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] -0.8759307 -0.0230088  1.5828269  4.2656623 -1.3865446&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example 2&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;capture a call&lt;/li&gt;
&lt;li&gt;simultaneously update a call and evalute it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cryogenic)

cc &amp;lt;- capture_call(runif(n = 10, min=-3))
cc&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;runif(n = 10, min = -3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;evaluate_call(cc, defaults = list(min=0, max=5), update = list(n = 15))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  4.18711748  4.55740215  2.28638234  2.03291235 -2.50570984 -1.35220340
 [7] -1.58754598  2.49618277  0.07282975  3.15873136  0.98159394  2.74094807
[13]  4.93524876  0.04028144  3.21956177&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example 3&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cryogenic)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Capture a call as-is.
#
# * the function does not have to exist in the capturing environment
# * By default, all arguments are eagerly evaluated in the environment in which
#   the call was captured
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc &amp;lt;- capture_call(farnarkle(6, x = 2, y = 3, z = 2+9, error = TRUE))
cc&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;farnarkle(6, x = 2, y = 3, z = 11, error = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Update the arguments to the call
#
# * &amp;#39;defaults&amp;#39; are only added to the arguments if the named argument does 
#    not already exist there.
# * &amp;#39;update&amp;#39; values are added to the arguments unconditionally
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc &amp;lt;- modify_call(
  cc, 
  defaults = list(x = NULL, y = 7), 
  update   = list(z = NULL, na.rm = TRUE),
  delete   = c(&amp;#39;error&amp;#39;)
)

cc&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;farnarkle(6, x = 2, y = 3, z = NULL, na.rm = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;#39;farnarkle&amp;#39; is not yet defined, so evaluation should fail
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
evaluate_call(cc)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in farnarkle(6, x = 2, y = 3, z = NULL, na.rm = TRUE): could not find function &amp;quot;farnarkle&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# define farnarkle and it should work
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
farnarkle &amp;lt;- function(...) {print(&amp;quot;Hello #Rstats&amp;quot;)}
evaluate_call(cc)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;Hello #Rstats&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rlang&lt;/code&gt; offers a lot of tools for call modification, but wasn’t quite a match
for how I’m working.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pryr::modify_call()&lt;/code&gt; is similar to what is done in this package, but &lt;code&gt;cryogenic&lt;/code&gt;
offers a few more features I need.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Inserting rgl as webgl in an Rmarkdown document - Part 2</title>
      <link>https://coolbutuseless.github.io/2020/09/07/inserting-rgl-as-webgl-in-an-rmarkdown-document-part-2/</link>
      <pubDate>Mon, 07 Sep 2020 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/07/inserting-rgl-as-webgl-in-an-rmarkdown-document-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/htmlwidgets/htmlwidgets.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglwidgetClass/rgl.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglwidgetClass/rglClass.src.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/CanvasMatrix4/CanvasMatrix.src.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/rglWebGL-binding/rglWebGL.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;https://coolbutuseless.github.io/rmarkdown-libs/crosstalk/css/crosstalk.css&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/crosstalk/js/crosstalk.min.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;how-to-insert-rgl-as-webgl-in-an-rmarkdown-document---part-2&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;How to insert &lt;code&gt;rgl&lt;/code&gt; as webgl in an Rmarkdown document - Part 2&lt;/h1&gt;
&lt;p&gt;This post is really a mini-reminder to myself on how to insert an rgl render
as webgl within an Rmarkdown document.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(rgl)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a 3D cube! Woo!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
shade3d(cube3d(color = rep(rainbow(6), rep(4, 6))))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use your mouse, mouse buttons and scrollwheel to manipulate the 3d plot&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Display the last render 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (!interactive()) rgl::rglwidget()&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;rgl15830&#34; style=&#34;width:768px;height:480px;&#34; class=&#34;rglWebGL html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;rgl15830&#34;&gt;{&#34;x&#34;:{&#34;material&#34;:{&#34;color&#34;:&#34;#000000&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:false,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:6,&#34;objects&#34;:{&#34;12&#34;:{&#34;id&#34;:12,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{},&#34;vertices&#34;:[[-1,-1,-1],[-1,1,-1],[1,1,-1],[1,-1,-1],[-1,1,-1],[-1,1,1],[1,1,1],[1,1,-1],[1,-1,-1],[1,1,-1],[1,1,1],[1,-1,1],[-1,-1,-1],[-1,-1,1],[-1,1,1],[-1,1,-1],[-1,-1,-1],[1,-1,-1],[1,-1,1],[-1,-1,1],[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1]],&#34;colors&#34;:[[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1]],&#34;centers&#34;:[[0,0,-1],[0,1,0],[1,0,0],[-1,0,0],[0,-1,0],[0,0,1]],&#34;normals&#34;:[[0,0,-1],[0,0,-1],[0,0,-1],[0,0,-1],[-0,1,0],[-0,1,0],[-0,1,0],[-0,1,0],[1,0,-0],[1,0,-0],[1,0,-0],[1,0,-0],[-1,0,0],[-1,0,0],[-1,0,0],[-1,0,0],[0,-1,0],[0,-1,0],[0,-1,0],[0,-1,0],[0,-0,1],[0,-0,1],[0,-0,1],[0,-0,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:3},&#34;10&#34;:{&#34;id&#34;:10,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0,0,1]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;9&#34;:{&#34;id&#34;:9,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;fog&#34;:true},&#34;colors&#34;:[[0.298039227724075,0.298039227724075,0.298039227724075,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;11&#34;:{&#34;id&#34;:11,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;back&#34;:&#34;lines&#34;},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;6&#34;:{&#34;id&#34;:6,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:8,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:6,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,6.69213056564331],&#34;modelMatrix&#34;:[[1,0,0,0],[0,0.342020153999329,0.939692616462708,0],[0,-0.939692616462708,0.342020153999329,-6.69213056564331],[0,0,0,1]],&#34;projMatrix&#34;:[[3.73205089569092,0,0,0],[0,3.73205089569092,0,0],[0,0,-3.86370348930359,-24.1243553161621],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[1,0,0,0],[0,0.342020143325668,0.939692620785909,0],[0,-0.939692620785909,0.342020143325668,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:1,&#34;bbox&#34;:[-1,1,-1,1,-1,1],&#34;windowRect&#34;:[0,45,256,301],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:true,&#34;fontname&#34;:&#34;/Library/Frameworks/R.framework/Versions/4.0/Resources/library/rgl/fonts/FreeSans.ttf&#34;,&#34;maxClipPlanes&#34;:6,&#34;glVersion&#34;:2.09999990463257,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[11,12,10],&#34;subscenes&#34;:[],&#34;flags&#34;:515},&#34;19&#34;:{&#34;id&#34;:19,&#34;type&#34;:&#34;linestrip&#34;,&#34;material&#34;:{&#34;alpha&#34;:0.498039215803146,&#34;lit&#34;:false,&#34;depth_test&#34;:&#34;always&#34;,&#34;isTransparent&#34;:true},&#34;vertices&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;colors&#34;:[[0,0,0,0.498039215803146]],&#34;centers&#34;:[[0,0,-0.999000012874603],[1,0,-0.999000012874603],[1,1,-0.999000012874603],[0,1,-0.999000012874603],[0,0,-0.999000012874603]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:32864}},&#34;crosstalk&#34;:{&#34;key&#34;:[null],&#34;group&#34;:&#34;&#34;,&#34;id&#34;:0,&#34;options&#34;:[null]},&#34;width&#34;:768,&#34;height&#34;:480,&#34;brushId&#34;:19,&#34;sphereVerts&#34;:{&#34;vb&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.195090322016128,-0.38268343236509,-0.555570233019602,-0.707106781186547,-0.831469612302545,-0.923879532511287,-0.98078528040323,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1],[0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.195090322016128,-0.38268343236509,-0.555570233019602,-0.707106781186547,-0.831469612302545,-0.923879532511287,-0.98078528040323,-1,-0.98078528040323,-0.923879532511287,-0.831469612302545,-0.707106781186547,-0.555570233019602,-0.38268343236509,-0.195090322016128,-0,-0,-0.180239955501737,-0.353553390593274,-0.513279967159337,-0.653281482438188,-0.768177756711416,-0.853553390593274,-0.906127446352888,-0.923879532511287,-0.906127446352888,-0.853553390593274,-0.768177756711416,-0.653281482438188,-0.513279967159337,-0.353553390593274,-0.180239955501737,-0,-0,-0.137949689641471,-0.270598050073098,-0.392847479193551,-0.5,-0.587937801209679,-0.653281482438188,-0.693519922661074,-0.707106781186547,-0.693519922661074,-0.653281482438188,-0.587937801209679,-0.5,-0.392847479193551,-0.270598050073098,-0.137949689641471,-0,-0,-0.0746578340503426,-0.146446609406726,-0.212607523691814,-0.270598050073098,-0.318189645143208,-0.353553390593274,-0.375330277517865,-0.38268343236509,-0.375330277517865,-0.353553390593274,-0.318189645143208,-0.270598050073098,-0.212607523691814,-0.146446609406726,-0.0746578340503426,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0746578340503426,0.146446609406726,0.212607523691814,0.270598050073098,0.318189645143208,0.353553390593274,0.375330277517865,0.38268343236509,0.375330277517865,0.353553390593274,0.318189645143208,0.270598050073098,0.212607523691814,0.146446609406726,0.0746578340503426,0,0,0.137949689641471,0.270598050073098,0.392847479193551,0.5,0.587937801209679,0.653281482438188,0.693519922661074,0.707106781186547,0.693519922661074,0.653281482438188,0.587937801209679,0.5,0.392847479193551,0.270598050073098,0.137949689641471,0,0,0.180239955501737,0.353553390593274,0.513279967159337,0.653281482438188,0.768177756711416,0.853553390593274,0.906127446352888,0.923879532511287,0.906127446352888,0.853553390593274,0.768177756711416,0.653281482438188,0.513279967159337,0.353553390593274,0.180239955501737,0,0,0.195090322016128,0.38268343236509,0.555570233019602,0.707106781186547,0.831469612302545,0.923879532511287,0.98078528040323,1,0.98078528040323,0.923879532511287,0.831469612302545,0.707106781186547,0.555570233019602,0.38268343236509,0.195090322016128,0]],&#34;it&#34;:[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270],[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271]],&#34;material&#34;:[],&#34;normals&#34;:null,&#34;texcoords&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1]],&#34;meshColor&#34;:&#34;vertices&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;players&#34;:[],&#34;webGLoptions&#34;:{&#34;preserveDrawingBuffer&#34;:true}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Inserting rgl as webgl in an Rmarkdown document</title>
      <link>https://coolbutuseless.github.io/2020/09/07/inserting-rgl-as-webgl-in-an-rmarkdown-document/</link>
      <pubDate>Mon, 07 Sep 2020 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/07/inserting-rgl-as-webgl-in-an-rmarkdown-document/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;how-to-insert-rgl-as-webgl-in-an-rmarkdown-document&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;How to insert &lt;code&gt;rgl&lt;/code&gt; as webgl in an Rmarkdown document&lt;/h1&gt;
&lt;p&gt;This post is really a mini-reminder to myself on how to insert an rgl render
as webgl within an Rmarkdown document.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(rgl)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The setupKnitr() function needs to be called once at the start of the 
# document to install the knitr hooks and to initialize hook_webgl
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rgl::setupKnitr()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# ^^^^^^ You can&amp;#39;t see it, but you have to set `webgl=TRUE` on the chunk
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a 3D cube! Woo!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
shade3d(cube3d(color = rep(rainbow(6), rep(4, 6))))

# Use your mouse to manipulate the object!&lt;/code&gt;&lt;/pre&gt;
&lt;script&gt;/*
* Copyright (C) 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS&#39;&#39; AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Copyright (2016) Duncan Murdoch - fixed CanvasMatrix4.ortho,
* cleaned up.
*/
/*
CanvasMatrix4 class
This class implements a 4x4 matrix. It has functions which
duplicate the functionality of the OpenGL matrix stack and
glut functions.
IDL:
[
Constructor(in CanvasMatrix4 matrix),           // copy passed matrix into new CanvasMatrix4
Constructor(in sequence&lt;float&gt; array)           // create new CanvasMatrix4 with 16 floats (row major)
Constructor()                                   // create new CanvasMatrix4 with identity matrix
]
interface CanvasMatrix4 {
attribute float m11;
attribute float m12;
attribute float m13;
attribute float m14;
attribute float m21;
attribute float m22;
attribute float m23;
attribute float m24;
attribute float m31;
attribute float m32;
attribute float m33;
attribute float m34;
attribute float m41;
attribute float m42;
attribute float m43;
attribute float m44;
void load(in CanvasMatrix4 matrix);                 // copy the values from the passed matrix
void load(in sequence&lt;float&gt; array);                // copy 16 floats into the matrix
sequence&lt;float&gt; getAsArray();                       // return the matrix as an array of 16 floats
WebGLFloatArray getAsCanvasFloatArray();           // return the matrix as a WebGLFloatArray with 16 values
void makeIdentity();                                // replace the matrix with identity
void transpose();                                   // replace the matrix with its transpose
void invert();                                      // replace the matrix with its inverse
void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
void scale(in float x, in float y, in float z);     // multiply the matrix by passed scale values on the right
void rotate(in float angle,                         // multiply the matrix by passed rotation values on the right
in float x, in float y, in float z);    // (angle is in degrees)
void multRight(in CanvasMatrix matrix);             // multiply the matrix by the passed matrix on the right
void multLeft(in CanvasMatrix matrix);              // multiply the matrix by the passed matrix on the left
void ortho(in float left, in float right,           // multiply the matrix by the passed ortho values on the right
in float bottom, in float top,
in float near, in float far);
void frustum(in float left, in float right,         // multiply the matrix by the passed frustum values on the right
in float bottom, in float top,
in float near, in float far);
void perspective(in float fovy, in float aspect,    // multiply the matrix by the passed perspective values on the right
in float zNear, in float zFar);
void lookat(in float eyex, in float eyey, in float eyez,    // multiply the matrix by the passed lookat
in float ctrx, in float ctry, in float ctrz,    // values on the right
in float upx, in float upy, in float upz);
}
*/
CanvasMatrix4 = function(m)
{
if (typeof m == &#39;object&#39;) {
if (&#34;length&#34; in m &amp;&amp; m.length &gt;= 16) {
this.load(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
return;
}
else if (m instanceof CanvasMatrix4) {
this.load(m);
return;
}
}
this.makeIdentity();
};
CanvasMatrix4.prototype.load = function()
{
if (arguments.length == 1 &amp;&amp; typeof arguments[0] == &#39;object&#39;) {
var matrix = arguments[0];
if (&#34;length&#34; in matrix &amp;&amp; matrix.length == 16) {
this.m11 = matrix[0];
this.m12 = matrix[1];
this.m13 = matrix[2];
this.m14 = matrix[3];
this.m21 = matrix[4];
this.m22 = matrix[5];
this.m23 = matrix[6];
this.m24 = matrix[7];
this.m31 = matrix[8];
this.m32 = matrix[9];
this.m33 = matrix[10];
this.m34 = matrix[11];
this.m41 = matrix[12];
this.m42 = matrix[13];
this.m43 = matrix[14];
this.m44 = matrix[15];
return;
}
if (arguments[0] instanceof CanvasMatrix4) {
this.m11 = matrix.m11;
this.m12 = matrix.m12;
this.m13 = matrix.m13;
this.m14 = matrix.m14;
this.m21 = matrix.m21;
this.m22 = matrix.m22;
this.m23 = matrix.m23;
this.m24 = matrix.m24;
this.m31 = matrix.m31;
this.m32 = matrix.m32;
this.m33 = matrix.m33;
this.m34 = matrix.m34;
this.m41 = matrix.m41;
this.m42 = matrix.m42;
this.m43 = matrix.m43;
this.m44 = matrix.m44;
return;
}
}
this.makeIdentity();
};
CanvasMatrix4.prototype.getAsArray = function()
{
return [
this.m11, this.m12, this.m13, this.m14,
this.m21, this.m22, this.m23, this.m24,
this.m31, this.m32, this.m33, this.m34,
this.m41, this.m42, this.m43, this.m44
];
};
CanvasMatrix4.prototype.getAsWebGLFloatArray = function()
{
return new WebGLFloatArray(this.getAsArray());
};
CanvasMatrix4.prototype.makeIdentity = function()
{
this.m11 = 1;
this.m12 = 0;
this.m13 = 0;
this.m14 = 0;
this.m21 = 0;
this.m22 = 1;
this.m23 = 0;
this.m24 = 0;
this.m31 = 0;
this.m32 = 0;
this.m33 = 1;
this.m34 = 0;
this.m41 = 0;
this.m42 = 0;
this.m43 = 0;
this.m44 = 1;
};
CanvasMatrix4.prototype.transpose = function()
{
var tmp = this.m12;
this.m12 = this.m21;
this.m21 = tmp;
tmp = this.m13;
this.m13 = this.m31;
this.m31 = tmp;
tmp = this.m14;
this.m14 = this.m41;
this.m41 = tmp;
tmp = this.m23;
this.m23 = this.m32;
this.m32 = tmp;
tmp = this.m24;
this.m24 = this.m42;
this.m42 = tmp;
tmp = this.m34;
this.m34 = this.m43;
this.m43 = tmp;
};
CanvasMatrix4.prototype.invert = function()
{
// Calculate the 4x4 determinant
// If the determinant is zero,
// then the inverse matrix is not unique.
var det = this._determinant4x4();
if (Math.abs(det) &lt; 1e-8)
return null;
this._makeAdjoint();
// Scale the adjoint matrix to get the inverse
this.m11 /= det;
this.m12 /= det;
this.m13 /= det;
this.m14 /= det;
this.m21 /= det;
this.m22 /= det;
this.m23 /= det;
this.m24 /= det;
this.m31 /= det;
this.m32 /= det;
this.m33 /= det;
this.m34 /= det;
this.m41 /= det;
this.m42 /= det;
this.m43 /= det;
this.m44 /= det;
};
CanvasMatrix4.prototype.translate = function(x,y,z)
{
if (x === undefined)
x = 0;
if (y === undefined)
y = 0;
if (z === undefined)
z = 0;
var matrix = new CanvasMatrix4();
matrix.m41 = x;
matrix.m42 = y;
matrix.m43 = z;
this.multRight(matrix);
};
CanvasMatrix4.prototype.scale = function(x,y,z)
{
if (x === undefined)
x = 1;
if (z === undefined) {
if (y === undefined) {
y = x;
z = x;
}
else
z = 1;
}
else if (y === undefined)
y = x;
var matrix = new CanvasMatrix4();
matrix.m11 = x;
matrix.m22 = y;
matrix.m33 = z;
this.multRight(matrix);
};
CanvasMatrix4.prototype.rotate = function(angle,x,y,z)
{
// angles are in degrees. Switch to radians
angle = angle / 180 * Math.PI;
angle /= 2;
var sinA = Math.sin(angle);
var cosA = Math.cos(angle);
var sinA2 = sinA * sinA;
// normalize
var length = Math.sqrt(x * x + y * y + z * z);
if (length === 0) {
// bad vector, just use something reasonable
x = 0;
y = 0;
z = 1;
} else if (length != 1) {
x /= length;
y /= length;
z /= length;
}
var mat = new CanvasMatrix4();
// optimize case where axis is along major axis
if (x == 1 &amp;&amp; y === 0 &amp;&amp; z === 0) {
mat.m11 = 1;
mat.m12 = 0;
mat.m13 = 0;
mat.m21 = 0;
mat.m22 = 1 - 2 * sinA2;
mat.m23 = 2 * sinA * cosA;
mat.m31 = 0;
mat.m32 = -2 * sinA * cosA;
mat.m33 = 1 - 2 * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else if (x === 0 &amp;&amp; y == 1 &amp;&amp; z === 0) {
mat.m11 = 1 - 2 * sinA2;
mat.m12 = 0;
mat.m13 = -2 * sinA * cosA;
mat.m21 = 0;
mat.m22 = 1;
mat.m23 = 0;
mat.m31 = 2 * sinA * cosA;
mat.m32 = 0;
mat.m33 = 1 - 2 * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else if (x === 0 &amp;&amp; y === 0 &amp;&amp; z == 1) {
mat.m11 = 1 - 2 * sinA2;
mat.m12 = 2 * sinA * cosA;
mat.m13 = 0;
mat.m21 = -2 * sinA * cosA;
mat.m22 = 1 - 2 * sinA2;
mat.m23 = 0;
mat.m31 = 0;
mat.m32 = 0;
mat.m33 = 1;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
} else {
var x2 = x*x;
var y2 = y*y;
var z2 = z*z;
mat.m11 = 1 - 2 * (y2 + z2) * sinA2;
mat.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
mat.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
mat.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
mat.m22 = 1 - 2 * (z2 + x2) * sinA2;
mat.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
mat.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
mat.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
mat.m33 = 1 - 2 * (x2 + y2) * sinA2;
mat.m14 = mat.m24 = mat.m34 = 0;
mat.m41 = mat.m42 = mat.m43 = 0;
mat.m44 = 1;
}
this.multRight(mat);
};
CanvasMatrix4.prototype.multRight = function(mat)
{
var m11 = (this.m11 * mat.m11 + this.m12 * mat.m21 +
this.m13 * mat.m31 + this.m14 * mat.m41);
var m12 = (this.m11 * mat.m12 + this.m12 * mat.m22 +
this.m13 * mat.m32 + this.m14 * mat.m42);
var m13 = (this.m11 * mat.m13 + this.m12 * mat.m23 +
this.m13 * mat.m33 + this.m14 * mat.m43);
var m14 = (this.m11 * mat.m14 + this.m12 * mat.m24 +
this.m13 * mat.m34 + this.m14 * mat.m44);
var m21 = (this.m21 * mat.m11 + this.m22 * mat.m21 +
this.m23 * mat.m31 + this.m24 * mat.m41);
var m22 = (this.m21 * mat.m12 + this.m22 * mat.m22 +
this.m23 * mat.m32 + this.m24 * mat.m42);
var m23 = (this.m21 * mat.m13 + this.m22 * mat.m23 +
this.m23 * mat.m33 + this.m24 * mat.m43);
var m24 = (this.m21 * mat.m14 + this.m22 * mat.m24 +
this.m23 * mat.m34 + this.m24 * mat.m44);
var m31 = (this.m31 * mat.m11 + this.m32 * mat.m21 +
this.m33 * mat.m31 + this.m34 * mat.m41);
var m32 = (this.m31 * mat.m12 + this.m32 * mat.m22 +
this.m33 * mat.m32 + this.m34 * mat.m42);
var m33 = (this.m31 * mat.m13 + this.m32 * mat.m23 +
this.m33 * mat.m33 + this.m34 * mat.m43);
var m34 = (this.m31 * mat.m14 + this.m32 * mat.m24 +
this.m33 * mat.m34 + this.m34 * mat.m44);
var m41 = (this.m41 * mat.m11 + this.m42 * mat.m21 +
this.m43 * mat.m31 + this.m44 * mat.m41);
var m42 = (this.m41 * mat.m12 + this.m42 * mat.m22 +
this.m43 * mat.m32 + this.m44 * mat.m42);
var m43 = (this.m41 * mat.m13 + this.m42 * mat.m23 +
this.m43 * mat.m33 + this.m44 * mat.m43);
var m44 = (this.m41 * mat.m14 + this.m42 * mat.m24 +
this.m43 * mat.m34 + this.m44 * mat.m44);
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m14 = m14;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m24 = m24;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
this.m34 = m34;
this.m41 = m41;
this.m42 = m42;
this.m43 = m43;
this.m44 = m44;
};
CanvasMatrix4.prototype.multLeft = function(mat)
{
var m11 = (mat.m11 * this.m11 + mat.m12 * this.m21 +
mat.m13 * this.m31 + mat.m14 * this.m41);
var m12 = (mat.m11 * this.m12 + mat.m12 * this.m22 +
mat.m13 * this.m32 + mat.m14 * this.m42);
var m13 = (mat.m11 * this.m13 + mat.m12 * this.m23 +
mat.m13 * this.m33 + mat.m14 * this.m43);
var m14 = (mat.m11 * this.m14 + mat.m12 * this.m24 +
mat.m13 * this.m34 + mat.m14 * this.m44);
var m21 = (mat.m21 * this.m11 + mat.m22 * this.m21 +
mat.m23 * this.m31 + mat.m24 * this.m41);
var m22 = (mat.m21 * this.m12 + mat.m22 * this.m22 +
mat.m23 * this.m32 + mat.m24 * this.m42);
var m23 = (mat.m21 * this.m13 + mat.m22 * this.m23 +
mat.m23 * this.m33 + mat.m24 * this.m43);
var m24 = (mat.m21 * this.m14 + mat.m22 * this.m24 +
mat.m23 * this.m34 + mat.m24 * this.m44);
var m31 = (mat.m31 * this.m11 + mat.m32 * this.m21 +
mat.m33 * this.m31 + mat.m34 * this.m41);
var m32 = (mat.m31 * this.m12 + mat.m32 * this.m22 +
mat.m33 * this.m32 + mat.m34 * this.m42);
var m33 = (mat.m31 * this.m13 + mat.m32 * this.m23 +
mat.m33 * this.m33 + mat.m34 * this.m43);
var m34 = (mat.m31 * this.m14 + mat.m32 * this.m24 +
mat.m33 * this.m34 + mat.m34 * this.m44);
var m41 = (mat.m41 * this.m11 + mat.m42 * this.m21 +
mat.m43 * this.m31 + mat.m44 * this.m41);
var m42 = (mat.m41 * this.m12 + mat.m42 * this.m22 +
mat.m43 * this.m32 + mat.m44 * this.m42);
var m43 = (mat.m41 * this.m13 + mat.m42 * this.m23 +
mat.m43 * this.m33 + mat.m44 * this.m43);
var m44 = (mat.m41 * this.m14 + mat.m42 * this.m24 +
mat.m43 * this.m34 + mat.m44 * this.m44);
this.m11 = m11;
this.m12 = m12;
this.m13 = m13;
this.m14 = m14;
this.m21 = m21;
this.m22 = m22;
this.m23 = m23;
this.m24 = m24;
this.m31 = m31;
this.m32 = m32;
this.m33 = m33;
this.m34 = m34;
this.m41 = m41;
this.m42 = m42;
this.m43 = m43;
this.m44 = m44;
};
CanvasMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
{
var tx = (left + right) / (left - right);
var ty = (top + bottom) / (bottom - top);
var tz = (far + near) / (near - far);
var matrix = new CanvasMatrix4();
matrix.m11 = 2 / (right - left);
matrix.m12 = 0;
matrix.m13 = 0;
matrix.m14 = 0;
matrix.m21 = 0;
matrix.m22 = 2 / (top - bottom);
matrix.m23 = 0;
matrix.m24 = 0;
matrix.m31 = 0;
matrix.m32 = 0;
matrix.m33 = -2 / (far - near);
matrix.m34 = 0;
matrix.m41 = tx;
matrix.m42 = ty;
matrix.m43 = tz;
matrix.m44 = 1;
this.multRight(matrix);
};
CanvasMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
{
var matrix = new CanvasMatrix4();
var A = (right + left) / (right - left);
var B = (top + bottom) / (top - bottom);
var C = -(far + near) / (far - near);
var D = -(2 * far * near) / (far - near);
matrix.m11 = (2 * near) / (right - left);
matrix.m12 = 0;
matrix.m13 = 0;
matrix.m14 = 0;
matrix.m21 = 0;
matrix.m22 = 2 * near / (top - bottom);
matrix.m23 = 0;
matrix.m24 = 0;
matrix.m31 = A;
matrix.m32 = B;
matrix.m33 = C;
matrix.m34 = -1;
matrix.m41 = 0;
matrix.m42 = 0;
matrix.m43 = D;
matrix.m44 = 0;
this.multRight(matrix);
};
CanvasMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
{
var top = Math.tan(fovy * Math.PI / 360) * zNear;
var bottom = -top;
var left = aspect * bottom;
var right = aspect * top;
this.frustum(left, right, bottom, top, zNear, zFar);
};
CanvasMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
{
var matrix = new CanvasMatrix4();
// Make rotation matrix
// Z vector
var zx = eyex - centerx;
var zy = eyey - centery;
var zz = eyez - centerz;
var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
if (mag) {
zx /= mag;
zy /= mag;
zz /= mag;
}
// Y vector
var yx = upx;
var yy = upy;
var yz = upz;
// X vector = Y cross Z
xx =  yy * zz - yz * zy;
xy = -yx * zz + yz * zx;
xz =  yx * zy - yy * zx;
// Recompute Y = Z cross X
yx = zy * xz - zz * xy;
yy = -zx * xz + zz * xx;
yx = zx * xy - zy * xx;
// cross product gives area of parallelogram, which is &lt; 1.0 for
// non-perpendicular unit-length vectors; so normalize x, y here
mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
if (mag) {
xx /= mag;
xy /= mag;
xz /= mag;
}
mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
if (mag) {
yx /= mag;
yy /= mag;
yz /= mag;
}
matrix.m11 = xx;
matrix.m12 = xy;
matrix.m13 = xz;
matrix.m14 = 0;
matrix.m21 = yx;
matrix.m22 = yy;
matrix.m23 = yz;
matrix.m24 = 0;
matrix.m31 = zx;
matrix.m32 = zy;
matrix.m33 = zz;
matrix.m34 = 0;
matrix.m41 = 0;
matrix.m42 = 0;
matrix.m43 = 0;
matrix.m44 = 1;
matrix.translate(-eyex, -eyey, -eyez);
this.multRight(matrix);
};
// Support functions
CanvasMatrix4.prototype._determinant2x2 = function(a, b, c, d)
{
return a * d - b * c;
};
CanvasMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
{
return a1 * this._determinant2x2(b2, b3, c2, c3) -
b1 * this._determinant2x2(a2, a3, c2, c3) +
c1 * this._determinant2x2(a2, a3, b2, b3);
};
CanvasMatrix4.prototype._determinant4x4 = function()
{
var a1 = this.m11;
var b1 = this.m12;
var c1 = this.m13;
var d1 = this.m14;
var a2 = this.m21;
var b2 = this.m22;
var c2 = this.m23;
var d2 = this.m24;
var a3 = this.m31;
var b3 = this.m32;
var c3 = this.m33;
var d3 = this.m34;
var a4 = this.m41;
var b4 = this.m42;
var c4 = this.m43;
var d4 = this.m44;
return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
};
CanvasMatrix4.prototype._makeAdjoint = function()
{
var a1 = this.m11;
var b1 = this.m12;
var c1 = this.m13;
var d1 = this.m14;
var a2 = this.m21;
var b2 = this.m22;
var c2 = this.m23;
var d2 = this.m24;
var a3 = this.m31;
var b3 = this.m32;
var c3 = this.m33;
var d3 = this.m34;
var a4 = this.m41;
var b4 = this.m42;
var c4 = this.m43;
var d4 = this.m44;
// Row column labeling reversed since we transpose rows &amp; columns
this.m11  =   this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
this.m21  = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
this.m31  =   this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
this.m41  = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
this.m12  = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
this.m22  =   this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
this.m32  = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
this.m42  =   this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
this.m13  =   this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
this.m23  = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
this.m33  =   this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
this.m43  = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
this.m14  = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
this.m24  =   this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
this.m34  = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
this.m44  =   this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
};&lt;/script&gt;
&lt;script&gt;// To generate the help pages for this library, use
// jsdoc --destination ../../../doc/rglwidgetClass --template ~/node_modules/jsdoc-baseline rglClass.src.js
// To validate, use
// setwd(&#34;.../inst/htmlwidgets/lib/rglClass&#34;)
// hints &lt;- js::jshint(readLines(&#34;rglClass.src.js&#34;))
// hints[, c(&#34;line&#34;, &#34;reason&#34;)]
/**
* The class of an rgl widget
* @class
*/
rglwidgetClass = function() {
this.canvas = null;
this.userMatrix = new CanvasMatrix4();
this.types = [];
this.prMatrix = new CanvasMatrix4();
this.mvMatrix = new CanvasMatrix4();
this.vp = null;
this.prmvMatrix = null;
this.origs = null;
this.gl = null;
this.scene = null;
this.select = {state: &#34;inactive&#34;, subscene: null, region: {p1: {x:0, y:0}, p2: {x:0, y:0}}};
this.drawing = false;
};
/**
* Multiply matrix by vector
* @returns {number[]}
* @param M {number[][]} Left operand
* @param v {number[]} Right operand
*/
rglwidgetClass.prototype.multMV = function(M, v) {
return [ M.m11 * v[0] + M.m12 * v[1] + M.m13 * v[2] + M.m14 * v[3],
M.m21 * v[0] + M.m22 * v[1] + M.m23 * v[2] + M.m24 * v[3],
M.m31 * v[0] + M.m32 * v[1] + M.m33 * v[2] + M.m34 * v[3],
M.m41 * v[0] + M.m42 * v[1] + M.m43 * v[2] + M.m44 * v[3]
];
};
/**
* Multiply row vector by Matrix
* @returns {number[]}
* @param v {number[]} left operand
* @param M {number[][]} right operand
*/
rglwidgetClass.prototype.multVM = function(v, M) {
return [ M.m11 * v[0] + M.m21 * v[1] + M.m31 * v[2] + M.m41 * v[3],
M.m12 * v[0] + M.m22 * v[1] + M.m32 * v[2] + M.m42 * v[3],
M.m13 * v[0] + M.m23 * v[1] + M.m33 * v[2] + M.m43 * v[3],
M.m14 * v[0] + M.m24 * v[1] + M.m34 * v[2] + M.m44 * v[3]
];
};
/**
* Euclidean length of a vector
* @returns {number}
* @param v {number[]}
*/
rglwidgetClass.prototype.vlen = function(v) {
return Math.sqrt(this.dotprod(v, v));
};
/**
* Dot product of two vectors
* @instance rglwidgetClass
* @returns {number}
* @param a {number[]}
* @param b {number[]}
*/
rglwidgetClass.prototype.dotprod = function(a, b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
};
/**
* Cross product of two vectors
* @returns {number[]}
* @param a {number[]}
* @param b {number[]}
*/
rglwidgetClass.prototype.xprod = function(a, b) {
return [a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]];
};
/**
* Bind vectors or matrices by columns
* @returns {number[][]}
* @param a {number[]|number[][]}
* @param b {number[]|number[][]}
*/
rglwidgetClass.prototype.cbind = function(a, b) {
if (b.length &lt; a.length)
b = this.repeatToLen(b, a.length);
else if (a.length &lt; b.length)
a = this.repeatToLen(a, b.length);
return a.map(function(currentValue, index, array) {
return currentValue.concat(b[index]);
});
};
/**
* Swap elements
* @returns {any[]}
* @param a {any[]}
* @param i {number} Element to swap
* @param j {number} Other element to swap
*/
rglwidgetClass.prototype.swap = function(a, i, j) {
var temp = a[i];
a[i] = a[j];
a[j] = temp;
};
/**
* Flatten a matrix into a vector
* @returns {any[]}
* @param a {any[][]}
*/
rglwidgetClass.prototype.flatten = function(arr, result) {
var value;
if (typeof result === &#34;undefined&#34;) result = [];
for (var i = 0, length = arr.length; i &lt; length; i++) {
value = arr[i];
if (Array.isArray(value)) {
this.flatten(value, result);
} else {
result.push(value);
}
}
return result;
};
/**
* set element of 1d or 2d array as if it was flattened.
* Column major, zero based!
* @returns {any[]|any[][]}
* @param {any[]|any[][]} a - array
* @param {number} i - element
* @param {any} value
*/
rglwidgetClass.prototype.setElement = function(a, i, value) {
if (Array.isArray(a[0])) {
var dim = a.length,
col = Math.floor(i/dim),
row = i % dim;
a[row][col] = value;
} else {
a[i] = value;
}
};
/**
* Transpose an array
* @returns {any[][]}
* @param {any[][]} a
*/
rglwidgetClass.prototype.transpose = function(a) {
var newArray = [],
n = a.length,
m = a[0].length,
i;
for(i = 0; i &lt; m; i++){
newArray.push([]);
}
for(i = 0; i &lt; n; i++){
for(var j = 0; j &lt; m; j++){
newArray[j].push(a[i][j]);
}
}
return newArray;
};
/**
* Calculate sum of squares of a numeric vector
* @returns {number}
* @param {number[]} x
*/
rglwidgetClass.prototype.sumsq = function(x) {
var result = 0, i;
for (i=0; i &lt; x.length; i++)
result += x[i]*x[i];
return result;
};
/**
* Convert a matrix to a CanvasMatrix4
* @returns {CanvasMatrix4}
* @param {number[][]|number[]} mat
*/
rglwidgetClass.prototype.toCanvasMatrix4 = function(mat) {
if (mat instanceof CanvasMatrix4)
return mat;
var result = new CanvasMatrix4();
mat = this.flatten(this.transpose(mat));
result.load(mat);
return result;
};
/**
* Convert an R-style numeric colour string to an rgb vector
* @returns {number[]}
* @param {string} s
*/
rglwidgetClass.prototype.stringToRgb = function(s) {
s = s.replace(&#34;#&#34;, &#34;&#34;);
var bigint = parseInt(s, 16);
return [((bigint &gt;&gt; 16) &amp; 255)/255,
((bigint &gt;&gt; 8) &amp; 255)/255,
(bigint &amp; 255)/255];
};
/**
* Take a component-by-component product of two 3 vectors
* @returns {number[]}
* @param {number[]} x
* @param {number[]} y
*/
rglwidgetClass.prototype.componentProduct = function(x, y) {
if (typeof y === &#34;undefined&#34;) {
this.alertOnce(&#34;Bad arg to componentProduct&#34;);
}
var result = new Float32Array(3), i;
for (i = 0; i&lt;3; i++)
result[i] = x[i]*y[i];
return result;
};
/**
* Get next higher power of two
* @returns { number }
* @param { number } value - input value
*/
rglwidgetClass.prototype.getPowerOfTwo = function(value) {
var pow = 1;
while(pow&lt;value) {
pow *= 2;
}
return pow;
};
/**
* Unique entries
* @returns { any[] }
* @param { any[] } arr - An array
*/
rglwidgetClass.prototype.unique = function(arr) {
arr = [].concat(arr);
return arr.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
};
/**
* Shallow compare of arrays
* @returns { boolean }
* @param { any[] } a - An array
* @param { any[] } b - Another array
*/
rglwidgetClass.prototype.equalArrays = function(a, b) {
return a === b || (a &amp;&amp; b &amp;&amp;
a.length === b.length &amp;&amp;
a.every(function(v, i) {return v === b[i];}));
};
/**
* Repeat an array to a desired length
* @returns {any[]}
* @param {any | any[]} arr The input array
* @param {number} len The desired output length
*/
rglwidgetClass.prototype.repeatToLen = function(arr, len) {
arr = [].concat(arr);
while (arr.length &lt; len/2)
arr = arr.concat(arr);
return arr.concat(arr.slice(0, len - arr.length));
};
/**
* Give a single alert message, not to be repeated.
* @param {string} msg  The message to give.
*/
rglwidgetClass.prototype.alertOnce = function(msg) {
if (typeof this.alerted !== &#34;undefined&#34;)
return;
this.alerted = true;
alert(msg);
};
rglwidgetClass.prototype.f_is_lit = 1;
rglwidgetClass.prototype.f_is_smooth = 2;
rglwidgetClass.prototype.f_has_texture = 4;
rglwidgetClass.prototype.f_depth_sort = 8;
rglwidgetClass.prototype.f_fixed_quads = 16;
rglwidgetClass.prototype.f_is_transparent = 32;
rglwidgetClass.prototype.f_is_lines = 64;
rglwidgetClass.prototype.f_sprites_3d = 128;
rglwidgetClass.prototype.f_sprite_3d = 256;
rglwidgetClass.prototype.f_is_subscene = 512;
rglwidgetClass.prototype.f_is_clipplanes = 1024;
rglwidgetClass.prototype.f_fixed_size = 2048;
rglwidgetClass.prototype.f_is_points = 4096;
rglwidgetClass.prototype.f_is_twosided = 8192;
rglwidgetClass.prototype.f_fat_lines = 16384;
rglwidgetClass.prototype.f_is_brush = 32768;
/**
* Which list does a particular id come from?
* @returns { string }
* @param {number} id The id to look up.
*/
rglwidgetClass.prototype.whichList = function(id) {
var obj = this.getObj(id),
flags = obj.flags;
if (obj.type === &#34;light&#34;)
return &#34;lights&#34;;
if (flags &amp; this.f_is_subscene)
return &#34;subscenes&#34;;
if (flags &amp; this.f_is_clipplanes)
return &#34;clipplanes&#34;;
if (flags &amp; this.f_is_transparent)
return &#34;transparent&#34;;
return &#34;opaque&#34;;
};
/**
* Get an object by id number.
* @returns { Object }
* @param {number} id
*/
rglwidgetClass.prototype.getObj = function(id) {
if (typeof id !== &#34;number&#34;) {
this.alertOnce(&#34;getObj id is &#34;+typeof id);
}
return this.scene.objects[id];
};
/**
* Get ids of a particular type from a subscene or the whole scene
* @returns { number[] }
* @param {string} type What type of object?
* @param {number} subscene  Which subscene?  If not given, find in the whole scene
*/
rglwidgetClass.prototype.getIdsByType = function(type, subscene) {
var
result = [], i, self = this;
if (typeof subscene === &#34;undefined&#34;) {
Object.keys(this.scene.objects).forEach(
function(key) {
key = parseInt(key, 10);
if (self.getObj(key).type === type)
result.push(key);
});
} else {
ids = this.getObj(subscene).objects;
for (i=0; i &lt; ids.length; i++) {
if (this.getObj(ids[i]).type === type) {
result.push(ids[i]);
}
}
}
return result;
};
/**
* Get a particular material property for an id
* @returns { any }
* @param {number} id  Which object?
* @param {string} property Which material property?
*/
rglwidgetClass.prototype.getMaterial = function(id, property) {
var obj = this.getObj(id), mat;
if (typeof obj.material === &#34;undefined&#34;)
console.error(&#34;material undefined&#34;);
mat = obj.material[property];
if (typeof mat === &#34;undefined&#34;)
mat = this.scene.material[property];
return mat;
};
/**
* Is a particular id in a subscene?
* @returns { boolean }
* @param {number} id Which id?
* @param {number} subscene Which subscene id?
*/
rglwidgetClass.prototype.inSubscene = function(id, subscene) {
return this.getObj(subscene).objects.indexOf(id) &gt; -1;
};
/**
* Add an id to a subscene.
* @param {number} id Which id?
* @param {number} subscene Which subscene id?
*/
rglwidgetClass.prototype.addToSubscene = function(id, subscene) {
var thelist,
thesub = this.getObj(subscene),
ids = [id],
obj = this.getObj(id), i;
if (typeof obj != &#34;undefined&#34; &amp;&amp; typeof (obj.newIds) !== &#34;undefined&#34;) {
ids = ids.concat(obj.newIds);
}
thesub.objects = [].concat(thesub.objects);
for (i = 0; i &lt; ids.length; i++) {
id = ids[i];
if (thesub.objects.indexOf(id) == -1) {
thelist = this.whichList(id);
thesub.objects.push(id);
thesub[thelist].push(id);
}
}
};
/**
* Delete an id from a subscene
* @param { number } id - the id to add
* @param { number } subscene - the id of the subscene
*/
rglwidgetClass.prototype.delFromSubscene = function(id, subscene) {
var thelist,
thesub = this.getObj(subscene),
obj = this.getObj(id),
ids = [id], i;
if (typeof obj !== &#34;undefined&#34; &amp;&amp; typeof (obj.newIds) !== &#34;undefined&#34;)
ids = ids.concat(obj.newIds);
thesub.objects = [].concat(thesub.objects); // It might be a scalar
for (j=0; j&lt;ids.length;j++) {
id = ids[j];
i = thesub.objects.indexOf(id);
if (i &gt; -1) {
thesub.objects.splice(i, 1);
thelist = this.whichList(id);
i = thesub[thelist].indexOf(id);
thesub[thelist].splice(i, 1);
}
}
};
/**
* Set the ids in a subscene
* @param { number[] } ids - the ids to set
* @param { number } subsceneid - the id of the subscene
*/
rglwidgetClass.prototype.setSubsceneEntries = function(ids, subsceneid) {
var sub = this.getObj(subsceneid);
sub.objects = ids;
this.initSubscene(subsceneid);
};
/**
* Get the ids in a subscene
* @returns {number[]}
* @param { number } subscene - the id of the subscene
*/
rglwidgetClass.prototype.getSubsceneEntries = function(subscene) {
return this.getObj(subscene).objects;
};
/**
* Get the ids of the subscenes within a subscene
* @returns { number[] }
* @param { number } subscene - the id of the subscene
*/
rglwidgetClass.prototype.getChildSubscenes = function(subscene) {
return this.getObj(subscene).subscenes;
};
/**
* Start drawing
* @returns { boolean } Previous state
*/
rglwidgetClass.prototype.startDrawing = function() {
var value = this.drawing;
this.drawing = true;
return value;
};
/**
* Stop drawing and check for context loss
* @param { boolean } saved - Previous state
*/
rglwidgetClass.prototype.stopDrawing = function(saved) {
this.drawing = saved;
if (!saved &amp;&amp; this.gl &amp;&amp; this.gl.isContextLost())
this.restartCanvas();
};
/**
* Generate the vertex shader for an object
* @returns {string}
* @param { number } id - Id of object
*/
rglwidgetClass.prototype.getVertexShader = function(id) {
var obj = this.getObj(id),
userShader = obj.userVertexShader,
flags = obj.flags,
type = obj.type,
is_lit = flags &amp; this.f_is_lit,
has_texture = flags &amp; this.f_has_texture,
fixed_quads = flags &amp; this.f_fixed_quads,
sprites_3d = flags &amp; this.f_sprites_3d,
sprite_3d = flags &amp; this.f_sprite_3d,
nclipplanes = this.countClipplanes(),
fixed_size = flags &amp; this.f_fixed_size,
is_points = flags &amp; this.f_is_points,
is_twosided = flags &amp; this.f_is_twosided,
fat_lines = flags &amp; this.f_fat_lines,
is_brush = flags &amp; this.f_is_brush,
result;
if (type === &#34;clipplanes&#34; || sprites_3d) return;
if (typeof userShader !== &#34;undefined&#34;) return userShader;
result = &#34;  /* ****** &#34;+type+&#34; object &#34;+id+&#34; vertex shader ****** */\n&#34;+
&#34;  attribute vec3 aPos;\n&#34;+
&#34;  attribute vec4 aCol;\n&#34;+
&#34; uniform mat4 mvMatrix;\n&#34;+
&#34; uniform mat4 prMatrix;\n&#34;+
&#34; varying vec4 vCol;\n&#34;+
&#34; varying vec4 vPosition;\n&#34;;
if ((is_lit &amp;&amp; !fixed_quads &amp;&amp; !is_brush) || sprite_3d)
result = result + &#34;  attribute vec3 aNorm;\n&#34;+
&#34; uniform mat4 normMatrix;\n&#34;+
&#34; varying vec3 vNormal;\n&#34;;
if (has_texture || type === &#34;text&#34;)
result = result + &#34; attribute vec2 aTexcoord;\n&#34;+
&#34; varying vec2 vTexcoord;\n&#34;;
if (fixed_size)
result = result + &#34;  uniform vec2 textScale;\n&#34;;
if (fixed_quads)
result = result + &#34;  attribute vec2 aOfs;\n&#34;;
else if (sprite_3d)
result = result + &#34;  uniform vec3 uOrig;\n&#34;+
&#34;  uniform float uSize;\n&#34;+
&#34;  uniform mat4 usermat;\n&#34;;
if (is_twosided)
result = result + &#34;  attribute vec3 aPos1;\n&#34;+
&#34;  attribute vec3 aPos2;\n&#34;+
&#34;  varying float normz;\n&#34;;
if (fat_lines) {
result = result +   &#34;  attribute vec3 aNext;\n&#34;+
&#34;  attribute vec2 aPoint;\n&#34;+
&#34;  varying vec2 vPoint;\n&#34;+
&#34;  varying float vLength;\n&#34;+
&#34;  uniform float uAspect;\n&#34;+
&#34;  uniform float uLwd;\n&#34;;
}
result = result + &#34;  void main(void) {\n&#34;;
if ((nclipplanes || (!fixed_quads &amp;&amp; !sprite_3d)) &amp;&amp; !is_brush)
result = result + &#34;    vPosition = mvMatrix * vec4(aPos, 1.);\n&#34;;
if (!fixed_quads &amp;&amp; !sprite_3d &amp;&amp; !is_brush)
result = result + &#34;    gl_Position = prMatrix * vPosition;\n&#34;;
if (is_points) {
var size = this.getMaterial(id, &#34;size&#34;);
result = result + &#34;    gl_PointSize = &#34;+size.toFixed(1)+&#34;;\n&#34;;
}
result = result + &#34;    vCol = aCol;\n&#34;;
if (is_lit &amp;&amp; !fixed_quads &amp;&amp; !sprite_3d &amp;&amp; !is_brush)
result = result + &#34;    vNormal = normalize((normMatrix * vec4(aNorm, 1.)).xyz);\n&#34;;
if (has_texture || type == &#34;text&#34;)
result = result + &#34;    vTexcoord = aTexcoord;\n&#34;;
if (fixed_size)
result = result + &#34;    vec4 pos = prMatrix * mvMatrix * vec4(aPos, 1.);\n&#34;+
&#34;   pos = pos/pos.w;\n&#34;+
&#34;   gl_Position = pos + vec4(aOfs*textScale, 0.,0.);\n&#34;;
if (type == &#34;sprites&#34; &amp;&amp; !fixed_size)
result = result + &#34;    vec4 pos = mvMatrix * vec4(aPos, 1.);\n&#34;+
&#34;   pos = pos/pos.w + vec4(aOfs, 0., 0.);\n&#34;+
&#34;   gl_Position = prMatrix*pos;\n&#34;;
if (sprite_3d)
result = result + &#34;   vNormal = normalize((normMatrix * vec4(aNorm, 1.)).xyz);\n&#34;+
&#34;   vec4 pos = mvMatrix * vec4(uOrig, 1.);\n&#34;+
&#34;   vPosition = pos/pos.w + vec4(uSize*(vec4(aPos, 1.)*usermat).xyz,0.);\n&#34;+
&#34;   gl_Position = prMatrix * vPosition;\n&#34;;
if (is_twosided)
result = result + &#34;   vec4 pos1 = prMatrix*(mvMatrix*vec4(aPos1, 1.));\n&#34;+
&#34;   pos1 = pos1/pos1.w - gl_Position/gl_Position.w;\n&#34;+
&#34;   vec4 pos2 = prMatrix*(mvMatrix*vec4(aPos2, 1.));\n&#34;+
&#34;   pos2 = pos2/pos2.w - gl_Position/gl_Position.w;\n&#34;+
&#34;   normz = pos1.x*pos2.y - pos1.y*pos2.x;\n&#34;;
if (fat_lines) 
/* This code was inspired by Matt Deslauriers&#39; code in https://mattdesl.svbtle.com/drawing-lines-is-hard */
result = result + &#34;   vec2 aspectVec = vec2(uAspect, 1.0);\n&#34;+
&#34;   mat4 projViewModel = prMatrix * mvMatrix;\n&#34;+
&#34;   vec4 currentProjected = projViewModel * vec4(aPos, 1.0);\n&#34;+
&#34;   currentProjected = currentProjected/currentProjected.w;\n&#34;+
&#34;   vec4 nextProjected = projViewModel * vec4(aNext, 1.0);\n&#34;+
&#34;   vec2 currentScreen = currentProjected.xy * aspectVec;\n&#34;+
&#34;   vec2 nextScreen = (nextProjected.xy / nextProjected.w) * aspectVec;\n&#34;+
&#34;   float len = uLwd;\n&#34;+
&#34;   vec2 dir = vec2(1.0, 0.0);\n&#34;+
&#34;   vPoint = aPoint;\n&#34;+
&#34;   vLength = length(nextScreen - currentScreen)/2.0;\n&#34;+
&#34;   vLength = vLength/(vLength + len);\n&#34;+
&#34;   if (vLength &gt; 0.0) {\n&#34;+
&#34;     dir = normalize(nextScreen - currentScreen);\n&#34;+
&#34;   }\n&#34;+
&#34;   vec2 normal = vec2(-dir.y, dir.x);\n&#34;+
&#34;   dir.x /= uAspect;\n&#34;+
&#34;   normal.x /= uAspect;\n&#34;+
&#34;   vec4 offset = vec4(len*(normal*aPoint.x*aPoint.y - dir), 0.0, 0.0);\n&#34;+
&#34;   gl_Position = currentProjected + offset;\n&#34;;
if (is_brush)
result = result + &#34;   gl_Position = vec4(aPos, 1.);\n&#34;;
result = result + &#34;  }\n&#34;;
// console.log(result);
return result;
};
/**
* Generate the fragment shader for an object
* @returns {string}
* @param { number } id - Id of object
*/
rglwidgetClass.prototype.getFragmentShader = function(id) {
var obj = this.getObj(id),
userShader = obj.userFragmentShader,
flags = obj.flags,
type = obj.type,
is_lit = flags &amp; this.f_is_lit,
has_texture = flags &amp; this.f_has_texture,
fixed_quads = flags &amp; this.f_fixed_quads,
sprites_3d = flags &amp; this.f_sprites_3d,
is_twosided = (flags &amp; this.f_is_twosided) &gt; 0,
fat_lines = flags &amp; this.f_fat_lines,
is_transparent = flags &amp; this.f_is_transparent,
nclipplanes = this.countClipplanes(), i,
texture_format, nlights,
result;
if (type === &#34;clipplanes&#34; || sprites_3d) return;
if (typeof userShader !== &#34;undefined&#34;) return userShader;
if (has_texture)
texture_format = this.getMaterial(id, &#34;textype&#34;);
result = &#34;/* ****** &#34;+type+&#34; object &#34;+id+&#34; fragment shader ****** */\n&#34;+
&#34;#ifdef GL_ES\n&#34;+
&#34;#ifdef GL_FRAGMENT_PRECISION_HIGH\n&#34;+
&#34;  precision highp float;\n&#34;+
&#34;#else\n&#34;+
&#34;  precision mediump float;\n&#34;+
&#34;#endif\n&#34;+
&#34;#endif\n&#34;+
&#34;  varying vec4 vCol; // carries alpha\n&#34;+
&#34;  varying vec4 vPosition;\n&#34;;
if (has_texture || type === &#34;text&#34;)
result = result + &#34;  varying vec2 vTexcoord;\n&#34;+
&#34; uniform sampler2D uSampler;\n&#34;;
if (is_lit &amp;&amp; !fixed_quads)
result = result + &#34;  varying vec3 vNormal;\n&#34;;
for (i = 0; i &lt; nclipplanes; i++)
result = result + &#34;  uniform vec4 vClipplane&#34;+i+&#34;;\n&#34;;
if (is_lit) {
nlights = this.countLights();
if (nlights)
result = result + &#34;  uniform mat4 mvMatrix;\n&#34;;
else
is_lit = false;
}
if (is_lit) {
result = result + &#34;   uniform vec3 emission;\n&#34;+
&#34;   uniform float shininess;\n&#34;;
for (i=0; i &lt; nlights; i++) {
result = result + &#34;   uniform vec3 ambient&#34; + i + &#34;;\n&#34;+
&#34;   uniform vec3 specular&#34; + i +&#34;; // light*material\n&#34;+
&#34;   uniform vec3 diffuse&#34; + i + &#34;;\n&#34;+
&#34;   uniform vec3 lightDir&#34; + i + &#34;;\n&#34;+
&#34;   uniform bool viewpoint&#34; + i + &#34;;\n&#34;+
&#34;   uniform bool finite&#34; + i + &#34;;\n&#34;;
}
}
if (is_twosided)
result = result + &#34;   uniform bool front;\n&#34;+
&#34;   varying float normz;\n&#34;;
if (fat_lines)
result = result + &#34;   varying vec2 vPoint;\n&#34;+
&#34;   varying float vLength;\n&#34;;
result = result + &#34;  void main(void) {\n&#34;;
if (fat_lines) {
result = result + &#34;    vec2 point = vPoint;\n&#34;+
&#34;    bool neg = point.y &lt; 0.0;\n&#34;+
&#34;    point.y = neg ? &#34;+
&#34;      (point.y + vLength)/(1.0 - vLength) :\n&#34;+
&#34;     -(point.y - vLength)/(1.0 - vLength);\n&#34;;
if (is_transparent &amp;&amp; type == &#34;linestrip&#34;)
result = result+&#34;    if (neg &amp;&amp; length(point) &lt;= 1.0) discard;\n&#34;;
result = result + &#34;    point.y = min(point.y, 0.0);\n&#34;+
&#34;    if (length(point) &gt; 1.0) discard;\n&#34;;
}
for (i=0; i &lt; nclipplanes;i++)
result = result + &#34;    if (dot(vPosition, vClipplane&#34;+i+&#34;) &lt; 0.0) discard;\n&#34;;
if (fixed_quads) {
result = result +   &#34;    vec3 n = vec3(0., 0., 1.);\n&#34;;
} else if (is_lit) {
result = result +   &#34;    vec3 n = normalize(vNormal);\n&#34;;
}
if (is_twosided) {
result = result +   &#34;    if ((normz &lt;= 0.) != front) discard;\n&#34;;
}
if (is_lit) {
result = result + &#34;    vec3 eye = normalize(-vPosition.xyz);\n&#34;+
&#34;   vec3 lightdir;\n&#34;+
&#34;   vec4 colDiff;\n&#34;+
&#34;   vec3 halfVec;\n&#34;+
&#34;   vec4 lighteffect = vec4(emission, 0.);\n&#34;+
&#34;   vec3 col;\n&#34;+
&#34;   float nDotL;\n&#34;;
if (!fixed_quads) {
result = result +   &#34;   n = -faceforward(n, n, eye);\n&#34;;
}
for (i=0; i &lt; nlights; i++) {
result = result + &#34;   colDiff = vec4(vCol.rgb * diffuse&#34; + i + &#34;, vCol.a);\n&#34;+
&#34;   lightdir = lightDir&#34; + i + &#34;;\n&#34;+
&#34;   if (!viewpoint&#34; + i +&#34;)\n&#34;+
&#34;     lightdir = (mvMatrix * vec4(lightdir, 1.)).xyz;\n&#34;+
&#34;   if (!finite&#34; + i + &#34;) {\n&#34;+
&#34;     halfVec = normalize(lightdir + eye);\n&#34;+
&#34;   } else {\n&#34;+
&#34;     lightdir = normalize(lightdir - vPosition.xyz);\n&#34;+
&#34;     halfVec = normalize(lightdir + eye);\n&#34;+
&#34;   }\n&#34;+
&#34;    col = ambient&#34; + i + &#34;;\n&#34;+
&#34;   nDotL = dot(n, lightdir);\n&#34;+
&#34;   col = col + max(nDotL, 0.) * colDiff.rgb;\n&#34;+
&#34;   col = col + pow(max(dot(halfVec, n), 0.), shininess) * specular&#34; + i + &#34;;\n&#34;+
&#34;   lighteffect = lighteffect + vec4(col, colDiff.a);\n&#34;;
}
} else {
result = result +   &#34;   vec4 colDiff = vCol;\n&#34;+
&#34;    vec4 lighteffect = colDiff;\n&#34;;
}
if (type === &#34;text&#34;)
result = result +   &#34;    vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n&#34;;
if (has_texture) {
result = result + {
rgb:            &#34;   vec4 textureColor = lighteffect*vec4(texture2D(uSampler, vTexcoord).rgb, 1.);\n&#34;,
rgba:           &#34;   vec4 textureColor = lighteffect*texture2D(uSampler, vTexcoord);\n&#34;,
alpha:          &#34;   vec4 textureColor = texture2D(uSampler, vTexcoord);\n&#34;+
&#34;   float luminance = dot(vec3(1.,1.,1.), textureColor.rgb)/3.;\n&#34;+
&#34;   textureColor =  vec4(lighteffect.rgb, lighteffect.a*luminance);\n&#34;,
luminance:      &#34;   vec4 textureColor = vec4(lighteffect.rgb*dot(texture2D(uSampler, vTexcoord).rgb, vec3(1.,1.,1.))/3., lighteffect.a);\n&#34;,
&#34;luminance.alpha&#34;:&#34;    vec4 textureColor = texture2D(uSampler, vTexcoord);\n&#34;+
&#34;   float luminance = dot(vec3(1.,1.,1.),textureColor.rgb)/3.;\n&#34;+
&#34;   textureColor = vec4(lighteffect.rgb*luminance, lighteffect.a*textureColor.a);\n&#34;
}[texture_format]+
&#34;   gl_FragColor = textureColor;\n&#34;;
} else if (type === &#34;text&#34;) {
result = result +   &#34;    if (textureColor.a &lt; 0.1)\n&#34;+
&#34;     discard;\n&#34;+
&#34;   else\n&#34;+
&#34;     gl_FragColor = textureColor;\n&#34;;
} else
result = result +   &#34;   gl_FragColor = lighteffect;\n&#34;;
//if (fat_lines)
//  result = result +   &#34;   gl_FragColor = vec4(0.0, abs(point.x), abs(point.y), 1.0);&#34;
result = result + &#34;  }\n&#34;;
// console.log(result);
return result;
};
/**
* Call gl functions to create and compile shader
* @returns {Object}
* @param { number } shaderType - gl code for shader type
* @param { string } code - code for the shader
*/
rglwidgetClass.prototype.getShader = function(shaderType, code) {
var gl = this.gl, shader;
shader = gl.createShader(shaderType);
gl.shaderSource(shader, code);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) &amp;&amp; !gl.isContextLost())
alert(gl.getShaderInfoLog(shader));
return shader;
};
/**
* Handle a texture after its image has been loaded
* @param { Object } texture - the gl texture object
* @param { Object } textureCanvas - the canvas holding the image
*/
rglwidgetClass.prototype.handleLoadedTexture = function(texture, textureCanvas) {
var gl = this.gl || this.initGL();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvas);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);
};
/**
* Get maximum dimension of texture in current browser.
* @returns {number}
*/
rglwidgetClass.prototype.getMaxTexSize = function() {
var gl = this.gl || this.initGL();  
return Math.min(4096, gl.getParameter(gl.MAX_TEXTURE_SIZE));
};
/**
* Load an image to a texture
* @param { string } uri - The image location
* @param { Object } texture - the gl texture object
*/
rglwidgetClass.prototype.loadImageToTexture = function(uri, texture) {
var canvas = this.textureCanvas,
ctx = canvas.getContext(&#34;2d&#34;),
image = new Image(),
self = this;
image.onload = function() {
var w = image.width,
h = image.height,
canvasX = self.getPowerOfTwo(w),
canvasY = self.getPowerOfTwo(h),
gl = self.gl || self.initGL(),
maxTexSize = self.getMaxTexSize();
while (canvasX &gt; 1 &amp;&amp; canvasY &gt; 1 &amp;&amp; (canvasX &gt; maxTexSize || canvasY &gt; maxTexSize)) {
canvasX /= 2;
canvasY /= 2;
}
canvas.width = canvasX;
canvas.height = canvasY;
ctx.imageSmoothingEnabled = true;
ctx.drawImage(image, 0, 0, canvasX, canvasY);
self.handleLoadedTexture(texture, canvas);
self.drawScene();
};
image.src = uri;
};
/**
* Draw text to the texture canvas
* @returns { Object } object with text measurements
* @param { string } text - the text
* @param { number } cex - expansion
* @param { string } family - font family
* @param { number } font - font number
*/
rglwidgetClass.prototype.drawTextToCanvas = function(text, cex, family, font) {
var canvasX, canvasY,
textY,
scaling = 20,
textColour = &#34;white&#34;,
backgroundColour = &#34;rgba(0,0,0,0)&#34;,
canvas = this.textureCanvas,
ctx = canvas.getContext(&#34;2d&#34;),
i, textHeight = 0, textHeights = [], width, widths = [], 
offsetx, offsety = 0, line, lines = [], offsetsx = [],
offsetsy = [], lineoffsetsy = [], fontStrings = [],
maxTexSize = this.getMaxTexSize(),
getFontString = function(i) {
textHeights[i] = scaling*cex[i];
var fontString = textHeights[i] + &#34;px&#34;,
family0 = family[i],
font0 = font[i];
if (family0 === &#34;sans&#34;)
family0 = &#34;sans-serif&#34;;
else if (family0 === &#34;mono&#34;)
family0 = &#34;monospace&#34;;
fontString = fontString + &#34; &#34; + family0;
if (font0 === 2 || font0 === 4)
fontString = &#34;bold &#34; + fontString;
if (font0 === 3 || font0 === 4)
fontString = &#34;italic &#34; + fontString;
return fontString;
};
cex = this.repeatToLen(cex, text.length);
family = this.repeatToLen(family, text.length);
font = this.repeatToLen(font, text.length);
canvasX = 1;
line = -1;
offsetx = maxTexSize;
for (i = 0; i &lt; text.length; i++)  {
ctx.font = fontStrings[i] = getFontString(i);
width = widths[i] = ctx.measureText(text[i]).width;
if (offsetx + width &gt; maxTexSize) {
line += 1;
offsety = lineoffsetsy[line] = offsety + 2*textHeight;
if (offsety &gt; maxTexSize)
console.error(&#34;Too many strings for texture.&#34;);
textHeight = 0;
offsetx = 0;
}
textHeight = Math.max(textHeight, textHeights[i]);
offsetsx[i] = offsetx;
offsetx += width;
canvasX = Math.max(canvasX, offsetx);
lines[i] = line;
}
offsety = lineoffsetsy[line] = offsety + 2*textHeight;
for (i = 0; i &lt; text.length; i++) {
offsetsy[i] = lineoffsetsy[lines[i]];
}
canvasX = this.getPowerOfTwo(canvasX);
canvasY = this.getPowerOfTwo(offsety);
canvas.width = canvasX;
canvas.height = canvasY;
ctx.fillStyle = backgroundColour;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.textBaseline = &#34;alphabetic&#34;;
for(i = 0; i &lt; text.length; i++) {
ctx.font = fontStrings[i];
ctx.fillStyle = textColour;
ctx.textAlign = &#34;left&#34;;
ctx.fillText(text[i], offsetsx[i],  offsetsy[i]);
}
return {canvasX:canvasX, canvasY:canvasY,
widths:widths, textHeights:textHeights,
offsetsx:offsetsx, offsetsy:offsetsy};
};
/**
* Set the gl viewport and scissor test
* @param { number } id - id of subscene
*/
rglwidgetClass.prototype.setViewport = function(id) {
var gl = this.gl || this.initGL(),
vp = this.getObj(id).par3d.viewport,
x = vp.x*this.canvas.width,
y = vp.y*this.canvas.height,
width = vp.width*this.canvas.width,
height = vp.height*this.canvas.height;
this.vp = {x:x, y:y, width:width, height:height};
gl.viewport(x, y, width, height);
gl.scissor(x, y, width, height);
gl.enable(gl.SCISSOR_TEST);
};
/**
* Set the projection matrix for a subscene
* @param { number } id - id of subscene
*/
rglwidgetClass.prototype.setprMatrix = function(id) {
var subscene = this.getObj(id),
embedding = subscene.embeddings.projection;
if (embedding === &#34;replace&#34;)
this.prMatrix.makeIdentity();
else
this.setprMatrix(subscene.parent);
if (embedding === &#34;inherit&#34;)
return;
// This is based on the Frustum::enclose code from geom.cpp
var bbox = subscene.par3d.bbox,
scale = subscene.par3d.scale,
ranges = [(bbox[1]-bbox[0])*scale[0]/2,
(bbox[3]-bbox[2])*scale[1]/2,
(bbox[5]-bbox[4])*scale[2]/2],
radius = Math.sqrt(this.sumsq(ranges))*1.1; // A bit bigger to handle labels
if (radius &lt;= 0) radius = 1;
var observer = subscene.par3d.observer,
distance = observer[2],
FOV = subscene.par3d.FOV, ortho = FOV === 0,
t = ortho ? 1 : Math.tan(FOV*Math.PI/360),
near = distance - radius,
far = distance + radius,
hlen,
aspect = this.vp.width/this.vp.height,
z = subscene.par3d.zoom,
userProjection = subscene.par3d.userProjection;
if (far &lt; 0.0)
far = 1.0;
if (near &lt; far/100.0)
near = far/100.0;
hlen = t*near;
if (ortho) {
if (aspect &gt; 1)
this.prMatrix.ortho(-hlen*aspect*z, hlen*aspect*z,
-hlen*z, hlen*z, near, far);
else
this.prMatrix.ortho(-hlen*z, hlen*z,
-hlen*z/aspect, hlen*z/aspect,
near, far);
} else {
if (aspect &gt; 1)
this.prMatrix.frustum(-hlen*aspect*z, hlen*aspect*z,
-hlen*z, hlen*z, near, far);
else
this.prMatrix.frustum(-hlen*z, hlen*z,
-hlen*z/aspect, hlen*z/aspect,
near, far);
}
this.prMatrix.multRight(userProjection);
};
/**
* Set the model-view matrix for a subscene
* @param { number } id - id of the subscene
*/
rglwidgetClass.prototype.setmvMatrix = function(id) {
var observer = this.getObj(id).par3d.observer;
this.mvMatrix.makeIdentity();
this.setmodelMatrix(id);
this.mvMatrix.translate(-observer[0], -observer[1], -observer[2]);
};
/**
* Set the model matrix for a subscene
* @param { number } id - id of the subscene
*/
rglwidgetClass.prototype.setmodelMatrix = function(id) {
var subscene = this.getObj(id),
embedding = subscene.embeddings.model;
if (embedding !== &#34;inherit&#34;) {
var scale = subscene.par3d.scale,
bbox = subscene.par3d.bbox,
center = [(bbox[0]+bbox[1])/2,
(bbox[2]+bbox[3])/2,
(bbox[4]+bbox[5])/2];
this.mvMatrix.translate(-center[0], -center[1], -center[2]);
this.mvMatrix.scale(scale[0], scale[1], scale[2]);
this.mvMatrix.multRight( subscene.par3d.userMatrix );
}
if (embedding !== &#34;replace&#34;)
this.setmodelMatrix(subscene.parent);
};
/**
* Set the normals matrix for a subscene
* @param { number } subsceneid - id of the subscene
*/
rglwidgetClass.prototype.setnormMatrix = function(subsceneid) {
var self = this,
recurse = function(id) {
var sub = self.getObj(id),
embedding = sub.embeddings.model;
if (embedding !== &#34;inherit&#34;) {
var scale = sub.par3d.scale;
self.normMatrix.scale(1/scale[0], 1/scale[1], 1/scale[2]);
self.normMatrix.multRight(sub.par3d.userMatrix);
}
if (embedding !== &#34;replace&#34;)
recurse(sub.parent);
};
self.normMatrix.makeIdentity();
recurse(subsceneid);
};
/**
* Set the combined projection-model-view matrix
*/
rglwidgetClass.prototype.setprmvMatrix = function() {
this.prmvMatrix = new CanvasMatrix4( this.mvMatrix );
this.prmvMatrix.multRight( this.prMatrix );
};
/**
* Count clipping planes in a scene
* @returns {number}
*/
rglwidgetClass.prototype.countClipplanes = function() {
return this.countObjs(&#34;clipplanes&#34;);
};
/**
* Count lights in a scene
* @returns { number }
*/
rglwidgetClass.prototype.countLights = function() {
return this.countObjs(&#34;light&#34;);
};
/**
* Count objects of specific type in a scene
* @returns { number }
* @param { string } type - Type of object to count
*/
rglwidgetClass.prototype.countObjs = function(type) {
var self = this,
bound = 0;
Object.keys(this.scene.objects).forEach(
function(key) {
if (self.getObj(parseInt(key, 10)).type === type)
bound = bound + 1;
});
return bound;
};
/**
* Initialize a subscene
* @param { number } id - id of subscene.
*/
rglwidgetClass.prototype.initSubscene = function(id) {
var sub = this.getObj(id),
i, obj;
if (sub.type !== &#34;subscene&#34;)
return;
sub.par3d.userMatrix = this.toCanvasMatrix4(sub.par3d.userMatrix);
sub.par3d.userProjection = this.toCanvasMatrix4(sub.par3d.userProjection);
sub.par3d.userProjection.transpose();
sub.par3d.listeners = [].concat(sub.par3d.listeners);
sub.backgroundId = undefined;
sub.subscenes = [];
sub.clipplanes = [];
sub.transparent = [];
sub.opaque = [];
sub.lights = [];
for (i=0; i &lt; sub.objects.length; i++) {
obj = this.getObj(sub.objects[i]);
if (typeof obj === &#34;undefined&#34;) {
sub.objects.splice(i, 1);
i--;
} else if (obj.type === &#34;background&#34;)
sub.backgroundId = obj.id;
else
sub[this.whichList(obj.id)].push(obj.id);
}
};
/**
* Copy object
* @param { number } id - id of object to copy
* @param { string } reuse - Document id of scene to reuse
*/
rglwidgetClass.prototype.copyObj = function(id, reuse) {
var obj = this.getObj(id),
prev = document.getElementById(reuse);
if (prev !== null) {
prev = prev.rglinstance;
var
prevobj = prev.getObj(id),
fields = [&#34;flags&#34;, &#34;type&#34;,
&#34;colors&#34;, &#34;vertices&#34;, &#34;centers&#34;,
&#34;normals&#34;, &#34;offsets&#34;,
&#34;texts&#34;, &#34;cex&#34;, &#34;family&#34;, &#34;font&#34;, &#34;adj&#34;,
&#34;material&#34;,
&#34;radii&#34;,
&#34;texcoords&#34;,
&#34;userMatrix&#34;, &#34;ids&#34;,
&#34;dim&#34;,
&#34;par3d&#34;, &#34;userMatrix&#34;,
&#34;viewpoint&#34;, &#34;finite&#34;,
&#34;pos&#34;],
i;
for (i = 0; i &lt; fields.length; i++) {
if (typeof prevobj[fields[i]] !== &#34;undefined&#34;)
obj[fields[i]] = prevobj[fields[i]];
}
} else
console.warn(&#34;copyObj failed&#34;);
};
/**
* Update the triangles used to display a plane
* @param { number } id - id of the plane
* @param { Object } bbox - bounding box in which to display the plane
*/
rglwidgetClass.prototype.planeUpdateTriangles = function(id, bbox) {
var perms = [[0,0,1], [1,2,2], [2,1,0]],
x, xrow, elem, A, d, nhits, i, j, k, u, v, w, intersect, which, v0, v2, vx, reverse,
face1 = [], face2 = [], normals = [],
obj = this.getObj(id),
nPlanes = obj.normals.length;
obj.bbox = bbox;
obj.vertices = [];
obj.initialized = false;
for (elem = 0; elem &lt; nPlanes; elem++) {
//    Vertex Av = normal.getRecycled(elem);
x = [];
A = obj.normals[elem];
d = obj.offsets[elem][0];
nhits = 0;
for (i=0; i&lt;3; i++)
for (j=0; j&lt;2; j++)
for (k=0; k&lt;2; k++) {
u = perms[0][i];
v = perms[1][i];
w = perms[2][i];
if (A[w] !== 0.0) {
intersect = -(d + A[u]*bbox[j+2*u] + A[v]*bbox[k+2*v])/A[w];
if (bbox[2*w] &lt; intersect &amp;&amp; intersect &lt; bbox[1+2*w]) {
xrow = [];
xrow[u] = bbox[j+2*u];
xrow[v] = bbox[k+2*v];
xrow[w] = intersect;
x.push(xrow);
face1[nhits] = j + 2*u;
face2[nhits] = k + 2*v;
nhits++;
}
}
}
if (nhits &gt; 3) {
/* Re-order the intersections so the triangles work */
for (i=0; i&lt;nhits-2; i++) {
which = 0; /* initialize to suppress warning */
for (j=i+1; j&lt;nhits; j++) {
if (face1[i] == face1[j] || face1[i] == face2[j] ||
face2[i] == face1[j] || face2[i] == face2[j] ) {
which = j;
break;
}
}
if (which &gt; i+1) {
this.swap(x, i+1, which);
this.swap(face1, i+1, which);
this.swap(face2, i+1, which);
}
}
}
if (nhits &gt;= 3) {
/* Put in order so that the normal points out the FRONT of the faces */
v0 = [x[0][0] - x[1][0] , x[0][1] - x[1][1], x[0][2] - x[1][2]];
v2 = [x[2][0] - x[1][0] , x[2][1] - x[1][1], x[2][2] - x[1][2]];
/* cross-product */
vx = this.xprod(v0, v2);
reverse = this.dotprod(vx, A) &gt; 0;
for (i=0; i&lt;nhits-2; i++) {
obj.vertices.push(x[0]);
normals.push(A);
for (j=1; j&lt;3; j++) {
obj.vertices.push(x[i + (reverse ? 3-j : j)]);
normals.push(A);
}
}
}
}
obj.pnormals = normals;
};
rglwidgetClass.prototype.getAdj = function (pos, offset, text) {
switch(pos) {
case 1: return [0.5, 1 + offset];
case 2: return [1 + offset/text.length, 0.5];
case 3: return [0.5, -offset];
case 4: return [-offset/text.length, 0.5];
}
}
/**
* Initialize object for display
* @param { number } id - id of object to initialize
*/
rglwidgetClass.prototype.initObj = function(id) {
var obj = this.getObj(id),
flags = obj.flags,
type = obj.type,
is_lit = flags &amp; this.f_is_lit,
is_lines = flags &amp; this.f_is_lines,
fat_lines = flags &amp; this.f_fat_lines,
has_texture = flags &amp; this.f_has_texture,
fixed_quads = flags &amp; this.f_fixed_quads,
is_transparent = obj.is_transparent,
depth_sort = flags &amp; this.f_depth_sort,
sprites_3d = flags &amp; this.f_sprites_3d,
sprite_3d = flags &amp; this.f_sprite_3d,
fixed_size = flags &amp; this.f_fixed_size,
is_twosided = (flags &amp; this.f_is_twosided) &gt; 0,
is_brush = flags &amp; this.f_is_brush,
gl = this.gl || this.initGL(),
polygon_offset,
texinfo, drawtype, nclipplanes, f, nrows, oldrows,
i,j,v,v1,v2, mat, uri, matobj, pass, passes, pmode,
dim, nx, nz, attr;
if (typeof id !== &#34;number&#34;) {
this.alertOnce(&#34;initObj id is &#34;+typeof id);
}
obj.initialized = true;
if (type === &#34;bboxdeco&#34; || type === &#34;subscene&#34;)
return;
if (type === &#34;light&#34;) {
obj.ambient = new Float32Array(obj.colors[0].slice(0,3));
obj.diffuse = new Float32Array(obj.colors[1].slice(0,3));
obj.specular = new Float32Array(obj.colors[2].slice(0,3));
obj.lightDir = new Float32Array(obj.vertices[0]);
return;
}
if (type === &#34;clipplanes&#34;) {
obj.vClipplane = this.flatten(this.cbind(obj.normals, obj.offsets));
return;
}
if (type === &#34;background&#34; &amp;&amp; typeof obj.ids !== &#34;undefined&#34;) {
obj.quad = this.flatten([].concat(obj.ids));
return;
}
polygon_offset = this.getMaterial(id, &#34;polygon_offset&#34;);
if (polygon_offset[0] != 0 || polygon_offset[1] != 0)
obj.polygon_offset = polygon_offset;
if (is_transparent) {
depth_sort = [&#34;triangles&#34;, &#34;quads&#34;, &#34;surface&#34;,
&#34;spheres&#34;, &#34;sprites&#34;, &#34;text&#34;].indexOf(type) &gt;= 0;
}
if (is_brush)
this.initSelection(id);
if (typeof obj.vertices === &#34;undefined&#34;)
obj.vertices = [];
v = obj.vertices;
obj.vertexCount = v.length;
if (!obj.vertexCount) return;
if (is_twosided) {
if (typeof obj.userAttributes === &#34;undefined&#34;)
obj.userAttributes = {};
v1 = Array(v.length);
v2 = Array(v.length);
if (obj.type == &#34;triangles&#34; || obj.type == &#34;quads&#34;) {
if (obj.type == &#34;triangles&#34;)
nrow = 3;
else
nrow = 4;
for (i=0; i&lt;Math.floor(v.length/nrow); i++)
for (j=0; j&lt;nrow; j++) {
v1[nrow*i + j] = v[nrow*i + ((j+1) % nrow)];
v2[nrow*i + j] = v[nrow*i + ((j+2) % nrow)];
}
} else if (obj.type == &#34;surface&#34;) {
dim = obj.dim[0];
nx = dim[0];
nz = dim[1];
for (j=0; j&lt;nx; j++) {
for (i=0; i&lt;nz; i++) {
if (i+1 &lt; nz &amp;&amp; j+1 &lt; nx) {
v2[j + nx*i] = v[j + nx*(i+1)];
v1[j + nx*i] = v[j+1 + nx*(i+1)];
} else if (i+1 &lt; nz) {
v2[j + nx*i] = v[j-1 + nx*i];
v1[j + nx*i] = v[j + nx*(i+1)];
} else {
v2[j + nx*i] = v[j + nx*(i-1)];
v1[j + nx*i] = v[j-1 + nx*(i-1)];
}
}
}
}
obj.userAttributes.aPos1 = v1;
obj.userAttributes.aPos2 = v2;
}
if (!sprites_3d) {
if (gl.isContextLost()) return;
obj.prog = gl.createProgram();
gl.attachShader(obj.prog, this.getShader( gl.VERTEX_SHADER,
this.getVertexShader(id) ));
gl.attachShader(obj.prog, this.getShader( gl.FRAGMENT_SHADER,
this.getFragmentShader(id) ));
//  Force aPos to location 0, aCol to location 1
gl.bindAttribLocation(obj.prog, 0, &#34;aPos&#34;);
gl.bindAttribLocation(obj.prog, 1, &#34;aCol&#34;);
gl.linkProgram(obj.prog);
var linked = gl.getProgramParameter(obj.prog, gl.LINK_STATUS);
if (!linked) {
// An error occurred while linking
var lastError = gl.getProgramInfoLog(obj.prog);
console.warn(&#34;Error in program linking:&#34; + lastError);
gl.deleteProgram(obj.prog);
return;
}
}
if (type === &#34;text&#34;) {
texinfo = this.drawTextToCanvas(obj.texts,
this.flatten(obj.cex),
this.flatten(obj.family),
this.flatten(obj.family));
}
if (fixed_quads &amp;&amp; !sprites_3d) {
obj.ofsLoc = gl.getAttribLocation(obj.prog, &#34;aOfs&#34;);
}
if (sprite_3d) {
obj.origLoc = gl.getUniformLocation(obj.prog, &#34;uOrig&#34;);
obj.sizeLoc = gl.getUniformLocation(obj.prog, &#34;uSize&#34;);
obj.usermatLoc = gl.getUniformLocation(obj.prog, &#34;usermat&#34;);
}
if (has_texture || type == &#34;text&#34;) {
if (!obj.texture)
obj.texture = gl.createTexture();
obj.texLoc = gl.getAttribLocation(obj.prog, &#34;aTexcoord&#34;);
obj.sampler = gl.getUniformLocation(obj.prog, &#34;uSampler&#34;);
}
if (has_texture) {
mat = obj.material;
if (typeof mat.uri !== &#34;undefined&#34;)
uri = mat.uri;
else if (typeof mat.uriElementId === &#34;undefined&#34;) {
matobj = this.getObj(mat.uriId);
if (typeof matobj !== &#34;undefined&#34;) {
uri = matobj.material.uri;
} else {
uri = &#34;&#34;;
}
} else
uri = document.getElementById(mat.uriElementId).rglinstance.getObj(mat.uriId).material.uri;
this.loadImageToTexture(uri, obj.texture);
}
if (type === &#34;text&#34;) {
this.handleLoadedTexture(obj.texture, this.textureCanvas);
}
var stride = 3, nc, cofs, nofs, radofs, oofs, tofs, vnew, fnew,
nextofs = -1, pointofs = -1, alias, colors, key, selection, filter, adj, pos, offset;
obj.alias = undefined;
colors = obj.colors;
j = this.scene.crosstalk.id.indexOf(id);
if (j &gt;= 0) {
key = this.scene.crosstalk.key[j];
options = this.scene.crosstalk.options[j];
colors = colors.slice(0); 
for (i = 0; i &lt; v.length; i++)
colors[i] = obj.colors[i % obj.colors.length].slice(0);
if ( (selection = this.scene.crosstalk.selection) &amp;&amp;
(selection.length || !options.selectedIgnoreNone) )
for (i = 0; i &lt; v.length; i++) {
if (!selection.includes(key[i])) {
if (options.deselectedColor)
colors[i] = options.deselectedColor.slice(0);
colors[i][3] = colors[i][3]*options.deselectedFade;   /* default: mostly transparent if not selected */
} else if (options.selectedColor)
colors[i] = options.selectedColor.slice(0);
}
if ( (filter = this.scene.crosstalk.filter) )
for (i = 0; i &lt; v.length; i++) 
if (!filter.includes(key[i])) {
if (options.filteredColor)
colors[i] = options.filteredColor.slice(0);
colors[i][3] = colors[i][3]*options.filteredFade;   /* default: completely hidden if filtered */
}
}  
nc = obj.colorCount = colors.length;
if (nc &gt; 1) {
cofs = stride;
stride = stride + 4;
v = this.cbind(v, colors);
} else {
cofs = -1;
obj.onecolor = this.flatten(colors);
}
if (typeof obj.normals !== &#34;undefined&#34;) {
nofs = stride;
stride = stride + 3;
v = this.cbind(v, typeof obj.pnormals !== &#34;undefined&#34; ? obj.pnormals : obj.normals);
} else
nofs = -1;
if (typeof obj.radii !== &#34;undefined&#34;) {
radofs = stride;
stride = stride + 1;
// FIXME:  always concat the radii?
if (obj.radii.length === v.length) {
v = this.cbind(v, obj.radii);
} else if (obj.radii.length === 1) {
v = v.map(function(row, i, arr) { return row.concat(obj.radii[0]);});
}
} else
radofs = -1;
// Add default indices
f = Array(v.length);
for (i = 0; i &lt; v.length; i++)
f[i] = i;
obj.f = [f,f];
if (type == &#34;sprites&#34; &amp;&amp; !sprites_3d) {
tofs = stride;
stride += 2;
oofs = stride;
stride += 2;
vnew = new Array(4*v.length);
fnew = new Array(4*v.length);
alias = new Array(v.length);
var rescale = fixed_size ? 72 : 1,
size = obj.radii, s = rescale*size[0]/2;
last = v.length;
f = obj.f[0];
for (i=0; i &lt; v.length; i++) {
if (size.length &gt; 1)
s = rescale*size[i]/2;
vnew[i]  = v[i].concat([0,0,-s,-s]);
fnew[4*i] = f[i];
vnew[last]= v[i].concat([1,0, s,-s]);
fnew[4*i+1] = last++;
vnew[last]= v[i].concat([1,1, s, s]);
fnew[4*i+2] = last++;
vnew[last]= v[i].concat([0,1,-s, s]);
fnew[4*i+3] = last++;
alias[i] = [last-3, last-2, last-1];
}
v = vnew;
obj.vertexCount = v.length;
obj.f = [fnew, fnew];
} else if (type === &#34;text&#34;) {
tofs = stride;
stride += 2;
oofs = stride;
stride += 2;
vnew = new Array(4*v.length);
f = obj.f[0];
fnew = new Array(4*f.length);
alias = new Array(v.length);
last = v.length;
adj = this.flatten(obj.adj);
if (typeof obj.pos !== &#34;undefined&#34;) {
pos = this.flatten(obj.pos);
offset = adj[0];
}
for (i=0; i &lt; v.length; i++) {
if (typeof pos !== &#34;undefined&#34;)
adj = this.getAdj(pos[i % pos.length], offset, obj.texts[i]);
vnew[i]  = v[i].concat([0,-0.5]).concat(adj);
fnew[4*i] = f[i];
vnew[last] = v[i].concat([1,-0.5]).concat(adj);
fnew[4*i+1] = last++;
vnew[last] = v[i].concat([1, 1.5]).concat(adj);
fnew[4*i+2] = last++;
vnew[last] = v[i].concat([0, 1.5]).concat(adj);
fnew[4*i+3] = last++;
alias[i] = [last-3, last-2, last-1];
for (j=0; j &lt; 4; j++) {
v1 = vnew[fnew[4*i+j]];
v1[tofs+2] = 2*(v1[tofs]-v1[tofs+2])*texinfo.widths[i];
v1[tofs+3] = 2*(v1[tofs+1]-v1[tofs+3])*texinfo.textHeights[i];
v1[tofs] = (texinfo.offsetsx[i] + v1[tofs]*texinfo.widths[i])/texinfo.canvasX;
v1[tofs+1] = 1.0-(texinfo.offsetsy[i] -
v1[tofs+1]*texinfo.textHeights[i])/texinfo.canvasY;
vnew[fnew[4*i+j]] = v1;
}
}
v = vnew;
obj.vertexCount = v.length;
obj.f = [fnew, fnew];
} else if (typeof obj.texcoords !== &#34;undefined&#34;) {
tofs = stride;
stride += 2;
oofs = -1;
v = this.cbind(v, obj.texcoords);
} else {
tofs = -1;
oofs = -1;
}
obj.alias = alias;
if (typeof obj.userAttributes !== &#34;undefined&#34;) {
obj.userAttribOffsets = {};
obj.userAttribLocations = {};
obj.userAttribSizes = {};
for (attr in obj.userAttributes) {
obj.userAttribLocations[attr] = gl.getAttribLocation(obj.prog, attr);
if (obj.userAttribLocations[attr] &gt;= 0) { // Attribute may not have been used
obj.userAttribOffsets[attr] = stride;
v = this.cbind(v, obj.userAttributes[attr]);
stride = v[0].length;
obj.userAttribSizes[attr] = stride - obj.userAttribOffsets[attr];
}
}
}
if (typeof obj.userUniforms !== &#34;undefined&#34;) {
obj.userUniformLocations = {};
for (attr in obj.userUniforms)
obj.userUniformLocations[attr] = gl.getUniformLocation(obj.prog, attr);
}
if (sprites_3d) {
obj.userMatrix = new CanvasMatrix4(obj.userMatrix);
obj.objects = this.flatten([].concat(obj.ids));
is_lit = false;
for (i=0; i &lt; obj.objects.length; i++)
this.initObj(obj.objects[i]);
}
if (is_lit &amp;&amp; !fixed_quads) {
obj.normLoc = gl.getAttribLocation(obj.prog, &#34;aNorm&#34;);
}
nclipplanes = this.countClipplanes();
if (nclipplanes &amp;&amp; !sprites_3d) {
obj.clipLoc = [];
for (i=0; i &lt; nclipplanes; i++)
obj.clipLoc[i] = gl.getUniformLocation(obj.prog,&#34;vClipplane&#34; + i);
}
if (is_lit) {
obj.emissionLoc = gl.getUniformLocation(obj.prog, &#34;emission&#34;);
obj.emission = new Float32Array(this.stringToRgb(this.getMaterial(id, &#34;emission&#34;)));
obj.shininessLoc = gl.getUniformLocation(obj.prog, &#34;shininess&#34;);
obj.shininess = this.getMaterial(id, &#34;shininess&#34;);
obj.nlights = this.countLights();
obj.ambientLoc = [];
obj.ambient = new Float32Array(this.stringToRgb(this.getMaterial(id, &#34;ambient&#34;)));
obj.specularLoc = [];
obj.specular = new Float32Array(this.stringToRgb(this.getMaterial(id, &#34;specular&#34;)));
obj.diffuseLoc = [];
obj.lightDirLoc = [];
obj.viewpointLoc = [];
obj.finiteLoc = [];
for (i=0; i &lt; obj.nlights; i++) {
obj.ambientLoc[i] = gl.getUniformLocation(obj.prog, &#34;ambient&#34; + i);
obj.specularLoc[i] = gl.getUniformLocation(obj.prog, &#34;specular&#34; + i);
obj.diffuseLoc[i] = gl.getUniformLocation(obj.prog, &#34;diffuse&#34; + i);
obj.lightDirLoc[i] = gl.getUniformLocation(obj.prog, &#34;lightDir&#34; + i);
obj.viewpointLoc[i] = gl.getUniformLocation(obj.prog, &#34;viewpoint&#34; + i);
obj.finiteLoc[i] = gl.getUniformLocation(obj.prog, &#34;finite&#34; + i);
}
}
obj.passes = is_twosided + 1;
obj.pmode = new Array(obj.passes);
for (pass = 0; pass &lt; obj.passes; pass++) {
if (type === &#34;triangles&#34; || type === &#34;quads&#34; || type === &#34;surface&#34;)
pmode = this.getMaterial(id, (pass === 0) ? &#34;front&#34; : &#34;back&#34;);
else pmode = &#34;filled&#34;;
obj.pmode[pass] = pmode;
}
obj.f.length = obj.passes;
for (pass = 0; pass &lt; obj.passes; pass++) {
f = fnew = obj.f[pass];
pmode = obj.pmode[pass];
if (pmode === &#34;culled&#34;)
f = [];
else if (pmode === &#34;points&#34;) {
// stay with default
} else if ((type === &#34;quads&#34; || type === &#34;text&#34; ||
type === &#34;sprites&#34;) &amp;&amp; !sprites_3d) {
nrows = Math.floor(obj.vertexCount/4);
if (pmode === &#34;filled&#34;) {
fnew = Array(6*nrows);
for (i=0; i &lt; nrows; i++) {
fnew[6*i] = f[4*i];
fnew[6*i+1] = f[4*i + 1];
fnew[6*i+2] = f[4*i + 2];
fnew[6*i+3] = f[4*i];
fnew[6*i+4] = f[4*i + 2];
fnew[6*i+5] = f[4*i + 3];
}
} else {
fnew = Array(8*nrows);
for (i=0; i &lt; nrows; i++) {
fnew[8*i] = f[4*i];
fnew[8*i+1] = f[4*i + 1];
fnew[8*i+2] = f[4*i + 1];
fnew[8*i+3] = f[4*i + 2];
fnew[8*i+4] = f[4*i + 2];
fnew[8*i+5] = f[4*i + 3];
fnew[8*i+6] = f[4*i + 3];
fnew[8*i+7] = f[4*i];
}
}
} else if (type === &#34;triangles&#34;) {
nrows = Math.floor(obj.vertexCount/3);
if (pmode === &#34;filled&#34;) {
fnew = Array(3*nrows);
for (i=0; i &lt; fnew.length; i++) {
fnew[i] = f[i];
}
} else if (pmode === &#34;lines&#34;) {
fnew = Array(6*nrows);
for (i=0; i &lt; nrows; i++) {
fnew[6*i] = f[3*i];
fnew[6*i + 1] = f[3*i + 1];
fnew[6*i + 2] = f[3*i + 1];
fnew[6*i + 3] = f[3*i + 2];
fnew[6*i + 4] = f[3*i + 2];
fnew[6*i + 5] = f[3*i];
}
}
} else if (type === &#34;spheres&#34;) {
// default
} else if (type === &#34;surface&#34;) {
dim = obj.dim[0];
nx = dim[0];
nz = dim[1];
if (pmode === &#34;filled&#34;) {
fnew = [];
for (j=0; j&lt;nx-1; j++) {
for (i=0; i&lt;nz-1; i++) {
fnew.push(f[j + nx*i],
f[j + nx*(i+1)],
f[j + 1 + nx*(i+1)],
f[j + nx*i],
f[j + 1 + nx*(i+1)],
f[j + 1 + nx*i]);
}
}
} else if (pmode === &#34;lines&#34;) {
fnew = [];
for (j=0; j&lt;nx; j++) {
for (i=0; i&lt;nz; i++) {
if (i+1 &lt; nz)
fnew.push(f[j + nx*i],
f[j + nx*(i+1)]);
if (j+1 &lt; nx)
fnew.push(f[j + nx*i],
f[j+1 + nx*i]);
}
}
}
}
obj.f[pass] = fnew;
if (depth_sort) {
drawtype = &#34;DYNAMIC_DRAW&#34;;
} else {
drawtype = &#34;STATIC_DRAW&#34;;
}
}
if (fat_lines) {
alias = undefined;
obj.nextLoc = gl.getAttribLocation(obj.prog, &#34;aNext&#34;);
obj.pointLoc = gl.getAttribLocation(obj.prog, &#34;aPoint&#34;);
obj.aspectLoc = gl.getUniformLocation(obj.prog, &#34;uAspect&#34;);
obj.lwdLoc = gl.getUniformLocation(obj.prog, &#34;uLwd&#34;);
// Expand vertices to turn each segment into a pair of triangles
for (pass = 0; pass &lt; obj.passes; pass++) {
f = obj.f[pass];    
oldrows = f.length;
if (obj.pmode[pass] === &#34;lines&#34;) 
break;
}
if (type === &#34;linestrip&#34;) 
nrows = 4*(oldrows - 1); 
else
nrows = 2*oldrows;
vnew = new Array(nrows);
fnew = new Array(1.5*nrows);
var fnext = new Array(nrows),
fpt = new Array(nrows), 
pt, start, gap = type === &#34;linestrip&#34; ? 3 : 1;
// We&#39;re going to turn each pair of vertices into 4 new ones, with the &#34;next&#34; and &#34;pt&#34; attributes
// added.
// We do this by copying the originals in the first pass, adding the new attributes, then in a 
// second pass add new vertices at the end.
for (i = 0; i &lt; v.length; i++) {
vnew[i] = v[i].concat([0,0,0,0,0]); 
}
nextofs = stride;
pointofs = stride + 3;
stride = stride + 5;
// Now add the extras
last = v.length - 1;
ind = 0;
alias = new Array(f.length);
for (i = 0; i &lt; f.length; i++)
alias[i] = [];
for (i = 0; i &lt; f.length - 1; i++) {
if (type !== &#34;linestrip&#34; &amp;&amp; i % 2 == 1)
continue;
k = ++last;
vnew[k] = vnew[f[i]].slice();
for (j=0; j&lt;3; j++)
vnew[k][nextofs + j] = vnew[f[i+1]][j];
vnew[k][pointofs] = -1;
vnew[k][pointofs+1] = -1;
fnew[ind] = k;
last++;
vnew[last] = vnew[k].slice();
vnew[last][pointofs] = 1;
fnew[ind+1] = last;
alias[f[i]].push(last-1, last);
last++;
k = last;
vnew[k] = vnew[f[i+1]].slice();
for (j=0; j&lt;3; j++)
vnew[k][nextofs + j] = vnew[f[i]][j];
vnew[k][pointofs] = -1;
vnew[k][pointofs+1] = 1;
fnew[ind+2] = k;
fnew[ind+3] = fnew[ind+1];
last++;
vnew[last] = vnew[k].slice();
vnew[last][pointofs] = 1;
fnew[ind+4] = last;
fnew[ind+5] = fnew[ind+2];
ind += 6;
alias[f[i+1]].push(last-1, last);
}
vnew.length = last+1;
v = vnew;
obj.vertexCount = v.length;
if (typeof alias !== &#34;undefined&#34; &amp;&amp; typeof obj.alias !== &#34;undefined&#34;) {  // Already have aliases from previous section?
var oldalias = obj.alias, newalias = Array(obj.alias.length);
for (i = 0; i &lt; newalias.length; i++) {
newalias[i] = oldalias[i].slice();
for (j = 0; j &lt; oldalias[i].length; j++)
Array.prototype.push.apply(newalias[i], alias[oldalias[j]]); // pushes each element 
}
obj.alias = newalias;
} else
obj.alias = alias;
for (pass = 0; pass &lt; obj.passes; pass++)
if (type === &#34;lines&#34; || type === &#34;linestrip&#34; || obj.pmode[pass] == &#34;lines&#34;) {
obj.f[pass] = fnew;
}
if (depth_sort) 
drawtype = &#34;DYNAMIC_DRAW&#34;;
else
drawtype = &#34;STATIC_DRAW&#34;;
}
for (pass = 0; pass &lt; obj.passes; pass++) {
if (obj.vertexCount &gt; 65535) {
if (this.index_uint) {
obj.f[pass] = new Uint32Array(obj.f[pass]);
obj.index_uint = true;
} else
this.alertOnce(&#34;Object has &#34;+obj.vertexCount+&#34; vertices, not supported in this browser.&#34;);
} else {
obj.f[pass] = new Uint16Array(obj.f[pass]);
obj.index_uint = false;
}
}
if (stride !== v[0].length) {
this.alertOnce(&#34;problem in stride calculation&#34;);
}
obj.vOffsets = {vofs:0, cofs:cofs, nofs:nofs, radofs:radofs, oofs:oofs, tofs:tofs,
nextofs:nextofs, pointofs:pointofs, stride:stride};
obj.values = new Float32Array(this.flatten(v));
if (type !== &#34;spheres&#34; &amp;&amp; !sprites_3d) {
obj.buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW); //
obj.ibuf = Array(obj.passes);
obj.ibuf[0] = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[0]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, obj.f[0], gl[drawtype]);
if (is_twosided) {
obj.ibuf[1] = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[1]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, obj.f[1], gl[drawtype]);
}
}
if (!sprites_3d) {
obj.mvMatLoc = gl.getUniformLocation(obj.prog, &#34;mvMatrix&#34;);
obj.prMatLoc = gl.getUniformLocation(obj.prog, &#34;prMatrix&#34;);
}
if (fixed_size) {
obj.textScaleLoc = gl.getUniformLocation(obj.prog, &#34;textScale&#34;);
}
if (is_lit &amp;&amp; !sprites_3d) {
obj.normMatLoc = gl.getUniformLocation(obj.prog, &#34;normMatrix&#34;);
}
if (is_twosided) {
obj.frontLoc = gl.getUniformLocation(obj.prog, &#34;front&#34;);
}
};
/**
* Set gl depth test based on object&#39;s material
* @param { number } id - object to use
*/
rglwidgetClass.prototype.setDepthTest = function(id) {
var gl = this.gl || this.initGL(),
tests = {never: gl.NEVER,
less:  gl.LESS,
equal: gl.EQUAL,
lequal:gl.LEQUAL,
greater: gl.GREATER,
notequal: gl.NOTEQUAL,
gequal: gl.GEQUAL,
always: gl.ALWAYS},
test = tests[this.getMaterial(id, &#34;depth_test&#34;)];
gl.depthFunc(test);
};
rglwidgetClass.prototype.mode4type = {points : &#34;POINTS&#34;,
linestrip : &#34;LINE_STRIP&#34;,
abclines : &#34;LINES&#34;,
lines : &#34;LINES&#34;,
sprites : &#34;TRIANGLES&#34;,
planes : &#34;TRIANGLES&#34;,
text : &#34;TRIANGLES&#34;,
quads : &#34;TRIANGLES&#34;,
surface : &#34;TRIANGLES&#34;,
triangles : &#34;TRIANGLES&#34;};
/**
* Sort objects from back to front
* @returns { number[] }
* @param { Object } obj - object to sort
*/
rglwidgetClass.prototype.depthSort = function(obj) {
var n = obj.centers.length,
depths = new Float32Array(n),
result = new Array(n),
compare = function(i,j) { return depths[j] - depths[i]; },
z, w;
for(i=0; i&lt;n; i++) {
z = this.prmvMatrix.m13*obj.centers[i][0] +
this.prmvMatrix.m23*obj.centers[i][1] +
this.prmvMatrix.m33*obj.centers[i][2] +
this.prmvMatrix.m43;
w = this.prmvMatrix.m14*obj.centers[i][0] +
this.prmvMatrix.m24*obj.centers[i][1] +
this.prmvMatrix.m34*obj.centers[i][2] +
this.prmvMatrix.m44;
depths[i] = z/w;
result[i] = i;
}
result.sort(compare);
return result;
};
rglwidgetClass.prototype.disableArrays = function(obj, enabled) {
var gl = this.gl || this.initGL(),
objLocs = [&#34;normLoc&#34;, &#34;texLoc&#34;, &#34;ofsLoc&#34;, &#34;pointLoc&#34;, &#34;nextLoc&#34;],
thisLocs = [&#34;posLoc&#34;, &#34;colLoc&#34;], i, attr;
for (i = 0; i &lt; objLocs.length; i++) 
if (enabled[objLocs[i]]) gl.disableVertexAttribArray(obj[objLocs[i]]);
for (i = 0; i &lt; thisLocs.length; i++)
if (enabled[thisLocs[i]]) gl.disableVertexAttribArray(this[objLocs[i]]);
if (typeof obj.userAttributes !== &#34;undefined&#34;) {
for (attr in obj.userAttribSizes) {  // Not all attributes may have been used
gl.disableVertexAttribArray( obj.userAttribLocations[attr] );
}
}
}
/**
* Draw an object in a subscene
* @param { number } id - object to draw
* @param { number } subsceneid - id of subscene
*/
rglwidgetClass.prototype.drawObj = function(id, subsceneid) {
var obj = this.getObj(id),
subscene = this.getObj(subsceneid),
flags = obj.flags,
type = obj.type,
is_lit = flags &amp; this.f_is_lit,
has_texture = flags &amp; this.f_has_texture,
fixed_quads = flags &amp; this.f_fixed_quads,
is_transparent = flags &amp; this.f_is_transparent,
depth_sort = flags &amp; this.f_depth_sort,
sprites_3d = flags &amp; this.f_sprites_3d,
sprite_3d = flags &amp; this.f_sprite_3d,
is_lines = flags &amp; this.f_is_lines,
fat_lines = flags &amp; this.f_fat_lines,
is_points = flags &amp; this.f_is_points,
fixed_size = flags &amp; this.f_fixed_size,
is_twosided = (flags &amp; this.f_is_twosided) &gt; 0,
gl = this.gl || this.initGL(),
mat,
sphereMV, baseofs, ofs, sscale, i, count, light,
pass, mode, pmode, attr,
enabled = {};
if (typeof id !== &#34;number&#34;) {
this.alertOnce(&#34;drawObj id is &#34;+typeof id);
}
if (type === &#34;planes&#34;) {
if (obj.bbox !== subscene.par3d.bbox || !obj.initialized) {
this.planeUpdateTriangles(id, subscene.par3d.bbox);
}
}
if (!obj.initialized)
this.initObj(id);
if (type === &#34;clipplanes&#34;) {
count = obj.offsets.length;
var IMVClip = [];
for (i=0; i &lt; count; i++) {
IMVClip[i] = this.multMV(this.invMatrix, obj.vClipplane.slice(4*i, 4*(i+1)));
}
obj.IMVClip = IMVClip;
return;
}
if (type === &#34;light&#34; || type === &#34;bboxdeco&#34; || !obj.vertexCount)
return;
if (!is_transparent &amp;&amp;
obj.someHidden) {
is_transparent = true;
depth_sort = [&#34;triangles&#34;, &#34;quads&#34;, &#34;surface&#34;,
&#34;spheres&#34;, &#34;sprites&#34;, &#34;text&#34;].indexOf(type) &gt;= 0;
}        
this.setDepthTest(id);
if (sprites_3d) {
var norigs = obj.vertices.length,
savenorm = new CanvasMatrix4(this.normMatrix);
this.origs = obj.vertices;
this.usermat = new Float32Array(obj.userMatrix.getAsArray());
this.radii = obj.radii;
this.normMatrix = subscene.spriteNormmat;
for (this.iOrig=0; this.iOrig &lt; norigs; this.iOrig++) {
for (i=0; i &lt; obj.objects.length; i++) {
this.drawObj(obj.objects[i], subsceneid);
}
}
this.normMatrix = savenorm;
return;
} else {
gl.useProgram(obj.prog);
}
if (typeof obj.polygon_offset !== &#34;undefined&#34;) {
gl.polygonOffset(obj.polygon_offset[0],
obj.polygon_offset[1]);
gl.enable(gl.POLYGON_OFFSET_FILL);
}
if (sprite_3d) {
gl.uniform3fv(obj.origLoc, new Float32Array(this.origs[this.iOrig]));
if (this.radii.length &gt; 1) {
gl.uniform1f(obj.sizeLoc, this.radii[this.iOrig][0]);
} else {
gl.uniform1f(obj.sizeLoc, this.radii[0][0]);
}
gl.uniformMatrix4fv(obj.usermatLoc, false, this.usermat);
}
if (type === &#34;spheres&#34;) {
gl.bindBuffer(gl.ARRAY_BUFFER, this.sphere.buf);
} else {
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
}
gl.uniformMatrix4fv( obj.prMatLoc, false, new Float32Array(this.prMatrix.getAsArray()) );
gl.uniformMatrix4fv( obj.mvMatLoc, false, new Float32Array(this.mvMatrix.getAsArray()) );
var clipcheck = 0,
clipplaneids = subscene.clipplanes,
clip, j;
for (i=0; i &lt; clipplaneids.length; i++) {
clip = this.getObj(clipplaneids[i]);
for (j=0; j &lt; clip.offsets.length; j++) {
gl.uniform4fv(obj.clipLoc[clipcheck + j], clip.IMVClip[j]);
}
clipcheck += clip.offsets.length;
}
if (typeof obj.clipLoc !== &#34;undefined&#34;)
for (i=clipcheck; i &lt; obj.clipLoc.length; i++)
gl.uniform4f(obj.clipLoc[i], 0,0,0,0);
if (is_lit) {
gl.uniformMatrix4fv( obj.normMatLoc, false, new Float32Array(this.normMatrix.getAsArray()) );
gl.uniform3fv( obj.emissionLoc, obj.emission);
gl.uniform1f( obj.shininessLoc, obj.shininess);
for (i=0; i &lt; subscene.lights.length; i++) {
light = this.getObj(subscene.lights[i]);
if (!light.initialized) this.initObj(subscene.lights[i]);
gl.uniform3fv( obj.ambientLoc[i], this.componentProduct(light.ambient, obj.ambient));
gl.uniform3fv( obj.specularLoc[i], this.componentProduct(light.specular, obj.specular));
gl.uniform3fv( obj.diffuseLoc[i], light.diffuse);
gl.uniform3fv( obj.lightDirLoc[i], light.lightDir);
gl.uniform1i( obj.viewpointLoc[i], light.viewpoint);
gl.uniform1i( obj.finiteLoc[i], light.finite);
}
for (i=subscene.lights.length; i &lt; obj.nlights; i++) {
gl.uniform3f( obj.ambientLoc[i], 0,0,0);
gl.uniform3f( obj.specularLoc[i], 0,0,0);
gl.uniform3f( obj.diffuseLoc[i], 0,0,0);
}
}
if (fixed_size) {
gl.uniform2f( obj.textScaleLoc, 0.75/this.vp.width, 0.75/this.vp.height);
}
gl.enableVertexAttribArray( this.posLoc );
enabled.posLoc = true;
var nc = obj.colorCount;
count = obj.vertexCount;
if (type === &#34;spheres&#34;) {
subscene = this.getObj(subsceneid);
var scale = subscene.par3d.scale,
scount = count, indices;
gl.vertexAttribPointer(this.posLoc,  3, gl.FLOAT, false, 4*this.sphere.vOffsets.stride,  0);
gl.enableVertexAttribArray(obj.normLoc );
enabled.normLoc = true;
gl.vertexAttribPointer(obj.normLoc,  3, gl.FLOAT, false, 4*this.sphere.vOffsets.stride,  0);
gl.disableVertexAttribArray( this.colLoc );
var sphereNorm = new CanvasMatrix4();
sphereNorm.scale(scale[0], scale[1], scale[2]);
sphereNorm.multRight(this.normMatrix);
gl.uniformMatrix4fv( obj.normMatLoc, false, new Float32Array(sphereNorm.getAsArray()) );
if (nc == 1) {
gl.vertexAttrib4fv( this.colLoc, new Float32Array(obj.onecolor));
}
if (has_texture) {
gl.enableVertexAttribArray( obj.texLoc );
enabled.texLoc = true;
gl.vertexAttribPointer(obj.texLoc, 2, gl.FLOAT, false, 4*this.sphere.vOffsets.stride,
4*this.sphere.vOffsets.tofs);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, obj.texture);
gl.uniform1i( obj.sampler, 0);
}
if (depth_sort)
indices = this.depthSort(obj);
for (i = 0; i &lt; scount; i++) {
sphereMV = new CanvasMatrix4();
if (depth_sort) {
baseofs = indices[i]*obj.vOffsets.stride;
} else {
baseofs = i*obj.vOffsets.stride;
}
ofs = baseofs + obj.vOffsets.radofs;
sscale = obj.values[ofs];
sphereMV.scale(sscale/scale[0], sscale/scale[1], sscale/scale[2]);
sphereMV.translate(obj.values[baseofs],
obj.values[baseofs+1],
obj.values[baseofs+2]);
sphereMV.multRight(this.mvMatrix);
gl.uniformMatrix4fv( obj.mvMatLoc, false, new Float32Array(sphereMV.getAsArray()) );
if (nc &gt; 1) {
ofs = baseofs + obj.vOffsets.cofs;
gl.vertexAttrib4f( this.colLoc, obj.values[ofs],
obj.values[ofs+1],
obj.values[ofs+2],
obj.values[ofs+3] );
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.sphere.ibuf);
gl.drawElements(gl.TRIANGLES, this.sphere.sphereCount, gl.UNSIGNED_SHORT, 0);
}
this.disableArrays(obj, enabled);
if (typeof obj.polygon_offset !== &#34;undefined&#34;) 
gl.disable(gl.POLYGON_OFFSET_FILL);
return;
} else {
if (obj.colorCount === 1) {
gl.disableVertexAttribArray( this.colLoc );
gl.vertexAttrib4fv( this.colLoc, new Float32Array(obj.onecolor));
} else {
gl.enableVertexAttribArray( this.colLoc );
enabled.colLoc = true;
gl.vertexAttribPointer(this.colLoc, 4, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.cofs);
}
}
if (is_lit &amp;&amp; obj.vOffsets.nofs &gt; 0) {
gl.enableVertexAttribArray( obj.normLoc );
enabled.normLoc = true;
gl.vertexAttribPointer(obj.normLoc, 3, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.nofs);
}
if (has_texture || type === &#34;text&#34;) {
gl.enableVertexAttribArray( obj.texLoc );
enabled.texLoc = true;
gl.vertexAttribPointer(obj.texLoc, 2, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.tofs);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, obj.texture);
gl.uniform1i( obj.sampler, 0);
}
if (fixed_quads) {
gl.enableVertexAttribArray( obj.ofsLoc );
enabled.ofsLoc = true;
gl.vertexAttribPointer(obj.ofsLoc, 2, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.oofs);
}
if (typeof obj.userAttributes !== &#34;undefined&#34;) {
for (attr in obj.userAttribSizes) {  // Not all attributes may have been used
gl.enableVertexAttribArray( obj.userAttribLocations[attr] );
gl.vertexAttribPointer( obj.userAttribLocations[attr], obj.userAttribSizes[attr],
gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.userAttribOffsets[attr]);
}
}
if (typeof obj.userUniforms !== &#34;undefined&#34;) {
for (attr in obj.userUniformLocations) {
var loc = obj.userUniformLocations[attr];
if (loc !== null) {
var uniform = obj.userUniforms[attr];
if (typeof uniform.length === &#34;undefined&#34;)
gl.uniform1f(loc, uniform);
else if (typeof uniform[0].length === &#34;undefined&#34;) {
uniform = new Float32Array(uniform);
switch(uniform.length) {
case 2: gl.uniform2fv(loc, uniform); break;
case 3: gl.uniform3fv(loc, uniform); break;
case 4: gl.uniform4fv(loc, uniform); break;
default: console.warn(&#34;bad uniform length&#34;);
}
} else if (uniform.length == 4 &amp;&amp; uniform[0].length == 4)
gl.uniformMatrix4fv(loc, false, new Float32Array(uniform.getAsArray()));
else
console.warn(&#34;unsupported uniform matrix&#34;);
}
}
}
for (pass = 0; pass &lt; obj.passes; pass++) {
pmode = obj.pmode[pass];
if (pmode === &#34;culled&#34;)
continue;
mode = fat_lines &amp;&amp; (is_lines || pmode == &#34;lines&#34;) ? &#34;TRIANGLES&#34; : this.mode4type[type];
if (depth_sort &amp;&amp; pmode == &#34;filled&#34;) {// Don&#39;t try depthsorting on wireframe or points
var faces = this.depthSort(obj),
nfaces = faces.length,
frowsize = Math.floor(obj.f[pass].length/nfaces);
if (type !== &#34;spheres&#34;) {
var f = obj.index_uint ? new Uint32Array(obj.f[pass].length) : new Uint16Array(obj.f[pass].length);
for (i=0; i&lt;nfaces; i++) {
for (j=0; j&lt;frowsize; j++) {
f[frowsize*i + j] = obj.f[pass][frowsize*faces[i] + j];
}
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[pass]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, f, gl.DYNAMIC_DRAW);
}
}
if (is_twosided)
gl.uniform1i(obj.frontLoc, pass !== 0);
if (type !== &#34;spheres&#34;) 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj.ibuf[pass]);
if (type === &#34;sprites&#34; || type === &#34;text&#34; || type === &#34;quads&#34;) {
count = count * 6/4;
} else if (type === &#34;surface&#34;) {
count = obj.f[pass].length;
}
count = obj.f[pass].length;
if (!is_lines &amp;&amp; pmode === &#34;lines&#34; &amp;&amp; !fat_lines) {
mode = &#34;LINES&#34;;
} else if (pmode === &#34;points&#34;) {
mode = &#34;POINTS&#34;;
}
if ((is_lines || pmode === &#34;lines&#34;) &amp;&amp; fat_lines) {
gl.enableVertexAttribArray(obj.pointLoc);
enabled.pointLoc = true;
gl.vertexAttribPointer(obj.pointLoc, 2, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.pointofs);
gl.enableVertexAttribArray(obj.nextLoc );
enabled.nextLoc = true;
gl.vertexAttribPointer(obj.nextLoc, 3, gl.FLOAT, false, 4*obj.vOffsets.stride, 4*obj.vOffsets.nextofs);
gl.uniform1f(obj.aspectLoc, this.vp.width/this.vp.height);
gl.uniform1f(obj.lwdLoc, this.getMaterial(id, &#34;lwd&#34;)/this.vp.height);
}
gl.vertexAttribPointer(this.posLoc,  3, gl.FLOAT, false, 4*obj.vOffsets.stride,  4*obj.vOffsets.vofs);
gl.drawElements(gl[mode], count, obj.index_uint ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT, 0);
this.disableArrays(obj, enabled);
}
if (typeof obj.polygon_offset !== &#34;undefined&#34;) 
gl.disable(gl.POLYGON_OFFSET_FILL);
};
/**
* Draw the background for a subscene
* @param { number } id - id of background object
* @param { number } subsceneid - id of subscene
*/
rglwidgetClass.prototype.drawBackground = function(id, subsceneid) {
var gl = this.gl || this.initGL(),
obj = this.getObj(id),
bg, i;
if (!obj.initialized)
this.initObj(id);
if (obj.colors.length) {
bg = obj.colors[0];
gl.clearColor(bg[0], bg[1], bg[2], bg[3]);
gl.depthMask(true);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
if (typeof obj.quad !== &#34;undefined&#34;) {
this.prMatrix.makeIdentity();
this.mvMatrix.makeIdentity();
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.depthMask(false);
for (i=0; i &lt; obj.quad.length; i++)
this.drawObj(obj.quad[i], subsceneid);
}
};
/**
* Draw a subscene
* @param { number } subsceneid - id of subscene
* @param { boolean } opaquePass - is this the opaque drawing pass?
*/
rglwidgetClass.prototype.drawSubscene = function(subsceneid, opaquePass) {
var gl = this.gl || this.initGL(),
sub = this.getObj(subsceneid),
objects = this.scene.objects,
subids = sub.objects,
subscene_has_faces = false,
subscene_needs_sorting = false,
flags, i, obj;
if (sub.par3d.skipRedraw)
return;
for (i=0; i &lt; subids.length; i++) {
obj = objects[subids[i]];
flags = obj.flags;
if (typeof flags !== &#34;undefined&#34;) {
subscene_has_faces |= (flags &amp; this.f_is_lit)
&amp; !(flags &amp; this.f_fixed_quads);
obj.is_transparent = (flags &amp; this.f_is_transparent) || obj.someHidden;
subscene_needs_sorting |= (flags &amp; this.f_depth_sort) || obj.is_transparent;
}
}
this.setViewport(subsceneid);
if (typeof sub.backgroundId !== &#34;undefined&#34; &amp;&amp; opaquePass)
this.drawBackground(sub.backgroundId, subsceneid);
if (subids.length) {
this.setprMatrix(subsceneid);
this.setmvMatrix(subsceneid);
if (subscene_has_faces) {
this.setnormMatrix(subsceneid);
if ((sub.flags &amp; this.f_sprites_3d) &amp;&amp;
typeof sub.spriteNormmat === &#34;undefined&#34;) {
sub.spriteNormmat = new CanvasMatrix4(this.normMatrix);
}
}
if (subscene_needs_sorting)
this.setprmvMatrix();
var clipids = sub.clipplanes;
if (typeof clipids === &#34;undefined&#34;) {
console.warn(&#34;bad clipids&#34;);
}
if (clipids.length &gt; 0) {
this.invMatrix = new CanvasMatrix4(this.mvMatrix);
this.invMatrix.invert();
for (i = 0; i &lt; clipids.length; i++)
this.drawObj(clipids[i], subsceneid);
}
subids = sub.opaque.concat(sub.transparent);
if (opaquePass) {
gl.enable(gl.DEPTH_TEST);
gl.depthMask(true);
gl.disable(gl.BLEND);
for (i = 0; i &lt; subids.length; i++) {
if (!this.getObj(subids[i]).is_transparent) 
this.drawObj(subids[i], subsceneid);
}
} else {
gl.depthMask(false);
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
gl.ONE, gl.ONE);
gl.enable(gl.BLEND);
for (i = 0; i &lt; subids.length; i++) {
if (this.getObj(subids[i]).is_transparent)
this.drawObj(subids[i], subsceneid);
}
}
subids = sub.subscenes;
for (i = 0; i &lt; subids.length; i++) {
this.drawSubscene(subids[i], opaquePass);
}
}
};
/**
* Respond to brush change
*/
rglwidgetClass.prototype.selectionChanged = function() {
var i, j, k, id, subid = this.select.subscene, subscene,
objids, obj,
p1 = this.select.region.p1, p2 = this.select.region.p2,
filter, selection = [], handle, keys, xmin, x, xmax, ymin, y, ymax, z, v,
someHidden;
if (!subid)
return;
subscene = this.getObj(subid);
objids = subscene.objects;
filter = this.scene.crosstalk.filter;
this.setmvMatrix(subid);
this.setprMatrix(subid);
this.setprmvMatrix();
xmin = Math.min(p1.x, p2.x);
xmax = Math.max(p1.x, p2.x);
ymin = Math.min(p1.y, p2.y);
ymax = Math.max(p1.y, p2.y);
for (i = 0; i &lt; objids.length; i++) {
id = objids[i];
j = this.scene.crosstalk.id.indexOf(id);
if (j &gt;= 0) {
keys = this.scene.crosstalk.key[j];
obj = this.getObj(id);
someHidden = false;
for (k = 0; k &lt; keys.length; k++) {
if (filter &amp;&amp; filter.indexOf(keys[k]) &lt; 0) {
someHidden = true;
continue;
}
v = [].concat(obj.vertices[k]).concat(1.0);
v = this.multVM(v, this.prmvMatrix);
x = v[0]/v[3];
y = v[1]/v[3];
z = v[2]/v[3];
if (xmin &lt;= x &amp;&amp; x &lt;= xmax &amp;&amp; ymin &lt;= y &amp;&amp; y &lt;= ymax &amp;&amp; -1.0 &lt;= z &amp;&amp; z &lt;= 1.0) {
selection.push(keys[k]);
} else
someHidden = true;
}
obj.someHidden = someHidden &amp;&amp; (filter || selection.length);
obj.initialized = false;
/* Who should we notify?  Only shared data in the current subscene, or everyone? */
if (!this.equalArrays(selection, this.scene.crosstalk.selection)) {
handle = this.scene.crosstalk.sel_handle[j];
handle.set(selection, {rglSubsceneId: this.select.subscene});
}
}
}
};
/**
* Respond to selection or filter change from crosstalk
* @param { Object } event - crosstalk event
* @param { boolean } filter - filter or selection?
*/
rglwidgetClass.prototype.selection = function(event, filter) {
var i, j, ids, obj, keys, crosstalk = this.scene.crosstalk,
selection, someHidden;
// Record the message and find out if this event makes some objects have mixed values:
crosstalk = this.scene.crosstalk;
if (filter) {
filter = crosstalk.filter = event.value;
selection = crosstalk.selection;
} else {  
selection = crosstalk.selection = event.value;
filter = crosstalk.filter;
}
ids = crosstalk.id;
for (i = 0; i &lt; ids.length ; i++) {
obj = this.getObj(ids[i]);
obj.initialized = false;
keys = crosstalk.key[i];
someHidden = false;
for (j = 0; j &lt; keys.length &amp;&amp; !someHidden; j++) {
if ((filter &amp;&amp; filter.indexOf(keys[j]) &lt; 0) ||
(selection.length &amp;&amp; selection.indexOf(keys[j]) &lt; 0))
someHidden = true;
}
obj.someHidden = someHidden;
}
this.drawScene();
};
/**
* Clear the selection brush
* @param { number } except - Subscene that should ignore this request
*/
rglwidgetClass.prototype.clearBrush = function(except) {
if (this.select.subscene != except) {
this.select.state = &#34;inactive&#34;;
this.delFromSubscene(this.scene.brushId, this.select.subscene);
}
this.drawScene();
};
/**
* Compute mouse coordinates relative to current canvas
* @returns { Object }
* @param { Object } event - event object from mouse click
*/
rglwidgetClass.prototype.relMouseCoords = function(event) {
var totalOffsetX = 0,
totalOffsetY = 0,
currentElement = this.canvas;
do {
totalOffsetX += currentElement.offsetLeft;
totalOffsetY += currentElement.offsetTop;
currentElement = currentElement.offsetParent;
}
while(currentElement);
var canvasX = event.pageX - totalOffsetX,
canvasY = event.pageY - totalOffsetY;
return {x:canvasX, y:canvasY};
};
/**
* Set mouse handlers for the scene
*/
rglwidgetClass.prototype.setMouseHandlers = function() {
var self = this, activeSubscene, handler,
handlers = {}, drag = 0;
handlers.rotBase = 0;
this.screenToVector = function(x, y) {
var viewport = this.getObj(activeSubscene).par3d.viewport,
width = viewport.width*this.canvas.width,
height = viewport.height*this.canvas.height,
radius = Math.max(width, height)/2.0,
cx = width/2.0,
cy = height/2.0,
px = (x-cx)/radius,
py = (y-cy)/radius,
plen = Math.sqrt(px*px+py*py);
if (plen &gt; 1.e-6) {
px = px/plen;
py = py/plen;
}
var angle = (Math.SQRT2 - plen)/Math.SQRT2*Math.PI/2,
z = Math.sin(angle),
zlen = Math.sqrt(1.0 - z*z);
px = px * zlen;
py = py * zlen;
return [px, py, z];
};
handlers.trackballdown = function(x,y) {
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
i, l = activeModel.par3d.listeners;
handlers.rotBase = this.screenToVector(x, y);
this.saveMat = [];
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.saveMat = new CanvasMatrix4(activeSub.par3d.userMatrix);
}
};
handlers.trackballmove = function(x,y) {
var rotCurrent = this.screenToVector(x,y),
rotBase = handlers.rotBase,
dot = rotBase[0]*rotCurrent[0] +
rotBase[1]*rotCurrent[1] +
rotBase[2]*rotCurrent[2],
angle = Math.acos( dot/this.vlen(rotBase)/this.vlen(rotCurrent) )*180.0/Math.PI,
axis = this.xprod(rotBase, rotCurrent),
objects = this.scene.objects,
activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
l = activeModel.par3d.listeners,
i;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.userMatrix.load(objects[l[i]].saveMat);
activeSub.par3d.userMatrix.rotate(angle, axis[0], axis[1], axis[2]);
}
this.drawScene();
};
handlers.trackballend = 0;
this.clamp = function(x, lo, hi) {
return Math.max(lo, Math.min(x, hi));
};
this.screenToPolar = function(x,y) {
var viewport = this.getObj(activeSubscene).par3d.viewport,
width = viewport.width*this.canvas.width,
height = viewport.height*this.canvas.height,
r = Math.min(width, height)/2,
dx = this.clamp(x - width/2, -r, r),
dy = this.clamp(y - height/2, -r, r);
return [Math.asin(dx/r), Math.asin(-dy/r)];
};
handlers.polardown = function(x,y) {
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
i, l = activeModel.par3d.listeners;
handlers.dragBase = this.screenToPolar(x, y);
this.saveMat = [];
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.saveMat = new CanvasMatrix4(activeSub.par3d.userMatrix);
activeSub.camBase = [-Math.atan2(activeSub.saveMat.m13, activeSub.saveMat.m11),
Math.atan2(activeSub.saveMat.m32, activeSub.saveMat.m22)];
}
};
handlers.polarmove = function(x,y) {
var dragCurrent = this.screenToPolar(x,y),
activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
objects = this.scene.objects,
l = activeModel.par3d.listeners,
i, changepos = [];
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
for (j=0; j&lt;2; j++)
changepos[j] = -(dragCurrent[j] - handlers.dragBase[j]);
activeSub.par3d.userMatrix.makeIdentity();
activeSub.par3d.userMatrix.rotate(changepos[0]*180/Math.PI, 0,-1,0);
activeSub.par3d.userMatrix.multRight(objects[l[i]].saveMat);
activeSub.par3d.userMatrix.rotate(changepos[1]*180/Math.PI, -1,0,0);
}
this.drawScene();
};
handlers.polarend = 0;
handlers.axisdown = function(x,y) {
handlers.rotBase = this.screenToVector(x, this.canvas.height/2);
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
i, l = activeModel.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.saveMat = new CanvasMatrix4(activeSub.par3d.userMatrix);
}
};
handlers.axismove = function(x,y) {
var rotCurrent = this.screenToVector(x, this.canvas.height/2),
rotBase = handlers.rotBase,
angle = (rotCurrent[0] - rotBase[0])*180/Math.PI,
rotMat = new CanvasMatrix4();
rotMat.rotate(angle, handlers.axis[0], handlers.axis[1], handlers.axis[2]);
var activeSub = this.getObj(activeSubscene),
activeModel = this.getObj(this.useid(activeSub.id, &#34;model&#34;)),
i, l = activeModel.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.userMatrix.load(activeSub.saveMat);
activeSub.par3d.userMatrix.multLeft(rotMat);
}
this.drawScene();
};
handlers.axisend = 0;
handlers.y0zoom = 0;
handlers.zoom0 = 0;
handlers.zoomdown = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, &#34;projection&#34;)),
i, l = activeProjection.par3d.listeners;
handlers.y0zoom = y;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.zoom0 = Math.log(activeSub.par3d.zoom);
}
};
handlers.zoommove = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, &#34;projection&#34;)),
i, l = activeProjection.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.zoom = Math.exp(activeSub.zoom0 + (y-handlers.y0zoom)/this.canvas.height);
}
this.drawScene();
};
handlers.zoomend = 0;
handlers.y0fov = 0;
handlers.fovdown = function(x, y) {
handlers.y0fov = y;
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, &#34;projection&#34;)),
i, l = activeProjection.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.fov0 = activeSub.par3d.FOV;
}
};
handlers.fovmove = function(x, y) {
var activeSub = this.getObj(activeSubscene),
activeProjection = this.getObj(this.useid(activeSub.id, &#34;projection&#34;)),
i, l = activeProjection.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = this.getObj(l[i]);
activeSub.par3d.FOV = Math.max(1, Math.min(179, activeSub.fov0 +
180*(y-handlers.y0fov)/this.canvas.height));
}
this.drawScene();
};
handlers.fovend = 0;
handlers.selectingdown = function(x, y) {
var viewport = this.getObj(activeSubscene).par3d.viewport,
width = viewport.width*this.canvas.width,
height = viewport.height*this.canvas.height, 
p = {x: 2.0*x/width - 1.0, y: 2.0*y/height - 1.0};
this.select.region = {p1: p, p2: p};
if (this.select.subscene &amp;&amp; this.select.subscene != activeSubscene)
this.delFromSubscene(this.scene.brushId, this.select.subscene);
this.select.subscene = activeSubscene;
this.addToSubscene(this.scene.brushId, activeSubscene);
this.select.state = &#34;changing&#34;;
if (typeof this.scene.brushId !== &#34;undefined&#34;)
this.getObj(this.scene.brushId).initialized = false;
this.drawScene();
};
handlers.selectingmove = function(x, y) {
var viewport = this.getObj(activeSubscene).par3d.viewport,
width = viewport.width*this.canvas.width,
height = viewport.height*this.canvas.height;
if (this.select.state === &#34;inactive&#34;) 
return;
this.select.region.p2 = {x: 2.0*x/width - 1.0, y: 2.0*y/height - 1.0};
if (typeof this.scene.brushId !== &#34;undefined&#34;)
this.getObj(this.scene.brushId).initialized = false;
this.drawScene();
};
handlers.selectingend = 0;
this.canvas.onmousedown = function ( ev ){
if (!ev.which) // Use w3c defns in preference to MS
switch (ev.button) {
case 0: ev.which = 1; break;
case 1:
case 4: ev.which = 2; break;
case 2: ev.which = 3;
}
drag = [&#34;left&#34;, &#34;middle&#34;, &#34;right&#34;][ev.which-1];
var coords = self.relMouseCoords(ev);
coords.y = self.canvas.height-coords.y;
activeSubscene = self.whichSubscene(coords);
var sub = self.getObj(activeSubscene), f;
handler = sub.par3d.mouseMode[drag];
switch (handler) {
case &#34;xAxis&#34;:
handler = &#34;axis&#34;;
handlers.axis = [1.0, 0.0, 0.0];
break;
case &#34;yAxis&#34;:
handler = &#34;axis&#34;;
handlers.axis = [0.0, 1.0, 0.0];
break;
case &#34;zAxis&#34;:
handler = &#34;axis&#34;;
handlers.axis = [0.0, 0.0, 1.0];
break;
}
f = handlers[handler + &#34;down&#34;];
if (f) {
coords = self.translateCoords(activeSubscene, coords);
f.call(self, coords.x, coords.y);
ev.preventDefault();
} else
console.warn(&#34;Mouse handler &#39;&#34; + handler + &#34;&#39; is not implemented.&#34;);
};
this.canvas.onmouseup = function ( ev ){
if ( drag === 0 ) return;
var f = handlers[handler + &#34;end&#34;];
if (f) {
f.call(self);
ev.preventDefault();
}
drag = 0;
};
this.canvas.onmouseout = this.canvas.onmouseup;
this.canvas.onmousemove = function ( ev ) {
if ( drag === 0 ) return;
var f = handlers[handler + &#34;move&#34;];
if (f) {
var coords = self.relMouseCoords(ev);
coords.y = self.canvas.height - coords.y;
coords = self.translateCoords(activeSubscene, coords);
f.call(self, coords.x, coords.y);
}
};
handlers.wheelHandler = function(ev) {
var del = 1.02, i;
if (ev.shiftKey) del = 1.002;
var ds = ((ev.detail || ev.wheelDelta) &gt; 0) ? del : (1 / del);
if (typeof activeSubscene === &#34;undefined&#34;)
activeSubscene = self.scene.rootSubscene;
var activeSub = self.getObj(activeSubscene),
activeProjection = self.getObj(self.useid(activeSub.id, &#34;projection&#34;)),
l = activeProjection.par3d.listeners;
for (i = 0; i &lt; l.length; i++) {
activeSub = self.getObj(l[i]);
activeSub.par3d.zoom *= ds;
}
self.drawScene();
ev.preventDefault();
};
this.canvas.addEventListener(&#34;DOMMouseScroll&#34;, handlers.wheelHandler, false);
this.canvas.addEventListener(&#34;mousewheel&#34;, handlers.wheelHandler, false);
};
/**
* Find a particular subscene by inheritance
* @returns { number } id of subscene to use
* @param { number } subsceneid - child subscene
* @param { string } type - type of inheritance:  &#34;projection&#34; or &#34;model&#34;
*/
rglwidgetClass.prototype.useid = function(subsceneid, type) {
var sub = this.getObj(subsceneid);
if (sub.embeddings[type] === &#34;inherit&#34;)
return(this.useid(sub.parent, type));
else
return subsceneid;
};
/**
* Check whether point is in viewport of subscene
* @returns {boolean}
* @param { Object } coords - screen coordinates of point
* @param { number } subsceneid - subscene to check
*/
rglwidgetClass.prototype.inViewport = function(coords, subsceneid) {
var viewport = this.getObj(subsceneid).par3d.viewport,
x0 = coords.x - viewport.x*this.canvas.width,
y0 = coords.y - viewport.y*this.canvas.height;
return 0 &lt;= x0 &amp;&amp; x0 &lt;= viewport.width*this.canvas.width &amp;&amp;
0 &lt;= y0 &amp;&amp; y0 &lt;= viewport.height*this.canvas.height;
};
/**
* Find which subscene contains a point
* @returns { number } subscene id
* @param { Object } coords - coordinates of point
*/
rglwidgetClass.prototype.whichSubscene = function(coords) {
var self = this,
recurse = function(subsceneid) {
var subscenes = self.getChildSubscenes(subsceneid), i, id;
for (i=0; i &lt; subscenes.length; i++) {
id = recurse(subscenes[i]);
if (typeof(id) !== &#34;undefined&#34;)
return(id);
}
if (self.inViewport(coords, subsceneid))
return(subsceneid);
else
return undefined;
},
rootid = this.scene.rootSubscene,
result = recurse(rootid);
if (typeof(result) === &#34;undefined&#34;)
result = rootid;
return result;
};
/**
* Translate from window coordinates to viewport coordinates
* @returns { Object } translated coordinates
* @param { number } subsceneid - which subscene to use?
* @param { Object } coords - point to translate
*/
rglwidgetClass.prototype.translateCoords = function(subsceneid, coords) {
var viewport = this.getObj(subsceneid).par3d.viewport;
return {x: coords.x - viewport.x*this.canvas.width,
y: coords.y - viewport.y*this.canvas.height};
};
/**
* Initialize the sphere object
*/
rglwidgetClass.prototype.initSphere = function() {
var verts = this.scene.sphereVerts,
reuse = verts.reuse, result;
if (typeof reuse !== &#34;undefined&#34;) {
var prev = document.getElementById(reuse).rglinstance.sphere;
result = {values: prev.values, vOffsets: prev.vOffsets, it: prev.it};
} else
result = {values: new Float32Array(this.flatten(this.cbind(this.transpose(verts.vb),
this.transpose(verts.texcoords)))),
it: new Uint16Array(this.flatten(this.transpose(verts.it))),
vOffsets: {vofs:0, cofs:-1, nofs:-1, radofs:-1, oofs:-1,
tofs:3, nextofs:-1, pointofs:-1, stride:5}};
result.sphereCount = result.it.length;
this.sphere = result;
};
/**
* Set the vertices in the selection box object
*/
rglwidgetClass.prototype.initSelection = function(id) {
if (typeof this.select.region === &#34;undefined&#34;)
return;
var obj = this.getObj(id),
width = this.canvas.width,
height = this.canvas.height, 
p1 = this.select.region.p1,
p2 = this.select.region.p2;
obj.vertices = [[p1.x, p1.y, 0.0],
[p2.x, p1.y, 0.0],
[p2.x, p2.y, 0.0],
[p1.x, p2.y, 0.0],
[p1.x, p1.y, 0.0]];
};
/**
* Do the gl part of initializing the sphere
*/
rglwidgetClass.prototype.initSphereGL = function() {
var gl = this.gl || this.initGL(), sphere = this.sphere;
if (gl.isContextLost()) return;
sphere.buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, sphere.buf);
gl.bufferData(gl.ARRAY_BUFFER, sphere.values, gl.STATIC_DRAW);
sphere.ibuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sphere.ibuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, sphere.it, gl.STATIC_DRAW);
return;
};
/**
* Initialize the DOM object
* @param { Object } el - the DOM object
* @param { Object } x - the scene data sent by JSON from R
*/
rglwidgetClass.prototype.initialize = function(el, x) {
this.textureCanvas = document.createElement(&#34;canvas&#34;);
this.textureCanvas.style.display = &#34;block&#34;;
this.scene = x;
this.normMatrix = new CanvasMatrix4();
this.saveMat = {};
this.distance = null;
this.posLoc = 0;
this.colLoc = 1;
if (el) {
el.rglinstance = this;
this.el = el;
this.webGLoptions = el.rglinstance.scene.webGLoptions;
this.initCanvas();
}
if (typeof Shiny !== &#34;undefined&#34;) {
var self = this;
Shiny.addCustomMessageHandler(&#34;shinyGetPar3d&#34;,
function(message) {
var i, param, 
subscene = self.getObj(message.subscene),
parameters = [].concat(message.parameters),
result = {tag: message.tag, subscene: message.subscene};
if (typeof subscene !== &#34;undefined&#34;) {
for (i = 0; i &lt; parameters.length; i++) {
param = parameters[i];
result[param] = subscene.par3d[param];
};
} else {
console.log(&#34;subscene &#34;+message.subscene+&#34; undefined.&#34;)
}
Shiny.setInputValue(&#34;par3d:shinyPar3d&#34;, result, {priority: &#34;event&#34;});
});
Shiny.addCustomMessageHandler(&#34;shinySetPar3d&#34;,
function(message) {
var param = message.parameter, 
subscene = self.getObj(message.subscene);
if (typeof subscene !== &#34;undefined&#34;) {
subscene.par3d[param] = message.value;
subscene.initialized = false;
self.drawScene();
} else {
console.log(&#34;subscene &#34;+message.subscene+&#34; undefined.&#34;)
}
})
}
};
/**
* Restart the WebGL canvas
*/
rglwidgetClass.prototype.restartCanvas = function() {
var newcanvas = document.createElement(&#34;canvas&#34;),
self = this;
newcanvas.width = this.el.width;
newcanvas.height = this.el.height;
newcanvas.addEventListener(&#34;webglcontextrestored&#34;,
this.onContextRestored, false);
newcanvas.addEventListener(&#34;webglcontextlost&#34;,
this.onContextLost, false);
while (this.el.firstChild) {
this.el.removeChild(this.el.firstChild);
}
this.el.appendChild(newcanvas);
this.canvas = newcanvas;
this.setMouseHandlers();
if (this.gl) 
Object.keys(this.scene.objects).forEach(function(key){
self.getObj(parseInt(key, 10)).texture = undefined; 
});
this.gl = null;
};
/**
* Initialize the WebGL canvas
*/
rglwidgetClass.prototype.initCanvas = function() {
this.restartCanvas();
var objs = this.scene.objects,
self = this;
Object.keys(objs).forEach(function(key){
var id = parseInt(key, 10),
obj = self.getObj(id);
if (typeof obj.reuse !== &#34;undefined&#34;)
self.copyObj(id, obj.reuse);
});
Object.keys(objs).forEach(function(key){
self.initSubscene(parseInt(key, 10));
});
this.setMouseHandlers();
this.initSphere();
this.onContextRestored = function(event) {
self.initGL();
self.drawScene();
};
this.onContextLost = function(event) {
if (!self.drawing)
this.gl = null;
event.preventDefault();
};
this.initGL0();
this.lazyLoadScene = function() {
if (typeof self.slide === &#34;undefined&#34;)
self.slide = self.getSlide();
if (self.isInBrowserViewport()) {
if (!self.gl || self.gl.isContextLost())
self.initGL();
self.drawScene();
}
};
window.addEventListener(&#34;DOMContentLoaded&#34;, this.lazyLoadScene, false);
window.addEventListener(&#34;load&#34;, this.lazyLoadScene, false);
window.addEventListener(&#34;resize&#34;, this.lazyLoadScene, false);
window.addEventListener(&#34;scroll&#34;, this.lazyLoadScene, false);
this.slide = this.getSlide();
if (this.slide) {
if (typeof this.slide.rgl === &#34;undefined&#34;)
this.slide.rgl = [this];
else
this.slide.rgl.push(this);
if (this.scene.context.rmarkdown) 
if (this.scene.context.rmarkdown === &#34;ioslides_presentation&#34;) {
this.slide.setAttribute(&#34;slideenter&#34;, &#34;this.rgl.forEach(function(scene) { scene.lazyLoadScene.call(window);})&#34;);
} else if (this.scene.context.rmarkdown === &#34;slidy_presentation&#34;) {
// This method would also work in ioslides, but it gets triggered
// something like 5 times per slide for every slide change, so
// you&#39;d need a quicker function than lazyLoadScene.
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
self.slide.rgl.forEach(function(scene) { scene.lazyLoadScene.call(window); });});});
observer.observe(this.slide, { attributes: true, attributeFilter:[&#34;class&#34;] });
}
}
};
/**
* Start the writeWebGL scene. This is only used by writeWebGL; rglwidget has
no debug element and does the drawing in rglwidget.js.
*/
rglwidgetClass.prototype.start = function() {
if (typeof this.prefix !== &#34;undefined&#34;) {
this.debugelement = document.getElementById(this.prefix + &#34;debug&#34;);
this.debug(&#34;&#34;);
}
this.drag = 0;
this.drawScene();
};
/**
* Display a debug message
* @param { string } msg - The message to display
* @param { Object } [img] - Image to insert before message
*/
rglwidgetClass.prototype.debug = function(msg, img) {
if (typeof this.debugelement !== &#34;undefined&#34; &amp;&amp; this.debugelement !== null) {
this.debugelement.innerHTML = msg;
if (typeof img !== &#34;undefined&#34;) {
this.debugelement.insertBefore(img, this.debugelement.firstChild);
}
} else if (msg !== &#34;&#34;)
alert(msg);
};
/**
* Get the snapshot image of this scene
* @returns { Object } The img DOM element
*/
rglwidgetClass.prototype.getSnapshot = function() {
var img;
if (typeof this.scene.snapshot !== &#34;undefined&#34;) {
img = document.createElement(&#34;img&#34;);
img.src = this.scene.snapshot;
img.alt = &#34;Snapshot&#34;;
}
return img;
};
/**
* Initial test for WebGL
*/
rglwidgetClass.prototype.initGL0 = function() {
if (!window.WebGLRenderingContext){
alert(&#34;Your browser does not support WebGL. See http://get.webgl.org&#34;);
return;
}
};
/**
* If we are in an ioslides or slidy presentation, get the
* DOM element of the current slide
* @returns { Object }
*/
rglwidgetClass.prototype.getSlide = function() {
var result = this.el, done = false;
while (result &amp;&amp; !done &amp;&amp; this.scene.context.rmarkdown) {
switch(this.scene.context.rmarkdown) {
case &#34;ioslides_presentation&#34;:
if (result.tagName === &#34;SLIDE&#34;) return result;
break;
case &#34;slidy_presentation&#34;:
if (result.tagName === &#34;DIV&#34; &amp;&amp; result.classList.contains(&#34;slide&#34;))
return result;
break;
default: return null;
}
result = result.parentElement;
}
return null;
};
/**
* Is this scene visible in the browser?
* @returns { boolean }
*/
rglwidgetClass.prototype.isInBrowserViewport = function() {
var rect = this.canvas.getBoundingClientRect(),
windHeight = (window.innerHeight || document.documentElement.clientHeight),
windWidth = (window.innerWidth || document.documentElement.clientWidth);
if (this.scene.context &amp;&amp; this.scene.context.rmarkdown !== null) {
if (this.slide)
return (this.scene.context.rmarkdown === &#34;ioslides_presentation&#34; &amp;&amp;
this.slide.classList.contains(&#34;current&#34;)) ||
(this.scene.context.rmarkdown === &#34;slidy_presentation&#34; &amp;&amp;
!this.slide.classList.contains(&#34;hidden&#34;));
}
return (
rect.top &gt;= -windHeight &amp;&amp;
rect.left &gt;= -windWidth &amp;&amp;
rect.bottom &lt;= 2*windHeight &amp;&amp;
rect.right &lt;= 2*windWidth);
};
/**
* Initialize WebGL
* @returns { Object } the WebGL context
*/
rglwidgetClass.prototype.initGL = function() {
var self = this;
if (this.gl) {
if (!this.drawing &amp;&amp; this.gl.isContextLost())
this.restartCanvas();
else
return this.gl;
}
// if (!this.isInBrowserViewport()) return; Return what??? At this point we know this.gl is null.
this.canvas.addEventListener(&#34;webglcontextrestored&#34;,
this.onContextRestored, false);
this.canvas.addEventListener(&#34;webglcontextlost&#34;,
this.onContextLost, false);
this.gl = this.canvas.getContext(&#34;webgl&#34;, this.webGLoptions) ||
this.canvas.getContext(&#34;experimental-webgl&#34;, this.webGLoptions);
this.index_uint = this.gl.getExtension(&#34;OES_element_index_uint&#34;);
var save = this.startDrawing();
this.initSphereGL();
Object.keys(this.scene.objects).forEach(function(key){
self.initObj(parseInt(key, 10));
});
this.stopDrawing(save);
return this.gl;
};
/**
* Resize the display to match element
* @param { Object } el - DOM element to match
*/
rglwidgetClass.prototype.resize = function(el) {
this.canvas.width = el.width;
this.canvas.height = el.height;
};
/**
* Draw the whole scene
*/
rglwidgetClass.prototype.drawScene = function() {
var gl = this.gl || this.initGL(),
wasDrawing = this.startDrawing();
if (!wasDrawing) {
if (this.select.state !== &#34;inactive&#34;)
this.selectionChanged();
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearDepth(1.0);
gl.clearColor(1,1,1,1);
gl.depthMask(true); // Must be true before clearing depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
this.drawSubscene(this.scene.rootSubscene, true);
this.drawSubscene(this.scene.rootSubscene, false);
}
this.stopDrawing(wasDrawing);
};
/**
* Change the displayed subset
* @param { Object } el - Element of the control; not used.
* @param { Object } control - The subset control data.
*/
rglwidgetClass.prototype.subsetSetter = function(el, control) {
if (typeof control.subscenes === &#34;undefined&#34; ||
control.subscenes === null)
control.subscenes = this.scene.rootSubscene;
var value = Math.round(control.value),
subscenes = [].concat(control.subscenes),
fullset = [].concat(control.fullset),
i, j, entries, subsceneid,
adds = [], deletes = [],
ismissing = function(x) {
return fullset.indexOf(x) &lt; 0;
},
tointeger = function(x) {
return parseInt(x, 10);
};
if (isNaN(value))
value = control.value = 0;
if (control.accumulate)
for (i=0; i &lt;= value; i++)
adds = adds.concat(control.subsets[i]);
else
adds = adds.concat(control.subsets[value]);
deletes = fullset.filter(function(x) { return adds.indexOf(x) &lt; 0; });
for (i = 0; i &lt; subscenes.length; i++) {
subsceneid = subscenes[i];
if (typeof this.getObj(subsceneid) === &#34;undefined&#34;)
this.alertOnce(&#34;typeof object is undefined&#34;);
for (j = 0; j &lt; adds.length; j++)
this.addToSubscene(adds[j], subsceneid);
for (j = 0; j &lt; deletes.length; j++)
this.delFromSubscene(deletes[j], subsceneid);
}
};
/**
* Change the requested property
* @param { Object } el - Element of the control; not used.
* @param { Object } control - The property setter control data.
*/
rglwidgetClass.prototype.propertySetter = function(el, control)  {
var value = control.value,
values = [].concat(control.values),
svals = [].concat(control.param),
direct = values[0] === null,
entries = [].concat(control.entries),
ncol = entries.length,
nrow = values.length/ncol,
properties = this.repeatToLen(control.properties, ncol),
objids = this.repeatToLen(control.objids, ncol),
property, objid = objids[0],
obj = this.getObj(objid),
propvals, i, v1, v2, p, entry, gl, needsBinding,
newprop, newid,
getPropvals = function() {
if (property === &#34;userMatrix&#34;)
return obj.par3d.userMatrix.getAsArray();
else if (property === &#34;scale&#34; || property === &#34;FOV&#34; || property === &#34;zoom&#34;)
return [].concat(obj.par3d[property]);
else
return [].concat(obj[property]);
};
putPropvals = function(newvals) {
if (newvals.length == 1)
newvals = newvals[0];
if (property === &#34;userMatrix&#34;)
obj.par3d.userMatrix.load(newvals);
else if (property === &#34;scale&#34; || property === &#34;FOV&#34; || property === &#34;zoom&#34;)
obj.par3d[property] = newvals;
else
obj[property] = newvals;
};
if (direct &amp;&amp; typeof value === &#34;undefined&#34;)
return;
if (control.interp) {
values = values.slice(0, ncol).concat(values).
concat(values.slice(ncol*(nrow-1), ncol*nrow));
svals = [-Infinity].concat(svals).concat(Infinity);
for (i = 1; i &lt; svals.length; i++) {
if (value &lt;= svals[i]) {
if (svals[i] === Infinity)
p = 1;
else
p = (svals[i] - value)/(svals[i] - svals[i-1]);
break;
}
}
} else if (!direct) {
value = Math.round(value);
}
for (j=0; j&lt;entries.length; j++) {
entry = entries[j];
newprop = properties[j];
newid = objids[j];
if (newprop !== property || newid != objid) {
if (typeof property !== &#34;undefined&#34;)
putPropvals(propvals);
property = newprop;
objid = newid;
obj = this.getObj(objid);
propvals = getPropvals();
}
if (control.interp) {
v1 = values[ncol*(i-1) + j];
v2 = values[ncol*i + j];
this.setElement(propvals, entry, p*v1 + (1-p)*v2);
} else if (!direct) {
this.setElement(propvals, entry, values[ncol*value + j]);
} else {
this.setElement(propvals, entry, value[j]);
}
}
putPropvals(propvals);
needsBinding = [];
for (j=0; j &lt; entries.length; j++) {
if (properties[j] === &#34;values&#34; &amp;&amp;
needsBinding.indexOf(objids[j]) === -1) {
needsBinding.push(objids[j]);
}
}
for (j=0; j &lt; needsBinding.length; j++) {
gl = this.gl || this.initGL();
obj = this.getObj(needsBinding[j]);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW);
}
};
/**
* Change the requested vertices
* @param { Object } el - Element of the control; not used.
* @param { Object } control - The vertext setter control data.
*/
rglwidgetClass.prototype.vertexSetter = function(el, control)  {
var svals = [].concat(control.param),
j, k, p, a, propvals, stride, ofs, obj, entry,
attrib,
ofss    = {x:&#34;vofs&#34;, y:&#34;vofs&#34;, z:&#34;vofs&#34;,
red:&#34;cofs&#34;, green:&#34;cofs&#34;, blue:&#34;cofs&#34;,
alpha:&#34;cofs&#34;, radii:&#34;radofs&#34;,
nx:&#34;nofs&#34;, ny:&#34;nofs&#34;, nz:&#34;nofs&#34;,
ox:&#34;oofs&#34;, oy:&#34;oofs&#34;, oz:&#34;oofs&#34;,
ts:&#34;tofs&#34;, tt:&#34;tofs&#34;},
pos     = {x:0, y:1, z:2,
red:0, green:1, blue:2,
alpha:3,radii:0,
nx:0, ny:1, nz:2,
ox:0, oy:1, oz:2,
ts:0, tt:1},
values = control.values,
direct = values === null,
ncol,
interp = control.interp,
vertices = [].concat(control.vertices),
attributes = [].concat(control.attributes),
value = control.value, newval, aliases, alias;
ncol = Math.max(vertices.length, attributes.length);
if (!ncol)
return;
vertices = this.repeatToLen(vertices, ncol);
attributes = this.repeatToLen(attributes, ncol);
if (direct)
interp = false;
/* JSON doesn&#39;t pass Infinity */
svals[0] = -Infinity;
svals[svals.length - 1] = Infinity;
for (j = 1; j &lt; svals.length; j++) {
if (value &lt;= svals[j]) {
if (interp) {
if (svals[j] === Infinity)
p = 1;
else
p = (svals[j] - value)/(svals[j] - svals[j-1]);
} else {
if (svals[j] - value &gt; value - svals[j-1])
j = j - 1;
}
break;
}
}
obj = this.getObj(control.objid);
// First, make sure color attributes vary in original
if (typeof obj.vOffsets !== &#34;undefined&#34;) {
varies = true;
for (k = 0; k &lt; ncol; k++) {
attrib = attributes[k];
if (typeof attrib !== &#34;undefined&#34;) {
ofs = obj.vOffsets[ofss[attrib]];
if (ofs &lt; 0) {
switch(attrib) {
case &#34;alpha&#34;:
case &#34;red&#34;:
case &#34;green&#34;:
case &#34;blue&#34;:
obj.colors = [obj.colors[0], obj.colors[0]];
break;
}
varies = false;
}
}
}
if (!varies)
this.initObj(control.objid);
}
propvals = obj.values;
aliases = obj.alias;
if (typeof aliases === &#34;undefined&#34;)
aliases = [];
for (k=0; k&lt;ncol; k++) {
if (direct) {
newval = value;
} else if (interp) {
newval = p*values[j-1][k] + (1-p)*values[j][k];
} else {
newval = values[j][k];
}       
attrib = attributes[k];
vertex = vertices[k];
alias = aliases[vertex];
if (obj.type === &#34;planes&#34; || obj.type === &#34;clipplanes&#34;) {
ofs = [&#34;nx&#34;, &#34;ny&#34;, &#34;nz&#34;, &#34;offset&#34;].indexOf(attrib);
if (ofs &gt;= 0) {
if (ofs &lt; 3) {
if (obj.normals[vertex][ofs] != newval) {  // Assume no aliases here...
obj.normals[vertex][ofs] = newval;
obj.initialized = false;
}
} else {
if (obj.offsets[vertex][0] != newval) {
obj.offsets[vertex][0] = newval;
obj.initialized = false;
}
}
continue;
}
}
// Not a plane setting...
ofs = obj.vOffsets[ofss[attrib]];
if (ofs &lt; 0)
this.alertOnce(&#34;Attribute &#39;&#34;+attrib+&#34;&#39; not found in object &#34;+control.objid);
else {
stride = obj.vOffsets.stride;
ofs = ofs + pos[attrib];
entry = vertex*stride + ofs;
propvals[entry] = newval;
if (typeof alias !== &#34;undefined&#34;)
for (a = 0; a &lt; alias.length; a++)
propvals[alias[a]*stride + ofs] = newval;
}
}
if (typeof obj.buf !== &#34;undefined&#34;) {
var gl = this.gl || this.initGL();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, propvals, gl.STATIC_DRAW);
}
};
/**
* Change the requested vertex properties by age
* @param { Object } el - Element of the control; not used.
* @param { Object } control - The age setter control data.
*/
rglwidgetClass.prototype.ageSetter = function(el, control) {
var objids = [].concat(control.objids),
nobjs = objids.length,
time = control.value,
births = [].concat(control.births),
ages = [].concat(control.ages),
steps = births.length,
j = Array(steps),
p = Array(steps),
i, k, age, j0, propvals, stride, ofs, objid, obj,
attrib, dim, varies, alias, aliases, a, d,
attribs = [&#34;colors&#34;, &#34;alpha&#34;, &#34;radii&#34;, &#34;vertices&#34;,
&#34;normals&#34;, &#34;origins&#34;, &#34;texcoords&#34;,
&#34;x&#34;, &#34;y&#34;, &#34;z&#34;,
&#34;red&#34;, &#34;green&#34;, &#34;blue&#34;],
ofss    = [&#34;cofs&#34;, &#34;cofs&#34;, &#34;radofs&#34;, &#34;vofs&#34;,
&#34;nofs&#34;, &#34;oofs&#34;, &#34;tofs&#34;,
&#34;vofs&#34;, &#34;vofs&#34;, &#34;vofs&#34;,
&#34;cofs&#34;, &#34;cofs&#34;, &#34;cofs&#34;],
dims    = [3,1,1,3,
3,2,2,
1,1,1,
1,1,1],
pos     = [0,3,0,0,
0,0,0,
0,1,2,
0,1,2];
/* Infinity doesn&#39;t make it through JSON */
ages[0] = -Infinity;
ages[ages.length-1] = Infinity;
for (i = 0; i &lt; steps; i++) {
if (births[i] !== null) {  // NA in R becomes null
age = time - births[i];
for (j0 = 1; age &gt; ages[j0]; j0++);
if (ages[j0] == Infinity)
p[i] = 1;
else if (ages[j0] &gt; ages[j0-1])
p[i] = (ages[j0] - age)/(ages[j0] - ages[j0-1]);
else
p[i] = 0;
j[i] = j0;
}
}
// First, make sure color attributes vary in original
for (l = 0; l &lt; nobjs; l++) {
objid = objids[l];
obj = this.getObj(objid);
varies = true;
if (typeof obj.vOffsets === &#34;undefined&#34;)
continue;
for (k = 0; k &lt; attribs.length; k++) {
attrib = control[attribs[k]];
if (typeof attrib !== &#34;undefined&#34;) {
ofs = obj.vOffsets[ofss[k]];
if (ofs &lt; 0) {
switch(attribs[k]) {
case &#34;colors&#34;:
case &#34;alpha&#34;:
case &#34;red&#34;:
case &#34;green&#34;:
case &#34;blue&#34;:
obj.colors = [obj.colors[0], obj.colors[0]];
break;
}
varies = false;
}
}
}
if (!varies)
this.initObj(objid);
}
for (l = 0; l &lt; nobjs; l++) {
objid = objids[l];
obj = this.getObj(objid);
if (typeof obj.vOffsets === &#34;undefined&#34;)
continue;
aliases = obj.alias;
if (typeof aliases === &#34;undefined&#34;)
aliases = [];
propvals = obj.values;
stride = obj.vOffsets.stride;
for (k = 0; k &lt; attribs.length; k++) {
attrib = control[attribs[k]];
if (typeof attrib !== &#34;undefined&#34;) {
ofs = obj.vOffsets[ofss[k]];
if (ofs &gt;= 0) {
dim = dims[k];
ofs = ofs + pos[k];
for (i = 0; i &lt; steps; i++) {
alias = aliases[i];
if (births[i] !== null) {
for (d=0; d &lt; dim; d++) {
propvals[i*stride + ofs + d] = p[i]*attrib[dim*(j[i]-1) + d] + (1-p[i])*attrib[dim*j[i] + d];
if (typeof alias !== &#34;undefined&#34;)
for (a=0; a &lt; alias.length; a++)
propvals[alias[a]*stride + ofs + d] = propvals[i*stride + ofs + d];
}
}
}
} else
this.alertOnce(&#34;\&#39;&#34;+attribs[k]+&#34;\&#39; property not found in object &#34;+objid);
}
}
obj.values = propvals;
if (typeof obj.buf !== &#34;undefined&#34;) {
gl = this.gl || this.initGL();
gl.bindBuffer(gl.ARRAY_BUFFER, obj.buf);
gl.bufferData(gl.ARRAY_BUFFER, obj.values, gl.STATIC_DRAW);
}
}
};
/**
* Bridge to old style control
* @param { Object } el - Element of the control; not used.
* @param { Object } control - The bridge control data.
*/
rglwidgetClass.prototype.oldBridge = function(el, control) {
var attrname, global = window[control.prefix + &#34;rgl&#34;];
if (global)
for (attrname in global)
this[attrname] = global[attrname];
window[control.prefix + &#34;rgl&#34;] = this;
};
/**
* Set up a player control
* @param { Object } el - The player control element
* @param { Object } control - The player data.
*/
rglwidgetClass.prototype.Player = function(el, control) {
var
self = this,
components = [].concat(control.components),
buttonLabels = [].concat(control.buttonLabels),
Tick = function() { /* &#34;this&#34; will be a timer */
var i,
nominal = this.value,
slider = this.Slider,
labels = this.outputLabels,
output = this.Output,
step;
if (typeof slider !== &#34;undefined&#34; &amp;&amp; nominal != slider.value)
slider.value = nominal;
if (typeof output !== &#34;undefined&#34;) {
step = Math.round((nominal - output.sliderMin)/output.sliderStep);
if (labels !== null) {
output.innerHTML = labels[step];
} else {
step = step*output.sliderStep + output.sliderMin;
output.innerHTML = step.toPrecision(output.outputPrecision);
}
}
for (i=0; i &lt; this.actions.length; i++) {
this.actions[i].value = nominal;
}
self.applyControls(el, this.actions, false);
self.drawScene();
},
OnSliderInput = function() { /* &#34;this&#34; will be the slider */
this.rgltimer.value = Number(this.value);
this.rgltimer.Tick();
},
addSlider = function(min, max, step, value) {
var slider = document.createElement(&#34;input&#34;);
slider.type = &#34;range&#34;;
slider.min = min;
slider.max = max;
slider.step = step;
slider.value = value;
slider.oninput = OnSliderInput;
slider.sliderActions = control.actions;
slider.sliderScene = this;
slider.className = &#34;rgl-slider&#34;;
slider.id = el.id + &#34;-slider&#34;;
el.rgltimer.Slider = slider;
slider.rgltimer = el.rgltimer;
el.appendChild(slider);
},
addLabel = function(labels, min, step, precision) {
var output = document.createElement(&#34;output&#34;);
output.sliderMin = min;
output.sliderStep = step;
output.outputPrecision = precision;
output.className = &#34;rgl-label&#34;;
output.id = el.id + &#34;-label&#34;;
el.rgltimer.Output = output;
el.rgltimer.outputLabels = labels;
el.appendChild(output);
},
addButton = function(which, label, active) {
var button = document.createElement(&#34;input&#34;),
onclicks = {Reverse: function() { this.rgltimer.reverse();},
Play: function() { this.rgltimer.play();
this.value = this.rgltimer.enabled ? this.inactiveValue : this.activeValue; },
Slower: function() { this.rgltimer.slower(); },
Faster: function() { this.rgltimer.faster(); },
Reset: function() { this.rgltimer.reset(); },
Step:  function() { this.rgltimer.step(); }
};
button.rgltimer = el.rgltimer;
button.type = &#34;button&#34;;
button.value = label;
button.activeValue = label;
button.inactiveValue = active;
if (which === &#34;Play&#34;)
button.rgltimer.PlayButton = button;
button.onclick = onclicks[which];
button.className = &#34;rgl-button&#34;;
button.id = el.id + &#34;-&#34; + which;
el.appendChild(button);
};
if (typeof control.reinit !== &#34;undefined&#34; &amp;&amp; control.reinit !== null) {
control.actions.reinit = control.reinit;
}
el.rgltimer = new rgltimerClass(Tick, control.start, control.interval, control.stop,
control.step, control.value, control.rate, control.loop, control.actions);
for (var i=0; i &lt; components.length; i++) {
switch(components[i]) {
case &#34;Slider&#34;: addSlider(control.start, control.stop,
control.step, control.value);
break;
case &#34;Label&#34;: addLabel(control.labels, control.start,
control.step, control.precision);
break;
default:
addButton(components[i], buttonLabels[i], control.pause);
}
}
el.rgltimer.Tick();
};
/**
* Apply all registered controls
* @param { Object } el - DOM element of the control
* @param { Object } x - List of actions to apply
* @param { boolean } [draw=true] - Whether to redraw after applying
*/
rglwidgetClass.prototype.applyControls = function(el, x, draw) {
var self = this, reinit = x.reinit, i, control, type;
for (i = 0; i &lt; x.length; i++) {
control = x[i];
type = control.type;
self[type](el, control);
}
if (typeof reinit !== &#34;undefined&#34; &amp;&amp; reinit !== null) {
reinit = [].concat(reinit);
for (i = 0; i &lt; reinit.length; i++)
self.getObj(reinit[i]).initialized = false;
}
if (typeof draw === &#34;undefined&#34; || draw)
self.drawScene();
};
/**
* Handler for scene change
* @param { Object } message - What sort of scene change to do?
*/
rglwidgetClass.prototype.sceneChangeHandler = function(message) {
var self = document.getElementById(message.elementId).rglinstance,
objs = message.objects, mat = message.material,
root = message.rootSubscene,
initSubs = message.initSubscenes,
redraw = message.redrawScene,
skipRedraw = message.skipRedraw,
deletes, subs, allsubs = [], i,j;
if (typeof message.delete !== &#34;undefined&#34;) {
deletes = [].concat(message.delete);
if (typeof message.delfromSubscenes !== &#34;undefined&#34;)
subs = [].concat(message.delfromSubscenes);
else
subs = [];
for (i = 0; i &lt; deletes.length; i++) {
for (j = 0; j &lt; subs.length; j++) {
self.delFromSubscene(deletes[i], subs[j]);
}
delete self.scene.objects[deletes[i]];
}
}
if (typeof objs !== &#34;undefined&#34;) {
Object.keys(objs).forEach(function(key){
key = parseInt(key, 10);
self.scene.objects[key] = objs[key];
self.initObj(key);
var obj = self.getObj(key),
subs = [].concat(obj.inSubscenes), k;
allsubs = allsubs.concat(subs);
for (k = 0; k &lt; subs.length; k++)
self.addToSubscene(key, subs[k]);
});
}
if (typeof mat !== &#34;undefined&#34;) {
self.scene.material = mat;
}
if (typeof root !== &#34;undefined&#34;) {
self.scene.rootSubscene = root;
}
if (typeof initSubs !== &#34;undefined&#34;)
allsubs = allsubs.concat(initSubs);
allsubs = self.unique(allsubs);
for (i = 0; i &lt; allsubs.length; i++) {
self.initSubscene(allsubs[i]);
}
if (typeof skipRedraw !== &#34;undefined&#34;) {
root = self.getObj(self.scene.rootSubscene);
root.par3d.skipRedraw = skipRedraw;
}
if (redraw)
self.drawScene();
};
/**
* Set mouse mode for a subscene
* @param { string } mode - name of mode
* @param { number } button - button number (1 to 3)
* @param { number } subscene - subscene id number
* @param { number } stayActive - if truthy, don&#39;t clear brush
*/
rglwidgetClass.prototype.setMouseMode = function(mode, button, subscene, stayActive) {
var sub = this.getObj(subscene),
which = [&#34;left&#34;, &#34;right&#34;, &#34;middle&#34;][button - 1];
if (!stayActive &amp;&amp; sub.par3d.mouseMode[which] === &#34;selecting&#34;)
this.clearBrush(null);
sub.par3d.mouseMode[which] = mode;
};
/**
* The class of an rgl timer object
* @class
*/
/**
* Construct an rgltimerClass object
* @constructor
* @param { function } Tick - action when timer fires
* @param { number } startTime - nominal start time in seconds
* @param { number } interval - seconds between updates
* @param { number } stopTime - nominal stop time in seconds
* @param { number } stepSize - nominal step size
* @param { number } value - current nominal time
* @param { number } rate - nominal units per second
* @param { string } loop - &#34;none&#34;, &#34;cycle&#34; or &#34;oscillate&#34;
* @param { Object } actions - list of actions
*/
rgltimerClass = function(Tick, startTime, interval, stopTime, stepSize, value, rate, loop, actions) {
this.enabled = false;
this.timerId = 0;
/** nominal start time in seconds */
this.startTime = startTime;   
/** current nominal time */      
this.value = value;
/** seconds between updates */                 
this.interval = interval;
/** nominal stop time */           
this.stopTime = stopTime;
/** nominal step size */           
this.stepSize = stepSize;
/** nominal units per second */           
this.rate = rate;
/** &#34;none&#34;, &#34;cycle&#34;, or &#34;oscillate&#34; */                   
this.loop = loop;
/** real world start time */                   
this.realStart = undefined;
/** multiplier for fast-forward or reverse */         
this.multiplier = 1;                
this.actions = actions;
this.Tick = Tick;
};
/**
* Start playing timer object
*/
rgltimerClass.prototype.play = function() {
if (this.enabled) {
this.enabled = false;
window.clearInterval(this.timerId);
this.timerId = 0;
return;
}
var tick = function(self) {
var now = new Date();
self.value = self.multiplier*self.rate*(now - self.realStart)/1000 + self.startTime;
self.forceToRange();
if (typeof self.Tick !== &#34;undefined&#34;) {
self.Tick(self.value);
}
};
this.realStart = new Date() - 1000*(this.value - this.startTime)/this.rate/this.multiplier;
this.timerId = window.setInterval(tick, 1000*this.interval, this);
this.enabled = true;
};
/**
* Force value into legal range
*/
rgltimerClass.prototype.forceToRange = function() {
if (this.value &gt; this.stopTime + this.stepSize/2 || this.value &lt; this.startTime - this.stepSize/2) {
if (!this.loop) {
this.reset();
} else {
var cycle = this.stopTime - this.startTime + this.stepSize,
newval = (this.value - this.startTime) % cycle + this.startTime;
if (newval &lt; this.startTime) {
newval += cycle;
}
this.realStart += (this.value - newval)*1000/this.multiplier/this.rate;
this.value = newval;
}
}
};
/**
* Reset to start values
*/
rgltimerClass.prototype.reset = function() {
this.value = this.startTime;
this.newmultiplier(1);
if (typeof this.Tick !== &#34;undefined&#34;) {
this.Tick(this.value);
}
if (this.enabled)
this.play();  /* really pause... */
if (typeof this.PlayButton !== &#34;undefined&#34;)
this.PlayButton.value = &#34;Play&#34;;
};
/**
* Increase the multiplier to play faster
*/
rgltimerClass.prototype.faster = function() {
this.newmultiplier(Math.SQRT2*this.multiplier);
};
/**
* Decrease the multiplier to play slower
*/
rgltimerClass.prototype.slower = function() {
this.newmultiplier(this.multiplier/Math.SQRT2);
};
/**
* Change sign of multiplier to reverse direction
*/
rgltimerClass.prototype.reverse = function() {
this.newmultiplier(-this.multiplier);
};
/**
* Set multiplier for play speed
* @param { number } newmult - new value
*/
rgltimerClass.prototype.newmultiplier = function(newmult) {
if (newmult != this.multiplier) {
this.realStart += 1000*(this.value - this.startTime)/this.rate*(1/this.multiplier - 1/newmult);
this.multiplier = newmult;
}
};
/**
* Take one step
*/
rgltimerClass.prototype.step = function() {
this.value += this.rate*this.multiplier;
this.forceToRange();
if (typeof this.Tick !== &#34;undefined&#34;)
this.Tick(this.value);
};&lt;/script&gt;
&lt;div id=&#34;unnamed_chunk_2div&#34; class=&#34;rglWebGL&#34;&gt;

&lt;/div&gt;
&lt;script type=&#34;text/javascript&#34;&gt;
var unnamed_chunk_2div = document.getElementById(&#34;unnamed_chunk_2div&#34;),
unnamed_chunk_2rgl = new rglwidgetClass();
unnamed_chunk_2div.width = 769;
unnamed_chunk_2div.height = 481;
unnamed_chunk_2rgl.initialize(unnamed_chunk_2div,
{&#34;material&#34;:{&#34;color&#34;:&#34;#000000&#34;,&#34;alpha&#34;:1,&#34;lit&#34;:true,&#34;ambient&#34;:&#34;#000000&#34;,&#34;specular&#34;:&#34;#FFFFFF&#34;,&#34;emission&#34;:&#34;#000000&#34;,&#34;shininess&#34;:50,&#34;smooth&#34;:true,&#34;front&#34;:&#34;filled&#34;,&#34;back&#34;:&#34;filled&#34;,&#34;size&#34;:3,&#34;lwd&#34;:1,&#34;fog&#34;:false,&#34;point_antialias&#34;:false,&#34;line_antialias&#34;:false,&#34;texture&#34;:null,&#34;textype&#34;:&#34;rgb&#34;,&#34;texmipmap&#34;:false,&#34;texminfilter&#34;:&#34;linear&#34;,&#34;texmagfilter&#34;:&#34;linear&#34;,&#34;texenvmap&#34;:false,&#34;depth_mask&#34;:true,&#34;depth_test&#34;:&#34;less&#34;,&#34;isTransparent&#34;:false,&#34;polygon_offset&#34;:[0,0]},&#34;rootSubscene&#34;:6,&#34;objects&#34;:{&#34;12&#34;:{&#34;id&#34;:12,&#34;type&#34;:&#34;quads&#34;,&#34;material&#34;:{},&#34;vertices&#34;:[[-1,-1,-1],[-1,1,-1],[1,1,-1],[1,-1,-1],[-1,1,-1],[-1,1,1],[1,1,1],[1,1,-1],[1,-1,-1],[1,1,-1],[1,1,1],[1,-1,1],[-1,-1,-1],[-1,-1,1],[-1,1,1],[-1,1,-1],[-1,-1,-1],[1,-1,-1],[1,-1,1],[-1,-1,1],[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1]],&#34;colors&#34;:[[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,0,0,1],[1,0,0,1],[1,0,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1],[1,1,0,1]],&#34;centers&#34;:[[0,0,-1],[0,1,0],[1,0,0],[-1,0,0],[0,-1,0],[0,0,1]],&#34;normals&#34;:[[0,0,-1],[0,0,-1],[0,0,-1],[0,0,-1],[-0,1,0],[-0,1,0],[-0,1,0],[-0,1,0],[1,0,-0],[1,0,-0],[1,0,-0],[1,0,-0],[-1,0,0],[-1,0,0],[-1,0,0],[-1,0,0],[0,-1,0],[0,-1,0],[0,-1,0],[0,-1,0],[0,-0,1],[0,-0,1],[0,-0,1],[0,-0,1]],&#34;ignoreExtent&#34;:false,&#34;flags&#34;:3},&#34;10&#34;:{&#34;id&#34;:10,&#34;type&#34;:&#34;light&#34;,&#34;vertices&#34;:[[0,0,1]],&#34;colors&#34;:[[1,1,1,1],[1,1,1,1],[1,1,1,1]],&#34;viewpoint&#34;:true,&#34;finite&#34;:false},&#34;9&#34;:{&#34;id&#34;:9,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;fog&#34;:true},&#34;colors&#34;:[[0.2980392,0.2980392,0.2980392,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;11&#34;:{&#34;id&#34;:11,&#34;type&#34;:&#34;background&#34;,&#34;material&#34;:{&#34;lit&#34;:false,&#34;back&#34;:&#34;lines&#34;},&#34;colors&#34;:[[1,1,1,1]],&#34;centers&#34;:[[0,0,0]],&#34;sphere&#34;:false,&#34;fogtype&#34;:&#34;none&#34;,&#34;flags&#34;:0},&#34;6&#34;:{&#34;id&#34;:6,&#34;type&#34;:&#34;subscene&#34;,&#34;par3d&#34;:{&#34;antialias&#34;:8,&#34;FOV&#34;:30,&#34;ignoreExtent&#34;:false,&#34;listeners&#34;:6,&#34;mouseMode&#34;:{&#34;left&#34;:&#34;trackball&#34;,&#34;right&#34;:&#34;zoom&#34;,&#34;middle&#34;:&#34;fov&#34;,&#34;wheel&#34;:&#34;pull&#34;},&#34;observer&#34;:[0,0,6.692131],&#34;modelMatrix&#34;:[[1,0,0,0],[0,0.3420202,0.9396926,0],[0,-0.9396926,0.3420202,-6.692131],[0,0,0,1]],&#34;projMatrix&#34;:[[2.332532,0,0,0],[0,3.732051,0,0],[0,0,-3.863703,-24.12436],[0,0,-1,0]],&#34;skipRedraw&#34;:false,&#34;userMatrix&#34;:[[1,0,0,0],[0,0.3420201,0.9396926,0],[0,-0.9396926,0.3420201,0],[0,0,0,1]],&#34;userProjection&#34;:[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],&#34;scale&#34;:[1,1,1],&#34;viewport&#34;:{&#34;x&#34;:0,&#34;y&#34;:0,&#34;width&#34;:1,&#34;height&#34;:1},&#34;zoom&#34;:1,&#34;bbox&#34;:[-1,1,-1,1,-1,1],&#34;windowRect&#34;:[0,45,768,525],&#34;family&#34;:&#34;sans&#34;,&#34;font&#34;:1,&#34;cex&#34;:1,&#34;useFreeType&#34;:true,&#34;fontname&#34;:&#34;/Library/Frameworks/R.framework/Versions/4.0/Resources/library/rgl/fonts/FreeSans.ttf&#34;,&#34;maxClipPlanes&#34;:6,&#34;glVersion&#34;:2.1,&#34;activeSubscene&#34;:0},&#34;embeddings&#34;:{&#34;viewport&#34;:&#34;replace&#34;,&#34;projection&#34;:&#34;replace&#34;,&#34;model&#34;:&#34;replace&#34;,&#34;mouse&#34;:&#34;replace&#34;},&#34;objects&#34;:[11,12,10],&#34;subscenes&#34;:[],&#34;flags&#34;:515}},&#34;snapshot&#34;:&#34;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwAAAAHgCAIAAACdOJ1yAAAAHXRFWHRTb2Z0d2FyZQBSL1JHTCBwYWNrYWdlL2xpYnBuZ7GveO8AABmYSURBVHic7d35t+13fddxuPM83xtnEUqFUiBQp9aplDEYCNpWnEsEwpBQW7XV4tAESCgJDh2IWoUMhRCIBZQiVC25IYkNNm2BiAmdkps2ZY65555xT9fPVpesZJ17z9n73Oz35/39PB7r+QfwA593Xmvd71n7CacBABrzhOj/AQAAs2YAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAAQDNMYAAgOYYQABAcwwgAKA5BhAA0BwDCABojgEEADTHAAIAmmMAwTfccsvlUoeLfmFQEQMI/p8rrvjOV77yCVKHu/baV0W/M6iFAQRjn//8reH/cZJm0PHj10W/NqiCAQSnv/KV+8P/syTNpssue1L5P3z0m4N4BhD4xy+1VdlA0W8O4hlAtO6WWy4P/w+SNON8EA0GEE3z6Y/a7LLLnlT+zx/9/iCSAUTTyn8Gwv9TJIXkYyAaZwDRLp/+qPH8VTwtM4Bo1PHj14X/50cKz8dANMsAokU+/ZH+bz4GolkGEC3yj1/S/89fxdMmA4jmWD/SY/IxEA0ygGiLf/ySVs1PZNAaA4iG+MkL6Uz5q3haYwDREP/4JZ0lHwPRFAOIVvjJC2nN/FU87TCAaIJPf6T15K/iaYcBRBPC/7siZcnHQDTCAKL7fPojTVR5MtGvFh53BhAd59MfaYp8DETnGUB0mU9/pOnyMRCdZwDRZf7xS5o6fxVPtxlAdJb1I20wP5FBhxlAdJN//JLOSX4ig64ygOggP3khnav8VTxdZQDRQf7xSzqH+RiITjKA6Bp/9y6d83wMRPcYQHSKT3+kxyl/FU/HGEB0h09/pMcvHwPRMQYQ3eHTH+lxzU9k0CUGEB3h0x9pBvmJDDrDAKILfPojzSY/kUFnGEB0QTnK4f9hkBrJX8XTDQYQ6fn0R5px/iqeDjCAyM0/fkkh+RiI7AwgEvN371JU/iqe7AwgEvOPX1JgPgYiNQOIrPzduxSej4HIywAiJZ/+SJXkr+JJygAiH5/+SPXkYyCSMoDIx6c/UlX5iQwyMoBIxqc/UoX5q3jSMYDIxKc/Up35iQzSMYDIxE9eSNXmr+LJxQAiDZ/+SJXnr+JJxAAih+PHrws/7pLWzMdAZGEAkYC/e5ey5GMgsjCASMA/fkmJ8jEQKRhA1O7aa18VftAlTZSPgaifAUTV/N27lLTjx6+Lvh9wNgYQ9fLpj5Q3P5FB5Qwg6uXTHyl1PgaiZgYQlfKTF1IH8lfxVMsAokY+/ZG6kb+Kp1oGEDXykxdSZ/IPYdTJAKI6Pv2ROpa/iqdCBhB18ZMXUifzMRC1MYCoiE9/pK7mYyBqYwBRlWtOnz5PUke7JvrCwDcYQNRkdM3p0XmSOpoBREUMIGoyuvn08DxJ3aw8cKiGAURNRneeHpwnqZsZQNTEAKImBpDU4coDh2oYQNSk3Mf+eZK62ejB6BMD32AAUZNyH3vnSepmBhA1MYCoSbmPK8ckdTMDiJoYQFRm+ZikbgY1MYCoTPiNlvQ4BTUxgKjM8redXjomqWuVpw01MYCoy2j5FaPFY5K61vIroq8LPIoBRF1GS68YLRyT1LWWDCDqYgBRl/EAmj8mqWstvyn6usCjGEDUpVzJ+Est6ZxnAFEZA4i6jFauHp06JqlrLRlA1MUAoi6j5atHc8ckda3lq6OvCzyKAURlejePTh6T1LHK044+LvAoBhCVWbl59MgxSR2rPO3o4wKPYgBRmf6d4Zda0jnPAKI2BhCVKQPofx2T1LHK044+LvAoBhCVGT44eviopI5Vnnb0cYFHMYCoTBlAXz8qqWMZQNTGAKIyZQB97aikjhV9WeCxDCCqE36pJZ3zou8KPJYBRHVGX3/u6KtHJXWnrz83+q7AYxlAVGc8gL5yVFJ3MoCojwFEdUYPXzT68lFJ3enhi6LvCjyWAUR1xgPoS0cldaeTfgmV6hhAVKfcyvh7LekcZgBRHwOI6oweedPoi0cldadHDCCqYwBRndHc1aPfPSqpO81dHX1X4LEMIKozHkAPHZXUnQwg6mMAUZ3RwvuHv3NUUmcqjzr6rsBjGUBUZ7R8R/i9lnQOM4CokAFEdcYD6LePSupM5VFH3xV4LAOI6owH0INHJHWm030/BU91DCDq039weOKIpM5kAFEhA4j6lAH0wBFJnckAokIGEDUKv9eSzmHRFwVWYQBRo+H9RyR1puiLAqswgKjR8MHnDH/riKQu9OBzoi8KrMIAokbDhy4a/uYRSV3ooYuiLwqswgCiRuMB9BtHJHUhA4gqGUDUyACSOtPoy5dFXxRYhQFEjUZfumz460ckdaDynKMvCqzCAKJGo6+9Y/hrRyR1oPKcoy8KrMIAokbjAfSFI5I6kAFEnQwgajR65P3D+45I6kDlOUdfFFiFAUSNxgPo3iOSOpABRJ0MIGo0WrhjeO9hSR2oPOfoiwKrMICo0XgA/c/DkjqQAUSdDCCq1Dsx/PxhSR2oPOfogwKrMICoUhlA/+OwpA5kAFEnA4hKDe85LKkDRd8SWJ0BRKUG9xyW1IGibwmszgCiUoP7zh987rCk3N13fvQtgdUZQFRqcO/5g88elpS7ew0gKmUAUanhb7x88JnDklJXHnL0LYHVGUBUavjrLx/86mFJqRueuDT6lsDqDCAqNXzg0sGvHJaUuvKQo28JrM4AolIGkNSBDCCqZQBRqeHvvmPwy4clpa485OhbAqszgKjU8KF3DO4+LCl1o6/dFH1LYHUGEJUaffWmwS8dkpS68pCjbwmszgCiUqO5Owb//ZCk1BlAVMsAolKjk3cMPn1IUurKQ46+JbA6A4haLZ8Iv92SNlh5yNGnBFZnAFGrMoDuOiQpdQYQ1TKAqFUZQL94SFLqDCCqZQBRr8F/OyQpddFXBM7IAKJeg7vPH9x5SFLeoq8InJEBRL0MICl3d58ffUXgjAwg6jW852WDOw5JSlp5wtFXBM7IAKJew8+9bHD7IUlJK084+orAGRlA1Gv42ZcNPnVIUtKGX/BT8NTLAKJew/suHdx2SFLSyhOOviJwRgYQ9Rre/2P944ckJa084egrAmdkAFGv/zOADkpKmgFEzQwg6jX84k39Ww9KSlp5wtFXBM7IAKJe4wH0yYOSkmYAUTMDiHqNHr69/wsHJSWtPOHoKwJnZABRr/EA+q8HJSXNAKJmBhD1Gi2e6P+Xg5KSVp5w9BWBMzKAqNd4AP3ng5KSZgBRMwOIqoVfcElTF30/4GwMIKrW//mDkpIWfT/gbAwgqta/7dn9TxyUlK/bnh19P+BsDCCqNvj0hf2PH5SUr+MGEFUzgKja4K4L+//poKR0lccbfT/gbAwgqjb4xQv7HzsoKV2Dz74x+n7A2RhAVK3c0PA7LmmKDCAqZwBRteEX3t7/uQOS0jX4jAFE1QwgqjYeQB89ICld5fFG3w84GwOIqg3ve3v/Px6QlK7hg++Lvh9wNgYQVSs3tP8fDkhKlwFE5Qwgqjb66u39jxyQlK7hCQOIqhlAVM0AkpJWHm/0/YCzMYCo2mjhRO/DBySlqzze6PsBZ2MAUbXxAPrQAUnpMoConAFE1cYD6GcPSEpX9PGANRhA1K737w9ISlf05YA1GEDUrv+xZ/VuOSApV9GXA9ZgAFG78QD64AFJiSrPNvpywBoMIGrXv/XC8GsuaaLKs42+HLAGA4ja9T95Ye8DByQlqjzb6MsBazCAqN3g02/o3bxfUqLKs42+HLAGA4jaDe56Q+/9+yUlqjzb6MsBazCAqN3gc2/v3bRfUqLKs42+HLAGA4jajQfQ+/ZLSpQBRP0MIGo3/M339d67X1KiyrONvhywBgOI2hlAUroMIOpnAFG70Zdu7/3MfkmJKs82+nLAGgwgajceQDful5QoA4j6GUDUbnTqRO+G/ZISVZ5t9OWANRhA1G48gK7fLylRBhD1M4BIoHfdfkmJir4ZsDYDiAR679kvKVHRNwPWZgCRQP+Dzww/6JLWWXmw0TcD1mYAkUDvYy9defc+SSnqfeBbo28GrM0AIoHxAPp3+ySlqDzY6JsBazOASKD3cy9d+bf7JKWof/z10TcD1mYAkUC5pys/vU9SigwgUjCASGBw91Ur/2afpBT1bzWASMAAIoHBL1218q/3SUpRebDRNwPWZgCRgAEkJWp4n5+CJwEDiATKPV35V/skpcgAIgUDiASGD92+cu0+SSkygEjBACKB4e/cvvKufZJSVB5s9M2AtRlAJDCaO7HyU/skpag82OibAWszgEhgdPLEyk/uk5Si8mCjbwaszQAigfEA+ol9klIUfTBgXQwgclj58X2SUhR9LWBdDCBy6F33jJUf3yup/qKvBayLAUQOvfc8Y+Vf7pVUeeWpRl8LWBcDiBx6t1yw8i/2Sqq88lSjrwWsiwFEDr0PXrDyz/dKqrzyVKOvBayLAUQO/U+8fuWf7ZVUeeWpRl8LWBcDiBz6H3/9yjv3Sqq88lSjrwWsiwFEDv07r1q+Zq+kyitPNfpawLoYQOTQv+Oq5av3Sqq88lSjrwWsiwFEDoN73ht+2SWtWXmq0dcC1sUAIofhiU8tv2OvpMozgMjCACKH8QD6sb2SKq881ehrAetiAJHDeAC9fa+kyjOAyMIAIofRIyeWr9orqfLKU42+FrAuBhA5jAfQlXskVZ4BRBYGEGksv22PpMqLvhOwXgYQaSy/dY+kyou+E7BeBhBprPzEtyy/ZY+kaiuPNPpOwHoZQKTRu+GC8Psu6SwZQCRiAJFG7/oLlq/YI6nayiONvhOwXgYQaYwH0OV7JFVb/yOvi74TsF4GEGn0P/y65R/dI6nayiONvhOwXgYQafQ/eeXyP90jqdr6HzKASMMAIo3xAPoneyRVW3mk0XcC1ssAIo3+L1y5/I/3SKq2wa/4KXjSMIBIY/DL713+R3skVVt5pNF3AtbLACKN4W99avnNeyRVmwFEIgYQaZQBtPTm3ZKqrTzS6DsB62UAkcbo4QeWfmS3pGorjzT6TsB6GUCkMR5A/3C3pGozgEjEACKN8QD6B7slVVv0kYAJGEBksvTDuyVVW/SFgAkYQGSyfNXTl35ot6Q6i74QMAEDiEyWr3z60t/fLanCyvOMvhAwAQOITFaufcnS39stqcLK84y+EDABA4hMVt71kqW/u1tShZXnGX0hYAIGEJn03n9J+JWXtGrleUZfCJiAAUQmvZsuWfrB3ZIqrDzP6AsBEzCAyKT/8SuXfmC3pAorzzP6QsAEDCAyGQ+gv7NbUoUZQORiAJHJ4NM/s/T9uyRVWHme0RcCJmAAkcnw1z619KZdkipscJcBRCYGEJmMB9BluyRVWHme0RcCJmAAkcl4AF26S1KFjb7mp+DJxAAik3Jhl964S1KFGUDkYgCRyXgAvWGXpAozgMjFACKZ8CsvadWibwNMxgAimcXX75JUYdG3ASZjAJHM0pufvvi6XZKqqjzM6NsAkzGASGb5nS9evGSXpKoqDzP6NsBkDCCSWb7mxYuv3SWpqsrDjL4NMBkDiGTGA+g1uyRV1cp7/BQ8yRhAJLPy7ksWX71LUlWVhxl9G2AyBhDJ9D7ytsW/vVNSVa28+7XRtwEmYwCRzHgAXbxTUlWVhxl9G2AyBhDJ9D78tsVX7ZRUVYPb/RQ8yRhAJFPu7OL37ZRUVQYQ6RhAJDO897bFv7VTUlUZQKRjAJGMASRVWHmY0bcBJmMAkczoqw8s/s2dkqqqPMzo2wCTMYBIZjyA/sZOSVVlAJGOAUQyo688sPjXd0qqqujDABMzgMhn8a/tlFRV0VcBJmYAkc/S9z9t8a/ulFRP0VcBJmYAkc/Sm562+Fd2Sqqk8iSjrwJMzAAin+UrXrT4yp2SKqk8yeirABMzgMhn6fIXLfzlHZIqqTzJ6KsAEzOAyGflXa9d+N4dkiqpPMnoqwATM4DIZ+WnXrvwPTskVVJ5ktFXASZmAJFP7wNvXfjuHZIqqTzJ6KsAEzOAyMcAkqrKACIjA4h8+p+8ceEv7ZBUSeVJRl8FmJgBRD6De25b+Is7JFWSAURGBhD5jAfQK3ZIqqTyJKOvAkzMACKf8QC6aIekShp92U/Bk48BRD7l2i68fIekSjKAyMgAIp/xAHrZDkmVZACRkQFESgsX7pBUSdH3AKZhAJHSwl/YLqmSou8BTMMAIqXFi7954aXbJYVXHmP0PYBpGECktPTDL1y4YLuk8MpjjL4HMA0DiJTGA+gl2yWFZwCRlAFESks/9MKFF2+XFN7KO18TfQ9gGgYQKa1c85qFF22XFF55jNH3AKZhAJFS78a3ht99SQsGEGkZQKQ0HkAv3C4pvPIYo+8BTMMAIqX+z984/4LtksIrjzH6HsA0DCBS6n/ixvnnb5cUXnmM0fcApmEAkdLgM7fNf9d2SeEZQCRlAJHS4Fdvm3/edknhlccYfQ9gGgYQKY2++MD8d26TFF55jNH3AKZhAJHSeAD9+W2SwjOASMoAIqXxAPpz2ySFF30MYEoGEFnN/9ltksKLvgQwJQOIrBa+56nzf2abpMDKM4y+BDAlA4isFr77qfN/epukwMozjL4EMCUDiKyWLn3B/HdskxRYeYbRlwCmZACR1dIbXzD/7dskBbb81ldHXwKYkgFEVuXyzv+pbZICM4DIywAiq+W3vHr+T26TFFh5htGXAKZkAJHVyk+/Zf5PbJMUWHmG0ZcApmQAkdV4AP3xbZICM4DIywAiq/5Hbwy//lLjlWcYfQlgSgYQWQ3uPj7/x7ZKCqz/0RuiLwFMyQAiqzKATn3bVkmBlWcYfQlgSgYQWY0H0HO3Sgps+JCfgicrA4isyuU99ZytkgIzgMjLACKr8QA6f6ukwAwg8jKASOzUs7dKCiz6BsD0DCASO/WsrZICi74BMD0DiMTmX/xNp565VVJI5QFG3wCYngFEYosXP//Ut26VFFJ5gNE3AKZnAJHY4quef+oZWyWFVB5g9A2A6RlAJLb4fc8/9S1bJYW09GY/BU9iBhCJLf3Iq089faukkMoDjL4BMD0DiMRWfvKKU0/bIimk8gCjbwBMzwAisfEA+qNbJIVkAJGaAURivQ/dcOqbt0gKqTzA6BsA0zOASKz3szeceuoWSSGVBxh9A2B6BhCJDe46fuqbtkgKqTzA6BsA0zOASGw8gJ6yRVJIBhCpGUAkNvztB049eYukkMoDjL4BMD0DiMTGA+iPbJEUkgFEagYQuc09aYukkKJfP2yIAURuc394i6SQol8/bIgBRG7z3/GUuT+0RdKMK08v+vXDhhhA5Db/7U+Z+4NbJM248vSiXz9siAFEbgvf+11zf2CzpBlXnl7064cNMYDIzQCSQlr6wYujXz9siAFEbks/cPHc798sacaVpxf9+mFDDCByGw+g37dZ0owzgMjOACK35XdeMfd7N0uaceXpRb9+2BADiNyWr7li7vdsljTjejdfH/36YUMMIHIrV3juvM2SZpwBRHYGELkN7jw+d2yzpBlnAJGdAURugzuOzx3dLGnGlacX/fphQwwgchs+eP/ckc2SZlx5etGvHzbEACK34Yn75w5vljTjytOLfv2wIQYQuY0H0KHNkmacAUR2BhDpzR3cJGnGRb972CgDiPTmn/XkuQObJM2y6HcPG2UAkd6pZz755P5NkmZWeXTR7x42ygAivfmXPu/kvk2SZlZ5dNHvHjbKACK9+Qued3LvJkkzqzy66HcPG2UAkd54AO3ZJGlmLb7OT8GTngFEeouXXHxy9yZJM6s8uuh3DxtlAJHe8tsuP7lrk6SZVR5d9LuHjTKASG88gHZukjSzDCA6wAAivd6N15/csUnSzCqPLvrdw0YZQKQ3HkDbN0maWQYQHWAAkV7/tuMnt22SNLPKo4t+97BRBhDp9Y/fenLrEyXNrPLoot89bJQBRHrDB+4/ueWJkmZWeXTR7x42ygAiveH995/c/ERJM6s8uuh3DxtlANEFJzc9UdLMin7xcA4YQHRB7/rrJc2s6BcP54ABBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzTGAAIDmGEAAQHMMIACgOQYQANAcAwgAaI4BBAA0xwACAJpjAAEAzfnfuXDxlIRxPfgAAAAASUVORK5CYII=&#34;,&#34;width&#34;:769,&#34;height&#34;:481,&#34;sphereVerts&#34;:{&#34;vb&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1950903,-0.3826834,-0.5555702,-0.7071068,-0.8314696,-0.9238795,-0.9807853,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1],[0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1950903,-0.3826834,-0.5555702,-0.7071068,-0.8314696,-0.9238795,-0.9807853,-1,-0.9807853,-0.9238795,-0.8314696,-0.7071068,-0.5555702,-0.3826834,-0.1950903,-0,-0,-0.18024,-0.3535534,-0.51328,-0.6532815,-0.7681778,-0.8535534,-0.9061274,-0.9238795,-0.9061274,-0.8535534,-0.7681778,-0.6532815,-0.51328,-0.3535534,-0.18024,-0,-0,-0.1379497,-0.2705981,-0.3928475,-0.5,-0.5879378,-0.6532815,-0.6935199,-0.7071068,-0.6935199,-0.6532815,-0.5879378,-0.5,-0.3928475,-0.2705981,-0.1379497,-0,-0,-0.07465783,-0.1464466,-0.2126075,-0.2705981,-0.3181896,-0.3535534,-0.3753303,-0.3826834,-0.3753303,-0.3535534,-0.3181896,-0.2705981,-0.2126075,-0.1464466,-0.07465783,-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.07465783,0.1464466,0.2126075,0.2705981,0.3181896,0.3535534,0.3753303,0.3826834,0.3753303,0.3535534,0.3181896,0.2705981,0.2126075,0.1464466,0.07465783,0,0,0.1379497,0.2705981,0.3928475,0.5,0.5879378,0.6532815,0.6935199,0.7071068,0.6935199,0.6532815,0.5879378,0.5,0.3928475,0.2705981,0.1379497,0,0,0.18024,0.3535534,0.51328,0.6532815,0.7681778,0.8535534,0.9061274,0.9238795,0.9061274,0.8535534,0.7681778,0.6532815,0.51328,0.3535534,0.18024,0,0,0.1950903,0.3826834,0.5555702,0.7071068,0.8314696,0.9238795,0.9807853,1,0.9807853,0.9238795,0.8314696,0.7071068,0.5555702,0.3826834,0.1950903,0]],&#34;it&#34;:[[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270],[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271]],&#34;material&#34;:[],&#34;normals&#34;:null,&#34;texcoords&#34;:[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.1875,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.3125,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.4375,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.5625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.625,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.6875,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.75,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.8125,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.875,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,0.9375,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1,0,0.0625,0.125,0.1875,0.25,0.3125,0.375,0.4375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,1]],&#34;meshColor&#34;:&#34;vertices&#34;},&#34;context&#34;:{&#34;shiny&#34;:false,&#34;rmarkdown&#34;:null},&#34;crosstalk&#34;:{&#34;key&#34;:[],&#34;group&#34;:[],&#34;id&#34;:[],&#34;options&#34;:[]}});
unnamed_chunk_2rgl.prefix = &#34;unnamed_chunk_2&#34;;
&lt;/script&gt;
&lt;p id=&#34;unnamed_chunk_2debug&#34;&gt;
You must enable Javascript to view this page properly.
&lt;/p&gt;
&lt;script&gt;unnamed_chunk_2rgl.start();&lt;/script&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;insitu&#39; - functions for in-place modification</title>
      <link>https://coolbutuseless.github.io/2020/09/03/introducing-insitu-functions-for-in-place-modification/</link>
      <pubDate>Thu, 03 Sep 2020 07:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/09/03/introducing-insitu-functions-for-in-place-modification/</guid>
      <description>


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;insitu&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;insitu&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://www.tidyverse.org/lifecycle/#experimental&#34;&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-experimental-orange.svg&#34; alt=&#34;Lifecycle: experimental&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;insitu&lt;/code&gt; provides some functions for modifying vectors &lt;em&gt;in-situ&lt;/em&gt; (in place)
without allocating a new vector.&lt;/p&gt;
&lt;p&gt;This is an experimental package I wrote to try and figure out just how fast things
could be in R.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Modifying vectors in-situ can be fast, but doing so violates some very strong norms
within R internals.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Unless you are very confident on who has references to your data,
do not use this package for in-place modification.&lt;/p&gt;
&lt;div id=&#34;modifying-vectors-in-place&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Modifying vectors in-place&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt; of modifying in-situ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Often faster as there is reduced memory allocation (and also reduced pressure
on the garbage collector)&lt;/li&gt;
&lt;li&gt;Often faster as there is no copying from the original vector into a new vector&lt;/li&gt;
&lt;li&gt;By using C, we can override the &lt;em&gt;copy-on-modify&lt;/em&gt; semantics usually used in R
(regardless of how many references exist to the given object)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt; of modifying in-situ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Normal R &lt;em&gt;copy-on-modify&lt;/em&gt; behaviour is not followed - this will be a point of
confusion as essentially everything in R uses &lt;em&gt;copy-on-modify&lt;/em&gt; and not
modification in-place.&lt;/li&gt;
&lt;li&gt;Copying and allocating vectors is already very fast. It only takes a
few &lt;em&gt;microseconds&lt;/em&gt; to allocate memory for a vector of 1000 elements and assign new values into
it. The speed saved by switching to in-situ modification will only possibly
be useful if this operations is performed many, many times.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the words of Luke Tierney in his User2020 keynote:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;You should never modify something without duplicating it.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This package ignores this advice. Beware.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;29%&#34; /&gt;
&lt;col width=&#34;51%&#34; /&gt;
&lt;col width=&#34;6%&#34; /&gt;
&lt;col width=&#34;4%&#34; /&gt;
&lt;col width=&#34;7%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;insitu&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;th&gt;integer&lt;/th&gt;
&lt;th&gt;real&lt;/th&gt;
&lt;th&gt;character&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;insitu_fill(x, value)&lt;/td&gt;
&lt;td&gt;Fill vector with the given value&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;insitu_fill_runif(x, lower, upper)&lt;/td&gt;
&lt;td&gt;Fill vector with uniform random numbers&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;insitu_fill_runif_fast(x, lower, upper)&lt;/td&gt;
&lt;td&gt;Fill vector with uniform random numbers&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;insitu_replace(x, pos, values)&lt;/td&gt;
&lt;td&gt;Replace values in x with given values starting from the given position&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td&gt;Reverse vector&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td&gt;Shuffle the elements of a vector&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td&gt;Shuffle the elements of a vector&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;insitu_sort(x)&lt;/td&gt;
&lt;td&gt;Sort the elements of a vector&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;fast-variants&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Fast Variants&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;_fast&lt;/code&gt; versions of some functions use their own random-number generator
rather than the one supplied in R. This generator is &lt;a href=&#34;https://lemire.me/blog/2019/03/19/the-fastest-conventional-random-number-generator-that-can-pass-big-crush/&#34;&gt;lehmer64&lt;/a&gt;.
It is very fast, but has different properties from R’s built in random
number generator. Use with caution.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;altrep-utils&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;ALTREP utils&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;is_altrep(x)&lt;/code&gt; tests whether an object is an ALTREP&lt;/li&gt;
&lt;li&gt;&lt;code&gt;is_mutable(x)&lt;/code&gt; tests whether an object is mutable in-place by checking its
reference count&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_refcnt(x)&lt;/code&gt; returns the reference count for the object&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/insitu&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/insitu&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In-place radix sort - instead of using &lt;code&gt;qsort()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cummin&lt;/code&gt;, &lt;code&gt;cummax&lt;/code&gt; etc&lt;/li&gt;
&lt;li&gt;&lt;code&gt;negate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-replacement&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ Replacement&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_replace()&lt;/code&gt; is analogous to &lt;code&gt;replace()&lt;/code&gt; but replaces values in the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- integer(10)
insitu_replace(x, 6, 1:5)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 0 0 0 0 0 1 2 3 4 5&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)
    x[1] &amp;lt;- x[1]
    idx &amp;lt;- seq(1, N/2)
    ins &amp;lt;- as.numeric(idx)
    
    bench::mark(
      replace(x, idx, ins),
      insitu_replace(x, 1, ins),
      check    = TRUE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.160156&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.106230&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.118310&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.797336&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.029647&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.446429&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.281246&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.195353&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.137832&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.494071&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.741992&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.738677&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25.238643&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.499401&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24.600466&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.240119&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31.171246&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.499940&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27.534510&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.387400&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.192379&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.499994&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17.034955&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)
    x[1] &amp;lt;- x[1]
    idx &amp;lt;- seq(1, N/2)
    ins &amp;lt;- as.numeric(idx)
    
    bench::mark(
      replace(x, idx, ins),
      insitu_replace(x, 1, ins),
      check    = TRUE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.33µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;604227.9275&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.23µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;626725.4925&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.92µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.62µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;320836.0319&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.07KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.05µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.26µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;681850.9878&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;448B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.62µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113786.9416&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.86KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.16µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.31µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;711556.3865&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.95KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42.78µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;80.93µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11838.8043&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;97.75KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.8µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.13µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;299449.9164&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39.11KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;417.16µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;726.44µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1459.5060&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;976.66KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.53µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;37556.2759&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;390.67KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.68ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.03ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;184.7498&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.54MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_replace(x, 1, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;245.95µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;287.6µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2939.2212&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.81MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-fill&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ fill&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_fill()&lt;/code&gt; is analogous to &lt;code&gt;replace()&lt;/code&gt; but assigns the value into the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- integer(10)
insitu_fill(x, 3L)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 3 3 3 3 3 3 3 3 3 3&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)
    idx &amp;lt;- 1:N
    ins &amp;lt;- 99
    
    bench::mark(
      replace(x, idx, ins),
      insitu_fill(x, ins),
      check    = TRUE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.229236&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.298578&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.326658&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.363341&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.667515&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.830421&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.181148&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.060364&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.324551&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.590073&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.347507&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.572959&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.455272&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.343936&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.357076&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.013211&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.217040&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.111741&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)
    idx &amp;lt;- 1:N
    ins &amp;lt;- 99
    
    bench::mark(
      replace(x, idx, ins),
      insitu_fill(x, ins),
      check    = TRUE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.35µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;662250.3834&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;867ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.05µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;850804.0257&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.67µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;386154.9397&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.27KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.26µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.36µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;597002.8780&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.29µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.64µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;155360.2575&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.81KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.72µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.92µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;194406.1723&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;66.16µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14534.3837&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117.28KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.24µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22958.4854&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;273.27µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;621.43µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1624.1870&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;380.05µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;420.89µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2334.8499&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;replace(x, idx, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.25ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.7ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;241.1781&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.44MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill(x, ins)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.69ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.21ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;235.6181&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-sort&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ sort&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_sort()&lt;/code&gt; is analogous to &lt;code&gt;sort()&lt;/code&gt; but sorts values in the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- sample(10)
insitu_sort(x)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1  2  3  4  5  6  7  8  9 10&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)

    bench::mark(
      sort(x),
      insitu_sort(x),
      check    = TRUE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;44.192865&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42.981013&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40.303405&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26.989432&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.228392&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.388349&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.541023&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.107368&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.478798&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.937674&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.525904&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.521864&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.064732&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.699909&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.669044&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.025600&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.175356&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.330278&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)
    
    bench::mark(
      sort(x),
      insitu_sort(x),
      check    = TRUE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40.45µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.63µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19323.2410&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;899ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.05µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;823655.6466&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41.66µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.55µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17223.6604&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.27KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.51µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.73µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;530651.7167&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.28µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;57.11µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15012.7291&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.81KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.04µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.86µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;109586.8553&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;107.95µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;173.51µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5329.9525&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117.28KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;62.18µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;65.97µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14349.4585&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;653.57µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.2ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;832.5820&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;591.85µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;674.37µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1450.3867&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.83ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.13ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;110.9861&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.44MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_sort(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.54ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;151.5278&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-shuffle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ Shuffle&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_shuffle()&lt;/code&gt; is analogous to &lt;code&gt;sample()&lt;/code&gt; but shuffles values in the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
insitu_shuffle(x)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 9 6 0 3 5 7 8 1 4 2&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)

    bench::mark(
      sample(x),
      insitu_shuffle(x),
      insitu_shuffle_fast(x),
      check    = FALSE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.385214&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.171458&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.053456&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.315175&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.382957&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.972455&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.043932&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.137506&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.700903&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.163097&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.310498&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.336377&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.971023&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.385535&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.233688&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.114623&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.455347&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.182072&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.935903&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.344195&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.137795&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.202304&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.109921&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.875612&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.665743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.785546&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.228209&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.517930&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.345945&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.129547&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.858372&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.382391&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.860528&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.340090&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.774192&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.934830&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)
    
    bench::mark(
      sample(x),
      insitu_shuffle(x),
      insitu_shuffle_fast(x),
      check    = FALSE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.89µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.16µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;129084.90804&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;818ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;975ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;952295.33521&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.77µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.26µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;414345.47824&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.3µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.41µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;83312.86336&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.2KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.74µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;446962.15223&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.03µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.58µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;364783.29064&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41.86µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.39µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20845.99544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.27KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.91µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.28µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;71481.19180&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.28µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.12µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;150911.04998&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;419.28µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;500.08µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1956.51662&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;158.89KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;112.27µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;120.26µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7967.50222&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;35.59µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24551.59483&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.54ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.69ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;143.55062&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.53MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.21ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.39ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;699.63921&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;375.44µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;391.24µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2437.92941&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sample(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;81.23ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;83.06ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.88900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.26MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17.31ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.98ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;44.18255&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_shuffle_fast(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.15ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.09ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;132.75626&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-13-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-reverse&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ Reverse&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_reverse()&lt;/code&gt; is analogous to &lt;code&gt;rev()&lt;/code&gt; but reverses values in the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
insitu_reverse(x)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 9 8 7 6 5 4 3 2 1 0&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)

    bench::mark(
      rev(x),
      insitu_reverse(x),
      check    = TRUE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.001531&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.259724&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.248889&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.519830&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.314951&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.458907&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.461066&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.297345&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.684822&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.170470&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.868918&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.590267&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.360748&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17.015706&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.858245&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.505439&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.468984&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.249604&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- runif(N)
    
    bench::mark(
      rev(x),
      insitu_reverse(x),
      check    = TRUE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.54µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.35µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;279979.0743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;641ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;764ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1148403.6022&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;231492.5363&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.27KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;718ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;820ns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1110216.6455&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.33µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.75µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113639.8907&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.81KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.03µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;823221.0911&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;79.71µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11979.8707&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117.28KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.53µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.88µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;190598.4239&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;278.97µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;716.12µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1380.1388&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.15MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39.46µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42.45µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21911.3579&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rev(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.87ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.5ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;252.3226&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.44MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_reverse(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;425.69µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;525.97µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1746.0251&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-16-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;in-situ-fill-with-random&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;In-situ fill with random&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;insitu_fill_runif()&lt;/code&gt; is analogous to &lt;code&gt;runif()&lt;/code&gt; but generates values in the current
vector rather than creating a new one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- integer(10)
insitu_fill_runif(x, 10, 15)
x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 14 10 10 14 15 13 11 10 10 11&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &amp;amp; results &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign values into a vector
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# N = c(1e1, 1e2, 1e3, 1e4, 1e5, 1e6)

res_rel &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)

    bench::mark(
      runif(x),
      insitu_fill_runif(x, 0, 1),
      insitu_fill_runif_fast(x, 0, 1),
      check    = FALSE,
      relative = TRUE
    )
  }
)

res_rel %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.892204&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.952124&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.937939&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.870067&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.896525&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.054534&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.441160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.689176&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.702906&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.209778&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.348808&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.093330&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.089969&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.102734&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.883208&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.530203&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.871414&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.659101&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16.993506&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.090761&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.584250&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.586271&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.393810&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.507435&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.036940&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.376697&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.573531&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.956403&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.169354&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.028264&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.948139&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20.726121&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.616963&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.674905&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.027731&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NaN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19.864069&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;Inf&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res_abs &amp;lt;- bench::press(
  N = N,
  {
    x &amp;lt;- numeric(N)
    
    bench::mark(
      runif(x),
      insitu_fill_runif(x, 0, 1),
      insitu_fill_runif_fast(x, 0, 1),
      check    = FALSE,
      relative = FALSE
    )
  }
)

res_abs %&amp;gt;%
  select(expression, min, median, `itr/sec`, mem_alloc) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.99µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.59µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;336636.38707&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.07µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.31µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;656322.24018&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.06µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.75µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;327837.27244&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.46µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.26µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;177614.21164&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.32KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.84µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.06µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;439719.78282&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.2µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;295293.68017&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.69µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30.94µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30566.18629&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.35KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.06µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.95µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;88317.87574&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.57µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;206912.05011&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;277.8µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;348.6µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2823.69086&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;80.66KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;95.31µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;101.88µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9417.11075&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16.65µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.25µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;51459.46531&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.72ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.26ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;303.64721&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;783.79KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;942.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.03ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;962.25305&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;143.63µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;148.54µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6491.03605&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;runif(x)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.57ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32.02ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31.96567&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.63MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.65ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.38ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;95.77602&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;insitu_fill_runif_fast(x, 0, 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.43ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.49ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;659.59949&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-09-03-insitu-in-place-modification_files/figure-html/unnamed-chunk-19-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=data.table&#34;&gt;data.table&lt;/a&gt; performs a lot of
operations in-situ (which data.table calls “by reference”)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Run-Length Encoding and The Problem of NAs</title>
      <link>https://coolbutuseless.github.io/2020/08/26/run-length-encoding-and-the-problem-of-nas/</link>
      <pubDate>Wed, 26 Aug 2020 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/26/run-length-encoding-and-the-problem-of-nas/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;run-length-encoding&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Run-Length Encoding&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Run-length encoding&lt;/em&gt; computes the lengths and values of runs of equal
values in a vector&lt;/p&gt;
&lt;p&gt;E.g. given a vector &lt;code&gt;c(1, 1, 1, 8, 9, 9)&lt;/code&gt;, run-length
encoding will summarise the data to say that there are “three 1s, one 8 and two
9s”.&lt;/p&gt;
&lt;p&gt;In R, this can be done with &lt;code&gt;base::rle()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rle(c(1, 1, 1, 8, 9, 9))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Run Length Encoding
  lengths: int [1:3] 3 1 2
  values : num [1:3] 1 8 9&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;a-problem-with-baserle---na-values&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A problem with &lt;code&gt;base::rle()&lt;/code&gt; - NA values&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;base::rle()&lt;/code&gt; checks for equality of one value and the next using &lt;code&gt;==&lt;/code&gt;, and if
they are different then it signals the end of a run of values, and the start
of the next.&lt;/p&gt;
&lt;p&gt;The problem with &lt;code&gt;==&lt;/code&gt; is that &lt;code&gt;NA&lt;/code&gt; values are never considered to equal each
other, which leads to multiple &lt;code&gt;NA&lt;/code&gt; values in a row &lt;em&gt;not&lt;/em&gt; being considered as a run. E.g.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rle(c(1, 1, 1, NA, NA, NA, 2, 2, 2, 2))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Run Length Encoding
  lengths: int [1:5] 3 1 1 1 4
  values : num [1:5] 1 NA NA NA 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The logic used to explain this is usually along the lines of “NA values are unknown
and so would never be equal to each other, so therefore it makes sense they
are not considered as a run of identical values”.&lt;/p&gt;
&lt;p&gt;That’s true: NA is never equal to anything:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;NA == NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;NA == 1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;NA == Inf&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rebuttals:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# While not equal to each other, NAs are identical()
identical(NA, NA)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# NAs are considered the same in unique()
unique(c(1, 1, 1, 2, 2, NA, NA, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1]  1  2 NA&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This NA handling issue has been raised on the R-devel list many years ago &lt;a href=&#34;https://stat.ethz.ch/pipermail/r-help/2011-June/281730.html&#34;&gt;2011&lt;/a&gt;
and today
&lt;a href=&#34;https://stat.ethz.ch/pipermail/r-devel/2020-August/079876.html&#34;&gt;2020&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, &lt;a href=&#34;https://stat.ethz.ch/pipermail/r-devel/2020-August/079876.html&#34;&gt;Gabe Becker&lt;/a&gt; notes
that the run-length encoding function in the &lt;a href=&#34;http://bioconductor.org/packages/release/bioc/html/S4Vectors.html&#34;&gt;Bioconductor - S4Vectors package&lt;/a&gt; does
group the NAs.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;i-want-nas-considered-as-equal-to-each-other-when-doing-run-length-encoding&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;I want NAs considered as equal to each other when doing run-length encoding&lt;/h1&gt;
&lt;p&gt;I acknowledge that NAs are never equal to each other or anything else, but
when I do run-length encoding I want them to be grouped together.&lt;/p&gt;
&lt;p&gt;I’d be interested to find a case when someone is doing run-length encoding
and &lt;em&gt;didn’t&lt;/em&gt; want the NAs grouped together. Hit me up on &lt;a href=&#34;https://twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt; if you can think of one!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;rle2---a-drop-in-replacement-for-rle-that-handles-nas-sanely&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;rle2()&lt;/code&gt; - A drop-in replacement for &lt;code&gt;rle()&lt;/code&gt; that handles NAs sanely&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;rle2()&lt;/code&gt; is a function for run-length encoding that treats
NAs as identical, and thus groups them together.&lt;/p&gt;
&lt;p&gt;This is a copy of the body of &lt;code&gt;base::rle()&lt;/code&gt; with just &lt;strong&gt;1 extra line&lt;/strong&gt; and
&lt;strong&gt;2&lt;/strong&gt; changed lines to handle NA values sanely.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; A drop-in replacement for \code{base::rle()} that treats all NAs as identical
#&amp;#39;
#&amp;#39; @param x an atomic vector
#&amp;#39;
#&amp;#39; @return An object of class \code{rle}
#&amp;#39;
#&amp;#39; @export
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rle2 &amp;lt;- function (x)  {
  stopifnot(&amp;quot;&amp;#39;x&amp;#39; must be a vector of an atomic type&amp;quot; = is.atomic(x))

  n &amp;lt;- length(x)
  if (n == 0L) {
    return(structure(list(
      lengths = integer(), values = x)
    ), class = &amp;#39;rle&amp;#39;)
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Where does next value not equal current value?
  # i.e. y will be TRUE at the last index before a change
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  y &amp;lt;- (x[-1L] != x[-n])

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Since NAs are never equal to anything, NAs in &amp;#39;x&amp;#39; will lead to NAs in &amp;#39;y&amp;#39;.
  # These current NAs in &amp;#39;y&amp;#39; tell use nothing - Set all NAs in y to FALSE
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  y[is.na(y)] &amp;lt;- FALSE

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # When a value in x is NA and its successor is not (or vice versa) then that
  # should also count as a value change and location in &amp;#39;y&amp;#39; should be set to TRUE
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  y &amp;lt;- y | xor(is.na(x[-1L]), is.na(x[-n]))

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Any TRUE locations in &amp;#39;y&amp;#39; are the end of a run, where the next value
  # changes to something different
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  i &amp;lt;- c(which(y), n)

  structure(list(
    lengths = diff(c(0L, i)),
    values  = x[i]
  ), class = &amp;#39;rle&amp;#39;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x &amp;lt;- c(1, 1, 1, NA, NA, NA, NA, 10, 10)
rle(x)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Run Length Encoding
  lengths: int [1:6] 3 1 1 1 1 2
  values : num [1:6] 1 NA NA NA NA 10&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rle2(x)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Run Length Encoding
  lengths: int [1:3] 3 4 2
  values : num [1:3] 1 NA 10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;chipmunkcore&#39; - a wrapper for the chipmunk2d physics simulation c library</title>
      <link>https://coolbutuseless.github.io/2020/08/20/introducing-chipmunkcore-a-wrapper-for-the-chipmunk2d-physics-simulation-c-library/</link>
      <pubDate>Thu, 20 Aug 2020 21:47:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/20/introducing-chipmunkcore-a-wrapper-for-the-chipmunk2d-physics-simulation-c-library/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;chipmunkcore&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;chipmunkcore&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chipmunkcore&lt;/code&gt; is a low-level wrapper around the &lt;a href=&#34;http://chipmunk-physics.net/&#34;&gt;Chipmunk2d&lt;/a&gt; rigid body
physics simulation library.&lt;/p&gt;
&lt;p&gt;There are many low-level functions available, but currently it’s probably
best to use the limited functionality available through the simple &lt;a href=&#34;&#34;&gt;R6&lt;/a&gt; class provided - &lt;code&gt;ChipmunkBasic&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chipmunkcore&lt;/code&gt; is just the simulator. To render the positions of bodies in the simulation you’ll need
to use &lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt;, &lt;a href=&#34;https://github.com/coolbutuseless/cairocore&#34;&gt;cairocore&lt;/a&gt; or
something else&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read the online documentation &lt;a href=&#34;https://coolbutuseless.github.io/package/chipmunkcore&#34;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&#34;pre-requisites&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pre-requisites&lt;/h2&gt;
&lt;p&gt;You’ll need to install the &lt;a href=&#34;http://chipmunk-physics.net/&#34;&gt;Chipmunk2d&lt;/a&gt; library on
your system.&lt;/p&gt;
&lt;p&gt;I only know how to do this on macOS where you can do&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install chipmunk&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you know how to install this library on other systems, and subsequently compile
this package, please let me know by filing an issue, or pinging me on
&lt;a href=&#34;https://twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;After installing the &lt;a href=&#34;http://chipmunk-physics.net/&#34;&gt;Chipmunk2d&lt;/a&gt; C library,
you can install this package from &lt;a href=&#34;https://github.com/coolbutuseless/chipmunkcore&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/chipmunkcore&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Add other shapes besides circles&lt;/li&gt;
&lt;li&gt;Add &lt;em&gt;constraints&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Expose more of the underlying C library&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;galton-board&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Galton Board&lt;/h2&gt;
&lt;p&gt;For full code, see the &lt;a href=&#34;https://coolbutuseless.github.io/package/chipmunkcore/articles/galton.html&#34;&gt;vignette&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chipmunkcore/galton.gif&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;a-simple-simulation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A simple simulation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(chipmunkcore)
library(ggplot2)
set.seed(1)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialize a simulation space
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cm &amp;lt;- Chipmunk$new()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add fixed segments
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cm$add_segment(-20, 10, -5, 0)
cm$add_segment( 20, 10,  5, 0)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch all the segments. Use for plotting
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
segments_df &amp;lt;- cm$get_segments()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add some bodies. Currently only circular bodies supported
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in 1:10) {
  cm$add_body(
    x = runif(1, -20, 20), 
    y = runif(1,  10, 50),
    vx = 10 * rnorm(1),
    vy = 10 * rnorm(1)
  )
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get the current positions of the bodies. as a data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bodies &amp;lt;- cm$get_bodies()
bodies



for (frame in 1:45) {
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Advance the simulation
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cm$advance(5)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Get the bodies in their new locations
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bodies &amp;lt;- cm$get_bodies()
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Plot everything
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  p &amp;lt;- ggplot(bodies) + 
    geom_point(aes(x, y, colour = as.factor(idx)), size = 4, na.rm=TRUE) + 
    geom_segment(data = segments_df, aes(x = x1, y = y1, xend = x2, yend = y2)) + 
    coord_fixed() + 
    # theme_void() + 
    theme_minimal() + 
    xlim(-20, 20) + 
    ylim(-10, 50) + 
    theme(legend.position = &amp;#39;none&amp;#39;)
  
  ggsave(sprintf(&amp;quot;man/figures/png/%04i.png&amp;quot;, frame), p, width = 6, height = 6)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chipmunkcore/simple.gif&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;cairobasic&#39; - an R6 wrapper around cairocore</title>
      <link>https://coolbutuseless.github.io/2020/08/18/introducing-cairobasic-an-r6-wrapper-around-cairocore/</link>
      <pubDate>Tue, 18 Aug 2020 15:39:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/18/introducing-cairobasic-an-r6-wrapper-around-cairocore/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;cairobasic&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;cairobasic&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/cairobasic/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/cairobasic/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cairobasic&lt;/code&gt; is a package which provides a fast canvas for drawing operations.&lt;/p&gt;
&lt;p&gt;This is a really demonstration package showing how &lt;a href=&#34;http://github.com/coolbutuseless/cairocore&#34;&gt;cairocore&lt;/a&gt;
may be made more palatable for programming within R.&lt;/p&gt;
&lt;p&gt;This package currently only offers some basic drawing tools, but could easily
be forked/expanded to suit different needs.&lt;/p&gt;
&lt;p&gt;To get the most out of CairoGraphics at this stage,
you would still need to use &lt;code&gt;cairocore&lt;/code&gt;, but &lt;code&gt;cairobasic&lt;/code&gt; will accumulate
features based upon user feedback.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/cairobasic&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cairobasic&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-cairobasic&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;cairobasic&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;cairobasic&lt;/code&gt; package provides an &lt;a href=&#34;https://cran.r-project.org/package=R6&#34;&gt;R6&lt;/a&gt;
class (&lt;code&gt;CairoBasic&lt;/code&gt;) which keeps track of context information for rendering and
the actual rendering surface.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cairobasic)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a new &amp;#39;CairoBasic&amp;#39; object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
width  &amp;lt;- 800
height &amp;lt;- 400
cb     &amp;lt;- CairoBasic$new(width = width, height = height)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add concentric circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- 10
cb$add_circles(
  x    = rep(width/2, N),
  y    = 0,
  r    = seq(width, 0, length.out = N),
  fill = &amp;#39;#80808020&amp;#39;
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add Lines with rainbow colouring
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- 500
cb$add_line_segments(
  x1 = rep(width/2, N),
  y1 = 0,
  x2 = seq(1, width, length.out = N),
  y2 = height,
  colour = rainbow(N, alpha = 0.1)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add rectangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- 10

xy &amp;lt;- expand.grid(x = seq(1, width/2, width/32), y = seq(1, height, width/32))
xy &amp;lt;- subset(xy, y &amp;lt; width/2 - x - width/16)

cb$add_rectangles(
  x      = xy$x,
  y      = xy$y,
  width  = width/32,
  height = width/32,
  fill   = terrain.colors(nrow(xy)),
  colour = &amp;#39;#20202020&amp;#39;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add polygons
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cx  &amp;lt;- width  * 0.85
cy  &amp;lt;- height * 0.35
ang &amp;lt;- seq(0, 2*pi, pi/3)

x1  &amp;lt;- cx + 50 * sin(ang)
y1  &amp;lt;- cy + 50 * cos(ang)

x2  &amp;lt;- cx + 60 * sin(ang)
y2  &amp;lt;- cy + 60 * cos(ang)

x   &amp;lt;- c(x1, x2)
y   &amp;lt;- c(y1, y2)
idx &amp;lt;- as.integer(c(1, 1, 1, 1, 1, 1, 1,   2, 2, 2, 2, 2, 2, 2))

cb$add_polygons(
  x, y, idx, fill = NA, 
  linewidth = 5,
  colour = c(&amp;#39;red&amp;#39;, &amp;#39;blue&amp;#39;))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add Text
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cb$add_text(&amp;quot;{cairobasic}&amp;quot;, width*0.65 + 1, 10, fontsize = 50, colour = &amp;#39;white&amp;#39;)
cb$add_text(&amp;quot;{cairobasic}&amp;quot;, width*0.65    , 11, fontsize = 50, colour = &amp;#39;#606060a0&amp;#39;)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Show it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cb$show(interpolate = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-18-introducing-cairobasic_files/figure-html/example-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save to PNG
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cb$write_png(&amp;quot;output.png&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;working-with-cairocore&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Working with &lt;code&gt;cairocore&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Read the &lt;a href=&#34;https://github.com/coolbutuseless/cairocore&#34;&gt;cairocore&lt;/a&gt; README for more information&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cairocore)

cairo_set_source_rgba(cb$cr, 1, 0, 0, 0.3)
cairo_set_line_width(cb$cr, 10)
cairo_set_dash(cb$cr, c(10, 15, 25), 3, 0)
cairo_rectangle(cb$cr, 100, 100, width-200, height-200)
cairo_stroke(cb$cr)

cb$show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-18-introducing-cairobasic_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;cairocore&#39; - fast 2d drawing canvas backed by cairo</title>
      <link>https://coolbutuseless.github.io/2020/08/17/introducing-cairocore-fast-2d-drawing-canvas-backed-by-cairo/</link>
      <pubDate>Mon, 17 Aug 2020 19:53:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/17/introducing-cairocore-fast-2d-drawing-canvas-backed-by-cairo/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;cairocore&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;cairocore&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/cairocore/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/cairocore/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cairocore&lt;/code&gt; provides a canvas and tools for fast 2d drawing operations.&lt;/p&gt;
&lt;p&gt;It provides a low-level wrapper around the &lt;a href=&#34;https://www.cairographics.org/&#34;&gt;cariographics&lt;/a&gt;
2D graphics library (written in C) which provides drawing operations
and related functions, with consistent output on multiple platforms and output
media (e.g. SVG, PDF, PNG etc).&lt;/p&gt;
&lt;p&gt;This package is &lt;em&gt;not&lt;/em&gt; a graphics device - you can’t plot to it. Instead it
provides a canvas for directly drawing shapes and text.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;View the online documentation &lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/index.html&#34;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-shapes.png&#34;     width=&#34;45%&#34; style=&#34;float: left;&#34; /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-swirl.png&#34;      width=&#34;45%&#34; style=&#34;float: left;&#34; /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-volcano.png&#34;    width=&#34;45%&#34; style=&#34;float: left;&#34; /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-cairobasic.png&#34; width=&#34;45%&#34; style=&#34;float: left;&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;clear: both;&#34; /&gt;


&lt;div id=&#34;key-features&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Key Features&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Very fast line and shape drawing&lt;/li&gt;
&lt;li&gt;Convert canvas surface to/from R arrays - this means you can draw on an array
from within R&lt;/li&gt;
&lt;li&gt;Alpha-blending and anti-aliasing&lt;/li&gt;
&lt;li&gt;Direct control of what pixels get put on a canvas i.e. not having to pass through
an intermediate plotting step (e.g. ggplot) or graphics device (e.g. png())&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;package-philosophy&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Package Philosophy&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cairocore&lt;/code&gt; is a one-to-one mapping from R functions to C functions in the &lt;a href=&#34;https://www.cairographics.org/&#34;&gt;cariographics&lt;/a&gt;
C library.&lt;/p&gt;
&lt;p&gt;This package will remain very “C-like”, but other packages are
welcome to wrap this &lt;code&gt;cairocore&lt;/code&gt; to enable more idiomatic R programming styles.&lt;/p&gt;
&lt;p&gt;One such wrapper is &lt;a href=&#34;https://github.com/coolbutuseless/cairobasic&#34;&gt;cairobasic&lt;/a&gt; which offers a
subset of the possible drawing operations with a friendlier interface.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation-pre-requisite-cairographics-c-library-headers&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation Pre-requisite: Cairographics C library + headers&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CairoGraphics&lt;/code&gt; library installed&lt;/li&gt;
&lt;li&gt;See &lt;a href=&#34;https://www.cairographics.org/download/&#34;&gt;CairoGraphics downloads page&lt;/a&gt;
for more information on how this might work on your platform.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Install CairoGraphics on Mac OSX &lt;/summary&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using &lt;a href=&#34;https://brew.sh/&#34;&gt;homebrew&lt;/a&gt; - &lt;code&gt;brew install cairo&lt;/code&gt; (this works on my Mac)&lt;/li&gt;
&lt;li&gt;Using &lt;a href=&#34;&#34;&gt;MacPorts&lt;/a&gt; - &lt;code&gt;sudo port install cairo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Using &lt;a href=&#34;sudo%20apt-get%20install%20cairo&#34;&gt;fink&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Install CairoGraphics on Linux &lt;/summary&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debian/Ubuntu - &lt;code&gt;sudo apt-get install libcairo2-dev&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fedora - &lt;code&gt;sudo yum install cairo-devel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;openSUSE - &lt;code&gt;zypper install cairo-devel&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Install CairoGraphics on Windows &lt;/summary&gt;&lt;/p&gt;
&lt;p&gt;I haven’t been able to test any of the windows techniques - if you are a windows user,
please let me know what worked for you!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cairographics.org/download/&#34;&gt;CairoGraphics downloads page&lt;/a&gt;
for more information&lt;/li&gt;
&lt;li&gt;Try the following:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/r-windows/docs/blob/master/rtools40.md#system-libraries-and-pacman&#34;&gt;Rtools/pacman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rwinlib/cairo&#34;&gt;rwinlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/microsoft/winget-cli&#34;&gt;winget&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/cairocore&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/cairocore&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;documentation-tutorials&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Documentation + Tutorials&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;cairocore&lt;/code&gt; behaves almost identically to the &lt;code&gt;CairoGraphics&lt;/code&gt; C library and in
many cases examples from the internet (which are all in C code) may be lightly modified and used as R code.&lt;/p&gt;
&lt;p&gt;The documentation for &lt;code&gt;cairocore&lt;/code&gt; is mostly a direct translation of the
&lt;a href=&#34;https://www.cairographics.org/manual/&#34;&gt;&lt;code&gt;CairoGraphics&lt;/code&gt; documentation&lt;/a&gt; and
has been extracted from the C source files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;View the online documentation &lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/index.html&#34;&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A great tutorial on using CairoGraphics in C is from &lt;a href=&#34;http://zetcode.com/gfx/cairo/&#34;&gt;zetcode&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;p&gt;I’ve tried to highlight a few interesting features of CairoGrapihcs in the vignettes,
but the library is huge and I can’t cover all of it here.&lt;/p&gt;
&lt;p&gt;Hopefully there are enough code examples to get you started!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-creating-and-using-patterns.html&#34;&gt;Creating patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-drawing-on-arrays.html&#34;&gt;Drawing on R arrays&lt;/a&gt; create a drawing canvas from an R array and draw on it&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-drawing-simple-shapes.html&#34;&gt;Drawing simple shapes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-image-output-formats.html&#34;&gt;Image output formats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-transforms.html&#34;&gt;Using Transforms&lt;/a&gt; by default CairoGraphics considers the origin to be the top left of the page. This vignette sets the transformation matrix on a surface such that the bottom left corner is considered the origin.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/demo-vectorised-functions.html&#34;&gt;Vectorised functions&lt;/a&gt; there are some custom functions for drawing multitudes of the same type of element. There is a speed advantage in looping over data within C rather than within R.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/technical-C-enums-in-R.html&#34;&gt;Technical - enums in C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/technical-C-pointers-in-R.html&#34;&gt;Technical - pointers in C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/cairocore/articles/technical-C-structs-in-R.html&#34;&gt;Technical - structs in C&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example---using-cairocore-as-a-drawing-canvas&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - Using &lt;code&gt;cairocore&lt;/code&gt; as a drawing canvas&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-shapes.png&#34;     width=&#34;45%&#34; /&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cairocore)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a surface to draw on.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
width  &amp;lt;- 800
height &amp;lt;- 400

surface &amp;lt;- cairo_image_surface_create(
  format = cairo_format_t$CAIRO_FORMAT_ARGB32, 
  width  = width,
  height = height
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Every surface must have a context in order to operate on it.
# For faster operation, antialiasing can be switched off
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cr &amp;lt;- cairo_create(surface)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Clear the surface to a light grey
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_set_source_rgb(cr, 0.98, 0.98, 0.98)
cairo_paint(cr)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw some red lines
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_set_source_rgba(cr, 1, 0, 0, 0.02)
for (i in seq(width)) {
  cairo_move_to(cr, 0, 0)
  cairo_line_to(cr, i, height)
  cairo_stroke(cr)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw some rectangles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_set_line_width(cr, 0.5)
cairo_set_source_rgba(cr, 0, 0, 1, 0.2)

for (j in seq(1, height, 22)) {
  for (i in seq(width/2, width, 22)) {
    cairo_rectangle(cr, i, j, 20, 20)
    cairo_fill(cr)
  }
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw green circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (x in seq(1, width/3, 50)) {
  for (y in seq(height/2, height, 50)) {
    cairo_set_source_rgba(cr, 0, 0.5, 0, 0.1)
    cairo_arc(cr, x, y, radius = 20, 0, 2*pi)
    cairo_fill(cr)
  }
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get the image surface as a raster
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
raster_out &amp;lt;- cairo_image_surface_get_raster(surface, nchannel = 3)
plot(raster_out, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-17-introducing-cairocore_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save the surface as a PNG
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_surface_write_to_png(surface, tempfile(fileext = &amp;quot;.png&amp;quot;))
[1] 0&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;example---drawing-10000-alpha-blended-lines&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - drawing 10,000 alpha blended lines&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-swirl.png&#34;      width=&#34;45%&#34; /&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cairocore)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Calculate the end coordinates of a lot of line segments
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
width  &amp;lt;- 1000
height &amp;lt;- 500
N      &amp;lt;- 10000
t      &amp;lt;- seq(0, 2*pi, length.out = N)
x1     &amp;lt;- width  * sin(t)
x2     &amp;lt;- width  * sin(2 * t + pi/2)
y1     &amp;lt;- height * cos(t)
y2     &amp;lt;- height * cos(4*t + pi/2)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a surface to draw on.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
surface &amp;lt;- cairo_image_surface_create(
  format = cairo_format_t$CAIRO_FORMAT_ARGB32, 
  width  = width,
  height = height
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Every surface must have a context in order to operate on it.
# For faster operation, antialiasing can be switched off
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cr &amp;lt;- cairo_create(surface)
# cairo_set_antialias(cr, cairo_antialias_t$CAIRO_ANTIALIAS_NONE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Clear the surface to a light grey
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_set_source_rgb(cr, 0.98, 0.98, 0.98)
cairo_paint(cr)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set the drawing colour for subsequent operations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_set_source_rgba(cr, 0.2, 0.3, 1, 0.01)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw each line - 
#   this seems laborious but it is idiomatic C/cairo programming style
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in seq(N)) {
  cairo_move_to(cr, x1[i], y1[i])
  cairo_line_to(cr, x2[i], y2[i])
  cairo_stroke(cr)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write some text on the cairo surface
# `cairo_font_slant_t` and `cairo_font_weight_t` are enums in C which have 
# been encoded as lists in R.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_select_font_face (
  cr, 
  family = &amp;quot;sans&amp;quot;, 
  slant  = cairo_font_slant_t$CAIRO_FONT_SLANT_NORMAL, 
  weight = cairo_font_weight_t$CAIRO_FONT_WEIGHT_BOLD
)

cairo_set_font_size(cr, 57.0)
cairo_set_source_rgba(cr, 0, 0, 0, 0.3) 
cairo_move_to (cr, 5.0, 60.0)
cairo_show_text (cr, &amp;quot;{cairocore}&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get the image surface as a raster
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
raster_out &amp;lt;- cairo_image_surface_get_raster(surface, nchannel = 3)
plot(raster_out, interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-17-introducing-cairocore_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;example---taking-an-array-in-r-drawing-on-it-returning-it-to-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - taking an array in R, drawing on it, returning it to R&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/cairocore/demo-volcano.png&#34;    width=&#34;45%&#34; /&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(cairocore)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Let&amp;#39;s grab the volcano
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arr &amp;lt;- (t(volcano) - min(volcano))/(max(volcano) - min(volcano))
plot(as.raster(arr), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-17-introducing-cairocore_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a surface from the array
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
surface &amp;lt;- cairo_image_surface_create_from_array(arr)
cr      &amp;lt;- cairo_create(surface)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a circle on the cairo surface
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_arc(cr, 70, 15, 10, 0, 2*pi)
cairo_set_line_width(cr, 3);
cairo_set_source_rgba(cr, 255/255, 99/255, 71/255, 0.8)
cairo_stroke(cr)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write some text on the cairo surface
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cairo_select_font_face (cr, &amp;quot;serif&amp;quot;, cairo_font_slant_t$CAIRO_FONT_SLANT_NORMAL, cairo_font_weight_t$CAIRO_FONT_WEIGHT_BOLD)
cairo_set_font_size (cr, 17.0)
cairo_set_source_rgb (cr, 0.2, 0.6, 1.0) 
cairo_move_to (cr, 2.0, 56.0)
cairo_show_text (cr, &amp;quot;{cairocore}&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch the drawing surface as an array
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
array_out &amp;lt;- cairo_image_surface_get_array(surface=surface)
plot(as.raster(array_out), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-17-introducing-cairocore_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The R &lt;a href=&#34;https://cran.r-project.org/package=Cairo&#34;&gt;Cairo&lt;/a&gt; package uses the CairoGraphics library
internally to provide graphics output devices for plotting.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The R &lt;a href=&#34;https://cran.r-project.org/package=cairoDevice&#34;&gt;cairoDevice&lt;/a&gt; package appears to be almost
identical to the &lt;code&gt;{Cairo}&lt;/code&gt; package in that it provides graphics output devices for plotting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining R&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;spng&#39; - In-memory decoding of PNG images</title>
      <link>https://coolbutuseless.github.io/2020/08/05/introducing-spng-in-memory-decoding-of-png-images/</link>
      <pubDate>Wed, 05 Aug 2020 20:22:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/05/introducing-spng-in-memory-decoding-of-png-images/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;spng&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;spng&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;spng&lt;/code&gt; offers in-memory decompression of PNG images to vectors of raw values.&lt;/p&gt;
&lt;p&gt;This is useful if you have bytes representing a PNG image (e.g. from a database)
and need to decompress these to an array representation within R.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;spng&lt;/code&gt; is a R wrapper for &lt;a href=&#34;https://github.com/randy408/libspng&#34;&gt;libspng&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://libspng.org/docs/api/&#34;&gt;libpng API docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/spng&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/spng&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;depng(raw_vec, fmt, flags)&lt;/code&gt; - convert a vector of raw values containing a
PNG image into a vector of raw bytes representing individual pixel values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;get_info(raw_vec)&lt;/code&gt; - interrogate a vector of raw values containing a PNG image
to determine image information i.e. width, height, bit_depth, color_type,
compression_method, filter_method, interlace_method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-decompress-a-png-in-memory&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Decompress a PNG in memory&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(spng)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A PNG file everyone should have!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
png_file &amp;lt;- system.file(&amp;quot;img&amp;quot;, &amp;quot;Rlogo.png&amp;quot;, package=&amp;quot;png&amp;quot;)
img &amp;lt;- magick::image_read(png_file)
img&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-05-introducing-spng_files/figure-html/example-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read in the raw bytes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
png_data &amp;lt;- readBin(png_file, &amp;#39;raw&amp;#39;, n = file.size(png_file))
png_data[1:100]
  [1] 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 64 00 00 00 4c 08
 [26] 06 00 00 00 9b 1d 12 0f 00 00 00 06 62 4b 47 44 00 ff 00 ff 00 ff a0 bd a7
 [51] 93 00 00 00 09 70 48 59 73 00 00 2e 23 00 00 2e 23 01 78 a5 3f 76 00 00 00
 [76] 07 74 49 4d 45 07 d5 02 10 10 08 0e 97 b9 27 bc 00 00 20 00 49 44 41 54 78&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get info about the PNG 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(png_info &amp;lt;- spng::png_info(png_data))
$width
[1] 100

$height
[1] 76

$bit_depth
[1] 8

$color_type
[1] 6

$compression_method
[1] 0

$filter_method
[1] 0

$interlace_method
[1] 0

$color_desc
[1] &amp;quot;RGB + Alpha&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Unpack the raw PNG bytes into RGB 8-bits-per-color packed format. 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
img_data &amp;lt;- spng::depng(png_data, fmt = spng_format$SPNG_FMT_RGB8)
img_data[1:200]
  [1] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [26] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [51] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [76] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[101] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c6 c8 c5 98 9b
[126] 96 8f 93 8c 87 8b 84 83 87 80 81 85 7e 80 84 7d 7e 82 7a 81 85 7e 7e 83 7b
[151] 7e 83 7b 7e 83 7b 78 7d 75 80 85 7d 7e 82 7b 80 84 7d 81 85 7e 88 8c 85 9a
[176] 9d 97 be bf bc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Pick the green channel and plot as greyscale
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- length(img_data)
mat &amp;lt;- matrix(img_data[seq(2, N, 3)], nrow = png_info$width, ncol = png_info$height)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Image had an alpha channel, let&amp;#39;s replace that with white background
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat[mat == 0] &amp;lt;- as.raw(255)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# PNG bytes are in row-major order. R is in column major order
# so need to transpose to view correctly
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot(as.raster(t(mat)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-05-introducing-spng_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Construct an array by plucking the relevant bytes.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arr &amp;lt;- array(
  c(
    img_data[seq(1, N, 3)], # R
    img_data[seq(2, N, 3)], # G
    img_data[seq(3, N, 3)]  # B
  ),
  dim = c(png_info$width, png_info$height, 3)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This array had an alpha channel. Let&amp;#39;s replace the background with white.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arr[arr == 0] &amp;lt;- as.raw(255)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# PNG bytes are in row-major order. R is in column major order
# so need to transpose to view correctly
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arr &amp;lt;- aperm(arr, c(2, 1, 3))
plot(as.raster(arr))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-05-introducing-spng_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;pixelweaver&#39; - Convert arrays/matrices to packed ARGB32 colour format</title>
      <link>https://coolbutuseless.github.io/2020/08/03/introducing-pixelweaver-convert-arrays/matrices-to-packed-argb32-colour-format/</link>
      <pubDate>Mon, 03 Aug 2020 20:34:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/03/introducing-pixelweaver-convert-arrays/matrices-to-packed-argb32-colour-format/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;pixelweaver&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;pixelweaver &lt;img src=&#34;https://coolbutuseless.github.io/img/pixelweaver/logo-hex.png&#34; align=&#34;right&#34; width=&#34;300&#34; /&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://github.com/coolbutuseless/pixelweaver/actions&#34;&gt;&lt;img src=&#34;https://github.com/coolbutuseless/pixelweaver/workflows/R-CMD-check/badge.svg&#34; alt=&#34;R build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pixelweaver&lt;/code&gt; provides functions for converting R matrices and arrays into a
common packed integer representation - &lt;code&gt;ARGB32&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The ARGB32 data is stored in memory and referenced by an external pointer. This
data can then either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;manipulated and then converted back to matrix or array&lt;/li&gt;
&lt;li&gt;be passed to other C library wrappers written in R which understand external pointers.&lt;/li&gt;
&lt;li&gt;converted to a vector of raw values&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;why&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Rstats&lt;/em&gt; commonly stores pixel information in arrays, where the R, G, B and A values
are specified as separate planes of an array (in that order). Values in the
array are commonly real numbers in the range [0, 1]&lt;/p&gt;
&lt;p&gt;Very few C graphics libraries support this planar colour representation.&lt;/p&gt;
&lt;p&gt;One common format C libraries support is ARGB32 - where a single byte is
used to represent each of the A, R, G and B values (each value is in the range
[0, 255]). These
bytes are then lumped together as a 4-byte sequence.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pixelweaver&lt;/code&gt; provides functions for converting R’s planar colour representation to/from
the packed ARGB32 representation.&lt;/p&gt;
&lt;p&gt;An overview/schematic of the pixel representations and where &lt;code&gt;pixelweaver&lt;/code&gt; sits is
illustrated below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/pixelweaver/array-representation.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Support copying into pre-allocated arrays to avoid having to allocate new
memory each time.&lt;/li&gt;
&lt;li&gt;Faster algorithms for the transpose and shuffle. MMX? SSE? AVX?&lt;/li&gt;
&lt;li&gt;Other pixel formats e.g. RGBA32&lt;/li&gt;
&lt;li&gt;Support for big-endian systems (are there any such systems in common use with R?)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/pixelweaver&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/pixelweaver&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;argb32_to_planar()&lt;/code&gt;, &lt;code&gt;planar_to_argb32()&lt;/code&gt; - convert matrices and arrays to/from
packed ARGB32 format. These functions store the ARGB32 data as a sequence of
bytes in memory and return an external pointer to this memory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;argb32_to_raw()&lt;/code&gt;, &lt;code&gt;raw_to_argb32()&lt;/code&gt; - convert the package ARGB32 format from
an external pointer (to data in memory) to a vector of raw values in R.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;conversion-of-an-rgba-array-to-argb32-format-and-back-again.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conversion of an RGBA array to ARGB32 format and back again.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(pixelweaver)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an an array with 3 planes representing RGB colour data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(arr &amp;lt;- array(seq(4*3*3)/36, c(4, 3, 3)))
, , 1

           [,1]      [,2]      [,3]
[1,] 0.02777778 0.1388889 0.2500000
[2,] 0.05555556 0.1666667 0.2777778
[3,] 0.08333333 0.1944444 0.3055556
[4,] 0.11111111 0.2222222 0.3333333

, , 2

          [,1]      [,2]      [,3]
[1,] 0.3611111 0.4722222 0.5833333
[2,] 0.3888889 0.5000000 0.6111111
[3,] 0.4166667 0.5277778 0.6388889
[4,] 0.4444444 0.5555556 0.6666667

, , 3

          [,1]      [,2]      [,3]
[1,] 0.6944444 0.8055556 0.9166667
[2,] 0.7222222 0.8333333 0.9444444
[3,] 0.7500000 0.8611111 0.9722222
[4,] 0.7777778 0.8888889 1.0000000
plot(as.raster(arr), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-03-introducing-pixelweaver_files/figure-html/example-1.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert the R planar colour representation to packed ARGB32 format 
# This is a pointer to a memory location that contains the data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
argb32_ptr &amp;lt;- planar_to_argb32(arr, maxval = 1)
argb32_ptr
&amp;lt;pointer: 0x7f9fb8577770&amp;gt;
attr(,&amp;quot;class&amp;quot;)
[1] &amp;quot;unsigned char&amp;quot;


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# View the raw data. Note the value = 255 every 4th value - this is the 
# default alpha value set for each pixel
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
as.integer(argb32_to_raw(argb32_ptr))
 [1] 177  92   7 255 205 120  35 255 233 148  63 255 184  99  14 255 212 127  42
[20] 255 240 155  70 255 191 106  21 255 219 134  49 255 247 162  77 255 198 113
[39]  28 255 226 141  56 255 255 170  85 255


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert the R, G and Blue values from the packed ARGB32 representation 
# back into the original representation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(arr_out &amp;lt;- argb32_to_planar(argb32_ptr, &amp;#39;rgb&amp;#39;))
, , 1

           [,1]      [,2]      [,3]
[1,] 0.02745098 0.1372549 0.2470588
[2,] 0.05490196 0.1647059 0.2745098
[3,] 0.08235294 0.1921569 0.3019608
[4,] 0.10980392 0.2196078 0.3333333

, , 2

          [,1]      [,2]      [,3]
[1,] 0.3607843 0.4705882 0.5803922
[2,] 0.3882353 0.4980392 0.6078431
[3,] 0.4156863 0.5254902 0.6352941
[4,] 0.4431373 0.5529412 0.6666667

, , 3

          [,1]      [,2]      [,3]
[1,] 0.6941176 0.8039216 0.9137255
[2,] 0.7215686 0.8313725 0.9411765
[3,] 0.7490196 0.8588235 0.9686275
[4,] 0.7764706 0.8862745 1.0000000
plot(as.raster(arr_out), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-03-introducing-pixelweaver_files/figure-html/example-2.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert the R, G and Blue values from the packed ARGB32 representation 
# back into a grey matrix using  0.3R + 0.59G + 0.11B
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(mat_out &amp;lt;- argb32_to_planar(argb32_ptr, &amp;#39;grey&amp;#39;))
          [,1]      [,2]      [,3]
[1,] 0.2974510 0.4072549 0.5170588
[2,] 0.3249020 0.4347059 0.5445098
[3,] 0.3523529 0.4621569 0.5719608
[4,] 0.3798039 0.4896078 0.6033333
plot(as.raster(mat_out), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-03-introducing-pixelweaver_files/figure-html/example-3.png&#34; width=&#34;40%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical bits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ARGB32 or ARGB8888 format.&lt;/li&gt;
&lt;li&gt;Each of A, R, G, B gets 1 byte (8 bits)&lt;/li&gt;
&lt;li&gt;Together these 4 bytes fit in a standard ‘int32’&lt;/li&gt;
&lt;li&gt;‘A’ (alpha) is in the most significant byte&lt;/li&gt;
&lt;li&gt;x86 systems are little-endian so when viewing these bytes one at a time, the
order will be B, G, R, A. i.e. from least signficant to most significant byte&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining the language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;simpletrie&#39; - a simple trie written in pure R (a.k.a. a tool for cheating at scrabble)</title>
      <link>https://coolbutuseless.github.io/2020/08/01/introducing-simpletrie-a-simple-trie-written-in-pure-r-a.k.a.-a-tool-for-cheating-at-scrabble/</link>
      <pubDate>Sat, 01 Aug 2020 21:11:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/08/01/introducing-simpletrie-a-simple-trie-written-in-pure-r-a.k.a.-a-tool-for-cheating-at-scrabble/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;simpletrie&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;simpletrie&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/dependencies-zero-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;simpletrie&lt;/code&gt; is a simple &lt;a href=&#34;https://en.wikipedia.org/wiki/Trie&#34;&gt;trie&lt;/a&gt; implementation
in plain R code.&lt;/p&gt;
&lt;p&gt;A trie is a structure for representing certain data as a tree of nodes. This
data representation allows for fast queries of certain types.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;simpletrie&lt;/code&gt; can build a trie from 175k words in about 3s.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;trie_create()&lt;/code&gt; - create a trie, and optionally initialise with a dictionary of words&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trie_insert()&lt;/code&gt; - insert words into a trie&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trie_find_subwords()&lt;/code&gt; - find all sub-words in the trie using the characters in the given word&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/simpletrie&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/simpletrie&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-finding-sub-words-from-a-given-word&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Finding sub-words from a given word&lt;/h2&gt;
&lt;p&gt;My main use-case for &lt;code&gt;simpletrie&lt;/code&gt; is for looking up scrabble words i.e. to find all possible sub-words of a given word with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the characters in any order&lt;/li&gt;
&lt;li&gt;being able to specify a &lt;em&gt;wildcard&lt;/em&gt; to indicate that any letter can be used
i.e. the &lt;code&gt;.&lt;/code&gt; character&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(simpletrie)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read the ENABLE word list
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
words &amp;lt;- tolower(readLines(&amp;quot;enable1.txt&amp;quot;))
length(words)
[1] 172821

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create trie strcture
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
system.time({
  trie &amp;lt;- trie_create(words)
})
   user  system elapsed 
  1.762   0.049   1.820 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Find all words which can be made with &amp;#39;hi.rstats&amp;#39;
# &amp;#39;.&amp;#39; is a wildcard, and can match any letter. (Like a blank tile in scrabble)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
system.time({
  subwords &amp;lt;- trie_find_subwords(trie, &amp;#39;hi.rstats&amp;#39;)
})
   user  system elapsed 
  0.109   0.003   0.113 

length(subwords)
[1] 2304
head(subwords, 100)
  [1] &amp;quot;hi&amp;quot;       &amp;quot;hire&amp;quot;     &amp;quot;hires&amp;quot;    &amp;quot;his&amp;quot;      &amp;quot;hist&amp;quot;     &amp;quot;hists&amp;quot;   
  [7] &amp;quot;hists&amp;quot;    &amp;quot;hiss&amp;quot;     &amp;quot;hisser&amp;quot;   &amp;quot;hissy&amp;quot;    &amp;quot;hisn&amp;quot;     &amp;quot;hiss&amp;quot;    
 [13] &amp;quot;hist&amp;quot;     &amp;quot;hists&amp;quot;    &amp;quot;hit&amp;quot;      &amp;quot;hits&amp;quot;     &amp;quot;hitter&amp;quot;   &amp;quot;hitters&amp;quot; 
 [19] &amp;quot;hits&amp;quot;     &amp;quot;hiatus&amp;quot;   &amp;quot;hic&amp;quot;      &amp;quot;hid&amp;quot;      &amp;quot;hie&amp;quot;      &amp;quot;hies&amp;quot;    
 [25] &amp;quot;hilt&amp;quot;     &amp;quot;hilts&amp;quot;    &amp;quot;hila&amp;quot;     &amp;quot;hilar&amp;quot;    &amp;quot;him&amp;quot;      &amp;quot;hin&amp;quot;     
 [31] &amp;quot;hins&amp;quot;     &amp;quot;hint&amp;quot;     &amp;quot;hints&amp;quot;    &amp;quot;hip&amp;quot;      &amp;quot;hips&amp;quot;     &amp;quot;his&amp;quot;     
 [37] &amp;quot;hiss&amp;quot;     &amp;quot;hist&amp;quot;     &amp;quot;hists&amp;quot;    &amp;quot;hit&amp;quot;      &amp;quot;hits&amp;quot;     &amp;quot;ha&amp;quot;      
 [43] &amp;quot;hair&amp;quot;     &amp;quot;hairs&amp;quot;    &amp;quot;hairs&amp;quot;    &amp;quot;hairy&amp;quot;    &amp;quot;haik&amp;quot;     &amp;quot;haiks&amp;quot;   
 [49] &amp;quot;hail&amp;quot;     &amp;quot;hails&amp;quot;    &amp;quot;hair&amp;quot;     &amp;quot;hairs&amp;quot;    &amp;quot;harsh&amp;quot;    &amp;quot;hart&amp;quot;    
 [55] &amp;quot;harts&amp;quot;    &amp;quot;harts&amp;quot;    &amp;quot;harass&amp;quot;   &amp;quot;hard&amp;quot;     &amp;quot;hards&amp;quot;    &amp;quot;hare&amp;quot;    
 [61] &amp;quot;hares&amp;quot;    &amp;quot;hark&amp;quot;     &amp;quot;harks&amp;quot;    &amp;quot;harl&amp;quot;     &amp;quot;harls&amp;quot;    &amp;quot;harm&amp;quot;    
 [67] &amp;quot;harms&amp;quot;    &amp;quot;harp&amp;quot;     &amp;quot;harpist&amp;quot;  &amp;quot;harpists&amp;quot; &amp;quot;harps&amp;quot;    &amp;quot;hart&amp;quot;    
 [73] &amp;quot;harts&amp;quot;    &amp;quot;has&amp;quot;      &amp;quot;hast&amp;quot;     &amp;quot;hastier&amp;quot;  &amp;quot;hastiest&amp;quot; &amp;quot;haste&amp;quot;   
 [79] &amp;quot;hastes&amp;quot;   &amp;quot;hasty&amp;quot;    &amp;quot;hash&amp;quot;     &amp;quot;hasp&amp;quot;     &amp;quot;hasps&amp;quot;    &amp;quot;hast&amp;quot;    
 [85] &amp;quot;hat&amp;quot;      &amp;quot;hats&amp;quot;     &amp;quot;hatter&amp;quot;   &amp;quot;hatters&amp;quot;  &amp;quot;hate&amp;quot;     &amp;quot;hater&amp;quot;   
 [91] &amp;quot;haters&amp;quot;   &amp;quot;hates&amp;quot;    &amp;quot;hath&amp;quot;     &amp;quot;hats&amp;quot;     &amp;quot;haar&amp;quot;     &amp;quot;haars&amp;quot;   
 [97] &amp;quot;habit&amp;quot;    &amp;quot;habits&amp;quot;   &amp;quot;had&amp;quot;      &amp;quot;hadst&amp;quot;   &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-a-trie&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s a trie?&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;trie&lt;/em&gt; is an ordered data structure represented as a tree of nodes.&lt;/p&gt;
&lt;p&gt;The image below shows a very small trie which represents the words: ‘cat’, ‘cog’, ‘dog’ and ‘dote.’&lt;/p&gt;
&lt;p&gt;This representation allows for very fast queries of certain types.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-08-01-introducing-simpletrie_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical bits&lt;/h2&gt;
&lt;p&gt;The trie is implemented here as nested environments. Environments are
created with &lt;code&gt;new.env(parent = emptyenv(), hash = FALSE)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;emptyenv()&lt;/code&gt; as parent saves some memory, as the parent
environment is never needed in this process.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hash&lt;/code&gt; is set to &lt;code&gt;FALSE&lt;/code&gt; as using a hash table expands the memory
usage by quite a bit - even if &lt;code&gt;size&lt;/code&gt; is set to limit the initial hash
table size.&lt;/p&gt;
&lt;p&gt;Using a hash table on the environment doesn’t
appreciably change the speed of trie creation or preforming look-ups.&lt;/p&gt;
&lt;p&gt;Environments are used instead of lists as I make use of the reference semantics
of environment objects when building the trie.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software-resources&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software + Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Trie&#34;&gt;Trie on Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hrbrmstr/iptrie&#34;&gt;iptrie&lt;/a&gt; - Efficiently Store and Query ‘IPv4’ Internet Addresses with Associated Data&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=triebeard&#34;&gt;triebeard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/rtrie/index.html&#34;&gt;rtrie&lt;/a&gt; - was previously on cran but has now been archived&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/AhoCorasickTrie/index.html&#34;&gt;AhoCorasickTrie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Some raw wordlists e.g. ENABLE1 and SOWPODS can be found &lt;a href=&#34;http://norvig.com/ngrams/&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://stackoverflow.com/questions/27060453/how-to-build-an-alphabetical-tree-from-a-list-of-words-in-r&#34;&gt;Bare bones trie creation in 10 lines of R&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;frak&#39; - a julia set fractal generator</title>
      <link>https://coolbutuseless.github.io/2020/07/16/introducing-frak-a-julia-set-fractal-generator/</link>
      <pubDate>Thu, 16 Jul 2020 20:41:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/07/16/introducing-frak-a-julia-set-fractal-generator/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;frak&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;frak &lt;img src=&#34;https://coolbutuseless.github.io/img/frak/logo-trans.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;frak&lt;/code&gt; is a small R package to generate fractals - currently just &lt;a href=&#34;https://en.wikipedia.org/wiki/Julia_set&#34;&gt;Julia Sets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I needed a fast way to generate test images for testing other software, with
images that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;are fast to produce&lt;/li&gt;
&lt;li&gt;are interesting, not just white noise&lt;/li&gt;
&lt;li&gt;8-bits-per-pixel, so the value can fit in an R &lt;code&gt;raw&lt;/code&gt; vector or a C
&lt;code&gt;uint8_t&lt;/code&gt; vector.&lt;/li&gt;
&lt;li&gt;can be be panned, zoomed and changed with simple changes to the input variables&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/frak&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/frak&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;julia(cx, cy, movex, movey, zoom, size, max_iter)&lt;/code&gt; generate a julia set, where
&lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt; are the components of imageinary iteration variable &lt;em&gt;c&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Returned array of raw values represents the iteration count at which a particular location
veered towards infinity. These values are scaled to span the full range from
allowable within a raw vector (i.e. the whole numbers from 0 to 255)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-generate-a-julia-set&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Generate a julia set&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(frak)

fractal &amp;lt;- julia(cx = -0.7, cy = 0.27, zoom = 1, size = 400, max_iter = 255)
mode(fractal) &amp;lt;- &amp;#39;integer&amp;#39;
plot(as.raster(fractal/255))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-16-frak-julia-set-fractal-generator_files/figure-html/example-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-colour-the-image-with-viridis&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: colour the image with viridis&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(viridisLite)

# generate a fractal
fractal &amp;lt;- julia(cx = -0.74, cy = 0.17, zoom = 3, size = 400, max_iter = 100)
mode(fractal) &amp;lt;- &amp;#39;integer&amp;#39;

# Grab a palette from viridis
pal &amp;lt;- rev(viridisLite::viridis(256))

# Recode the values with the palette. Lowest raw value is 0, so offset by 1.
fractal_raster   &amp;lt;- fractal
fractal_raster[] &amp;lt;- pal[fractal_raster + 1]

plot(as.raster(fractal_raster))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-16-frak-julia-set-fractal-generator_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-git-file-rendered-from-multiple-frames&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: git file rendered from multiple frames&lt;/h2&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code to generate gif &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(foist)
library(displease)
library(frak)

dir.create(&amp;#39;/img/frak/anim&amp;#39;, showWarnings = FALSE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Use {displease} to get a pleasing motion as the zoom is performed
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- 100
zoom &amp;lt;- displease::seq_ease(1, 1000, n = N, type = &amp;#39;exp-in&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Loop: create an image dump it to file.
# Using {foist} here for fast image output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in seq(N)) {
  frac &amp;lt;- frak::julia(cx = -0.71, zoom = zoom[i], movex = 0.1)
  mode(frac) &amp;lt;- &amp;#39;integer&amp;#39;
  frac &amp;lt;- frac/255
  
  filename &amp;lt;- sprintf(&amp;quot;/img/frak/anim/%03i.png&amp;quot;, i)
  
  foist::write_png(
    data                 = frac, 
    filename             = filename, 
    pal                  = foist::vir$magma, 
    convert_to_row_major = FALSE
  )
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the animation using imagemagick and delete the source frames
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
system(&amp;quot;convert /img/frak/anim/*.png /img/frak/anim.gif&amp;quot;)
unlink(&amp;quot;/img/frak/anim/&amp;quot;, recursive = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/frak/anim.gif&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;p&gt;Creating a julia set in C is about 100x faster than using plain R (as in the &lt;a href=&#34;https://cran.r-project.org/package=Julia&#34;&gt;Julia&lt;/a&gt; package on CRAN)&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide bench::mark() code&lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;suppressPackageStartupMessages({
  library(Julia)
  library(frak)
  library(ggplot2)
  library(dplyr)
  library(tidyr)
})

size &amp;lt;- 400

# Julia::JuliaImage does at most 50 iterations
res &amp;lt;- bench::mark(
  `Julia::JuliaImage()` = Julia::JuliaImage(imageN = size, centre = 0.0, L = 4, C = 1-1.6180339887),
  `frak::julia()`       = julia(size = size, max_iter = 50),
  check = FALSE
)
Warning: Some expressions had a GC in every iteration; so filtering is disabled.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Julia::JuliaImage()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;802.68ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;802.68ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.24582&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;frak::julia()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.57ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.92ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;115.48860&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-16-frak-julia-set-fractal-generator_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=mandelbrot&#34;&gt;mandelbrot&lt;/a&gt; - Generate view on the Mandelbrot Set.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=Julia&#34;&gt;Julia&lt;/a&gt; - a Pure R Julia Set generator&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;displease&#39; - a package for non-linear numeric inteprolation</title>
      <link>https://coolbutuseless.github.io/2020/07/14/introducing-displease-a-package-for-non-linear-numeric-inteprolation/</link>
      <pubDate>Tue, 14 Jul 2020 19:48:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/07/14/introducing-displease-a-package-for-non-linear-numeric-inteprolation/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;displease&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;displease&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;displease&lt;/code&gt; package provides non-linear interpolation between numeric values.&lt;/p&gt;
&lt;p&gt;It is a replacement for &lt;code&gt;seq()&lt;/code&gt; for when you want a sequence between two values which is &lt;strong&gt;not&lt;/strong&gt; equally spaced.&lt;/p&gt;
&lt;p&gt;Easing can look much better than strict linear interpolation when applied to
objects moving spatially.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;displease&lt;/code&gt; = &lt;strong&gt;displ&lt;/strong&gt; + &lt;strong&gt;ease&lt;/strong&gt;. The results are often used for
animating visual &lt;strong&gt;displacement&lt;/strong&gt;, and the non-linear interpolation is
performed by applying an &lt;strong&gt;easing&lt;/strong&gt; function.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/displease&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/displease)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;seq_ease(x1, x2, n, type)&lt;/code&gt; - create a sequence of length &lt;code&gt;n&lt;/code&gt;
between &lt;code&gt;x1&lt;/code&gt; and &lt;code&gt;x2&lt;/code&gt;. Apply the easing function given by &lt;code&gt;type&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;type is one of: &lt;code&gt;sine-in&lt;/code&gt;, &lt;code&gt;sine-out&lt;/code&gt;, &lt;code&gt;sine-in-out&lt;/code&gt;, &lt;code&gt;quad-in&lt;/code&gt;, &lt;code&gt;quad-out&lt;/code&gt;, &lt;code&gt;quad-in-out&lt;/code&gt;, &lt;code&gt;cubic-in&lt;/code&gt;, &lt;code&gt;cubic-out&lt;/code&gt;, &lt;code&gt;cubic-in-out&lt;/code&gt;, &lt;code&gt;quart-in&lt;/code&gt;, &lt;code&gt;quart-out&lt;/code&gt;, &lt;code&gt;quart-in-out&lt;/code&gt;, &lt;code&gt;quint-in&lt;/code&gt;, &lt;code&gt;quint-out&lt;/code&gt;, &lt;code&gt;quint-in-out&lt;/code&gt;, &lt;code&gt;exp-in&lt;/code&gt;, &lt;code&gt;exp-out&lt;/code&gt;, &lt;code&gt;exp-in-out&lt;/code&gt;, &lt;code&gt;circle-in&lt;/code&gt;, &lt;code&gt;circle-out&lt;/code&gt;, &lt;code&gt;circle-in-out&lt;/code&gt;, &lt;code&gt;back-in&lt;/code&gt;, &lt;code&gt;back-out&lt;/code&gt;, &lt;code&gt;back-in-out&lt;/code&gt;, &lt;code&gt;elastic-in&lt;/code&gt;, &lt;code&gt;elastic-out&lt;/code&gt;, &lt;code&gt;elastic-in-out&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following graph shows the &lt;code&gt;seq_ease()&lt;/code&gt; output for &lt;code&gt;n = 100&lt;/code&gt; for
all the different easing functions with given extens of &lt;code&gt;x1 = 0&lt;/code&gt; and &lt;code&gt;x2 = 1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-13-displease-non-linear-interpolation_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(displease)

# normal linear interpolation using seq()
(y_linear       &amp;lt;- seq(1, 10, length.out = 10))
 [1]  1  2  3  4  5  6  7  8  9 10

# Non-linear interpolation using {displease}
(y_cubic_in     &amp;lt;- seq_ease(1, 10, n=10, type = &amp;#39;cubic-in&amp;#39;))
 [1]  1.000000  1.012346  1.098765  1.333333  1.790123  2.543210  3.666667
 [8]  5.234568  7.320988 10.000000
(y_cubic_in_out &amp;lt;- seq_ease(1, 10, n=10, type = &amp;#39;cubic-in-out&amp;#39;))
 [1]  1.000000  1.049383  1.395062  2.333333  4.160494  6.839506  8.666667
 [8]  9.604938  9.950617 10.000000

plot(1:10, y_linear      , type = &amp;#39;b&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-13-displease-non-linear-interpolation_files/figure-html/example-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(1:10, y_cubic_in    , type = &amp;#39;b&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-13-displease-non-linear-interpolation_files/figure-html/example-2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot(1:10, y_cubic_in_out, type = &amp;#39;b&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-13-displease-non-linear-interpolation_files/figure-html/example-3.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated example&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/displease/anim3.gif&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/thomasp85/tweenr&#34;&gt;tweenr&lt;/a&gt; is a more general purpose package
which will interpolate other types besides numeric values e.g. dates and colours.
Expected data input is data.frames, or lists of data.frames. See for example
&lt;code&gt;tweenr::tween_numeric()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;miranda&#39; - a package of fast, modern, uniform pseudo-random number generators</title>
      <link>https://coolbutuseless.github.io/2020/07/09/introducing-miranda-a-package-of-fast-modern-uniform-pseudo-random-number-generators/</link>
      <pubDate>Thu, 09 Jul 2020 22:32:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/07/09/introducing-miranda-a-package-of-fast-modern-uniform-pseudo-random-number-generators/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;miranda&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;miranda &lt;img src=&#34;https://coolbutuseless.github.io/img/miranda//miranda-logo.jpg&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;miranda&lt;/code&gt; packages includes some modern pseudo-random number generators (PRNGs). These
are up to 20x faster than the built-in PRNGs in R.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.romu-random.org/&#34;&gt;romu trio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://xorshift.di.unimi.it&#34;&gt;xoshiro256+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lemire.me/blog/2019/03/19/the-fastest-conventional-random-number-generator-that-can-pass-big-crush/&#34;&gt;Lehmer64&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://xorshift.di.unimi.it/splitmix64.c&#34;&gt;SplitMix64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;prng-summary&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;PRNG summary&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;PRNG&lt;/th&gt;
&lt;th&gt;BigCrush result&lt;/th&gt;
&lt;th&gt;Reference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;xoshiro256p&lt;/td&gt;
&lt;td&gt;“No Systematic Failures”&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;http://prng.di.unimi.it/&#34;&gt;http://prng.di.unimi.it/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;lehmer64&lt;/td&gt;
&lt;td&gt;Passes&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://lemire.me/blog/2019/03/19/the-fastest-conventional-random-number-generator-that-can-pass-big-crush/&#34;&gt;Lemire’s blog&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;splitmix64&lt;/td&gt;
&lt;td&gt;Passes&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;http://xorshift.di.unimi.it/splitmix64.c&#34;&gt;source&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;romutrio&lt;/td&gt;
&lt;td&gt;Passes&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;romu-random.org&#34;&gt;romu-random.org&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;runif() [Mersenne Twister]&lt;/td&gt;
&lt;td&gt;Two failures&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/miranda&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/miranda)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;xoshiro256p&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;xoshiro256p&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(miranda)

# Set the seed
set_seed_xoshiro256p(2020)

# Get the internal state of the generator. 32 bytes.
(state &amp;lt;- get_state_xoshiro256p())
 [1] ee 6d 45 f5 0b 1c e9 8e 81 89 5b 6b ee ca 13 07 d9 3f 76 fe 13 4f c2 33 44
[26] 3c a9 de 5e b7 56 f9

# Generate some uniform random numbers from xoshiro256+
runif_xoshiro256p(5)
[1] 0.5322239 0.7788869 0.4601653 0.8475389 0.9540731

# Jump ahead. As if 2^128 numbers had been generated
jump_xoshiro256p()

# Generate some uniform random numbers from xoshiro256+
runif_xoshiro256p(5)
[1] 0.5714143 0.5006207 0.6907487 0.2625934 0.5053289

# reset the state to a prior value
set_state_xoshiro256p(state)

# Generate some uniform random numbers from xoshiro256+
runif_xoshiro256p(5)
[1] 0.5322239 0.7788869 0.4601653 0.8475389 0.9540731&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark-generating-1-million-uniform-random-numbers&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Benchmark: Generating 1 million uniform random numbers&lt;/h1&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide bench::mark() code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 1e6
res &amp;lt;- bench::mark(
  runif_xoshiro256p(N),
  runif_lehmer64(N),
  runif_splitmix64(N),
  runif_romutrio(N),
  runif(N),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-09-miranda-modern-prngs_files/figure-html/bench-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The PRNGs in this package all roughly run at the same speed&lt;/li&gt;
&lt;li&gt;At their best, these PRNGs are about &lt;strong&gt;20x faster&lt;/strong&gt; than &lt;code&gt;runif()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=dqrng&#34;&gt;dqrng&lt;/a&gt; - Fast PRNGs (xoshiro, PCG)
with an interface compatible with &lt;code&gt;runif()&lt;/code&gt;. Also supplies &lt;code&gt;rnorm()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=random&#34;&gt;random&lt;/a&gt; a package for true random
numbers fetched from &lt;a href=&#34;random.org&#34;&gt;random.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>The quality of R&#39;s Random Number Generators</title>
      <link>https://coolbutuseless.github.io/2020/07/07/the-quality-of-rs-random-number-generators/</link>
      <pubDate>Tue, 07 Jul 2020 21:02:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/07/07/the-quality-of-rs-random-number-generators/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;a-mini-exploration-of-the-quality-rs-random-number-generators.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;A mini-exploration of the quality R’s random number generators.&lt;/h1&gt;
&lt;p&gt;In general, we want &lt;em&gt;pseudo-random number generators&lt;/em&gt; (&lt;strong&gt;PRNG&lt;/strong&gt;s) which have (among other things) 2 key properties:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;They should be random&lt;/li&gt;
&lt;li&gt;They should be fast&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are other considerations (e.g. period, availability of multiple streams, jump-aheads etc),
but I’m not going there (nor am I considering cryptographic security).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;rs-built-in-prngs&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;R’s built-in PRNGs&lt;/h1&gt;
&lt;p&gt;R has 7 built-in PRNGs. These are accessible by calling &lt;code&gt;RNGkind(name)&lt;/code&gt; to
switch the backend to use a particular PRNG. The user-facing code
remains the same e.g. &lt;code&gt;runif()&lt;/code&gt;, &lt;code&gt;rnorm()&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mersenne-Twister&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The default PRNG in R&lt;/li&gt;
&lt;li&gt;Also known as: MT19937&lt;/li&gt;
&lt;li&gt;Developed by: Matsumoto and Nishimura, 1997&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wichmann-Hill&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;A combined linear congruential generator (LCG)&lt;/li&gt;
&lt;li&gt;Developed by: Wichman and Hill, 1982&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Marsaglia-Multicarry&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Developed by: Marsaglia, 1997&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Super-Duper&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Developed by: Marsaglia in the 70s&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knuth-TAOCP-2002&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;generalized feedback shift-register generator (GFSR) using lagged Fibonacci sequences&lt;/li&gt;
&lt;li&gt;Developed by: Knuth, 2002&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knuth-TAOCP&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Another GFSR using using lagged Fibonacci sequences&lt;/li&gt;
&lt;li&gt;Developed by: Knuth, 1997&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L’Ecuyer-CMRG&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;A combined multiple recursive generator&lt;/li&gt;
&lt;li&gt;Developed by: L’Ecuyer, 1999&lt;/li&gt;
&lt;li&gt;Defined in this paper &lt;a href=&#34;https://www.iro.umontreal.ca/~lecuyer/myftp/papers/opres-combmrg2-1999.pdf&#34;&gt;Good Parameters and Implementations for Combined Multiple Recursive Random Number Generators (pdf)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Also known as: MRG32ka&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;testing-built-in-prngs-for-quality&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Testing built-in PRNGs for quality&lt;/h1&gt;
&lt;p&gt;A 2007 paper which reviews many PRNGs and tests then for quality is L’Ecuyer’s &lt;a href=&#34;http://www.iro.umontreal.ca/~lecuyer/myftp/papers/testu01.pdf&#34;&gt;TestU01: A C Library for Empirical Testing of Random Number Generators (pdf)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’ve summarised Table 1 from this paper for the PRNGs which are available in base R. In this
summary I only include the BigCrush numbers.
The full version of Table 1 is included at the end of this post;&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;4%&#34; /&gt;
&lt;col width=&#34;19%&#34; /&gt;
&lt;col width=&#34;16%&#34; /&gt;
&lt;col width=&#34;59%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;RNGkind&lt;/th&gt;
&lt;th&gt;Alias&lt;/th&gt;
&lt;th&gt;Big Crush Errors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;1970s&lt;/td&gt;
&lt;td&gt;Super Duper&lt;/td&gt;
&lt;td&gt;Super Duper 73&lt;/td&gt;
&lt;td&gt;Test not run as there were too many errors already at lower levels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;1982&lt;/td&gt;
&lt;td&gt;Wichmann-Hill&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;1997&lt;/td&gt;
&lt;td&gt;Mersenne Twister&lt;/td&gt;
&lt;td&gt;MT19937&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;1997&lt;/td&gt;
&lt;td&gt;Marsaglia-Multicarry&lt;/td&gt;
&lt;td&gt;R-Multicarry&lt;/td&gt;
&lt;td&gt;Test not run as there were too many errors already at lower levels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;1997&lt;/td&gt;
&lt;td&gt;Knuth-TAOCP&lt;/td&gt;
&lt;td&gt;Knuth.ran_array2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;1999&lt;/td&gt;
&lt;td&gt;L’Ecuyer-CMRG&lt;/td&gt;
&lt;td&gt;MRG32k3a&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;2002&lt;/td&gt;
&lt;td&gt;Knuth-TAOCP-2002&lt;/td&gt;
&lt;td&gt;Knuth.ranf_array2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;notes-on-built-in-prng-quality&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Notes on built-in PRNG quality:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;R’s default PRNG (Mersenne-Twister) fails 2 test on BigCrush&lt;/li&gt;
&lt;li&gt;Only L’Ecuyer and Knuth-TAOCP-2002 pass the BigCrush tests with no failures&lt;/li&gt;
&lt;li&gt;The other PRNGs seem to perform quite badly with either multiple failures on BigCrush, or
so many failures on &lt;em&gt;SmallCrush&lt;/em&gt; and &lt;em&gt;Crush&lt;/em&gt; that it wasn’t even worth
testing then on &lt;em&gt;BigCrush&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;There appears to be a trend that more recent PRNGs have fewer failures on &lt;em&gt;BigCrush&lt;/em&gt;.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The most recent PRNG is &lt;strong&gt;18 years old&lt;/strong&gt;! What’s happened since then in PRNG development?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;testing-built-in-prngs-for-speed&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Testing built-in PRNGs for speed&lt;/h1&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(bench)

rng_kinds &amp;lt;- c( 
  &amp;#39;Mersenne-Twister&amp;#39;,   
  &amp;#39;Wichmann-Hill&amp;#39;,        
  &amp;#39;Marsaglia-Multicarry&amp;#39;, 
  &amp;#39;Super-Duper&amp;#39;,           
  &amp;#39;Knuth-TAOCP-2002&amp;#39;,     
  &amp;#39;Knuth-TAOCP&amp;#39;,          
  &amp;quot;L&amp;#39;Ecuyer-CMRG&amp;quot;         
  )

N &amp;lt;- 1e6

fun &amp;lt;- function(rng_kind) {
  RNGkind(kind = rng_kind)
  res &amp;lt;- bench::mark(runif(N))
  res$expression &amp;lt;- rng_kind
  res
}

baser &amp;lt;- lapply(rng_kinds, fun)
baser &amp;lt;- do.call(rbind, baser)

plot(baser) + 
  labs(title = &amp;quot;Benchmark: runif() generation of 1e6 random numbers&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-07-07-the-quality-of-random-numbers-in-R_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;notes-on-built-in-prng-speed&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Notes on built-in PRNG speed:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;All the built-in PRNGs are about the same speed&lt;/li&gt;
&lt;li&gt;Not sure if this is a characteristic of the way they are included within R - there may
be a lot of setup/call overhead that is overshadowing the timing of the
actual random number generation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-full-prng-comparison-table.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appendix: Full PRNG comparison table.&lt;/h1&gt;
&lt;p&gt;This is an extract from L’Ecuyer’s &lt;a href=&#34;http://www.iro.umontreal.ca/~lecuyer/myftp/papers/testu01.pdf&#34;&gt;TestU01: A C Library for Empirical Testing of Random Number Generators (pdf)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;How to read this table:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The numbers in the last 3 rows are the number of &lt;strong&gt;failures&lt;/strong&gt; for a particular
statistical test i.e. SmallCrush, Crush and BigCrush.
&lt;ul&gt;
&lt;li&gt;A number in brackets e.g. &lt;code&gt;(12)&lt;/code&gt; indicates a &lt;em&gt;suspect&lt;/em&gt; p-value, but
not necessarily a failure.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The second column is the log2 of the period of the generator (how long before it
loops back to the start)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t-32&lt;/code&gt; and &lt;code&gt;t-64&lt;/code&gt; are the times to generate 10^8 random numbers on a 32 and 64-bit
machine (see the paper for actual specs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/random/page1.png&#34; width=&#34;100%&#34; /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/random/page2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-other-resources&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appendix: Other resources:&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Correction to random number generation in R3.6.0 - &lt;a href=&#34;https://www.stat.berkeley.edu/~stark/Preprints/r-random-issues.pdf&#34;&gt;here&lt;/a&gt; and
&lt;a href=&#34;https://www.r-bloggers.com/whats-new-in-r-3-6-0/&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;John Cook looks at few modern PRNGs in his &lt;a href=&#34;https://www.johndcook.com/blog/2017/08/14/testing-rngs-with-practrand/&#34;&gt;2017 blog post Testing RNGs with PractRand&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.pcg-random.org/&#34;&gt;PCG PRNG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Some criticism on the claims around PCG - &lt;a href=&#34;http://pcg.di.unimi.it/pcg.php&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf&#34;&gt;Good Practice in (Pseudo) Random Number Generationfor Bioinformatics Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing terse - a package for compact output of lists and data.frames</title>
      <link>https://coolbutuseless.github.io/2020/07/01/introducing-terse-a-package-for-compact-output-of-lists-and-data.frames/</link>
      <pubDate>Wed, 01 Jul 2020 22:32:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/07/01/introducing-terse-a-package-for-compact-output-of-lists-and-data.frames/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;terse&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;terse&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;terse&lt;/code&gt; is an alternative to &lt;code&gt;str()&lt;/code&gt; that aims to be more succinct for simple
objects.&lt;/p&gt;
&lt;p&gt;It was built with (nested) &lt;code&gt;list&lt;/code&gt; output in mind, but handles &lt;code&gt;data.frames&lt;/code&gt; and many
other standard data structures in R.&lt;/p&gt;
&lt;div id=&#34;features&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Features&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compact output&lt;/li&gt;
&lt;li&gt;ANSI colour (configurable)&lt;/li&gt;
&lt;li&gt;Alignment of indexes at start of each row, such that names at the same
depth are aligned under each other&lt;/li&gt;
&lt;li&gt;Alignment of values within data.frames&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Currently supports the standard vector types and lists&lt;/li&gt;
&lt;li&gt;Lists are always recursed in to (there is currently no option to limit the recursion depth)&lt;/li&gt;
&lt;li&gt;Weirder data structures might not work how you want - e.g. list-columns in
data.frames, R6 objects etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you find a common case that doesn’t produce nice output, please file an issue
(or PR!).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/terse&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/terse&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;terse-data.frame-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Terse &lt;code&gt;data.frame&lt;/code&gt; output&lt;/h2&gt;
&lt;p&gt;Simple data.frame output&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(terse)
terse(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/terse/mtcars.png&#34; width=&#34;100%&#34; &gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary style=&#39;color: blue;&#39;&gt; Click here to show/hide - Comparison to str() and glimpse()&lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;#39;data.frame&amp;#39;:   32 obs. of  11 variables:
 $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
 $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
 $ disp: num  160 160 108 258 360 ...
 $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
 $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
 $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
 $ qsec: num  16.5 17 18.6 19.4 17 ...
 $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
 $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
 $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dplyr::glimpse(mtcars)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Rows: 32
Columns: 11
$ mpg  &amp;lt;dbl&amp;gt; 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8…
$ cyl  &amp;lt;dbl&amp;gt; 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8…
$ disp &amp;lt;dbl&amp;gt; 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 1…
$ hp   &amp;lt;dbl&amp;gt; 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 18…
$ drat &amp;lt;dbl&amp;gt; 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92…
$ wt   &amp;lt;dbl&amp;gt; 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3…
$ qsec &amp;lt;dbl&amp;gt; 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 1…
$ vs   &amp;lt;dbl&amp;gt; 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0…
$ am   &amp;lt;dbl&amp;gt; 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0…
$ gear &amp;lt;dbl&amp;gt; 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3…
$ carb &amp;lt;dbl&amp;gt; 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2…&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;terse-data.frame-output---plain-ascii&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Terse &lt;code&gt;data.frame&lt;/code&gt; output - plain ASCII&lt;/h2&gt;
&lt;p&gt;Simple data.frame output without ANSI&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;terse(mtcars, config = list(ansi = FALSE), width = 100)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;mtcars$mpg  d32 21   , 21   , 22.8 , 21.4 , 18.7 , 18.1 , 14.3 , 24.4 , 22.8 , 19.2 , 17.8 , 16 ...
mtcars$cyl  d32 6    , 6    , 4    , 6    , 8    , 6    , 8    , 4    , 4    , 6    , 6    , 8  ...
mtcars$disp d32 160  , 160  , 108  , 258  , 360  , 225  , 360  , 146.7, 140.8, 167.6, 167.6, 27 ...
mtcars$hp   d32 110  , 110  , 93   , 110  , 175  , 105  , 245  , 62   , 95   , 123  , 123  , 18 ...
mtcars$drat d32 3.9  , 3.9  , 3.85 , 3.08 , 3.15 , 2.76 , 3.21 , 3.69 , 3.92 , 3.92 , 3.92 , 3. ...
mtcars$wt   d32 2.62 , 2.875, 2.32 , 3.215, 3.44 , 3.46 , 3.57 , 3.19 , 3.15 , 3.44 , 3.44 , 4. ...
mtcars$qsec d32 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20   , 22.9 , 18.3 , 18.9 , 17 ...
mtcars$vs   d32 0    , 0    , 1    , 1    , 0    , 1    , 0    , 1    , 1    , 1    , 1    , 0  ...
mtcars$am   d32 1    , 1    , 1    , 0    , 0    , 0    , 0    , 0    , 0    , 0    , 0    , 0  ...
mtcars$gear d32 4    , 4    , 4    , 3    , 3    , 3    , 3    , 4    , 4    , 4    , 4    , 3  ...
mtcars$carb d32 4    , 4    , 1    , 1    , 2    , 1    , 4    , 2    , 2    , 4    , 4    , 3  ...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;terse-nested-list-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Terse nested &lt;code&gt;list&lt;/code&gt; output&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ll &amp;lt;- list(
  apple = list(
    bob = list(c = 1:3),
    c = list(
      list(d = head(mtcars))
    ),
    ddd = setNames(1:26, letters)
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;terse(ll, config = list(nth = 4, colour_nth = &amp;#39;red&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/terse/ll.png&#34; width=&#34;100%&#34; &gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary style=&#39;color: blue;&#39;&gt; Click here to show/hide - Comparison to str() &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;str(ll)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;List of 1
 $ apple:List of 3
  ..$ bob:List of 1
  .. ..$ c: int [1:3] 1 2 3
  ..$ c  :List of 1
  .. ..$ :List of 1
  .. .. ..$ d:&amp;#39;data.frame&amp;#39;: 6 obs. of  11 variables:
  .. .. .. ..$ mpg : num [1:6] 21 21 22.8 21.4 18.7 18.1
  .. .. .. ..$ cyl : num [1:6] 6 6 4 6 8 6
  .. .. .. ..$ disp: num [1:6] 160 160 108 258 360 225
  .. .. .. ..$ hp  : num [1:6] 110 110 93 110 175 105
  .. .. .. ..$ drat: num [1:6] 3.9 3.9 3.85 3.08 3.15 2.76
  .. .. .. ..$ wt  : num [1:6] 2.62 2.88 2.32 3.21 3.44 ...
  .. .. .. ..$ qsec: num [1:6] 16.5 17 18.6 19.4 17 ...
  .. .. .. ..$ vs  : num [1:6] 0 0 1 1 0 1
  .. .. .. ..$ am  : num [1:6] 1 1 1 0 0 0
  .. .. .. ..$ gear: num [1:6] 4 4 4 3 3 3
  .. .. .. ..$ carb: num [1:6] 4 4 1 1 2 1
  ..$ ddd: Named int [1:26] 1 2 3 4 5 6 7 8 9 10 ...
  .. ..- attr(*, &amp;quot;names&amp;quot;)= chr [1:26] &amp;quot;a&amp;quot; &amp;quot;b&amp;quot; &amp;quot;c&amp;quot; &amp;quot;d&amp;quot; ...&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;notes-on-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes on output&lt;/h2&gt;
&lt;p&gt;The output consists of 3 sections:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Names and indices (on the left)&lt;/li&gt;
&lt;li&gt;Compact type + length information&lt;/li&gt;
&lt;li&gt;Vectors of values (on the right)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The green output consists of a single character for type information, followed
by a length (the number of elements in this vector)&lt;/p&gt;
&lt;details open&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide list of all type information &lt;/summary&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;a&lt;/strong&gt; - array&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;m&lt;/strong&gt; - matrix&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;l&lt;/strong&gt; - logical&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;f&lt;/strong&gt; - factor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;p&lt;/strong&gt; - POSIXct&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P&lt;/strong&gt; - POSIXlt&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;D&lt;/strong&gt; - Date&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;n&lt;/strong&gt; - name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;i&lt;/strong&gt; - integer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d&lt;/strong&gt; - double&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;r&lt;/strong&gt; - raw&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;c&lt;/strong&gt; - character&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C&lt;/strong&gt; - complex&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;N&lt;/strong&gt; - null&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K&lt;/strong&gt; - call&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;F&lt;/strong&gt; - function&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E&lt;/strong&gt; - environment&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;e&lt;/strong&gt; - expression&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L&lt;/strong&gt; - list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;x&lt;/strong&gt; - unknown&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;config&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Config&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;terse()&lt;/code&gt; takes a &lt;code&gt;config&lt;/code&gt; argument which must be a named list. Possible elements
are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ansi&lt;/code&gt; - Use ANSI colouring? default: &lt;code&gt;TRUE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;soft&lt;/code&gt; - non-highlight colour. default: &lt;code&gt;grey40&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gsep&lt;/code&gt; - separator for vector output. default: &lt;code&gt;,&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colour_nth&lt;/code&gt; - colour for every nth vector element. default: &lt;code&gt;blue4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colour_all&lt;/code&gt; - colour for all other vector elements. default: &lt;code&gt;grey40&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colour_type&lt;/code&gt; - colour for the type/length meta information. default: &lt;code&gt;seagreen&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nth&lt;/code&gt; - interval for colouring vector elements. default: &lt;code&gt;0&lt;/code&gt; (off)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Base R &lt;a href=&#34;&#34;&gt;utils::str()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;&#34;&gt;dplyr::glimpse()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core &amp;amp; CRAN maintainers for giving me a playground&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;Brodie Gaslam&lt;/a&gt; for the excellent ANSI tools in &lt;a href=&#34;https://cran.r-project.org/package=fansi&#34;&gt;fansi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/dmi3k&#34;&gt;Deemah&lt;/a&gt; and
&lt;a href=&#34;https://twitter.com/carroll_jono&#34;&gt;Jonathan Carroll&lt;/a&gt; for helping me find a
good name&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>simplec, simplecall, simplercpp - demo packages incorporating C code</title>
      <link>https://coolbutuseless.github.io/2020/06/30/simplec-simplecall-simplercpp-demo-packages-incorporating-c-code/</link>
      <pubDate>Tue, 30 Jun 2020 20:32:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/06/30/simplec-simplecall-simplercpp-demo-packages-incorporating-c-code/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;demo-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;3 demo packages&lt;/h2&gt;
&lt;p&gt;In the process of working out how to best call C code in an R package, I
created 3 small demonstration packages showing how C code can be included
and called within a package.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplec&#34;&gt;&lt;code&gt;simplec&lt;/code&gt;&lt;/a&gt; A package using &lt;code&gt;.C()&lt;/code&gt; to interface with C code&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplecall&#34;&gt;&lt;code&gt;simplecall&lt;/code&gt;&lt;/a&gt; A package using &lt;code&gt;.Call()&lt;/code&gt; to interface with C code&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplercpp&#34;&gt;&lt;code&gt;simplercpp&lt;/code&gt;&lt;/a&gt; A package using &lt;code&gt;{Rcpp}&lt;/code&gt; to interface with C code&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;rough-comparison-of-.c-.call-and-rcpp&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rough comparison of &lt;code&gt;.C()&lt;/code&gt;, &lt;code&gt;.Call()&lt;/code&gt; and &lt;code&gt;{Rcpp}&lt;/code&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;8%&#34; /&gt;
&lt;col width=&#34;28%&#34; /&gt;
&lt;col width=&#34;31%&#34; /&gt;
&lt;col width=&#34;31%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;.C()&lt;/th&gt;
&lt;th&gt;.Call()&lt;/th&gt;
&lt;th&gt;Rcpp&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Overview&lt;/td&gt;
&lt;td&gt;No real understanding of R objects&lt;/td&gt;
&lt;td&gt;Need to understand SEXP macros &amp;amp; internals&lt;/td&gt;
&lt;td&gt;C++ classes hide the complexity of the SEXP internals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;What code?&lt;/td&gt;
&lt;td&gt;Basic C code. Numeric calcs.&lt;/td&gt;
&lt;td&gt;Complex C code. Can manipulate R objects from C&lt;/td&gt;
&lt;td&gt;Complex C and C++ code involving numerics and R objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Pros&lt;/td&gt;
&lt;td&gt;Simple to understand and use&lt;/td&gt;
&lt;td&gt;Simple. No unnecessary copying.&lt;/td&gt;
&lt;td&gt;Great documentation. Wrapping of R objects very intuitive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Cons&lt;/td&gt;
&lt;td&gt;Too simple for most interesting things&lt;/td&gt;
&lt;td&gt;Need to understand SEXP &amp;amp; R internals&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Cons&lt;/td&gt;
&lt;td&gt;Performs copying of data to call functions&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Demo R package&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplec&#34;&gt;{simplec}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplecall&#34;&gt;{simplecall}&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://github.com/coolbutuseless/simplercpp&#34;&gt;{simplercpp}&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;zstdlite&#39; - fast, configurable, in-memory compression of numeric vectors with Zstandard</title>
      <link>https://coolbutuseless.github.io/2020/06/19/introducing-zstdlite-fast-configurable-in-memory-compression-of-numeric-vectors-with-zstandard/</link>
      <pubDate>Fri, 19 Jun 2020 21:42:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/06/19/introducing-zstdlite-fast-configurable-in-memory-compression-of-numeric-vectors-with-zstandard/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;zstdlite&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;zstdlite&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zstdlite&lt;/code&gt; provides access to the very fast (and highly configurable) compression
in &lt;a href=&#34;https://github.com/facebook/zstd&#34;&gt;zstd&lt;/a&gt; for performing in-memory compression.&lt;/p&gt;
&lt;p&gt;The scope of this package is limited - it aims to provide functions for direct hashing of vectors
which contain raw, integer, real, complex or logical values. It does this by operating on the
data payload within the vectors, and gains significant speed by not serializing the R object
itself. If you wanted to
compress arbitrary R objects, you must first manually convert into a raw
vector representation using &lt;code&gt;base::serialize()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For a more general solution to fast serialization of R objects, see the
&lt;a href=&#34;https://github.com/fstpackage/fst&#34;&gt;fst&lt;/a&gt; or &lt;a href=&#34;https://cran.r-project.org/package=qs&#34;&gt;qs&lt;/a&gt; packages.&lt;/p&gt;
&lt;p&gt;Currently zstd code provided with this package is v1.4.5.&lt;/p&gt;
&lt;div id=&#34;design-choices&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Design Choices&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;zstdlite&lt;/code&gt; will compress the &lt;em&gt;data payload&lt;/em&gt; within a numeric-ish vector, and not the
R object itself.&lt;/p&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Limitations&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;As it is the &lt;em&gt;data payload&lt;/em&gt; of the vector that is being compressed, this
does not include any notion of the container for that data i.e
dimensions or other attributes are not compressed with the data.&lt;/li&gt;
&lt;li&gt;Values must be of type: raw, integer, real, complex or logical.&lt;/li&gt;
&lt;li&gt;Decompressed values are always returned as a vector i.e. all dimensional
information is lost during compression.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/zstdlite&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/zstdlite)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;compressing-1-million-integers&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compressing 1 million Integers&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;zstdlite&lt;/code&gt; supports the direct compression of raw, integer, real, complex and logical vectors.&lt;/p&gt;
&lt;p&gt;These vectors do not need to be serialized first to a raw representation, instead
the data-payload within these vectors is compressed.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(zstdlite)
library(lz4lite)

N                 &amp;lt;- 1e6
input_ints        &amp;lt;- sample(1:5, N, prob = (1:5)^2, replace = TRUE)
compressed_lo     &amp;lt;- zstd_compress(input_ints)
compressed_hi     &amp;lt;- zstd_compress(input_ints, level = 100)
compressed_lo_lz4 &amp;lt;- lz4_compress(input_ints, acc = 1)
compressed_hi_lz4 &amp;lt;- lz4_compress(input_ints, use_hc = TRUE, hc_level = 12)&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(zstdlite)

res &amp;lt;- bench::mark(
  zstd_compress(input_ints, level =  -5),
  zstd_compress(input_ints, level =   1),
  zstd_compress(input_ints, level =   3),
  zstd_compress(input_ints, level =  10),
  zstd_compress(input_ints, level =  22),
  lz4_compress (input_ints, acc = 1),
  lz4_compress (input_ints, use_hc = TRUE, hc_level = 12),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB/s&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;compression_ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_compress(input_ints, level = -5)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.29ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;266.9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_compress(input_ints, level = 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.5ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;263.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.131&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_compress(input_ints, level = 3)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.28ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;70&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;267.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.131&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_compress(input_ints, level = 10)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;87.92ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;43.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.106&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_compress(input_ints, level = 22)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.33s&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.075&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4lite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.4ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;158&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;596.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4lite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 12)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.87s&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.122&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;decompressing-1-million-integers&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Decompressing 1 million integers&lt;/h3&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- bench::mark(
  zstd_decompress(compressed_lo),
  zstd_decompress(compressed_hi),
  lz4_decompress(compressed_lo_lz4),
  lz4_decompress(compressed_hi_lz4),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_decompress(compressed_lo)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.98ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;121&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;477.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstdlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;zstd_decompress(compressed_hi)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.38ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;414&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1603.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4lite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lz4_decompress(compressed_lo_lz4)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.53ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;651&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2492.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4lite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lz4_decompress(compressed_hi_lz4)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.14ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;863&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3333.9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical bits&lt;/h2&gt;
&lt;div id=&#34;why-only-vectors-of-raw-integer-real-complex-or-logical&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Why only vectors of raw, integer, real, complex or logical?&lt;/h3&gt;
&lt;p&gt;R objects can be considered to consist of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a header - giving information like length and information for the garbage collector&lt;/li&gt;
&lt;li&gt;a body - data of some kind.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The vectors supported by &lt;code&gt;zstdlite&lt;/code&gt; are those vectors whose body consists of
data that is directly interpretable as a contiguous sequence of bytes representing
numerical values.&lt;/p&gt;
&lt;p&gt;Other R objects (like lists or character vectors) are really collections of pointers
to other objects, and do not live in memory as a contiguous sequence of byte data.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;how-it-works.&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;How it works.&lt;/h3&gt;
&lt;div id=&#34;compression&#34; class=&#34;section level5&#34;&gt;
&lt;h5&gt;Compression&lt;/h5&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Given a pointer to a standard numeric vector from R (i.e. an &lt;em&gt;SEXP&lt;/em&gt; pointer).&lt;/li&gt;
&lt;li&gt;Ignore any attributes or dimension information- just compress the data payload within
the object.&lt;/li&gt;
&lt;li&gt;Prefix the compressed data with an 4 byte header giving the SEXP type.&lt;/li&gt;
&lt;li&gt;Return a raw vector to the user containing the compressed bytes.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;decompression&#34; class=&#34;section level5&#34;&gt;
&lt;h5&gt;Decompression&lt;/h5&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Strip off the 4-bytes of header information.&lt;/li&gt;
&lt;li&gt;Feed the other bytes in to the ZSTD decompression function written in C&lt;/li&gt;
&lt;li&gt;Use the header to decide what sort of R object this is.&lt;/li&gt;
&lt;li&gt;Decompress the data into an R object of the correct type.&lt;/li&gt;
&lt;li&gt;Return the R object to the user.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; matrices and arrays may also be passed to &lt;code&gt;zstd_compress()&lt;/code&gt;, but since
no attributes are retained (e.g. dims), the uncompressed object
returned by &lt;code&gt;zstd_decompress()&lt;/code&gt; can only be a simple vector.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;framing-of-the-compressed-data&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Framing of the compressed data&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;zstdlite&lt;/code&gt; prefixes the standard Zstandard frame with some extra bytes.&lt;/li&gt;
&lt;li&gt;The compressed representation is the compressed data prefixed with
a custom 8 byte header consisting of
&lt;ul&gt;
&lt;li&gt;‘ZST’&lt;/li&gt;
&lt;li&gt;1-byte for SEXP type i.e. INTSXP, RAWSXP, REALSXP or LGLSXP&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;This data representation
&lt;ul&gt;
&lt;li&gt;is compatible with the standard Zstandard frame
format if the leading bytes are removed.&lt;/li&gt;
&lt;li&gt;is likely to evolve (so currently do not plan on compressing something in
one version of &lt;code&gt;zstdlite&lt;/code&gt; and decompressing in another version.)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/lz4/lz4&#34;&gt;lz4&lt;/a&gt; and &lt;a href=&#34;https://github.com/facebook/zstd&#34;&gt;zstd&lt;/a&gt; - both by Yann Collet&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/fstpackage/fst&#34;&gt;fst&lt;/a&gt; for serialisation of data.frames using
lz4 and zstd&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=qs&#34;&gt;qs&lt;/a&gt; for fast serialization of arbitrary R objects
with lz4 and zstd&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yann Collett for releasing, maintaining and advancing
&lt;a href=&#34;https://github.com/lz4/lz4&#34;&gt;lz4&lt;/a&gt; and &lt;a href=&#34;https://github.com/facebook/zstd&#34;&gt;zstd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;lz4lite&#39; - extremely fast compression with LZ4</title>
      <link>https://coolbutuseless.github.io/2020/06/16/introducing-lz4lite-extremely-fast-compression-with-lz4/</link>
      <pubDate>Tue, 16 Jun 2020 20:22:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/06/16/introducing-lz4lite-extremely-fast-compression-with-lz4/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;lz4lite&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;lz4lite&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lz4lite&lt;/code&gt; provides access to the extremely fast compression in &lt;a href=&#34;https://github.com/lz4/lz4&#34;&gt;lz4&lt;/a&gt;
for performing in-memory compression.&lt;/p&gt;
&lt;p&gt;The scope of this package is limited - it aims to provide functions for direct hashing of vectors
which contain raw, integer, real or logical values. If you wanted to
compress arbitrary R objects, you must first convert into a raw
vector representation using &lt;code&gt;base::serialize()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For a more general solution to fast serialization of R objects, see the
&lt;a href=&#34;https://github.com/fstpackage/fst&#34;&gt;fst&lt;/a&gt; or &lt;a href=&#34;https://cran.r-project.org/package=qs&#34;&gt;qs&lt;/a&gt; packages.&lt;/p&gt;
&lt;p&gt;Currently lz4 code provided with this package is v1.9.3.&lt;/p&gt;
&lt;div id=&#34;design-choices&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Design Choices&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;lz4lite&lt;/code&gt; will compress the &lt;em&gt;data payload&lt;/em&gt; within a numeric-ish vector, and not the
R object itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;As it is the &lt;em&gt;data payload&lt;/em&gt; of the vector that is being compressed, this
does not include any notion of the container for that data i.e
dimensions or other attributes are not compressed with the data.&lt;/li&gt;
&lt;li&gt;Values must be of type: raw, integer, real or logical.&lt;/li&gt;
&lt;li&gt;Decompressed values are always returned as a vector i.e. all dimensional
information is lost during compression.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;What’s in the box&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lz4compress()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;compress the data within a vector of raw, integer, real or logical values&lt;/li&gt;
&lt;li&gt;set &lt;code&gt;use_hc = TRUE&lt;/code&gt; to use the High Compression variant of LZ4. This
variant can be slow to compress, but with higher compression ratios,
and it retains the fast decompression speed i.e. multiple gigabytes per second!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lz4decompress()&lt;/code&gt; - decompress a compressed representation that was created with
&lt;code&gt;lz4compress()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/lz4lite&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/lz4lite)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;compressing-1-million-integers&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compressing 1 million Integers&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;lz4lite&lt;/code&gt; supports the direct compression of raw, integer, real and logical vectors.&lt;/p&gt;
&lt;p&gt;On this test data, compression speed is ~600 MB/s, and decompression speed is ~3GB/s&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(lz4lite)

N             &amp;lt;- 1e6
input_ints    &amp;lt;- (sample(seq(1:5), N, prob = (1:5)^2, replace = TRUE))
compressed_lo &amp;lt;- lz4_compress(input_ints)
compressed_hi &amp;lt;- lz4_compress(input_ints, use_hc = TRUE, hc_level = 12)&lt;/code&gt;&lt;/pre&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(lz4lite)

res &amp;lt;- bench::mark(
  lz4_compress(input_ints, acc   =   1),
  lz4_compress(input_ints, acc   =  10),
  lz4_compress(input_ints, acc   =  20),
  lz4_compress(input_ints, acc   =  50),
  lz4_compress(input_ints, acc   = 100),
  lz4_compress(input_ints, use_hc = TRUE, hc_level =   1),
  lz4_compress(input_ints, use_hc = TRUE, hc_level =   2),
  lz4_compress(input_ints, use_hc = TRUE, hc_level =   4),
  lz4_compress(input_ints, use_hc = TRUE, hc_level =   8),
  lz4_compress(input_ints, use_hc = TRUE, hc_level =  12),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB/s&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;compression_ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.36ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;157&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;599.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 10)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.19ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;162&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;616.6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 20)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.11ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;163&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;624.5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 50)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.13ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;162&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;622.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, acc = 100)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.19ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;163&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;616.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.306&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34.38ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;110.9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.294&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 2)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;33.76ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.294&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 4)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;67.82ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;56.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.233&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 8)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;453.89ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.167&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_compress(input_ints, use_hc = TRUE, hc_level = 12)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.34s&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.122&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;decompressing-1-million-integers&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Decompressing 1 million integers&lt;/h3&gt;
&lt;p&gt;Decompression speed varies slightly depending upon the compressed size.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- bench::mark(
  lz4_decompress(compressed_lo),
  lz4_decompress(compressed_hi)
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;MB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_decompress(compressed_lo)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.52ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;633&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2504.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4_decompress(compressed_hi)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.14ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;897&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3349.9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;technical-bits&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Technical bits&lt;/h2&gt;
&lt;div id=&#34;how-it-works.&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;How it works.&lt;/h3&gt;
&lt;div id=&#34;compression&#34; class=&#34;section level5&#34;&gt;
&lt;h5&gt;Compression&lt;/h5&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Given a pointer to a standard numeric vector from R, an &lt;em&gt;SEXP&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Ignoring any attributes or dimensions, compress the data payload within
the object.&lt;/li&gt;
&lt;li&gt;Prefix the compressed data with an 8 byte header giving size and SEXP type&lt;/li&gt;
&lt;li&gt;Return a raw vector to the user containing the compressed bytes.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;decompression&#34; class=&#34;section level5&#34;&gt;
&lt;h5&gt;Decompression&lt;/h5&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Strip off the header information&lt;/li&gt;
&lt;li&gt;Feed the raw bytes in to the C LZ4 decompression function&lt;/li&gt;
&lt;li&gt;Use the header to decide what sort of R object this is&lt;/li&gt;
&lt;li&gt;Uncompress the data into an R object of the correct type.&lt;/li&gt;
&lt;li&gt;Return the R object to the user&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; matrices and arrays may also be passed to &lt;code&gt;lz4_compress()&lt;/code&gt;, but since
no attributes are retained (e.g. dims), the uncompressed object
returned by &lt;code&gt;lz4_decompress()&lt;/code&gt; can only be a simple vector.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;framing-of-the-compressed-data&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Framing of the compressed data&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lz4lite&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; use the standard LZ4 frame to store data.&lt;/li&gt;
&lt;li&gt;The compressed representation is the compressed data prefixed with
a custom 8 byte header consisting of
&lt;ul&gt;
&lt;li&gt;‘LZ4’&lt;/li&gt;
&lt;li&gt;1-byte for SEXP type i.e. INTSXP, RAWSXP, REALSXP or LGLSXP&lt;/li&gt;
&lt;li&gt;4-bytes representing an integer i.e. the number of bytes in the
original uncompressed data.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;This data representation
&lt;ul&gt;
&lt;li&gt;is not compatible with the standard LZ4 frame
format.&lt;/li&gt;
&lt;li&gt;is likely to evolve (so currently do not plan on compressing something in
one version of &lt;code&gt;lz4lite&lt;/code&gt; and decompressing in another version).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/lz4/lz4&#34;&gt;lz4&lt;/a&gt; and &lt;a href=&#34;https://github.com/facebook/zstd&#34;&gt;zstd&lt;/a&gt; - both by Yann Collet&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/fstpackage/fst&#34;&gt;fst&lt;/a&gt; for serialisation of data.frames using
lz4 and zstd&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=qs&#34;&gt;qs&lt;/a&gt; for fast serialization of arbitrary R objects
with lz4 and zstd&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yann Collett for releasing, maintaining and advancing
&lt;a href=&#34;https://github.com/lz4/lz4&#34;&gt;lz4&lt;/a&gt; and &lt;a href=&#34;https://github.com/facebook/zstd&#34;&gt;zstd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining such a wonderful language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;xxhashr&#39; - extremely fast hashing with xxHash</title>
      <link>https://coolbutuseless.github.io/2020/06/12/introducing-xxhashr-extremely-fast-hashing-with-xxhash/</link>
      <pubDate>Fri, 12 Jun 2020 20:35:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/06/12/introducing-xxhashr-extremely-fast-hashing-with-xxhash/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;xxhashr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;xxhashr&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xxhashr&lt;/code&gt; provides simple access to the &lt;em&gt;very&lt;/em&gt; fast hashing functions
in &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The package provides support for hashing of vectors, matrices and arrays
which contain raw, integer, real or logical values. To hash arbitrary R
objects, use &lt;code&gt;base::serialize()&lt;/code&gt; to first turn the object into
a vector of raw bytes.&lt;/p&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Limitations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It is the underlying data of the vector or matrix that is being hashed, and this
does not include any notion of the container for that data. This
means that a vector and array which contain the same data will hash to the
same value - regardless of the dimensions.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xxHash v0.7.x&lt;/code&gt; includes the experimental &lt;code&gt;xxh3&lt;/code&gt; and &lt;code&gt;xxh128&lt;/code&gt; hash functionx.
From the documentation: “The algorithm is currently in development, meaning
its return values might still change in future versions. However, the API is
stable, and can be used in production, typically for generation of
ephemeral hashes (produced and consumed in same session)”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xxHash&lt;/code&gt; is a non-cryptographic hash.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/xxhashr&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/xxhashr)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;optimisation-via-makevars&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Optimisation via &lt;code&gt;Makevars&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;To get the most out of what &lt;code&gt;xxHash&lt;/code&gt; offers, it’s important to set
some optimisation flags for your machine. The important compiler flags to set
are &lt;code&gt;-O3&lt;/code&gt; and &lt;code&gt;-march=native&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here are 2 possible ways to do this:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Copy &lt;code&gt;src/Makevars.custom&lt;/code&gt; to &lt;code&gt;src/Makevars&lt;/code&gt; re-build package.&lt;/li&gt;
&lt;li&gt;Edit your &lt;code&gt;~/.R/Makevars&lt;/code&gt; to include &lt;code&gt;CFLAGS = -O3 -march=native&lt;/code&gt; (this will
change flags for all future compilation, and should probably be used with caution)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-hashing&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple hashing&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(xxhashr)

vec &amp;lt;- raw(1e6)

xxhashr::xxhash32(vec)
[1] &amp;quot;5fff0bcb&amp;quot;

xxhashr::xxhash64(vec)
[1] &amp;quot;8a76d36d39caaecc&amp;quot;

xxhashr::xxhash128(vec)
[1] &amp;quot;118fde282639e0a3b5ce7c14a206fb68&amp;quot;

xxhashr::xxh3_64bits(vec)
[1] &amp;quot;b5ce7c14a206fb68&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;hashing-1-million-raw-bytes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hashing 1 million raw bytes&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;xxhashr::xxh3_64bits()&lt;/code&gt; hashes data at around 25 GB/s for this input data size.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;digest::digest()&lt;/code&gt; can hash raw bytes like &lt;code&gt;xxhashr&lt;/code&gt; the speeds for &lt;code&gt;xxhashr::xxhash64()&lt;/code&gt;
and &lt;code&gt;digest(algo = &#39;xxhash64&#39;)&lt;/code&gt; are about the same.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(digest)

N   &amp;lt;- 1e6
vec &amp;lt;- raw(N)

res &amp;lt;- bench::mark(
  xxhash32(vec),
  xxhash64(vec),
  xxhash128(vec),
  xxh3_64bits(vec),
  digest(vec, algo = &amp;#39;xxhash32&amp;#39;, serialize = FALSE),
  digest(vec, algo = &amp;#39;xxhash64&amp;#39;, serialize = FALSE),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;Hashing 1 million raw bytes&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;GB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;158.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6080&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash64(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;79.5µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11952&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash128(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27687&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxh3_64bits(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash32”, serialize = FALSE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;310.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3093&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash64”, serialize = FALSE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;114µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8394&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;hashing-1-thousand-raw-bytes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hashing 1 thousand raw bytes&lt;/h2&gt;
&lt;p&gt;At smaller data sizes, the call overhead becomes more significant, and the
overall throughput drops drastically.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xxhashr&lt;/code&gt; is about 20x faster than &lt;code&gt;digest::digest()&lt;/code&gt; in this case.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 1024L
vec &amp;lt;- raw(N)

res &amp;lt;- bench::mark(
  xxhash32(vec),
  xxhash64(vec),
  xxhash128(vec),
  xxh3_64bits(vec),
  digest(vec, algo = &amp;#39;xxhash32&amp;#39;, serialize = FALSE),
  digest(vec, algo = &amp;#39;xxhash64&amp;#39;, serialize = FALSE),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-4&#34;&gt;Table 2: &lt;/span&gt;Hashing 1000 raw bytes&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;GB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.06µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;872697&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.898&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash64(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.01µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;912220&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.946&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash128(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;908029&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.936&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxh3_64bits(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.04µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;885477&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.915&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash32”, serialize = FALSE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31.87µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29611&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.030&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash64”, serialize = FALSE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31.44µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29787&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.030&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;hashing-1-million-numeric-values&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hashing 1 million numeric values&lt;/h2&gt;
&lt;p&gt;In the case of integers, doubles and logical values, &lt;code&gt;xxhashr&lt;/code&gt; will hash the
data values directly, while &lt;code&gt;digest::digest()&lt;/code&gt; must first serialize them to
raw bytes.&lt;/p&gt;
&lt;p&gt;As a result, &lt;code&gt;xxhashr::xxhash128()&lt;/code&gt; is about 100x faster than &lt;code&gt;digest::digest()&lt;/code&gt;,
and operates at about 20 GB/s (on my machine).&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N   &amp;lt;- 1e6
vec &amp;lt;- numeric(N)

res &amp;lt;- bench::mark(
  xxhash32(vec),
  xxhash64(vec),
  xxhash128(vec),
  xxh3_64bits(vec),
  digest(vec, algo = &amp;#39;xxhash32&amp;#39;, serialize = TRUE),
  digest(vec, algo = &amp;#39;xxhash64&amp;#39;, serialize = TRUE),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-6&#34;&gt;Table 3: &lt;/span&gt;Hashing 1 million numeric values&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;GB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.33ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;734&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash64(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;679.23µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1437&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash128(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;313.31µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2960&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxh3_64bits(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;295.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3116&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash32”, serialize = TRUE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36.94ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash64”, serialize = TRUE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32.09ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;hashing-1-million-integer-values&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hashing 1 million integer values&lt;/h2&gt;
&lt;p&gt;In the case of integers, doubles and logical values, &lt;code&gt;xxhashr&lt;/code&gt; will hash the
data values directly, while &lt;code&gt;digest::digest()&lt;/code&gt; must first serialize them to
raw bytes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;hashFunction&lt;/code&gt; package offers a few hashes that work directly with integer values.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;xxhashr::xxhash128()&lt;/code&gt; is about 100x faster than &lt;code&gt;digest::digest()&lt;/code&gt;, and about
5x faster than &lt;code&gt;hashFunction&lt;/code&gt; hashes.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click here to show/hide benchmark code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(hashFunction)
N &amp;lt;- 1e6
vec &amp;lt;- integer(N)

res &amp;lt;- bench::mark(
  xxhash32(vec),
  xxhash64(vec),
  xxhash128(vec),
  xxh3_64bits(vec),
  digest(vec, algo = &amp;#39;xxhash32&amp;#39;, serialize = TRUE),
  digest(vec, algo = &amp;#39;xxhash64&amp;#39;, serialize = TRUE),
  murmur3.32(vec),
  cityhash.64(vec),
  spooky.32(vec),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-8&#34;&gt;Table 4: &lt;/span&gt;Hashing 1 million integer values&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;GB/s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;640.3µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1499&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash64(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;325.7µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2916&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxhash128(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;140.2µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6710&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xxh3_64bits(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;128.1µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7071&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash32”, serialize = TRUE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.8ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;71&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;digest(vec, algo = “xxhash64”, serialize = TRUE)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.7ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;78&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;murmur3.32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;563.2µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1586&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;cityhash.64(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;636.8µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;947&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;spooky.32(vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;602.3µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1134&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The original &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt; software.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=digest&#34;&gt;&lt;code&gt;digest&lt;/code&gt;&lt;/a&gt; package is
a much more comprehensive approach to hashing from within R - multiple
hashing functions and much more configurability&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://cran.r-project.org/package=hashFunction&#34;&gt;&lt;code&gt;hashFunction&lt;/code&gt;&lt;/a&gt; offers
some hasing functions that work directly on character or integer values.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yann Collett for releasing, maintaining and advancing &lt;a href=&#34;https://cyan4973.github.io/xxHash/&#34;&gt;xxHash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;R Core for developing and maintaining such a great language.&lt;/li&gt;
&lt;li&gt;CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining
the repository&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the &#39;defaultlist&#39; package - R list objects with a user-defined default value.</title>
      <link>https://coolbutuseless.github.io/2020/05/13/introducing-the-defaultlist-package-r-list-objects-with-a-user-defined-default-value./</link>
      <pubDate>Wed, 13 May 2020 21:58:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/05/13/introducing-the-defaultlist-package-r-list-objects-with-a-user-defined-default-value./</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;defaultlist&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;defaultlist&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;defaultlist&lt;/code&gt; provides an object which behaves like a normal R list, but which
has a user-defined default value when the requested element is not present.&lt;/p&gt;
&lt;p&gt;Regular &lt;code&gt;list&lt;/code&gt; objects will return &lt;code&gt;NULL&lt;/code&gt; when an unknown character index is used,
or throw an error if a numeric index is beyond the length of the list.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;defaultlist&lt;/code&gt; in these situations will instead return a default value set by
the user during initialisation.&lt;/p&gt;
&lt;div id=&#34;why&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;Use defaultlist objects if you would like to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;avoid having to initialise for every entry&lt;/li&gt;
&lt;li&gt;avoid having to check whether an entry exists before accessing&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dlist(..., .default)&lt;/code&gt; - used to construct a new &lt;code&gt;defaultlist&lt;/code&gt;. Same syntax as &lt;code&gt;list()&lt;/code&gt; but
needs an additional argument to set the default value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;empty_dlist(.default)&lt;/code&gt; - create an empty list with the given default.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;as.dlist()&lt;/code&gt; - identical to &lt;code&gt;as.list()&lt;/code&gt; except it requires an additional
argument to set the default value&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/defaultlist&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.package(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;#39;coolbutuseless/defaultlist&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic Example&lt;/h2&gt;
&lt;p&gt;In this example a &lt;code&gt;defaultlist&lt;/code&gt; is created which will return &lt;code&gt;FALSE&lt;/code&gt; for any
access to an unknown element. Besides this, it will bevave identically to
a normal &lt;code&gt;list()&lt;/code&gt; object.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;haystack &amp;lt;- empty_dlist(FALSE)
haystack$surprise &amp;lt;- TRUE

haystack[[&amp;#39;hello&amp;#39;]]
[1] FALSE
haystack$mcfly
[1] FALSE
haystack[[&amp;#39;surprise&amp;#39;]]
[1] TRUE
haystack$surprise
[1] TRUE

haystack[11:13]
[[1]]
[1] FALSE

[[2]]
[1] FALSE

[[3]]
[1] FALSE

[.default = FALSE]
haystack[c(&amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;)]
$x
[1] FALSE

$y
[1] FALSE

[.default = FALSE]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-counters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Counters&lt;/h2&gt;
&lt;p&gt;When counting from a stream of unknown objects, using a normal &lt;code&gt;list&lt;/code&gt; can get
a little messy as for each object pulled from the stream there needs to be
an explicit check to see if the value is already in the list or not.&lt;/p&gt;
&lt;p&gt;Using a &lt;code&gt;defaultlist&lt;/code&gt; lets you avoid lots of checking, and assume that for
any object not in the list, the count is zero.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;census &amp;lt;- empty_dlist(0)

population &amp;lt;- c(&amp;#39;andy&amp;#39;, &amp;#39;bob&amp;#39;, &amp;#39;carol&amp;#39;, &amp;#39;carol&amp;#39;)

for (name in population) {
  census[[name]] &amp;lt;- census[[name]] + 1
}

census&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$andy
[1] 1

$bob
[1] 1

$carol
[1] 2

[.default = 0]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;census$mike&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;extra-credit-example---using-nested-defaultlists&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extra Credit Example - using nested defaultlists&lt;/h2&gt;
&lt;p&gt;In this example, nested defaultlists are used to determine the most common pairing
of elements in a stream of unknown values.&lt;/p&gt;
&lt;p&gt;This implementation does not need to know anything about the possible values in the
stream beforehand, and does not need to explicitly test for list membership for every new
token plucked from the stream.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a stream of characters heavily weighted towards &amp;#39;a&amp;#39; and &amp;#39;e&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set.seed(1)
stream &amp;lt;- sample(letters[1:5], 1000, replace = TRUE, prob = c(5, 1, 1, 1, 4))
head(stream)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;a&amp;quot; &amp;quot;a&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;a&amp;quot; &amp;quot;d&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create nested defaultlists
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
counter &amp;lt;- empty_dlist(empty_dlist(0))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Count the pair of characters (prev, this)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (idx in 2:length(stream)) {
  this &amp;lt;- stream[[idx]]
  prev &amp;lt;- stream[[idx  - 1]]
  counter[[prev]][[this]] &amp;lt;- counter[[prev]][[this]] + 1
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The most probable letter pair in the stream is: a-a
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sort(unlist(counter), decreasing = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;a.a a.e e.a e.e a.b b.a b.e d.a a.c e.b a.d c.e c.a e.c e.d d.e b.b c.b c.c d.b 
178 138 137 108  41  39  37  35  32  32  30  30  30  28  27  19   8   8   8   7 
d.c b.d b.c d.d c.d 
  7   7   5   4   4 &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;related-software&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Related Software&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Python’s &lt;a href=&#34;https://docs.python.org/3.8/library/collections.html#collections.defaultdict&#34;&gt;defaultdict&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;R’s &lt;a href=&#34;https://cran.r-project.org/package=collections&#34;&gt;collections package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;acknowledgements&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Acknowledgements&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R Core &amp;amp; CRAN maintainers for giving me a playground&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hadley&#34;&gt;Hadley Wickham&lt;/a&gt; for &lt;a href=&#34;https://cran.r-project.org/package=testthat&#34;&gt;testthat&lt;/a&gt;
which allowed test-driver-development, without which this package never
would have worked.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>defaultlist - an R list with a user-defined default value. Take 2</title>
      <link>https://coolbutuseless.github.io/2020/05/12/defaultlist-an-r-list-with-a-user-defined-default-value.-take-2/</link>
      <pubDate>Tue, 12 May 2020 20:18:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/05/12/defaultlist-an-r-list-with-a-user-defined-default-value.-take-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;problem-i-want-a-list-with-a-user-defined-default-value&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: I want a list with a user-defined default value&lt;/h2&gt;
&lt;p&gt;The default &lt;code&gt;list&lt;/code&gt; in R is great, but sometimes I’d like it to return something
other than &lt;code&gt;NULL&lt;/code&gt; if a name isn’t in the list.&lt;/p&gt;
&lt;p&gt;Some motivating examples and initial implementation is
&lt;a href=&#34;https://coolbutuseless.github.io/2020/05/11/defaultlist-an-r-list-with-a-default-value/&#34;&gt;yesterday’s post&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-new-since-yesterday&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s new since yesterday?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Can now store a NULL in a defaultlist without it being replaced with the default value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defaultdict&lt;/code&gt; now responds correctly for both character and integer indexing.&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;[&lt;/code&gt; extraction (in addition to &lt;code&gt;[[&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;defaultlist-implementation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;defaultlist&lt;/code&gt; implementation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a list with a default value
#&amp;#39;
#&amp;#39; This behaves exactly like a &amp;#39;list()&amp;#39; object, except if the requested value
#&amp;#39; does not exist, a default value is returned (instead of NULL).
#&amp;#39;
#&amp;#39; v0.1 2020-05-11  
#&amp;#39;      Initial release.  
#&amp;#39; v0.2 2020-05-12 
#&amp;#39;      Can now store &amp;#39;NULL&amp;#39; in list properly. 
#&amp;#39;      Added `[` access
#&amp;#39;      Handle defaults when indexing by a numeric
#&amp;#39;
#&amp;#39; Similar to a `defaultdict` in Python
#&amp;#39;
#&amp;#39; @param value default value to return if item not in list
#&amp;#39;
#&amp;#39; @return new `defaultlist` object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
defaultlist &amp;lt;- function(value) {
  structure(list(), class = &amp;#39;defaultlist&amp;#39;, value = value)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch value from defaultlist: [[]] or $
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[[.defaultlist` &amp;lt;- `$.defaultlist` &amp;lt;- function(x, y) {
  if ((is.character(y) &amp;amp;&amp;amp; y %in% names(x)) || 
    (is.numeric(y) &amp;amp;&amp;amp; as.integer(y) &amp;lt;= length(x))) {
      NextMethod()
    } else {
      attr(x, &amp;#39;value&amp;#39;)
    }
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch value from defaultlist: []
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[.defaultlist` &amp;lt;- function(x, y) {
  if ((is.character(y) &amp;amp;&amp;amp; y %in% names(x)) || 
    (is.numeric(y) &amp;amp;&amp;amp; as.integer(y) &amp;lt;= length(x))) {
      NextMethod()
    } else if (is.character(y)) {
      setNames(list(attr(x, &amp;#39;value&amp;#39;)), y)
    } else {
      list(attr(x, &amp;#39;value&amp;#39;))
    }
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Print like a list
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print.defaultlist &amp;lt;- function(x, ...) {
  attr(x, &amp;#39;value&amp;#39;) &amp;lt;- NULL
  attr(x, &amp;#39;class&amp;#39;) &amp;lt;- NULL
  print(x)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---defaultlist-with-a-default-of-false&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - &lt;code&gt;defaultlist&lt;/code&gt; with a default of FALSE&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;haystack &amp;lt;- defaultlist(FALSE)
haystack$surprise &amp;lt;- TRUE

haystack[[&amp;#39;hello&amp;#39;]]
[1] FALSE
haystack$mcfly
[1] FALSE
haystack[[&amp;#39;surprise&amp;#39;]]
[1] TRUE
haystack$surprise
[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;defaultlist-in-action---list-with-a-default-of-0&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;defaultlist&lt;/code&gt; in action - list with a default of ‘0’&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;counter &amp;lt;- defaultlist(0)

things &amp;lt;- c(&amp;#39;andy&amp;#39;, &amp;#39;bob&amp;#39;, &amp;#39;carol&amp;#39;, &amp;#39;carol&amp;#39;)

for (thing in things) {
  counter[[thing]] &amp;lt;- counter[[thing]] + 1
}

counter&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$andy
[1] 1

$bob
[1] 1

$carol
[1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;extra-credit-example---using-nested-defaultlists-to-count-most-common-letter-pairs-in-a-stream-of-unknown-characters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extra Credit Example - using nested defaultlists to count most common letter pairs in a stream of unknown characters&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create nested defaultlists
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
counter &amp;lt;- defaultlist(defaultlist(0))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a stream of characters heavily weighted towards &amp;#39;a&amp;#39; and &amp;#39;e&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set.seed(1)
stream &amp;lt;- sample(letters[1:5], 1000, replace = TRUE, prob = c(5, 1, 1, 1, 4))
head(stream)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;a&amp;quot; &amp;quot;a&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;a&amp;quot; &amp;quot;d&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Count the pair of characters (prev, this)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (idx in 2:length(stream)) {
  this &amp;lt;- stream[[idx]]
  prev &amp;lt;- stream[[idx  - 1]]
  counter[[prev]][[this]] &amp;lt;- counter[[prev]][[this]] + 1
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The most probable letter pair in the stream is: a-a
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sort(unlist(counter), decreasing = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;a.a a.e e.a e.e a.b b.a b.e d.a a.c e.b a.d c.e c.a e.c e.d d.e b.b c.b c.c d.b 
178 138 137 108  41  39  37  35  32  32  30  30  30  28  27  19   8   8   8   7 
d.c b.d b.c d.d c.d 
  7   7   5   4   4 &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>defaultlist - an R list with a default value</title>
      <link>https://coolbutuseless.github.io/2020/05/11/defaultlist-an-r-list-with-a-default-value/</link>
      <pubDate>Mon, 11 May 2020 20:53:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/05/11/defaultlist-an-r-list-with-a-default-value/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;problem-i-want-a-list-with-a-default-value&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: I want a list with a default value&lt;/h2&gt;
&lt;p&gt;The default &lt;code&gt;list&lt;/code&gt; in R is great, but sometimes I’d like it to return something
other than &lt;code&gt;NULL&lt;/code&gt; if a name isn’t in the list.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;contrived-motivating-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Contrived motivating example&lt;/h2&gt;
&lt;p&gt;Say I want to use a list as a counter for elements in a stream
of data, but I’m not sure
before-hand what elements are present. Each time I want to increase the count
of a particular name, I first have to manually check if the name is already in the list.
If it is, then add 1 to that location, otherwise set the counter for that item to 1.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;counter &amp;lt;- list()

things &amp;lt;- c(&amp;#39;bob&amp;#39;, &amp;#39;david&amp;#39;, &amp;#39;kate&amp;#39;, &amp;#39;susan&amp;#39;, &amp;#39;susan&amp;#39;)

for (thing in things) {
  if (thing %in% names(counter)) {
    counter[[thing]] &amp;lt;- counter[[thing]] + 1L
  } else {
    counter[[thing]] &amp;lt;- 1
  }
}

counter&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$bob
[1] 1

$david
[1] 1

$kate
[1] 1

$susan
[1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is fine, but if I’ve got a lot of counters, I’d like something a bit
less clunky.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;preferred-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Preferred syntax&lt;/h2&gt;
&lt;p&gt;I want something which looks pretty much like a list, but if the requested
name is not in the list, then the default value is returned, rather than &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the case of a counter, I want this new &lt;code&gt;defaultlist&lt;/code&gt; to return &lt;code&gt;0&lt;/code&gt; if
the requested name is not present.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;counter &amp;lt;- defaultlist(0)

things &amp;lt;- c(&amp;#39;bob&amp;#39;, &amp;#39;david&amp;#39;, &amp;#39;kate&amp;#39;, &amp;#39;susan&amp;#39;, &amp;#39;susan&amp;#39;)

for (thing in things) {
  counter[[thing]] &amp;lt;- counter[[thing]] + 1
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;defaultlist-implementation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;defaultlist&lt;/code&gt; implementation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a list with a default value
#&amp;#39;
#&amp;#39; This behaves exactly like a &amp;#39;list()&amp;#39; object, except if the requested value
#&amp;#39; does not exist, a default value is returned (instead of NULL).
#&amp;#39;
#&amp;#39; Similar to a `defaultdict` in Python
#&amp;#39;
#&amp;#39; @param value default value to return if item not in list
#&amp;#39;
#&amp;#39; @return new `defaultlist` object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
defaultlist &amp;lt;- function(value) {
  structure(list(), class = &amp;#39;defaultlist&amp;#39;, value = value)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fetch value from defaultlist
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[[.defaultlist` &amp;lt;- `$.defaultlist` &amp;lt;- function(x, y) {
  res &amp;lt;- unclass(x)[[y]] 
  if (is.null(res)) attr(x, &amp;#39;value&amp;#39;) else res
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Print like a list
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
print.defaultlist &amp;lt;- function(x, ...) {
  attr(x, &amp;#39;value&amp;#39;) &amp;lt;- NULL
  attr(x, &amp;#39;class&amp;#39;) &amp;lt;- NULL
  print(x)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;defaultlist-in-action---list-with-a-default-of-0&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;defaultlist&lt;/code&gt; in action - list with a default of ‘0’&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;counter &amp;lt;- defaultlist(0)

things &amp;lt;- c(&amp;#39;bob&amp;#39;, &amp;#39;david&amp;#39;, &amp;#39;kate&amp;#39;, &amp;#39;susan&amp;#39;, &amp;#39;susan&amp;#39;)

for (thing in things) {
  counter[[thing]] &amp;lt;- counter[[thing]] + 1
}

counter&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$bob
[1] 1

$david
[1] 1

$kate
[1] 1

$susan
[1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---defaultlist-with-a-default-of-false&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - &lt;code&gt;defaultlist&lt;/code&gt; with a default of FALSE&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;haystack &amp;lt;- defaultlist(FALSE)
haystack[[&amp;#39;surprise&amp;#39;]] &amp;lt;- TRUE

haystack[[&amp;#39;hello?&amp;#39;]]
[1] FALSE
haystack$mcfly
[1] FALSE
haystack[[&amp;#39;anyone home?&amp;#39;]]
[1] FALSE
haystack[[&amp;#39;surprise&amp;#39;]]
[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;extra-credit-example---using-nested-defaultlists-to-count-most-common-letter-pairs-in-a-stream-of-unknown-characters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extra Credit Example - using nested defaultlists to count most common letter pairs in a stream of unknown characters&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create nested defaultlists
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
counter &amp;lt;- defaultlist(defaultlist(0))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a stream of characters heavily weighted towards &amp;#39;a&amp;#39; and &amp;#39;e&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set.seed(1)
stream &amp;lt;- sample(letters[1:5], 1000, replace = TRUE, prob = c(5, 1, 1, 1, 4))
head(stream)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;a&amp;quot; &amp;quot;a&amp;quot; &amp;quot;e&amp;quot; &amp;quot;d&amp;quot; &amp;quot;a&amp;quot; &amp;quot;d&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Count the pair of characters (prev, this)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (idx in 2:length(stream)) {
  this &amp;lt;- stream[[idx]]
  prev &amp;lt;- stream[[idx  - 1]]
  counter[[prev]][[this]] &amp;lt;- counter[[prev]][[this]] + 1
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The most probable letter pair in the stream is: a-a
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sort(unlist(counter), decreasing = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;a.a a.e e.a e.e a.b b.a b.e d.a a.c e.b a.d c.e c.a e.c e.d d.e b.b c.b c.c d.b 
178 138 137 108  41  39  37  35  32  32  30  30  30  28  27  19   8   8   8   7 
d.c b.d b.c d.d c.d 
  7   7   5   4   4 &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;gridfont&#39; - a vector font</title>
      <link>https://coolbutuseless.github.io/2020/05/08/introducing-gridfont-a-vector-font/</link>
      <pubDate>Fri, 08 May 2020 20:33:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/05/08/introducing-gridfont-a-vector-font/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;gridfont&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;gridfont&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;An R repackaging of the &lt;a href=&#34;https://github.com/inconvergent/gridfont&#34;&gt;gridfont&lt;/a&gt;
vector font created by &lt;a href=&#34;https://twitter.com/inconvergent&#34;&gt;inconvergent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This package is similar to the packages &lt;a href=&#34;https://github.com/coolbutuseless/hershey&#34;&gt;hershey&lt;/a&gt; and &lt;a href=&#34;https://github.com/coolbutuseless/arcadefont&#34;&gt;arcadefont&lt;/a&gt;
in that it provides point and stroke information, but how this is actually
rendered is up to you.&lt;/p&gt;
&lt;p&gt;In the examples below &lt;code&gt;ggplot&lt;/code&gt; is used to render the strokes for each glyph as
&lt;code&gt;geom_path&lt;/code&gt; objects.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;What’s in the box?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;original_df&lt;/code&gt; - a data.frame of coordinates and stroke information for all the
provided glyphs for the &lt;strong&gt;original&lt;/strong&gt; version of the font.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;smooth_df&lt;/code&gt; - a data.frame of coordinates and stroke information for all the
provided glyphs for the &lt;strong&gt;smooth&lt;/strong&gt; version of the font.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create_text_df()&lt;/code&gt; - a function to create stroke information for all the
characters in a given string, and offset them appropriately (vertically and
horizontally) so that they are ready to render.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;original_json&lt;/code&gt;, &lt;code&gt;smooth_json&lt;/code&gt; the original JSON data read in using &lt;code&gt;jsonlite&lt;/code&gt;
and provided as list objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Installation&lt;/h4&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/gridfont&#34;&gt;github&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;quot;coolbutuseless/gridfont&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;license&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;License&lt;/h4&gt;
&lt;p&gt;This package is made available under the MIT license. See the file “LICENCSE”.&lt;/p&gt;
&lt;p&gt;The original font data was made available by Anders Hoff (a.k.a Inconvergent)
also under the MIT license. See the file “LICENSE-font”&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sample-sheet-for-the-original-font&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sample sheet for the ‘original’ font&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(gridfont::original_df, aes(x, y)) +
  geom_path(aes(group = as.factor(stroke)), na.rm=TRUE) +
  coord_equal() +
  theme_void() + 
  facet_wrap(~char)  + 
  theme(
    strip.background = element_blank(),
    strip.text.x     = element_blank()
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-08-gridfont_files/figure-html/sample-original-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sample-sheet-for-the-smooth-font&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sample sheet for the ‘smooth’ font&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(gridfont::smooth_df, aes(x, y)) +
  # geom_point() +
  geom_path(aes(group = as.factor(stroke)), na.rm=TRUE) +
  coord_equal() +
  theme_void() + 
  facet_wrap(~char)  + 
  theme(
    strip.background = element_blank(),
    strip.text.x     = element_blank()
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-08-gridfont_files/figure-html/sample-smooth-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-blocks-of-text&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating blocks of text&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gridfont&lt;/code&gt; includes &lt;code&gt;create_text_df()&lt;/code&gt; as an easy way to create stroke data for
all the characters from a given string.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;text    &amp;lt;- &amp;#39;hello  #RStats\noriginal {gridfont}&amp;#39;
plot_df &amp;lt;- create_text_df(text, font=&amp;#39;original&amp;#39;)

ggplot(plot_df, aes(x, y)) +
  geom_path(aes(group = interaction(char_idx, stroke)), na.rm=TRUE) +
  coord_equal() +
  theme_void()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-08-gridfont_files/figure-html/example-original-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;text    &amp;lt;- &amp;#39;hello  #RStats\nsmooth {gridfont}&amp;#39;
plot_df &amp;lt;- create_text_df(text, font=&amp;#39;smooth&amp;#39;)

ggplot(plot_df, aes(x, y)) +
  geom_path(aes(group = interaction(char_idx, stroke)), na.rm=TRUE) +
  coord_equal() +
  theme_void()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-08-gridfont_files/figure-html/example-smooth-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-rendering&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated rendering&lt;/h2&gt;
&lt;p&gt;Now that all the stroke information is available, we can render each stroke,
character-by-character to get a “writing” effect.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/gridfont/rstats/animo.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;arcadefont&#39; - an oldschool arcade vector font  (Happy Star Wars Day)</title>
      <link>https://coolbutuseless.github.io/2020/05/04/introducing-arcadefont-an-oldschool-arcade-vector-font-happy-star-wars-day/</link>
      <pubDate>Mon, 04 May 2020 20:58:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/05/04/introducing-arcadefont-an-oldschool-arcade-vector-font-happy-star-wars-day/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;arcadefont&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;arcadefont&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;arcadefont&lt;/code&gt; provides raw vector data for an 80s arcade vector font - similar to
that seen in &lt;a href=&#34;https://en.wikipedia.org/wiki/Battlezone_(1980_video_game)&#34;&gt;Battlezone&lt;/a&gt;
or &lt;a href=&#34;https://en.wikipedia.org/wiki/Star_Wars_(1983_video_game)&#34;&gt;Star Wars&lt;/a&gt;. It
is a fixed-width, caps-only font.&lt;/p&gt;
&lt;p&gt;This package was released on “May the 4th” 2020 - i.e. “Star Wars Day”.&lt;/p&gt;
&lt;p&gt;This is similar to the &lt;a href=&#34;https://github.com/coolbutuseless/hershey&#34;&gt;hershey vector font package&lt;/a&gt;
in that it provides point and stroke information, but how this is actually
rendered is up to you.&lt;/p&gt;
&lt;p&gt;In the examples below &lt;code&gt;ggplot&lt;/code&gt; is used to render the strokes for each glyphs as
&lt;code&gt;geom_path&lt;/code&gt; objects.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;arcade_df&lt;/code&gt; - a data.frame of coordinates and stroke information for all the
provided glyphs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create_text_df()&lt;/code&gt; - a function to create stroke information for all the
characters in a given string, and offset them appropriately (vertically and
horizontally) so that they are ready to render.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/arcadefont&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/arcadefont&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;vector-data-source---arcade_df&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vector data source - &lt;code&gt;arcade_df&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The following output shows the data for the letter &lt;code&gt;A&lt;/code&gt; contained in the &lt;code&gt;arcade_df&lt;/code&gt;
data.frame.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;letter - character represented in this data, in this case “A”&lt;/li&gt;
&lt;li&gt;stroke - grouping variable for the points belonging to the same stroke. The
letter ‘A’ is made of 2 strokes:
1. the frame of the A shape
2. the crossbar.&lt;/li&gt;
&lt;li&gt;x,y - coordinates of points which make up a stroke. Are point coordinates are
integer locations on a 9x9 grid.&lt;/li&gt;
&lt;li&gt;idx - ordering index of points within each stroke&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;arcadefont::arcade_df %&amp;gt;%
  filter(letter == &amp;#39;A&amp;#39;) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;letter&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;stroke&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;y&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;idx&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;A&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;font-sample-sheet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Font Sample Sheet&lt;/h2&gt;
&lt;p&gt;A rendering of all the glyphs represented in &lt;code&gt;arcade_df&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(arcadefont)

ggplot(arcadefont::arcade_df, aes(x, y)) + 
  geom_path(aes(group=stroke)) + 
  coord_fixed() + 
  theme_void() + 
  facet_wrap(~letter)  + 
  theme(
    strip.background = element_blank(),
    strip.text.x     = element_blank()
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-04-arcadefont_files/figure-html/onesheet-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-data-for-sequences-of-characters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create data for sequences of characters&lt;/h2&gt;
&lt;p&gt;A simple way to create all the strokes for lines of text is to use &lt;code&gt;create_text_df()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This function will offset the characters along a row of text, and arrange the characters
over multiple lines.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;text    &amp;lt;- &amp;quot;Hello #RStats!\n@coolbutuseless&amp;quot;
text_df &amp;lt;- arcadefont::create_text_df(text, dx = 2, dy = 3)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot it!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(text_df, aes(x, y)) +
  geom_path(aes(group=interaction(char_idx, stroke))) +
  coord_fixed() +
  theme_void()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-04-arcadefont_files/figure-html/simple-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;recreation-of-instructions-screen-for-star-wars---the-arcade-game&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Recreation of instructions screen for “Star Wars - The Arcade Game”&lt;/h2&gt;
&lt;p&gt;Star Wars is a 3D vector graphics arcade game released in 1983. See more on
&lt;a href=&#34;https://en.wikipedia.org/wiki/Star_Wars_(1983_video_game)&#34;&gt;wikipedia&lt;/a&gt; and &lt;a href=&#34;https://www.youtube.com/watch?v=EA_kDTwZodQ&#34;&gt;playthrough video&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;man/figures/sw.gif&#34; /&gt;&lt;/p&gt;
&lt;p&gt;When running in ‘attract mode’ the arcade machine displayed information such as the
high score table and instructions for playing.&lt;/p&gt;
&lt;p&gt;Here I’ve recreated the instructions screen - colours too!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(ggplot2)
library(arcadefont)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Full text of the instructions screen
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
text &amp;lt;- &amp;quot;
    score                         0 wave
       00      game over
             1 coin 1 play

    flight instructions to red five

  1.   your x-wing is equiped with an
   invisible deflector shield that
   will protect you for 8 collisions.

  2.   deflector strength is lost when
   a firevall impacts your shield or
   what you strike a laser tower or
   trench catwalk.

  3.   aim your lasers with cursor to
   explode empire tie fighters laser
   tower tops and trench turrets.

  4.   shoot fireballs before they
   impact your shield.

  5. the rebel force is depending on
   you to stop the empire by blowing
   up the death star.&amp;quot;


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the text in the arcade font and set some colours
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
text_df &amp;lt;- arcadefont::create_text_df(text, dx = 2, dy = 3)
text_df &amp;lt;- text_df %&amp;gt;% mutate(
  colour = case_when(
    line == 2 &amp;amp; letter == &amp;#39;0&amp;#39; ~ &amp;#39;green&amp;#39;,
    line == 2                 ~ &amp;#39;red&amp;#39;,
    line == 3 &amp;amp; letter == &amp;#39;0&amp;#39; ~ &amp;#39;green&amp;#39;,
    line == 3                 ~ &amp;#39;cyan&amp;#39;,
    line == 4                 ~ &amp;#39;yellow&amp;#39;,
    TRUE                      ~ &amp;#39;red&amp;#39;
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot it!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(text_df, aes(x, y)) +
  geom_path(aes(group=interaction(char_idx, stroke), colour = I(colour))) +
  coord_fixed() +
  theme_void() +
  theme(panel.background = element_rect(fill = &amp;#39;black&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-05-04-arcadefont_files/figure-html/starwars-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing devoutansi - an ANSI graphics device</title>
      <link>https://coolbutuseless.github.io/2020/04/30/introducing-devoutansi-an-ansi-graphics-device/</link>
      <pubDate>Thu, 30 Apr 2020 20:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/30/introducing-devoutansi-an-ansi-graphics-device/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;devoutansi&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutansi &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutansi&lt;/code&gt; is a graphics output device for R which will output graphics
as text files with ANSI colouring.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devoutansi&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)     # devout framework
remotes::install_github(&amp;quot;coolbutuseless/miniansi&amp;quot;)   # ANSI doc creator
remotes::install_github(&amp;quot;coolbutuseless/devoutansi&amp;quot;) # this device&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Limitations&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;No current support for clipping paths or rasters.&lt;/li&gt;
&lt;li&gt;Text positioning and spacing will always be a little off&lt;/li&gt;
&lt;li&gt;Rotated text (except for 0 and 90 degrees) is probably going to be placed incorrectly.&lt;/li&gt;
&lt;li&gt;No support for transparency i.e. alpha has no effect other then to suppress
rendering completely when &lt;code&gt;alpha = 0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-usage&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Basic Usage&lt;/h1&gt;
&lt;p&gt;Use &lt;code&gt;devoutansi::ansi()&lt;/code&gt; as you would the &lt;code&gt;pdf()&lt;/code&gt; or &lt;code&gt;png()&lt;/code&gt; device.&lt;/p&gt;
&lt;p&gt;The output will be written as ANSI characters to the screen, or a text file if specified.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; - Because you can’t readily view ANSI in an HTML document, all images
included are screenshots of the output in my terminal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Click any image to view its ANSI text&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(devoutansi)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# PNG output of plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot(mtcars) +
  geom_bar(aes(as.factor(cyl), fill = as.factor(cyl)), colour = NA) +
  theme_minimal() + 
  theme(
    panel.grid   = element_blank()
  ) +
  labs(
    title    = &amp;quot;{devoutansi} - ANSI graphics device&amp;quot;,
    subtitle = &amp;quot;Hello #RStats&amp;quot;
  ) 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devoutansi::ansi(filename = &amp;quot;/img/devoutansi/mtcars1.txt&amp;quot;, width = 120)
  p 
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/mtcars1.txt&amp;#39;: No
such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars1.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars1.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;All the demo plots on this page are available as their ANSI txt files by clicking on the
images.&lt;/p&gt;
&lt;div id=&#34;geom_density&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_density()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars3.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars3.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

p &amp;lt;- ggplot(mtcars) +
  geom_density(aes(mpg, fill = as.factor(cyl))) + 
  theme_minimal() +
  theme(
    panel.grid      = element_blank(), 
    legend.key.size = unit(5, &amp;#39;in&amp;#39;)
  ) + 
  scale_fill_viridis_d() + 
  labs(
    title    = &amp;quot;{devoutansi} - ANSI graphics device&amp;quot;,
    subtitle = &amp;quot;filled polygons (geom_density)&amp;quot;
  )

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devoutansi::ansi(&amp;quot;/img/devoutansi/mtcars3.txt&amp;quot;, width = 150)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/mtcars3.txt&amp;#39;: No
such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;geom_density-in-ascii-only&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_density()&lt;/code&gt; in ASCII only&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars3.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars3-ascii.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;p&gt;Extra options for ASCII mode:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;char_lookup_table&lt;/code&gt; set to 1, 2 or 3 to select the character set&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pow&lt;/code&gt; nonlinear intensity remapping using this exponent. default 1&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devoutansi::ansi(&amp;quot;/img/devoutansi/mtcars3-ascii.txt&amp;quot;, width = 150, plain_ascii = TRUE)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/mtcars3-ascii.txt&amp;#39;:
No such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;geom_sf&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_sf()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/geom-sf.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/geom-sf.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(sf)
library(ggplot2)
library(devoutansi)

nc &amp;lt;- sf::st_read(system.file(&amp;quot;shape/nc.shp&amp;quot;, package = &amp;quot;sf&amp;quot;), quiet = TRUE)
nc &amp;lt;- nc %&amp;gt;% filter(between(CNTY_ID, 1820, 1830))

p &amp;lt;- ggplot(nc) +
  geom_sf(aes(fill = NAME)) +
  theme_bw(15) +
  theme(legend.key.size = unit(5, &amp;#39;in&amp;#39;)) + 
  scale_fill_brewer(palette = &amp;#39;Dark2&amp;#39;) + 
  labs(
    title    = &amp;quot;{devoutansi} - ANSI graphics device&amp;quot;,
    subtitle = &amp;quot;filled polygons (geom_density)&amp;quot;
  )

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
devoutansi::ansi(&amp;quot;/img/devoutansi/geom-sf.txt&amp;quot;, width = 150)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/geom-sf.txt&amp;#39;: No
such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;pie-plot-from-base-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;pie&lt;/code&gt; plot from base R&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/pie.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/pie.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutansi::ansi(&amp;quot;/img/devoutansi/pie.txt&amp;quot;, width = 180)
pie(c(cool = 4, but = 2, use = 1, less = 8), main = &amp;quot;ANSI graphics device - Base pie plot&amp;quot;)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/pie.txt&amp;#39;: No such
file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;geom_histogram&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_histogram()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars2.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/mtcars2.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

p &amp;lt;- ggplot(mtcars) +
  geom_histogram(aes(mpg, fill = as.factor(cyl)), bins = 20) + 
  theme_minimal() +
  theme(
    panel.grid      = element_blank(),
    legend.key.size = unit(5, &amp;#39;in&amp;#39;)
  ) + 
  labs(
    title    = &amp;quot;{devoutansi} - ANSI graphics device&amp;quot;,
    subtitle = &amp;quot;ggraph&amp;quot;
  ) + 
  scale_fill_brewer(palette = &amp;#39;Set2&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ansi(&amp;quot;/img/devoutansi/mtcars2.txt&amp;quot;, width = 150)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/mtcars2.txt&amp;#39;: No
such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;ggraph&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;ggraph&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutansi/ggraph.txt&#34;&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutansi/ggraph.png&#34; width=&#34;100%&#34; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; Click to show/hide code &lt;/summary&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggraph)
library(tidygraph)
library(dplyr)

set.seed(1)
simple &amp;lt;- create_notable(&amp;#39;bull&amp;#39;) %&amp;gt;%
  mutate(name = c(&amp;#39;But&amp;#39;, &amp;#39;Use&amp;#39;, &amp;#39;Cool&amp;#39;, &amp;#39;Less&amp;#39;, &amp;#39;Mike&amp;#39;)) %&amp;gt;%
  activate(edges) %&amp;gt;%
  mutate(type = sample(c(&amp;#39;friend&amp;#39;, &amp;#39;foe&amp;#39;), 5, TRUE))

p &amp;lt;- ggraph(simple, layout = &amp;#39;graphopt&amp;#39;) +
  geom_edge_link0(colour = &amp;#39;grey70&amp;#39;) +
  geom_node_text(aes(label = name), size = 10) + 
  theme_void() + 
  labs(
    title    = &amp;quot;{devoutansi} - ANSI graphics device&amp;quot;,
    subtitle = &amp;quot;ggraph&amp;quot;
  )

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ANSI output
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ansi(&amp;quot;/img/devoutansi/ggraph.txt&amp;quot;, width = 150)
p
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;/img/devoutansi/ggraph.txt&amp;#39;: No
such file or directory&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning in dev.off(): rdevice_close: Evaluation error: cannot open the
connection.&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing miniansi - a package for creating simple ANSI documents</title>
      <link>https://coolbutuseless.github.io/2020/04/29/introducing-miniansi-a-package-for-creating-simple-ansi-documents/</link>
      <pubDate>Wed, 29 Apr 2020 20:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/29/introducing-miniansi-a-package-for-creating-simple-ansi-documents/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;miniansi&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;miniansi &lt;img src=&#34;https://coolbutuseless.github.io/img/miniansi//logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;div id=&#34;miniansi-is-a-package-for-creating-simple-ansi-documents.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;miniansi&lt;/code&gt; is a package for creating simple ANSI documents.&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;miniansi&lt;/code&gt; is an R package for creating coloured ANSI output.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;miniansi&lt;/code&gt; currently has quite a minimal feature set, as only enough was included
such that it could act as a graphics output device for R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/miniansi&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/miniansi&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Slice documents, copy one document into another&lt;/li&gt;
&lt;li&gt;Image/raster support&lt;/li&gt;
&lt;li&gt;Manually simulate alpha blending by tinting colours&lt;/li&gt;
&lt;li&gt;Anti-aliasing&lt;/li&gt;
&lt;li&gt;Figlet support&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example-of-creating-an-ansi-document&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example of creating an ANSI document&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(miniansi)

doc &amp;lt;- ANSI$new(width = 80, height = 20, background = &amp;#39;cornflowerblue&amp;#39;)
doc$rect(5, 5, 15, 15, colour = &amp;#39;red&amp;#39;, fill = &amp;#39;white&amp;#39;)
doc$line(1, 1, 80, 20, &amp;#39;gold&amp;#39;)
doc$circle(25, 10, r = 17, colour = &amp;#39;darkgreen&amp;#39;, fill = NA)
doc$text(50,  5, &amp;quot;Hello #RStats&amp;quot; , angle = 90, colour = &amp;#39;brown&amp;#39;)
doc$text(60, 20, &amp;quot;coolbutuseless&amp;quot;, angle =  0)

doc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/miniansi/example.png&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;aspect-ratio-tweaks&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Aspect ratio tweaks&lt;/h1&gt;
&lt;p&gt;Working with ANSI is often painful due to the fundamental pixel unit not being square.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;miniansi&lt;/code&gt; includes a mode which lets you specify the aspect ratio of the font,
and tries to adjust everything else (by scaling the y values) so that square
things still look square.&lt;/p&gt;
&lt;p&gt;Use the &lt;code&gt;font_aspect&lt;/code&gt; argument during initialisation to let &lt;code&gt;miniansi&lt;/code&gt; know
how to compensate for aspect ratio.&lt;/p&gt;
&lt;p&gt;This mode has its own problems (as evidenced in the plot below). Note:&lt;/p&gt;
&lt;p&gt;The Good:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;rect&lt;/code&gt; sides now actually look (nearly) the same length&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Bad:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Even though the document is only nominally 20 characters high, because of the
y-coord adjustment, the visible plotting area is larger i.e. &lt;code&gt;doc$max_height = height/font_aspect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Vertical text writing will never work properly in this mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Weird:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Circles are always fudged by &lt;code&gt;miniansi&lt;/code&gt; to look circular. This was a deliberate
choice in order to work sanely with &lt;code&gt;grid&lt;/code&gt; graphics and &lt;code&gt;ggplot2::geom_point&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(miniansi)

doc &amp;lt;- ANSI$new(width = 80, height = 20, background = &amp;#39;cornflowerblue&amp;#39;, font_aspect = 0.45)

max_height &amp;lt;- doc$max_height

doc$rect(5, 5, 15, 15, colour = &amp;#39;red&amp;#39;, fill = &amp;#39;white&amp;#39;)
doc$line(1, 1, 80, max_height, &amp;#39;gold&amp;#39;)
doc$circle(25, 10, r = 17, colour = &amp;#39;darkgreen&amp;#39;, fill = NA)
doc$text(50,  5, &amp;quot;Hello #RStats&amp;quot; , angle = 90, colour = &amp;#39;black&amp;#39;)
doc$text(60, 20, &amp;quot;coolbutuseless&amp;quot;, angle =  0)

doc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/miniansi/example-aspect.png&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;alternate-logo---rendering-a-vector-font-to-ansi&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Alternate logo - Rendering a vector font to ANSI&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(hershey)  # Hershey Vector Fonts: https://github.com/coolbutuseless/hershey

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc &amp;lt;- ANSI$new(width = 110, height = 50, font_aspect = 0.4, background = &amp;#39;white&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set some sizes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
w  &amp;lt;- 110
h  &amp;lt;- doc$max_height
ll &amp;lt;- h/2.1

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up a hexagon
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polygon_df &amp;lt;- tibble(
  angle = seq(0, 2*pi, length.out = 7) + pi/6,
  x     = ll * cos(angle) + w/2,
  y     = ll * sin(angle) + h/2
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw the polygon
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc$polygon(polygon_df$x, polygon_df$y, fill = &amp;#39;cornflowerblue&amp;#39;, colour = &amp;#39;darkblue&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up the letter R
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
letter_r &amp;lt;- hershey::hershey %&amp;gt;%
  filter(char == &amp;#39;R&amp;#39;, font == &amp;#39;music&amp;#39;) %&amp;gt;%
  mutate(
    x = 3.3 *  x,
    y = 3.3 * -y,
    
    x = x + w/2,
    y = y + h/2 + 2
  )


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw the letter
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
letter_r %&amp;gt;% 
  group_by(stroke) %&amp;gt;% 
  group_walk(~doc$polyline(.x$x, .x$y, colour = &amp;#39;darkred&amp;#39;))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# print
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/miniansi/logo-alt.png&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animation&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Animation&lt;/h1&gt;
&lt;p&gt;This is a gif capture of this code running in my terminal. I definitely tweaked the
frame rate up, as capturing a clean set of images in the terminal was hard.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(miniansi)
library(dplyr)
library(hershey)  # Hershey Vector Fonts: https://github.com/coolbutuseless/hershey

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up the positions for each frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xoffs  &amp;lt;- seq(135, -265, -10)
angles &amp;lt;- seq(pi/6, pi/2, length.out = length(xoffs))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Loop over all frames
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (idx in seq_along(xoffs)) {
  
  xoff  &amp;lt;- xoffs[idx]
  angle &amp;lt;- angles[idx]
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Set up an ANSI document
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  doc &amp;lt;- ANSI$new(width = 110, height = 50, font_aspect = 0.4, background = &amp;#39;white&amp;#39;)

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Define some sizes
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  w  &amp;lt;- 110
  h  &amp;lt;- doc$max_height
  ll &amp;lt;- h/2.3
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # draw a rotated hexagon
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  polygon_df &amp;lt;- tibble(
    angle = seq(0, 2*pi, length.out = 7) + angle,
    x     = ll * cos(angle) + w/2,
    y     = ll * sin(angle) + h/2
  )
  
  doc$polygon(polygon_df$x, polygon_df$y, fill = &amp;#39;cornflowerblue&amp;#39;, colour = NA)
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create a word in the hershey &amp;#39;meteorology&amp;#39; font
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  rstats &amp;lt;- hershey::create_string_df(&amp;quot;RStats&amp;quot;, font = &amp;#39;meteorology&amp;#39;) %&amp;gt;%
    mutate(
      x = 3 *  x,
      y = 3 * -y,
      y = y + h/2,
      x = x + xoff  # (-2*w-45), w+25 =&amp;gt; -265, 135
    )
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Draw the word using polylines for each stroke for each character
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  rstats %&amp;gt;% 
    group_by(char_idx, stroke) %&amp;gt;% 
    group_walk(~doc$polyline(.x$x, .x$y, colour = &amp;#39;darkred&amp;#39;))
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Print the frame, reset the cursor to top of screen for a slightly 
  # cleaner render
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  print(doc)
  cat(&amp;quot;\033[0;0H&amp;quot;)
  Sys.sleep(0.2)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/miniansi/anim-o.gif&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Scanline Polygon Fill Algorithm in Plain R (with bonus ANSI colour!)</title>
      <link>https://coolbutuseless.github.io/2020/04/28/scanline-polygon-fill-algorithm-in-plain-r-with-bonus-ansi-colour/</link>
      <pubDate>Tue, 28 Apr 2020 20:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/28/scanline-polygon-fill-algorithm-in-plain-r-with-bonus-ansi-colour/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;why-the-hell-would-you-do-this&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why the Hell would you do this?&lt;/h2&gt;
&lt;p&gt;Polygon filling is ubiquitous in computer graphics, with modern GPU hardware
rendering approximately 1 &lt;strong&gt;Billion&lt;/strong&gt; polygons per second.&lt;/p&gt;
&lt;p&gt;So why have I regressed to 30 years ago and hand-rolled a scanline polygon
filling algorithm in plain R?&lt;/p&gt;
&lt;ol style=&#34;list-style-type: lower-alpha&#34;&gt;
&lt;li&gt;I needed it&lt;/li&gt;
&lt;li&gt;I hadn’t written one since Computer Graphics 101 - so many years ago.&lt;/li&gt;
&lt;li&gt;I was interested to see how much the built-in R data structures would help -
mainly the use of data.frames to hold the edge lists.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;specifications&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Specifications&lt;/h2&gt;
&lt;p&gt;Specifications for my use case&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base R only - I don’t want to compile C code or pull in some other dependency.&lt;/li&gt;
&lt;li&gt;Integer coordinates only. Everything will be rounded to an integer as I’m
not anti-aliasing or anything fancy.&lt;/li&gt;
&lt;li&gt;Polygons only expected to be a maximum of about 100x100 pixels, so speed
won’t be a huge factor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;scanline-polygon-fill&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Scanline Polygon Fill&lt;/h2&gt;
&lt;p&gt;See &lt;a href=&#34;https://en.wikipedia.org/wiki/Scanline_rendering&#34;&gt;wikipedia&lt;/a&gt; for an overview
of scanline rendering.&lt;/p&gt;
&lt;p&gt;The code here is broken in to 2 functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make_edges()&lt;/code&gt; creates edge information for each pair of vertices in the polygon&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fill_polygon()&lt;/code&gt; fills the polygon specified by vectors of vertices.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Make edge information structure from polygon vertex coords
#&amp;#39;
#&amp;#39; @param xs,ys vertex coords
#&amp;#39;
#&amp;#39; @return data.frame
#&amp;#39;
#&amp;#39; @importFrom utils head tail
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make_edges &amp;lt;- function(xs, ys) {

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Ensure we have a closed loop
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  N &amp;lt;- length(xs)
  if (!(xs[1] == xs[N] &amp;amp;&amp;amp; ys[1] == ys[N])) {
    xs &amp;lt;- c(xs, xs[1])
    ys &amp;lt;- c(ys, ys[1])
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Basic edge structure: the 2 vertices
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  edges &amp;lt;- data.frame(
    x1 = head(xs, -1),
    y1 = head(ys, -1),
    x2 = tail(xs, -1),
    y2 = tail(ys, -1)
  )

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Enhanced edge structure
  #  - ymin,ymax the extents of this edge
  #  - x the x coordinate of ymin
  #  - igrad inverse gradient (used to increment the x as we step through the
  #          y scanlines)
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  edges &amp;lt;- transform(
    edges,
    ymin  = pmin(y1, y2),
    ymax  = pmax(y1, y2),
    x     = ifelse(y2 &amp;gt; y1, x1, x2),
    igrad = (x2 - x1)/(y2 - y1)
  )

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # order by increasing ymin
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  edges &amp;lt;- edges[order(edges$ymin),]

  edges
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Fill a polygon
#&amp;#39;
#&amp;#39; @param mat matrix to fill
#&amp;#39; @param xs,ys coordinates of vertices (integers)
#&amp;#39; @param fill fill value. usually a character.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fill_polygon &amp;lt;- function(mat, xs, ys, fill) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Ensure we only have integers
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  xs &amp;lt;- round(as.integer(xs))
  ys &amp;lt;- round(as.integer(ys))

  stopifnot(length(xs) == length(ys))

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Initialise the edge lists
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  all_edges &amp;lt;- make_edges(xs, ys)
  active    &amp;lt;- NULL

  if (nrow(all_edges) &amp;lt; 3) {
    return(mat)
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Set the vertices
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mat[cbind(ys, xs)] &amp;lt;- fill

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Draw any horizontal edges and remove from list
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  hedges    &amp;lt;- subset(all_edges, y1 == y2)
  all_edges &amp;lt;- subset(all_edges, y1 != y2)

  for (i in seq_len(nrow(hedges))) {
    hedge_row &amp;lt;- hedges[i, ]
    ys &amp;lt;- hedge_row$y1
    xs &amp;lt;- hedge_row$x1:hedge_row$x2
    mat[ys, xs] &amp;lt;- fill
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # For each &amp;#39;y&amp;#39; scanline
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (yscan in min(all_edges$ymin):max(all_edges$ymax)) {

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Add new active edges to &amp;#39;active&amp;#39;, and remove from &amp;#39;all_edges&amp;#39;
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    new_active &amp;lt;- subset(all_edges, ymin == yscan)
    all_edges  &amp;lt;- subset(all_edges, ymin &amp;gt;  yscan)

    active     &amp;lt;- rbind(active, new_active)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Remove any active edges which the scanline has passed.
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    active &amp;lt;- subset(active, ymax &amp;gt; yscan)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Check if all edges have been processed
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (nrow(all_edges) == 0 &amp;amp;&amp;amp; nrow(active) == 0) {
      break
    }

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Arrange active list by x
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    active &amp;lt;- active[order(active$x),]

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # For each pair of edges, draw the scanline between them
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    for (pidx in seq(1, nrow(active), by=2)) {
      x1 &amp;lt;- as.integer(round(active$x[pidx    ]))
      x2 &amp;lt;- as.integer(round(active$x[pidx + 1]))
      ys &amp;lt;- yscan
      xs &amp;lt;- x1:x2

      mat[ys, xs] &amp;lt;- fill
    }

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Increment the x position of the active edges
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    active$x &amp;lt;- active$x + active$igrad

  }

  mat
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;draw-a-filled-hexagon-in-ascii&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Draw a filled hexagon in ASCII&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a hexagon.  Distort in the x axis for better visual appearance since
# fonts are alwyas wider than they are tall.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polygon_df &amp;lt;- tibble(
  angle = seq(0, 2*pi, length.out = 7) + pi/6,
  x     = 2.3 * (8 * cos(angle) + 11),
  y     = 8 * sin(angle) + 11
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a blank matrix and draw the polygon on it.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat &amp;lt;- matrix(&amp;#39;.&amp;#39;, 20, 50)
mat &amp;lt;- fill_polygon(mat, xs = polygon_df$x, ys = polygon_df$y, fill = &amp;#39;#&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add some text and dump the canvas to the console
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat[11, 18:31] &amp;lt;- strsplit(&amp;#39;Hello #RStats!&amp;#39;, &amp;#39;&amp;#39;)[[1]]
cat(apply(mat, 1, paste, collapse = &amp;quot;&amp;quot;), sep=&amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;..................................................
..................................................
........................#.........................
....................##########....................
................####################..............
............#############################.........
........#################################.........
........#################################.........
........#################################.........
........#################################.........
........#########Hello #RStats!##########.........
........#################################.........
........#################################.........
........#################################.........
........#################################.........
............#########################.............
................#################.................
....................#########.....................
........................#.........................
..................................................&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;drawing-with-ansi&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Drawing with ANSI&lt;/h2&gt;
&lt;p&gt;Instead of just ASCII characters, you would use ANSI colours to make
something prettier. Here I’ll use &lt;a href=&#34;https://github.com/coolbutuseless/ransid&#34;&gt;ransid&lt;/a&gt;
for the ANSI codes (but in general you will probably want to use something well-designed
like &lt;a href=&#34;https://cran.r-project.org/package=crayon&#34;&gt;crayon&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ANSI colours won’t display in an Rmarkdown document (as far as I know),
so I’ve just taken a screen capture of my terminal and included the image.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ransid)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define some ANSI strings for the colours I want
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dark_bg  &amp;lt;- paste0(col2bg(&amp;#39;darkblue&amp;#39; ), &amp;#39; &amp;#39;)
light_bg &amp;lt;- paste0(col2bg(&amp;#39;lightblue&amp;#39;), &amp;#39; &amp;#39;)
text_fg  &amp;lt;- paste0(col2fg(&amp;#39;red&amp;#39;   ))
text_bg  &amp;lt;- paste0(col2bg(&amp;#39;yellow&amp;#39;))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise a matrix with a light background and draw the polygon on it.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat &amp;lt;- matrix(light_bg, 20, 50)
mat &amp;lt;- fill_polygon(mat, xs = polygon_df$x, ys = polygon_df$y, fill=dark_bg)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add some text and dump the canvas to the console
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat[11, 18:31] &amp;lt;- paste0(text_fg, text_bg, strsplit(&amp;#39;Hello #RStats!&amp;#39;, &amp;#39;&amp;#39;)[[1]])
res &amp;lt;- paste0(apply(mat, 1, paste, collapse = &amp;quot;&amp;quot;), collapse=&amp;quot;\n&amp;quot;)
cat(res)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/polygon-fill/example.png&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animating-the-ansi&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animating the ANSI&lt;/h2&gt;
&lt;p&gt;Dump ANSI to the console and screencapture it to a gif. Inelegant, but it works for now.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a hexagon.  Distort in the x axis for better visual appearance since
# fonts are alwyas wider than they are tall.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (start_angle in seq(pi/6, pi/2, length.out = 30)) {
  polygon_df &amp;lt;- tibble(
    angle = seq(0, 2*pi, length.out = 7) + start_angle,
    x     = 2.3 * (16 * cos(angle) + 21),
    y     = 16 * sin(angle) + 21
  )
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Initialise a matrix with a light background and draw the polygon on it.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mat &amp;lt;- matrix(light_bg, 40, 100)
  mat &amp;lt;- fill_polygon(mat, xs = polygon_df$x, ys = polygon_df$y, fill=dark_bg)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Add some text and dump the canvas to the console
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  mat[21, 41:54] &amp;lt;- paste0(text_fg, text_bg, strsplit(&amp;#39;Hello #RStats!&amp;#39;, &amp;#39;&amp;#39;)[[1]])
  cat(paste0(apply(mat, 1, paste, collapse = &amp;quot;&amp;quot;), sep=&amp;quot;\n&amp;quot;))
  Sys.sleep(0.3)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#39;https://coolbutuseless.github.io/img/polygon-fill/polygon-o.gif&#39; width=&#39;50%&#39; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;ransid&#39; - a simple image to ANSI converter</title>
      <link>https://coolbutuseless.github.io/2020/04/27/introducing-ransid-a-simple-image-to-ansi-converter/</link>
      <pubDate>Mon, 27 Apr 2020 14:46:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/27/introducing-ransid-a-simple-image-to-ansi-converter/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;ransid&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ransid&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ransid&lt;/code&gt; converts images to ANSI text which can be displayed in the console.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Because.&lt;/li&gt;
&lt;li&gt;R pranks!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note to be confused with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.redox-os.org/redox-os/ransid&#34;&gt;ransid - Rust ANSI Driver&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;ransid&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/ransid&#34;&gt;github&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;#39;remotes&amp;#39;)
remotes::install_github(&amp;quot;coolbutuseless/ransid&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; - because ANSI is for display in a terminal, it does not render in a
markdown document. The following images are screenshots of my Rstudio terminal&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;im &amp;lt;- image_read(system.file(&amp;#39;img&amp;#39;, &amp;#39;Rlogo.png&amp;#39;, package = &amp;#39;png&amp;#39;))
cat(im2ansi(im, width = 120))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ransid/R.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;im &amp;lt;- magick::image_read(&amp;#39;https://www.fillmurray.com/300/250&amp;#39;)
cat(im2ansi(im, width = 120))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ransid/murray.png&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;im &amp;lt;- magick::image_read(&amp;#39;https://placekitten.com/300/200&amp;#39;)
cat(im2ansi(im, width = 120))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ransid/kitten.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing devoutdrawio - A graphics device which outputs to draw.io format</title>
      <link>https://coolbutuseless.github.io/2020/04/23/introducing-devoutdrawio-a-graphics-device-which-outputs-to-draw.io-format/</link>
      <pubDate>Thu, 23 Apr 2020 19:47:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/23/introducing-devoutdrawio-a-graphics-device-which-outputs-to-draw.io-format/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;devoutdrawio&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutdrawio &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;drawio&lt;/code&gt; is an open source web and desktop application for creating and editing structured
diagrams.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutdrawio&lt;/code&gt; is a new graphics output device for R which will output graphics
in the drawio XML format suitable for editing in &lt;a href=&#34;http://draw.io&#34;&gt;drawio&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;why-drawio&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Why drawio?&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;drawio&lt;/code&gt; allows you to quickly edit structured documents online for free. By
outputting in a format suitable for drawio, you can output graphics from R
and then manually edit individual elements, lines and polygons to suite your
needs.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devoutdrawio&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)       # devout framework
remotes::install_github(&amp;quot;coolbutuseless/minidrawio&amp;quot;)   # draw.io doc creator
remotes::install_github(&amp;quot;coolbutuseless/devoutdrawio&amp;quot;) # this device&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Limitations&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;No current support for clipping paths or rasters.&lt;/li&gt;
&lt;li&gt;Text positioning and spacing is still a little off&lt;/li&gt;
&lt;li&gt;Rotated text (except for 0 and 90 degrees) is probably going to be placed incorrectly.&lt;/li&gt;
&lt;li&gt;No code has been written to handle changes to the font family so you’re stuck with helvetica for now.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-usage&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Basic Usage&lt;/h1&gt;
&lt;p&gt;Use &lt;code&gt;devoutdrawio::drawio&lt;/code&gt; as you would the &lt;code&gt;pdf()&lt;/code&gt; or &lt;code&gt;png()&lt;/code&gt; device.&lt;/p&gt;
&lt;p&gt;The output will be written to an XML file in the draw.io format.&lt;/p&gt;
&lt;p&gt;You can then load this into the &lt;a href=&#34;draw.io&#34;&gt;draw.io web app&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# PNG output of plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot(mtcars) +
    geom_density(aes(mpg, fill = as.factor(cyl)), colour = NA) +
    theme_bw() +
    labs(title = &amp;quot;Hello #RStats&amp;quot;, subtitle = &amp;quot;{devoutdrawio} - draw.io graphics device&amp;quot;)
  print(p)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save to drawio XML format
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drawio(&amp;quot;/img/devoutdrawio/mtcars.xml&amp;quot;)
print(p)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;examples-click-to-view-and-edit-on-draw.io&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Examples: click to view and edit on draw.io&lt;/h1&gt;
&lt;p&gt;Click on an image to take you to a draw.io preview page. At the bottom of
that page, click on the pencil icon to edit the image in the draw.io web app.&lt;/p&gt;
&lt;p&gt;The XML draw.io plots can be downloaded from here:
&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars.xml&#34;&gt;1&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars2.xml&#34;&gt;2&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutdrawio/ggraph-simple.xml&#34;&gt;3&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/img/devoutdrawio/geom-sf.xml&#34;&gt;4&lt;/a&gt;&lt;/p&gt;
&lt;div style=&#34;width:100%;&#34;&gt;
&lt;div style=&#34;width:45%; float: left;&#34;&gt;
&lt;a href=&#34;https://app.diagrams.net?lightbox=1&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=mtcars.xml#R7LzXsu1IciX4NTSbeZhr0OIRWm1ojTdorTfk1zdwMotkdXHaSFpbV1Z1pjgXJ6BCLHdfy8Nx%2FwVm%2BlNY4qlSxyzv%2FgUCsvNfYPZfIIggiOfn23D91oCBwG8N5VJnvzWB%2F9Zg13f%2Be%2BNfLtvqLF%2F%2F6sLvOHbfevrrxnQchjz9%2FlVbvCzj8deXFWP312%2Bd4jL%2FmwY7jbu%2FbfXr7Fv91opDwL%2B1i3ldVr%2B%2FGcWx30708V%2Bu%2Ff3KtYqz8fh3TTD3LzCzjOP3t6P%2BZPLunbq%2FTMtv9%2FH%2FP2f%2FtV9LPnz%2FMzdkS3zU4%2F%2BnfxV1GZLmt9v3uNt%2BH%2Bjvvfxefxn5Mm5Dlr93A%2F8C00dVf3N7itP37PEs9dNWffvu%2BQ18Dou665ixG5efe2H%2B55%2Bnff0uY5v%2F5cwwDvm%2FNv5lOt%2Fbx%2BfB9feFCAi8b%2Fvbwf0%2B3j1fvvn575p%2BH6yQj33%2BXa7nkuM%2FWKbqP1qi%2BHdolP96779N33Pw%2Bwz%2BL2fTTW7KnZn2n3c2fz%2BLAL9%2Bn7Xf7Rgmf4Eo%2FlvTv5txlCB%2FAQgBIDgBYygI%2FwfTD6C%2FAJJAnisBBAT%2Fty3FPvRHb5j%2FCWA%2Flji9h%2Bs3H9K6%2B3%2BykPywo3qwnGW0EHyriTON9c6ZESVBwhyP8jOD9MaC3NJX3pxsJwoNK5exKsSBusAGA688ndzsABbqmxGoZeJyT08qBBVuwf%2FmCd98HaDwBM%2FLEvlYWNcVwJG%2BLcYRQJ2oUHyY013CqrBAM2w5mV73cQyI1MmBmP77PHswLu6%2BTJK868Hm3waUTvnv6P2%2Ff4OKBy8c%2Ff77N9AAfuEgCIMEQeIYjOMk%2Bj8h7Xc8%2Fc%2FoyeK1%2BgEu%2BPsvRvz95svwe8v%2FJnABAAhAAPIYJ4L%2FFdAQHP6FYDgA4hBJgij834Dc%2Fz6Q1SGlnjsX%2FQmyfy6QPT39RQA4icEITgJ%2FX4zt8b3Gk879ibF%2FLoxBBPQLRJ6oR2Jv7MP%2BriArzjILJS35E2T%2FXCADCezXgzECRQmYwAno7woypbZKo%2Fqcf4LsnwtkJPCLgAHiOfnA7QHa3xVkn%2BLUp%2BPe%2FusgS9znFRY7SgdrXPGeTFt4tMSDK85BOFoSkuhIBMt4iKfvxqz9nIALfwNR5MDDD4lLtiDHGZIGaaxOGA9WjimnYwI1FqAJ3POs%2FXkSmEHJTNt178PAimsocOBW7fSgQlSuuBY6cqvLInyjE%2B9Yp3z64xc0UyI9lKfT85vhkc%2FAaHPIGWffUtuSxOfXotVuL2OIZyz%2FFGADQfTXEx4BBINAAIfJ%2F0BoggAGYghMwOjfgA38P6cx%2Fesoeq8X%2FsTaPyzWHu%2F1C8QeIBHE48egPyzU7E1cvVQc%2F4TaPyzUYAR%2BoPFoShBBcBgA%2F7BY2zjGOG62%2FBNr%2F7BYe1jaLwBGkYe4YQ%2F3%2F%2BP6tWZSmW2brD%2Bx9g%2BLNRQHfpE4CIEY9oRRDP7DYs2mIyXpw%2F%2BGX%2Fu%2FRX%2BCvxAI%2Bg1dEI6i5B8FYv9L%2BYlC4C%2BIxFAEgQASAv8WYv8n5WeYtOunp9Q%2FMfZPhTEEQn89fUZIAH4ztn%2FfPFqing2jD9KfGPunwhj8SFESJ5AHPxhBYsTfFWOUYUhNKlF%2FYuyfCmOPCP0FgyRMQDhCEAjyd8UY1%2Fip4PJ%2F7p7%2Fc2EMhIlfGAbAEEFCBP73DZWp3fGiUmR%2FQuyfCmJvJg0An%2F6CAIGS2N%2FXjcXhx%2F048fRfx9j%2FbSmMPyrWUOIXhAEgQpIAiJJ%2F4GxZUGnaYcr%2FjVqgP6H2x4DaM8G%2FQBIlH0EJkgT%2Bx93bDNg%2Bnx3pP1HK%2FCfU%2FphQgwjsFwiDOPzEPwL8j8q1%2FxhI%2Byx5V9Zx%2FyfS%2FlGRhgDALwDDn07hKIYgf9ydzUnpXNbJqj%2Bh9o8KNRREHuoPwxAA4wj%2Bl4X7A0JtOL%2Bduqn%2FjQTan1D7Y0ANg%2FBfJEyCIESSMAD8cfc19YGW48DT%2F%2BtQGyI4apscTnO%2FqJbseR%2BYoOktBwyLSZJrf1ih42kgws%2B3U194LufREiGPCZwP28RdMjNHNCHEljMDkb79%2Fvlvc%2FffDhZ0wkScPB9w%2FOvJuDB%2BDt6W4Lcm7Lx%2BO0Cx1zfThl%2B8D7hf0GMPReYJ4f2BT3lRPAcw%2FnkWgx%2BL9%2FTw%2FEjUF414rT6tifOeC5r3MUseP6%2Fm2xvP1uMWVBgH9D1AfnsXkRnI%2B8UaT5L7bhS%2FNZLf33uEgi%2FMf%2F9l%2F%2BnNTye730eWv28hk%2BftPE5iOIFv74vep%2BxvX4rCew7F%2BflJ%2B7k19tUsWE%2BL3q2kRP4Mon2eQO8Ovuu3A9Vvh6BEVg3Ysd8R69gn38MgeZ7tO%2Blr42IywUL4HXpiH0Ij0gY%2Fy7AgdvABpc4W%2Fkbbw6D4afKRDIRhJLw%2BH8C8M%2B3Cw%2FRBEq0Ba4%2BzW48%2FswUuX%2BD%2BpHfy0RX8Y0jPjY4o%2BtdCbkCzG%2F6DFR5AgoEco6%2Bq2XfxvW55xZcPNMBoRyRZFWAZCn%2BLQRfi%2Fuov4ZNPdWBEXyHZf1tao2N54HzaGkE03FMlv2jgtKZ7P%2BfW%2B0bDyefeceUe9k7n1KXwpifvi1UK2IvkXb%2Fn%2FwOVrh1t7w22Fk3C69aAjok3iuTHAeHcejwGQYvOTagXaW1Dmg0O9C5iou4KnkaTQG%2Fd9q4cFU0QkHbw8IIuey%2FRBa25CTDZYCRaThD3w6exUgHSOd%2FVh2DpKByyPN6%2B6Jez7mZg7yC0uti6yx8NPd6UG7nbOHiFSQcNSYn160imuI9lHFO82Fr1DCGtI196p35%2Bp0HkHXJ8JucO3e9gU%2FbCoqzHvtHrZO8XLzrhqPpFRj847pSlFIckG6DCwsU87zE5nxprq0AAD41FA29B23OH2FRHr%2FtZ2t5cFz%2BRwb20FLwjviZ%2Fzds%2ByaOsCnAXnEvkl14DHCTQzBbbYKdB7Xt6IEf3WKER0bsaw6WHaCcUTaYSJw4edpt%2BB%2BGBlZiir336GY3BSc%2FNt9qS4lcb8GVKmgYyzjvUFCxb8S3JdzxwqnOTUZ2AO00JLc0nxVpveuPL2lTSbGwM%2BnelEQe5QO3uEtMKOoXRbetVJL0hHLekhngBG%2BhhgNV87gSJt19%2FL6KSx5N84PkNLnLLlrCbNeYItJAOJN7O32tSLHqPAuVSGdrT3Q4Uucsj8GszIvJTo%2B%2B8ZjIQaCL3AkUz2pncURdqlPfUUPaGQifbHQZiVnTr84BTDOspzZPNsN2rgtQYiDzH36Bgtq9iZ4wRNFAUjcJsZDTyghgmdO97e8PmrdZSBdY2SsDSiuHKSVq3bcrjJhKo15e18nov7gUjrWiU41QsVTQQE%2Bs3ccnGgPzYEg3RLCfQ67XR%2B4vkZZIHYxq6bMOcCsIZOHvNe7uKMZ785%2FBdTHHTKIk6pBwKW0P98UuAgJGBPlUy9uPTtqFttSmVFtoPdoa6SHyDMT%2FNGyh9PZUYW%2B3ORQIcuQlzf3XIiZs0pMuKl1cEmw7T1Jc5IXYIM%2BNmfee1Pju1pUJ5s%2FXXkNbXG4cYRYns9M6rhsTsAAv%2B7SYFmn7fedVsggvvcxU97RZyywIaIqzOyHp9LKQNh2U0zVaHG7XTnnKEgUzASUtDlAhGQBbs71tIYAhF4iFGBGkYOZnTR6mseFNBjenlOYY8IhhFP8xwxLr4Vadd9cgdQ9lvrjhrSOTKJWZGDd3PqmgqFLj4y24aJeKZ%2B8YQevoeQgEVyYa9sQZmyx0AENFxgeAgeTRrmIWSwN4otq3zoc1FjtfRpqFnfqLva%2B3eG8IbjP2qVfUdDQj5Zhgo7m61yOzDGsYMsEeZbl5AhmAfMI994pCFwp%2FxbozZHmc1S9vHO9N2Wa1Q%2B5AsXsAEFXzMHX1D6FUtrT5LoEMSAFcYI8Jsyv16VV%2BkvN2Gv2uq9AAfH0vyOjHeMm3RgrKjKKiBJdH8hShCHhrjr6%2FXuCVGOzhflGnqcgQ9pBtKZbpy0pptuBmM0U85oneTX7ZuQrVRaXaG3wRq4fSta%2FaPZloZYHrwXRWS4SWhLibLFLt5YL4BYaU8enB3Stcofhsq3ivhB4i0U5UshbH8wsiAxaWqdB2RTDNdcw3S5nLgQQccDyFIoupBQESXSmxyS2EbXxyglgOOEOzRzR6p4QADNXNMd3DdASY3SXgNS33zZu6bK%2Fi2VEe9LpbW1n7I8QYUfA17Yqf4XS2rr9RQ56Vtw6WGfuebR3MGJLlRW%2Fkp7xBMPtBYmWjp5o%2B6FBZt%2FloQyRXZQbilNOZW2YR9UazhYVYwEgBYkTSRtHigSdA2U9TEp3oD%2FBh%2Bq2F8HOOdOlO%2FVKtLxQ4%2FSAnyrXcnIhdMCV93JVJpv5po8Jr%2B6tm%2Btq6COdvK8RtvqhjjdLrMauowZpBgMiOgj3BYbFuldJhTi8tjP8h1pdZYfKPtJw3L0tRQ9lmC1hqA12zqiO4%2BNsydikoRS0722%2FG9mRaLE4l7GZVaYlEpgNQF1EdsAYzyhJyx3Xc1oQxhXFPBJvP8rnCcajmqeDzsD7Ert555lgJtGXxL66PsAUukHg6MhZItfzcwMioIXEeCpue%2BkGOBqnYU%2B9ClivCZ%2BvpikLipgGg8gMsk6of%2Fhv4L%2F5sqp7wKRpTlCP4wlsaMiT3H1%2F2yg2OS9ddf9NR2We%2BMybck%2BUSeM5wThsWGnGx713le%2BMtaY%2FMjyPjI8YZvB4Nlw8hGhJqdNyxuhb28jjv84B7G19JUAQtmMy0HXeH8WAIPqUoe%2F%2B2a5QWJEVavscW%2BwCY%2F1DXi4Rtp%2BovDgVAO2QApfEHIpKL55l9G%2FGgSXfQIe7QWKfMWBnHPKgMlkquRV10W8z3XvsQd0n61Fo2WivxVJU2NqNeTU0nPWktrbnun0uEGSFfVPcbxBXSscF9SIYSp0Gla4970tLnxsU3VefheRT7eZckaKhV7o%2FZpVHVzU7E%2FUgCQ6irc9roYnSXQX4uT2FbV79LsekSnG2VZtA8dQLKsK2cvPPwlAA6D8vvLq5NVthtjPM7exCg9yyAHIZmK%2FHAAp3TWDbZxVfhZbWyBZTpcJc9KtNLJueIhxUdfoMtaMMjaK2V80xbWuWBgIC20hY%2BsAl8HvO2Iz0vCxJSK9UGvHGQrd64Uxg1d5Cf20aGfLWZChh3PFZfDHyvHdoFEuYhS8gx2w54Ns7ZxGY7hiJ4Q%2BRwQqOGqvn6ZMCjq0UI8n%2FG6eYdqXVW1b5q2ZourUynZZ1c6vbawcu2zgd3p6zjKG8hTlGuWVVfeWIz0%2BfasqMAwfgKadxscwgFJZQgG8jR%2FxliykcDMyTDorPEjM6ni08X2XBwGYIi%2BksQ6k6q4qpdE1WE46rL9in142S7WiES83nrqRT2EhpLWdQAUDB95%2BlSUBkl86jvXeRQDRfcGrE5g1ozq9wxbZmotr9o2Ok3Vs9RakwBhqIysNH%2BedJFxDBfakHDB0gTjRFcmayGH2aOUauqEShzFeGo96kybVVGWBaldQR7IqLNGL%2B26istCiCR6uYdluK4cDTRoKS3ZIOJZ3VL3Tq8xW%2FXcV%2Bhuxpzkqd5P6Wp7kwLH3IlU8Hqd1jpQFKum2cI1a%2F1wBK1dVJ4qDyYmmDcGHFkpo8cB160ZZjL4GRJvPfcDM0izjT7DeTulvTA9ahOAOtLR%2FT1oguE7cbBF9KVHpd%2FlZEPgMVPVMiR5rXpyqQba6rrROl9GGqXA%2FKuOGDDS0pbDhhT4TuPH4TZAIQ%2F9w8bMw1bohVFth%2FOcEsife1S2Ig9P%2B3nHw5lx6nPkxyWVpyBvS0UYuSxwq3fj5aQyDBekqnCEZhftPrR%2BqicuER8UxQv90zrSE4gEieYYWhuQZ0Joug4IFC6qcMiM6rhimiwdrLwflxUO8yvD18qpp4Q92M%2Bw12NZuowd0yU6Ujzl%2B7dyyFgDgJUZiRNj%2Ba%2BPL%2FPeuz%2FE1jvBEI8lIPNyRX0D23JqFUI0Y5DyzH6lGR1V3rfkMZY0mKHcvE4W27OzEPoiRJ4CCsq%2BnxD%2Bxpmo9VUHZ0vd7gYAyDB%2BtDyKegIZDYy9OnNbYQaPukSUeR0OI3WOIy6A8uxyzAxAlqTl%2FbihEsUbqqUVLLqWuCGpJqBGlZ6RT5KNrF7i%2BqNL94D4VtG2sYta0zjNFbWrETp9sBgofcVcjrOrDhOuTnf6MMXE%2BJz7Q%2FzNkw%2B%2FkDRDR16VZs2%2B9mkDNDDHBnGu0ET1RYrxkovcFhVA7Gx%2FEiTVex6TtSwyHupcIq0hcuPAiWW2XLO1LzIFYE6rP2ceqgfKIYVRwJeMkx%2BWTvLQpsIsRIUBLaSBj2gJfXMemWscLsC2apbn4dSlpOgXmz9ezfXFJOzIfir7kd5c543c7qq4maXzyPJoP9rLHc4%2Fa8rgWCcV6MB4o%2BgQEgzruQnfxRy%2BfjEGaAXqgIouLedkTSUsDuogXKZWai%2BC6eR4opPqLCbNEE%2FzSovGfJaMkjUpXw2yJAMksaoQwhUXe7mFyDFvRoQCL7JYAvjGbA2x6JxyXYDDwzS7dp1tJGerUYehNK6PCMTUFH7WFT1RpKggjYYhG357TH4z5HimHK3zqKzFkH279rLHx%2F1SYFhcLX3lVccA2lCdeQZtXzNlOoaLKbxOXa40cycPfHKvkatBECGv5qXk889Ls1sVQe56a%2BvAPQoFeu%2Flu0ISBBl35eAVyDwrn7UNpWDbeQCN0JRkmpWdkRTPHg%2FX0Q8c%2Bfg4%2BXR1QqOTP%2B66TvhXjnzLvZUYGcPK8qBORXBvns6JgA9AsWVonNMyftDpvE6zczMo%2BxLDrO15e%2FCqVxKtJCF%2Bpxz9fMMjQHqPrhR6RKqCjVIXIh518S19WqOFjdI5EYi0eokwzpdev0%2F7xl0JCsUfM9ootKI7rRxNwZoOVsDL5RzUYFijDMSZpfKt%2FVLqqLynSerNVVhrnX3iLHUxmy8Ak6nK0aBBmGuAFsn361svU%2FmZABJ4I%2BdhhcEuJ4UAiVNVTER39yzOB5%2FGUuiY8QjhUQEBhiECfzKDRC9YxoB5wXq8Sh3Ru0hSkHW%2BNEus8LJ2Wk4RNqEg5hLXeP6UUtS9qpYidK82%2FDNbP3kh6Vz%2B3RPKFAj7NF3V9hqeq3tRCJYy4u6HCWS531NT%2BBHpKeNO6xoKKbnl5%2Bks4R%2BPL7fSZ8U5DohOR7EikX6ECWY4txCgGfUwfkbHZJwbFyRjget4%2BSB%2B75%2BbD%2BSyJ3KT43Q%2BrITlaJAc4S19SxBclF59OeUiAlDXx3p54dho3zI6xCY8CS%2FdREUKh0ePkQh4LPn04e%2B9hCW8YNGH%2Banicli08kTwRVzC0%2FLMYmcnEHWMIO%2FlsOXZenX6kUrngLQyucds%2BU5AKg3kO8wm3osN72vJAl9jLCaJKbrJ91opO%2FL1tL1aBMNX71BcH6l1IRT3eSG9WpIMsY7AALf80QM6Nm9CpqsQUKJR4rP1NV77dGLkDj5aq%2BvjTlURI3d3BGFUB3Pzt9N6r1tMh374xFrpPBCG0qS1gFSysx4y6jShrxowbX6xQia5QsGEF8BnVViWy7CQTOmmMaGmGARb8qab8GB5qUjJ5BI3GuHFIUHzcZPFsx3K9RqNzCwUKuvcrIvPOv0ok%2BFN9E4yq6ImUDrhMUY0tYkl8S5ZkKjIYrvNcbpYJwOIYx%2F6QNVRx3Hh8azEY3FXFIOWWvkvkz5fB6nUJaEWnxFButnZm4LtjdLjayB9gnzTbjH13KOcOnMEdhXzXGqfy1Cro6wdxYy1AGMLzfsXAfCcaS4nhSkvWw85h0Ud3fWDrRx15IkQjmxQZYlRW7xVwRJB1LBcmLnwgR41J%2F2J6KzS0X7LXwrZTKk5GquxXY%2F%2F6VwwMJmCGwYCE6SC%2FrjucVwmdcYxc99ti3imSoA3p7Y3ImwWRyvSgl9cWpVA8WhNaLPBkEvp2cqrW5dfGBTeqrse0uuat9lHwSEwQw8xN40QXFm9vQj77pEKn3XQWGOjMbZaGxinAQzmm0xeAyD1qEZlv7K86Q4BFt80raXEkjgyrPWKekKpGizts%2FB%2BJ7l3sWv1Z5HgkIqjR%2FZCm4vn5yiiUQTFWY1Q%2FPWBusebRben1AdHRQClqP7yEKFGkrAlKQcuX5i23wxXgViMus1SN9uDS0jN3t%2FdgCf6Ye7CQD0jFlDILAfJxO8wE8DgMNkPDMiSTORhdJf1yCi5THCwfBRB93CV%2Bjrhu2o4oY%2FCkMouDSCtgp7bRyRLrioQr0UnzZsuZeMhe3cnGkA%2F46Dbb7YWhngvlNsTzXqWOlRQU4VJZ079bdeBXnxkpZS7WaAO9KGsukoqf%2BQYZeECSs%2FXZ0vFuop8I34vZuiSpbEXOUV2CiKc1ggHrQE8LrQaWNL16GGWDjjWmiod%2FxzaIEYTbce86enc0TyC44zVdKzYQNANJghhvDIIzjt%2F8kSYVNZYR82TUNycKVkEhv5stIivSN0%2F0UeLTLYcG7oYZk4ZXYt7NWZtwHqfbbWHgTY82yZKR9s7MueHtJGCwbq%2B5%2FouIJavjJ2%2BHmatMjVYM3XfKL9Pt4m81iV9gJKNrev%2BlglqCUWdabJp4Qn3mgzzqMGW6hbh8CWA8kQCuT7dVWisYhSbSB%2BfipWa3wQ6hdVlHdrsR85SPkX8kAqOxbpxtUnqXiZlyxSuT5wAva6E%2FOM4YuE8sJ5Kkcv4TqViyGarmGOiNA%2FX2lckkesvbHmMkXANr7YcEralPhcovKbZLfXqqq%2BPCjohQWBV6mFM9AdGgj6hJOy60JIAOwt1Z%2BdDs2DrfYIoAgL31civfWQTMKae9GqG6Kt0VYQZWrtZTkKVIB%2FRDWSEaUjSjCaBX71%2BxIxPsgxDYWOglzrBDW6FaoftShxLm%2FpHMY03lcLjrZhO1eM2cFJGPbM6pFJ2hII5aEQsDwNXlNwYx0JLZvO7hi3A96XcqNUs1CYvvcASR%2BrSqY1RGBOlZJ%2Fag2IBv0y7rLN0HpvpaDrLyLY0iYJFSZKYnZqEpNbM2pwSGskCXihY%2BDSTPWrAQP2BHNrKyigZlHTkTQZK7fi1hdzqAnfwz5BmnQkVfrbAqBvJLp00aHNfVXU3DM7FeYvqSq9CBtkMqCt%2BddH47lRcVz9G9SLxtOlYVOar0diJXAQd5gA%2BBIqaWDVw1cdzZ2d1i0w0rucjJQaHJiQRKwcjb%2FOI7q9x%2FklqjA8vw8KbC9eF7Xeof7SVGkbl2CLOQ2xU7Ehd5zs8bsKSJ6QiXtG00Cj1zbEgACTfHvwOZa2Be%2FMfxoirwWbM6rzScCjMD%2Bs6BphaXt614vYJJfzHrptLhYUS%2FjDmz77Ttb3l2UHQktEdUUM4m8txC%2F6lFJ3FmZkjDvn3GyGS24U653K4%2FQHo2zXJoN98VO7D3lKWsq1ttW6dz9DXzvzmDVfXpscjxTiTYw7Nyt%2BggUTBlRPMq0823V5cpfRIasG4T61Dpnqz87GzxeW%2BxOrq%2BFYSjvw8H1cqWVkgeBL7tSr5UnZaRHGRz67czkESjjGfDZNMUH3PQPVp5EjWOOqcyWNmki4XdYLssT5zPWqHwUXqPmJMTSOAWJFFBx8CfpTIqKHWA4Shfywn4jtmIID27on5GJVH%2BDi5pY58M8mUj2Oxn74s9gDamj7aiHp3KNOAtdcEWfnXBlWaV8P9cGQftLfxExs7hoXB0QGXAiYZIw%2FSPBqC5MmCw2KcsgoTU3xQrUwpNqZIkd6PZ1m%2BtUW%2BW4%2F0Z096M4pYhlNTxNZY1I7eXMbgWKosqHK36NUrYnSBGleaGV93JdD9Y1S1CkprZ9rgQWDsw0RzxAz50Bop3KaW7E1FxLYeB8Qr6GKX1nH8Ce0Id0nFhfOlcjU7V82idH49Yuq7NlJE9ciswdpbEYHR9NDsTFhQPMINpU0pk%2Bt9gPWP79mVhSnAdz9J9ydYrYB7pvy7usv4aEjVUWWgnYM%2BU1Wqny21vSRU4gSr1xhtYeTwlmaESeOEcmpanWjkOEYMWNIv%2B6yStLZK5UUly3OE3FNSKvUF2ThqT5ASA8L3oU%2FcaSdz7Qkks0PkRyEq4AMhqJjGtLjZqZTZ0qv4koDWctU9Uf4hriKxZsk4XV0oa2dlyl5b854z5mSUBVYenUj5dcjWZ5Qg64ur5L4TYuz0iYkm95ablHMKYJs9IrKu5ziH61SMyhgNHuWGnDw3ZId51a7fc5BMsDth2a6NvYbAU3inGWj%2FseizEkgwEGtW%2FgBOqWIey2nEm0YVzb19okmXMnpoog9Xdtcp%2BDxUr9UF7SdJ4%2FD0YNBiY1RvOsNLO5U09GoFtFjMDkukRTjqEnPPuqAWXrXIDK2o6k7ThS%2B0jtPaJ3%2BlULcKvg43tnc1fWDwNG1j8hVkzrMLETdPH3nb%2FKRsjqiyA2%2FdJ3QvcUiD5g5DRsEO%2FmQXyhsarpQy8fLxLSI42dUEhv9UCE9Ne%2BWUQWe7ibtMxKnTbpScgYuMnxGMo2hXS3sjsUQA1lyfTWq3dYR%2F2MITkehRxsfvTHxdaxtm6uC4Isxk%2BiqVrnx4Mb%2BZoLaKKi1IZeSG11kLb9LAzr27IuCP2GD3pFTAYxS5FpgaejvrAYVSAJPITXl%2Bl2wMzegEO7OT%2BJqDMKZywjwecIsZUS2yaoTF0HQL%2FJheN90s8nzNkGP4Rl%2B2UpchM06vrdHmVbGZvsPS62UHKc5jsmxqwEh%2Fz1v4iBsXqx8kyV2w5wXJhqTyUTOl1isURWeBMtgW4lL6qSNmHdFx3XQqrn3QzTeBMfA2Mayrd%2BvfNlzcrc%2B7y5mt6Z3GnU3p2KRI5Bk%2Bj4zfuNzHUQi0Ou1ISJkKUXjqAL6Air55BFWnalaXQzGcI2adTZBZeZaqS21TKfJy3ZNVp7qkPZ1iqbCU7CDhIWScX3Yg5bUMKAtt%2BwLziEnKumbXc2y7Ky3YolQTl%2FiA%2BVKri5Qqd56XjSMo%2B1V1ZmEEmDovapfXfWYPnb0pW%2B4GaNTLB%2Bx4mlvPipiQ76llVk%2Bt7Il6KUSUwvBMG4gs26IWmHv5wz5pxI77HMk8CzzEdZPumK0DYqowUfrIZoIym6J2o86BlzdokEjxGih%2BzeS6Zuutxaqe%2BCvokZ0hWMQ1IyFhJa9vHz8FO0nkUn5%2B%2FekEKJw3lnpcrbSjvmSxfnyq1Ut8A1XrEgRepgjb44XkvHIK%2BdUYac8IvvdJm1HFSyGzvODLY5QtkgbV7bLi78mF2hR6uXf16A26aI1L8OyllxqJWg5M5BX1So3dtsBwrhfsTklRlizZoo9jCGPKAWgMviKacPLiDLWsi3QdP54JCpmhWTWsCGtcEU16mXfJfytAvjtDIEcNwqunMXfd49T3ylceOPmka81789ZNwGHdcokGPN6lZaRQwpQ3pyTyZUX2SUKk9CNBPzyLxS5n1mL8ytWk9wqvNbj2cB9Bj7ppvRyuJX%2BYfbPfSO5%2FNue5zeUI12N06pUjbc47GXiYC%2B7dej3CQKnNL0Hlk6FsJKJuf7ZBiyoSWQHrAGEWekX5jA2m8prMefCwV8yoaMdPWcgAyfpLYJzf8oavIEhTMll3Kn7ZS1eWdSH4pb3QJ8khy6QUFlx1apQ3B5XkVkh97TMc6dEtJ93Kuw%2BZuU94CvUa%2BQ62Pe3tS%2BgOTzkCmQ9U%2BllSijoa94nUIb06BHx43wa38qbVDfmRbt8FO42XQz%2BYblAjpCEbOyyf5RiWEQCCQXGGmJAbtrvect5yI14xSoxhCqKkb8zGOvNAAqwwXKbpAsCMktE6AZ%2FKORPh2jfvxPM2vi7F9zvXPU335yWYLSe8M11ciGIl5F4DwUQyf6kwE8wpO9OVxt%2BCCL%2BIJaw3EbSx3yketauatcY99MdEfYiHL40Ug%2BgkqNyoKrUWzDniHgbE4BcaBkI8uI%2BIyVo1YLCIOvBBWRH5wj8ce3nK4xHp3O3HfaCpsMdqvWNoMnKEaBHMjBrcc857%2Bi2vePSazlXUFoGPnnoTcV9M3rZAUUZqx7ePC8KzcrGAF6QOQl21CVqwejqcdhJHT5XxVhrap5rbdzj50l0vOV1FPArYjfiejO5%2FHhzpPkvpH5b2cGfl00c6oTgiFSyV4JWiYwz7sF4uDGvYWpTWOB11FituUZqxgASqdzYpTvWR1Si5eyQgmUnvu6bqYnTSJjdjdE2T1q9WFxkr4rmZSKk1wOTKasDzkd6rSWqNwJmxXWG6JhlJeTnSjCLqSNk0t9fzzH8Ldigrvo%2FfkrOUDmet7BW6K8KcakL6QqUdaBQPp4O9FFyGTPuGozLDrr7ntjGSxyETjJtVfXTMQ7mA3t3rum0IxxDvwL%2BW%2FhhVuRb4x0ZEgvS4vfwscst6e79WhP6x7%2FaR0DvWGh54avBbB3O8uQa%2BB9HOZD%2FMma%2BnfIa31uH8SVU%2BZdAPMWlojXuIhejEOVLpMTptJsuE3ildgsA9zujVwl%2FkblSnK5oIpPzhBfcjCNWMKnuAbuUVCYU94lpM0kz%2B0uXPhxreKpLTxG41Wrp0ZttOXL89bX2XrL4hmLez8SG7y%2Bnj1EC3Ba4r0101D%2FWeZmWVVVmxubv5HDJMg6qlctUjY1z5OJ%2F1OcBFisNTV9xUulLigfAbpmvTNIUftz%2BNqx3UvfhqEaKnZswfve%2FGUm%2BHtuWbCAznZ3kceBxaVfR2CfpJjq9dn2XzGUa8nlZmpmIMIZDGUqTZqH0rMU2S7BS1JKeUXfr6Mxu3ds0jSutCKXFirWycFEWjkBOKmxyPOWmR2Lia2S%2BzPHfI2fBHIoAiCNHaKVorRoFJ8ebTJyCNSqLDwi%2B%2BXKpK%2BnzFZlVk6lkpdW3q9%2Bi4U%2BYr8BxZIKQPbqm%2BTOmF9uZ2nw69f7TCQb0qPBQE2pXYecKEn1rknlonEy%2BDg9YlAnrivZS%2FRX00cLI1gp%2FN60TZ7%2F1Ff6oP7%2BbRsCrEGG%2B24YnVrFmG0qQzAMz5aWpwus1nuonVJuGPquXMb2nf0BzaxUJqzR80SooMuvJiCDDbtY%2FwqId5bXgIgqDEQVWnQLlikI6g2OasOrZrvrm8KqGIxTg595ObxkrYx3DU4ZwHhJbgN7JE68wttkQDd7SIr8zH1OnqIwer%2FEwJz5bHEZ7RzzzyboIdolVTcTNZqyqI7k92DPK1e2H0dwJRlba%2Fg0ZNnSZS2jpbwCN7L6mmZSVJd6eSqLvqp9oyHnrEKFRwoPHbq3FIKekcZzXvZ9WUdThEYhJ4C7fWY383rt%2F6kicWxfQdwifwycWtDmaK6HAsMaE078O3qKMxJX01xQIdR%2B3sPx%2BMsZw2dWnfFN25uY%2Fjzfc2TdHMgtvCXT5TpVp85GjLX2xreW5sl1akKC%2FLSSnvot%2Fhr5fnHCJBp%2FxLvGkvnTp9rTtchlHEtT5wTNXwmzeEABwNWQkImgbbAmEbbKVEq8EfJYXxEKFYB45opFvYIOG%2BKQZ0lNcWMzv1Jg7trMXZvVy882MGa9P%2BcYHYl34LeSqB3dDMopAvktPJJwzYhnPpa42lF4osLgUpVAvsK5kfrzDvwLJ2GAE9a4IUBK0dk21IR4IuCstI5OfTYX5yi6XzcgUqpFE5ZJB5Y4tzJJ%2B1NAcZmOzA06tTl503cYg4jf7O2bpZ8IGya4UpDnIC3CMhxgSM7A0yjMksHJeTk859YgtntLdZWIM3cmUTm%2F7IEUcRnI59nu7jDizAKEJevNqHN4u9tUk6jCFfsEt1Ur3fUoWg0%2FRcP%2FiYIm6dvPuNJGGhvXwqNsiQ1lwiLFVg7G4Sxw7jZqwQmQ0lwNdXYRwcikxjXJWiXBXyCm9lplriuBTtsTZEgO8I3kRALVin2JKEwlnO485tfbnAw3iDOx2Phh7WgEjbWN9P8PpTIZ4bQ8BSCCW5h3qeWHHeYXAnryndnO6uPerMDFpLQ6yqtMro%2BMOszQuLeWOsNTPTOERdIbPPfGBirAoJOydhPD5WpK3UGMVj3wJE30X50m1MebQCwswsESwiITwLmU%2BiV3nk94k0rGl2EWKk1Zu2Tc1z%2FOnd65IZidUetkm5lfL%2B7XYP23odTfhWffPVtPkl1I2RTi7OQ9Gyvhb6MXK3D6kgBS1JzdENGxOFXc%2F1dHKwL8Tl50bgtlWvFtQXZm5o3qw9By8lopVv66Z0zVMCTI6zRtYugquxR3URerJCf6x8V9sCTmtZ4x%2F4Q%2BN5g2Ouk%2BLmW1GXF0zvDu2PRz2MgRju0%2FDZt2SwfkSbH28QTumr8nPdtW79m3LJINwRqWTaHo5Yq5wMUpiCXg34eaUFuAZv1T7nYH4JtmNWpmidwKUD%2BOfHjbIONOg2Jg5rNN%2BCpyaZj7vOuRYExMHqFZvI4Tc%2By6hcN2WMXH0Uz61RsPAh27MjgIj%2FYam71ZVr5W2J5mNGe%2FcbPPytpPV5al%2FzXbyENJHsTjDtl9C7JT3ZmFbhPM5%2BspNLN8xyQbaqi4WDaZkl5dTlEADr82UzZpvxO8ZdueY4bKX%2FYp4teXSIModrIgdBDV%2FucMR3KaX5oo2NKVPDtX3EXQkA0kVLVZmGIm%2FvVCvTJHJfkPBmUvykaUaKBBAeRmAGmTgXrBtmiMvPCm1GA6Q%2BudIjPjCeqvGSJ4QMcPABQWLqExPQnLNF8NgMSkSor6%2B1JsDfYNyZsJLW%2BPGxqtKuVVHnLLLn2CiS1xTBaJuy3bGkoZldBY0oviakSR5yTdAdXqyx1rkbutReALHOdzCsMEey9a1fGeTndbHyXhsC8Ym4A6dAWwGIqVxtgO1qbk6Id%2F92YfeatxzKY90z87sgHllLSl3gOt56UvxkAYKed7vhtiXibBtfUBB6%2BKvjv9AKmSasrXKtOUWF8tqmjPleFSViSMBCD72d9aaNcoZgaha1U7kIv74cpApZDeZqUALGjj8fZ6w8SvyI9vFKeQaICUSax%2F6NHNtL1YiNC6vsPtJ0JkIOpArVio0jY4jbhe27N0cqwD8uNZ2KUXiWIpJ0n8HzSzry7rIT4RW9NOA69EelzV19FNPyRAnaPGY3%2BSnc1Tqo%2FcJwFeJx2dOAWLTDJIPm1wXmDTVenjHSnyuRJtK1TbCBOVnytTcdRu5MzgHk0Eszs7NvXJF0zTQDukrf5Ma2eM5Y8F73hvtbbKQcGPXzgdYhC6pCsl0nfLCFy0fxQmc71ET%2BzfMhV2p%2F%2FGxWnuAVkjQMi3vaRQ0RVeMOOEB0C2Wu%2Bxzv%2BSW6Jhf%2FWV%2BVedIhvK93OV%2FIPFZhxFw0IABXiJNRoY7XjZagwOj6Q%2FRNM1vmbhGzM4G1nL4%2F81hIEqNJ%2FMs59g%2BRJwqr6cunkbSOO3xh9GsPoJOcN8U6YfsPzqmMrW5Fb26HqI8o21LtmXyYRxsdg1C0yAB%2FOPT7%2FY7xVTNxuCXl5k0w%2FVmG0t%2BS3gq3h3h7VZAT8Ug87kX42l9IqqR8o08VEaSs%2Bym1JTKlCi%2BGspPrzIggeVSS7Cf%2Bw%2BAeNuYw1KEE0I%2Br5uEy%2FslhD1srqWOOUDj9Mcsj5bRH6z6RdmkYchaR%2FCGkJUKXTqhHl%2FpQPvh0IODWvCRWIGmhCBxsymooog%2B3YJQLmQTJmY9jdOMFKM39Rt8CtDWQ7fJDmpVouY9S3ITKFyE8hQZS46vtNIZlS7kSVd8vVmilD3LgUOiCqyokOg9re6BRHIR0hb1blCxLhHyZh2n5cW%2FRStpWFFO5KcvTclmqr6HZocOR5oj7iTphGFDcleINYHeY5JQpc4w0%2BbOnPclttVb9aY%2FVjHz9Ak7eSJVLnPk58wNRlFwGj%2FLRjDdjf7KyrFoyTr5mzYxqJ42WPfHCcTNtMS5fw8vezbZARuhHRz3xHMVqlSTq%2BDUUWKR4Jp6IrXOFnjr2cWTNaK9moBRXaaPS1s3pbQCixCBgEg%2Bg89tOUQ8bk9ffK%2Br6QzeM34%2BqI2j11vKktcdPqIez9v3ZyYek6bDSA0Rt5ZB6BN%2FnrmG6ds3QXEfxo4kE5jvDvfjbSO9i515UYe7MOrfLXV1v5qWyAgROhxDxMNbnvaLPPDd%2F6DTOk4rkxvsGTKk%2FhTfA872dW2Nzvo9X9RFYr%2FuyF80Q9QNYjxESTOTVIOOZUCGUAndpN8Zr0jMCEMdbhGEvRmLXRT3DQVF8xtePyIvx5e04ty1jigbxA%2Fpxnln%2B0xM%2B%2FUYzE%2B1owWNd76adN03oR4i7Ps0LbxqjNnsZR%2BpQIIHs9Jb8fG6RINabLTdNcOPKIsaIp5cNZu9aownmzkjfN2DqKUc%2BwkQBkWLiFZVIGxfqPSGITg2B6orlsWRuFPA8RF9rlAwHn0nt8h0Y7zczky6Ymj2%2BW0%2Bm4SKwanjIeo%2F6qb5vJp7b9W58vXNCh%2FezUiAt4Lnr8kJm0R01TduLWhwxZ9%2Fj78p65phPntE%2F%2FalDe73omI1fQuKtTvFV1Itkpmfl6xSavoZSl%2FWi7RLTrnQ38lDMfDSftRJ7DWY%2FGgvBlrGXhK3uQJWW9YkS6quAO9rPQbw3tPQmBZCfL26mkcRKK3cQDWxOySDnnWjcHfg8iJK%2B5%2FJg46h3NprpDKnSqySvmTOgEliXIJFolYATfExsb4E7axe420AY5Fn9TxA%2Fq4wpvUJARKmDb%2B%2F9XfuoDKgarwtoLeLBplzZC6Niu8YaeXlJ%2B%2FhcYcmUywKd3w9D9JD5m2gFwpLO5wmEOD3nrxubNMN4BP47%2Fit5xo%2BAFxt4s%2B6KCoejb97pmj3%2BAtIbm73xS8kTCnm%2BtwXdFPjPExU0e6z3jZZpt3YxiebBsxJDRa57XuZ2QOKqeMQwXofPXDY2%2BhVnu1i8Ae0ndXg61kVxLdzF3UIPcySxO304xy4mjX1zX25prPsxKdYb8CuLvej68hb7McDWi2M4LqfKnfwwUEwMxNFeznrxju5XIB7Lktw29cxK0Pms3ej7yCld7xUfyT8E%2BAPy3rhss0AkqZZPj1JB%2BxHeY9ZT5iCowBwaCxVYBO8ZbOcur6VUnjTfyRF%2Fomemx1ej1ko%2BPsY6A%2BBjY653Hn1CBZ6SuQ3q%2F7AHJm1lWOT5iJmbS4sJxY39yDuYCRhPc%2BrueNM8YCofwL7ZhunNyr6rIDudH%2BVL%2FFXW%2B5sNJsNbi%2Bl5RqnsR5J%2B49ZbPOKDTXPXynYQy59G9ieWwt%2Bn3Dbc8%2B8XpNpiq4FmfhXo%2BQPWJzR1dDh92c1z0HKQV1jbJNNb%2Bhljgs7yq0r2M3Tj8NUU6DcWG3lDJ3toonKmcgxSBMdl8Wtc1Xs4fDRtFcqNiwv2cFRu9uxR3eZcnh15xxgp3CFDzPkiSccI8hxPn9mAxBB2Qngd%2BVAKJ1v0ltlIYEwF%2FZSism2By3dPmJWwgoO8oqxEPkpofxPAcD8hfi4czRew%2BPIK%2BMEOYolVZzIzA9nKKw28pviK2%2FXN03QTPG%2B0QgVrEEb4LlWW0U3hHDEw4tsXEBdzrx%2BqvxfqKV2y47i457zpjgXp3nK4CNcvN%2BtefyqIFMxnnRkMxVKXNDzEqXi03NwgSIhcO7DD%2FU%2FtWxooP%2FWL8DBL%2FQpTgZ09YvajvnFQqIH1ng8wSa%2Baft%2BTuw2LWycMVb2oHJOQyJjdv7FRjbQjeXSr8iBWmTL1%2B9WsAjc8RxDMaZ0UpSp8tSlgJJooi3je8nhE7U0v2LH4%2FWyfZBNgf2bNIYgn97r4C39ft79b3I2XpOkTZqQAn8YpzVCrIy6G3h6G9D1Q%2B%2Bt%2FNm7XCkG3IvQVqQAtnlWroUugCzYl5pr38LvJIFQ%2F9xYS%2BbTYfoMCwNRD0Kf4sbEO7blvuGlgcABY%2FItEuf16pflGJUTB77uDEFkyAf2nmsGLJvTdjjgfv98bDPjYsce9m6p2%2F8b56YMk1ywEh7HrG4F60xylszk5WNW1Siw5i8ZqcMWq59HWfBaZUeHGd4BEFbOTsDxOlO4aHKKDiDv6EEDt28%2FnT%2BebrPxEaXmzroRtq4E0gIJOpOWlYEMbsg2y7%2FaN99Wwze0JmvPzzvUT2mw7JlGg6X5nhsaztR7EOxg15Pvz5TbEPsRPJ6ISDoRw8XUupT9kOLroF1AWopOkW0WrrIeP3ulWpzccN4OrOscb59Rlv5%2BfoNHDEPWNBW9WzlxGIvcUduSWvRluDKHvx0kld7qZN9v%2BjldthiBuFP2%2B8S%2B60AYoA6j3mYFRHOOJv7TWZaBdxhGQxFrKPZEEXnui1kLS%2BhBBUSum940kNcfS7ad%2BCSoiBgrbzy1RAg5FVOcnAxgjdHbAKcyeyhGTJBO%2FmIiDB7ngcW3BuV09qtnugyKMTKmNjK6kJ4V%2BAPVRGPJknBMfut%2FvDRrXQaZRKTM%2FqDiphMn3g5nXNw%2BzV8cwO30UOY%2FjbzVOstYUsWRrL6cj4sycXHEbDjaJZ%2BuD9v7sr292dFKIXeK7dNMrcOVubxWZrCTjAZ71yEtP5d2L154uZV569dmbRtQ8TV9B8Ca4qFw6XrjjAVqwdg2PeFtSgNqwdp64OfqyOS7CgXpDou8947ZxgXE4HXi3fN%2FcpN8cC6Rh6hdLNvny4h7hocfXnKibA8%2F8zVVUiqo8O5Nn9U%2FAVbBPDbCk4grQAtk7B9Y%2FyY3It%2BIdiO03r8PV2OTa8PNMorvRKnb6LjfPd5Rf8gIdbxwwRF9q3L9ioC9Zt16HiCkd6rHYizb4vnZZvl7Dbow6NI5dNAinXn4%2FW69mDggo54r72MnR8cuqqAfZR3ct9oqWQ%2BcIwFhqrxhtmbror8%2FX51RHxL8ZfC3K49smitCmttGi70iyjhjBxa61ZVBtX7gY31QhD998G9yPT0Q5qLO6WdL5w%2BFizCCgNUP2MxBMgvneLkPIJTbumfd%2BSxxoI9l%2BrSU8bITtTIT6vi5DiiEUerSjsIKUX0EGYX3SDl7qjnWPoEz9rwBiaxkxy4S2vEWt6PlSuIu9KdJ2kx1mJFkYAijcrJ3Zvn6U0Fgvvp3EgkZeRdsCZgZungvf7NaJmkvkZZ4AG5%2BPPOWMP5DC0ATMOkDRZJlXlQ%2B8BxkdVd82%2BX6y%2BHXUD47VYIDfAKeO37HqkLR2yfh%2FMPceSw4rS5bg19T2GbRYQoPQWu2gQQCE1l%2FfiLyvqsfKelNjbTaTq2QmSQARHu7nuHucoHPKtdi9nGjbgld5rsqIxL5I8DPVecKke66I2oq2ZrtEYEPxVy8R3gA5I80gCs2Ph8DRdEAaUGNKevpKmXCfjz31exlHststm92nr3jSQbe%2BzRCwZrdoucPylQg4tuscqSaTwMrZAqONTHuE%2B4TY5B5KehMwruQSabHfokUi8mPSEakOGVo0KwN2Nf5EAO1H%2Bkh%2BxrxDhRvhv29%2F%2F86pCW7KfDKt7Bj8kG%2F3%2BIJ1fDEzapzagSohjICy687BMmRhcEx8h5eVw4otn%2BhKrNgqDQTzTjB7wHA4cpTMsW5Mf7Tnidhz%2BG5Rvy%2F%2BymHz61q9cYquuiMJPjfyIT3wjHPdr4HK%2BEUrGS97cmUJtWrSp6rAIbwQVCe68vEzlh8HMTgMAowQWmouS23HL9cS%2BfVJQpxzyboWdi%2B5wr6pcgVunr9zMTcQkBXwpQUrLWQs4otBt41EkUXVu0Ttij%2FHUx3yDDgVCMh%2BuDn1%2ByBveOIZOwhbSsJ4348sA7dYEn9i4F9EKsZQ4QLU4GK8ZTfhFgE%2BTDSpGz2DSrUPMP1tNEahUW5LpS6va52y934vEYFPzaYBfCn%2B2dIW%2FuksSL82mtX2N0Np%2BMODZInNztEw%2FCLQ%2BPet1Na%2BpmKv3JZVD7VJyPl4QjvQ%2FDpSUdX5keXrJyIPxQaPBEbfRs%2FZxXPRk5VBM%2FsV1V5%2FPNzH0pkEFGRQvteCFZQk54pCOFZzFsSKfnasIGqBlJYuG1%2BWg0yahs4ml0o%2FZeTvTCKpnNVoYogFGtqFplty5ZBK%2BQ1fW3MK9c4Leuy7Lfa7Y%2BcwHRIJPtHokC8GyxQQathqzN3klfSxMeJcjbqLQr9E%2BblSKeFy%2BNB2RQaZ41XBSOsbWEdOrvZnkNPtcdu5M23Lwreoe33P1l6gpkPnv%2B6xyhQ8CdwzPkrtmFYTHkLXSBHWuYK0Ad6sCP%2FOXnHMv4ue6UL%2BMfOC0OJTkafHKOiBSwVUG2iWJxxx8%2BxOFgqy3xGxSqQxA44jhrsS9gJTceuMSwfKwAq%2FgnWsJmPMp8f7kDb%2F16GJarSFO0FyuJqeey9aR7X694GhxP6LNvDSXTmKJO0bqrbKyCRIwhekyFYUZdeW5D1af9CVlkDRuflrSgH0n4HOk8pXrCiptnEQXXLM%2BZJtBu0PUHTENPAmq3%2B2o05hyBbUP8tcsNN5UdmzcCcd6kxUrx4yHZcjlGb6YrsRJ%2BF9tnoEmHRYa8GZ3ttJhiIKQr8OUyYZxTf7BiT8BgQimOSvcRaPhKsptDDbVWQnvei33f1M%2BaU297AOoT0asK9bes1dIE6%2FbmqYFZprRhrDmdHFd4ou9S5Xng%2BFGppiVbIAc922bq38hx3%2FQDkse5%2B8FClAraPUN6zGJAMzLmGdEnkQJdhHSfhM9NPAfGhvgKjTJFBuTliEhpNnRu1fV9rkUB%2FRVkwoH74YO%2B6IrkaNx3K87ElhutYXefPjDrJn7ZfcSWYsNx5CIEPqk0vp0raIvH58ixz1JIfSLVeJ2FNbZ5Mk9R4lhrE2TOrxjUb578MxX6nNmUU%2BZMDGtNkf9EeinpDUV45AEikUDrDq3jtZRmjKSAibtDb5mFaolLJy%2FmhxqNQbfQpf5%2FziaMLoGnap3D3sMzhp%2Byg1UOJIM2RCcFs7MoVey6fjhSGWyMX7JKu1bs1dHMlAysyZgnQklnjNp%2BC88LUV6JbQAzILewFuykkjdqkfXFgW1M62aj1SvEVTkm6qWtuOWNbqZQ2mJaq14%2F3ex0ZrLXZwAkv58nMsqNuetvaIbQvcp7aDgO7900tD3P9bn4kH7UYXBHzR8M9fEOL5%2B4WlSqCu8ifMtFnoP1WueyEpIvyvT1fkg6L%2F%2FEpm%2F%2FFvkSe2qB6wM42ESPjf3wQQDfC1f2pOrA20qf5PkmH%2FVv76b2ph%2F00e7D8QVKRIguD%2Fv9EII%2F%2BFkjgEoygMQwT0308Rx%2F%2BFIyRMgX%2FB%2F3m44P9TpRrF%2F4XRFPgFwun%2Fk2QYjOH%2FIgkaBYfG0fB%2F6lj%2FX9AMk7JfJ0vx93%2BuGbYkaLKuLtLGaXUteeEWDqEHL%2Bn8fBdsdffEVH2Mem76MFih%2B40%2FjLfn7jdXyp3b55KfLLAj8SDAqj2%2BxwAshsIh8FfeQP7LxuB%2FtLmM%2F7Iua0D%2FbZNtg8gY7lD%2F8Z%2BaYl6mgXc%2FwOieHWjI%2FVleeVgHBb7MsskCLOV70KqoXV%2BeWwAlHXZTFpdmZ7Rwvj9YQDNI3w%2Fo79Mu6IakbuJ%2F27YXoShJ0%2F9eDZX1ALggkiARCm5EBtdBhwV8rAf3SVVEBpH7sf1ZOggz5j%2FfFMkY8Z%2BLQ1zBx0C%2BUgRXndG0IKUJNMQ5qULKubZDdDgUV%2BvqBG7Hv%2FECMZO%2BkcPL%2FlCvET0hbRG0uv2BnP0m2RX4YxIRcWglSGZ9TA7TCoh6VqpDkgSODBWiO7OCWjIhC2nFfy0RgG0Uf%2Bppp4k8igmRWZxPgDWn6wUyAdDybCsxEX8NeX81bu9D5ZBHm5Cmm0hbwecLbsJ7ujV4ctpftTXSmlzkVkJIZBLDBuTzWLJZNXkzX2RqJlELQw8HFNayeaXI0wBJOBu9FjV%2FOW8DalmsiuGLa0loCx%2Fl67L7X%2FkQEvy4ZlROfzJvpbdSgZTdjYZMSUOOWTuRP%2BjIULHZylA5PEmfYzxLNpwwMhFtyKmI8S%2ByJfBPfx%2BoAj0yn4WvrBR4ReRyKcKqXEw7nzAyFuhXiCu6bLuNr74PchMENboPjYCgl6Eq%2FKAQ%2BrI7SzN%2FSg4bNY4DGNSMbKRbaxKhCOrtQ9RSlYWdGBCzC16AAZ3FXPWtp3%2BhaUl0eAJ9rCKybFAlwEVwhcnmQaG1ax8d7Ox%2FDhVU1vASV2Y0%2BuID8Y76g5lNCf%2FIDR%2FmE8d9L0F%2BL1cpj%2FTJdYp%2FGUT5d0IAL8LH%2FUg0%2FPGQmZDF92Lkg5%2BWtou9RJTNDyMqMgsK6PGycICJJz%2F%2BskPmTYvw9yYzMpTSXYZK84aDCfSaiTtJiyVYpT9Yo3KqkIYvyXZp6WsKEunEQc2uZlkvm8533i2%2BUjZLzoRXGOms5%2BMOe7mHi0VWD7Si%2BYxk1AOk%2FRCxwRUDjVGwEBZLjnDqt6hrTDIL8cvaP%2FmowhYcT%2F%2BFMdrD4zPBpGfJ32STF4xuSCVLPdg0pYQfCWCvfVFgoGHC1ur7PDBjrlpkRrO9vIE%2FCZoyv2ZCC6GpjYw5gw1TlCozUrJetF8GAKaa07Mtjmikzvbn16rYo3PwMejJB94qG%2FgZlMutsnoKlNWeX0D%2F%2BsQu8%2BSnJoCaP%2Feq3LOJBFFA33ryYnx4icvkIZ5e%2BhHQvpzR%2BV1%2B6nlTQri1WhH1yBDLuPdxqxrd2VxrdqmeHqz08fY6iwzc0tCV63xOmrACqHDkIXVIZf5FIclfVZqKd3nRyeydbQHV2mK36xsiMhh0SRf4dKeaVw3lhnax0aN5FqB7G5vSisLtTn7slOlT6%2FspbbMj5HdG47vPJC4vH3Iu6TKfg0403LRt5CczGcR459vaxxKPk7mVgG4eiwz7Og3RT9QIjPksyKzD%2FUweMCoiPVMA58Yzqkr%2BMr2qVoIYZG46JIaedzWh9SP7LNLvkQ7tY1kD0s3OesMSpie5OEc2%2BPoYoqeWiuqvLavEWJky9TPMfOhNsHLZnLbrD%2F1zCa79ZX64VF9sNSjVbpbwgSPJ4pPEvVAeBRB7fjiC%2BSJNQ14Kpnsax9YkClEzEnKdzj%2BD95XlQ1DNeGz1dvC1uvDpybBAb5HZOAb%2BW0tD65jX0BgXLNC1vrbk9cC2VYL0U%2BUgkcjXMnCnbIhISlPHXfYjK%2BGa8h07jf5kve2OP2pg5L3s%2FuBH6%2BuXTvSP10JhaKA94eiFjSU1NHJGxqHxu3ysADufl0RJfqX8RlL58FnMVZ%2F4e20NrAwOVSQ7gXnYb%2FuUbV17bbFoosQL4dSFmGkNfzuzEzCQOfXlFfN58jwaKGk0%2FQAXEas%2FrXT9qzlvBPbdcmVUxk3%2FJ0rVHPrXG3e22u0Msp3OUkRZlpfvV3NIMmdehdJW04tGgDfHtTqNGxQ12ePlK0cfzMlGya%2BtNOnMT83kTDn5O61HvTDHquZHZT%2FCh7ALqUBf%2B58quXmE6Dxj5yzhDoS0AVJ%2FZfm0RMg6evDBNbzov5x8mBoGczqIpDlOZsIN3cn7%2FOf1cHSTBgNTpSVN5yIbLqmB5oSyUiVIatrBa6kgwPYgzQw05FjJlMtaUsq6eSP%2B8T5gaRwzKX9%2BtNZOK%2FUjRCk4GkxYhiLHKtCZvbVsJv5BLc5ADo4A0WpMRd5ClTXlxjEewT6ppkuwddMeKb5HEK3QOs8YlKPpF8hkgAevC7VQyRfEa54JMvUnF23wTfgBdN%2BwveoTd38SvgmZ1XmD0DKvmpFFaSV%2FHrTSuCAy0QbyWPXTsnsSTUQL9EvZHzPWPBELHnddYHzSn8yKwdqs6Ce2EJrmdZ1pzaOfDpfAuOt8wBYC8FQ2Zv0cITFwKYHIfICNkMyDQcYC5q%2Bf%2Bg6yoWp%2BOZr97QTYxySJy7BkV7V7mC%2BbMaFXlkZSVu5uZMnTDC2uhGL0yxE9G0j%2Bc6U6tsBBeiXBzm4qy3bE529PtvO4bzAm%2FL49M%2FfLiDUf10vk0BThxwM0JbSUbbksbt9kVL%2B4c52NwP8COVn0zqNynfXmI%2BO53QwLMpaJYlGpGEbotvaCHNLb0bTSz%2B7eGPp8fJSHevjpRcvHb4RPdGkA40pI5gB1GICICFzEDMWk9v0xacrDCDsssOXK3LqdGT%2F6VCP%2F2aLlQ65CcSzD6xKklxqBZZLK8Sxi1a%2FqHDDq16ZaqFoedtHUTvSGdxnuC2eS62kZFKYxuV4AuQjzuhkjFKlwEyEWJZqZYAqmZYyK0A1IQqXauWPPcNsP3KDaM3s9VX6vUWwkbdBG4eByBPO%2Fo6cmuflAfSDdJ%2FzLapCJ%2FBvtKa0gdfRHA7sfNtN7091BAdz1%2FbLF4T%2BNyobAa7nT1zteEzzvnYrPFxJZc8H98%2Bv4fh6IN4S%2BpPGUOBPLMlELinxE92e%2BkyKaRNGfWsVcskHeHAwjoVxzLmOsjHFy0Ixc%2BOcEkzwBJS7OaIAPThyINTbCsG5Pb0LNwWcY00xEgDK0eahkleKKlfyDi1omB0lktqTYgOTxL2xOoJ853xkKoGloLSvI1CueW6QXNXTli4pexxbyCSkWnoWaLfHznRFrM6njPr5nZbdkMUyvC%2FQvSDqWOQxhtH9fkR%2FpbMfEbYv13cWwmwMBS0zr5I0fV0SmaBHJZNvoDYM720sgeFC%2FSGTN5I44amoo5spdGNDxj1RUACfdwBka6L0VNBGXqZw%2FIzLvOL%2FU%2B3vn7JdLSmpQYaW2SBXdpDA46V4Md8rBdMVen6T1HPJrkYDW5IofqStQIxDzdGXMrIk%2BpbypSFxsgD7kaqanHdpy4Rq2tx3eWl5NePutDc2OQyH4sj83MZni%2BAiQ9Tk%2BGlwASNkSsvmLqdQ3VaV7ScBQg0VeDAOIqESNEPYcMSJo5OOIj2wO2kt0Ih%2F7nLQxzyGTCqazYsKga0k7cIb0DWPG3xd6yzXOro%2FGrK1Mf6OsAWQC2LWW4yKtTBR8H3XWL9aSVV1KXyv2VZ1YSJkREz5M4mjiNFRCBDqUQlNim8qdjmV07xjVbfFbUP7ehvK52C%2Bb2EdB1vImGE2Y1TDVRbDkEfhBR9hTSOrLU5gXQH6lZxV0s8izc%2F8xR12eZJeFjL6xD%2BfsGLoZpRk%2BJD2%2FLEh6h7UKZBSEbtXqzkaDV1QsW1CrAWv1ZvR0LzZfTItoKvC%2BtbTxx8rehksgAtSEtua02a1W4pBTvVvm4KmszJ7UNyI%2FtV3XB7XZ7JhwqN6%2BdhbuZw1qbLXqcNMJRQDmHvlhx7qJYob%2BUr%2BI2eL7Lz8jio5ntqJu8L3AwDn%2BJ5JS%2BisusPadtPTXujHH%2FMjKes6BKCg4eiOgQzMoPiiHPlAXEx5A9mXAUe%2FkzfDmmLhOMET%2B89QetVxNv1R9QU2wlH4BEuVRf45273%2B%2BuHdQRiyBrPfXJXjntT5GRrYx7umCo5g6V6JVD8qvkdjUC9vMb%2FAL80t8pDu5bL5suhUEF2EO1Cabyiu3GHJ7PSx33J5Xku8st%2B3E5KaGz%2BF4Vl7O%2BfapK%2FWg7ak1eH5b4E0aVZcN8gUMO1gVQpSitSiooysHLdbujnsPt6QFBQazo%2Biz%2FGJqZ5bJhL74qwbc1hiUuLi9HnUpjfDfiH7DX8YImp3kOUWCt9WeAD9rmy%2FaoUGQ4zPzePrKfjCL8o7ExY4XvTXtkUdjVY7dMLFiHEUbRn0qeAMIW2A1uZBtN7dlkgMVcsVa3AuoG%2Br%2BOexiwEsVr4GgbxG%2Bd2XDTyp2gfOD9JH1gd9OlT7sJfl6yr2g%2FZRCSaOyYYcnfarXmCoayFOzw2ay0C0acyyUqwHlltcnP5E%2BPNx%2FDLInJJ07P8ZFDmJpCx8yvKB1acNbrvdSf12jaqwGoyjTUCTUCliSX3oDjGYEEn7amN7rw%2F6NmFEl9qqRfsiRGtNNQ%2BjJNWVwzbQAFEhpTPFacvvZ95fnerE4PSmfaVx4JevvMddArWHLcWJtaeBzZIZq4KtyUE7pNXcrbVTFLmjGsq5zliXo45l5LlPYj%2B9tVqD7idieI%2BLwmptfc83y3586hpdZ7VofMT3wqcf8XsPUGlWL2AsbbJeQe5AdldeN2j%2BSq9jwj3oxbTCHId4yYVrl763JoWkOfgxjNlCdXVyI43fmDf%2B%2FL9ThbimtuqA%2BAqNG9IoSCZbXJPS8TnhoA4X7U2fKM0RP4kRp7LVdJz64g30ogvM8w0XIiERam%2Bs78584a75yKnA6RL9j8WLgKnHJmh8lTmb7kZ4LLY7lDFQWDYsi98Stbfnbwl5Xd3nEp8hpUqxDp%2BMRwfTMkpzUfp0wbJPJC381oa%2BcQeVeaWuIDnpCP%2BvA7pZ%2FQ8pZoh%2FjKbDqi39HmZTrLnHLsdhGRQsdlHqMs%2FKpmXt8J%2BI6RHnKKfd583UCDIq45V%2FKl98TRO1K8aamBPkTAgNgiOHwHBsKlve44A6FGMJU2jcg%2BPebX1ZwK8I%2BcsAxBqYqFw3naa99PGYq5N2EuZ%2BvVSm7G19nTNovhhNB6w0qpnHyuTCyw8YKWuk8kCND2uvvVTSdagjyTDHrh%2FoF0sGTCMK7uNDykdbpzdGMAbcVKlWTpris1uoj6gJX7ekQqruCfoka7CWQuQNIFKpN7xsgeJrSZcC8n3HIx6s9GOMF6adNkfa1mmOvXDuyamNn%2FRL5xDDHOTLp9Jpgh2W2adKnexy%2FsTsWk2kzL%2B0vIygBnofnd9XwYKL51H6BU7CcjP2VG3jBKHrmo4qGR1Nn4NIyr%2F3YNZEMGTv4UF25Zyn7jPnLmo0vUYVIGcXR48s4q9n2C%2FQQuUaTc1Dv7ij9UYiV7r2YX0xmNDKcH3dxyZxB%2Fqf4uoCsSaAtbvJGRiFrr5ztnBL6dgP%2FG2hFeOLVSXf10uj743xr29G5A9fb9JxsSowsTZCrF%2BDZQZZTstnJ5i5%2FJvJ5Hxcdc%2BFLYML7c2J9AvEM2d2SQJb3nP96A9FlmPGxi5FR17McioaEjzjBJMEIgs3HgtowLMK0l4Spq6ob1vK68QVLv5jI2dxViQmElWpIYSY1ALLMABhVa7fUUFZBjLYH%2BZ6WQEpDtIhkrlsofj%2BcpR6930awKiNVCe8YBb%2F23wmMY8vlzZ69URRpaBNi8UMm8wzLUV5PoMtxfY70jmUqcPTZ9HuUaQiZ2xVKiGsLOTzMN1bsUyq06zFsbXVM9SPMc03RRLJa3vgh76SACkmjbx%2BtG3JnwmK1e4nI8bkESzIZBbdJuWUGduhTfLl9w2LLWjb2qBJgxh2RSKmruycDXjeEdtXY%2Fsbk18pXEjy5wt%2Bb9kHcmtQ%2F3McrGSpjf8t0k3J%2F8q4rR43k1go0zEqwYXXvjoSEpQBdcjVj45l0Qq9bkkn2vE7N3g%2FLYxebaR5CcPRm%2FV14KvxIVHegPkXQMhlyXpvoFy1shOW0TJ%2BysC9CMT5pjHcLzHEP%2Ft96f1fVlGpt2HXtRyShn%2By8wUq2cCKlGlecQl6rTaihSJiJ7kZ4xwSJbOLH37EIgQRDxZNarJ8D9jg9SJEZHi%2BU4Yd3DWm2msSbUd9c%2BLpUlSZvuNfcobRx1rQgfUGmlL6UFX%2BZohLWyBjx7G9gMb0Qmq4RXhk%2F%2BWtfgcRrFWRJ4bNM3UNnybk3MhktSMpnetTafQM5k10%2F3xsxvlSkxZXPhnEZB5zqEScnixybcOrWDg6Hk5XbgrtsNNkxzkSd2gpbftwuyyFbGFoZthbYwYc%2BTNbOK6fiKdkFmExRZuT6S4BF8Z6BALU94Ru8WiebblhizU41U55iLiEUcqtXQw6kAp4r5xFz0%2FYW29iCkvfzBu1%2B33Fe1%2BjeXtq6FWm6fREANaV47ArhF0uEyfryy9%2B0OMI4O9OSqv38uD9%2Fjft3EC2ai2IKuxmX8ExJLIefJ66wExH5KeozTRBTQkrSc9C4hOwGllveMf%2BiVhZHrS%2BYtMX%2FUybB7GvKcNEsI4RHkbm5L9MviVKf89vAXuRCIZYrno6%2BKyGtLTYtwTBmWBID8IDzBQHy%2BiDVJ6SXpAJMjwx9xwPFiRppYFc61aFfvSgeMQIK%2FZd1RNby4Bi7QKAOyCVAn4Zlvy%2B4qyv9U%2F6JikWM0O1FJu29U9cWdzFLHWLC9uujJp%2BfR3k%2BY26eNMIvTXZzerSjmQTAVQF1Fq7qtPjSR5%2BzY%2FZkvJF7TN9hR160qvTl3wNtfsUY4i%2B8Vu4P59HH%2FmlxHuS0w2k46xsJjd6WFEaGt8cz7%2B9vTgstvWjjmzTa1Jt6iSThdsQjuCI%2FJFftppJ%2B6u6o3Vy4uw00hopOTQ36MlP7O9Op0PUvIB4oAUVH6yM%2FNnvRjNwkolLHiS7FtGmPsByxqpBHMSN9T7su6p5HyK6hZkELZX7nU%2Bi7kdydrOFVdBzf5nEDqjHt1y1b7lA%2BhUyDY3JY2%2Ft9GawfTs6FG0rr%2FeqDPrt5tojtgKMfWBvc9vV4o%2FosTVNK6iw%2BfeFqzOe%2BqkIamX5tCFiS%2FP5SELYnEmEV6rg9TOYX1YOsS%2FkjnZzKKAIdy13LYoKy%2BVQWpTXH0wNe%2BrcMcZzwSPrxhQ8Xni0oL%2BIaiSRZXhc10sz9JbFdt6gEPaunEEX2C3HcGBTNPsUJzDt%2B3OsMTjxh6aHulWNlg9TX6jCuJNHSsv5Poz84m1%2B0%2Bq3%2BMRF26vnLzLk6dws9FMn0R7Sy%2FX2MxoJkfQ3Y7vez%2F%2BpWJEAHueAn5dVZtn7ncsHucnPZTO2AEi3b3Iebz9zAIzkTsshrJrvFtN0J6YDGoFYlN%2F3IRqqRxpwUCy8SeTpPJJQS7BplxfWaxrC6tVFttzM8Xgasjl%2BpcGJjSateppmotF7KdFOECaUKVhwgh1y99ycQQhCze1kGTMpYfbn7RUVd8nl5IyjluMP%2BxmesSJb643mPlu1a37kTunAgS3Pvu77HlJi%2B5BCcYUDZdOos3iAWr6vvFMyKeIhX89Xb2tA%2FBuunLD%2BPw6WdpmuJcyOwBD14EGdvm%2FWPEt9iZL%2FhJ%2FX680C5hTGEq%2BZvJKbUI9AOsDX90moWy%2F3gRiOjBSotLxro8TomKf4Tnlou6J1QYU9mpSofsGcWD4sKA58n302y9J0o1cNRa5QOXY8cVw4tGef5G9piNHD9gqie1sO1JO3C86tOuvnUpWDJHz9SrkiT4zKz0w%2BZVYidxWnUFMxJLm5nRG0o1%2B%2BkZUvQuIVwvNM%2FnVAkAmS3mqVjcucOn%2BpXSaCB36GPERL9iVu61pBbTxl%2BiBK6elgeQGoJDrkvVQs7i7AQO209lFGQXBK8ILPWAvb1wbzIz2cgENpL0pl%2F6rn2DsdxfRVOl0AMdRMPxA9kk415egebEKMogRgwpksi2O%2FntXONQp1T2CbYIiz0PThvlaU%2Bu3u8M8gxODpyXebmEXmM7%2F%2BpYn3xvTWaD336MQGRtghliOGkSsc63Ldnkbb%2FNvwEccVf%2BkpJWaZE%2BfX4SZwdFB1M8XHY1hLP6GzdPe3QxLAv0L%2FduahRCf7OPwCwUJbfWCV0Sq7CuLoWOBbUfSxrwt6wjdqhYhuzW%2FcCEGCXEvOD9b%2BdlhBI7bAPvUzrj7lexCybC%2FySoPWdGV8VJYuzVzL%2BaKw2eJUWsjd%2BjSzHni%2BZGlH5VzQ76CZiax0ZoIyjRF8WV2jJrd11nsXPn43jgI92v4LJ72qDmLT%2B47uMViWvXoJAvX0bsiOmiJ06ykBsCuX7s6BJodx4Gtt57%2BpoGK%2FfS4Qlr%2BAX50boNnba73TJ3ul0WjC15zwX3%2BqitDkCbags%2B3nwhxF1OI3VwzuVOoW05xRindTkNNT0ByY86u%2B4nHNZWpe249bMdxx8lBYj0mq8BJ%2BbDhLbEE4ho2mGEO%2B2Pkn6LRMWpebxYwhiS5KEGWTyWFoR2UkRIaDBZEEFlofvf0DaZntBvVt8Y8i6h8hGuZfDlTNd9itoDhekOZPljuG5UtJ%2B%2Fg9xrAPYo%2FgS0XrMXdwMRlt%2FOQ98YRbFYXLLrnv6jrlpAUXxS5JBtP6c0fT9a4%2Brc%2FaSdIwtnRhs%2FaA5yZkpjx5to9DT2XiInpApsK3GgZlq8qcsRYu6pgNsbt8IrgDazgotyC3vrEYGfvPtjLVbn%2FwYDzYfQTfkUEZvaPtxC4BY0X18mCJaGE8un6%2F%2BMJ7C4X46wO0tkxY7TiBn7H5dxCbhTw7O0SEhqyn3ALrnSchxW9HVgZlZy%2FQb%2FKN0Zk94mYP35if9U79guV%2BtvuiU8B9xEzYtVdyAqRDxFtlGSXDTOR9xem%2ByJeVzhUWu%2BaHNbNlrzt%2BLqzVFQ7d2uNkLA2oFaDtgocSr7J9KwCphliQoysIUtGmsPgc9zV%2Bp%2F8JM1%2B5EOuoh9UrN59adGPllLbSKuxmRgSmzabz3YBSv%2B4M7%2FOqARDkE%2B6CtxKfw%2BMMyxNfZy0HziQsDD7L9ZFgInbv2hkCLZH%2BeKGG3AknfTchj8IgfEAbfXvCf54Qm0ZxevrYEao3alrwY5LSrf5xUpluhkH33hz1IcJ4EZ9z2fMNWcG9QnMe%2BYMNmpTfJ8IVdkLz9YTL5gwTGZWN2gBKDh0t8GmT45f%2Fu3rwjCapVLDt6XRjhUKT9DmWzEhdba1SlAnzKHgNHT3vIhGyySeTkYX8mja6JSodBS0NnOJDMH1nz4H4nlxfyMzLodLonSfRq84B8ueFktvRxfxpWCSZL0QzYCgUJ9gfFoOYO8yvJ5PaWnMnRTsCvGv7cw64ZU3qbmhoFdBnftftdJodTaIKkP9csO%2Fmqy0z73RcmvqHrkq2u95JaVX1V8PbJdFyKZ5zQLFaeIx4JtAmyt%2F%2Bhlu8q1dFL%2F7fvlFO8FuQ1l8hLv%2BrxjGJmAdVvbPnq4w55JSjI2eyswwMSmjVA3OSPwJWJ%2FnKVlsee45DIwVEp1o5%2Bmuyarmu5XDmcEP409Ldvdy%2Bl93LXuRftBua8DN0ZtY9nM9YPxKBVF7rB9OxbR9rjpnY1rpCQ57m2V%2BYLlE%2BzfGysB5aVVg32QlHh17sysfbQtSOF%2BKm1mxxBSNrV%2B3BrxkrkEysvfisaZvW6UqLNKExIpu%2BEb3rBQexRQ%2FvRHh12ovyJXfve9n%2By2i5mHzieiazbkSV2ftiR5F%2FuYT%2Fxjh45ycUHi%2BfNQ1FJL5bH07wRB24BdYC1xnGDP%2BH%2FBvmRBGzlW0C8ISFaKygqpf3g%2BHVHU3E1xVh8viFu5%2FeUuBSOn47m3fYBRtjhgnTVr6v%2BcNq6LQUnNTFg%2F5%2FvdBqUBeJGmvsg5nbyk8NsT8GcDV2uMD%2B2w9Iz57xEWaJpHidULjA%2BGrLVPvszkTzUoVsclOZb8pLTC9rpl%2F41vuSxuQk%2Fu%2FkFtcq2nqXCjq7li6hiGpbp5n5tu8rKkxmXoSaXUebGoXh5WZAxPHXjahygbqjypv00uy%2FjXSQa6ZOepzuLMX0qhSkXXtSy%2FUtByC%2B9ssPGUT4zg4UGdliLCqXd8ADyASt3zlnrD4b64t7Dq%2B0X6MZW0RBgSX153OY2KPlCSCGIv%2B%2Bnbp7XJy3WdOJKmThe%2FKUv53od7qDmkMa9cPvB8rqh0nvmLJS3xolk2uTTUgEJjd2sW%2F403qS3HyuEtjZIRWVV%2B%2BVmJcOXfsKLblkVLu6wYsH0nH1DWAo3NgwgfeKlKLmGAgyD3aJSI4B9DAagi1kXxoHsiIR8ndnrYSDchwD%2BIiFxFH%2BX%2B5UwWiLoNM1UGKZMBIIebHXZ%2FZcrW9XGtNR9OKyDR%2BjonL%2FkGBPoNMT3OT5kr8GrawBWvxQ4oCga1r0reGeanXHiJTxOrsenmt3PCyNBzRbbZOy3a9WI1oGI6LpBrrjhIDTLlx3sLBqFJ5llYTD5IYOtPSjhcstOibYY8Ha%2BMtjg%2BinGpXOqbCmxK0wbQdyUrj%2FfALbPGtNCDa2UpOaUwORVpR2RD9hf10TUuOYWGp3WPSPuTskqT9Xr0FxUo329q2C%2FOH5JlkEbeSI2HzdWoudMhONMxgCXUmRITthdMcvOXSr769iTzBkWU%2BTvZNSI97772S2cPmpMn4B2RfVrxmBVcNTeGNzpvejqb1M0WTF9NQZ9UE%2BkqipxjU6RsymzGAnR0OU1iICKM351XpEOzdjIdbJ0MwQrq9Tkrf%2FlvxN6Yb062fbQFTl%2FLOnrCT%2Fou6iVdzQ5U8DQ9LmSbQ4EnvhiBowIypdcMY6k2unbrJMjxRI57y0nPp%2B0r5Q94W7TOAXFdjqFyrJysgAecFrTnShylf46E0CIqGZSyVEsxOBJdxv3XSr0qMkHkejUeq4OiUk4zJa9vVgK42d555Y%2BIzoffwiUiUJI3Do9YYorGwFAVlA%2Ba%2F1deIeJ1s3dlG%2F%2B0zhnFF9OAVqB8Obj936g5pulmDXqfJ7w%2BZTklGdSD%2BEMYal9cgpyHr%2FTpUIuzo7VIZyWYp0YOZnh4BW2ts%2BZ4Uf2HkMnjrpfwH%2B3UrPOl1aqz%2B2MARxlHLMqSB%2F1PPV5uGIK3LKvOHWgj0CO91UsYIgvZMuAjvulsc%2FsacvIjCJSIJdzKEMgrJ1qSTWX9QztRAcPzmZnx%2BwIHgkK0%2B4xBxuRv48%2Fx6XlbGV2cPsX9OCRdve9y8%2BKavztMSJWRI5QSBiHlsvRtul0cFvRHkq3h%2BwqwtdKrZw2ggqh%2FqHTQ4GIr82IpPhSYbFnvfWDeNNfbkJAt%2BhX9JckZhyAzd6DSqMgu6w%2Ftyim78puGZH04l5fAkt51oAXw2DOd2aRc5DRdRrdnLrqFtsrbDxvcLEhz783wEztX9mtqL4f9XEw8EGjWy34cZ3rZU8h1l%2Fd7Qgw9ZpILlPFb6oI5yt%2F57%2FU5fKMGaiXlrxP7Z%2B4jIYXR8sNcnoE9aeBxbFEZGP9HLXiXYxN9kYoukEEy6Yv9mvVKgRCu%2FD4bj6bvKmbDZGxNWUIUZBcR8epjlJmuXCOesjmQQogTaF2JdIwQfPCx7F5SUMlUb4BUs6aDOYAZ3%2Bl0MwpZ4dTz4wFpykuBg9YvXLp6Na%2B%2BjQf76WPn4twZYj%2BbPMITjj8CvBXT3c9gytB%2F1qzvcqX2nGg50m0qT89%2BIjG%2F8n8jQrs3w843vnjV4pffTlHpt%2FJAq6QP1m0L6lW4wwsQI%2BXAs5uQln%2BdROTuZHJNHX3RzYoioASRzNk753yDIPbb48xllQhEI8iEDugj2Wht%2F7CNLVTMDFSokLYqK0pQPLv%2FttgESHPjNNf0DqNfN2KGIs9o8Si0Dib%2BEAUaMUAXIJ%2FMbWoYiwS%2FCm3qNLdU1vE28yzLSN899FlrDBecVY3TmbQMDra5goin%2F47SbhQsh5G85rOkeksU7kGtiR4X8HjpRn47vEhGxTW%2BctEB9iPxMlXcM6nuQciEanGcvO8mqvZQL54k8DsZCPOGpCKqT1GElgNTCSIhZ%2FpR5jc7zblF7jYTQOpi7DvVCUF85n04i%2BhfGqPI%2Boo9w9nDDskN2s8zhuopvh1MPQbJuA3LPSYiIiRakiqI1%2Bio4aOKWdR9aE6C28QjVBbqu5BuYsQN0UPrE8gt6MZKKjsPcLi7FL%2FS%2BIqNzTd9enrZ32mDte997Xl5iGRitnMfwbcMS41CD9QPr3rLix6K2t1kirnX%2BgdLUGkTh9OCEQ9ar5sU7K%2FCDRF10cjsqRdIH15%2FKTN2icvV0ufs6SPpYk%2B9IdF6DQM%2BqXAoD%2BNwIxyDdDCyy5lpUKCs7CUX1JlWFDz6EL5AjGPWDikG%2BNIkzgzkoUpyhZc%2BB0aA6aWM5JtUhSzu%2FsJBUn%2F8H8i7fskwF7eF2mY%2BHI2TYlj0%2FtvH%2Fy7YnVk9kvQ7ikmgZvsv74TtR%2BRhpkPg3cmHvICUbtf3VlFeff5TkNuiLqTaD8M%2B6Lp6%2F2Wej0M%2BLHrbzAysCU6hP2NsCba%2FxpBXNOrjEUaaYNCVrsT0Be8pU6IPermzPctjqbFqLUYJkSZLEEvjT8khsWRWpSb6Nw6twBFfAmxWBz33kY3j0d%2Bl2xqhofnLuKNp8x9ob2s9vg9s1PkObyxG2lw0cj5quLFW5mArvFfGpTaPvWDqeL8sCyUrQ9bhBc%2FfQbNm%2FLsDiNXD%2FKP2Phj8p%2FjtYsgUKn0RVx5dk3J5FqFuLJlEfC%2FXVIa8wOnv6ysdGSEh8FzmxysE0GTQoCyuc%2BIAq8dUqGDBv2m7zfaOl5ZujhuDDQfPuG4oHgo9AnoZXEEzPODhIC4wySjRweJDINA1t%2Bqo0%2FgGPfA3xMMAwpcJq16%2BE8Agc656PFqcr7yopDpl5pud1A1kVwO0xKTxrLn9IsAAaBvcJhR41pbLWZ%2B7bMPLBpzu1%2BGWcfFumCedkVuAACaDlUFZCOaI1fe3KMD8%2FWXgauMtFkyOkKYH5LixHGVBc9hb8BVRu4FVBCh2N2nLNIW%2Fso%2FGQzG%2BGcA0KdAHkS%2FbPTxp0IVB3RX%2BHS4wLnxbAViwffvbAoOONzOssrvrKtjZyULiDKEz8h5FVml%2FkTL96qg9LWEqXntlhkquLtlR3Wlr52FGtanJVQIwa1htt8Ewpelcsl4LdmJd1G3M8%2FISLfEuNPiZxZOW%2F1vc4I0RI9RHuw8bT%2B435J3XZepeh%2F66%2Fr9FdNir6jWCxt25Pebf4gwX10zCfj7NmWJ5hCoJjxNZgNJpylZAJCy9HIgj2kaLiD89kbv1dNmhMKf1qe6Klmap6hSuJqP368jyIb6pIr5%2FaCuwt966l0zkY8fTIcS5Pg8c1et%2FXMdxy%2BlPtHizVOiKt2nU1XrydUFNZIx0W4530RVNGHdB7j0c4l2HNHd4ZCCNG9A8OVZAdGHo%2Fr3uoyaemeiSm6cqC5BwT%2BQSphmvOxCwe1cpyob%2FdGDoJFOFb8DoQAdmuwX7FVk36d%2FXahypmJje2t6FFIhjMyOvUBnmshDNVYrRfes0Zhl1oTzHSKE90tXBs6F3dqgHwzIBVrSk61y5xDDRQ2MuA0CxL2jdz2AYwBKGL1ASpJW9D6lrB01ZHnawutxZvddgHC9RoOjMeTKen5avPO0%2FNN7nUxzD1acuSu0Urp3ApqWA%2BwXWGV5UoeBcBFNmKrgxIUEUdecaBGW9Pohuj%2FlC%2FCQEYC9jQowyF%2FRUn393izVtcZft1PEaDsVKTBN9OKTnd76HCE8WOxt%2F5MnUm0sxsVvvScGnOKB%2FBeyfywK%2ByD1haUiayIhTMyAX1ktuM%2BiYIBf0moE775ygiv3pLi5Bgu97w4Np46Ta3P8vUgg0xsO6lFWUBh3e4laZIIEYakZpRA%2BloY54qKQXoKC%2FhJROtIEspsZA3ltiWz2SmmpVOGUCTOg2bfqTnM9Nrp4otAg%2FwSPrN89Bu4LVXTY98GiiAd%2Ff1YE26j8pqprLKTzPrx51gz6qApvwUai%2FgsZAkN%2BjO%2Bv9TwDYrEtlijDA6IQ5RJ7X7GQUygfWBmPmj%2FZmOT0QEcPCjPKo82sSZ7haGBwoS%2Bx07MHN5oqPzYvhg7ESxXhc2Dm8yMeE3%2BdIWpdFBaFa5QNAOUEx5%2FaOwxWmMvP2diKvG9HXT5%2BE2acG%2F6vIaH%2Flgn5cStmyCYVg7TbP%2F4aXxIVNPiNoY3a1u8ziujm%2BdmLHf62W97ZqvB1FEfb%2BUa9Q11tn3Uxvc3mDx4vunt2pZgvd%2Fn1a7kKTrvTuIIM%2FAuQEgl4aLv%2FfS9VZg1MREuJJrz%2B4ayzU0GpQbQ8MOSfR%2F067%2FCO8dL%2BqlPbbgDblJtMiFY%2B6DRbhKFbw2xOir9est7lsiuL4Bz0W6LGNO374tAC%2FARucw8cIb5RfPcrrowcdVZwAhm%2F7uRgobA82peee6iLoPRC6%2BX3KKu4znVUPGuzDLS9NiXocCWydcc6K1TwP8WYXlZI9nxq1M7F8%2FcNtVSl%2FwbOdpXlcn%2FTRfk%2BK1KIq31BGVKE510DlR6RdYo3%2FuK0L0%2Ff2rQC3G6%2FEWwCStNM4jI8m%2FvRqQzT%2FviV%2FaLQm3EcO%2BS%2FL98s4lhstNfH%2Fs2dPSrYG6m8AWoSXi39wxzdPEYIJecwSPkF3eXCucH527eJPhPGqUY1kjxPk49uS5LMPlJoqNtxOSwm4tVle5rOmF6weoPTniJeZKx0KD1RPDalN01J5ohREXed6Fo1YpnKmBot94%2Ft9saJVdDnReQCxeb3AFZIwjV5MYA%2By3r5qua4swRjgiJzzCojPTOrqaLmhSkoSXeRvqVoQHbS2Ooc0ocfhZkylub2fX5x%2B6T10xCEb7xSzbkBxwV9QuBUMmSyKhu8XoKciYCjpGbLUM3FhpGpi12R3cmoq%2FjWyBl%2Bg%2Fdc10aq3t8hSfkiAF4r1j5Rj67XYkFux5IpUEYQQY%2BFutiVrYHy7iDOWPd3jWmRxNiPdmshwgmqAXfuKhpDTXC0tpgGCUCo4%2Bs9FnY0EPNg1VROJmkvL3ztgwi9uFsOGLuOQJmCZncCLIWQdtQx6e9p9Gj%2FxT%2BCXzU1ZD6TQgKL6JQPHV8QosoafE%2FC9euiyCvBOHwFSWjUcq7v0xIOOM2l50uOaHHy9BKEuXctqE8snpfympNVYdVkL0Xc1NUDiVylkmD%2F5zdeQWUBYCAs%2BfKPMytTHwuur%2FnivDJw5TV2ZXbHDTX8gLiZVWU3kBE1zt8TuHTehCMPs9eWeFEaPlhICHxHzR76FEhN7F7qyiez4jG7FgiOdyWjcc8R1UzyXOj7Y5O5RMFlF1rbxaD1nzvmiR8k%2BOrypIGcYbKO3uslV59lvEwL8wtR6Ty2qOlOK1IapqnM%2BEgR%2FEiTejMa4lCUiU8gPPGBzgnzB2Mj1NkaCZwmOsmCRSRXSjtmHH5VlIEGqcpqNB1CB%2BS41BcdFiksVevntkHcUd30xKd2oDatiHhpTTeW11fRDYQ3tm%2FEnP%2FGba026xgtJyqlFwp2Dj5OxCcZBy4KmUzEPznOKVouN%2F7FbvP0GyInhgyDxQNGCuBNPbKZmCpHSsXvgmKbKU8TI6eVJfgGIsO%2BzsBdQJr5SHMp%2FpiB44BKM1uXa0hDSGYO9acMm4ldCuMT8HTOES00XYx5%2BW4sj2snb1a3hCxdT3mbE0rIFwr0o2MRKXBnKO6QLaZg4flb8J6eUThBc2tqNeAB8SXd1mJ4nFiNkuANhpZKPHUkmCeeeaHTnPGtanp1H5QXLQ6Blvy1QQSe8JMdVJyCT4EL8yoUacUFmPbwdBJY23Ce%2FyQKmKhEq7bB99PE2uauxDjBsVNnkfj8Ue0KAtawwdSluDyZOJuUQayt7dbOe8zgKtH403nSI%2B5t7arqB97NlFj5j2ZBMvmRzb6sG8pPA9OokeK6T%2FPXBiSbaFvb2h2Jfy7j2UE04v%2BQkUhRVVlVUPMPTvrKNOX%2Bx3%2FtFP8TwwAOgN7%2B0RwQ6c3CV70DeaJDWzLAH2g6K6p%2F%2FotY1gWuQMXFP3%2BonhZoHIjfv83p1v97bQIIYhmU%2Bv%2BfNsF7E%2F%2BiKIiAEZKCULAh%2FX%2BsTYAh0L8wGKdRGEMoiqD%2Fr2kTtOpeKy9b%2BZ9rEwwJmi27j7RjWilLvlgNtePz4vDX57V8t9GJX%2B1v0AMy4NkDZemKkuv66zamU9D9cAOvFwAEs8wZmNpf4Prb5d8vf%2FoERY5WQAQA%2FFr%2BW4xgACIBYmX98yrw3vHGwXvNIYP%2FWTwUsEGKPMxBI%2Bl%2F3vb7Ezd4uH1Bk6kZkr1HhRzY8vth4nvJ4BP8PngFwlctskQIuAbxd5HoH4s30WWD%2FrH4P6MmyAd8NwpeoBFJg1sggZnD6L%2BvGf%2Fd90Bv9C%2BtyL%2Fi9UFUuOFFBvTFH5iAjRx9JhxFbfnfSh3PxyhJbzKJh0P9p4Ag1KNwb1As9TFM%2FWoR6HmsP7UGxUJTel0J2kDOlke0bQgHM0lxDBT2cgQdxh9NJDEJwIVsjOxvL%2BDd4e5TS%2FewKPs0Ajwd685boyFKo1ZokfWHTwx3XTk3d2YiSZp49SzZBLydRz%2B0hpABDXquYC6snwx%2BLNriQxsBeSHRLMZoRpBhCo4hdp6oRnXSptNoidX3Q2hclOHrzAH8C6dywgHIQQdS9ffoZ%2FikDsV0BcWAwIcwrd3FdUNlSYZF%2BCWxk0LNPUMMj2E9k479XfOfMkVeojfvpJA1cw%2FCYh8k5lAex3RkeSylRTmbEY2audd392aCA8rEaNPbiF8XpyVp3jmK%2BfqdqUnzipGi%2BVmBOdAoc8TN9OSqL93rXy7Kyn3IHTTcehT%2B6jBCe3VIGjlkkDp6PbXu%2FQkZZMVufou7%2BO6dWFY6URh3eLV9g4bHDpO%2F7Pdnf7O3kgceh1r9PDpHb%2FERG87%2Fau%2B9liRHkizRrxnZ3YcNASeP4JxzvDmIg3PAQb7%2BAtF9R6arqmV7SqqrarozRUIy0x2OgJsdUz1HTVUN%2F4TQQLIgzIxyg1Hh3KJv19fPXewQUUxP%2BMnhQi%2F7Mx11GOetYNqgGsFK%2BSKiIHddOA5fe05CwCoeH%2BN06lkIy%2B%2FeErNpptIq%2But3nXH9hjnbbnAK%2BoTumxHq%2FORvmoGppXGmdRvm38cN8JKvJlnuB64AXNjgP33j1xzQe4OlBeWFTuyeDZjKseuGzi%2FwJJgWj14dlmUHHr%2FP0QbzJDGME5k0GEYmg7gFkATUxfj4oKY90SEy2UvznyhN%2F72hfiDkEOrapXIQnBa9ob3xBMJ6QV666uJI0Vr62TAZ1vqIudwrWndSSaYB6dWg1AeqbksZR%2BZbeipuUqFXVMl%2FggwoAnmXriNI0CrggqdhHaybaLR5GoUEdOpcEZZCcK39QIBb3EITOEOhxDVuLhKyyTPAFhc7yBLnlWkFJh%2F0lksVg0Bw1JMjgdGwFBjRTqCeSi%2FPwaZ0rRCy744aQR4bCoo9xqNpXFrCmwvU9pMHEWZj3iNqxbP3yyz9aIRHp%2B33MRakPkHRpZJ75rt5uqcihQ2CzFvzy3iPa47Kbw24tRoZxm9fppaJu%2Be4C3QH1d6AsMQo7hfnS%2FAN8pz1PRcnfqDkFC7dVMEda5zLtL4wHikbKlV3niiEEjnam1BCiZKQI4SoKVoOmEXpTjrnooSjhyMaPoB8RO2gFJjeKAZfsZqu3xVfovVlttG4LbamYFwtYfJLsY4N2FUM8u%2FH4f0zj6ykLOxPQLQebZiJBVX6e7v15BMDAptOi16AyA6AKuea1bqUIGpUqmRbf0%2BoyZuptwU%2Bob37dMb2lt7OdWAQMsolNWFRBUOj9H1it3%2B4VqkgzBI17Hll4LY60IS%2FOhg9KnQJm%2B8T51w6TdpFFdP1GPzuWI7EdfK3DsIAfzKCFhMW4dWvJ0C4bu1EVd%2FB10G31O6cXk%2BXGdqYh9YCgpi%2BIMsuYTa9BIPjQD0IWoq6Cap0rbrpSxsQx1WrFrkECQhenmzzCUFYQNDSpxsCp%2Bbu3fNHViCDbZycLCovilhGmYes0eRht6nGm8ay0GWl%2Fvo0PKYVAl1U9xCsaDd2JMOgiVjMhFaXbnI%2BbYQfoIeyJiaNQJYaogNGzslAcDvuNvJGqMcelhzGtBuddJp4upzO8CJAAXgpV%2F28qccn6U4p9Z6kVcrt4U6iZq6beCVDUsY83Hd7BVR5LW621wY4cJ86ExlPOc4hUYHC2APQPnJr0DTZRW%2FXQgfz4AGiKEoBjCe91%2BbFhoqSwC33v59gQzR4Q8heBUgx4di0SklFWYm4EpB3pBvz2vkpqkA%2BI2kpx7Xo9vBAYoGeNFehruFJuOXD6tqNkKIWy1motE%2BMo%2BMJ8qbNHmhiK56i1a5w8ZZ2BVTygHcm7Mz5C3q03v4EFNTxw8wvy9ahDqCTfrx6ORrCUVW9tbwumln42WIi3fju%2B4G8CGPthHzxGvJbp1ORSSX3Yo1SGJnr775dyvUdy4S60Bo5SLJwKThYDa8ZyDspru2sKXa3x1OXR6sQ%2BvkSQRJPtc%2FJ68AtEYH4ec%2B1Kinh6YKLoyNDHUhFidvPg7DWRIXUJV50jaCH30J3krMn9jV1EtNY7AoY74HXEQVujYPa%2BmIat4jXnlBlUWpwg0hIkNec6A55kOpWmqDFLLD7Tf%2F161MySG9IgYqKZLB%2Fc35Gszi6K2zuuo7xe1s1UgqTK21tLXyXES6eHi54%2BaS7OSr2IMlZDLFsqrFAb1KGErpWrmZSGmJQC44UnRbdbSD3SJm%2Bj6%2BhDXpIjflJa2Nb5mFJsYXSvbVnhA8A%2BKlNsIbZ1cl%2FJ4O7IfNJGHvTRqgsmwNFTmJedrNUSMzlWz49PdWgXqDpGxySQjpfvWmfiCxT4ufU6VSPvX234Tw9bmhg8ntthQLKqcVPbUnndz7KmN4Mh%2FJDonbW2IEeQuJ2MaWvhG7ZOVq8hRZuZwh6Sltf7vy0DNTUVit2S3NzKhYIQ2SW9OVpT7cmOqxIgBIQyq6EkuKZj9pBklhEL%2B45sOM1PIner6sD6yZH1JB1r7HczqnBZablWN40RPt4duUfTrnVn4nhzodhbl3IXQO2Mjak8BGqPm2JaGX6Pndr32rMdzGjuOX2%2Bh1S9pxrOqD8Ggt1JBc4eMGJl5OWi70mI4EFbUwNMklzrjeSAQQL0CoTIvFrr65h2jaXRZyXZ%2B9IeL7psbtmJxY3k%2Bd1I49W8Xp4BA%2F14cONkOLF3HpCF%2BQPwn5kuu175QlmpGamRCk9ivryotgReAFC8H32m3p%2FPjPh7aWeC%2B1e0myyXCr5MFim%2B1k%2BqxpSBQzQ%2BI97o%2F29MwsK7s%2BpCwkCNwL%2BOuQZIhbUoliUn4kLsBFCb1FcL4mXW8KEnbZ58tY1R5K24CO9JctKZ4%2Bg0XnRhT4O%2BUbBnoAoeXLeoVnORhqxZSp1UlTuAvnbFlpElYlRgDlkOSDmQ7Qi66Aju8zEVA9W6rsrSFlA8YvI6eKYg3c6u8yLzRGynZCP8VjqVS0CmqVtymkIdnAoaCYqky0%2BSyHpycDZyNl9m5Q3qLkU%2BtRE5bK8XPibrjEiSpukSfY0CFn4XaHti2gWsmdDJilJr5jf75ankkhkiZCYxdGz0iCtFXi4rTHx6aIgxMp%2BpDhgDEbIZ7bo3S7dsOOokybKPRrJPdi1hld9Jy%2BtRnQpUmWNgzPZzFiCvmtSv6m03WW9xWaMoVrri402zeaiUlDKYX5C8xq7eb1XOPvNqN%2Bs65bWPsMhNKa%2BcoqZj%2B9FVGgGk%2B9KYYSicsJ2kZ2tWUZIzErvnnrvXKoJDbklkXmTmWVpUkHTpRhLioy5uEPd0XRwOidJqPc3b5slKzJeUsB6tUCuYPnwRtbX2V5TYCeyLE%2Bh%2BKYWnpSgN2ACKaYihkgaXc%2Bg4m2UX5mw630rL3GXffQHtQOWvp130NDcurPrAlUv1GSBA2WRxG4bbCXRPdOOiALeCzUcwMdG7E4gwnf5HN9lUderrqdwcU6hs%2BQm4%2BywqbLqc15E3LZ9TdlRkfs%2BvDa5djsphwFLiNNsHDaoPqFD%2B%2FNaup2dULe1zFxBwRagd4jD1cYQs83BDCbNniW%2F5IAbIbeBGyudyA3CjJ%2B6BAE8sBJeFWrG3Ba7JAS1Ofu%2BUBCe2JvJ415EkK%2F6xF95CoQ4BQNKei89g9PwviyaQV1tyBODh556vkP5mjsD0mxYV6vejl5RVzyIBnQRaZVdq4ti3n0n6LDoiXjt8MyBMNbhicrY0wJBYYF%2BJCwGuH4L1XDBlPzNaE5CFuzQoPU0smFyYqimEKfdc2nSPWJIh7KdPBCZSEIjYldbQBZx15u%2BOc%2BbIvNoidAZjE9cGji6v0SMxMKYZHskqKVWWmYtNdz61aStiynkZEHeA2Z0%2FFuJLFoRO%2FrYIKTebT7N1LK%2BlyHRCkHwVB25LMn1o1yq5b0ERb3g5uVCFYosAafXNMK2iziQ3OvwGef0JheNnbDbGUV40cppnNonO46WBNBQ1EsVc9n62qnbuJljyUpwykgeULVPkA6nyk0XreZ8TqS7v8wlgcFjLTN5UrxLolcffkLe3UMo3gwtB6rCXTWCpXlq3dJr3ou28QZVLHDKiUgjKsigv0CEMrgtSTCPrQs5lsFU4a9eVVK0CKV43baKcMvyQ%2BhLQJ2fN8A0cXjWRPEYIujkK2TVbF7djL4obz1IThadot9J6AxJMYNNnKFIVzm02rG9AJ2Em8AZDF20zpYGomcV3B6htKl9pORPhxgLwl83h7OojIrueX9D5Jl0xIXwJcMrwGRMna6Ns3S7YEfvaeJGXoSeQzymqLRCjvyJ6ldBhysSpBolAaJ0%2BpTWj%2BGjKfG0j3qGq%2BIF8QtiEeDknpwie4sg6%2FXs4xPZFbXW%2FrwOW30FH1amzLWx4iZgzGG8SJpahAALV%2BvhFalVvAzmdbaVfBO8tawXbV24t9VKiJEhaItLzF7dcjpT3KEPwmRirfazAx%2FlanpbaCxrRR2vu31TQW0OznNz7LF2N8jdgrTFTty3xZ3WjFckj1l6JrrYCFAEnhcVaYZQjhhwtrxigSEkmwJwlwBArbhltYgLZS0XeTVAFxDQEWmayCUhgkW7rwIi1Jw9rYS1cm3fVTbrQeHbdnqrtGrkYVE4uZ4tRaJ5i0iZM1pSZI3huUsxIhadBVHRG9wVcIdLi3zx1HVz50akXWd8nx4Fu5GNLQoWj8k%2BW5LGjNX3RmfPXCCFW9pbR1Kg6uBPWEWHYLss56qi5Cp8pwg1OBkhHzI8W5%2BGabBFFWplSzgQrhLRG79mWXHpAJ%2FhOIHZVgmit2UFlp%2FuYlrE26Vq%2Bp6OZrFsaTFQ2vY6ObxULcAjvY5rd6z5%2BF3x2U5%2Bc4ojZm7doaQtV14Z2O0folBsrd%2FYZiAfyrZZHkLGFWXHPspse5KicxrfWsdFXPUKDDrLASSs6Q87rr0HGeHqWkKjcpcRmBGzo%2BaS3uR1ZNVkC9WgpQ%2BZiiNLmthryIk1ryCMn6IIIEn6CXxUgFPPThZVZe87kr7E0oWoA8hrcZ2yaroCkXQbzWeLf9F9SN1iI6ZQW5dmul7veZ7Rbm3xgFq0Q0AN7OZg20Lb2je36h4GgMIBVdgvxNlsP3XOFY3qSzX4%2FETnLhLgnUIdTK3Iur2f9fN6RJMJQ%2BGaMKJcQ2w60Y8hqTleHBeNY99JUd%2Bc2ci1IeXtKgdqsmvRJKDEdw4cKfiEfuci0NZTAgxRlfee73YdKQY3CsNDuTV9fB0nDCWPcwi2t8J5KW1gSojnUU%2Bc9sqQ9Yugw%2FytHrhY9tWHa32ha4xZ%2BBRS%2BzE%2F7oa8nSeAI3%2BSz9pMFERI9upSeV9EH%2FRFiM6z4zFa5Lt5JRsYCnGKSUXhk1lVyoAsr3W1tzI7VuVcV10ncFN3UZi2sHALvZxSrJkOkSqn8i5EHMUJpwY55vKgwvuAlCjaFYXmCafYtAjWJvtxC%2Fl2nl3V8A1cYbyo0xyqFeCgU5mfMEqqhFljo%2FWtpvHXOr4Aeeo5QnEZprmoq7GQWYcel9sW1XHFUhZHdAQ%2BlXlpMwAn5LWlBqETFJ%2BIgO%2BGNKLPNyeynnkbPInWfKF9evbQ9nXsXzFVSj6gfLfLJY6FriFDpCPgU5xUU7VYWESOu3Z1cbPv4np8RL1NHUMFvjwDn1ahnyho5Qw8YHqPpLPMT5ukHGNAhg0LWFyggwxQG6RHqCCp5LWrLJV%2BfJFoxuVAjFcVcsWrSYjaK9VpcrAQ2IIQKLfRMmY6MtmM%2BlCR07tWOjG0A%2Buw%2FpnC3jKYarZQ3UKzlysb%2FUcVlSY4SgnIHt1xM3tJlOWo6LyyPqcADaKtdTt3bxYXuh6WrWZLFu%2F%2BvH%2FqSmrYnqNi0ENcRORKNVysxlqWzXms0C1NR%2Bd62H8zvOp7CUVCCMeKOBtIqb71e%2FUvSrseHur0do44IWP5TXFqJKGhUNM%2BJ2Joqeipp0qlu30d67MtgOVs0yZuJWK1TXqmQtVzcDFDE6tBNNI2gbaInNw2IKk4zCoQzRTozdzy0Eppf01g%2FgqtCkFuRxitzBk46egmsnfLwc59BXtLgR%2BmKCLJ0Zn1AJ8Vk71kxxrq0MjK5Qk0WVwwn4Pht0wOXEVFwYNo1r4971k7lOsasnnQK089Mz1hoQMRFoN46L68602n125v09eRgYUc2HSV6EFzu88rQOanLXiKJvotuUCBi%2BplqL0DEDxIBOGDp9totHOy8Hr9ohcNPJdNMTUW2ffVrrZMZME0zTY%2BiuV9hd0lDin4xaD8Oz37tlRrPHsZQvbWNNmDnSHzm3HW%2FGp%2BKLNVgbsudNrMYMde2Naz9XtbqUzkDMNIbcJp8MdiZtMrOLJP4Ye2V8NTyG%2F3zfpmefYLOm9%2FE5G%2BV3Z9HZZda1MNufNqgB6XzZy1axpfJbdAyj7Vs78oW%2FCZLpFVvqhLNJAIq4uW3PoPOjNRUqGNB5xIUAMsY%2FERG9QgrbEf9KrUdaHV11qcNHHuTl0BJskJ9Y5W2pSfH2XnB9SOVABtzoNWGbeHM8H5KLg2ugj3RpnwwW2kRbJUiiVpq2E0FsHtddpTfidPXgO2x5%2Fqkja40Cef5ZCeHy2UAakLdTvq3UuYWe18yYXpTT%2BfXf0VSpDCrhxpMDdEcWQ2FihpjIKyX1myLLjpQy605UZa7apvMdoc6LtSZzhcMXIxTXdcvamYJwjAg5a2S9TF9kA%2BouZ3u7Ps5XgNJj2Rie6J0hye%2FBSjvkQp4GVsPrYK7kRFo6gG8%2FTtWm%2BCCSXJ2zIdQgw%2Fh29Rg5S%2BuVWYp6CT80%2B745HVa%2B4Vde1%2BOjruEvFogL0PwV47UosLF%2FKUEkP6ouZcWe1X82H4LII9is1T3ivhmKE%2B6SFDzZiN3lEoG5QShmhnyhN%2BUYygO%2F9yODNfe3O1%2BoUofK7Lfurgmv0RcGG%2FqnnKGfuBU9mHHRru2nxhhOYumBvtFdbfffi3RI8ifyXJGFmJnlsHYVehkgbS8Hw6zbg7YSw4ReAV4BafUWyZdfiou2%2B357JykIXfSz9fXiqgvvD%2BSoQE7bcSSPNWosTjcwu4zepzUY9KqgygNv7eoaLGccp2d4E3l50RPLIPvjqi93aTnXkG25RfjifVjWqT96yLhqVPIvrM5N7RdaMZQyDb7CwjFXBz0UGp0%2FHDLBW5Ty%2F%2BcwITrThuJpvtcLVAWSPVVZwHX%2FZt81J6igW2Q2Y9Jm2qk2gEka166NNQIbK%2FnI52tTlgCFdK2roZdGjJs8MpuvQe0my67nW1LR5jAIttoS894EF6QVTN54ybyL7bQm5TiCNI1lPyd4l3R%2FGG2u92rrkvcZq8x1sbjHExG46mShT5fkyLRqaxONk5valU%2FLr8Z7Hm%2BdMOgs5vjKaDFZzodzX6K0SLi1jK%2BAkqhlT4bO7wbAeITieiKTMyzlwYZntVQqvIOVH2YF3FV224kdl4qQiu4jglZ7SKsVRZZ9SN53cfYg9VDSYwoDex0fHE%2BywoM5PfpNtjlF4BfdgkcmvsKFetHWQBzJteT81AcnNLMHoKTZwybx0dQM0R7%2Bnv1uoNX%2FObZZrVy6xL%2FZLUygzQsL3t5dtIqza9Tv%2B5Lg7LrRj33okpgGhz1KwyMQvZz6K2oocJ8P2l4DQAPWVLxGaFeLJidGwpc4rjQw5p8B0ddWSEAzJj4MAIJCWvrYcSVAUwk70%2BDbIP6FYual5m6ASXPjurnGgXa9ApeZ6ywcyq0%2B3tF9U5wNWMb9JEvRt0OGOC5M6qPGxHUBPI6uR99hKjuvxil5IY%2Bt7N6KaZywryfuIL0aliyF4tAjwRy906iQC59Xc9AHiNk7Db85T%2BUdYBsXYbyBhWerlw6eI8AJNdfWvV%2F3iy6EQ%2BOQVyv31STZeFjElNvQIbze9Ja7qTYvqCESEjJ0dV3uopacCSulwGlIKAusvJ9FDBW7lHDJ2gco%2BH0er3PriuAjbsmnrpx4gl1zuxPmjwrv3eMGg6fHUiqatYHxmisbYLWipgYtUBoj4NPKwTadiTrikeIrtwvFkIsfOiUbbPPq8mKPRtx0GJhOt3FSJofUZXeT6lL%2BInvSQS4PT3ZUgDn7X2FOzhUO%2BskLExTU%2FfgZXQHkAUeLsSujLtiMi0j2VXsTw2nh0YIjT3VpK0qw64vVu95RWoamDiLMVCMZcZymW4fLa05Kcu8ltSf4ehsiQNeg7scXr9WAJn6EpXE0izilcndd9zpkl5Mu4Pp9Ue%2BO0AfcnIy0MB0eXXmC2mq5HHJChW7WYjV3smdSuNACWGs3BKgmPwrACtauh8qodTwuwt7%2BOLbKRboft9jhDvwJZg4qOAvh80a3y6MNofml8anrzQuULcv4%2BB3cLmusvGFO%2B09fdDbQTPEUgwl8J1D98lkAuvdT69cpdp9nalq5xlxpP1YNbJklTNbanld8CjSjrX2YWLsKd%2FXFdbVcd6I%2B8CW4rEJAa1mN2acJZNOPiHSDu6kI7X4NWMEsd452E92%2Bx7LynLKD%2F%2Bg0jOe0EszehaOhLHIPJ2t5PjTPhYXwgMSUCJC3LgiGwsBu%2BjbkofdLxj%2FwCPBXEK%2FJwqGNeoqbcA9KgyCSkM6dLFvn5dXY0Cuw4dbk%2BhfCKRPXA6lQ1%2BlnGDcMYW1HZivk%2FAQieK4LapURcooVu66whLCdvPGcUkWllBRZQV6TqIzaHBFCcfN7ZagUmYs9EEW6o1z76%2BC%2FCET2O9cgapqh2nkLWNpRzYGk3mIsG5TQ2NP8nDeg6QL%2Ff17J8gQsRdDcFXZ48i6OaEWvBEpbu3vVW2IJ0jj90y%2FcPYssTEVaspydNVmT%2BGJ4Zin%2Fo3GBIHekONSSU2P5GXi0mH%2FBlAhCXAOVSJspHtKIAhQn0yurxi4noHFiD6I25B83BWnXsVLMA60pNowfvOmRe2485DEzzRFzJ4aekol9D9PMi30QdxB45Rx30zkNhiZcb2quO1UIsGN4GBHLiv%2BeWFp0%2FeiD1EEK6eNRYvkaPISWCHjjOB78NSOLk1%2BQlwkcZW8l5FkLZoKzUBb5Kve1IAhFThOuErAhdW%2FCDxfJ4zuSKXRchdAzWRYmdEAUzzeW0Xo8gCMI26MtWMDXZAbRAmc49F3LmVcd9%2FovrBu0bGer%2BfwYUQczgQhmjKJdYteVjhSuC30zoSEprm6KJyF12358CSFjwNHSoIbiVg7cwJyPs%2B3wquegVc6Q%2BtUMxqSMpjAGrKfzhP0ZdPUhF0IYYucU92DtgCzwYPne2fjUHTEtHBJRySVgvpkJWQXSBakiuslzmgidUHgswLBiVmvk0EopNS7bvLhuOV9IaJgJNNyuFi9huQsLo7dL0aV6TwAQJ9SzzyftIuEomA75ksEH0ATxcghOS9N5zkJazoxrnXUwfRd9TpTvYpC6MK5ct3cFGjt9N7ZjeefPr73FAJ4g2qz65nGknv4UMMASfVNnrS8CqEXe%2F6rTHPm60%2FgYuFsxLC80op1Y1p5%2Ft37EpztLcykolGevPBjrmCx0EhyX65zEF13FzNbmLU4W5u6EB71fqMX7LTOwldfd68ZmnRTy6r44FtTlcf4ZBSKHiDuowrE9VLfAiQZ267rfytza%2Bz6KdHeLdiqQENjrB6ZKEy970kz0Gj2mLLz9KIVKQMJKts81rm81sNU%2F17AW%2FVb%2FAJzKElJsROevtg3W5bpszyqAhfSyviKCR%2FbsJqtR8dLkMM6SpbkuExQer7BSTnCJjJIQxpCZcMI3lQm0VKM77n6FIqBKKrrEi2VU6B2gRxNRlpwJh2d4QziSh4XbE3EKaBDnbDyghZPhjl24MKhx6zXUJAJkB6WBerWUicvEwcAc9pr1VglBIMV1Sse7X0e6U%2BH9331WgFRX9Pbtm2fMztqZLht8MYbilj1VlKYtONRK8tzU7Kwbdvj7ZAKLjSvIvdeitjbJgoyZuuLBOqCNQ73oNOpa0SomBkG7%2BKtLfHnQdnCl48WT3oCBNosDB0smejwL3FjCyeoH4x%2FXE9O44qkz7nf9IkV34HokICUmA8TZStvFJBb80iFZzvc%2Bt45xbtbffk%2BPHb57WOg01nj9CACtIQnpMJWWZcOVJWb3rkzaNRdqhTBYTVpWLfedHrW2kB5z6J46u4BVxQgeveuow9%2BBCagNxcviDFvZk%2FgeJ%2BrJzhYXghzCbWDOcic88mNPrrE%2F8zFCqbgtAqbyFfYPEt6fACKNGdublQjV7clm%2BruEvc3r%2FMEG5ILZCTgQb96%2BQf03xVhfhqLdPTpdq3eCRY%2FS7OJ0M8S7NRoDU4u6pULXV9YTT1ljvA8A68upfWdUjvjkofQub3o3YJnly%2BlZdCv%2B8lDqmy6I031oowbQsmIOA5kNrR4SdnAm6kgDdRTgVEA%2BnHWxcFFsWnEqAA9JigfI4qBbitFbV4l%2BG8Nfs4Caw%2B9bmAqY60ILCfPaqt1jGF8ZPqvitcYqjXktRERmV%2F39jZXusGfagw5UfP2ihkOq8ATUe8qnSEh2zU5B%2BPlDZO1bD1fsnCQES7YVwNOOnIEzIgWlwZyjIQfOa7nivdgsAvoUej513aXdfRYAt83o5jJ6bZCxsbg1CyjaqRF2ofmXUn4POpLAbQV%2FpzKv1ldKcPTZG%2BJ4VbAE4nN97uRvMVgY%2BenJ9qKOMyKObINVFBlvwWiDLfSegxECqmVje9dV%2BBZe86EzSZyPoBSPnjNPtpfIzOs%2FVchlvZTDfgfbV0mQbv8FuPldb5QbQrQdt%2BG4Cy9bH3NKWzeyyNowePO7Vy78mEytNcDozunEXHYpZH4B8HmDw9745s1j6PL94j99lqmokbegbJTeHbA4mBlaIogbOrcroMkN7cp5EMHEW0BDlnXvNtSt1vxttN%2BsZzPNrmyn4KfPog97UoGhgJuiUQOJSzYJTNCmKyeswPWg21Wz1OO0M2bRbxt91%2FIiBjOFJQ1hzdzBcdo%2FIz6k%2B2UMDxU6hEc0hVDvE84KhS8c7HP%2BxEw%2FZptAKgw8fqM%2BqUh0KbhzapL3eKL4eIL7cdnd0%2BBDcZCIQyq4ooyYWoh1uX1wRA5gRcwgCgRH7qnY3xpez52ZW1T3HFBHL33APHMjTnNHlXOnC3RQF8UQxHAoEvLG%2BMNYDkWYC1AYqi2JdP1BuB0ZMhp%2Bvj8NNKWDXEH2aT9GwIZbIUbLV6S0%2Bc1Q10GggKLsRWDcKIiZuKxbHYHSi5XYjL0m1fYQBaQQY6ftNawdw64elVBZGpIygtKKEcQmj5lp%2B0dhzybuzwfpzxQRy1kesCr4LPXicQ65QxY7rpncxExH4p0nNFVDMzxrOymbSBT9Z12Ls%2Ffue03haVH32wmNPZ6arZwePZ2a25OsT750FGNYH0hr8GNBYTZpyozAkbb5nebG0WL9Jvl3JeAtNTJuAZP4y8Qc3G0HTTUk%2FWoT3JJWUduY43W6CfPNIJorZsKeRIJa9jrJYtiCTQ1gwd8EJMwcC9MD2nNlAVOQ2cUa3nzjoaWw%2BMp3amfPaVTgH68chWG3EZrFF7%2FM6xnjn45jJQCLQUDZfpNNApGyrtsvlujEzd0NMZ7h%2Bjf%2FtUBz6ncbmYgJwIeURAvQUurni2DLmW1kgNcVrU8VL9gLW47acR8rbCy8xYnLDP64hDAG2Mk9lMDPFH2jSnHRXtm%2BXgpLkPr7bUiZAJVs7H7y%2BWhpHUP45DAvzRHYA8s7kRZlv3MHKghi1doVAcOdDUGGCpc2IAq1mmhRH4YTz%2Btj8xuJqZQEkEorgAYO45W46%2BcEzbWj9YBfgQegRbFSlD8xzq8hliarxItnE5dlOV3rY%2F9yxeGPbmme6a9J8dp50Q4j%2Bd%2FtTa07eZmuLPuV%2BsX4K8YU0udEhtLmAZuXprs4Um9HziqVXCxCjpNDwbHk95f%2B6s8DzsCUnsgt5JZnwNnzwKcsjKMUt2ljAaD6oQ2Qp0TCMh54ij%2BnbxsNS%2FZVu5XXmc%2BLJ5lo34LIxIEGc0yM2%2BiG6%2FAyIBH2EJIN6mbvcxmwENtl4j%2BHKtDLccBnvmyhP1EpNAHs2TgxpZW2QoH%2B5t2wgdg94QL8BKSGgzcM%2FLMcgbsbnvPJFod98559L7zp9ximHqKQIjoLe2u%2BKSljct2LVFtfOOPLDSv%2F2TQ3JM01aggLw9CakAgs0fsnr5%2BMI3WpuvJPVhd7qtZ%2FUD8A3mQBt9SuqMMOgAMMTHvPlBe7G6%2FHqb%2FQeBPgvJyLAIl9j31lVwINbNxVr46W2ihTtmvXd1U7gKxSxiftTZrX%2BlJ7bB%2BmTHhXLH74%2BT04T8NcDbGhCK32J2JtRNwPlhsQpOWHzCR93LmtFYPIW32nRWoDgMJumO2mCFr2pyHp3YvrCwd74fxA%2Bbp5t7jLW6l9Hr5MuyW2B5ukKkzK4U8W7w14iECfvmwEucjIDXDEBjSgwKa2wz3Wa5NeuuYMDtON0qIEN4n6SkYEbWkJzHyD%2FYAPto0m30ZG1NhvRQLBSZo%2Frkyg91XPNW1ImGulG%2FiE82wStjY%2FUiUO5TRau0qKR6MicpnlgOzIqKf4tAbR1KCVKXySXCz1Njcytx%2Fy%2FhYFvDL63PHf%2FMISWykfniwLe57wxOtE%2FCD81dFWzAfGcfLRMw4QhSeNgm7Zq2%2B5NHX9Ej1D6HJaIiIAt6kyQ3bncIHwCLyVZ9zvNvaYmaPb2w3%2F2YnqNYQ%2FGDJrZJPMH5q5E6GIRP2ul3Tn%2BYWh8avmNbLjuxmZxmyg64Tttbdm%2BTLWPdjj1cotT4%2BCT1si937vKNHcCzPKEDfxvNxCCEjpjiqgHVqsWmqSREuN%2Fsknidg7uvDPjk5PK6KQlIAmLeSePchAFm0VhnIhLNrcoWiRuaHbNzKduJWhAdw2mJ1K4Dp2jbjiv2%2BUh8228YdAFBf%2BUH%2F2FGzexUZBSXU2HSG4HZ%2BrVgZr8U%2BaF8YqgVBEps2rf71rgMSd8JcZn1rXbDDJkBgWg%2BkT%2BWIqfALeVFEZVrxFZlcCt5khmaFhU2jZdLpsB0sHngcUoS2sxdHi3ISX209mrXLePtGXovauU2wC9jKFSjuZpKXw1f6FLHkDGT%2BZgcrgFwv7GOsRikgvdD8f5MtZfIoUTBQojLzVMNne9hXLkmB2wMUynzTfXRouMqy%2F1MI6MthXM72LS%2F%2BTrig038vSUVl1i3KNIg5yRK9upymW6syWIBm7HdmJjOFX161bmQE9eNp8zpQf9hrseT5h0QLjtDjtWZzZWv1A5LD7Gmt%2Bvw8yMJ7IQUvP2dEwdmCFzqhW8NfPlWzDbL8X0YQLKTZ42whzFSh%2FLYvIfaCa1G5mruu%2BXbnq%2FguzZfl65OiCgdX9OlKC%2BtEVImC%2BXbUb0rEmTGTM1yNquKuGR188k2zsTkctmxKJ9KRg%2Fxy5FEdtFGGyY1TsUNBBVARHiBQp0%2F%2BpNlfEvgKio5nKFE%2Bbk%2F9KLtSxQYovGh1Zfd8d%2BKUfFB8FvHIGTeZZiK0bkS8ni5cuP0fsF9s9WqDwYVZT%2F2QN4pAfhQw0seVZGdbEfmuO%2FtmM4Qe15LzPYDyHFoobd3ReesemlpPOJitSb7%2FZAbamSCeQMIDJwnlUEVGqjlUCR2zN2dFJR4AgiZIvcM9CpsQOIROf%2BuALcr6jESGkUEwrmIDOtDJWE%2BLWhc6z0o0WGnGcFmTEMw%2Bzm%2Fitqccu0AHRx8PDrhVdkkaSMJKEjRVOWCeww%2BTCpj82o71tK9WGxdzK30A4jPbn90Euvb0d%2FA0yiZlo63MA7Yya1y5Mj0hoIe6AUybYCQ4QAN0y44IGDvK17gSrhwzf6Y3nMdDG6LjXTcbOEnt0XEozR1C8BZptIZwMAi2Go%2FnNKbBxChUCRDHuDVVeTbUtl0%2BFtk1JSI9W66LofqhSxWScKDK9lSOQm9VSCdLbZSA5Jccs0uH5gXyWUrIhG17fA84qYmNL7KCAOqEq4%2FkrRkYGoEZDHdcTcuXvlU4JZQjYjTsVWHWAl1ewubGbUJ15HiJscsgQw09IRh9yVkYL%2FoXyDBXAq3MZvPPL1xwbeBkt66f59Ppt82%2FklZjL7PCcucgDNv%2B5mD8dUpsoDkTCjrwUCvFJvPOs6kTifo8aDwp%2BfszFYC9Q1BHtU76TmdJPGLBnCeO333h%2FLBIVLHdthnIo4GkGAfVfB6jsniS4nqmxmpqbW3gXN7jh7hP5qxMzXLKmKIlO5NNQq8uqSGwelE6jAY1y8EmhYuhN3bqpbSjFDASyERMrn1D1MalU7JiP3E3riX5e5Vxchv4DhepMVFQh9LyPGRzOE54R03bGpNxbfihjCjG2ravyxI9tD6YY%2Bp9DoquFn2PUYt6%2BZPwASQui09ez0v9T19Vz4rn9F5OgQDDXQKin7x67k99kZlg3HKWN%2FW64GHdQQpb3Z9UEIGrkE9DiSxfAdyy2KciNujeUKkvjslmKmkDW%2FeQmdzrxhdvxZhwkuPBQJLSkym1Bpzr0SVc2316Cp9Fttn36LLmrqC%2BZ4XSmVc%2BP6VsJXMZ2MWUdYqRqPrnkNGPrYQw5nGM7NVun286Xzt6N0asVRc6e3TKTyE2zSH3mpbsVPlUFV26%2BvsWHlJuw1ucCPhxLSgHABdAY6PrErdWUqI4ftd%2F%2BH0cIjkEfOZW27HM4qOqewf8D2zDsrevxtSTsQZk13BhRXTTiGhE%2F7NNEa6T3lU02suvmerUwC9jbXeqDrJFs1uTUeMzZSWeCEcliqkgLPZtC5zjFaJ%2B9jqQk39gD4RBa9WpsIogwxeAULhQBDZV5rSf6ElbV6kphzV8LKZ5XX1fzl5mr9ClfzrydfkY6II7KFA4ndVKp0b5uevNabPLaaPS7zdqP7r5Z8wGf9yNDb%2FfsNw%2F5CX7dmhEi8Y%2Feun8uWvx8I%2Flc%2B%2Fvu4ZA0mG5%2F98dc8Y9AWCT9UzcD%2Fj%2FfevqXtGyS%2BQABAQBwkUfUpHf6O655w1Zq5%2BGvb8v%2Bqe52Hrs%2B9RfIZ0L6s1d%2B5xft7d59d4v1auXfsLM%2FM30%2Fdfpusvf34%2BsV%2FIPWQwjpMohD%2FHqv8R84kAX9jfzCF8jz%2BK%2F3zmCPILQO6JwQkYQ0H45zOHAugXQBLIfeU9feBvNnGsonqvKGV%2FYeKwdn2mYLi%2FPQSkfx3w%2F%2FVMw%2F%2B63yyeN4GveyD%2FeuGzMr%2Bv%2FctbP5v4e8jWv53dX1yevzDlr7Yqnklp8%2Fdzh2f4q%2FTVUn99uauy7PkldPtK8tYclmqthueN9J64fP4vn1B%2FcsF%2FfvJvQTkP6%2BuvVwB%2FHQGnup6vQXwRf32Bfz1NgO%2BXxLz95M%2FdfxvEgMQXiuAwAAMEBJIg8TfoQUHsC4UhnEQg4F7f6M9w9Dzfz6Dzny%2F%2BBnA5lJp5v58ORb8SLugPuPxucHm6XBA4jCMAfFsN8ucO458Ol%2Bza9S2ZtV8LF%2FCHdfn94AJD6BcEIhiBoRhBYsTvD5e0OW8JMBq%2FGi4%2FrMvvBxcIIr9uDond%2FgghCAT5%2FeGivrKK6oT418IF%2BmFdfj%2B43Jrm67YqKE6QEIH%2FAb4o%2FZhtHdW%2FJFH%2BMbT8MC6%2Foy8ivqBbCd%2BMFyBQEvsDjMvSSUG4d80vwOX%2F0cnr%2B5QTmxm0nTXP12dCwCJtcrJ6ok%2BVQIGRD8x6%2FElggnAAV4y8E4WP0%2B8XuRs7fKd1YDV0nNxV2AIp%2BpJjNPJne0TFplFCpzueFFfaQ7BAWHYjs9MkiFijwbU8FWcxfOcTx%2Buwu5AH3rpVn%2BbEJ9E93zCw7fzAMOToCEIzwBHH5fuJBu9BmSTs%2FnwXmP151OS%2FpbB%2FAdK%2Fv%2BiG8S8CA2AcA8BbTePI30ooCPyCbjOE%2FD0JBX3hMIlDGAD95e%2Bfo%2By3E99ToDVOW4s%2FMPYvhTHkJtL3MyPk39NdvyfGuioM0jnqfmDsXwpj8M2%2BSZxA4L8n1n5PjOnWccgJs%2F%2FA2L8UxiAY%2BYJBEib%2BnsL7PTF2OLxF9S31A2P%2FUhgDb6aP3e9Cf0cW%2Fp4Qk8RhY%2FNx%2BgGxfymIIfAXAID38%2F49Lfn70rFadWat%2Fe9jLPG%2BkxwW6cbY9gq7LnGK3eiVmDwVG3QAexzPhwfwI8p3HlW4M%2BceSKu%2F6PeCQjWl%2BpdqZOgYsXtMaUP09CQTFLBshW5kWjZZOpH%2BRAbKTuz15KomcF8OrlGK3qZ7JxyaTPXOgZhvYcXNn1z6I8Xnp5rEuLJjuiZue5JLtqdBi%2F%2BdfmS2stJB9LXghx7sSLLR1r8O4lDi6wYMiJAkAKIkAf2tyESQL%2BiJjaIARiAk%2FDPE%2FcLW%2FN%2BCEPztAhmF5bhMzo4%2FEPc%2FG3EgDn2BJEre6hIkCZz88yLuPYesO3rlD8T9z0YcRGBfIAziMHqzNBD78wLudXncvp3LD8D9zwYcAgBfAIbfD4WjGIKAf17EaeZSOstzSv0PxP1PRhwKIrc4uCXSLR4Q%2FP%2Bfvj8j4gJ%2FTAJx%2FwcyLH8g7s%2BMOAzCv0iYBEGIJOEben9exH3kplGM5%2FDznyHuH9gw%2F5G69dtul6PwF4zh9xRjEHz7x5%2FSf%2FwLvZGOgySIE8AfkLpl2la%2BzOkvbQH8I2D5kVvx2%2BZWPIUEAIzCN6cCH%2BP35wKLH5tsF6m%2FlFvxD4DlR9rWbwsWiAC%2FIJiEIYRASQL5k2Gl04bp5Uz0r8TKD8Pym2IFJtEvEEdB8GbLBAj9VKH90WBpzddIKYr368AC%2FzAsvy1lAcgvEATIm1qTGAL8VFz90WDpRUNbLj%2F%2FlWD5YVl%2BU7DctPYLQDD8ljFPDcJPddEfDZZs9eW2p38ppv0PgKUbi38ntIDgP9sNQcgt7xESwCHwNiw%2FcUMo8QUSMIDgJIJCwM9TPMFfUNG%2FYUnlO7iqqDWSXweVLO%2BXJyLxrwyX%2F0v%2B7oD5QnAAwHEA%2FQsq%2FgYwEEneBBgiEBIiCBj8hajLPxcwr71n03T8B1I0f3Xx9H9AMP%2F95%2B8B5OdV8T8Njf0WNv6ph%2F5JVTuEQl8I8PMxx%2BEvEoQR8macMAyTvzADOHHfDEMIEMQQmICx32w%2BjDmnPoI4%2F7oF%2FFq%2B3q90Heb%2FnZ7t%2F%2FmXXse%2F9yrGEOwLIJ7g6M0UMAz8CZDwr5trkhAEfNfI%2F96r2Jnr3OeL17%2FBKn5m4Ser%2BF6uGPnzIce%2FoF8gZv%2Fl5d9g4Jlg2%2BRrrf7JA0%2FgGMb%2B4QN%2Fk%2BCfDDzyBZO%2FMPLoF4FBGI6DGAqjyC90lPjlK36D%2BbgaRvD98vz3XAgk8EX%2BvMHH77IQFmMN%2FGXj%2FrkDDwA0BRN%2F%2BMD%2FbCGQ4BeG%2F6kWgluLA5XX%2F0Cu57%2FgQoAB4rtk9o9YCEnLlsUhmf%2Fcgf%2FPPlF%2FroXwDDyJ%2FqkWwtTw3JENzC%2FMxz9AqJF%2FJw79OwTasPt3ICiJEiAAIuhP6QT%2BhWJP8SL4XzTV7xloUzwhFAa3%2FnVYwX5g5ffDConcb%2F4nVv6AblRJU0tTdx6%2FDivED6z8bliBQegLhP5IrFx01wTL%2FCubxfwHTmf5Z9jWv9ztP%2FD7k8D%2FvX%2Be%2F389564Axc0XyipdnhfzT%2FUcLvLvA69%2FeujnO3IIgAAEICiOIT8RXeAXjAAgioDADb9foD7%2F3MhPolNHJIm%2FpLv%2BAWjdA9U%2B%2BLkZpe3c47v8W%2BEG%2FoL%2BSOTAXwBGQPd73%2FsCyM83Fr8f8Ofg%2Bc9X%2Fxvwuf87D8P6X94THpOhDVn%2BXPH%2FAQ%3D%3D&#34;&gt;&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars.png&#34; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float: left;&#34;&gt;
&lt;a href=&#34;https://app.diagrams.net?lightbox=1&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=mtcars2.xml#R7Z1Zd6LKGoZ%2FTa9z9sVhVRU1XopznHAe7lRQUUBFHH%2F9KRLTOyb23naiSGjTa3W0gChvPTV8VW8VP9Sks8t6%2FcWkNDdM%2BwcCxu6HmvqBkMBU%2Fh8k7F8SIADqS8rYs4xj2t8Jdetgvp54TF1bhrk6OdGfz23fWpwmDueuaw79k7S%2B5823p6eN5vbppy76Y%2FNDQn3Ytz%2Bmti3Dn7ykMgT%2BTs%2BZ1nhy%2FGTCjjfs9F%2FPPZ65mvSN%2BfZNkpr%2BoSa9%2Bdx%2FeeXskqYdaPcqy8t1mV8c%2Ffm9PNP1L7nA8Ppba%2F6%2F2aCyWO5S9ZfLN317fbzR47f096937s3XrmEGV4MfqradWL5ZX%2FSHwdGtzGuZNvEdW76D8uXIsu3k3J57z9eqmecfmb7yvfnMfD3izl3zZ%2BKrnMHlc%2FmHLT9gRAIi33%2B8ueP9bkzPN3dvko43mzXnjul7e3nK9kw2Tc5lUf%2BIxvjntX%2FLJ18cFfxHNXXdzTfKdeO2aqa14N991DweRVxR2fGqY1EmCmbiJeWN5BRABTEqkKAMYXJGfpUrjFEIVQBVKsTV8mJYy6e3%2Bfrh3%2FNCFsVF8HLlm%2B7Qsv9rdEUxNS9tU%2BmaPkOoUUm287WWmR%2FvE7VVuQmq9RwYym%2BxqmeN7LLpGtOD0Lt5sGfdFGeJtvdUaDFjjPulzDaTSLSQtSm45SoYNohXbG9S4%2B1SXl196vt%2BootWuMWb0G2k%2FOxTZdC0D6mtrg97qAYteZaxZ7ZbzxRMsfFqs71dwoWCrDG14PPzDf2pqHayRX1WFHq9Qpbr6VDex18f0PhYBF%2F5AAqT0kPOBaMqY4K8w%2B0I1XuEjP5q8kwvPL7R5c2YnntMuRphshZDQHBZck9Yw0x%2Bb06BIBAiwH%2BfOng1zHr7Sn55aEwemMUPM5UhhSPKAeQq5RTdk7NZZlMZtlaLB2fx4wwxrHDKCOCEQorxPTkrlleFRt1yHpzFjzPIqCIAR5AgTjGi9%2BRsYvc0q2XpD87ixxnjisBcyKN3755tknNzufat38ds0JQf8QKavu53fCNX1qycW0uMxrPqGAzmbXtQzKmYL%2FvliqOah%2B6wnc%2BwZlFMS8veU9%2FA28ZKd4asUKnStDWqZMtzVH3iC3uUbzTmfez1eaa7fFpkhW62i7Ut1UzQTQO88Jx0Vd%2BYPS2jTj1jx%2BzUeCqZkjpqSc9wehnZCci4vDxSmVEY4aessHc9Nt4QUZ35PZrBcYEMAqEAQCmXEElQTiF7jjcxQYAEv%2FFHymCIweYhsxg7h9b2gdk3xEweV7AqqyoMZdVFWXQxyw9ytc24m35g9g0xU1VV4YQQKvv4HAs1upg1Bg1DmxYuGMZ8YBY5zDCmCuIAyH4%2BEBCK6GLWMexud%2BJsHph9Q8wIkVQAjAlAWLDXTnwUMRukC47t2ftHpPlPoMkukAzMnhFDjBARFc7%2BMdAkUCiMEoYhw4LyT0w%2FXS%2FSzNgVN32wUw%2FMYocZlgECB1RWZJhh%2FDrveSfM3N7M3i0qD8xih5mKZIAg8SKyWhOyPbwnZu6sMU9rpfIDs9hhFnTPOGecQoEwUMk9MRssGl6uq9sPzGKHGURMEYgTyinmHLJ7YlY1%2BzU7PZw%2FMIsdZkgoQjLEiMpUIu4aAaxsu2odxtrvU%2FbnjGdElTGClGCkgkJAJSs8wnMA83UhPxrp%2BQdl348ySImCIBdAhUB%2BLxxdypyZFNRtf6Jj9qDs3pQhxhSKVRUTiDnk0YWsshgm97vmJ8YyHpDdGzJVAAVQxjiDnHNAo0tZupSxvJJtPCj7fpQRgBQsgl5%2BsHhMRdGlzOp01r388NEt%2B4aUUYgVASmVQSYDgES4878xB0axNbtgtcmXlutxRmnqQ8aGucCMEIWBs8PjH%2FXnCpK5I7VGQLKlXk3smrYe%2BOneBUX6m4vNVEWgd36k55nVjw7xm4mdzI1Ts8K4E3uxBVIgvrPYTrVaSKzK7diLDSFQVHoaZx9nc8NTezbvNMyCGX%2B0IeIK4e9GNcJmu6x369Wiloy%2F2phKjk%2BNV6G3kV69udLXnV381aZEAehU7Ze5h38TG11N7E5jbBqNtBd%2FsbmqIHw6phB6tb3YahVd9%2BNfkSAgAzN6Z7WbbmufrpSW8VdbNoj03QRT6NW2P9K1Vdloxl9tlSkCnKp9IdvXq7etnT623F78G0lEqCI7gaeN5LPd6Mywya3Y1tq5etI2a%2FFXm2FFxe%2Fmd8Lubneyu3G32bn1BlIRUFsG7uS1t3ficfrXHuBR7bcjhEJeSOSlKmIEQXa9EcJVLZeqzBPxr2tUGOwBdJofv9drCSU%2F6tO%2BP98VhvHPDxkNgdMtwX6vW3NiyhJEEZATTgkBWL3eDm0tL7XV0k%2BJ%2BGcHZsq9x3TbQ3Pc1pe5%2BItNiYLJKfwRrIsaC3e46%2Fcz8c8Prir0%2Ff6EYdNv5typvthVY682BpJ0gaJO%2F0JbLZ5SZvzpxwgoEJ7mR%2Bj0Lw%2B6OWjN4h%2BFYZUrqnra0kaQ%2FnWl1Hwa5%2BI%2FvoYJVQi5c89nq1md9W56gX32u6vNsMLYnaf8MoN2JZfd%2FwEtrUCKEHdW23Uqq2FmHH9bDIFQQfBTE6zoY81%2Bs5C2nHB2U2cd%2F7F8goSC1Xc7jVxGP7qa2n4iuel1c1781cZMoeRTs4I0xH7NLNVbJ7RyL%2F75QYnC2Tuffdj0Tysld2iU4j8nTjhWgPjKvGEo9O%2Bnu85gNr5gm4av5AcAWkLl982PCPiBvfZ4Ukyvb2y%2BjoDYUfADV8qZ7c7oXbBk%2F5uLHQU%2F8NNQX1cruULsxY6EH3g0Hi4KRufGHfYoqB0FP3Czas%2F7ufqNDQpRUDsKfuD8ZDTIFEur%2BKsdAT%2FwUM92ltn2H4B2FPzAu2anWWmlbzzKGAG1I%2BEHTjadYqa6vPEIehTU%2FrIfOJRRxnGiWzLM5o3HvaKQH1FwDG9HpUS9VS3GX%2B0vO4ZDob8x6mxHKa8V%2F%2FyIgqf40NPWTn5gxF%2FtM57iz9OPhGw1gh1ZBA9Gi%2FHV8mOwO%2BzXJevGy4UjkB%2FnPMWh0999Whaszh8QQp1xDIcutu9UnOW6F%2F%2BqJgp%2B4FZL2%2FhD58YepCiIfcYPHLrahb2bWh3sP0DtKLh9a8Yq1y4PZrFX%2B5zbN3S1F92iVtY6Fzzc%2FburHQUvb7pWWbZ0%2Byn%2Bap%2Fx8oaudv%2BwcaeL9o39dVFQOwpO3cl2rdUP9fg7KCLh1N0549Gu6E3jr3YUnLq1fHY5aOQv2F%2F3m6t9zqkbujfO0tLFjXOIf58kEj7c0W7T7WX8fvzVPuPDvVDt641%2Fr3qlspZx4t8DjITLdpxNukmzEn871jmXbehqF1L1zHbTv%2FF4K4Ui%2BWZL5G%2FpoQ1lqq1bqGw7Rf3GG5hEIDui4LJdTEv9arWTjb3YUXDZppam7bmZGy9ViYDYX3fZhrJ4orgye6XBIP4VfyR8uN1cxW5stH381f6yDzeUdrZkjWvZrTeOf3581an7Njswl8VGUEypyii4Xl1kTNrTRDLRjX9ufNnKG0rbkFuXW%2FOVE%2F%2BO0dfNvqHkR2%2BzmFbt3o1D4ijkxxk7cOht9cAsbUu1yo2HMqOg9pfNvuHQv%2B9miuneja0cUciPM3bgCNZGieEymcv1%2F4D8iIIduGN0PHuzuvFSkCiofcYOHLra3tI0J%2BvljZceREDtSJh9La092uhPNzZ7REHtCJh9U85hYNnb%2BA9BRMHsm6smk36lrsVf7CiYfUd2pu7uGzfemCcKakfB7JvYFLSyvY1%2FGxkJs28j08lqtZURf7WjYPbdawmr5FTiP0sVCbPvYTvr%2Bv4k%2FiMt0TD76hU7O9pt4692FMy%2BKX1UmvnJG5t9o6B2FMy%2BuXLPtdzpjS16EVA7Embf0mE%2BLAzr6%2FirHQWzb7dXzxQX1fgH7pEw%2B2abSX19mNx4f7ooqB0Fs6%2FhriqZhRn%2FHmAkzL6aq7V6zuFcD5DafqDbXN4gAsOjQP8JFPqPPDgODoLXs%2BSnvZz4kv4hq6Qk%2Fml%2BnNX9bSYdk%2Fq2NXblW9scBX8hkNca9u3EMdmxDCP4EM3uD0xbn68s35oHB4YyY0zvzRXFdyf8vPIUI2%2Fu949ngOPt161DcBtc4ceETN%2Bx7CDHcqa9MYO%2Ffh0iZC7LCk8FKuAICvh%2BmokoAEAhIMOCvo7Tv2Ek%2BH7PaW%2Bn%2FH4mXmMmJGMdRnrv3PZ6F7ACH6yExgqGTAEYUcFl4INfRwfDZGXl7CoHs3zuUXcXsIIerITGiiqbHMBVLFsXIdDriESYrOhuLZeethefY0V9sBIaK%2FKwAmXtAqFAGLxGQWGyUkrZE3%2FePrf11gWs4AcrobECkapAijnk8j8OP3q9b87K%2Fqk87j%2Fp59YzXMAKebASXr1CFBndENn6MJWIO3Rtc%2FZwkcxfMny1mvQXwcuVb7pDy%2F6v0ZQfUUvOS9uUvu9vlhiOhzNTWLUfSLOyCdhtAa%2Fc2wxUzuugkes290Td7Vvu6slZOGyrlYFfKTOxLapVmNAOTz3SbXm1BcnNZoVO3dnJj9e0Jqbt7GpbMWrDQbubqsxYyRzmvFxnZC7TmbLaWIkdsxuWOzT5ZlButioVut5vVBXVyxhrSbDr9SYjSbS2bU8Gg9Q2uBc19dcHVmVk%2FPLzMQhWMEJUxp6CIEaIOE%2F0%2BzDZ6K8mz%2FjB4xu970t03WPKFbiS6FAVYoEhRxi9snMSThOGfxUzIYWpgiEK0Mvvj5TBqzE26Ywn%2BafRBTurPBj7Rowd7bgY%2FyrWCpOxfHLRW02tC4y4D8a%2BEWPH5XKQ%2FCpGC5Mxr1Gv69uW%2F2AsVoy97LPMOP1VbBcmY9PNbtKt5gcPxmLFGERMEYgT%2BquYMEzGOodKwjPzFyyjeDD2jRh7Wcosv%2B8vYskwETOSy0U2rY9%2BH7FBgFgxtcpLxNb9juMM6uNtxS30xL5Qg3VQWyz2VMa%2FmQXJOM3EuOGlGztsl%2FvaaEXQNFFsHYoVgyy6qW0vUZp3C%2FLUbAFO7KyzSNqpwcrJaZtuhaSWqcNCHhuo7mTeqExyzXW5uVc7etIamaCXsdVCw9xKiHZD5snzMpWDsVselul1W75bO%2FJIKygMlm4%2FFRykHVZsV25v8WCtVeMDHJHQCIwpBFSi9X41KsYKIoRQAijH4mPnDH5E7BRCeL2BjEl%2B0LYGlQdx35y4YJMGBLkAKgTye%2BHoEtdYtseLmXvBSvQHcVEmDjGmUKyqmMBg0D66wM3rxVnTSV6wIdoDuCgDpwqgABo8nwdy%2FnNBexSJSyUn7bHe1h%2FEfW%2FiCEAKFs%2FrypHAKooucdNtJrkclC94kumDuCgTRyFWBKSUQcQAIBEOHObdqncw1ucWzF5i7ns4Qa86W46DbXgQIIBxTsH7rQrlUSJJZ1BAxsHHR%2BPdfLrctXP7mpHPfBKWh7XiutYKChQVUdmycdmyqZGDRU%2Fv%2Ffbk3NZxl1hBHzXLVWFBTDYhBAgVcyr4%2B073vVlZ9%2Bxudnf2mRGXsPKoWK7KisqJAoOBdCogwJGDpZq017n6pPo5WNRHxXLdLouQPAjBIRcEyp%2BIwdLcFu2tN0t9EpZHzXJVWCgECkBYxjHBeib1fVx0b1hq49F0v89%2FcqWTsxj%2FSbRAeOtmCHJFlQ0QpUhQQN4N2xCuQK4CzAQmCHy0rcAzUfRr2jWeTtj13Zzb8T6HylBq7Mcalv%2BJ0HFRMAOAMUBemDjBBTEeDBUBwTEg6useFeHhMnXWiW5Za5zB5V1uf2V1c%2Bb551eAhLK6mWKg0Hc7CSOVKIR%2B1Dx48gtUsVAFUVVVnMkBmWsUBItJIMUqv%2BKu%2F%2F5Kmzu57vBzxbe%2FUkb9oT%2F3%2Fjvc23%2FFuhyHXYoppgrgwdBoUPHT0%2B4kknAhogJBgIp%2F7p4fXin23WVquX268U4%2BGRT8u3MpDnLhXSkmVOGv%2Bzu%2B1Zwp6Ey%2F7E3yNQaTNH2679nGjZXnjNLU3ZWXfeB3ysuO8RnYicIpooxBSlSCz2z8ff6MazwyaFjPVvf%2BuRD8DygIDCtQvVNBaG1WXaObuvEDUiLwTMSzBUEqz8%2F03e5XEGbrWqa9b1zgu4tjQRBQwfBOBaHjJbKWV3duq3wE9gs6WxCC5%2FihKBWEYW3gbdKtc5tlPRbohz7MRuVnYCIIhwBi8o4dChSGmIySARcA32GTmFZna24q7dTnWKEPVsJjRQbgANyTlaVVnmlPqXMr9C9ghT9YCY8VQWT7HgYr8q03n%2FtvjmVlOz4pzQ0zOOP%2F&#34;&gt;&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars2.png&#34; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float: left;&#34;&gt;
&lt;a href=&#34;https://app.diagrams.net?lightbox=1&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=ggraph-simple.xml#R7Znrbxo5EMD%2FGtRPtfx%2BfCxck9wlpIikPeXTacsa2GZZ5xbz6l%2FfMWseCzSK0nCXKoBYrcdjjz3%2BeTwWDdYazc%2FL5GHYdqnNGxSn8wb7o0Gp4RKeQbCoBARjVkkGZZZG2UZwk323K8UonWSpHdcUvXO5zx7qwp4rCtvzNVlSlm5WV%2Bu7vG71IRnYPcFNL8n3pX9nqR9WUkXxRn5hs8EwWhYqTniUrHSj5niYpG62JWIfG6xVOuert9G8ZfPgu5VbqnZnP6ldj6u0hX9Kg7RMZpl737n9Nsjc5LJqPk3ySZxoHKVfrGZui%2FRDcCCUCleAsDn0oxxKBF7HvnT3tuVyVy61GV5%2BoCZNxkMbbIaCe0h6mQ9rT5aVVbOVIzcd%2FTNbiRCnVDKljKBKCBM77CTe27KIbfanHr1h09piRkecWzeyvlyAwmyzhEwZxAhWimnOJIlUDrfWUhJkDNeUaMolNrzSKG2e%2BGxaxyOJlA3WptbWOy6DUVIcd4TUCgE%2B62%2FVPu4OxjTSRhjOODea6HrnYzcpezb2t73SOyYY1shIYgTj1BDC6yaMARNYSfAv53THhE%2FKgfV7JuBly40b0RKxR3H7tLi9vLzoLN48brDWSBOm4UeNwAdwI1QhTphgREuBpfxdcONEIC605qEjKNZMwKwQbCFOiNBcCXpk3Lru3P%2FZ%2F9Z587hBYEPcSG2oIOD8A7RpjTjWgBsoSfUytP1C5Pkdabv67Ju%2BO%2Bu%2FedqogijDuNRYYaL5IdwERgbWnUjBmRIvc5b%2BB7gxitRP46fgYIKsv8fG7bq76LfvOifctEQEhxxccYqN4oeim0IwL2EYxxQeL4LbL4SeJ%2BPGMGJCEiooJmQHNwrT3sKNHBm3%2BVnx9aacFgdwkzn4udl3y6H3IknvAmrvoHIQKpsTv9IDe5VqVbNHq7dz%2FxiiEeF%2Bluc7oiTPBoGs3PZDD1Nb%2Bgyubh%2BieJSlaTDSzJOvNu%2B4ceYzFyp6QJ8tt1pc7SisW5ZuUqTrPVE6n0QNHB0Qb6wUTtMKeywEgVSqqj1LRlkelu%2FC5lMbTD22B8Jo7PzRXbBK66RAhmijKcQ3bUg98hGOjICbKGGSURw53Q7Xu4Pd2z%2BHNQ5tlRpnTzgyk7u76%2F6s%2BzyoPo%2FtCaqjQUU1Q1JSIbGiwJSpQ6WAOIGFhuuJ0qvr8uuAqn%2Fdvv%2F3r9H186BqOZefqDoaVSyc1sYYDDkaEFY%2FNcMtREDaQE24gDL9mqhafFnMbn279Tyqrux4fKLqeLEKwZ2VMwyZPSGS63peTgXSkIcaoxgR8lVRNZq2mt0v5zfPo6qd3Z9OwCPGKgzpNzFEScwZJ7SefiPI7iWTGO43mBnxf1AFxc0%2FBlVqv%2FnbhX38AQ%3D%3D&#34;&gt;&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/ggraph-simple.png&#34; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float: left;&#34;&gt;
&lt;a href=&#34;https://app.diagrams.net?lightbox=1&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=geom-sf.xml#R7Z1pm6JI96c%2FTV%2F%2FmRfjxb68lB1BkFXlHZuAsgnI4qefIKvqebo6s5bJySrtbiq7MzUAhTi%2FOPc5QUTwB8oWo9j4dbqtojj%2FA4Gi8Q%2BU%2BwNBYJJEwZ%2B5ZPpUQmDUp4KkyaLPO%2F23wMru8edC6HPpLYvi9qsdu6rKu6z%2BujCsyjIOu6%2FK%2FKaphq93O1X5199a%2B0n8qsAK%2Ffx16T6LuvRTKYWQ%2Fy2X4ixJv3wzTNCfthT%2Bl50%2FX0mb%2BlE1%2FKkI5f9A2aaquk%2BvipGN87nyvtTLp%2BOEb2z9z4k1cdn9zAFR4w9Z9X8Od9fgdsL20%2BG9n98%2BX%2Bnns%2BymL5feVLcyiuejoT9QZkizLrZqP5y3DsDYoCztihy8g8HLU5bnbJVXzcuxqPDyD5S3XVNd4i9byqqM%2F1P4pT4xUFKBD866WSMwNH%2Fb64v7fL193HTx%2BKeizxcrxlURd80EdvmsNJhCVxAMoRRMQhAJfdbh8F8jkl8sk%2F7JgAhEr2iSRlACpymcxj4r6bOKkv98y38rGrz4XNffrfcjK5194179wnr%2Fqna%2FbYwv9Q6vaJSmCYhAaBqBEeINM0R%2Bm76cCfz5zc7vurgpP5f886zEjjs3347MP7d1fN6KkyuChmgIIQmCJkji0%2FFfjEJDK4wCtQv8N44hr42CI8gK%2FMJwlEAgFENfWwgmiRUFQxiNAdPSEPFhFuo1sb3Lhv9jCwGHW88v2y4uwyz%2FX2f3vAnyUeJ2g3%2Bwyts08eUw0tmgbkqedyZPPACvzsAmma6NzbrK1vL2vj%2BDovHaXptjBM4wSMFb8N%2FB7rCQxGPwslcpgDRhB%2F4fXzYKpxFcLhPnOn2qofiQ4f1NdvumpQ4qHR9asIfkXC4dqe%2F223pCwZcKdLyJY%2FoUTHegF3Ds4eUj%2BvN9rh7wwsbpngxq%2BqSSkdPf5%2FOMYgn8DsF3CkIHfnnzWUgt3M8b8b5Hb9SuR3sSCeQtvS07%2B3YJKhoLYNEOj%2BeDy7Y7rTwgdERkcimoNq0rpHrS%2BiasfKERdlYnUUOYkQDdRt7UY1VHiK1YTujL2cSTMF12VliU0PUIFWtKESeWvwtKe4vGLK%2FXd8vgyVo85t2xd4xpKPD8IOaBoDRYZ7DipbgW8xUm5GSHF6w1UfmsUwmpqKZ9H3KVWpNT1Mgt5Hkse5Itlt3l1hYxCH%2BIcAXlyasaKxyieZZVBLUVXQ8WRGaq66x5Ng8THx3217pKN4XDw3d9MJpJCYSLKBYRT468YPl1DsQnpKnqwq5juEO6LuRNpBkWQ%2BgmNF7LczvtL55xTRhyCkc8NlNZ4RVs8DuPi5uw3KQst2VTAQomMmqrlDmU49UtLjf55tgHZZr1PKiRzl97Z%2FB5dn%2F2yDKILszFUZ2NgdVHJ55Iiyc2d2NNlXUam2e54k46BBAhsIOfRhv2ZK31Yq4mtRH5wzppz51xUdoOvew3FZvC%2BRDuC53KzhUQJ1PpvUGYIrOJYcEQLwc88VQlnzd4rO%2Fg%2BFgxcNtFNyg2CMPGWMjad4bNWgYZWprgB0aEi5zIOcY9Z8D5memG3dpsyyEyrk5COTVepVVezs8f6V4M8Nsxm4u%2FvrKjy4N30gRdQscWkU1DcKguTEw2OPhZh%2B8sseGgyL9XHBFVCWmvcaKrrd2u5%2FXQDq%2BUwzI2sou4UjgoMjxG5QUf77Jlb7FwF2%2FnBkcddNNOOd%2FBospt0l3pyyI06mVPNKwLtl8v4yE9M8kFvzBpVKWBU%2Ba81FC6SErcEDNz07xye0qq5TDf3%2FB07Z%2BtxCNkqJMp6SxtC3nQrpMUy%2BL5rnMYggwChWP5SNqDimQVxNA7uz1UpzWmyGbCM9SW8LF7t76wGV9Fe3EKqayi1ZMyUJoijrP5BQcBddAgvIzUR5KBDBF8K3cJUTcU9mSkcJNd8M36eA6oFrc2ex1DmSQRig60H%2FUYjWxz32F8sR%2BtgSoYYmw9d73eH68lJ9sirwRJXVQ4M%2BRb7kIeJE0Gl9il5k4xEs0g1rO7Kpn6yO6r1rxtjR1LF5J30NcJxV3Ps8%2FZUFNW%2Bui0zgp5tIr1ndxHVaby16srxNVGz%2BlrTXFnTj5aORLccDO5cIrE3GUTvkmb4z2ZBn1dMPiVFHsQTzLkznTc9qKIhQZaxqxb4ZDLWL3eKNn2whCN4DNybw%2BmgoGYefLiC654k3YTjtlAOEJCuRsvFAaB4O61s3XYLeI54EN4gbki4wwZpjC63VSyjcSpbFuh9AmUabOPDKEThJ8aLFZvBmBgdwNbhP4UqTQZkcqux4T%2F%2FVZkxDPzz89ERm%2FEWb8xWPq8lYBWEIRBKE1hNAWjyP8btOHfSGm27E%2BMpysLpRdKL5ReKL1QeqH0v4XSAMwrEkFpHENpAqHw56W0vQ97ObHlhdILpRdKL5ReKL1Q%2Bt9CaQTCVxgAKkHRGELi8PNS%2Bmju9cP%2B4CyUXii9UHqh9ELphdL%2FGkqT1AomUJJCMYpGkCfu8V4nTjce63ah9ELphdILpRdKL5T%2Bt1AaxaEVRaEETUEoTtD081J6E7i%2BuZ1910LphdILpRdKL5ReKP3voDRg74qAAIcRnEJg4onvS9%2BloL1KF36h9ELphdILpRdKL5T%2B11CaJlYoyKgREkYoAn3i%2B9KybLfWpdYWSi%2BUXii9UHqh9ELpfwulcYJeQRiKYTBB4vCXaevPSOnswIznynvfTCw1SL9QehaRhMUhN7NOXod9bJr25rI5HFDi5BOUyST8mmo4zpcM0oP9MaOju3eb0XLgYComa2sWQjOv%2FwFAKtyHT4g%2BnOdd9qVOHxpo3jnFT1dFmRmOxC%2BQ75spbuYtyGiDP2hq1fVVjvO2KU7lXECXAUrSu%2FtE7cr8hcflmXyRHTpifTTdTuW8HxnbJHaf9AADm0gKnr%2BcJmNSutI7EDMwWBaNyOa40ZAO3huOBE6Nn0%2BUna%2B4sXeFZvO1XeZnmeDHvOFk%2FBpoZBxFA8FilcJloyLSneGLjc3nrpJ6seswmUDbvJvvzrVfMn1YQZ44dXiep5dmq%2FDXQJ4MQJ4uUE%2Fm5pqN3KhwtrGtdXMrr2WO3htSbGeecJkSErEKfXYs4Jx4T7IE1m%2F9LeRZY8dApmWj8WEPkTVfJYVlUbaJnw58FaYahikwMekHYV%2FaWpLnqCTcU4KVMFDvQnLcKrZ%2FLW57e0uqtXw%2BWVBEXmSkRDeGFZ6KkZFSdjwDfwMXJQOl4WClk7q3%2BO3UKNNe50z6SKBetkluoZkokRrvtdDMoxt8tVk2yYEqgm0Oz94DmKxhlbEGX%2BvCdWVuFPfcqKmBTqTMHutTsPHNm2nIQNlMrU%2BbMC86%2F6AzYEd9PZtVBEfGAF7%2BYc2cRNkT4VGRq%2F29FCu9vUuqrjNacVcyr72rfazfjkWquJ7pJ%2BOAySBMFZS9qbXeHPYlOiuF17NylJ1hgutTTfJlxvNGcjvaZKfrqbBP04pJnGY%2FEbXic%2Fgh9KTLwadon79vL1AC2iKTydKe5oB31Pyj55Z%2B6l6w2NLjo4quWeek5MLRsyo14%2FWK7EV2Om3Zbr3Z823n2ZMlb%2Fhw3VlmMOTc5bCDGNWubCWJOB45FsPZCGT71p19UWYzZkhllm6i8STulFpjx4vJnQld9SovUs7nfF%2BVbHo597SVbSEl9C2jz52ItDV5HQhH0ITu3RiBfTeAaC17ufHrMmLM%2Fbol1wzEhMXe4Gy3m7EVVkYf7RHnumlHj9isr25jOFSqsCxfaFitqW0dWbaq%2BFmxQSOIdRw%2FggQAuzy4iY3FDtXFcqBAQSCCVpLUkfeayORwuncHA%2FU43WC3MXM8RhiED3eIFHCdO7eZ1m0TgKphDtk5gR3hXnbCPVJlOD0a%2Bjj61z0rKYkx3qphTOrqolzG47ojUwgECRXaZydWWodyzjmXdSausbhFrzUGw85VJw3ppBCHaGuM0l7nQ2SLng%2F8ditOWjQpFcXm%2FtiC9mD4rjGk7W3XKbJ0hST%2BeLj2MRsl2NrYknf%2B3NXeZndRD%2BvZF7HcLqfYy9GCt3JymexUbfBkNE22H2zhxGy0jg0Ng5dPm4unddfYnH3Ojt5Hc3JyPoT7cvZ6uzMZHmSaDi16jgLoBp09Y4zS2ZyJUOw%2FgpTfW2gExcFpkwCRNITP85pfkfIvC41gb4Dzw0gpKFteYfNyIeVCyoWUCykXUi6kfB5SIvQKpTAIxmAUJzHyoaRUvboKQPUspFxIuZByIeVCyoWUz0NKiFiRNEpS4JRJDKceS8prF%2Btr830jmRZSLqRcSLmQciHlQspfQUqEwlbIPGMHA2f9n4XrH0TKdLPX2ZvfLaRcSLmQciHlQsqFlM9DSgJeETCKojRKQRT52N7Xnb0be%2FVQL6RcSLmQciHlQsqFlM9DSpReQQgKwxhGIDj12N5Xjg3ScnN%2F3wyVhZQLKRdSLqRcSLmQ8peQEiZWGIpQFI1jcwfsQ0mppIm32e82CykXUi6kXEi5kHIh5dOQEqbRFYUhBAFSSgKCHtv7mq31Sj1F73hmTu4eAClrhgekbG7abNkBw80TZljUURxtfr%2B5fqKdPSFqeTjwZtUkAyeTsO26sA0Fs%2FAn4ob2XlCZsU2duBlkyKyWE1zTyOXclrM0guPMLh7F0yA4zWJicB2iZyrIBMpZG4ua4gCmYSjcsaOWUBpPNFPbjf0sMGmNvQB1lyIvasT7O0X1kW%2BfXpDMlA22qw%2Fgte6LKucVyRbSAx05QQd6a%2FEUvJt9qI7MDhy9h2kv50rnWFV76yqxt9j64IoNksaUy%2Bk4o8RSSEZNzGJT5rhlrbjNxvFb6iZ7VhhkZtRfLXNuDMDF2AJUwXjpxPpGb5EpKZVjK3EBk5b5poWVUDxOXtt48yUw%2FK3W2W5%2Fze%2FTJb2AIpHl9Rru9%2FeDZsXdkTbrxN84LppVLeIOZyssOTlU0RZTo6KfLzy6kUFx5PLU3d%2BQWNjTxSHLka4%2BEgisA%2FMKrFqfdfG8OXSZbDieizvXHvh6H4msaCJxvYKLKcx4vFXBzoOeMXaR7YTdOWOp7ZS2nCSwm6JQBb2ap6gzmqxlQlidhnMIu6Lo1kyJ76n4eMmwWyaWSQiV0v5IKsd9Uh3jvXHvD0NurXEQICRD3agYZ0wOL5sZCMGEJk6Ok0kkCaE5AuL5VgSMbCMmz4sgZmKG2Y7A8G60Vd025uKp1dZOU8Z2zKQtifW%2BO7GZeWUPPO4m1KajvfvFCqxqw7dTZeidRJkYu6PkQajHTjFOyZXigB9DoJdFOpSRYIwBZkybZDxp7Ryh3BO8deDBBAxPopA0W7sywGlCxtYQxSNRbzGnC0aSFbujZwukZAOIM4LHYRvHIW7mrRlQKHU11YjS7QWxbzbL5J1fnB2ZSu6I0kdHWHOHpKqPGmkBczMmO%2BI%2BVxSniSEnjb7C6sHg7%2Bxl8FUAtE6DoCidAV879vFO0qcSkeCTdp%2FFoxKFNPtZzjzlTIQH%2FeyDEZGcQ1vY7E%2FDFrTpN30uTs8%2Fr33uGw8Ap4Cf4x6zojqCrXCYJDCMxAgKpb7OSSBiBUMIDlwxAk7ojZnrBLwCB6IETGDz%2BJHXnhb4ahKjCQxCUAh8zsc9ml0u9GTi7XdMZJ8d77nT1vxu8g%2FiaaamnQ5GOch8JfDqpnO15v7i2dRzwkujlQ%2Btjuv11SeuZFfWCH7iXhwzc6Lt2zkPzziNlnOGcmqSEL2N%2FHnW3KyaU44NZr%2Fn%2Bv5cU9rsneuCS6vO6lAvPx4Ef3bMiGphnuwR6YVurIpEA4K%2B7ep%2BR0O7Ep7ddMkBReKzG3Xvp76eg0j7OLvfQmWiFGmtAmcdF0bGE0VKfD5XpXQlA6midz0Z1Wf0aMrlVisNyi3KyOWGPDXUzXQT4fk6eJCyJWlWhY07ue6ag0gmoaCDU0YVu6bR6wXrhGgjFF4uQde1w81RucZWsCZdbiY1BSjvwPt8C3caOZDMGDnK0FvW9pbVYeUZKGiHtWOZG87fnVPJ56%2BTGQTxva7SGx%2BBsH%2FrXcO6Y9WAGfcE422yPogyRM2EmyBFXDTg0bTHzqPPENfG8CnfuyQSm7Y8dlVgOGAg3%2Fb3aw21JG1zCepKYMRTCF3xrI1DwVVHtQmozamj2ps0XKdKvdmVOuKKTCnMcT8Mft1JFVLbNmQhzrY%2BxW1asb0hg8yX0UdVgzezY%2BrWM70MQclEOzKvIb93MQcyhBI%2FTiQiQYqYxDlLMNCcgUIU72d77uBVMdRk8SYYKaxmE9OUG%2FQoi1E%2FDWciEAw336MCMRGKuMkHHrpt7DlJEwsxNBR4bZwCW8%2FOOJYK20wQNP1A8tnWFGe3k%2FWmiyozR4L9vgCHCzc%2FznS6aLSNGAV6mkGaD583mXzOrLNfWAXjI%2FXO1wUv5yaRFwunrKEkvM%2FeWR61AB6dKRAAUdCttpbyC8GKBnuMLOM6e0X95IijdExnseYuNJxTts99Tz5dNq0lQ%2BN5J6JX54SFnHm%2FKJw2SDcBOppz8oxfiTWmT4dWShxHFMTjgQu3SLvd2%2BszpQoOsiEKTENpadYVLyhWk%2B0rcOC1vHobLTXcNOaCvr9Lh9NhwMmAjKWR6jXizhKIdJqFLs6xSQc3%2BtxQ1sbc4v%2B%2F3TEEMWvgCR%2FhjingTxGawCECp0ia%2FuuinBTw1TQCIWAfGMNfu2MKBL4ITRIoQpL0G2EvAa1wcH00iPopkkI%2BzBkzW8br2N077qyU7mETphoj7Fr%2FcO9AFEOEV2mQXfPcypnpbLX%2BNK%2B7xGNbJQj1wzq4ISfHv%2BS7PtLRw5z89f1tRI2c3t2hF588q1on59eSdr%2FNSRSjzTpGBwoz8ubl5TiXimAfYYvu5fu1ul6NPHbROYMa9%2Bh5Ww%2FsuCsooolf%2BNClxNxtJIQn4P%2FnaJhET%2BW8GpsQlwb50gcVlyTV33YjCNkuwtV3XE3xjnPaNzuFu5NgXZMbdxveRDMH8P1ZPp0xmNqK8SZ1LNLHirm2JZEToI3kqJtSd8zTVZtYhWlIBM6uFAyHUMSxG69aF7FLGgHCXGYP7iCVk0Yhd4SU5AQS3014yNbQzmkKak12bClVYeWYAw1ZnFprxOjEmqBQU5o59uGuriFsalh7bCRMkJGxulTmRVDz%2BBjZyVZ3Ww%2Bl5raMHUMp0ZBczsXuUnf%2BloE8k68Mr%2FK0GjRr03JVLTusbS%2FgmMtQDMmlbXhktNenbE1NDsg5Tp3wgq4oYQPcTpJ8Wxa7itX4%2FFDDFL6%2F24aCGVsWcgFP2fPaR5VcqLbFhO8uVbVHRRS8DqBuHRpeIg5uJsOR7%2BI3MU1ZvsJOvoqco9YxW53ci6erKFy785QIrMVi1Sa9t62BbrlEkjtyc2TkE1be965cFJ0qeTSIoMcrdxQivWbZo3JBNF8tNSLYalfCuVXyDtJygzmj6yu%2BhY9q7DPTRpA9DvjreITFIesN09F8sySgyyHZD9W6InjEsTRGJdzBbZnrRglHq10PNbqNs5vPcbdkK%2B%2BBiitpeywrcwOfBBBMAh97k1MazRPfP%2FgC8M65HtOqq%2BNWSm6gQ1C3jLfOa9fUkjAoXUKVdzpHYZmteEJnh3ODEJi%2BssGLY3zZwyjMJzB0ZhWSObV5DBMGb2zFzg4w%2Fl6nPEw56yq5zybWjG0G%2Fri7UYhIs6l0WVZxZV9VSE44bmVm6cYfUzQIpEDkokRWmw2fKtd5MSHhU6ba0WiEUv3cTStI6TFAUJUUqU%2Fb4qx3b31Ezm2M%2BxhHTcA0KwiPecYBga5QhIIIBALxL%2FmXsJle4ThNIwQBtqHEaz9NIysQ8uMYiJph%2BK3lnzB6RdAERFEUQiPkx3VX%2BEzJ52xt%2FthRN9WtjF7qcK7QIc262AK1PG8dGr8GZWlX5G%2FY5XOn0Suzfvr3M11QT9ff9IP1u%2F7S34S%2BYc9ftZzXWbrv55DyDXsSeTdbpgKVgkDhZzv8z2yd%2FwEbk3kjSoDz%2FrLnnK687Pxp2ytBgKrsvrb61yb%2BbPc3pODnWTIbK49P8yfMZslCP19%2FLi6yKJq%2FhMn9IM53VZt1WTVvCIFB4%2BZPR6h%2F2eE%2FR34t1qbq%2FM97QJ%2BrwMru82XAyOf3gl9k%2BWxfKc77eP7wjxESCdJhEKZBwCnMf7%2FSEYrhq1lE31zdBkbeUM7HBWmjYlalc33rwaE%2FoZU%2FWOQPBlrE8oFiQckVDsHA59AY%2FXRqaUQh3W2T9fvUoi1C%2BUChYMgKJKUwhD%2BjWzEOWScp7OXdCEIXrXygVmBsBWM4BYE44w2nAiIVkoTxby4b84u1Eniho%2BoVsyDoSdTyfQQ9WC0xUyqGcfUXBD1eKN9H0IOFcrfE9j5Eb02B%2BkkELVnQb8uCIGgFUzDyzfVYfrFW9uut6tUSuyDoScTyfQQ9WC2WfD5t9%2BKwIOjxQvk%2Bgh4sFFG%2BFAflfn83grBFK78rC0JI4HJoGPrmQie%2FWCuuJkWTeh0XBD2JWr6LoEerJbNsLrv0woKgxwvluwh6tFC08NiKXvTWw8x%2FEkFLFvS7siAEx1cQBFHfXEHkF2vF1%2BKdKQ9LFvQsYvk%2Bgh6sFnmTyXLX6wuCHi%2BU7yPowULpW7Mxt%2Bw7bxoCBC0E%2Bn1ZEIqsMBCtfHNpjl%2BslY3AH6%2FK0VsQ9CRq%2BT6CHqyWKbvdqqPyzpx5QdDvQ9CDhVIm6ztnVYf3I2hh0G%2FLgiB6RSEQ%2Bs01L36xVk7Szb8W1js7bRcE%2FWYEPVgtWqCnE9%2FZC4IeL5TvI%2BjBQunis9lVbPBuBBGLVn5XFgRT5ApBIfibi0n86o64eFIErXjnAP4FQb8XQY9WS7RTD7HnqwuCHi%2BU7yLo0UKxi3Tfus5bA23%2FYuu%2FTsiNnHnRC67aDtzu5h%2B6k8HyUBhdNhTLKIKpd76rqgd0nj9rZQ5iR1V93kN42wpIVZLw2PKp7s1z%2FEojTi%2Blrsm7Rm997SBTkGkR%2FHWDHn1Jpj1tjXGBytYI07WjN09XzCMZ4chy29d6ZgW3Q1gRFlOf54tvBfeAqRmp9Oe%2BnZdCSC7OzuBv1PbT5MIbD%2FvksTfWf3xjUuHPzz57jgWQ0BUIXmjghxBwduTX8wt%2F%2BJhsdEWiOE1DEPry9w2lfZjQ3P3RVi%2FpWwOkFqH97YX2o6fM%2FkahdccYECF8K1dfhPa3F9qPHtL4G4V2KAvekbhFaP9Eof3wGWe%2FUWiWm7jrvfGOx2YvQnt%2Bof3oEUG%2FUWhpb52O7tpchPZPFNqPnrDxG4XGnTn%2FdC0WdP4jhfajBep%2Fo9ACwdmY8fBWP9gitL%2B70H64vvNvFNqxY5hcjt5aM%2BUHQgu%2BJzTmk9AaIDTK6sTSthveHrGL1iU9uh0vkgWRoy2F3rYGAtiGo3K83Ay3sbdFYWcHLSX0PRdqaxF3x09LkebXkms51TvbnJXHa4SjmhIoM7GC%2BSEIYUVmDHmm1KZgSrd04wFcqxB11PzxZ%2F40Hi67lusDlPU7rz20zD9BZAS0gqC5f4zCaApGka8zToJcITRC4QSMkyjyxj3C17J6U3cf0Vl7L0K7kt7hzRaRPVpkQFcrEsRgOIbSBJDT04rs6HrR%2FXZ7a%2FTCIrInFxkC4SsMQymCojGExOGnFVmtjLfwPrzjuUGLyB4uMpJawQRKUqCSaQR5Xlzueyd03WgR2d9QZCgOrSgKJWhq7oT9IoonFJmn%2BI7S396aybKI7MlFhgFVEBBKwAhOITDxvDHZxfQuJ3dzWkT2NxQZTaxQ4M8QEkYoAn3emKzTRO1yud0Wkf39RAYQuYIwFMNgAoT9Xx7A84Qiu2bNkTffHAb0EwMTKXhFLWMTP3JsIrRCCJSCcIzEXnd9kaC6ERIC5QiG%2F%2F5JwqfLUZmC7TsXNFmGPH%2B4WggQLsE0QmJAD0%2Bnlp3Wy5fi%2BM7JFPtFKB8pFGqFwRQMIehbPeoPFop2qnTGD94aTvNzCFpm3XzorBsYWdEUSiIQBKz8147xB2tlH693bKDwC4KeRS3zIrwoDVMUST6dWsrpNpxcIJEFQY8XCgavYBDZwgT1xv22Bwtluopae%2B3enwUti4B%2BqFYofEVCKIFiOEG%2Bum32YK107p6P1%2BI7F7dfEPThaplnjUPz%2Bo0oCj%2BdWlhp091U753L3ywI%2BlChwOiKwkkahbE37sY%2FWCiS0x3CTqrejSBk0cpHagUHKTOCzmMdYezVTfUHa4XbFbWxcbkFQc%2BiFtD%2BSJKGYJIink4tDssURzdpFgQ9g1CIFZAAheH0G2N1HiwUP4rtjXQX34ugRSkfuZwJSqxgjEQJel6Z%2FK8Dbh6slPZ6LA7bTbIA6FnUgtErjMYhhICJp1NLnwmaJ%2B7fWtNkAdDvFgqOrRAapXBsHn%2FwZELJOflwD6vtOwEELYMRPngwAsiXCRQlKQQiXw3He7BWhslnvKxcVqF%2BGrUg5AqBKQojaPzp1MLXNzPn%2BncuAbog6EOFgiIrkCkTJA69Mcr3wUJx%2FZzJp8M7l3UECFoGI3yoVkiQL1MoQiMkjr4arPtgraR8nHPZeweuLAj6eLXQ9ArEtiQB49DTqUXXjX69U995j3lB0EcKBYewFYmS%2BMtQhGcTihT6QcvG0rsRtAxG%2BFCtYPQKhVCQAr2sGos%2BlVb0XG8kp3hnxrwg6OPVQiIrAqcIkoDwp1NLdDq4gzXVC4KeQSjkCmgAkAh%2BY4bQo3ts75pbntKfmHr2dX0OadbFVu2H89ah8euvZfBni%2F%2BBoMLLv2%2FJ4%2BuJXtgfr6dxfYQVaGxFUSQK0lCU%2BOuQEJgmVhQBQxhF0jiCwa%2BtAJMrAoNICEUpCv8ykesrmxDYCsJRGIFQDEHIDzPQGGpKuS7a97Vkbb3l%2F1WNGf%2FFjZmAkBWK0whNEDCMkV%2FLCNh%2BNUcREEoRNE28ISP8DeHgH6aVkI2t48SX%2F%2FjG%2FH0rIPi8gAGMojSGEdRrK2DICgctngKpI40C1%2FvaJm%2Fv8RFPVOz4ItTGtx7q%2B5EWAokxwT3YQugKIoA3pSAEOFX0LxYi5sdwg60ogUAQ9tpC8GqewkSAFoWRCIa9YaE39%2FgAC52L3em8Pbzlbz%2FKQl%2FZ4U9mw%2Bn555WF4BU2TwAkZzSR%2BMsOj1ip7W9qz%2BZmD%2FeK%2FYnlAf%2FRPnGeFwgsB1M0hUH4U%2FnEHRv3%2Fr4vfq2FIIhZo9QT%2B0SCXsHAcBSEgWSAfKo21J9MXRz7t4aLLT7xb2jPs9Wm%2BaU2%2Ft0%2BEYWhFf3SQzzPlkaeyifeTuM9vSXyr7UQAdPswy30nTaEwvCKAL8IHAO5N%2FZUbWgncnEcXfTFJ%2F4z7BmcpSA%2F2e%2B8xbvO8zhJ%2FXL6V3W2%2FOqeUwKf3TdEEzCJ4DjxNV8xaEVgIM9FaQJDCeKVln5xx%2Bm2ja%2BZOb0Vtf6MXkA7XKTyu6RCoSuYIFHs06Jav10quZwGGe%2B%2Bcwy9dWuaxa38Lq2gCL4iKBJCMQgDAeIv0wp421RV96dtIogF0m0VxfMe%2Fxc%3D&#34;&gt;&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/geom-sf.png&#34; /&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear: both;&#34; /&gt;



&lt;/div&gt;
&lt;div id=&#34;editing-in-drawio---moving-adding-text-changing-colours&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Editing in drawio - moving, adding text, changing colours&lt;/h1&gt;
&lt;p&gt;Rather than outputting a plot as an array of pixels, the &lt;code&gt;devoutdrawio&lt;/code&gt; device
outputs the plot as a collection of geometric elements.&lt;/p&gt;
&lt;p&gt;These elements can then be manipulated, resized, deleted or altered, all from
within the &lt;code&gt;drawio&lt;/code&gt; web interface.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars-move-o.gif&#34;            style=&#34;width: 48%; float: left;&#34;  /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars-add-text-o.gif&#34;        style=&#34;width: 48%; float: left;&#34;  /&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutdrawio/mtcars-change-colour-o.gif&#34;   style=&#34;width: 48%; float: left;&#34;  /&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34; /&gt;


&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing minidrawio - create simple draw.io documents in R</title>
      <link>https://coolbutuseless.github.io/2020/04/22/introducing-minidrawio-create-simple-draw.io-documents-in-r/</link>
      <pubDate>Wed, 22 Apr 2020 19:57:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/22/introducing-minidrawio-create-simple-draw.io-documents-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;minidrawio&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minidrawio &lt;img src=&#34;https://coolbutuseless.github.io/img/minidrawio/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;div id=&#34;minidrawio-is-a-package-for-creating-simple-single-page-draw.io-documents.&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;minidrawio&lt;/code&gt; is a package for creating simple, single-page &lt;a href=&#34;draw.io&#34;&gt;draw.io&lt;/a&gt; documents.&lt;/h4&gt;
&lt;p&gt;&lt;a href=&#34;draw.io&#34;&gt;draw.io&lt;/a&gt; is a vector diagram format and a website for editing such diagrams.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minidrawio&lt;/code&gt; is an R package which allows you to create draw.io diagrams.&lt;/p&gt;
&lt;p&gt;It’s killer feature is that the &lt;a href=&#34;draw.io&#34;&gt;draw.io&lt;/a&gt; website is an interactive vector
diagram editor. Any diagram you create with &lt;code&gt;minidrawio&lt;/code&gt; can be uploaded
to the site (for free!) and edited.&lt;/p&gt;
&lt;p&gt;Currently, &lt;code&gt;minidrawio&lt;/code&gt; is not a very complete implementation. Its initial purpose is to
contain enough functionality to be able to use it as a graphics device backend.
(&lt;a href=&#34;https://github.com/coolbutuseless/devoutdrawio&#34;&gt;devoutdrawio&lt;/a&gt; is coming soon!)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/minidrawio&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/minidrawio&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Lots more documentation and examples&lt;/li&gt;
&lt;li&gt;Feature parity with what the &lt;a href=&#34;draw.io&#34;&gt;draw.io&lt;/a&gt; web interface offers.
&lt;ul&gt;
&lt;li&gt;e.g. be able to programatically add any of the library of shapes and
link them together correctly in a hierarchy.&lt;/li&gt;
&lt;li&gt;text rotation, shadows, grid layouts, etc, etc.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example-of-building-a-draw.io-document&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example of building a draw.io document&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is the basic setup needed for every drawio file
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc   &amp;lt;- DrawIODocument$new()
dia   &amp;lt;- doc$diagram(id = &amp;#39;aaa&amp;#39;)
graph &amp;lt;- dia$mxGraphModel()
root  &amp;lt;- graph$root()
root$mxCell(id = 0)
root$mxCell(id = 1, parent = 0)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Now add some text and other elements
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
root$rect(x = 50, y = 50, width = 100, height = 50, size = 0, colour = NA, fill = &amp;#39;green&amp;#39;, alpha = 0.2)
root$text(x = 150, y = 50, colour = &amp;#39;blue&amp;#39;, text = &amp;quot;Hello Rstats&amp;quot;, fontsize = 50)
root$line(x1 = 100, y1=100, x2=200, y2 = 200)
root$circle(0, 0, 20, fill = &amp;#39;red&amp;#39;)
root$polygon(c(0, 200, 200), c(0, 0, 200), fill = &amp;#39;none&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save to drawio/XML format
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc$save(&amp;quot;/img/minidrawio/example.xml&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can &lt;a href=&#34;https://coolbutuseless.github.io/img/minidrawio/example.xml&#34;&gt;download the xml&lt;/a&gt;, or click the
link below to take you directly to the plot on &lt;a href=&#34;draw.io&#34;&gt;draw.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://app.diagrams.net?lightbox=1&amp;highlight=0000ff&amp;edit=_blank&amp;layers=1&amp;nav=1&amp;title=example.xml#RtVZdd6IwEP01nt196Dl8%2BPlYUWq1VVvban1LSYR0I6EhAu6v30SCgNDWPcd9MrmZmTj3zkxomNY2uWEg8O4pRKRhaDBpmIOGYeidjil%2BJLJXSFfvpIjLMFRYDizwH6RATaE7DFFYMuSUEo6DMuhQ30cOL2GAMRqXzTaUlG8NgIsqwMIBpIouMeReinaNTo6PEHa97Ga93UtPtiAzVpmEHoA0LkDmsGFajFKerraJhYhkL%2BMl9bM%2FOT3%2BMYZ8fo4DZCDG9MpGzm72bA9S9wiQncpU%2FUu%2Bz1JndOdDJL21htmPPczRIgCOPI2F2gLz%2BJaInS6WG0yIRQllB19T02xbk24hZ%2FQ3yk586qMjmPEpzagIjLksEkNuq7mpdCPEOEoKkMr1BtEt4mwvTNRpS9G%2BL2%2FjXERdU5hXEDCzA6pu3GPgnFqxUOx%2BybTzekc%2F7JVdw3SbcMkZFdnJ0k3J%2BXHgTTInVm1XWoxEYCpMHkMOeJj5iftT19SoIpxgiJfVqVWhKJmCAMGuL7aO4B0JvC%2F5xqIbrtXBFkMor%2BkT8IbInIaYY1rrcXdiwKmsmHJNMSrSSo81xYeaAK1sb4MtJlJDQUWEZOTLlIf%2BfX20%2Fm95jEHI%2Fcnm8ftGRD68lqMs1%2BlTaVUJHVoPgtA7Up03mF7oy6wF9a9IRbA0IquUlnpKr5J2BBkiQu%2BoPFrrqFR3zCk%2BdEimmVbW7LjPQoR0xxykvIqj8CSQcRLIOA3EAXMRrwQ6KHtM%2FF%2FEjmLk4VmYnCE2IeJtOxEZhEH6uG1wIiU9d6yeTGU5k7W6arhAQ10ZZU6P%2B0J1NGs6qnm5jrpLxv5s7Sy%2FJ1m8xYFchhz5DiY%2FyYvVGYT3sTWPwZpFhmn5E097mFgA70ZPvtbboKnbMPrTpflGYWIOR%2B6st7zxXodrfTNuv97OR3Q1a%2FaTURzu9xToo%2F1gOqZrQ1%2B8v3jrVTyPAr5I3rf%2BMkk81oL9xXSom8%2FRbWh6z17PWU0%2F6GQ0jj6g9dQLlvxJh3b3JXCb%2FYG5b8%2BNHRAcPKwivzv49WXTV%2Fu6ZsxfUv6CvEbdg1rprTMEFtv8uyhtuvzz0hz%2BBQ%3D%3D&#34;&gt;Click to view/edit the plot on draw.io&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;screenshot-of-plot-in-draw.io&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Screenshot of plot in draw.io&lt;/h4&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minidrawio/example.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;edit-in-drawio&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Edit in drawio&lt;/h1&gt;
&lt;p&gt;Now that the diagram is saved in drawio format, we can load it up in the drawio
web app and edit it to our heart’s content!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minidrawio/example.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Manipulate CSV files on the command line with dplyr-cli</title>
      <link>https://coolbutuseless.github.io/2020/04/20/manipulate-csv-files-on-the-command-line-with-dplyr-cli/</link>
      <pubDate>Mon, 20 Apr 2020 21:46:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/20/manipulate-csv-files-on-the-command-line-with-dplyr-cli/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;dplyr-cli&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;dplyr-cli&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dplyr-cli&lt;/code&gt; uses &lt;a href=&#34;https://cran.r-project.org/package=littler&#34;&gt;{littler}&lt;/a&gt; to
run dplyr commands on CSV files in the terminal.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dplyr-cli&lt;/code&gt; makes use of the terminal pipe &lt;code&gt;|&lt;/code&gt; instead of the magrittr pipe (&lt;code&gt;%&amp;gt;%&lt;/code&gt;)
to run sequences of commands.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat mtcars.csv | group_by cyl | summarise &amp;quot;mpg = mean(mpg)&amp;quot; | kable
#&amp;gt; | cyl|      mpg|
#&amp;gt; |---:|--------:|
#&amp;gt; |   4| 26.66364|
#&amp;gt; |   6| 19.74286|
#&amp;gt; |   8| 15.10000|&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;motivation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Motivation&lt;/h2&gt;
&lt;p&gt;I wanted to be able to do quick hacks on CSV files on the command line without
actually starting a proper R session.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-dplyr-commands-are-supported&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What dplyr commands are supported?&lt;/h2&gt;
&lt;p&gt;Any command of the form &lt;code&gt;dplyr::verb(.data, code)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Currently two extra commands are supported which are not part of &lt;code&gt;dplyr&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;csv&lt;/code&gt; performs no dplyr command, but only outputs the input data as CSV to stdout&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kable&lt;/code&gt; performs no dplyr command, but only outputs the input data as a
&lt;code&gt;knitr::kable()&lt;/code&gt; formatted string to stdout&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;When using special shell characters such as &lt;code&gt;()&lt;/code&gt;, you’ll have to quote
your code arguments&lt;/li&gt;
&lt;li&gt;Every command runs in a separate R session - startup overhead can get
prohibitive.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;./dplyr.sh --help&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;dplyr-cli

Usage:
    dplyr.sh &amp;lt;command&amp;gt; [--file=fn] [--csv | -c] [--verbose | -v] [&amp;lt;code&amp;gt;...]
    dplyr.sh -h | --help

Options:
    -h --help            show this help text
    -f FILE --file=FILE  input CSV or RDS filename. If reading from stdin, assumes CSV [default: stdin]
    -c --csv             write output to stdout in CSV format (instead of default RDS file)
    -v --verbose         be verbose &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;dplyr-cli&lt;/code&gt; is run from the shell but at every invocation is starting a new
rsession where the following packages are expected to be installed:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;install.packages(&amp;#39;littler&amp;#39;)  # Scripting front-end for R
install.packages(&amp;#39;glue&amp;#39;)     # text manipulation
install.packages(&amp;#39;dplyr&amp;#39;)    # data manipulation
install.packages(&amp;#39;docopt&amp;#39;)   # CLI description language&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll then need to download the shell script from my github and put &lt;code&gt;dplyr.sh&lt;/code&gt;
somewhere in your path.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone https://github.com/coolbutuseless/dplyr-cli&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;example-data&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example data&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;write.csv(mtcars, &amp;quot;mtcars.csv&amp;quot;, row.names = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-1---basic-usage&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example 1 - Basic Usage&lt;/h1&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;# cat contents of input CSV into dplyr-cli.  
# Use &amp;#39;-c&amp;#39; to output CSV if this is the final step
cat mtcars.csv | ./dplyr.sh filter -c mpg == 21&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;mpg&amp;quot;,&amp;quot;cyl&amp;quot;,&amp;quot;disp&amp;quot;,&amp;quot;hp&amp;quot;,&amp;quot;drat&amp;quot;,&amp;quot;wt&amp;quot;,&amp;quot;qsec&amp;quot;,&amp;quot;vs&amp;quot;,&amp;quot;am&amp;quot;,&amp;quot;gear&amp;quot;,&amp;quot;carb&amp;quot;
21,6,160,110,3.9,2.62,16.46,0,1,4,4
21,6,160,110,3.9,2.875,17.02,0,1,4,4&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;# Put quotes around any commands which contain special characters like &amp;lt;&amp;gt;()
cat mtcars.csv | ./dplyr.sh filter -c &amp;quot;mpg &amp;lt; 11&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;mpg&amp;quot;,&amp;quot;cyl&amp;quot;,&amp;quot;disp&amp;quot;,&amp;quot;hp&amp;quot;,&amp;quot;drat&amp;quot;,&amp;quot;wt&amp;quot;,&amp;quot;qsec&amp;quot;,&amp;quot;vs&amp;quot;,&amp;quot;am&amp;quot;,&amp;quot;gear&amp;quot;,&amp;quot;carb&amp;quot;
10.4,8,472,205,2.93,5.25,17.98,0,0,3,4
10.4,8,460,215,3,5.424,17.82,0,0,3,4&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;# Combine dplyr commands with shell &amp;#39;head&amp;#39; command
./dplyr.sh select --file mtcars.csv -c cyl | head -n 6&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;cyl&amp;quot;
6
6
4
6
8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2---simple-piping-of-commands-with-shell-pipe-not-magrittr-pipe&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example 2 - Simple piping of commands (with shell pipe, not magrittr pipe)&lt;/h1&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;cat mtcars.csv | \
   ./dplyr.sh mutate &amp;quot;cyl2 = 2 * cyl&amp;quot;  | \
   ./dplyr.sh filter &amp;quot;cyl == 8&amp;quot; | \
   ./dplyr.sh kable&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;|  mpg| cyl|  disp|  hp| drat|    wt|  qsec| vs| am| gear| carb| cyl2|
|----:|---:|-----:|---:|----:|-----:|-----:|--:|--:|----:|----:|----:|
| 18.7|   8| 360.0| 175| 3.15| 3.440| 17.02|  0|  0|    3|    2|   16|
| 14.3|   8| 360.0| 245| 3.21| 3.570| 15.84|  0|  0|    3|    4|   16|
| 16.4|   8| 275.8| 180| 3.07| 4.070| 17.40|  0|  0|    3|    3|   16|
| 17.3|   8| 275.8| 180| 3.07| 3.730| 17.60|  0|  0|    3|    3|   16|
| 15.2|   8| 275.8| 180| 3.07| 3.780| 18.00|  0|  0|    3|    3|   16|
| 10.4|   8| 472.0| 205| 2.93| 5.250| 17.98|  0|  0|    3|    4|   16|
| 10.4|   8| 460.0| 215| 3.00| 5.424| 17.82|  0|  0|    3|    4|   16|
| 14.7|   8| 440.0| 230| 3.23| 5.345| 17.42|  0|  0|    3|    4|   16|
| 15.5|   8| 318.0| 150| 2.76| 3.520| 16.87|  0|  0|    3|    2|   16|
| 15.2|   8| 304.0| 150| 3.15| 3.435| 17.30|  0|  0|    3|    2|   16|
| 13.3|   8| 350.0| 245| 3.73| 3.840| 15.41|  0|  0|    3|    4|   16|
| 19.2|   8| 400.0| 175| 3.08| 3.845| 17.05|  0|  0|    3|    2|   16|
| 15.8|   8| 351.0| 264| 4.22| 3.170| 14.50|  0|  1|    5|    4|   16|
| 15.0|   8| 301.0| 335| 3.54| 3.570| 14.60|  0|  1|    5|    8|   16|&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-3---set-up-some-aliases-for-convenience&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example 3 - set up some aliases for convenience&lt;/h1&gt;
&lt;pre class=&#34;sh&#34;&gt;&lt;code&gt;alias mutate=&amp;quot;./dplyr.sh mutate&amp;quot;
alias filter=&amp;quot;./dplyr.sh filter&amp;quot;
alias select=&amp;quot;./dplyr.sh select&amp;quot;
alias summarise=&amp;quot;./dplyr.sh summarise&amp;quot;
alias group_by=&amp;quot;./dplyr.sh group_by&amp;quot;
alias ungroup=&amp;quot;./dplyr.sh ungroup&amp;quot;
alias count=&amp;quot;./dplyr.sh count&amp;quot;
alias arrange=&amp;quot;./dplyr.sh arrange&amp;quot;
alias kable=&amp;quot;./dplyr.sh kable&amp;quot;


cat mtcars.csv | group_by cyl | summarise &amp;quot;mpg = mean(mpg)&amp;quot; | kable&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;| cyl|      mpg|
|---:|--------:|
|   4| 26.66364|
|   6| 19.74286|
|   8| 15.10000|&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;security-warning&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Security warning&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;dplyr-cli&lt;/code&gt; uses &lt;code&gt;eval(parse(text = ...))&lt;/code&gt; on user input. Do not expose this
program to the internet or random users under any circumstances.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;inspirations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Inspirations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/BurntSushi/xsv&#34;&gt;xsv&lt;/a&gt; - a fast CSV command line toolkit
written in Rust&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stedolan.github.io/jq/&#34;&gt;jq&lt;/a&gt; - a command line JSON processor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Racing Barplots with {ggpattern}, {flagon} &amp; {gganimate}</title>
      <link>https://coolbutuseless.github.io/2020/04/12/racing-barplots-with-ggpattern-flagon-gganimate/</link>
      <pubDate>Sun, 12 Apr 2020 13:32:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/12/racing-barplots-with-ggpattern-flagon-gganimate/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;racing-barplot&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Racing Barplot&lt;/h1&gt;
&lt;p&gt;A racing barplot is a way to visualize changed rankings and magnitudes over time.&lt;/p&gt;
&lt;p&gt;In this post, I use flag images from the &lt;a href=&#34;https://github.com/coolbutuseless/flagon&#34;&gt;flagon package&lt;/a&gt; to decorate
the a barplot (using &lt;a href=&#34;https://github.com/coolbutuseless/ggpattern&#34;&gt;ggpattern&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I adapted a great presentation/flipbook by &lt;a href=&#34;https://twitter.com/EvaMaeRey&#34;&gt;Gina Reynolds&lt;/a&gt; which can be found &lt;a href=&#34;https://evamaerey.github.io/little_flipbooks_library/racing_bars/racing_barcharts.html#35&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;use-the-gapminder-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use the &lt;code&gt;gapminder&lt;/code&gt; data&lt;/h2&gt;
&lt;p&gt;Keep only the top 10 most populous countries for all available years.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(ggplot2)
library(gganimate)
library(gapminder)
library(ggpattern)


ranked_by_year &amp;lt;- gapminder %&amp;gt;%  
  select(country, pop, year, continent) %&amp;gt;%  
  group_by(year) %&amp;gt;%  
  arrange(year, -pop) %&amp;gt;%  
  mutate(rank = 1:n()) %&amp;gt;%  
  filter(rank &amp;lt;= 10) %&amp;gt;%
  mutate(pop = pop / 1e6)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;assign-a-flag-for-each-country&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Assign a flag for each country&lt;/h2&gt;
&lt;p&gt;Lookup a flag image for each country in the &lt;a href=&#34;https://github.com/coolbutuseless/flagon&#34;&gt;flagon package&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ccodes &amp;lt;- flagon::country_codes %&amp;gt;% select(country, ccode)

ranked_by_year &amp;lt;- ranked_by_year %&amp;gt;%
  left_join(ccodes, by = &amp;#39;country&amp;#39;) %&amp;gt;%
  mutate(
    flag = flagon::flags(ccode)
  )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: Column `country` joining factor and character vector, coercing into
character vector&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ranked_by_year %&amp;gt;%
  head(5) %&amp;gt;%
  knitr::kable(caption = &amp;quot;Attach a flag image to each country&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-3&#34;&gt;Table 1: &lt;/span&gt;Attach a flag image to each country&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;pop&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;year&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;continent&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;rank&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;ccode&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;flag&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;China&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;556.26353&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1952&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Asia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/cn.png&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;India&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;372.00000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1952&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Asia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;in&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/in.png&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;157.55300&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1952&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Americas&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;us&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/us.png&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Japan&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;86.45902&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1952&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Asia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;jp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/jp.png&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Indonesia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82.05200&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1952&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Asia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;id&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/id.png&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;animate-the-bar-plot-of-population-over-time&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animate the bar plot of population over time&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot_df &amp;lt;- ranked_by_year #%&amp;gt;% filter(year %in% c(1957, 1987, 2007))

dev.off()
dev.off()

p &amp;lt;- ggplot(plot_df, aes(group = country)) + 
  geom_rect_pattern(
    aes(
      xmin = 0, 
      xmax = pop, 
      ymin = rank - 0.45, 
      ymax = rank + 0.45,
      pattern_filename = I(flag)
    ), 
    pattern = &amp;#39;image&amp;#39;,
    fill    = &amp;#39;grey70&amp;#39;,
    pattern_gravity = &amp;#39;East&amp;#39;,  # Push flag to the right
    pattern_type    = &amp;#39;none&amp;#39;,  # no auto-rescale
    pattern_scale   = -2       # Scale to height.
  ) +   
  geom_text(aes(y = rank, label = country), x = -50, col = &amp;quot;gray13&amp;quot;,  hjust = &amp;quot;right&amp;quot;, size = 10) +
  geom_text(aes(label = as.character(year)), x = 1000 , y = -10, size = 30, col = &amp;quot;grey18&amp;quot;) +
  scale_y_reverse() + 
  scale_fill_brewer(palette = &amp;#39;Set2&amp;#39;) + 
  labs(x = &amp;#39;Population (millions)&amp;#39;, fill = NULL) +  
  theme_bw() + 
  theme(
    axis.text.y     = element_blank(),
    axis.title.y    = element_blank(),
    axis.ticks.y    = element_blank(),
    legend.key.size = unit(2, &amp;#39;cm&amp;#39;),
    axis.text       = element_text(size = 20),
    axis.title      = element_text(size = 20)
  ) +   
  scale_x_continuous(  
    limits = c(-450, 1400),  
    breaks = c(0, 400, 800, 1200)
  ) +
  gganimate::transition_time(year)&lt;/code&gt;&lt;/pre&gt;
&lt;video width=&#34;1000&#34; height=&#34;500&#34; controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/race-bars/race.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;flagon&#39; - A package of just flag images in PNG and SVG format</title>
      <link>https://coolbutuseless.github.io/2020/04/03/introducing-flagon-a-package-of-just-flag-images-in-png-and-svg-format/</link>
      <pubDate>Fri, 03 Apr 2020 22:11:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/03/introducing-flagon-a-package-of-just-flag-images-in-png-and-svg-format/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;flagon&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;flagon&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;flagon&lt;/code&gt; provides PNG and SVG images of the flags of the world, indexed by
their &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes&#34;&gt;2-letter ISO-3166 country codes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The flags are sourced from &lt;a href=&#34;https://github.com/hjnilsson/country-flags&#34;&gt;https://github.com/hjnilsson/country-flags&lt;/a&gt;, and are the public domain flag images from wikipedia.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/flagon&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/flagon&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;usage-retrieving-filenames&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Usage: Retrieving filenames&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(flagon)

country_codes &amp;lt;- c(&amp;#39;au&amp;#39;, &amp;#39;dk&amp;#39;) # Australia and Germany

flagon::flags(country_codes)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/au.png&amp;quot;
[2] &amp;quot;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/png/dk.png&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;flagon::flags(country_codes, &amp;#39;svg&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/svg/au.svg&amp;quot;
[2] &amp;quot;/Library/Frameworks/R.framework/Versions/3.6/Resources/library/flagon/svg/dk.svg&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-with-magick&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using with &lt;code&gt;magick&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;magick::image_read(flagon::flags(&amp;#39;no&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-04-03-announcing-flagon_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;thats-it&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;That’s it&lt;/h2&gt;
&lt;p&gt;That’s all it does.&lt;/p&gt;
&lt;p&gt;There’s also a table of country codes (&lt;code&gt;flagon::country_codes&lt;/code&gt;),
the first rows of which are shown below:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;ccode&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ad&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Andorra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ae&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United Arab Emirates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;af&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Afghanistan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ag&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Antigua and Barbuda&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ai&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Anguilla&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;al&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Albania&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing &#39;optout&#39; - A package for optimizing graphics output</title>
      <link>https://coolbutuseless.github.io/2020/04/03/introducing-optout-a-package-for-optimizing-graphics-output/</link>
      <pubDate>Fri, 03 Apr 2020 21:33:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/03/introducing-optout-a-package-for-optimizing-graphics-output/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;optout---optimized-graphics-output&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;optout - Optimized Graphics Output&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;This package enables access to some common command-line image optimization and
compression tools from within R, with a mostly consistent call interface.&lt;/p&gt;
&lt;p&gt;Tools are included for interfacing command line tools for compressing
JPG, PNG and PDF files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My use case&lt;/strong&gt; - the vignettes for &lt;a href=&#34;https:/github.com/coolbutuseless/ggpattern&#34;&gt;ggpattern&lt;/a&gt;
are huge because of the image example, and I wanted to be able to optimize and
compress images from within the vignette &lt;em&gt;Rmd&lt;/em&gt; files.&lt;/p&gt;
&lt;div id=&#34;security-warning&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Security Warning&lt;/h2&gt;
&lt;p&gt;This package does a lot of &lt;code&gt;system2()&lt;/code&gt; calls with user input. I’ve
sanitised all user input, but nothing is ever perfect, so in general
this library should not accept input from the internet e.g. as part of a shiny
app.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/optout&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/optout&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This package relies on your system having installed the following command line
programs. If a particular utility is not installed, the package will still
load fine, but you will not be able to use that particular compression type.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PNG compression
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pngquant.org/&#34;&gt;pngquant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://optipng.sourceforge.net/&#34;&gt;optpng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pmt.sourceforge.io/pngcrush/&#34;&gt;pngcrush&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/google/zopfli&#34;&gt;zopfli + zopflipng&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;JPEG compression
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tjko/jpegoptim&#34;&gt;jpegoptim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;PDF compression
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ghostscript.com/&#34;&gt;ghostscript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;overview-of-available-compressors&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview of available compressors&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;14%&#34; /&gt;
&lt;col width=&#34;16%&#34; /&gt;
&lt;col width=&#34;14%&#34; /&gt;
&lt;col width=&#34;54%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;filetype&lt;/th&gt;
&lt;th&gt;compressor&lt;/th&gt;
&lt;th&gt;lossless&lt;/th&gt;
&lt;th&gt;default options&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;png&lt;/td&gt;
&lt;td&gt;pngquant&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;speed = 4, dither = FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;png&lt;/td&gt;
&lt;td&gt;pngcrush&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;brute = FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;png&lt;/td&gt;
&lt;td&gt;optipng&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;level = 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;png&lt;/td&gt;
&lt;td&gt;zopflipng&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;lossy_alpha = FALSE, lossy_8bit = FALSE, more = FALSE, insane = FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;jpeg&lt;/td&gt;
&lt;td&gt;jpegoptim&lt;/td&gt;
&lt;td&gt;optional&lt;/td&gt;
&lt;td&gt;quality = NULL, size = NULL (i.e. lossless)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;pdf&lt;/td&gt;
&lt;td&gt;pdfopt&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;quality = ‘screen’&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;sample-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sample Plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) + 
  geom_density(aes(mpg, fill = as.factor(cyl))) + 
  theme_gray(15)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-04-03-announcing-optout_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dpi &amp;lt;- 72
ggsave(&amp;quot;/img/optout/png-orig.png&amp;quot;, p, width = 6, height = 4)
ggsave(&amp;quot;/img/optout/jpg-orig.jpg&amp;quot;, p, width = 6, height = 4)
ggsave(&amp;quot;/img/optout/pdf-orig.pdf&amp;quot;, p, width = 6, height = 4)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-optimizing-png-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Optimizing PNG output&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r1 &amp;lt;- pngquant (infile = &amp;quot;/img/optout/png-orig.png&amp;quot;, outfile = &amp;quot;/img/optout/png-pngquant.png&amp;quot; , verbosity = 1)
r2 &amp;lt;- pngcrush (infile = &amp;quot;/img/optout/png-orig.png&amp;quot;, outfile = &amp;quot;/img/optout/png-pngcrush.png&amp;quot; , verbosity = 1)
r3 &amp;lt;- optipng  (infile = &amp;quot;/img/optout/png-orig.png&amp;quot;, outfile = &amp;quot;/img/optout/png-optipng.png&amp;quot;  , verbosity = 1)
r4 &amp;lt;- zopflipng(infile = &amp;quot;/img/optout/png-orig.png&amp;quot;, outfile = &amp;quot;/img/optout/png-zopflipng.png&amp;quot;, verbosity = 1)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
Orig PNG
&lt;/h4&gt;
&lt;p&gt;&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/png-orig.png&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear:both;&#34;&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
pngquant - space saving 66%
&lt;/h4&gt;
&lt;p&gt;&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/png-pngquant.png&#34;  /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
pngcrush - space saving 31%
&lt;/h4&gt;
&lt;p&gt;&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/png-pngcrush.png&#34;  /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
optipng - space saving 33%
&lt;/h4&gt;
&lt;p&gt;&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/png-optipng.png&#34;   /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
zopflipng - space saving 43%
&lt;/h4&gt;
&lt;p&gt;&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/png-zopflipng.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear:both;&#34; /&gt;




&lt;/div&gt;
&lt;div id=&#34;example-optimizing-jpeg-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Optimizing JPEG output&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r5 &amp;lt;- jpegoptim(
  infile    = &amp;quot;/img/optout/jpg-orig.jpg&amp;quot;, 
  outfile   = &amp;quot;/img/optout/jpg-jpegoptim-lossless.jpg&amp;quot; , 
  verbosity = 1
)


r6 &amp;lt;- jpegoptim(
  infile    = &amp;quot;/img/optout/jpg-orig.jpg&amp;quot;, 
  outfile   = &amp;quot;/img/optout/jpg-jpegoptim-lossy-size.jpg&amp;quot;,
  size      = 50,  
  verbosity = 1
)


r7 &amp;lt;- jpegoptim(
  infile    = &amp;quot;/img/optout/jpg-orig.jpg&amp;quot;, 
  outfile   = &amp;quot;/img/optout/jpg-jpegoptim-lossy-quality.jpg&amp;quot;, 
  quality   = 10,
  verbosity = 1
)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
Orig JPG
&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;.&lt;/span&gt;
&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/jpg-orig.jpg&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
jpegoptim - lossless
&lt;/h4&gt;
&lt;p&gt;Space saving 18%
&lt;img width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/jpg-jpegoptim-lossless.jpg&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
jpegoptim - target size 50kB
&lt;/h4&gt;
&lt;p&gt;Space saving 66%
&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/jpg-jpegoptim-lossy-size.jpg&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
jpegoptim - target quality 10
&lt;/h4&gt;
&lt;p&gt;Space saving 77%
&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/jpg-jpegoptim-lossy-quality.jpg&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear:both;&#34; /&gt;



&lt;/div&gt;
&lt;div id=&#34;example-optimizing-pdf-output&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Optimizing PDF output&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r8 &amp;lt;- pdfopt(infile = &amp;quot;/img/optout/pdf-orig.pdf&amp;quot;, outfile = &amp;quot;/img/optout/pdf-pdfopt.pdf&amp;quot;, verbosity = 1)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
Orig PDF
&lt;/h4&gt;
&lt;p&gt;&lt;span&gt;.&lt;/span&gt;
&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/pdf-orig.png&#34;      /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%; float:left;&#34;&gt;
&lt;h4&gt;
pdfopt
&lt;/h4&gt;
&lt;p&gt;Space saving 33%
&lt;img  width=&#34;100%&#34; src=&#34;https://coolbutuseless.github.io/img/optout/pdf-pdfopt.png&#34;  /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear:both;&#34; /&gt;



&lt;/div&gt;
&lt;div id=&#34;speed&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Speed&lt;/h2&gt;
&lt;p&gt;Most optimizers run in reasonable time i.e. ~1 second for a single file.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;zopflipng&lt;/code&gt; is the exception and with higher compression options you will see
the heat death of the universe before you will see it finish. Even at its lowest
settings (the default) it will take tens-of-seconds up to several minutes to
compress a file. &lt;strong&gt;Use with caution!&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing ggpattern - pattern fills for ggplot</title>
      <link>https://coolbutuseless.github.io/2020/04/01/introducing-ggpattern-pattern-fills-for-ggplot/</link>
      <pubDate>Wed, 01 Apr 2020 06:55:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/04/01/introducing-ggpattern-pattern-fills-for-ggplot/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggpattern&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggpattern &lt;img src=&#34;https://coolbutuseless.github.io/img/ggpattern/logo.png&#34; align=&#34;right&#34; width=&#34;300&#34; /&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&#34;font-size: xx-large; font-weight: normal;&#34;&gt;&lt;code&gt;ggpattern&lt;/code&gt; provides custom &lt;code&gt;ggplot2&lt;/code&gt; geoms which support filled areas with
geometric and image-based patterns.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reading the articles/vignettes on &lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/&#34;&gt;the package website&lt;/a&gt; is
probably the best way to get started.&lt;/p&gt;
&lt;div id=&#34;feature-summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Feature Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Custom versions of (almost) all the &lt;strong&gt;geoms&lt;/strong&gt; from ggplot2 which have a region which can be filled.&lt;/li&gt;
&lt;li&gt;A suite of &lt;strong&gt;aesthetics&lt;/strong&gt; for controlling the pattern appearance (e.g. &lt;code&gt;pattern_alpha&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The ability to include &lt;strong&gt;user-defined patterns&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/ggpattern&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/ggpattern&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;quickstart&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quickstart&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Take an existing plot which contains a geom with a fillable area e.g &lt;code&gt;geom_col()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;{ggpattern}&lt;/code&gt; version of the geom e.g. &lt;code&gt;ggpattern::geom_col_pattern()&lt;/code&gt; instead of &lt;code&gt;ggplot2::geom_col()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the aesthetic &lt;code&gt;pattern&lt;/code&gt; to your choice of pattern e.g &lt;code&gt;pattern = &#39;stripe&#39;&lt;/code&gt;,
and set other options using &lt;code&gt;pattern_*&lt;/code&gt; aesthetics&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- data.frame(level = c(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;#39;d&amp;#39;), outcome = c(2.3, 1.9, 3.2, 1))

ggplot(df) +
  geom_col_pattern(
    aes(level, outcome, pattern_fill = level), 
    pattern = &amp;#39;stripe&amp;#39;,
    fill    = &amp;#39;white&amp;#39;,
    colour  = &amp;#39;black&amp;#39;
  ) +
  theme_bw(18) +
  theme(legend.position = &amp;#39;none&amp;#39;) + 
  labs(
    title    = &amp;quot;ggpattern::geom_pattern_col()&amp;quot;,
    subtitle = &amp;quot;pattern = &amp;#39;stripe&amp;#39;&amp;quot;
  ) +
  coord_fixed(ratio = 1/2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-04-01-announcing-ggpattern_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;gallery&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Gallery&lt;/h1&gt;
&lt;div&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html#geom-bar-pattern-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-bar-array.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-geometry.html#b-w-example&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-bar-bw.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-geometry.html#colour-example-1&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-bar-colour.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html#geom-bar-pattern-coord-flip-and-fit-image-to-height-and-graivty-towards-the-east-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-bar2-array.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html#geom-density-pattern-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-density-array.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-geometry.html#geom-density-pattern-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-density-grid.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html#geom-map-pattern-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-map-array.jpg&#34; /&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html#geom-rect-pattern-&#34;&gt;&lt;img width=&#34;45%&#34; src=&#34;https://coolbutuseless.github.io/img/ggpattern/readme/gallery-rect-array.jpg&#34; /&gt; &lt;/a&gt;
&lt;div&gt;



&lt;/div&gt;
&lt;div id=&#34;feature-details&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Feature Details&lt;/h1&gt;
&lt;div id=&#34;available-geoms&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Available Geoms&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ggpattern&lt;/code&gt; includes versions of (nearly) all geoms from &lt;code&gt;ggplot2&lt;/code&gt; which could plausiblly
support being filled with a pattern.&lt;/p&gt;
&lt;p&gt;See the vignette galleries for examples of all the available geoms filled with
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-geometry.html&#34;&gt;geometry-based patterns&lt;/a&gt; and
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html&#34;&gt;image-based/array-based patterns&lt;/a&gt;.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; &lt;span style=&#34;color: blue;&#34;&gt; Click to show/hide list of supported geoms &lt;/span&gt; &lt;/summary&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;ggplot2&lt;/th&gt;
&lt;th&gt;ggpattern&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_area&lt;/td&gt;
&lt;td&gt;geom_area_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_bar&lt;/td&gt;
&lt;td&gt;geom_bar_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_bin2d&lt;/td&gt;
&lt;td&gt;geom_bin2d_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_boxplot&lt;/td&gt;
&lt;td&gt;geom_boxplot_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_col&lt;/td&gt;
&lt;td&gt;geom_col_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_crossbar&lt;/td&gt;
&lt;td&gt;geom_crossbar_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_density&lt;/td&gt;
&lt;td&gt;geom_density_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_map&lt;/td&gt;
&lt;td&gt;geom_map_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_polygon&lt;/td&gt;
&lt;td&gt;geom_polygon_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_rect&lt;/td&gt;
&lt;td&gt;geom_rect_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_ribbon&lt;/td&gt;
&lt;td&gt;geom_ribbon_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_sf&lt;/td&gt;
&lt;td&gt;geom_sf_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;geom_tile&lt;/td&gt;
&lt;td&gt;geom_tile_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;geom_violin&lt;/td&gt;
&lt;td&gt;geom_violin_pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;new-aesthetics&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;New aesthetics&lt;/h2&gt;
&lt;p&gt;To control pattern appearance, a raft of new aesthetics have been added. e.g. 
&lt;code&gt;pattern_alpha&lt;/code&gt;, &lt;code&gt;pattern_filename&lt;/code&gt;, &lt;code&gt;pattern_density&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are also scale functions to control each of these new aesthetics e.g. 
&lt;code&gt;scale_pattern_alpha_discrete&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Not all aesthetics apply to all patterns. See the individual pattern vignettes
for which aesthetics it uses, or see the first vignette on developing user-defined
patterns for a &lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-1.html#aes-by-pattern&#34;&gt;table of aesthetic use by pattern&lt;/a&gt;,
or see the individual vignettes for each pattern.&lt;/p&gt;
&lt;details&gt;
&lt;p&gt;&lt;summary&gt; &lt;span style=&#34;color: blue;&#34;&gt; Click to show/hide list of new aesthetics &lt;/span&gt; &lt;/summary&gt;&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;21%&#34; /&gt;
&lt;col width=&#34;38%&#34; /&gt;
&lt;col width=&#34;9%&#34; /&gt;
&lt;col width=&#34;29%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;aesthetic&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;th&gt;default&lt;/th&gt;
&lt;th&gt;possible values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of the pattern to draw&lt;/td&gt;
&lt;td&gt;‘stripe’&lt;/td&gt;
&lt;td&gt;stripe, crosshatch, circle, image, placeholder, magick, gradient, plasma&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic control option&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;pattern-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_subtype&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic control option&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;pattern-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_alpha&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alpha&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;value in range [0, 1] (npc units)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_linetype&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stroke linetype&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;linetype&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stroke linewidth&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;linewidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_shape&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Plotting shape&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;shapes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_colour&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stroke colour&lt;/td&gt;
&lt;td&gt;‘grey20’&lt;/td&gt;
&lt;td&gt;colour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_fill&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fill colour&lt;/td&gt;
&lt;td&gt;‘grey80’&lt;/td&gt;
&lt;td&gt;colour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_fill2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Second fill colour&lt;/td&gt;
&lt;td&gt;‘#4169E1’&lt;/td&gt;
&lt;td&gt;colour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_angle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rotation angle&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;angle in degrees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_density&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Approx. fraction of area the pattern fills&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;value in range [0, 1] (fraction)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_spacing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spacing between repetitions of pattern&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;value in range [0, 1] (npc units)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_xoffset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shift pattern along x axis&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;value in range [0, 1] (npc units)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_yoffset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shift pattern along y axis&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;value in range [0, 1] (npc units)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_aspect_ratio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aspect ratio adjustment&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td&gt;usual range [0.01, 10]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_key_scale_factor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Scale factor for pattern in legend&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_filename&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image filename/URL&lt;/td&gt;
&lt;td&gt;’’&lt;/td&gt;
&lt;td&gt;Filename/URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_gravity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image placement&lt;/td&gt;
&lt;td&gt;‘center’&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ggpattern::magick_gravity_names&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_filter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image scaling filter&lt;/td&gt;
&lt;td&gt;‘lanczos’&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ggpattern::magick_filter_names&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_scale&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Scale&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Multiplier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_orientation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Orientation&lt;/td&gt;
&lt;td&gt;‘vertical’&lt;/td&gt;
&lt;td&gt;‘vertical’, ‘horizontal’, ‘radial’&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_phase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Phase&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_frequency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Frequency&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;code&gt;pattern_option_1 - 5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic options for expansion&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/summary&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;user-defined-patterns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;User-Defined Patterns&lt;/h2&gt;
&lt;p&gt;Users can write their own pattern functions and ask &lt;code&gt;ggpattern&lt;/code&gt; to use them,
without having to include the pattern in the package.&lt;/p&gt;
&lt;p&gt;See the vignettes on developing patterns (
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-1.html&#34;&gt;1&lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-2.html&#34;&gt;2&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-3.html&#34;&gt;3&lt;/a&gt;
) for how to do this, and see the vignettes on experimental patterns to see
this in action (
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-points.html&#34;&gt;Point filling&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-hex.html&#34;&gt;Hex pattern&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-ambient.html&#34;&gt;Ambient Noise&lt;/a&gt;
).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Vignettes&lt;/h1&gt;
&lt;div id=&#34;general-examples&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;General examples&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-geometry.html&#34;&gt;geom gallery (geometry-based patterns)&lt;/a&gt; Examples of every geom filled with the geometry-based patterns (i.e. ‘stripe’, ‘crosshatch’, ‘circle’)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geom-gallery-array.html&#34;&gt;geom gallery (array-based patterns)&lt;/a&gt; Examples of every geom filled with the array-based patterns (i.e. ‘image’, ‘magick’, ‘gradient’, ‘plasma’, ‘placeholder’)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;exploration-of-pattern-parameters-and-appearance&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Exploration of pattern parameters and appearance&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Geometry-based patterns
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/geometry-based-pattern-parameters.html&#34;&gt;Common aesthetics for geometry-based patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-stripe.html&#34;&gt;stripes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-crosshatch.html&#34;&gt;crosshatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-circle.html&#34;&gt;circles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Array-based patterns
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-image.html&#34;&gt;image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-placeholder.html&#34;&gt;placeholder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-gradient.html&#34;&gt;gradient&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-plasma.html&#34;&gt;plasma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/pattern-magick.html&#34;&gt;magick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;developing-your-own-pattern&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Developing your own pattern&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-1.html&#34;&gt;Devloping Patterns 1 - Pattern Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-2.html&#34;&gt;Devloping Patterns 2 - Geometry-based pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/developing-patterns-3.html&#34;&gt;Devloping Patterns 3 - Array-based pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;experimental-patterns&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Experimental patterns&lt;/h4&gt;
&lt;p&gt;These are patterns that aren’t quite ready for prime-time. Feel free to steal the code and extend to suit your needs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-points.html&#34;&gt;Point filling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-hex.html&#34;&gt;Hex pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/experimental-pattern-ambient.html&#34;&gt;Ambient Noise&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;other-examples&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Other examples&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/ggpattern/articles/gganimate.html&#34;&gt;gganimate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Limitations&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Nearly always need to use &lt;code&gt;coord_fixed()&lt;/code&gt; to ensure the aspect ratio is
calculated correctly. Use &lt;code&gt;pattern_aspect_ratio&lt;/code&gt; to override the internal
calculation, of for occasions where you can’t use &lt;code&gt;coord_fixed()&lt;/code&gt; because
a different &lt;code&gt;coord_*()&lt;/code&gt; is used.&lt;/li&gt;
&lt;li&gt;Legend rendering for patterns is still not great.
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;pattern_key_scale_factor&lt;/code&gt; to adjust legend appearance.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The Rstudio output device can be quite slow for plots with lots of patterns. It is
often faster to save directly to PNG or PDF and view that.&lt;/li&gt;
&lt;li&gt;Self intersecting geometry can be an issue.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Non-linear coordinate systems have not been tested.&lt;/li&gt;
&lt;li&gt;Polygons with holes are not supported&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ToDo&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Possibly add geoms from third-party sources e.g.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;geom_circle()&lt;/code&gt; and &lt;code&gt;geom_voronoi()&lt;/code&gt; from &lt;a href=&#34;https://github.com/thomasp85/ggforce&#34;&gt;ggforce&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A technical vignette on how array-based patterns are implemented.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Line Segment/Box Intersection Test</title>
      <link>https://coolbutuseless.github.io/2020/03/01/line-segment/box-intersection-test/</link>
      <pubDate>Sun, 01 Mar 2020 06:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/03/01/line-segment/box-intersection-test/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;line-segmentbox-intersection-test&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Line Segment/Box Intersection Test&lt;/h2&gt;
&lt;p&gt;While working with &lt;code&gt;{grid}&lt;/code&gt; graphics I needed a way to cull some generated
geometry if it didn’t lie within a given rectangular bounding box.&lt;/p&gt;
&lt;p&gt;The following code is based upon a &lt;a href=&#34;https://stackoverflow.com/questions/99353/how-to-test-if-a-line-segment-intersects-an-axis-aligned-rectange-in-2d&#34;&gt;stackoverflow response&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This code will test 100 thousand line segments against a box in about 20ms, which
is fast enough for my purposes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Determine if line segments intersect a rectangle
#&amp;#39;
#&amp;#39; @param x1,y1,x2,y2 coordinates of line segment endpoints
#&amp;#39; @param xmin,ymin,xmax,ymax coordinates of lower-left and upper-right of
#&amp;#39;        rectangle.
#&amp;#39;
#&amp;#39; @return logical vector the same length as x1
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
line_intersects_box &amp;lt;- function(x1, y1, x2, y2, xmin, ymin, xmax, ymax) {

  # Returns 0/1 depending on which side of the line segment the corner lies
  left_of &amp;lt;- function(xcorner, ycorner) {
    ((y2 - y1) * xcorner + (x1 - x2) * ycorner + (x2 * y1 - x1 * y2)) &amp;gt;= 0
  }

  # test segments against each of the 4 corners of the box
  res &amp;lt;- list(
    left_of(xmin, ymin),
    left_of(xmin, ymax),
    left_of(xmax, ymax),
    left_of(xmax, ymin)
  )

  # if the test for each corner
  # are all of the same sign, then the segment definitely misses the box
  a_miss &amp;lt;- Reduce(`+`, res) %in% c(0, 4)

  # Does it miss based upon the shadow intersection test?
  b_miss &amp;lt;-
    (x1 &amp;gt; xmax &amp;amp; x2 &amp;gt; xmax) | (x1 &amp;lt; xmin &amp;amp; x2 &amp;lt; xmin) |
    (y1 &amp;gt; ymax &amp;amp; y2 &amp;gt; ymax) | (y1 &amp;lt; ymin &amp;amp; y2 &amp;lt; ymin)

  # a hit is if it doesn&amp;#39;t miss!
  !(a_miss | b_miss)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 300000

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate lots of random lines
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x1 &amp;lt;- runif(N)
y1 &amp;lt;- runif(N)
x2 &amp;lt;- runif(N)
y2 &amp;lt;- runif(N)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Test if the segments intersect a box
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xmin &amp;lt;- 0.4
ymin &amp;lt;- 0.4
xmax &amp;lt;- 0.9
ymax &amp;lt;- 0.9

int1 &amp;lt;- line_intersects_box(x1, y1, x2, y2, xmin, ymin, xmax, ymax)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Test if the segments intersect a second box
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xmin &amp;lt;- 0.1
ymin &amp;lt;- 0.1
xmax &amp;lt;- 0.9
ymax &amp;lt;- 0.2

int2 &amp;lt;- line_intersects_box(x1, y1, x2, y2, xmin, ymin, xmax, ymax)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot all segments that don&amp;#39;t intersect the boxes
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
df &amp;lt;- data.frame(
  x1, y1, x2, y2, int1, int2
) %&amp;gt;% filter(!int1, !int2)


ggplot(df) +
  geom_segment(aes(x=x1,y=y1,xend=x2,yend=y2), alpha=0.005) +
  annotate(&amp;#39;rect&amp;#39;, xmin=xmin, ymin=ymin, xmax=xmax,ymax=ymax, fill=NA, colour=NA) +
  theme_void() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-03-01-segment-box-intersection_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>My mental model of how alpha works is wrong</title>
      <link>https://coolbutuseless.github.io/2020/02/14/my-mental-model-of-how-alpha-works-is-wrong/</link>
      <pubDate>Fri, 14 Feb 2020 06:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/02/14/my-mental-model-of-how-alpha-works-is-wrong/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;my-mental-model-of-alpha-when-plotting&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My mental model of alpha when plotting&lt;/h2&gt;
&lt;p&gt;When plotting overlapping elements with a defined alpha (opacity), I had always
thought about it as an additive process with results clamped to not exceed 1.&lt;/p&gt;
&lt;p&gt;Thus, without every bothering to check, my mental model was: three overlapping
black rectangles,
each with an opacity of 0.4, would result in a black rectangle since their combined
opacity is 1.2, and this is clamped the maximum possible value of 1.&lt;/p&gt;
&lt;p&gt;My mental model is wrong.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-actually-happens-with-overlapping-alpha&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What actually happens with overlapping alpha&lt;/h2&gt;
&lt;p&gt;In each sub-plot, I’ve plotted the overlap of a number of rectangles, each with &lt;code&gt;opacity&lt;/code&gt; of 0.4.&lt;/p&gt;
&lt;p&gt;The combined opacity increases with each overlap but doesn’t quite reach an opacity of 1.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Simple function to create a plot with N overlapping rectangles with 
# each having an alpha of 0.4
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stack_alpha &amp;lt;- function(N) {
  plot_df &amp;lt;- tibble(
    x       = seq(0.45, 0.55, length.out = N),
    y       = seq(0.45, 0.55, length.out = N), 
    opacity = 0.4
  )
  
  ggplot(plot_df) + 
    geom_tile(aes(x, y, alpha = I(opacity)), fill = &amp;#39;black&amp;#39;, 
              width=0.5, height = 0.5, colour = NA) + 
    theme_void() + 
    coord_equal()
}

plots &amp;lt;- lapply(1:4, stack_alpha)

patchwork::wrap_plots(plots, ncol = 4)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-02-13-stacking-alpha_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;correcting-my-thinking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Correcting my thinking&lt;/h2&gt;
&lt;p&gt;Rather than talking about &lt;code&gt;opacity&lt;/code&gt;, I should think in terms of &lt;code&gt;transmissivity&lt;/code&gt;
(i.e. &lt;code&gt;1-opacity&lt;/code&gt;) - and transmissivity is a &lt;em&gt;multiplicative&lt;/em&gt; property.&lt;/p&gt;
&lt;p&gt;So, for a sequence of N layers with a transmissivity &lt;code&gt;t&lt;/code&gt;, the transmissivity of the
result is &lt;code&gt;t^N&lt;/code&gt;, and thus the &lt;code&gt;opacity&lt;/code&gt; is &lt;code&gt;(1 - t^N)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The following plots show the original 4 plots from above, and below them plots of my
estimation of the combined alpha using multiplicative transmissivity&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;opacity&lt;/th&gt;
&lt;th&gt;transmissivity&lt;/th&gt;
&lt;th&gt;cumulative transmissivity&lt;/th&gt;
&lt;th&gt;cumulative alpha&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;1 - 0.6 = 0.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;0.6 * 0.6 = 0.36&lt;/td&gt;
&lt;td&gt;1 - 0.36 = 0.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;0.6 * 0.6 * 0.6 = 0.216&lt;/td&gt;
&lt;td&gt;1 - 0.216 = 0.784&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;0.6 ^ 4 = 0.1296&lt;/td&gt;
&lt;td&gt;1 - 0.1296 = 0.8704&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manually calculate the total transmissivity for 1-4 overlapping rectangles.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
manually_stack_alpha &amp;lt;- function(N) {
  plot_df &amp;lt;- tibble(
    N = N,
    x = 0.5,
    y = 0.5, 
    tranmissivity = (1 - 0.4)^N,
    opacity       = 1 - tranmissivity
  )
  
  ggplot(plot_df) + 
    geom_tile(aes(x, y, alpha = I(opacity)), fill = &amp;#39;black&amp;#39;, 
              width=0.5, height = 0.5, colour = NA) + 
    theme_void() + 
    coord_equal() + 
    facet_wrap(~N + opacity, labeller = label_both)
}


manual_plots &amp;lt;- lapply(1:4, manually_stack_alpha)

patchwork::wrap_plots(c(plots, manual_plots), ncol = 4)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-02-13-stacking-alpha_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Opacity isn’t additive.&lt;/li&gt;
&lt;li&gt;Transmissivity = 1 - Opacity.&lt;/li&gt;
&lt;li&gt;Transmissivity is multiplicative&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the {ggblur} package</title>
      <link>https://coolbutuseless.github.io/2020/02/11/introducing-the-ggblur-package/</link>
      <pubDate>Tue, 11 Feb 2020 19:40:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2020/02/11/introducing-the-ggblur-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/header-attrs/header-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggblur&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggblur &lt;img src=&#34;https://coolbutuseless.github.io/img/ggblur/logo-blurred.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggblur&lt;/code&gt; provides &lt;code&gt;geom_point_blur()&lt;/code&gt; for use in &lt;code&gt;ggplot&lt;/code&gt; - this geom allows you
to control the blurriness of the drawn points, but is otherwise
identical to the standard &lt;code&gt;geom_point()&lt;/code&gt;.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;What’s in the box?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;geom_point_blur()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;same as &lt;code&gt;geom_point()&lt;/code&gt; but now accepts &lt;code&gt;blur_size&lt;/code&gt; as an aesthetic&lt;/li&gt;
&lt;li&gt;also allows for control of the smoothness of the blur (&lt;code&gt;blur_steps&lt;/code&gt;) and
the maximum opacity (&lt;code&gt;blur_alpha&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scale_blur_size_continuous()&lt;/code&gt;, &lt;code&gt;scale_blur_size_discrete()&lt;/code&gt; and &lt;code&gt;scale_blur_size_manual()&lt;/code&gt;
for controlling &lt;code&gt;blur_size&lt;/code&gt; when used as a mapped aesthetic/&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;similar-packages&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Similar packages&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/ggecho&#34;&gt;ggecho&lt;/a&gt; is an earlier experiment of
mine from 2019 where I echo components using a custom stat &lt;code&gt;stat_echo&lt;/code&gt;. This
solution works across multiple geoms, but didn’t allow for adjusting the
echo for individual points.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/thomasp85/ggfx&#34;&gt;ggfx&lt;/a&gt; adds blur at the layer level i.e. 
no individual control over the amount of blur for each point.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;how-it-works&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;How it works&lt;/h4&gt;
&lt;p&gt;Blur is simulated by keeping the original point, and drawing a sequence of
larger, faded points behind it (illustrated below).&lt;/p&gt;
&lt;p&gt;The number of
points rendered is controlled by &lt;code&gt;blur_steps&lt;/code&gt; and the distance to which the
blur extends beyond the edge of the original point is controlled by &lt;code&gt;blur_size&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note: Paul Murrell has some experiments to add radial gradients to grid graphics
(see &lt;a href=&#34;https://github.com/pmur002/r-defs-proposal&#34;&gt;his github&lt;/a&gt;) and if this
becomes part of grid it may be a better method of simulating blur.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggblur/how.png&#34; width=&#34;50%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/ggblur&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/ggblur&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-1---constant-blur_size&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 1 - constant &lt;code&gt;blur_size&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When not used as a mapped aesthetic within &lt;code&gt;aes()&lt;/code&gt;, the same &lt;code&gt;blur_size&lt;/code&gt; is
applied to every point.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggblur)

ggplot(mtcars) +
  geom_point_blur(aes(mpg, wt), blur_size = 10) +
  theme_bw() + 
  labs(title = &amp;quot;Same blur for each point&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-02-11-ggblur_files/figure-html/example1-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2---mapping-blur_size-as-an-aesthetic&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 2 - mapping &lt;code&gt;blur_size&lt;/code&gt; as an aesthetic&lt;/h2&gt;
&lt;p&gt;When used as a mapped aesthetic within &lt;code&gt;aes()&lt;/code&gt;, the &lt;code&gt;blur_size&lt;/code&gt; is calculated
individually for each point.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(ggblur)

ggplot(mtcars) +
  geom_point_blur(aes(mpg, wt, blur_size = disp)) +
  theme_bw() + 
  labs(title = &amp;quot;Larger blur indicates larger engine displacement&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-02-11-ggblur_files/figure-html/example2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-3---control-over-blur-parameters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 3 - control over blur parameters&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;blur_alpha&lt;/code&gt;, &lt;code&gt;blur_steps&lt;/code&gt; and &lt;code&gt;scale_blue_size_continuous/discrete/manual()&lt;/code&gt;
can be used to further customise the appearance.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  geom_point_blur(aes(mpg, wt, blur_size = disp), blur_alpha = 0.3, blur_steps = 2) +
  scale_blur_size_continuous(range = c(1, 15)) +
  theme_bw() + 
  labs(title = &amp;quot;Larger blur indicates larger engine displacement&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2020-02-11-ggblur_files/figure-html/example3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Drawing with epicycles in R</title>
      <link>https://coolbutuseless.github.io/2019/12/31/drawing-with-epicycles-in-r/</link>
      <pubDate>Tue, 31 Dec 2019 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/12/31/drawing-with-epicycles-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;drawing-with-epicycles&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Drawing with epicycles&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create a set of points to define the path&lt;/li&gt;
&lt;li&gt;Take the discrete fourier transform of the points (as represented in the complex plane)&lt;/li&gt;
&lt;li&gt;The magnitude and phase of the fourier transform components are the radius
and phase offset of the circles to draw&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(gganimate)
library(ggforce) # geom_circle
library(dplyr)
library(hershey) # vector font: https://github.com/coolbutuseless/hershey&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;extract-a-set-of-points-for-the-letter-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extract a set of points for the letter R&lt;/h2&gt;
&lt;p&gt;This uses the &lt;a href=&#34;https://github.com/coolbutuseless/hershey&#34;&gt;Hershey vector fonts&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Choose a character from a Hershey vector font and extract x and y coords
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char &amp;lt;- hershey::hershey %&amp;gt;%
  filter(font == &amp;#39;futural&amp;#39;, char == &amp;#39;R&amp;#39;)

x &amp;lt;- char$x
y &amp;lt;- char$y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-12-31-epicycles_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;fft-of-the-xy-coordinates&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;FFT of the (x,y) coordinates&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Calculate a fourier transform of the points in the complex plane
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
f &amp;lt;- fft(complex(real = x, imaginary = y))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# From the FFT, calculate
# -  R     - radius
# -  phi   - phase shift
# -  omega - angular velocity
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N     &amp;lt;- length(x)
R     &amp;lt;- Mod(f) / N
phi   &amp;lt;- Arg(f)
omega &amp;lt;- 2 * pi * seq(0, N-1) / N&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;construct-the-epicycles-at-each-timestep&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Construct the epicycles at each timestep&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Debug/Sanity check:
# Recreate the original points by manually doing the inverse fourier transform.
# Generate points with timestamp so we can highlight in gganimate
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xs &amp;lt;- c()
ys &amp;lt;- c()

for (t in seq(0, N)) {
  xo &amp;lt;- R * cos(omega * t + phi)
  yo &amp;lt;- R * sin(omega * t + phi)
  
  xs &amp;lt;- c(xs, sum(xo))
  ys &amp;lt;- c(ys, sum(yo))
}

rpoints &amp;lt;- data.frame(x = xs, y = ys, t = as.numeric(seq(0, N)))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a data.frame of the cumulative sum of the components at
# each timepoint.  This will give us the position of each of the circle
# centres at each time point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reconstruction &amp;lt;- list()

F &amp;lt;- 40  # how many steps between each input point

for (t in seq(0, N * F)) {
  t  &amp;lt;- t/F
  xo &amp;lt;- R * cos(omega * t + phi)
  yo &amp;lt;- R * sin(omega * t + phi)
  
  xc &amp;lt;- cumsum(xo)
  yc &amp;lt;- cumsum(yo)
  
  reconstruction[[length(reconstruction) + 1]] &amp;lt;- data.frame(x = xc, y = yc, t = t, R = R)
}

reconstruction &amp;lt;- do.call(rbind, reconstruction)

centres &amp;lt;- reconstruction %&amp;gt;%
  group_by(t) %&amp;gt;%
  mutate(R = lead(R)) %&amp;gt;%
  ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-epicycles-at-a-single-instant&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Plot epicycles at a single instant&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cdf &amp;lt;- reconstruction %&amp;gt;% filter(t == 0)
centres &amp;lt;- centres %&amp;gt;% filter(t == 0)
p &amp;lt;- ggplot() +
  geom_path(data = cdf, aes(x, y), alpha = 0.3) +
  geom_circle(data = centres, aes(x0 = x, y0 = y, r = R), na.rm = TRUE, colour = &amp;#39;#00000030&amp;#39;) +
  geom_path(data = char, aes(x, y, group = stroke), size = 0.5, colour = &amp;#39;black&amp;#39;) +
  geom_point(data = char, aes(x, y), size = 1, colour = &amp;#39;black&amp;#39;) +
  geom_point(data = rpoints, aes(x, y), size = 3, colour = &amp;#39;red&amp;#39;) +
  theme_void() +
  coord_equal()

p&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-12-31-epicycles_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animate-the-epicycles&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animate the epicycles&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot() +
  geom_path(data = reconstruction, aes(x, y), alpha = 0.3) +
  geom_circle(data = centres, aes(x0 = x, y0 = y, r = R), na.rm = TRUE, colour = &amp;#39;#00000030&amp;#39;) +
  geom_path(data = char, aes(x, y, group = stroke), size = 0.5, colour = &amp;#39;black&amp;#39;) +
  geom_point(data = char, aes(x, y), size = 1, colour = &amp;#39;black&amp;#39;) +
  geom_point(data = rpoints, aes(x, y), size = 3, colour = &amp;#39;red&amp;#39;) +
  theme_void() +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# animate
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ga &amp;lt;- p + transition_manual(t)
a &amp;lt;- gganimate::animate(ga, nframes = N*F+1, fps = 20)
gganimate::anim_save(&amp;quot;r.gif&amp;quot;, a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/epicycles/ready.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>dplyr::ungroup() - forget me not. Part 4.</title>
      <link>https://coolbutuseless.github.io/2019/12/06/dplyrungroup-forget-me-not.-part-4./</link>
      <pubDate>Fri, 06 Dec 2019 20:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/12/06/dplyrungroup-forget-me-not.-part-4./</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;forget-me-not---dplyrungroup&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Forget me not - dplyr::ungroup()&lt;/h1&gt;
&lt;p&gt;If you forget to &lt;code&gt;ungroup()&lt;/code&gt; an operation after a &lt;code&gt;group_by()&lt;/code&gt; it can lead to
unwanted behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; What if we didn’t have to remember to ungroup after every chain?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-just-be-annoying-non-solution---part-2&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;My “just be annoying” non-solution - Part 2&lt;/h1&gt;
&lt;p&gt;Since I almost never want to leave grouped data in my workspace, just make a
noisy version of the pipe operator (&lt;code&gt;%&amp;gt;%&lt;/code&gt;) which&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;warns if you try and operate on a dataset which is already grouped.&lt;/li&gt;
&lt;li&gt;warns if you the end result of an operation still has groups.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(magrittr)
library(dplyr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Define a new version of the pipe that always checks for grouped data.
# This is a slightly modified clone of `magrittr::%&amp;gt;%`
#-----------------------------------------------------------------------------
&amp;#39;%&amp;gt;%&amp;#39; &amp;lt;- function (lhs, rhs) {
  parent &amp;lt;- parent.frame()
  env &amp;lt;- new.env(parent = parent)
  chain_parts &amp;lt;- magrittr:::split_chain(match.call(), env = env)
  pipes &amp;lt;- chain_parts[[&amp;quot;pipes&amp;quot;]]
  rhss &amp;lt;- chain_parts[[&amp;quot;rhss&amp;quot;]]
  lhs &amp;lt;- chain_parts[[&amp;quot;lhs&amp;quot;]]
  env[[&amp;quot;_function_list&amp;quot;]] &amp;lt;- lapply(
    1:length(rhss),
    function(i) magrittr:::wrap_function(rhss[[i]], pipes[[i]], parent)
  )
  env[[&amp;quot;_fseq&amp;quot;]] &amp;lt;- `class&amp;lt;-`(eval(quote(
    function(value) freduce(value, `_function_list`)),
    env, env), c(&amp;quot;fseq&amp;quot;, &amp;quot;function&amp;quot;)
  )
  env[[&amp;quot;freduce&amp;quot;]] &amp;lt;- freduce
  if (magrittr:::is_placeholder(lhs)) {
    env[[&amp;quot;_fseq&amp;quot;]]
  } else {
    env[[&amp;quot;_lhs&amp;quot;]] &amp;lt;- eval(lhs, parent, parent)
    if (!is.null(groups(env[[&amp;quot;_lhs&amp;quot;]])) || inherits(env[[&amp;#39;_lhs&amp;#39;]], &amp;#39;rowwise_df&amp;#39;)) {
      warning(&amp;quot;This data.frame already has groups - did you forget to call `ungroup()` earlier?&amp;quot;, call. = FALSE)
    }
    result &amp;lt;- withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
    if (magrittr:::is_compound_pipe(pipes[[1L]])) {
      eval(call(&amp;quot;&amp;lt;-&amp;quot;, lhs, result[[&amp;quot;value&amp;quot;]]), parent, parent)
    }  else {
      if (!is.null(groups(result[[&amp;quot;value&amp;quot;]])) || inherits(result[[&amp;quot;value&amp;quot;]], &amp;#39;rowwise_df&amp;#39;)) {
        warning(&amp;quot;The end result of this operation still has groups - did you mean to call `ungroup()` as well?&amp;quot;, call. = FALSE)
      }
      if (result[[&amp;quot;visible&amp;quot;]])
        result[[&amp;quot;value&amp;quot;]]
      else
        invisible(result[[&amp;quot;value&amp;quot;]])
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Use this new pipe instead of the original magrittr pipe and you get 
# a warning if end result is ungrouped
#-----------------------------------------------------------------------------
res1 &amp;lt;- mtcars %&amp;gt;%
  group_by(cyl) &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: The end result of this operation still has groups - did you mean to
call `ungroup()` as well?&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Get a warning when the initial data.frame is already grouped
#-----------------------------------------------------------------------------
res2 &amp;lt;- res1 %&amp;gt;%
  mutate(mean_mpg = mean(mpg)) %&amp;gt;%
  select(cyl, mean_mpg) %&amp;gt;%
  ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: This data.frame already has groups - did you forget to call `ungroup()`
earlier?&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# But don&amp;#39;t get any warning if it isn&amp;#39;t grouped input or output
#-----------------------------------------------------------------------------
res3 &amp;lt;- mtcars %&amp;gt;%
  mutate(mean_mpg = mean(mpg)) %&amp;gt;%
  select(cyl, mean_mpg) %&amp;gt;%
  ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>dplyr::ungroup() - forget me not. Part 3.</title>
      <link>https://coolbutuseless.github.io/2019/11/22/dplyrungroup-forget-me-not.-part-3./</link>
      <pubDate>Fri, 22 Nov 2019 22:05:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/11/22/dplyrungroup-forget-me-not.-part-3./</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;forget-me-not---dplyrungroup&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Forget me not - dplyr::ungroup()&lt;/h1&gt;
&lt;p&gt;If you forget to &lt;code&gt;ungroup()&lt;/code&gt; an operation after a &lt;code&gt;group_by()&lt;/code&gt; it can lead to
unwanted behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; What if we didn’t have to remember to ungroup after every chain?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-just-be-annoying-non-solution.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;My “just be annoying” non-solution.&lt;/h1&gt;
&lt;p&gt;Since I almost never want to leave grouped data in my workspace, just make a
noisy version of the pipe operator (&lt;code&gt;%&amp;gt;%&lt;/code&gt;) which puts out a big red warning
if you try and operate on a dataset which is already grouped.&lt;/p&gt;
&lt;p&gt;Note: this is a ill-conceived, poorly implemented, fragile, throwaway,
non-solution to a complex problem.&lt;/p&gt;
&lt;p&gt;But it was fun to do, and that’s what counts! :)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(magrittr)
library(dplyr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Define a new version of the pipe that always checks for grouped data.
# This is super-fragile, so please do it better!
#-----------------------------------------------------------------------------
&amp;#39;%&amp;gt;%&amp;#39; &amp;lt;- function (lhs, rhs) {
  parent &amp;lt;- parent.frame()
  env &amp;lt;- new.env(parent = parent)
  chain_parts &amp;lt;- magrittr:::split_chain(match.call(), env = env)
  pipes &amp;lt;- chain_parts[[&amp;quot;pipes&amp;quot;]]
  rhss &amp;lt;- chain_parts[[&amp;quot;rhss&amp;quot;]]
  lhs &amp;lt;- chain_parts[[&amp;quot;lhs&amp;quot;]]
  env[[&amp;quot;_function_list&amp;quot;]] &amp;lt;- lapply(
    1:length(rhss),
    function(i) magrittr:::wrap_function(rhss[[i]], pipes[[i]], parent)
  )
  env[[&amp;quot;_fseq&amp;quot;]] &amp;lt;- `class&amp;lt;-`(eval(quote(
    function(value) freduce(value, `_function_list`)),
    env, env), c(&amp;quot;fseq&amp;quot;, &amp;quot;function&amp;quot;)
  )
  env[[&amp;quot;freduce&amp;quot;]] &amp;lt;- freduce
  if (magrittr:::is_placeholder(lhs)) {
    env[[&amp;quot;_fseq&amp;quot;]]
  } else {
    env[[&amp;quot;_lhs&amp;quot;]] &amp;lt;- eval(lhs, parent, parent)
    if (!is.null(groups(env[[&amp;quot;_lhs&amp;quot;]])) || inherits(env[[&amp;#39;_lhs&amp;#39;]], &amp;#39;rowwise_df&amp;#39;)) {
      warning(&amp;quot;This data.frame already has groups!&amp;quot;, call. = FALSE)
    }
    result &amp;lt;- withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
    if (magrittr:::is_compound_pipe(pipes[[1L]])) {
      eval(call(&amp;quot;&amp;lt;-&amp;quot;, lhs, result[[&amp;quot;value&amp;quot;]]), parent, parent)
    }  else {
      if (result[[&amp;quot;visible&amp;quot;]])
        result[[&amp;quot;value&amp;quot;]]
      else
        invisible(result[[&amp;quot;value&amp;quot;]])
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Use this new pipe instead of the original magrittr pipe
#-----------------------------------------------------------------------------
res &amp;lt;- mtcars %&amp;gt;%
  group_by(cyl) 



#-----------------------------------------------------------------------------
# Get a warning when the data.frame is already grouped
#-----------------------------------------------------------------------------
res2 &amp;lt;- res %&amp;gt;%
  mutate(mean_mpg = mean(mpg)) %&amp;gt;%
  select(cyl, mean_mpg)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: This data.frame already has groups!&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# But don&amp;#39;t get any warning if it isn&amp;#39;t grouped input
#-----------------------------------------------------------------------------
res3 &amp;lt;- mtcars %&amp;gt;%
  mutate(mean_mpg = mean(mpg)) %&amp;gt;%
  select(cyl, mean_mpg)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>dplyr::ungroup() - forget me not. Part 2.</title>
      <link>https://coolbutuseless.github.io/2019/11/20/dplyrungroup-forget-me-not.-part-2./</link>
      <pubDate>Wed, 20 Nov 2019 19:25:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/11/20/dplyrungroup-forget-me-not.-part-2./</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;forget-me-not---dplyrungroup&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Forget me not - dplyr::ungroup()&lt;/h1&gt;
&lt;p&gt;If you forget to &lt;code&gt;ungroup()&lt;/code&gt; an operation after a &lt;code&gt;group_by()&lt;/code&gt; it can lead to
unwanted behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; What if we didn’t have to remember to ungroup after every chain?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-lets-break-backwards-compatibility-with-the-universe-non-solution.&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;My “Let’s break backwards compatibility with the universe” non-solution.&lt;/h1&gt;
&lt;p&gt;Instead of having to use an explicit &lt;code&gt;ungroup()&lt;/code&gt;, use this brand new &lt;code&gt;%&amp;gt;%&lt;/code&gt; (pipe operator)
which will automatically apply an &lt;code&gt;ungroup()&lt;/code&gt; at the end of every chain.&lt;/p&gt;
&lt;p&gt;Note: this is a ill-conceived, poorly implemented, fragile, throwaway,
non-solution to a complex problem.&lt;/p&gt;
&lt;p&gt;But it was fun to do, and that’s what counts! :)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(magrittr)
library(dplyr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Define a new version of the pipe that always ungroups.
# This is super-fragile, so please do it better!
#-----------------------------------------------------------------------------
&amp;#39;%&amp;gt;%&amp;#39; &amp;lt;- function (lhs, rhs) {
  parent &amp;lt;- parent.frame()
  env &amp;lt;- new.env(parent = parent)
  chain_parts &amp;lt;- magrittr:::split_chain(match.call(), env = env)
  pipes &amp;lt;- chain_parts[[&amp;quot;pipes&amp;quot;]]
  rhss &amp;lt;- chain_parts[[&amp;quot;rhss&amp;quot;]]
  lhs &amp;lt;- chain_parts[[&amp;quot;lhs&amp;quot;]]
  env[[&amp;quot;_function_list&amp;quot;]] &amp;lt;- lapply(
    1:length(rhss),
    function(i) magrittr:::wrap_function(rhss[[i]], pipes[[i]], parent)
  )
  env[[&amp;quot;_fseq&amp;quot;]] &amp;lt;- `class&amp;lt;-`(eval(quote(
    function(value) freduce(value, `_function_list`)),
    env, env), c(&amp;quot;fseq&amp;quot;, &amp;quot;function&amp;quot;)
  )
  env[[&amp;quot;freduce&amp;quot;]] &amp;lt;- freduce
  if (magrittr:::is_placeholder(lhs)) {
    env[[&amp;quot;_fseq&amp;quot;]]
  } else {
    env[[&amp;quot;_lhs&amp;quot;]] &amp;lt;- eval(lhs, parent, parent)
    result &amp;lt;- withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
    if (magrittr:::is_compound_pipe(pipes[[1L]])) {
      eval(call(&amp;quot;&amp;lt;-&amp;quot;, lhs, result[[&amp;quot;value&amp;quot;]]), parent, parent)
    }  else {
      if (result[[&amp;quot;visible&amp;quot;]])
        ungroup(result[[&amp;quot;value&amp;quot;]])  # Explicit &amp;#39;ungroup()&amp;#39; before returning
      else
        invisible(ungroup(result[[&amp;quot;value&amp;quot;]])) # Explicit ungroup()
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Use this new pipe instead of the original magrittr pipe
# Note:  ungroup() is not called explicitly by the user
#-----------------------------------------------------------------------------
res &amp;lt;- mtcars %&amp;gt;%
  group_by(cyl) %&amp;gt;%
  mutate(mean_mpg = mean(mpg)) %&amp;gt;%
  select(cyl, mean_mpg)

head(res)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 2
    cyl mean_mpg
  &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
1     6     19.7
2     6     19.7
3     4     26.7
4     6     19.7
5     8     15.1
6     6     19.7&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Result is not grouped!
#-----------------------------------------------------------------------------
groups(res)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;NULL&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>dplyr::ungroup() - forget me not</title>
      <link>https://coolbutuseless.github.io/2019/11/19/dplyrungroup-forget-me-not/</link>
      <pubDate>Tue, 19 Nov 2019 20:25:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/11/19/dplyrungroup-forget-me-not/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;forget-me-not---dplyrungroup&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Forget me not - dplyr::ungroup()&lt;/h1&gt;
&lt;p&gt;If you forget to &lt;code&gt;ungroup()&lt;/code&gt; an operation after a &lt;code&gt;group_by()&lt;/code&gt; it can lead to
unwanted behaviour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; What if we didn’t have to remember to ungroup after every chain?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-post-lunch-sugar-coma-non-solution&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;My post-lunch, sugar-coma non-solution&lt;/h1&gt;
&lt;p&gt;Instead of using &lt;code&gt;group_by()&lt;/code&gt;, use &lt;code&gt;with_group_by()&lt;/code&gt; which will automatically
apply an &lt;code&gt;ungroup()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This isn’t really a solution as the syntax is pretty darn horrible,
but was a fun post-lunch idea to implement.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Perform a grouped operation and automatically ungroup the data
#&amp;#39;
#&amp;#39; @param .data data.frame
#&amp;#39; @param ... arguments.  The last-but-one arguments are treated as
#&amp;#39;        grouping variables. The last argument is treated as a function
#&amp;#39;        chain
#-----------------------------------------------------------------------------
with_group_by &amp;lt;- function(.data, ...) {
  dots   &amp;lt;- rlang::dots_definitions(...)$dots
  f      &amp;lt;- dots[[length(dots)]]
  groups &amp;lt;- dots[-length(dots) ]

  .data &amp;lt;- group_by(.data, !!!groups)
  .data &amp;lt;- rlang::eval_tidy(f)(.data)
  ungroup(.data)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# The first argument is the data frame
# subsequent arguments are the grouping variables
# The final argument to `with_group_by()` treated as a function chain.
#
# Note:  ungroup() is not called explicitly by the user
#-----------------------------------------------------------------------------
res &amp;lt;- mtcars %&amp;gt;%
  with_group_by(
    cyl,
    . %&amp;gt;%
      mutate(mean_mpg = mean(mpg)) %&amp;gt;%
      select(cyl, mean_mpg)
  )&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(res)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 2
    cyl mean_mpg
  &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;
1     6     19.7
2     6     19.7
3     4     26.7
4     6     19.7
5     8     15.1
6     6     19.7&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Data is not grouped!
#-----------------------------------------------------------------------------
groups(res)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;NULL&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {devoutsvg} - SVG graphics output device with pattern fills</title>
      <link>https://coolbutuseless.github.io/2019/10/10/introducing-devoutsvg-svg-graphics-output-device-with-pattern-fills/</link>
      <pubDate>Thu, 10 Oct 2019 21:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/10/introducing-devoutsvg-svg-graphics-output-device-with-pattern-fills/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;devoutsvg&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutsvg &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutsvg/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutsvg&lt;/code&gt; provides a bespoke SVG graphics device written in plain R.&lt;/p&gt;
&lt;p&gt;The key feature of this SVG graphics device is that it allowd for the use of
patterns for filled regions in plots!&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devoutsvg&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/lofi&amp;quot;)      # Colour encoding
devtools::install_github(&amp;quot;coolbutuseless/minisvg&amp;quot;)   # SVG creation
devtools::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)    # Device interface
devtools::install_github(&amp;quot;coolbutuseless/devoutsvg&amp;quot;) # This package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-usage-of-the-svgout-device&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic usage of the &lt;code&gt;svgout&lt;/code&gt; device&lt;/h2&gt;
&lt;p&gt;Use this device in the same way you would use &lt;code&gt;pdf()&lt;/code&gt;, &lt;code&gt;png()&lt;/code&gt; any of the other
graphics output devices in R.&lt;/p&gt;
&lt;p&gt;This results is thankfully uninteresting! That is, if the &lt;code&gt;svgout&lt;/code&gt; device works
properly then the output should like the standard ggplot output you’ve seen
hundreds of times before.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutsvg::svgout(filename = &amp;quot;img/devoutsvg/example-basic.svg&amp;quot;)
ggplot(mtcars) + 
  geom_point(aes(mpg, wt, colour = as.factor(cyl))) + 
  labs(title = basename(&amp;quot;Example - Basic&amp;quot;)) 
invisible(dev.off())
Warning in file(con, &amp;quot;w&amp;quot;): cannot open file &amp;#39;img/devoutsvg/example-basic.svg&amp;#39;:
No such file or directory
Warning in dev.off(): rdevice_close: svg_callback() Evaluation error: cannot
open the connection.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutsvg/example-basic.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;filling-with-patterns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filling with patterns&lt;/h2&gt;
&lt;p&gt;Because we now have control over the graphics device at quite a low level, we
get to misbehave!&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;svgout&lt;/code&gt; device can be instructed to use patterns instead of the actual RGB
colour - this is achieved by&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;instructing the device to use a particular pattern package (&lt;code&gt;pattern_pkg&lt;/code&gt;), and&lt;/li&gt;
&lt;li&gt;encoding particular patterns from that package as their RGB representations using
&lt;code&gt;{pattern_pkg}::encode_pattern_params_as_hex_colour()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When &lt;code&gt;svgout&lt;/code&gt; is asked to render a colour, it instead asks &lt;code&gt;pattern_pkg&lt;/code&gt; to &lt;code&gt;**decode**hex_colour_as_pattern_params&lt;/code&gt;
and returns the desired SVG pattern snippet.&lt;/p&gt;
&lt;p&gt;Some examples of pattern packages are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/svgpatternsimple&#34;&gt;&lt;code&gt;svgpatternsimple&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/coolbutuseless/svgpatternusgs&#34;&gt;&lt;code&gt;svgpatternusgs&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(svgpatternsimple)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Encode the parameters for 3 different patterns into 3 different colours
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gear4_colour &amp;lt;- svgpatternsimple::encode_pattern_params_as_hex_colour(
  pattern_name = &amp;#39;null&amp;#39;, 
  colour       = &amp;#39;#123456&amp;#39;
)

gear6_colour &amp;lt;- svgpatternsimple::encode_pattern_params_as_hex_colour(
  pattern_name = &amp;#39;stipple&amp;#39;, 
  colour       = &amp;#39;#ff4455&amp;#39;, 
  spacing      = 10
)

gear8_colour &amp;lt;- svgpatternsimple::encode_pattern_params_as_hex_colour(
  pattern_name  = &amp;#39;hex&amp;#39;, 
  angle         = 0, 
  spacing       = 20, 
  fill_fraction = 0.1,
  colour        = &amp;#39;#125634&amp;#39;
)

c(gear4_colour, gear6_colour, gear8_colour)


svgout(filename = &amp;quot;img/devoutsvg/example-manual.svg&amp;quot;, pattern_pkg = &amp;#39;svgpatternsimple&amp;#39;)
ggplot(mtcars) + 
  geom_bar(aes(as.factor(cyl), fill = as.factor(cyl)), colour = &amp;#39;black&amp;#39;) + 
  labs(title = basename(&amp;quot;Example - manual pattern specification&amp;quot;)) + 
  theme_bw() +
  theme(legend.key.size = unit(1.5, &amp;quot;cm&amp;quot;)) + 
  scale_fill_manual(
    values = c(
      &amp;#39;4&amp;#39; = gear4_colour,
      &amp;#39;6&amp;#39; = gear6_colour,
      &amp;#39;8&amp;#39; = gear8_colour
    )
  )
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/devoutsvg/example-manual.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-scale_fill_pattern_simple&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;scale_fill_pattern_simple()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Rather than specifying individual patterns to map to colours, you can use a &lt;code&gt;scale_fill&lt;/code&gt;.
Since RGB colours don’t intuitively map to patterns, if you let ggplot choose the patterns
using the default &lt;code&gt;scale_fill_discrete()&lt;/code&gt; you will get a pretty ugly combination of
patterns in your plot.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;scale_fill_pattern_simple()&lt;/code&gt; allows the user to specify the envelope of desired outputs
and ggplot will map values-to-patterns automatically within this envelope.&lt;/p&gt;
&lt;p&gt;By default this will give an OK spread of pattern styles, but it probably won’t be great.&lt;br /&gt;
See the next section for how to specify the desired envelope of possible patterns.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;svgout(pattern_pkg = &amp;#39;svgpatternsimple&amp;#39;, filename = &amp;quot;img/devoutsvg/example-scale-fill-2.svg&amp;quot;)
ggplot(mtcars) + 
  geom_bar(aes(as.factor(cyl), fill = as.factor(cyl)), colour = &amp;#39;black&amp;#39;) + 
  labs(title = &amp;quot;scale_fill_pattern_simple() - defaults&amp;quot;) + 
  theme_bw() +
  theme(legend.key.size = unit(1.5, &amp;quot;cm&amp;quot;)) +
  svgpatternsimple::scale_fill_pattern_simple()
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/devoutsvg/example-scale-fill-2.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-scale_fill_pattern_simple-with-a-defined-pattern-set.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;scale_fill_pattern_simple()&lt;/code&gt; with a defined pattern set.&lt;/h2&gt;
&lt;p&gt;By default &lt;code&gt;scale_fill_pattern_simple()&lt;/code&gt; will give an OK spread of pattern styles, but it probably won’t be great.&lt;/p&gt;
&lt;p&gt;The call to &lt;code&gt;scale_fill_pattern_simple()&lt;/code&gt; can be customised to limit the possible
choices of pattern which will appear in the plot. The default options are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pattern_name = c(&#39;stripe&#39;, &#39;dot&#39;, &#39;hatch&#39;, &#39;check&#39;, &#39;stipple&#39;, &#39;hex&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;angle = c(22., 45, 67.5)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spacing = seq(5, 50, length.out = 7)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fill_fraction = seq(0.1, 0.9, length.out = 3)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this following example, the choice of possible patterns is limited to ‘stripe’ and ‘hatch’,
all at 45 degrees, with a range of &lt;code&gt;fill_fraction&lt;/code&gt; and &lt;code&gt;spacing&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;svgout(pattern_pkg = &amp;#39;svgpatternsimple&amp;#39;, filename = &amp;quot;img/devoutsvg/example-patternsimple-scale-fill.svg&amp;quot;,
       width = 8, height = 6)
ggplot(mtcars) + 
  geom_density(aes(mpg, fill = interaction(cyl, am)), alpha = 1) +
  theme_bw() +
  theme(legend.key.size = unit(1.2, &amp;quot;cm&amp;quot;)) +
  labs(title = &amp;quot;scale_fill_pattern_simple() - custom&amp;quot;) +
  svgpatternsimple::scale_fill_pattern_simple(
    pattern_name  = c(&amp;#39;stripe&amp;#39;, &amp;#39;hatch&amp;#39;),
    fill_fraction = seq(0.1, 0.4, length.out = 5), 
    angle         = c(45), 
    spacing       = c(10, 20)) 
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutsvg/example-patternsimple-scale-fill.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern-fills-with-base-plots&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pattern fills with base plots&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
colours &amp;lt;- c(
  svgpatternsimple::encode_pattern_params_as_hex_colour(
    pattern_name = &amp;#39;null&amp;#39;, 
    colour       = &amp;#39;#123456&amp;#39;
  ),
  
  svgpatternsimple::encode_pattern_params_as_hex_colour(
    pattern_name = &amp;#39;stipple&amp;#39;, 
    colour       = &amp;#39;#ff4455&amp;#39;, 
    spacing      = 10
  ),
  
  svgpatternsimple::encode_pattern_params_as_hex_colour(
    pattern_name = &amp;#39;hex&amp;#39;, 
    colour       = &amp;#39;#ddff55&amp;#39;, 
    spacing      = 8
  ),
  
  svgpatternsimple::encode_pattern_params_as_hex_colour(
    pattern_name = &amp;#39;check&amp;#39;, 
    colour       = &amp;#39;#ee55ff&amp;#39;, 
    spacing      = 10
  )
)


devoutsvg::svgout(pattern_pkg = &amp;#39;svgpatternsimple&amp;#39;, filename = &amp;quot;img/devoutsvg/example-pie.svg&amp;quot;)
pie(c(cool = 4, but = 2, use = 1, less = 8), col = colours)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutsvg/example-pie.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;u.s.-geological-survey-patterns-on-geom_sf-plots&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;U.S. Geological Survey patterns on &lt;code&gt;geom_sf()&lt;/code&gt; plots&lt;/h2&gt;
&lt;p&gt;The following plot uses the SVG pattern library made available in &lt;a href=&#34;https://github.com/coolbutuseless/svgpatternusgs&#34;&gt;&lt;code&gt;svgpatternusgs&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The 6 areas are manually assigned a colour which corresponds to a set of pattern params.
The parameters are encoded to a colour by the &lt;code&gt;encode_pattern_params_as_hex_colour()&lt;/code&gt; function
in the &lt;code&gt;svgpatternusgs&lt;/code&gt; package.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(sf)
library(svgpatternusgs)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Select some data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nc &amp;lt;- sf::st_read(system.file(&amp;quot;shape/nc.shp&amp;quot;, package = &amp;quot;sf&amp;quot;), quiet = TRUE)
nc$mid &amp;lt;- sf::st_centroid(nc$geometry)
nc &amp;lt;- nc[nc$NAME %in% c(&amp;#39;Surry&amp;#39;, &amp;#39;Stokes&amp;#39;, &amp;#39;Rockingham&amp;#39;, &amp;#39;Yadkin&amp;#39;, &amp;#39;Forsyth&amp;#39;, &amp;#39;Guilford&amp;#39;), ]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Encode specific USGS pattern numbers into colours
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
colours &amp;lt;- c(
  Surry      = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 601, spacing = 100, fill=&amp;#39;#77ff99&amp;#39;),
  Stokes     = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 606, spacing = 100),
  Rockingham = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 629, spacing = 100),
  Yadkin     = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 632, spacing = 100),
  Forsyth    = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 706, spacing = 100),
  Guilford   = svgpatternusgs::encode_pattern_params_as_hex_colour(usgs_code = 717, spacing = 100)
)

devoutsvg::svgout(filename = &amp;quot;img/devoutsvg/example-usgs.svg&amp;quot;, pattern_pkg = &amp;#39;svgpatternusgs&amp;#39;)
ggplot(nc) +
  geom_sf(aes(fill = NAME)) +
  scale_fill_manual(values = colours) + 
  theme(legend.key.size = unit(0.6, &amp;quot;cm&amp;quot;)) + 
  labs(title = &amp;quot;U.S. Geological Survey Patterns with `geom_sf()`&amp;quot;) +
  theme_bw()
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutsvg/example-usgs.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;svg-to-pdf&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;SVG to PDF&lt;/h2&gt;
&lt;p&gt;If you need a PDF version of an SVG file, there are a number of options.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;a href=&#34;https://inkscape.org/&#34;&gt;Inkscape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rsvg&lt;/code&gt; on the command line
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rsvg-convert -f pdf -o t.pdf t.svg&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CairoSVG&lt;/code&gt; on the command line (python based)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cairosvg in.svg -o out.pdf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Imagemagick&lt;/code&gt; (not 100% sure)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;convert file.svg file.pdf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Chrome&lt;/code&gt; headless (maybe?)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chrome --headless --disable-gpu --print-to-pdf=&#34;output.pdf&#34; &#34;input.svg&#34;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Web-based. There are lots of these e.g.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cloudconvert.com/svg-to-pdf&#34;&gt;https://cloudconvert.com/svg-to-pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {svgpatternusgs} - a collection U.S. Geological Survey repeating SVG patterns</title>
      <link>https://coolbutuseless.github.io/2019/10/10/introducing-svgpatternusgs-a-collection-u.s.-geological-survey-repeating-svg-patterns/</link>
      <pubDate>Thu, 10 Oct 2019 06:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/10/introducing-svgpatternusgs-a-collection-u.s.-geological-survey-repeating-svg-patterns/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;svgpatternusgs&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;svgpatternusgs &lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternusgs/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;svgpatternusgs&lt;/code&gt; provides SVG patterns from the &lt;a href=&#34;usgs.gov&#34;&gt;United States Geological Survey (USGS)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The USGS provides a large array of reference styles for geologic linework and map symbology.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://ngmdb.usgs.gov/fgdc_gds/geolsymstd/download.php&#34;&gt;USGS website for Geological Map Symbols&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The raw data for this package was sourced from &lt;a href=&#34;https://github.com/davenquinn/geologic-patterns&#34;&gt;davenquinn’s github version&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;an-example-of-the-patterns-provided&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;An example of the patterns provided&lt;/h2&gt;
&lt;p&gt;This is a screenshot of the original documentation which comes with these patterns
from the USGS&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternusgs/USGS-sample.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;This list of all codes which have a pattern in this package:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;svgpatternusgs::all_usgs_codes
  [1] 101 102 103 104 105 106 114 116 117 118 119 120 121 122 123 124 132 134
 [19] 135 136 137 201 202 204 206 207 214 215 216 217 218 219 226 228 229 230
 [37] 231 232 233 301 302 303 304 305 306 313 314 315 316 317 318 319 327 328
 [55] 330 331 401 402 403 405 406 411 412 416 417 418 419 420 423 424 427 428
 [73] 429 430 431 432 433 434 435 436 521 522 523 524 591 592 593 594 595 601
 [91] 602 603 605 606 607 608 609 610 611 612 613 614 616 617 618 619 620 621
[109] 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
[127] 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
[145] 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
[163] 676 677 678 679 680 681 682 683 684 685 686 701 702 703 704 705 706 707
[181] 708 709 710 711 712 713 714 715 716 717 719 720 721 722 723 724 725 726
[199] 727 728 729 730 731 732 733&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Functions for accessing the SVG for all the provided USGS codes&lt;/li&gt;
&lt;li&gt;SVG pattern are supplied as &lt;code&gt;minisvg::SVGPattern&lt;/code&gt; objects.&lt;/li&gt;
&lt;li&gt;Functions for encoding/decoding a pattern specification from a hex colour.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;to-do&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;To Do&lt;/h2&gt;
&lt;p&gt;The original SVG sources for this were OK but not perfect. I’ve patched some issues, but there
are still quite a few occasions where gaps and tears appear in patterns.&lt;/p&gt;
&lt;p&gt;These errors don’t appear to be systematic, so I think it will require some labour-intensive manual
corrections to individual patterns.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/svgpatternusgs&#34;&gt;github&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/lofi&amp;quot;)           # Colour encoding
devtools::install_github(&amp;quot;coolbutuseless/minisvg&amp;quot;)        # SVG support
devtools::install_github(&amp;quot;coolbutuseless/svgpatternusgs&amp;quot;) # This package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-and-show-a-pattern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create and show a pattern&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pattern &amp;lt;- create_usgs_pattern(usgs_code = 605, spacing = 50)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pattern$show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternusgs/usgs-605.svg&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;multiple-patterns&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Multiple patterns&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pattern_list &amp;lt;- svgpatternusgs::all_usgs_codes[41:72] %&amp;gt;%
  purrr::map(create_usgs_pattern, spacing = 200) 

patterns &amp;lt;- minisvg::SVGPatternList_to_svg(pattern_list, width=200, height=100, ncol = 4)

patterns$save(&amp;quot;/img/svgpatternusgs/usgs-sample.svg&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternusgs/usgs-sample.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;encodingdecoding-patterns-from-colours&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding/decoding patterns from colours&lt;/h2&gt;
&lt;p&gt;A key feature of this set of patterns is that they can be encoded in
an RGB colour. Also, every RGB colour (excluding black, white and fully transparent)
can be decoded to a pattern in this library.&lt;/p&gt;
&lt;p&gt;This encoding/decoding is carried out by the &lt;a href=&#34;https://github.com/coolbutuseless/lofi&#34;&gt;&lt;code&gt;lofi&lt;/code&gt;&lt;/a&gt; package.
Because this has to squeeze multiple continuous variables in to 24-bits, along with
the actual colour of the pattern, there
will be some quantization associated with a pattern-encoded-as-RGB e.g. angle may
only be encoded in 45degree increments.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Encode a stripe pattern into a colour. Arguments to set correspond to 
# arguments from the individual pattern creation function 
# e.g. `create_stripe_pattern()`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hex_colour &amp;lt;- encode_pattern_params_as_hex_colour(
  usgs_code = 701,
  spacing   = 200,
  fill      = &amp;#39;#558899&amp;#39;
)

hex_colour
[1] &amp;quot;#ADC520FF&amp;quot;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Decode this hex colour back into a pattern object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pattern &amp;lt;- decode_pattern_from_rgba_vec(lofi::hex_colour_to_rgba_vec(hex_colour))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render the pattern object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc &amp;lt;- pattern$as_full_svg(width = 400, height = 100)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg viewBox=&#34;0 0 400 100&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;usgs-701-ADC520FF&#34; patternUnits=&#34;userSpaceOnUse&#34; patternTransform=&#34;rotate(0 0 0)&#34; x=&#34;0px&#34; y=&#34;0px&#34; width=&#34;204&#34; height=&#34;204&#34; viewBox=&#34;0 -85.875 85.875 85.875&#34;&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect x=&#34;0&#34; y=&#34;-85.875&#34; style=&#34;fill:#4992AA; fill-opacity:1; stroke:none;&#34; width=&#34;85.875&#34; height=&#34;85.875&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;9.375&#34; y1=&#34;-77.909&#34; x2=&#34;11.625&#34; y2=&#34;-75.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;9.5&#34; y1=&#34;-81.659&#34; x2=&#34;12.875&#34; y2=&#34;-81.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;20.375&#34; y1=&#34;-78.471&#34; x2=&#34;23.063&#34; y2=&#34;-76.426&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;16.875&#34; y1=&#34;-79.534&#34; x2=&#34;14.75&#34; y2=&#34;-76.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;18.5&#34; y1=&#34;-82.284&#34; x2=&#34;15.75&#34; y2=&#34;-84.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;23.75&#34; y1=&#34;-85.034&#34; x2=&#34;21.5&#34; y2=&#34;-83.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;25.375&#34; y1=&#34;-81.659&#34; x2=&#34;25.5&#34; y2=&#34;-78.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;28.75&#34; y1=&#34;-84.226&#34; x2=&#34;31.25&#34; y2=&#34;-82.976&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.125&#34; y1=&#34;-82.592&#34; x2=&#34;37.125&#34; y2=&#34;-84.967&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;39.875&#34; y1=&#34;-81.659&#34; x2=&#34;42.625&#34; y2=&#34;-79.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.75&#34; y1=&#34;-78.034&#34; x2=&#34;36.375&#34; y2=&#34;-75.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.5&#34; y1=&#34;-78.034&#34; x2=&#34;29&#34; y2=&#34;-75.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;42.5&#34; y1=&#34;-75.034&#34; x2=&#34;40.375&#34; y2=&#34;-72.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;39&#34; y1=&#34;-68.659&#34; x2=&#34;42.375&#34; y2=&#34;-67.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;34.701&#34; y1=&#34;-70.318&#34; x2=&#34;31.398&#34; y2=&#34;-72.791&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.25&#34; y1=&#34;-67.909&#34; x2=&#34;28.375&#34; y2=&#34;-66.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.25&#34; y1=&#34;-66.784&#34; x2=&#34;34.25&#34; y2=&#34;-63.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;40&#34; y1=&#34;-63.659&#34; x2=&#34;41.75&#34; y2=&#34;-60.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;42&#34; y1=&#34;-56.284&#34; x2=&#34;39.25&#34; y2=&#34;-54.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;37.5&#34; y1=&#34;-59.034&#34; x2=&#34;34&#34; y2=&#34;-59.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;38.875&#34; y1=&#34;-50.034&#34; x2=&#34;42.5&#34; y2=&#34;-49.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;37.4&#34; y1=&#34;-48.043&#34; x2=&#34;38.65&#34; y2=&#34;-45.043&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;6.25&#34; y1=&#34;-81.275&#34; x2=&#34;3.875&#34; y2=&#34;-78.775&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;3.75&#34; y1=&#34;-76.034&#34; x2=&#34;7.75&#34; y2=&#34;-74.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;2.75&#34; y1=&#34;-72.284&#34; x2=&#34;3.875&#34; y2=&#34;-68.659&#34; /&amp;gt;
        &amp;lt;path style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; d=&#34;M4.5-65.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;4.5&#34; y1=&#34;-65.659&#34; x2=&#34;1.5&#34; y2=&#34;-63.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;4.509&#34; y1=&#34;-60&#34; x2=&#34;4.134&#34; y2=&#34;-56.375&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;1.75&#34; y1=&#34;-53.159&#34; x2=&#34;4.625&#34; y2=&#34;-51.159&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;2.125&#34; y1=&#34;-47.409&#34; x2=&#34;0.5&#34; y2=&#34;-44.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;0.375&#34; y1=&#34;-84.784&#34; x2=&#34;3.625&#34; y2=&#34;-84.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;8.5&#34; y1=&#34;-43.784&#34; x2=&#34;7.375&#34; y2=&#34;-47.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;12.083&#34; y1=&#34;-43.367&#34; x2=&#34;15.208&#34; y2=&#34;-45.492&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;8.625&#34; y1=&#34;-51.034&#34; x2=&#34;12&#34; y2=&#34;-51.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;6.75&#34; y1=&#34;-62.159&#34; x2=&#34;10.375&#34; y2=&#34;-62.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;10.875&#34; y1=&#34;-71.534&#34; x2=&#34;6.75&#34; y2=&#34;-71.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;11.375&#34; y1=&#34;-68.409&#34; x2=&#34;9.375&#34; y2=&#34;-65.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;14.375&#34; y1=&#34;-64.784&#34; x2=&#34;16.875&#34; y2=&#34;-62.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;14.375&#34; y1=&#34;-72.409&#34; x2=&#34;15.5&#34; y2=&#34;-68.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;26.099&#34; y1=&#34;-50.909&#34; x2=&#34;29.863&#34; y2=&#34;-49.833&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;18.456&#34; y1=&#34;-74.121&#34; x2=&#34;21.75&#34; y2=&#34;-72.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;25.625&#34; y1=&#34;-72.784&#34; x2=&#34;27.208&#34; y2=&#34;-69.513&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;21.5&#34; y1=&#34;-68.784&#34; x2=&#34;18.875&#34; y2=&#34;-66.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;22&#34; y1=&#34;-63.784&#34; x2=&#34;25.375&#34; y2=&#34;-64.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;28.125&#34; y1=&#34;-62.909&#34; x2=&#34;31.375&#34; y2=&#34;-60.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;30&#34; y1=&#34;-57.409&#34; x2=&#34;27.875&#34; y2=&#34;-54.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35&#34; y1=&#34;-51.159&#34; x2=&#34;33.5&#34; y2=&#34;-54.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.567&#34; y1=&#34;-44.117&#34; x2=&#34;34.317&#34; y2=&#34;-47.242&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;26.375&#34; y1=&#34;-44.909&#34; x2=&#34;24.625&#34; y2=&#34;-47.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;20.208&#34; y1=&#34;-45.025&#34; x2=&#34;21.333&#34; y2=&#34;-48.15&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;20&#34; y1=&#34;-54.242&#34; x2=&#34;23.25&#34; y2=&#34;-52.867&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;23.868&#34; y1=&#34;-56.068&#34; x2=&#34;25.168&#34; y2=&#34;-59.585&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;19.875&#34; y1=&#34;-60.784&#34; x2=&#34;16.75&#34; y2=&#34;-58.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;15.167&#34; y1=&#34;-53.617&#34; x2=&#34;17.542&#34; y2=&#34;-50.492&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;52.413&#34; y1=&#34;-77.909&#34; x2=&#34;54.663&#34; y2=&#34;-75.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;52.538&#34; y1=&#34;-81.659&#34; x2=&#34;55.913&#34; y2=&#34;-81.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;63.413&#34; y1=&#34;-78.471&#34; x2=&#34;66.101&#34; y2=&#34;-76.426&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;59.913&#34; y1=&#34;-79.534&#34; x2=&#34;57.788&#34; y2=&#34;-76.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;61.538&#34; y1=&#34;-82.284&#34; x2=&#34;58.788&#34; y2=&#34;-84.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;66.788&#34; y1=&#34;-85.034&#34; x2=&#34;64.538&#34; y2=&#34;-83.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;68.413&#34; y1=&#34;-81.659&#34; x2=&#34;68.538&#34; y2=&#34;-78.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;71.788&#34; y1=&#34;-84.226&#34; x2=&#34;74.288&#34; y2=&#34;-82.976&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.163&#34; y1=&#34;-82.592&#34; x2=&#34;80.163&#34; y2=&#34;-84.967&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;82.913&#34; y1=&#34;-81.659&#34; x2=&#34;85.663&#34; y2=&#34;-79.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.788&#34; y1=&#34;-78.034&#34; x2=&#34;79.413&#34; y2=&#34;-75.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.538&#34; y1=&#34;-78.034&#34; x2=&#34;72.038&#34; y2=&#34;-75.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;85.538&#34; y1=&#34;-75.034&#34; x2=&#34;83.413&#34; y2=&#34;-72.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;82.038&#34; y1=&#34;-68.659&#34; x2=&#34;85.413&#34; y2=&#34;-67.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.163&#34; y1=&#34;-71.409&#34; x2=&#34;74.038&#34; y2=&#34;-71.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.288&#34; y1=&#34;-67.909&#34; x2=&#34;71.413&#34; y2=&#34;-66.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.288&#34; y1=&#34;-66.784&#34; x2=&#34;77.288&#34; y2=&#34;-63.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;83.038&#34; y1=&#34;-63.659&#34; x2=&#34;84.788&#34; y2=&#34;-60.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;85.038&#34; y1=&#34;-56.284&#34; x2=&#34;82.288&#34; y2=&#34;-54.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;80.538&#34; y1=&#34;-59.034&#34; x2=&#34;77.038&#34; y2=&#34;-59.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;81.913&#34; y1=&#34;-50.034&#34; x2=&#34;85.538&#34; y2=&#34;-49.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;80.437&#34; y1=&#34;-48.043&#34; x2=&#34;81.687&#34; y2=&#34;-45.043&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;49.288&#34; y1=&#34;-82.409&#34; x2=&#34;46.913&#34; y2=&#34;-79.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;46.788&#34; y1=&#34;-76.034&#34; x2=&#34;50.788&#34; y2=&#34;-74.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;45.788&#34; y1=&#34;-72.284&#34; x2=&#34;46.913&#34; y2=&#34;-68.659&#34; /&amp;gt;
        &amp;lt;path style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; d=&#34;M47.538-65.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;47.538&#34; y1=&#34;-65.659&#34; x2=&#34;44.538&#34; y2=&#34;-63.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;46.98&#34; y1=&#34;-58.583&#34; x2=&#34;48.669&#34; y2=&#34;-55.354&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;44.788&#34; y1=&#34;-53.159&#34; x2=&#34;47.663&#34; y2=&#34;-51.159&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;46.863&#34; y1=&#34;-47.409&#34; x2=&#34;45.238&#34; y2=&#34;-44.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;43.413&#34; y1=&#34;-84.784&#34; x2=&#34;46.663&#34; y2=&#34;-84.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;52.388&#34; y1=&#34;-42.367&#34; x2=&#34;51.263&#34; y2=&#34;-45.867&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;56.288&#34; y1=&#34;-45.659&#34; x2=&#34;59.413&#34; y2=&#34;-47.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;51.663&#34; y1=&#34;-51.034&#34; x2=&#34;55.038&#34; y2=&#34;-51.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;54.529&#34; y1=&#34;-58.284&#34; x2=&#34;53.529&#34; y2=&#34;-54.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;49.953&#34; y1=&#34;-61.285&#34; x2=&#34;53.295&#34; y2=&#34;-62.694&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;53.913&#34; y1=&#34;-71.534&#34; x2=&#34;49.788&#34; y2=&#34;-71.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;54.413&#34; y1=&#34;-68.409&#34; x2=&#34;52.413&#34; y2=&#34;-65.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;57.413&#34; y1=&#34;-64.784&#34; x2=&#34;59.913&#34; y2=&#34;-62.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;57.413&#34; y1=&#34;-72.409&#34; x2=&#34;58.538&#34; y2=&#34;-68.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;61.333&#34; y1=&#34;-72.619&#34; x2=&#34;64.776&#34; y2=&#34;-73.505&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;69.362&#34; y1=&#34;-72.542&#34; x2=&#34;67.519&#34; y2=&#34;-69.411&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;64.538&#34; y1=&#34;-68.784&#34; x2=&#34;61.913&#34; y2=&#34;-66.034&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;65.038&#34; y1=&#34;-63.784&#34; x2=&#34;68.413&#34; y2=&#34;-64.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;71.163&#34; y1=&#34;-62.909&#34; x2=&#34;74.413&#34; y2=&#34;-60.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.225&#34; y1=&#34;-57.138&#34; x2=&#34;72.1&#34; y2=&#34;-54.263&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.038&#34; y1=&#34;-51.159&#34; x2=&#34;76.538&#34; y2=&#34;-54.409&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.888&#34; y1=&#34;-44.4&#34; x2=&#34;77.638&#34; y2=&#34;-47.525&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;73.413&#34; y1=&#34;-50.534&#34; x2=&#34;69.413&#34; y2=&#34;-50.534&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;69.413&#34; y1=&#34;-44.909&#34; x2=&#34;67.663&#34; y2=&#34;-47.909&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;63.375&#34; y1=&#34;-44.659&#34; x2=&#34;64.5&#34; y2=&#34;-47.784&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;64.375&#34; y1=&#34;-53.659&#34; x2=&#34;67.625&#34; y2=&#34;-52.284&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;8.934&#34; y1=&#34;-57.992&#34; x2=&#34;12.184&#34; y2=&#34;-56.617&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;68.487&#34; y1=&#34;-56.208&#34; x2=&#34;66.787&#34; y2=&#34;-59.551&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;62.913&#34; y1=&#34;-60.784&#34; x2=&#34;59.788&#34; y2=&#34;-58.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;58.038&#34; y1=&#34;-54.784&#34; x2=&#34;60.413&#34; y2=&#34;-51.659&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;9.408&#34; y1=&#34;-34.904&#34; x2=&#34;11.658&#34; y2=&#34;-32.279&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;9.533&#34; y1=&#34;-38.654&#34; x2=&#34;12.908&#34; y2=&#34;-38.529&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;20.408&#34; y1=&#34;-35.467&#34; x2=&#34;23.096&#34; y2=&#34;-33.422&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;16.908&#34; y1=&#34;-36.529&#34; x2=&#34;14.783&#34; y2=&#34;-33.779&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;18.533&#34; y1=&#34;-40.13&#34; x2=&#34;15.783&#34; y2=&#34;-41.88&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;23.783&#34; y1=&#34;-42.029&#34; x2=&#34;21.533&#34; y2=&#34;-40.529&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;26.542&#34; y1=&#34;-38.654&#34; x2=&#34;24.905&#34; y2=&#34;-35.99&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;28.783&#34; y1=&#34;-41.221&#34; x2=&#34;31.283&#34; y2=&#34;-39.971&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.158&#34; y1=&#34;-39.587&#34; x2=&#34;37.158&#34; y2=&#34;-41.962&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;39.908&#34; y1=&#34;-38.654&#34; x2=&#34;42.658&#34; y2=&#34;-36.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.783&#34; y1=&#34;-35.029&#34; x2=&#34;36.408&#34; y2=&#34;-32.029&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.533&#34; y1=&#34;-35.029&#34; x2=&#34;29.033&#34; y2=&#34;-32.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;42.533&#34; y1=&#34;-32.029&#34; x2=&#34;40.408&#34; y2=&#34;-29.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;39.033&#34; y1=&#34;-25.654&#34; x2=&#34;42.408&#34; y2=&#34;-24.529&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.08&#34; y1=&#34;-29.024&#34; x2=&#34;31.123&#34; y2=&#34;-27.853&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.283&#34; y1=&#34;-24.904&#34; x2=&#34;28.408&#34; y2=&#34;-23.529&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.283&#34; y1=&#34;-23.779&#34; x2=&#34;34.283&#34; y2=&#34;-20.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;40.033&#34; y1=&#34;-20.654&#34; x2=&#34;41.783&#34; y2=&#34;-17.904&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;42.033&#34; y1=&#34;-13.279&#34; x2=&#34;39.283&#34; y2=&#34;-11.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;37.533&#34; y1=&#34;-16.029&#34; x2=&#34;34.033&#34; y2=&#34;-16.529&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;38.908&#34; y1=&#34;-7.029&#34; x2=&#34;42.533&#34; y2=&#34;-6.779&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;38.287&#34; y1=&#34;-3.517&#34; x2=&#34;39.537&#34; y2=&#34;-0.517&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;6.283&#34; y1=&#34;-39.404&#34; x2=&#34;3.908&#34; y2=&#34;-36.904&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;3.783&#34; y1=&#34;-33.029&#34; x2=&#34;7.783&#34; y2=&#34;-31.904&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;2.783&#34; y1=&#34;-29.279&#34; x2=&#34;3.908&#34; y2=&#34;-25.654&#34; /&amp;gt;
        &amp;lt;path style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; d=&#34;M4.533-22.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;4.533&#34; y1=&#34;-22.654&#34; x2=&#34;1.533&#34; y2=&#34;-20.279&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;4.542&#34; y1=&#34;-16.996&#34; x2=&#34;4.167&#34; y2=&#34;-13.371&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;1.783&#34; y1=&#34;-10.154&#34; x2=&#34;4.658&#34; y2=&#34;-8.154&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;2.158&#34; y1=&#34;-4.404&#34; x2=&#34;0.533&#34; y2=&#34;-1.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;0.408&#34; y1=&#34;-41.779&#34; x2=&#34;3.658&#34; y2=&#34;-41.029&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;8.617&#34; y1=&#34;-0.175&#34; x2=&#34;7.492&#34; y2=&#34;-3.675&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;13.637&#34; y1=&#34;-1.967&#34; x2=&#34;16.763&#34; y2=&#34;-4.092&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;8.658&#34; y1=&#34;-8.029&#34; x2=&#34;12.033&#34; y2=&#34;-8.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;12.658&#34; y1=&#34;-15.279&#34; x2=&#34;10.001&#34; y2=&#34;-12.619&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;6.783&#34; y1=&#34;-18.021&#34; x2=&#34;10.408&#34; y2=&#34;-17.896&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;10.908&#34; y1=&#34;-28.529&#34; x2=&#34;6.783&#34; y2=&#34;-28.279&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;11.408&#34; y1=&#34;-25.404&#34; x2=&#34;9.408&#34; y2=&#34;-22.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;14.408&#34; y1=&#34;-21.779&#34; x2=&#34;16.908&#34; y2=&#34;-19.779&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;14.408&#34; y1=&#34;-29.404&#34; x2=&#34;15.533&#34; y2=&#34;-25.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;18.283&#34; y1=&#34;-30.404&#34; x2=&#34;21.422&#34; y2=&#34;-28.733&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;26.367&#34; y1=&#34;-29.544&#34; x2=&#34;24.504&#34; y2=&#34;-26.424&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;19.846&#34; y1=&#34;-26.713&#34; x2=&#34;18.908&#34; y2=&#34;-23.029&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;22.033&#34; y1=&#34;-20.779&#34; x2=&#34;25.408&#34; y2=&#34;-21.279&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;28.158&#34; y1=&#34;-19.904&#34; x2=&#34;31.408&#34; y2=&#34;-17.904&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;30.033&#34; y1=&#34;-13.554&#34; x2=&#34;27.908&#34; y2=&#34;-10.679&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;35.033&#34; y1=&#34;-8.154&#34; x2=&#34;33.533&#34; y2=&#34;-11.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;31.554&#34; y1=&#34;-1.342&#34; x2=&#34;34.304&#34; y2=&#34;-4.467&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;30.408&#34; y1=&#34;-6.679&#34; x2=&#34;26.408&#34; y2=&#34;-6.679&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;26.513&#34; y1=&#34;-0.967&#34; x2=&#34;24.763&#34; y2=&#34;-3.967&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;19.775&#34; y1=&#34;-2.296&#34; x2=&#34;20.9&#34; y2=&#34;-5.421&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;20.388&#34; y1=&#34;-11.425&#34; x2=&#34;23.638&#34; y2=&#34;-10.05&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;24.029&#34; y1=&#34;-13.608&#34; x2=&#34;25.299&#34; y2=&#34;-17.137&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;19.908&#34; y1=&#34;-17.779&#34; x2=&#34;16.783&#34; y2=&#34;-15.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;15.033&#34; y1=&#34;-11.779&#34; x2=&#34;17.408&#34; y2=&#34;-8.654&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;52.467&#34; y1=&#34;-34.938&#34; x2=&#34;54.717&#34; y2=&#34;-32.313&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;52.592&#34; y1=&#34;-38.688&#34; x2=&#34;55.967&#34; y2=&#34;-38.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;63.467&#34; y1=&#34;-35.5&#34; x2=&#34;66.155&#34; y2=&#34;-33.455&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;59.967&#34; y1=&#34;-36.563&#34; x2=&#34;57.842&#34; y2=&#34;-33.813&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;61.592&#34; y1=&#34;-40.447&#34; x2=&#34;58.842&#34; y2=&#34;-42.197&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;66.842&#34; y1=&#34;-42.063&#34; x2=&#34;64.592&#34; y2=&#34;-40.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;70.103&#34; y1=&#34;-38.301&#34; x2=&#34;68.592&#34; y2=&#34;-35.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;71.842&#34; y1=&#34;-41.255&#34; x2=&#34;74.342&#34; y2=&#34;-40.005&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.217&#34; y1=&#34;-39.621&#34; x2=&#34;80.217&#34; y2=&#34;-41.996&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;82.967&#34; y1=&#34;-38.688&#34; x2=&#34;85.717&#34; y2=&#34;-36.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.842&#34; y1=&#34;-35.063&#34; x2=&#34;79.467&#34; y2=&#34;-32.063&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.592&#34; y1=&#34;-35.063&#34; x2=&#34;72.092&#34; y2=&#34;-32.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;85.592&#34; y1=&#34;-32.063&#34; x2=&#34;83.467&#34; y2=&#34;-29.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;82.092&#34; y1=&#34;-25.688&#34; x2=&#34;85.467&#34; y2=&#34;-24.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.217&#34; y1=&#34;-28.438&#34; x2=&#34;74.092&#34; y2=&#34;-28.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.342&#34; y1=&#34;-24.938&#34; x2=&#34;71.467&#34; y2=&#34;-23.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.342&#34; y1=&#34;-23.813&#34; x2=&#34;77.342&#34; y2=&#34;-20.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;83.092&#34; y1=&#34;-20.688&#34; x2=&#34;84.842&#34; y2=&#34;-17.938&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;85.092&#34; y1=&#34;-13.313&#34; x2=&#34;82.342&#34; y2=&#34;-11.688&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;80.592&#34; y1=&#34;-16.063&#34; x2=&#34;77.092&#34; y2=&#34;-16.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;81.967&#34; y1=&#34;-7.063&#34; x2=&#34;85.592&#34; y2=&#34;-6.813&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;81.554&#34; y1=&#34;-3.717&#34; x2=&#34;82.804&#34; y2=&#34;-0.717&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;49.342&#34; y1=&#34;-39.438&#34; x2=&#34;46.967&#34; y2=&#34;-36.938&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;46.842&#34; y1=&#34;-33.063&#34; x2=&#34;50.842&#34; y2=&#34;-31.938&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;45.842&#34; y1=&#34;-29.313&#34; x2=&#34;46.967&#34; y2=&#34;-25.688&#34; /&amp;gt;
        &amp;lt;path style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; d=&#34;M47.592-22.688&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;47.592&#34; y1=&#34;-22.688&#34; x2=&#34;44.592&#34; y2=&#34;-20.313&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;47.601&#34; y1=&#34;-17.029&#34; x2=&#34;47.226&#34; y2=&#34;-13.404&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;44.842&#34; y1=&#34;-10.188&#34; x2=&#34;47.717&#34; y2=&#34;-8.188&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;45.217&#34; y1=&#34;-4.438&#34; x2=&#34;43.592&#34; y2=&#34;-1.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;43.467&#34; y1=&#34;-41.813&#34; x2=&#34;46.717&#34; y2=&#34;-41.063&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;51.717&#34; y1=&#34;-0.292&#34; x2=&#34;50.592&#34; y2=&#34;-3.792&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;56.529&#34; y1=&#34;-1.105&#34; x2=&#34;59.654&#34; y2=&#34;-3.23&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;51.717&#34; y1=&#34;-8.063&#34; x2=&#34;55.092&#34; y2=&#34;-8.688&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;54.867&#34; y1=&#34;-15.313&#34; x2=&#34;52.121&#34; y2=&#34;-12.744&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;49.842&#34; y1=&#34;-19.188&#34; x2=&#34;53.467&#34; y2=&#34;-19.063&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;53.967&#34; y1=&#34;-28.563&#34; x2=&#34;49.842&#34; y2=&#34;-28.313&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;54.467&#34; y1=&#34;-25.438&#34; x2=&#34;52.467&#34; y2=&#34;-22.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;57.467&#34; y1=&#34;-21.813&#34; x2=&#34;59.967&#34; y2=&#34;-19.813&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;57.467&#34; y1=&#34;-29.438&#34; x2=&#34;58.592&#34; y2=&#34;-25.688&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;61.342&#34; y1=&#34;-30.438&#34; x2=&#34;64.842&#34; y2=&#34;-29.813&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;68.368&#34; y1=&#34;-30.42&#34; x2=&#34;69.412&#34; y2=&#34;-26.939&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;64.592&#34; y1=&#34;-25.813&#34; x2=&#34;61.967&#34; y2=&#34;-23.063&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;65.092&#34; y1=&#34;-20.813&#34; x2=&#34;68.467&#34; y2=&#34;-21.313&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;71.217&#34; y1=&#34;-19.938&#34; x2=&#34;74.467&#34; y2=&#34;-17.938&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;73.092&#34; y1=&#34;-14.438&#34; x2=&#34;70.967&#34; y2=&#34;-11.563&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;78.092&#34; y1=&#34;-8.188&#34; x2=&#34;76.592&#34; y2=&#34;-11.438&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;74.55&#34; y1=&#34;-1.855&#34; x2=&#34;77.3&#34; y2=&#34;-4.979&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;73.236&#34; y1=&#34;-6.656&#34; x2=&#34;69.699&#34; y2=&#34;-8.523&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;69.55&#34; y1=&#34;-0.334&#34; x2=&#34;67.8&#34; y2=&#34;-3.334&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;63.342&#34; y1=&#34;-3.938&#34; x2=&#34;64.467&#34; y2=&#34;-7.063&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;63.092&#34; y1=&#34;-12.688&#34; x2=&#34;66.342&#34; y2=&#34;-11.313&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;65.893&#34; y1=&#34;-14.607&#34; x2=&#34;69.24&#34; y2=&#34;-16.298&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;62.967&#34; y1=&#34;-17.813&#34; x2=&#34;59.842&#34; y2=&#34;-15.688&#34; /&amp;gt;
        &amp;lt;line style=&#34;fill:none;stroke:#000000;stroke-width:0.3;&#34; x1=&#34;58.175&#34; y1=&#34;-10.604&#34; x2=&#34;60.55&#34; y2=&#34;-7.479&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#34;fill: url(#usgs-701-ADC520FF) #fff;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternusgs/README-encode-as-colour.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {svgpatternsimple} - a collection of simple repeating SVG patterns</title>
      <link>https://coolbutuseless.github.io/2019/10/09/introducing-svgpatternsimple-a-collection-of-simple-repeating-svg-patterns/</link>
      <pubDate>Wed, 09 Oct 2019 19:20:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/09/introducing-svgpatternsimple-a-collection-of-simple-repeating-svg-patterns/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;svgpatternsimple&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;svgpatternsimple &lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;svgpatternsimple&lt;/code&gt; provides a basic set of simple repeating SVG patterns.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/svgpatternsimple&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
install_github(&amp;quot;coolbutuseless/lofi&amp;quot;)             # for encoding information as RGB colours
install_github(&amp;quot;coolbutuseless/poissoned&amp;quot;)        # Generate points via poisson disk sampling
install_github(&amp;quot;coolbutuseless/minnisvg&amp;quot;)         # Build SVG documents with R
install_github(&amp;quot;coolbutuseless/svgpatternsimple&amp;quot;) # This package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-what-is-a-pattern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: What is a pattern?&lt;/h2&gt;
&lt;p&gt;The patterns generated by this package are SVG &lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; elements created
with &lt;a href=&#34;https://github.com/coolbutuseless/minisvg&#34;&gt;&lt;code&gt;minisvg&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minisvg&lt;/code&gt; elements are R6 objects which render to a string representing SVG.&lt;/p&gt;
&lt;p&gt;To wrap the pattern in a generic SVG document use the
method &lt;code&gt;$as_full_svg()&lt;/code&gt;, and to display it in an RStudio session use &lt;code&gt;$show()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a dot pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dot &amp;lt;- create_dot_pattern(id = &amp;#39;dot&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dot$show()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg viewBox=&#34;0 0 400 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;dot&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;1.9&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#34;fill: url(#dot) #fff;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-example-dot.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-all-patterns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: All patterns&lt;/h2&gt;
&lt;p&gt;There are 8 pattern types included in this package - this includes a &lt;code&gt;null&lt;/code&gt;
pattern which doesn’t do anything.&lt;/p&gt;
&lt;p&gt;Patterns are created using &lt;code&gt;create_[type]_pattern()&lt;/code&gt;, and arguments control the
appearance of the generated pattern e.g. opacity, orientation etc.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dot          &amp;lt;- create_dot_pattern     (id = &amp;#39;p1&amp;#39; , fill_fraction = 0.4)
stripe       &amp;lt;- create_stripe_pattern  (id = &amp;#39;p2&amp;#39; , angle = 60)
hatch        &amp;lt;- create_hatch_pattern   (id = &amp;#39;p3&amp;#39; , spacing = 50)
stipple      &amp;lt;- create_stipple_pattern (id = &amp;#39;p4&amp;#39; , colour = &amp;#39;hotpink&amp;#39;)
hex          &amp;lt;- create_hex_pattern     (id = &amp;#39;p5&amp;#39; , fill_fraction = 0.1)
check        &amp;lt;- create_check_pattern   (id = &amp;#39;p6&amp;#39; , spacing = 30, colour = &amp;#39;darkgreen&amp;#39;)
gradient     &amp;lt;- create_gradient_pattern(id = &amp;#39;p7&amp;#39; , colour1 = &amp;#39;hotpink&amp;#39;, colour2 = &amp;#39;darkblue&amp;#39;)
null         &amp;lt;- create_null_pattern    (id = &amp;#39;p8&amp;#39; , colour = &amp;#39;#123456&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;p1&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;3.81&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;p2&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(60 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:8; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;p3&#34; width=&#34;50&#34; height=&#34;50&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;50&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;50&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;p4&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-7.22&#39; cy=&#39;-4.32&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.61&#39; cy=&#39;47.93&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.54&#39; cy=&#39;78.06&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.22&#39; cy=&#39;395.68&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.12&#39; cy=&#39;10.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.26&#39; cy=&#39;61.42&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.46&#39; cy=&#39;96.27&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.75&#39; cy=&#39;131.56&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.56&#39; cy=&#39;197.36&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.19&#39; cy=&#39;235.5&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.14&#39; cy=&#39;282.68&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.42&#39; cy=&#39;328.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.17&#39; cy=&#39;378.64&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.12&#39; cy=&#39;410.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.23&#39; cy=&#39;38.31&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.96&#39; cy=&#39;102.91&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.14&#39; cy=&#39;174.25&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.66&#39; cy=&#39;220.65&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.52&#39; cy=&#39;260.29&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;29.89&#39; cy=&#39;301.87&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.04&#39; cy=&#39;353.3&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.01&#39; cy=&#39;16.75&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.56&#39; cy=&#39;61.2&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.86&#39; cy=&#39;129.59&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.86&#39; cy=&#39;206.89&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.21&#39; cy=&#39;379.55&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.01&#39; cy=&#39;416.75&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.79&#39; cy=&#39;34.14&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.35&#39; cy=&#39;154.15&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.29&#39; cy=&#39;239.33&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;61.73&#39; cy=&#39;278.56&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.13&#39; cy=&#39;306.66&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.8&#39; cy=&#39;342.52&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.56&#39; cy=&#39;17.08&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.83&#39; cy=&#39;68.24&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.71&#39; cy=&#39;103.95&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.92&#39; cy=&#39;152.81&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.75&#39; cy=&#39;191.84&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.77&#39; cy=&#39;228.05&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.21&#39; cy=&#39;258.89&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.8&#39; cy=&#39;379.54&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.56&#39; cy=&#39;417.08&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.3&#39; cy=&#39;-17.66&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.89&#39; cy=&#39;41.27&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;119.3&#39; cy=&#39;124.51&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.95&#39; cy=&#39;279.92&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.78&#39; cy=&#39;325.47&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.3&#39; cy=&#39;382.34&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.24&#39; cy=&#39;16.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.91&#39; cy=&#39;65.66&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126&#39; cy=&#39;97.26&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.3&#39; cy=&#39;176.53&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.86&#39; cy=&#39;203.55&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.95&#39; cy=&#39;231.21&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.66&#39; cy=&#39;302.33&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.57&#39; cy=&#39;352.94&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.24&#39; cy=&#39;416.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.36&#39; cy=&#39;40.5&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.52&#39; cy=&#39;128.98&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.1&#39; cy=&#39;174.42&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.23&#39; cy=&#39;263.88&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.87&#39; cy=&#39;335.79&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.19&#39; cy=&#39;19.82&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.81&#39; cy=&#39;72.67&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.07&#39; cy=&#39;105.27&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;179.33&#39; cy=&#39;135.92&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.9&#39; cy=&#39;207.54&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.61&#39; cy=&#39;235.55&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.37&#39; cy=&#39;312.63&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.62&#39; cy=&#39;378.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.19&#39; cy=&#39;419.82&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.15&#39; cy=&#39;20&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;189.35&#39; cy=&#39;44.19&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.88&#39; cy=&#39;168.91&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.13&#39; cy=&#39;212.72&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.58&#39; cy=&#39;263.27&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.12&#39; cy=&#39;339.77&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.85&#39; cy=&#39;364.11&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.15&#39; cy=&#39;420&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.82&#39; cy=&#39;-5.9&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.03&#39; cy=&#39;74.37&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;210.8&#39; cy=&#39;117.48&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.96&#39; cy=&#39;301.37&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.12&#39; cy=&#39;331.36&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.82&#39; cy=&#39;394.1&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.53&#39; cy=&#39;18.99&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.53&#39; cy=&#39;53.48&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.21&#39; cy=&#39;145.96&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;220.67&#39; cy=&#39;174.14&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;226.49&#39; cy=&#39;209.06&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.32&#39; cy=&#39;246.39&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.97&#39; cy=&#39;276.93&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.53&#39; cy=&#39;418.99&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.48&#39; cy=&#39;81.39&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.87&#39; cy=&#39;124.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.57&#39; cy=&#39;179.21&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;255.54&#39; cy=&#39;222.18&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.88&#39; cy=&#39;276.15&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.03&#39; cy=&#39;302.43&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;245.43&#39; cy=&#39;333.22&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.76&#39; cy=&#39;378.65&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.6&#39; cy=&#39;-16.14&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;268.35&#39; cy=&#39;33.15&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;269.86&#39; cy=&#39;74.82&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.95&#39; cy=&#39;145.66&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.71&#39; cy=&#39;197.62&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.83&#39; cy=&#39;319.69&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.54&#39; cy=&#39;347.1&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.6&#39; cy=&#39;383.86&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.84&#39; cy=&#39;33.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.5&#39; cy=&#39;106.78&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;281.88&#39; cy=&#39;167.7&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.02&#39; cy=&#39;222.53&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;280.4&#39; cy=&#39;265.38&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.36&#39; cy=&#39;292.54&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.81&#39; cy=&#39;-4.65&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.94&#39; cy=&#39;78.66&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.28&#39; cy=&#39;140.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.02&#39; cy=&#39;181.35&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.78&#39; cy=&#39;236.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;310.65&#39; cy=&#39;261.75&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.22&#39; cy=&#39;306.77&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.02&#39; cy=&#39;335.7&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.87&#39; cy=&#39;366.24&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.81&#39; cy=&#39;395.35&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.27&#39; cy=&#39;45.01&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.91&#39; cy=&#39;103.97&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;323.74&#39; cy=&#39;204.69&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;-3.59&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.53&#39; cy=&#39;27.58&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.28&#39; cy=&#39;59.45&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.59&#39; cy=&#39;96.22&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.31&#39; cy=&#39;153.82&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.97&#39; cy=&#39;181.54&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;345.77&#39; cy=&#39;244.83&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.25&#39; cy=&#39;287.06&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.96&#39; cy=&#39;337.06&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.15&#39; cy=&#39;360.3&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;396.41&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.02&#39; cy=&#39;124.79&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.08&#39; cy=&#39;168.52&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;367.84&#39; cy=&#39;206.22&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.28&#39; cy=&#39;243.97&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.13&#39; cy=&#39;332.69&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.75&#39; cy=&#39;367.99&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.78&#39; cy=&#39;-4.32&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.39&#39; cy=&#39;47.93&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.46&#39; cy=&#39;78.06&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.78&#39; cy=&#39;395.68&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.12&#39; cy=&#39;10.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.26&#39; cy=&#39;61.42&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.46&#39; cy=&#39;96.27&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.75&#39; cy=&#39;131.56&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.56&#39; cy=&#39;197.36&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.19&#39; cy=&#39;235.5&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.14&#39; cy=&#39;282.68&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.42&#39; cy=&#39;328.23&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.17&#39; cy=&#39;378.64&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.12&#39; cy=&#39;410.17&#39; r=&#39;4&#39; style=&#39;fill: hotpink; stroke: hotpink; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;p5&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:3.2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;p6&#34; width=&#34;30&#34; height=&#34;30&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:darkgreen; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;15&#34; height=&#34;15&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:darkgreen; fill-opacity:1;&#34; x=&#34;15&#34; y=&#34;15&#34; width=&#34;15&#34; height=&#34;15&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;linearGradient id=&#34;p7&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:hotpink;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:darkblue;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;pattern id=&#34;p8&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#123456; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#p1);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p2);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p3);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p4);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p6);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p7);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#p8);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;400&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-all-patterns.svg&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;stripes&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Stripes&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;stripe_0_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_45_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_90_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(90 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_135_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_0_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_45_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_90_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(90 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_135_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_0_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_45_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_90_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(90 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_135_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_0_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_45_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_90_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(90 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stripe_135_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#stripe_0_0.05);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_45_0.05);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_90_0.05);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_135_0.05);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_0_0.25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_45_0.25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_90_0.25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_135_0.25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_0_0.5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_45_0.5);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_90_0.5);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_135_0.5);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_0_0.95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_45_0.95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_90_0.95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stripe_135_0.95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-stripes.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dot-patterns&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Dot patterns&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;dot_0_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;0.48&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_22.5_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;0.48&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_45_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;0.48&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_67.5_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;0.48&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_0_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;2.38&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_22.5_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;2.38&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_45_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;2.38&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_67.5_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;2.38&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_0_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;4.76&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_22.5_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;4.76&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_45_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;4.76&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_67.5_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;4.76&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_0_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;9.05&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_22.5_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;9.05&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_45_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;9.05&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;dot_67.5_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#000000; fill:#000000; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;10&#34; cy=&#34;10&#34; r=&#34;9.05&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#dot_0_0.05);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_22.5_0.05);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_45_0.05);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_67.5_0.05);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_0_0.25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_22.5_0.25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_45_0.25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_67.5_0.25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_0_0.5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_22.5_0.5);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_45_0.5);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_67.5_0.5);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_0_0.95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_22.5_0.95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_45_0.95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#dot_67.5_0.95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-dots.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hatching&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Hatching&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;hatch_0_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_22.5_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_45_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_67.5_0.05&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_0_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_22.5_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_45_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_67.5_0.25&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:10; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_0_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_22.5_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_45_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_67.5_0.5&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:20; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_0_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_22.5_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_45_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hatch_67.5_0.95&#34; width=&#34;20&#34; height=&#34;20&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:38; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;20&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#hatch_0_0.05);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_22.5_0.05);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_45_0.05);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_67.5_0.05);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_0_0.25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_22.5_0.25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_45_0.25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_67.5_0.25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_0_0.5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_22.5_0.5);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_45_0.5);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_67.5_0.5);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_0_0.95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_22.5_0.95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_45_0.95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hatch_67.5_0.95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-hatch.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;stippling&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Stippling&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;stipple_0_0.05&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-7.22&#39; cy=&#39;-4.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.61&#39; cy=&#39;47.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.54&#39; cy=&#39;78.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.22&#39; cy=&#39;395.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.12&#39; cy=&#39;10.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.26&#39; cy=&#39;61.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.46&#39; cy=&#39;96.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.75&#39; cy=&#39;131.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.56&#39; cy=&#39;197.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.19&#39; cy=&#39;235.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.14&#39; cy=&#39;282.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.42&#39; cy=&#39;328.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.17&#39; cy=&#39;378.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.12&#39; cy=&#39;410.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.23&#39; cy=&#39;38.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.96&#39; cy=&#39;102.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.14&#39; cy=&#39;174.25&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.66&#39; cy=&#39;220.65&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.52&#39; cy=&#39;260.29&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;29.89&#39; cy=&#39;301.87&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.04&#39; cy=&#39;353.3&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.01&#39; cy=&#39;16.75&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.56&#39; cy=&#39;61.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.86&#39; cy=&#39;129.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.86&#39; cy=&#39;206.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.21&#39; cy=&#39;379.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.01&#39; cy=&#39;416.75&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.79&#39; cy=&#39;34.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.35&#39; cy=&#39;154.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.29&#39; cy=&#39;239.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;61.73&#39; cy=&#39;278.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.13&#39; cy=&#39;306.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.8&#39; cy=&#39;342.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.56&#39; cy=&#39;17.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.83&#39; cy=&#39;68.24&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.71&#39; cy=&#39;103.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.92&#39; cy=&#39;152.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.75&#39; cy=&#39;191.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.77&#39; cy=&#39;228.05&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.21&#39; cy=&#39;258.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.8&#39; cy=&#39;379.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.56&#39; cy=&#39;417.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.3&#39; cy=&#39;-17.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.89&#39; cy=&#39;41.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;119.3&#39; cy=&#39;124.51&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.95&#39; cy=&#39;279.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.78&#39; cy=&#39;325.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.3&#39; cy=&#39;382.34&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.24&#39; cy=&#39;16.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.91&#39; cy=&#39;65.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126&#39; cy=&#39;97.26&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.3&#39; cy=&#39;176.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.86&#39; cy=&#39;203.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.95&#39; cy=&#39;231.21&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.66&#39; cy=&#39;302.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.57&#39; cy=&#39;352.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.24&#39; cy=&#39;416.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.36&#39; cy=&#39;40.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.52&#39; cy=&#39;128.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.1&#39; cy=&#39;174.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.23&#39; cy=&#39;263.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.87&#39; cy=&#39;335.79&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.19&#39; cy=&#39;19.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.81&#39; cy=&#39;72.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.07&#39; cy=&#39;105.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;179.33&#39; cy=&#39;135.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.9&#39; cy=&#39;207.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.61&#39; cy=&#39;235.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.37&#39; cy=&#39;312.63&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.62&#39; cy=&#39;378.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.19&#39; cy=&#39;419.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.15&#39; cy=&#39;20&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;189.35&#39; cy=&#39;44.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.88&#39; cy=&#39;168.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.13&#39; cy=&#39;212.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.58&#39; cy=&#39;263.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.12&#39; cy=&#39;339.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.85&#39; cy=&#39;364.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.15&#39; cy=&#39;420&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.82&#39; cy=&#39;-5.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.03&#39; cy=&#39;74.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;210.8&#39; cy=&#39;117.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.96&#39; cy=&#39;301.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.12&#39; cy=&#39;331.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.82&#39; cy=&#39;394.1&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.53&#39; cy=&#39;18.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.53&#39; cy=&#39;53.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.21&#39; cy=&#39;145.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;220.67&#39; cy=&#39;174.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;226.49&#39; cy=&#39;209.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.32&#39; cy=&#39;246.39&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.97&#39; cy=&#39;276.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.53&#39; cy=&#39;418.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.48&#39; cy=&#39;81.39&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.87&#39; cy=&#39;124.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.57&#39; cy=&#39;179.21&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;255.54&#39; cy=&#39;222.18&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.88&#39; cy=&#39;276.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.03&#39; cy=&#39;302.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;245.43&#39; cy=&#39;333.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.76&#39; cy=&#39;378.65&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.6&#39; cy=&#39;-16.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;268.35&#39; cy=&#39;33.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;269.86&#39; cy=&#39;74.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.95&#39; cy=&#39;145.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.71&#39; cy=&#39;197.62&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.83&#39; cy=&#39;319.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.54&#39; cy=&#39;347.1&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.6&#39; cy=&#39;383.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.84&#39; cy=&#39;33.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.5&#39; cy=&#39;106.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;281.88&#39; cy=&#39;167.7&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.02&#39; cy=&#39;222.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;280.4&#39; cy=&#39;265.38&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.36&#39; cy=&#39;292.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.81&#39; cy=&#39;-4.65&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.94&#39; cy=&#39;78.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.28&#39; cy=&#39;140.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.02&#39; cy=&#39;181.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.78&#39; cy=&#39;236.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;310.65&#39; cy=&#39;261.75&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.22&#39; cy=&#39;306.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.02&#39; cy=&#39;335.7&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.87&#39; cy=&#39;366.24&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.81&#39; cy=&#39;395.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.27&#39; cy=&#39;45.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.91&#39; cy=&#39;103.97&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;323.74&#39; cy=&#39;204.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;-3.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.53&#39; cy=&#39;27.58&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.28&#39; cy=&#39;59.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.59&#39; cy=&#39;96.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.31&#39; cy=&#39;153.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.97&#39; cy=&#39;181.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;345.77&#39; cy=&#39;244.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.25&#39; cy=&#39;287.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.96&#39; cy=&#39;337.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.15&#39; cy=&#39;360.3&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;396.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.02&#39; cy=&#39;124.79&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.08&#39; cy=&#39;168.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;367.84&#39; cy=&#39;206.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.28&#39; cy=&#39;243.97&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.13&#39; cy=&#39;332.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.75&#39; cy=&#39;367.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.78&#39; cy=&#39;-4.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.39&#39; cy=&#39;47.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.46&#39; cy=&#39;78.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.78&#39; cy=&#39;395.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.12&#39; cy=&#39;10.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.26&#39; cy=&#39;61.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.46&#39; cy=&#39;96.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.75&#39; cy=&#39;131.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.56&#39; cy=&#39;197.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.19&#39; cy=&#39;235.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.14&#39; cy=&#39;282.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.42&#39; cy=&#39;328.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.17&#39; cy=&#39;378.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.12&#39; cy=&#39;410.17&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_22.5_0.05&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-17.35&#39; cy=&#39;-9.75&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.89&#39; cy=&#39;103.85&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.93&#39; cy=&#39;158.18&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.7&#39; cy=&#39;187.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.35&#39; cy=&#39;390.25&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.19&#39; cy=&#39;10.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;11.17&#39; cy=&#39;58.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.56&#39; cy=&#39;145.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.74&#39; cy=&#39;218.12&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.8&#39; cy=&#39;242.51&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.95&#39; cy=&#39;271.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.12&#39; cy=&#39;307.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.6&#39; cy=&#39;347.38&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.19&#39; cy=&#39;410.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.11&#39; cy=&#39;9.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.47&#39; cy=&#39;43.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.8&#39; cy=&#39;101.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;30.4&#39; cy=&#39;192.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.11&#39; cy=&#39;409.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.16&#39; cy=&#39;71.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;43.44&#39; cy=&#39;125.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;43.17&#39; cy=&#39;159.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.28&#39; cy=&#39;213.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;43.97&#39; cy=&#39;251.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;42.75&#39; cy=&#39;297.62&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.03&#39; cy=&#39;331.26&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.61&#39; cy=&#39;368.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.31&#39; cy=&#39;20.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;71.47&#39; cy=&#39;51.39&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;71.6&#39; cy=&#39;97.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.63&#39; cy=&#39;170.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.17&#39; cy=&#39;259.05&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.8&#39; cy=&#39;282.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;78.01&#39; cy=&#39;331.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.17&#39; cy=&#39;-11.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.69&#39; cy=&#39;48.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.25&#39; cy=&#39;80.38&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;87.77&#39; cy=&#39;144.07&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.31&#39; cy=&#39;200.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.16&#39; cy=&#39;228.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.26&#39; cy=&#39;308.09&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.46&#39; cy=&#39;359.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.17&#39; cy=&#39;388.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.47&#39; cy=&#39;11.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.85&#39; cy=&#39;122.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.89&#39; cy=&#39;169.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.97&#39; cy=&#39;243.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;104.59&#39; cy=&#39;273.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.47&#39; cy=&#39;411.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.89&#39; cy=&#39;-19.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.44&#39; cy=&#39;6.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.29&#39; cy=&#39;57.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.75&#39; cy=&#39;99.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.99&#39; cy=&#39;145.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.05&#39; cy=&#39;200.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.76&#39; cy=&#39;234.05&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.23&#39; cy=&#39;306.63&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.93&#39; cy=&#39;339.4&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.89&#39; cy=&#39;380.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.44&#39; cy=&#39;406.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.67&#39; cy=&#39;37.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.46&#39; cy=&#39;77.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.19&#39; cy=&#39;103.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.02&#39; cy=&#39;164.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.59&#39; cy=&#39;276.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;149.93&#39; cy=&#39;357.24&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.91&#39; cy=&#39;0.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.29&#39; cy=&#39;130.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.69&#39; cy=&#39;202.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.02&#39; cy=&#39;243.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;172.52&#39; cy=&#39;298.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.8&#39; cy=&#39;326.03&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.72&#39; cy=&#39;369.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.91&#39; cy=&#39;400.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.65&#39; cy=&#39;27.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;196.29&#39; cy=&#39;60.74&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.16&#39; cy=&#39;99.34&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;187.16&#39; cy=&#39;167.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.44&#39; cy=&#39;204.61&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.83&#39; cy=&#39;239.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.77&#39; cy=&#39;0.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.43&#39; cy=&#39;33.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.97&#39; cy=&#39;122.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.76&#39; cy=&#39;151.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.93&#39; cy=&#39;260.58&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.28&#39; cy=&#39;323.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;202.19&#39; cy=&#39;353.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.77&#39; cy=&#39;400.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;230.59&#39; cy=&#39;201.85&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;230.64&#39; cy=&#39;254.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.31&#39; cy=&#39;283.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.62&#39; cy=&#39;346.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.52&#39; cy=&#39;-18.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.59&#39; cy=&#39;17.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.81&#39; cy=&#39;41.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.73&#39; cy=&#39;78.97&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.18&#39; cy=&#39;119.26&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.24&#39; cy=&#39;165.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.83&#39; cy=&#39;311.24&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.52&#39; cy=&#39;381.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.59&#39; cy=&#39;417.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.78&#39; cy=&#39;7.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.63&#39; cy=&#39;86.65&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;272.08&#39; cy=&#39;147.13&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.59&#39; cy=&#39;184.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.62&#39; cy=&#39;226&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.44&#39; cy=&#39;268.63&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;268.09&#39; cy=&#39;343.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.78&#39; cy=&#39;407.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;281.05&#39; cy=&#39;41.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;281.35&#39; cy=&#39;302.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;290.09&#39; cy=&#39;376.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.82&#39; cy=&#39;19.04&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.33&#39; cy=&#39;46.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.52&#39; cy=&#39;74.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.45&#39; cy=&#39;124.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.83&#39; cy=&#39;172.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.71&#39; cy=&#39;204.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.16&#39; cy=&#39;241.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.86&#39; cy=&#39;277.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;310.21&#39; cy=&#39;313.79&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;314.73&#39; cy=&#39;350.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.82&#39; cy=&#39;419.04&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.49&#39; cy=&#39;60.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.41&#39; cy=&#39;142.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;338.23&#39; cy=&#39;233.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.39&#39; cy=&#39;371.61&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.5&#39; cy=&#39;9.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;39.4&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.91&#39; cy=&#39;112.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;355.85&#39; cy=&#39;162.85&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.47&#39; cy=&#39;187.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.41&#39; cy=&#39;212.02&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.77&#39; cy=&#39;267.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.1&#39; cy=&#39;296.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.25&#39; cy=&#39;325.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.5&#39; cy=&#39;409.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.34&#39; cy=&#39;38.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.47&#39; cy=&#39;63.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.61&#39; cy=&#39;122.74&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.61&#39; cy=&#39;249.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.32&#39; cy=&#39;305.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.33&#39; cy=&#39;336.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;365.89&#39; cy=&#39;366.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.65&#39; cy=&#39;-9.75&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.11&#39; cy=&#39;103.85&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;381.07&#39; cy=&#39;158.18&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.3&#39; cy=&#39;187.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.65&#39; cy=&#39;390.25&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.19&#39; cy=&#39;10.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;411.17&#39; cy=&#39;58.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.56&#39; cy=&#39;145.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.74&#39; cy=&#39;218.12&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.8&#39; cy=&#39;242.51&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.95&#39; cy=&#39;271.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.12&#39; cy=&#39;307.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.6&#39; cy=&#39;347.38&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.19&#39; cy=&#39;410.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_45_0.05&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-16.69&#39; cy=&#39;40.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-0.63&#39; cy=&#39;67.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.04&#39; cy=&#39;88.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-6.42&#39; cy=&#39;128.71&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-5.3&#39; cy=&#39;216.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-13.06&#39; cy=&#39;246.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-2.91&#39; cy=&#39;288.87&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.85&#39; cy=&#39;326.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.34&#39; cy=&#39;8.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;15.92&#39; cy=&#39;32.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;16.1&#39; cy=&#39;99.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;16.57&#39; cy=&#39;354.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.27&#39; cy=&#39;379.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.34&#39; cy=&#39;408.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.99&#39; cy=&#39;-13.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.91&#39; cy=&#39;70.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.04&#39; cy=&#39;126.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.82&#39; cy=&#39;163.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;20.15&#39; cy=&#39;196.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.13&#39; cy=&#39;233.39&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;29.42&#39; cy=&#39;264.79&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.99&#39; cy=&#39;386.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.62&#39; cy=&#39;6.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;50.09&#39; cy=&#39;42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.7&#39; cy=&#39;96.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;50.01&#39; cy=&#39;194.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.81&#39; cy=&#39;285.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.2&#39; cy=&#39;317.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.34&#39; cy=&#39;346.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.62&#39; cy=&#39;406.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.14&#39; cy=&#39;128.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;61.83&#39; cy=&#39;167.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.81&#39; cy=&#39;215.4&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.21&#39; cy=&#39;254.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.13&#39; cy=&#39;-1.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.66&#39; cy=&#39;21.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.82&#39; cy=&#39;51.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;87.61&#39; cy=&#39;79.87&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.81&#39; cy=&#39;100.25&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;87.63&#39; cy=&#39;147.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.22&#39; cy=&#39;279.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.33&#39; cy=&#39;328&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.01&#39; cy=&#39;368.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.13&#39; cy=&#39;398.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.28&#39; cy=&#39;15.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.94&#39; cy=&#39;200.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.54&#39; cy=&#39;246.3&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.99&#39; cy=&#39;280.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;104.98&#39; cy=&#39;353.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.28&#39; cy=&#39;415.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.72&#39; cy=&#39;53.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;135.2&#39; cy=&#39;80.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.85&#39; cy=&#39;129.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.2&#39; cy=&#39;158.63&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.88&#39; cy=&#39;185.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.39&#39; cy=&#39;216.74&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.53&#39; cy=&#39;322.61&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.92&#39; cy=&#39;371.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;142.25&#39; cy=&#39;21.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.27&#39; cy=&#39;142.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.98&#39; cy=&#39;195.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.79&#39; cy=&#39;249.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;141.17&#39; cy=&#39;280.45&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.3&#39; cy=&#39;2.61&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.04&#39; cy=&#39;50.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.48&#39; cy=&#39;88.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.62&#39; cy=&#39;117.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;175.91&#39; cy=&#39;271.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.57&#39; cy=&#39;311.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.05&#39; cy=&#39;362.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.3&#39; cy=&#39;402.61&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.78&#39; cy=&#39;-17.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;186.68&#39; cy=&#39;34.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.24&#39; cy=&#39;64.09&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.46&#39; cy=&#39;190.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;192.37&#39; cy=&#39;219.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.73&#39; cy=&#39;348.04&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.78&#39; cy=&#39;382.28&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.91&#39; cy=&#39;13.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.34&#39; cy=&#39;98.18&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.38&#39; cy=&#39;127.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;205.64&#39; cy=&#39;158.28&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.74&#39; cy=&#39;245.85&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;208.34&#39; cy=&#39;317.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.91&#39; cy=&#39;413.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;227.92&#39; cy=&#39;64.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;230.91&#39; cy=&#39;172.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235.3&#39; cy=&#39;200.87&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.42&#39; cy=&#39;278.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.29&#39; cy=&#39;342.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.15&#39; cy=&#39;368.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.4&#39; cy=&#39;-8.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;256.02&#39; cy=&#39;53.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;246.15&#39; cy=&#39;87.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.36&#39; cy=&#39;125.76&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.24&#39; cy=&#39;258.44&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;258.09&#39; cy=&#39;301.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.4&#39; cy=&#39;391.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.49&#39; cy=&#39;23.18&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.94&#39; cy=&#39;96.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;277.18&#39; cy=&#39;145.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.95&#39; cy=&#39;172.4&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.61&#39; cy=&#39;226.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.29&#39; cy=&#39;330.57&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.65&#39; cy=&#39;364.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.81&#39; cy=&#39;3.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.46&#39; cy=&#39;52.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.44&#39; cy=&#39;120.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;283.32&#39; cy=&#39;261.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.38&#39; cy=&#39;299.15&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;290.62&#39; cy=&#39;355.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.81&#39; cy=&#39;403.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.2&#39; cy=&#39;-17.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;312.22&#39; cy=&#39;31.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.83&#39; cy=&#39;69.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.23&#39; cy=&#39;96.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.58&#39; cy=&#39;155.07&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.3&#39; cy=&#39;191.02&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.26&#39; cy=&#39;247.9&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.54&#39; cy=&#39;324.24&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.2&#39; cy=&#39;382.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.54&#39; cy=&#39;14.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.73&#39; cy=&#39;49.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;338.3&#39; cy=&#39;182.21&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;326.19&#39; cy=&#39;211.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;326.41&#39; cy=&#39;285.09&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;334.33&#39; cy=&#39;316.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.15&#39; cy=&#39;340.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.54&#39; cy=&#39;414.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;349.62&#39; cy=&#39;-16.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;349.29&#39; cy=&#39;76.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.02&#39; cy=&#39;126.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;340.02&#39; cy=&#39;155.7&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;357.78&#39; cy=&#39;230.71&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.33&#39; cy=&#39;279.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;349.62&#39; cy=&#39;383.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371&#39; cy=&#39;6.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374&#39; cy=&#39;160.6&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;375.5&#39; cy=&#39;190.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.2&#39; cy=&#39;313.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.36&#39; cy=&#39;360.4&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371&#39; cy=&#39;406.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.31&#39; cy=&#39;40.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;399.37&#39; cy=&#39;67.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.96&#39; cy=&#39;88.93&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;393.58&#39; cy=&#39;128.71&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;394.7&#39; cy=&#39;216.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;386.94&#39; cy=&#39;246.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;397.09&#39; cy=&#39;288.87&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.15&#39; cy=&#39;326.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.34&#39; cy=&#39;8.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;415.92&#39; cy=&#39;32.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;416.1&#39; cy=&#39;99.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;416.57&#39; cy=&#39;354.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.27&#39; cy=&#39;379.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.34&#39; cy=&#39;408.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_67.5_0.05&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-1.76&#39; cy=&#39;21.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-12.41&#39; cy=&#39;56.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.89&#39; cy=&#39;95.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.55&#39; cy=&#39;124.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.89&#39; cy=&#39;207.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.14&#39; cy=&#39;239.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-10.83&#39; cy=&#39;278.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.81&#39; cy=&#39;303.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.25&#39; cy=&#39;-12.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.26&#39; cy=&#39;81.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.41&#39; cy=&#39;157.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.92&#39; cy=&#39;182.13&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.42&#39; cy=&#39;222.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.63&#39; cy=&#39;309.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;7.46&#39; cy=&#39;337.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.25&#39; cy=&#39;387.44&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.82&#39; cy=&#39;23.6&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;20.46&#39; cy=&#39;54.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.59&#39; cy=&#39;110.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;37.42&#39; cy=&#39;149.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;37.49&#39; cy=&#39;189.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.57&#39; cy=&#39;258.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;36.68&#39; cy=&#39;281.07&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;27.04&#39; cy=&#39;361.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.26&#39; cy=&#39;-11.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.15&#39; cy=&#39;26.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.08&#39; cy=&#39;75.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;50.18&#39; cy=&#39;216.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.1&#39; cy=&#39;333.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.26&#39; cy=&#39;388.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.22&#39; cy=&#39;100.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.47&#39; cy=&#39;157.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.8&#39; cy=&#39;254.76&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.92&#39; cy=&#39;279.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.25&#39; cy=&#39;313.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.81&#39; cy=&#39;351.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;83.61&#39; cy=&#39;-12.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.66&#39; cy=&#39;54.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.25&#39; cy=&#39;137.79&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.45&#39; cy=&#39;209.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.67&#39; cy=&#39;254.07&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.14&#39; cy=&#39;363.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;83.61&#39; cy=&#39;387.64&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.58&#39; cy=&#39;-9.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;110.63&#39; cy=&#39;25.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;117.75&#39; cy=&#39;67.08&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.23&#39; cy=&#39;94.6&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.22&#39; cy=&#39;171.73&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;104.63&#39; cy=&#39;288.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.25&#39; cy=&#39;332.23&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.58&#39; cy=&#39;390.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.9&#39; cy=&#39;110.39&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.21&#39; cy=&#39;140.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.03&#39; cy=&#39;167.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;131.04&#39; cy=&#39;209.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.95&#39; cy=&#39;242.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.42&#39; cy=&#39;296.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.1&#39; cy=&#39;374.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.24&#39; cy=&#39;8.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;142.89&#39; cy=&#39;38.95&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.16&#39; cy=&#39;61.63&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.61&#39; cy=&#39;245.58&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;154.54&#39; cy=&#39;344.07&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.24&#39; cy=&#39;408.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.58&#39; cy=&#39;-18.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.42&#39; cy=&#39;13.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.8&#39; cy=&#39;108.66&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.15&#39; cy=&#39;139.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.22&#39; cy=&#39;211.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.43&#39; cy=&#39;314.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.58&#39; cy=&#39;381.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.42&#39; cy=&#39;413.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;180.86&#39; cy=&#39;42.19&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;194.58&#39; cy=&#39;68.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;198.87&#39; cy=&#39;107.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.71&#39; cy=&#39;164.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.92&#39; cy=&#39;196.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.99&#39; cy=&#39;261.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.18&#39; cy=&#39;291.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.5&#39; cy=&#39;324.96&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.5&#39; cy=&#39;366.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.15&#39; cy=&#39;-7.11&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.78&#39; cy=&#39;20.06&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.76&#39; cy=&#39;48.59&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.05&#39; cy=&#39;202.68&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.98&#39; cy=&#39;242.41&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.39&#39; cy=&#39;273.38&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.15&#39; cy=&#39;392.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.01&#39; cy=&#39;-7.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.63&#39; cy=&#39;69.51&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.29&#39; cy=&#39;118.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;220.48&#39; cy=&#39;156.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.43&#39; cy=&#39;310.69&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.42&#39; cy=&#39;340.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;221.77&#39; cy=&#39;368.42&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.01&#39; cy=&#39;392.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;252.7&#39; cy=&#39;27.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.27&#39; cy=&#39;137.01&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;252.28&#39; cy=&#39;179.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.13&#39; cy=&#39;213.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.52&#39; cy=&#39;256.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.32&#39; cy=&#39;288.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.68&#39; cy=&#39;363.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.26&#39; cy=&#39;2.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.1&#39; cy=&#39;69.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;273.93&#39; cy=&#39;123.12&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;272.84&#39; cy=&#39;216.03&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.86&#39; cy=&#39;250.31&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.38&#39; cy=&#39;339.8&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.26&#39; cy=&#39;402.43&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.25&#39; cy=&#39;33.88&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;296.15&#39; cy=&#39;63.05&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.34&#39; cy=&#39;97.44&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;283.52&#39; cy=&#39;156.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.05&#39; cy=&#39;188.21&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;287.46&#39; cy=&#39;282.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.25&#39; cy=&#39;320.89&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.8&#39; cy=&#39;379.81&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.21&#39; cy=&#39;123.27&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.94&#39; cy=&#39;176.13&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.64&#39; cy=&#39;218.92&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.8&#39; cy=&#39;248.99&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.82&#39; cy=&#39;359.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320&#39; cy=&#39;-6.78&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.47&#39; cy=&#39;39.55&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.4&#39; cy=&#39;60.94&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.93&#39; cy=&#39;85.5&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.74&#39; cy=&#39;199.86&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.09&#39; cy=&#39;297.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.07&#39; cy=&#39;322.28&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320&#39; cy=&#39;393.22&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.5&#39; cy=&#39;19.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;357.26&#39; cy=&#39;50.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.94&#39; cy=&#39;122.82&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;344.94&#39; cy=&#39;159.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.37&#39; cy=&#39;189.72&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.03&#39; cy=&#39;232.97&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;350.85&#39; cy=&#39;279.14&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.51&#39; cy=&#39;315.65&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.65&#39; cy=&#39;369.16&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.5&#39; cy=&#39;419.91&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.1&#39; cy=&#39;-18.33&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;361.87&#39; cy=&#39;79.34&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.99&#39; cy=&#39;165.37&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.65&#39; cy=&#39;347.32&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.1&#39; cy=&#39;381.67&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.24&#39; cy=&#39;21.54&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;387.59&#39; cy=&#39;56.83&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.11&#39; cy=&#39;95.53&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;381.45&#39; cy=&#39;124.52&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.11&#39; cy=&#39;207.84&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.86&#39; cy=&#39;239.35&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;389.17&#39; cy=&#39;278.98&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.19&#39; cy=&#39;303.77&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.25&#39; cy=&#39;-12.56&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.26&#39; cy=&#39;81.46&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.41&#39; cy=&#39;157.47&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.92&#39; cy=&#39;182.13&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.42&#39; cy=&#39;222.2&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.63&#39; cy=&#39;309.48&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;407.46&#39; cy=&#39;337.36&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.25&#39; cy=&#39;387.44&#39; r=&#39;1&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_0_0.25&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-13.59&#39; cy=&#39;5.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.29&#39; cy=&#39;36.12&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.2&#39; cy=&#39;104.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.18&#39; cy=&#39;254.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.24&#39; cy=&#39;315.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.01&#39; cy=&#39;358.09&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-13.59&#39; cy=&#39;405.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.37&#39; cy=&#39;-17.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.26&#39; cy=&#39;71.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.52&#39; cy=&#39;137.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.23&#39; cy=&#39;185.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1.75&#39; cy=&#39;209.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.37&#39; cy=&#39;258.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.05&#39; cy=&#39;283.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.34&#39; cy=&#39;334.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.37&#39; cy=&#39;382.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.51&#39; cy=&#39;20.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.86&#39; cy=&#39;112.08&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;29.17&#39; cy=&#39;219.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.84&#39; cy=&#39;271.64&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.67&#39; cy=&#39;302.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.71&#39; cy=&#39;-4.09&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.74&#39; cy=&#39;36.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;53.47&#39; cy=&#39;85.12&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.87&#39; cy=&#39;144.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.25&#39; cy=&#39;329.64&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;41.86&#39; cy=&#39;359.09&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.71&#39; cy=&#39;395.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;73.69&#39; cy=&#39;17.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74.41&#39; cy=&#39;64.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.34&#39; cy=&#39;109&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;62.93&#39; cy=&#39;184.2&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;68.51&#39; cy=&#39;229.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.44&#39; cy=&#39;267.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;71.39&#39; cy=&#39;304.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.79&#39; cy=&#39;362.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;73.69&#39; cy=&#39;417.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.23&#39; cy=&#39;-10&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.37&#39; cy=&#39;142.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.51&#39; cy=&#39;194.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.56&#39; cy=&#39;227.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.03&#39; cy=&#39;338.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.23&#39; cy=&#39;390&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;117.47&#39; cy=&#39;40.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.56&#39; cy=&#39;70.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.13&#39; cy=&#39;103.84&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;117.18&#39; cy=&#39;172.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;106.5&#39; cy=&#39;287.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.89&#39; cy=&#39;330.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;121.69&#39; cy=&#39;14.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;131.62&#39; cy=&#39;90.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.69&#39; cy=&#39;143.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.8&#39; cy=&#39;211.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.56&#39; cy=&#39;238.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.27&#39; cy=&#39;264.35&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.74&#39; cy=&#39;373.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;121.69&#39; cy=&#39;414.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;154.41&#39; cy=&#39;-17.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;152.43&#39; cy=&#39;14.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.53&#39; cy=&#39;74.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.21&#39; cy=&#39;117.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.65&#39; cy=&#39;152.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.75&#39; cy=&#39;191.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.29&#39; cy=&#39;300.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;142.84&#39; cy=&#39;348.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;154.41&#39; cy=&#39;382.86&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;152.43&#39; cy=&#39;414.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.22&#39; cy=&#39;44.05&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.33&#39; cy=&#39;233.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;175.61&#39; cy=&#39;270.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.15&#39; cy=&#39;328.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.34&#39; cy=&#39;-19.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.56&#39; cy=&#39;12.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.95&#39; cy=&#39;94.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.87&#39; cy=&#39;147.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;187.88&#39; cy=&#39;178.57&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.43&#39; cy=&#39;207.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;196.45&#39; cy=&#39;295.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.29&#39; cy=&#39;358.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.34&#39; cy=&#39;380.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.56&#39; cy=&#39;412.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.8&#39; cy=&#39;46.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.24&#39; cy=&#39;122.59&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.46&#39; cy=&#39;161.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.15&#39; cy=&#39;195.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.81&#39; cy=&#39;227.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.28&#39; cy=&#39;261.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.96&#39; cy=&#39;324.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.1&#39; cy=&#39;-17.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.78&#39; cy=&#39;15.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.34&#39; cy=&#39;98.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.46&#39; cy=&#39;129.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.57&#39; cy=&#39;185.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.34&#39; cy=&#39;357.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.1&#39; cy=&#39;382.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.78&#39; cy=&#39;415.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.62&#39; cy=&#39;-4.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.2&#39; cy=&#39;54.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;258.3&#39; cy=&#39;146.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;246.32&#39; cy=&#39;218.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;258.56&#39; cy=&#39;257.73&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.67&#39; cy=&#39;284.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.38&#39; cy=&#39;329.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.62&#39; cy=&#39;395.25&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;273.85&#39; cy=&#39;24.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.21&#39; cy=&#39;82.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.59&#39; cy=&#39;113.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.56&#39; cy=&#39;175.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;271.4&#39; cy=&#39;200.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.83&#39; cy=&#39;291.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.69&#39; cy=&#39;329.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;266.24&#39; cy=&#39;366.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;296.26&#39; cy=&#39;71.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;292.44&#39; cy=&#39;107.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;293.35&#39; cy=&#39;230.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.16&#39; cy=&#39;262.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.53&#39; cy=&#39;-4.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;314.92&#39; cy=&#39;49.2&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.63&#39; cy=&#39;138.47&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.01&#39; cy=&#39;165.08&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.43&#39; cy=&#39;209.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.34&#39; cy=&#39;272.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.44&#39; cy=&#39;304.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.13&#39; cy=&#39;332.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.82&#39; cy=&#39;366.85&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.53&#39; cy=&#39;395.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.42&#39; cy=&#39;103.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.2&#39; cy=&#39;242.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.04&#39; cy=&#39;-6.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.12&#39; cy=&#39;32.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;350.65&#39; cy=&#39;75.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;340.96&#39; cy=&#39;128.57&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;345.17&#39; cy=&#39;197.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;340.29&#39; cy=&#39;267.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.07&#39; cy=&#39;322.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.37&#39; cy=&#39;356.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.04&#39; cy=&#39;393.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.61&#39; cy=&#39;76.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;360.46&#39; cy=&#39;106.35&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.03&#39; cy=&#39;129.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.51&#39; cy=&#39;168.68&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.43&#39; cy=&#39;200.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.98&#39; cy=&#39;231.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;360.34&#39; cy=&#39;296.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;386.41&#39; cy=&#39;5.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.71&#39; cy=&#39;36.12&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.8&#39; cy=&#39;104.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;381.82&#39; cy=&#39;254.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.76&#39; cy=&#39;315.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.99&#39; cy=&#39;358.09&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;386.41&#39; cy=&#39;405.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.37&#39; cy=&#39;-17.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.26&#39; cy=&#39;71.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.52&#39; cy=&#39;137.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.23&#39; cy=&#39;185.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;401.75&#39; cy=&#39;209.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.37&#39; cy=&#39;258.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.05&#39; cy=&#39;283.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.34&#39; cy=&#39;334.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.37&#39; cy=&#39;382.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_22.5_0.25&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-8.86&#39; cy=&#39;-15.73&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.83&#39; cy=&#39;16.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-0.52&#39; cy=&#39;73.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.87&#39; cy=&#39;97.07&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.67&#39; cy=&#39;197.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.05&#39; cy=&#39;248.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.53&#39; cy=&#39;287.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.98&#39; cy=&#39;320.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-8.69&#39; cy=&#39;354.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-8.86&#39; cy=&#39;384.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.83&#39; cy=&#39;416.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.83&#39; cy=&#39;37.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.86&#39; cy=&#39;116.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1.52&#39; cy=&#39;146.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.42&#39; cy=&#39;10.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.66&#39; cy=&#39;88.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;33.23&#39; cy=&#39;148.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;30.91&#39; cy=&#39;189.35&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.5&#39; cy=&#39;327.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;31.43&#39; cy=&#39;377.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.42&#39; cy=&#39;410.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;40.46&#39; cy=&#39;41.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.28&#39; cy=&#39;130.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;41.31&#39; cy=&#39;217.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.63&#39; cy=&#39;240.13&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;42.53&#39; cy=&#39;283.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.32&#39; cy=&#39;336.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;62.7&#39; cy=&#39;22.2&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;71.95&#39; cy=&#39;67.94&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;75.63&#39; cy=&#39;103.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.73&#39; cy=&#39;162.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.53&#39; cy=&#39;187.33&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;73.69&#39; cy=&#39;231.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.14&#39; cy=&#39;310.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.34&#39; cy=&#39;375.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.74&#39; cy=&#39;-2.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.87&#39; cy=&#39;46.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.98&#39; cy=&#39;79.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.25&#39; cy=&#39;131.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86&#39; cy=&#39;270.41&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.22&#39; cy=&#39;356.62&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.74&#39; cy=&#39;397.58&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.08&#39; cy=&#39;-17.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;112.11&#39; cy=&#39;19.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.09&#39; cy=&#39;164.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.98&#39; cy=&#39;197.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;108.1&#39; cy=&#39;225.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.76&#39; cy=&#39;322.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.08&#39; cy=&#39;382.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;112.11&#39; cy=&#39;419.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.26&#39; cy=&#39;45.59&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.52&#39; cy=&#39;84.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.58&#39; cy=&#39;116.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.27&#39; cy=&#39;192.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138.02&#39; cy=&#39;222.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.58&#39; cy=&#39;261.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.76&#39; cy=&#39;291.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.59&#39; cy=&#39;352.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;146.53&#39; cy=&#39;18.94&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;147&#39; cy=&#39;62.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.77&#39; cy=&#39;96.13&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.1&#39; cy=&#39;152.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;145.72&#39; cy=&#39;366.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;146.53&#39; cy=&#39;418.94&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.74&#39; cy=&#39;-0.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.68&#39; cy=&#39;59.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.34&#39; cy=&#39;126.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;163.84&#39; cy=&#39;184.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.33&#39; cy=&#39;254.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;174.23&#39; cy=&#39;285.13&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.19&#39; cy=&#39;324.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.64&#39; cy=&#39;361.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.74&#39; cy=&#39;399.37&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.07&#39; cy=&#39;35.68&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;186.3&#39; cy=&#39;90.62&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.7&#39; cy=&#39;155.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;187.41&#39; cy=&#39;216.37&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.69&#39; cy=&#39;-11.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.56&#39; cy=&#39;64.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.79&#39; cy=&#39;111.04&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.52&#39; cy=&#39;147.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.37&#39; cy=&#39;189.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.88&#39; cy=&#39;238.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.4&#39; cy=&#39;260.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.92&#39; cy=&#39;307.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.24&#39; cy=&#39;337.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.69&#39; cy=&#39;388.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.43&#39; cy=&#39;31.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;230.73&#39; cy=&#39;201.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.21&#39; cy=&#39;230.41&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.96&#39; cy=&#39;259.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.43&#39; cy=&#39;301.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;224.85&#39; cy=&#39;356.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.19&#39; cy=&#39;-3.58&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.27&#39; cy=&#39;87.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;248.45&#39; cy=&#39;120.95&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.27&#39; cy=&#39;177.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.48&#39; cy=&#39;340.08&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.52&#39; cy=&#39;370.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.19&#39; cy=&#39;396.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.02&#39; cy=&#39;23.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;271.49&#39; cy=&#39;64.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.25&#39; cy=&#39;93.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.48&#39; cy=&#39;132.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.22&#39; cy=&#39;161.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.45&#39; cy=&#39;224.12&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.66&#39; cy=&#39;267.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.77&#39; cy=&#39;304.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.3&#39; cy=&#39;-5.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.15&#39; cy=&#39;198.13&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.86&#39; cy=&#39;299.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;285.58&#39; cy=&#39;359.07&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.3&#39; cy=&#39;394.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;316.14&#39; cy=&#39;31.64&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.22&#39; cy=&#39;62.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.67&#39; cy=&#39;105.18&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.73&#39; cy=&#39;147.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;313.17&#39; cy=&#39;176.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.95&#39; cy=&#39;234.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;301.44&#39; cy=&#39;266.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.64&#39; cy=&#39;-7.34&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.99&#39; cy=&#39;94.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.54&#39; cy=&#39;197.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.16&#39; cy=&#39;229.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.58&#39; cy=&#39;275.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;334.49&#39; cy=&#39;303.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.06&#39; cy=&#39;331.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.72&#39; cy=&#39;363.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.64&#39; cy=&#39;392.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.69&#39; cy=&#39;19.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;344.94&#39; cy=&#39;55.62&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.34&#39; cy=&#39;138.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.98&#39; cy=&#39;354.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.69&#39; cy=&#39;419.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;361.73&#39; cy=&#39;-8.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.6&#39; cy=&#39;58.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;376.08&#39; cy=&#39;129.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;375.3&#39; cy=&#39;171.04&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.62&#39; cy=&#39;203.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;363.14&#39; cy=&#39;234.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.19&#39; cy=&#39;261.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.09&#39; cy=&#39;295.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;366.73&#39; cy=&#39;322.77&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;361.73&#39; cy=&#39;391.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;391.14&#39; cy=&#39;-15.73&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.17&#39; cy=&#39;16.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;399.48&#39; cy=&#39;73.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;381.13&#39; cy=&#39;97.07&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.33&#39; cy=&#39;197.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.95&#39; cy=&#39;248.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.47&#39; cy=&#39;287.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.02&#39; cy=&#39;320.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;391.31&#39; cy=&#39;354.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;391.14&#39; cy=&#39;384.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.17&#39; cy=&#39;416.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.83&#39; cy=&#39;37.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.86&#39; cy=&#39;116.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;401.52&#39; cy=&#39;146.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_45_0.25&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-16.01&#39; cy=&#39;7.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.89&#39; cy=&#39;39.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-9.36&#39; cy=&#39;172.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-13.42&#39; cy=&#39;213.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.72&#39; cy=&#39;252.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.43&#39; cy=&#39;288.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.12&#39; cy=&#39;370.79&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.01&#39; cy=&#39;407.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.47&#39; cy=&#39;12.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;8.84&#39; cy=&#39;56.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.04&#39; cy=&#39;92.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.33&#39; cy=&#39;125.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.19&#39; cy=&#39;159.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.18&#39; cy=&#39;234.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;15&#39; cy=&#39;261.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;12.72&#39; cy=&#39;299.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.47&#39; cy=&#39;412.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.03&#39; cy=&#39;81.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.24&#39; cy=&#39;197.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.94&#39; cy=&#39;338.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.47&#39; cy=&#39;362.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;40.65&#39; cy=&#39;54.71&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;43.85&#39; cy=&#39;123.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.68&#39; cy=&#39;153.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.43&#39; cy=&#39;231.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;41.59&#39; cy=&#39;261.35&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.9&#39; cy=&#39;296.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.35&#39; cy=&#39;340.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;59.48&#39; cy=&#39;376.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;61.29&#39; cy=&#39;18.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.99&#39; cy=&#39;52.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;65.25&#39; cy=&#39;80.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.47&#39; cy=&#39;203.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.75&#39; cy=&#39;232.18&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;61.29&#39; cy=&#39;418.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.47&#39; cy=&#39;-4.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95&#39; cy=&#39;33.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;94.98&#39; cy=&#39;75.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.05&#39; cy=&#39;113.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.64&#39; cy=&#39;140.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.73&#39; cy=&#39;178.62&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.58&#39; cy=&#39;277.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.08&#39; cy=&#39;314.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.64&#39; cy=&#39;355.08&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.47&#39; cy=&#39;395.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.45&#39; cy=&#39;202.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;110.99&#39; cy=&#39;331.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.84&#39; cy=&#39;0.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124&#39; cy=&#39;45.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.55&#39; cy=&#39;77.04&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.05&#39; cy=&#39;115.86&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.2&#39; cy=&#39;167.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138&#39; cy=&#39;218.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.62&#39; cy=&#39;242.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;121.01&#39; cy=&#39;297&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;130.34&#39; cy=&#39;358.56&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.84&#39; cy=&#39;400.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;145.25&#39; cy=&#39;24.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.86&#39; cy=&#39;149.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;145.31&#39; cy=&#39;187.57&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;154.11&#39; cy=&#39;286.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;141.31&#39; cy=&#39;327.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.79&#39; cy=&#39;369.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;174.86&#39; cy=&#39;23.56&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.18&#39; cy=&#39;57.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;163.82&#39; cy=&#39;89.47&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.79&#39; cy=&#39;120.05&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.64&#39; cy=&#39;182.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;163.79&#39; cy=&#39;211.41&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.31&#39; cy=&#39;245.74&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;186.69&#39; cy=&#39;144.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.02&#39; cy=&#39;218.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.72&#39; cy=&#39;256.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;186.25&#39; cy=&#39;285.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;188.05&#39; cy=&#39;319.56&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.78&#39; cy=&#39;362.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.87&#39; cy=&#39;14.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.1&#39; cy=&#39;46.25&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;202.88&#39; cy=&#39;76.02&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.19&#39; cy=&#39;103.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.92&#39; cy=&#39;168.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.38&#39; cy=&#39;308.18&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.87&#39; cy=&#39;414.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.38&#39; cy=&#39;-6.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235.43&#39; cy=&#39;121.83&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.37&#39; cy=&#39;198.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.16&#39; cy=&#39;221.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.9&#39; cy=&#39;268.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.19&#39; cy=&#39;334.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.17&#39; cy=&#39;361.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.38&#39; cy=&#39;393.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;253.49&#39; cy=&#39;-17.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.53&#39; cy=&#39;20.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;252.94&#39; cy=&#39;79.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.33&#39; cy=&#39;145.06&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;244.89&#39; cy=&#39;175.5&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.33&#39; cy=&#39;244.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.84&#39; cy=&#39;301.58&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;253.49&#39; cy=&#39;382.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.84&#39; cy=&#39;21.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.19&#39; cy=&#39;113.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.22&#39; cy=&#39;172.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;273.18&#39; cy=&#39;212.07&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.01&#39; cy=&#39;252.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.83&#39; cy=&#39;282.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.18&#39; cy=&#39;313.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.19&#39; cy=&#39;347.58&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.54&#39; cy=&#39;59.27&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.21&#39; cy=&#39;291.34&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;287.05&#39; cy=&#39;362.34&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.16&#39; cy=&#39;-14.62&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.8&#39; cy=&#39;27.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.13&#39; cy=&#39;98.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.07&#39; cy=&#39;122.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;301.43&#39; cy=&#39;152.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;303.99&#39; cy=&#39;181.33&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.11&#39; cy=&#39;223.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.27&#39; cy=&#39;261.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;303.12&#39; cy=&#39;336.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.16&#39; cy=&#39;385.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.65&#39; cy=&#39;86.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.65&#39; cy=&#39;134.88&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;327.61&#39; cy=&#39;198.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;327.98&#39; cy=&#39;304.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.11&#39; cy=&#39;337.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;354.27&#39; cy=&#39;15.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.36&#39; cy=&#39;50.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.16&#39; cy=&#39;209.03&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.94&#39; cy=&#39;240.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.58&#39; cy=&#39;273.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;357.51&#39; cy=&#39;302.23&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;340.39&#39; cy=&#39;363.68&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;354.27&#39; cy=&#39;415.91&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.02&#39; cy=&#39;69.17&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.18&#39; cy=&#39;118.71&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;360.95&#39; cy=&#39;155.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;367.41&#39; cy=&#39;335.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.99&#39; cy=&#39;7.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.11&#39; cy=&#39;39.69&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;390.64&#39; cy=&#39;172.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;386.58&#39; cy=&#39;213.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.28&#39; cy=&#39;252.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.57&#39; cy=&#39;288.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.88&#39; cy=&#39;370.79&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.99&#39; cy=&#39;407.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.47&#39; cy=&#39;12.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;408.84&#39; cy=&#39;56.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.04&#39; cy=&#39;92.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.33&#39; cy=&#39;125.44&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.19&#39; cy=&#39;159.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.18&#39; cy=&#39;234.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;415&#39; cy=&#39;261.1&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;412.72&#39; cy=&#39;299.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.47&#39; cy=&#39;412.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_67.5_0.25&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-5.18&#39; cy=&#39;-7.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-11.42&#39; cy=&#39;173.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-5.18&#39; cy=&#39;392.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.93&#39; cy=&#39;39.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2.12&#39; cy=&#39;64.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.84&#39; cy=&#39;92.84&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.22&#39; cy=&#39;120.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;7.15&#39; cy=&#39;149.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.45&#39; cy=&#39;196.71&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;8.71&#39; cy=&#39;242.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2.04&#39; cy=&#39;317.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.79&#39; cy=&#39;345.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.11&#39; cy=&#39;-7.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;34.75&#39; cy=&#39;121.87&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.77&#39; cy=&#39;158.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.46&#39; cy=&#39;195.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.84&#39; cy=&#39;292.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.11&#39; cy=&#39;392.57&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.38&#39; cy=&#39;31.5&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.11&#39; cy=&#39;84.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;46.92&#39; cy=&#39;225.56&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.79&#39; cy=&#39;266.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.76&#39; cy=&#39;309.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.37&#39; cy=&#39;340.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.77&#39; cy=&#39;-18.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74.78&#39; cy=&#39;71.9&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.66&#39; cy=&#39;111.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;68.52&#39; cy=&#39;141.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.42&#39; cy=&#39;170.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.32&#39; cy=&#39;206.48&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.77&#39; cy=&#39;381.68&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.3&#39; cy=&#39;44.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;94.81&#39; cy=&#39;93.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.91&#39; cy=&#39;161.93&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.34&#39; cy=&#39;191.77&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.66&#39; cy=&#39;255.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.69&#39; cy=&#39;289.25&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.11&#39; cy=&#39;315.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.27&#39; cy=&#39;359.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.33&#39; cy=&#39;-10.37&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;117.48&#39; cy=&#39;22.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.25&#39; cy=&#39;129.26&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.61&#39; cy=&#39;335.07&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.33&#39; cy=&#39;389.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.3&#39; cy=&#39;-2.37&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.18&#39; cy=&#39;60.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.66&#39; cy=&#39;94.75&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.19&#39; cy=&#39;158.54&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.49&#39; cy=&#39;187.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.5&#39; cy=&#39;237.68&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.73&#39; cy=&#39;270.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.93&#39; cy=&#39;313.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;131.14&#39; cy=&#39;364.22&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.3&#39; cy=&#39;397.63&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.75&#39; cy=&#39;91.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.64&#39; cy=&#39;128.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;155.41&#39; cy=&#39;190.41&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;155.85&#39; cy=&#39;241.45&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.69&#39; cy=&#39;-8.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.84&#39; cy=&#39;45.3&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.89&#39; cy=&#39;215.15&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.46&#39; cy=&#39;265.25&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;163.98&#39; cy=&#39;290.94&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.96&#39; cy=&#39;346.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.69&#39; cy=&#39;391.64&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.94&#39; cy=&#39;91.42&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.08&#39; cy=&#39;133.87&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.38&#39; cy=&#39;165.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.2&#39; cy=&#39;291.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.21&#39; cy=&#39;320.47&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.5&#39; cy=&#39;6.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.13&#39; cy=&#39;39.2&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.7&#39; cy=&#39;65.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.93&#39; cy=&#39;187.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.62&#39; cy=&#39;218.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.21&#39; cy=&#39;259.14&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;215.96&#39; cy=&#39;318.01&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.86&#39; cy=&#39;340.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.82&#39; cy=&#39;377.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.5&#39; cy=&#39;406.97&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.81&#39; cy=&#39;-5.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.42&#39; cy=&#39;79.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;227.47&#39; cy=&#39;130.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.14&#39; cy=&#39;195.78&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.16&#39; cy=&#39;253.55&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.6&#39; cy=&#39;283.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.81&#39; cy=&#39;394.79&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.04&#39; cy=&#39;46.8&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.3&#39; cy=&#39;108.86&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.81&#39; cy=&#39;161.61&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.37&#39; cy=&#39;316.84&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;252.41&#39; cy=&#39;370.31&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.24&#39; cy=&#39;-1.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.35&#39; cy=&#39;22.32&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.85&#39; cy=&#39;138.57&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;266.55&#39; cy=&#39;192.46&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;266.01&#39; cy=&#39;237.59&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;260.47&#39; cy=&#39;270.56&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.12&#39; cy=&#39;304.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.32&#39; cy=&#39;351.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.24&#39; cy=&#39;398.79&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.82&#39; cy=&#39;-12.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;283.14&#39; cy=&#39;78.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;290.92&#39; cy=&#39;280.19&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.82&#39; cy=&#39;387.64&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.12&#39; cy=&#39;-14.92&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.25&#39; cy=&#39;17.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.44&#39; cy=&#39;45.04&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;313.66&#39; cy=&#39;76.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.4&#39; cy=&#39;117.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.93&#39; cy=&#39;161.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.94&#39; cy=&#39;193.43&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.41&#39; cy=&#39;227.7&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.57&#39; cy=&#39;256.66&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;311.76&#39; cy=&#39;308.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.26&#39; cy=&#39;359.11&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.12&#39; cy=&#39;385.08&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.25&#39; cy=&#39;417.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.23&#39; cy=&#39;119.29&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.09&#39; cy=&#39;153.4&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.56&#39; cy=&#39;268.52&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;339.51&#39; cy=&#39;298.41&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.29&#39; cy=&#39;341.47&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.11&#39; cy=&#39;-18.51&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.66&#39; cy=&#39;11.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.11&#39; cy=&#39;51.24&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;344.67&#39; cy=&#39;85.98&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.56&#39; cy=&#39;184.89&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.05&#39; cy=&#39;234.96&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;357.19&#39; cy=&#39;328.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.11&#39; cy=&#39;381.49&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.66&#39; cy=&#39;411.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.93&#39; cy=&#39;41.81&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;376.74&#39; cy=&#39;86.99&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;369.31&#39; cy=&#39;144.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.94&#39; cy=&#39;206.47&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.93&#39; cy=&#39;261.82&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.59&#39; cy=&#39;303.39&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.3&#39; cy=&#39;349.21&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;394.82&#39; cy=&#39;-7.28&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;388.58&#39; cy=&#39;173.67&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;394.82&#39; cy=&#39;392.72&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.93&#39; cy=&#39;39.76&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402.12&#39; cy=&#39;64.53&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.84&#39; cy=&#39;92.84&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.22&#39; cy=&#39;120.16&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;407.15&#39; cy=&#39;149.65&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.45&#39; cy=&#39;196.71&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;408.71&#39; cy=&#39;242.6&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402.04&#39; cy=&#39;317.38&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.79&#39; cy=&#39;345.36&#39; r=&#39;5&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_0_0.5&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-19.46&#39; cy=&#39;-14.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.1&#39; cy=&#39;34.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.69&#39; cy=&#39;110.52&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-5.12&#39; cy=&#39;152.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-11.4&#39; cy=&#39;183.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-0.2&#39; cy=&#39;210.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.67&#39; cy=&#39;238.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.72&#39; cy=&#39;318.63&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.46&#39; cy=&#39;385.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.73&#39; cy=&#39;62.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.82&#39; cy=&#39;188.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.99&#39; cy=&#39;301.56&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;33.26&#39; cy=&#39;24.45&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.04&#39; cy=&#39;58.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.33&#39; cy=&#39;104.7&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;31.67&#39; cy=&#39;140.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.98&#39; cy=&#39;231.13&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;21&#39; cy=&#39;260.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.73&#39; cy=&#39;322.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.24&#39; cy=&#39;348.84&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.06&#39; cy=&#39;377.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.85&#39; cy=&#39;7.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;59.26&#39; cy=&#39;207.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.61&#39; cy=&#39;262.78&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.31&#39; cy=&#39;294.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.15&#39; cy=&#39;360.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.85&#39; cy=&#39;407.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.04&#39; cy=&#39;35.75&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.55&#39; cy=&#39;75.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.08&#39; cy=&#39;121.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;64.69&#39; cy=&#39;169.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.46&#39; cy=&#39;235.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;65.73&#39; cy=&#39;330.7&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.11&#39; cy=&#39;-9.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.69&#39; cy=&#39;63.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.02&#39; cy=&#39;93.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.58&#39; cy=&#39;193.68&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;87.57&#39; cy=&#39;259.52&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.02&#39; cy=&#39;282.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.62&#39; cy=&#39;311.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.91&#39; cy=&#39;342.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.11&#39; cy=&#39;390.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;101.12&#39; cy=&#39;144.76&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.11&#39; cy=&#39;233.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.8&#39; cy=&#39;266.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.99&#39; cy=&#39;369.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.1&#39; cy=&#39;-19.19&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.6&#39; cy=&#39;18.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.53&#39; cy=&#39;49.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.47&#39; cy=&#39;78.48&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.61&#39; cy=&#39;104.5&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.67&#39; cy=&#39;133.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.56&#39; cy=&#39;170.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;139.58&#39; cy=&#39;246.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;122.53&#39; cy=&#39;306.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.32&#39; cy=&#39;351.16&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.1&#39; cy=&#39;380.81&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.6&#39; cy=&#39;418.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.95&#39; cy=&#39;126.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.13&#39; cy=&#39;219.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.25&#39; cy=&#39;328.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.88&#39; cy=&#39;-6.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.83&#39; cy=&#39;51.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.41&#39; cy=&#39;92.78&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.45&#39; cy=&#39;182.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;174.78&#39; cy=&#39;232.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.26&#39; cy=&#39;270.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.73&#39; cy=&#39;298.93&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.18&#39; cy=&#39;355.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.88&#39; cy=&#39;393.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;196.96&#39; cy=&#39;77.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.9&#39; cy=&#39;118.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183&#39; cy=&#39;158.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.63&#39; cy=&#39;193.79&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;190.56&#39; cy=&#39;259.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.67&#39; cy=&#39;329.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.75&#39; cy=&#39;-17.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.68&#39; cy=&#39;17.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.5&#39; cy=&#39;142.81&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;205.56&#39; cy=&#39;223.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.04&#39; cy=&#39;297.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.56&#39; cy=&#39;354.53&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.75&#39; cy=&#39;382.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.68&#39; cy=&#39;417.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.01&#39; cy=&#39;12.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;224.39&#39; cy=&#39;55.91&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;220.95&#39; cy=&#39;82.08&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.82&#39; cy=&#39;113.68&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;226.91&#39; cy=&#39;172.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235.62&#39; cy=&#39;217.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.76&#39; cy=&#39;290.87&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.01&#39; cy=&#39;412.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;249.48&#39; cy=&#39;77.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.44&#39; cy=&#39;181.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;245.9&#39; cy=&#39;250.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.43&#39; cy=&#39;328.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.41&#39; cy=&#39;370.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.01&#39; cy=&#39;33.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.39&#39; cy=&#39;62.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.93&#39; cy=&#39;94.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.87&#39; cy=&#39;120.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.54&#39; cy=&#39;157.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.37&#39; cy=&#39;212.16&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.35&#39; cy=&#39;247.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.25&#39; cy=&#39;278.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.4&#39; cy=&#39;301.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.14&#39; cy=&#39;-6.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;299.77&#39; cy=&#39;46.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;295.34&#39; cy=&#39;146.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.11&#39; cy=&#39;196.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;283.6&#39; cy=&#39;331.56&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;293.84&#39; cy=&#39;365.27&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.14&#39; cy=&#39;393.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;316.2&#39; cy=&#39;21.27&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.63&#39; cy=&#39;95.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.02&#39; cy=&#39;118.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.23&#39; cy=&#39;183.36&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;302.99&#39; cy=&#39;248.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.58&#39; cy=&#39;280.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.56&#39; cy=&#39;309.64&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.23&#39; cy=&#39;-4.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;338.08&#39; cy=&#39;44.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.35&#39; cy=&#39;69.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;323.15&#39; cy=&#39;152.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;339.48&#39; cy=&#39;205.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.25&#39; cy=&#39;233.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.28&#39; cy=&#39;275.24&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.2&#39; cy=&#39;322.63&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.12&#39; cy=&#39;350.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.23&#39; cy=&#39;395.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.02&#39; cy=&#39;17.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.34&#39; cy=&#39;88.63&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;344.5&#39; cy=&#39;131.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.31&#39; cy=&#39;160.67&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.71&#39; cy=&#39;373.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.02&#39; cy=&#39;417.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;375.95&#39; cy=&#39;78.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.42&#39; cy=&#39;205.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.96&#39; cy=&#39;268.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;361.56&#39; cy=&#39;292.78&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;375.89&#39; cy=&#39;346.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.54&#39; cy=&#39;-14.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.9&#39; cy=&#39;34.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.31&#39; cy=&#39;110.52&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;394.88&#39; cy=&#39;152.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;388.6&#39; cy=&#39;183.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;399.8&#39; cy=&#39;210.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.33&#39; cy=&#39;238.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.28&#39; cy=&#39;318.63&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.54&#39; cy=&#39;385.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.73&#39; cy=&#39;62.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.82&#39; cy=&#39;188.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.99&#39; cy=&#39;301.56&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_22.5_0.5&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-7.23&#39; cy=&#39;2.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-6.76&#39; cy=&#39;36.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.34&#39; cy=&#39;156.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.64&#39; cy=&#39;219.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.75&#39; cy=&#39;361.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.23&#39; cy=&#39;402.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.77&#39; cy=&#39;-17.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.41&#39; cy=&#39;62.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.52&#39; cy=&#39;97.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.05&#39; cy=&#39;127.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.59&#39; cy=&#39;188.07&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.61&#39; cy=&#39;260.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.47&#39; cy=&#39;306.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3.81&#39; cy=&#39;340.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.77&#39; cy=&#39;382.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;21.27&#39; cy=&#39;12.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.69&#39; cy=&#39;41.36&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;34.84&#39; cy=&#39;75.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;34.13&#39; cy=&#39;110.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.14&#39; cy=&#39;185.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.65&#39; cy=&#39;219.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;33.91&#39; cy=&#39;294.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.72&#39; cy=&#39;343.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;21.27&#39; cy=&#39;412.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.68&#39; cy=&#39;-0.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;46.45&#39; cy=&#39;148.25&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;42&#39; cy=&#39;242.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.2&#39; cy=&#39;273.01&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.68&#39; cy=&#39;399.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.09&#39; cy=&#39;49.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;64.38&#39; cy=&#39;97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;65.61&#39; cy=&#39;178.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;72.45&#39; cy=&#39;200.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.53&#39; cy=&#39;237.07&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;64.23&#39; cy=&#39;325.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.98&#39; cy=&#39;362.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.29&#39; cy=&#39;-4.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.37&#39; cy=&#39;32.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;92.11&#39; cy=&#39;83.74&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.91&#39; cy=&#39;151.75&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.69&#39; cy=&#39;295.41&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.21&#39; cy=&#39;357.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.29&#39; cy=&#39;395.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.73&#39; cy=&#39;-16.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;112.5&#39; cy=&#39;110.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.61&#39; cy=&#39;167.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.79&#39; cy=&#39;202.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.51&#39; cy=&#39;232.62&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.74&#39; cy=&#39;266.55&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.05&#39; cy=&#39;331.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.73&#39; cy=&#39;383.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.75&#39; cy=&#39;39.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138.02&#39; cy=&#39;75.16&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;135.07&#39; cy=&#39;136.78&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.65&#39; cy=&#39;254.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.53&#39; cy=&#39;305.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;130.68&#39; cy=&#39;356.5&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;151.34&#39; cy=&#39;24.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.62&#39; cy=&#39;107.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;146.66&#39; cy=&#39;189.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.83&#39; cy=&#39;276.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.95&#39; cy=&#39;332.27&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.33&#39; cy=&#39;366.91&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.01&#39; cy=&#39;-3.93&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;172.98&#39; cy=&#39;58.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;175.29&#39; cy=&#39;90.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;172.92&#39; cy=&#39;118.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;164.64&#39; cy=&#39;143.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.32&#39; cy=&#39;225.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;179.98&#39; cy=&#39;323.54&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.01&#39; cy=&#39;396.07&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;182.27&#39; cy=&#39;174.38&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.94&#39; cy=&#39;206.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.76&#39; cy=&#39;251.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.8&#39; cy=&#39;299.68&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.97&#39; cy=&#39;367.84&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.29&#39; cy=&#39;6.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.05&#39; cy=&#39;34.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.84&#39; cy=&#39;64.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.54&#39; cy=&#39;93.87&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;201.34&#39; cy=&#39;130.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;212.54&#39; cy=&#39;172.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.22&#39; cy=&#39;226.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.68&#39; cy=&#39;280.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;201.75&#39; cy=&#39;328.27&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.29&#39; cy=&#39;406.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.33&#39; cy=&#39;29.79&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.64&#39; cy=&#39;113.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.53&#39; cy=&#39;257.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.15&#39; cy=&#39;322.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.41&#39; cy=&#39;356.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;244.41&#39; cy=&#39;-15.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.84&#39; cy=&#39;39.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.06&#39; cy=&#39;63.24&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.67&#39; cy=&#39;145.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;244.29&#39; cy=&#39;186.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.81&#39; cy=&#39;217.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.18&#39; cy=&#39;278.91&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;255.46&#39; cy=&#39;302.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.59&#39; cy=&#39;347.25&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;244.41&#39; cy=&#39;384.08&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;260.12&#39; cy=&#39;100.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.45&#39; cy=&#39;167.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.6&#39; cy=&#39;213.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.24&#39; cy=&#39;247.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;286.73&#39; cy=&#39;-11.74&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.06&#39; cy=&#39;24.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;281.11&#39; cy=&#39;58.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.48&#39; cy=&#39;103.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;287.79&#39; cy=&#39;134.75&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;286.62&#39; cy=&#39;263.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;299.15&#39; cy=&#39;291.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.69&#39; cy=&#39;338.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;286.73&#39; cy=&#39;388.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;313.65&#39; cy=&#39;60.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.99&#39; cy=&#39;132.45&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;303.78&#39; cy=&#39;159.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;313.18&#39; cy=&#39;184.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.64&#39; cy=&#39;214.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.07&#39; cy=&#39;371.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.6&#39; cy=&#39;4.54&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;329.98&#39; cy=&#39;35.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;323.3&#39; cy=&#39;86.89&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.58&#39; cy=&#39;242.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.92&#39; cy=&#39;290.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;326.2&#39; cy=&#39;325.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;338.63&#39; cy=&#39;353.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.6&#39; cy=&#39;404.54&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.98&#39; cy=&#39;-17.95&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358&#39; cy=&#39;45.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.37&#39; cy=&#39;108.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.06&#39; cy=&#39;172.45&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.19&#39; cy=&#39;212.64&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.98&#39; cy=&#39;382.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.83&#39; cy=&#39;15.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;372.88&#39; cy=&#39;73.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;372.06&#39; cy=&#39;135.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.56&#39; cy=&#39;189.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;376.58&#39; cy=&#39;255.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.06&#39; cy=&#39;284.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.18&#39; cy=&#39;328.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.83&#39; cy=&#39;415.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.77&#39; cy=&#39;2.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;393.24&#39; cy=&#39;36.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.66&#39; cy=&#39;156.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.36&#39; cy=&#39;219.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.25&#39; cy=&#39;361.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.77&#39; cy=&#39;402.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.77&#39; cy=&#39;-17.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.41&#39; cy=&#39;62.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.52&#39; cy=&#39;97.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.05&#39; cy=&#39;127.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.59&#39; cy=&#39;188.07&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.61&#39; cy=&#39;260.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.47&#39; cy=&#39;306.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;403.81&#39; cy=&#39;340.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.77&#39; cy=&#39;382.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_45_0.5&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-2.45&#39; cy=&#39;5.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.77&#39; cy=&#39;59.36&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.74&#39; cy=&#39;83.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.58&#39; cy=&#39;111.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.99&#39; cy=&#39;175&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-2.59&#39; cy=&#39;204.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-10.16&#39; cy=&#39;323.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-2.45&#39; cy=&#39;405.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;15&#39; cy=&#39;54.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;12.67&#39; cy=&#39;142.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;15.34&#39; cy=&#39;178.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.66&#39; cy=&#39;238.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;13.57&#39; cy=&#39;267.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2.49&#39; cy=&#39;293.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;7.77&#39; cy=&#39;345.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2.13&#39; cy=&#39;376.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;30.79&#39; cy=&#39;20.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.2&#39; cy=&#39;96.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;34.68&#39; cy=&#39;124&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;30.29&#39; cy=&#39;219.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.14&#39; cy=&#39;312.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;30.94&#39; cy=&#39;378.52&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.15&#39; cy=&#39;1.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49.51&#39; cy=&#39;64.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.44&#39; cy=&#39;148.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.21&#39; cy=&#39;179.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.52&#39; cy=&#39;242.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.12&#39; cy=&#39;288&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.9&#39; cy=&#39;328.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.38&#39; cy=&#39;366.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.15&#39; cy=&#39;401.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.93&#39; cy=&#39;37.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.68&#39; cy=&#39;116.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;75.87&#39; cy=&#39;200.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.58&#39; cy=&#39;9.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.52&#39; cy=&#39;64.53&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.11&#39; cy=&#39;94.84&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.09&#39; cy=&#39;145.42&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;85.77&#39; cy=&#39;173.76&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.9&#39; cy=&#39;244.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;94.18&#39; cy=&#39;276.38&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.77&#39; cy=&#39;310.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.58&#39; cy=&#39;409.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.11&#39; cy=&#39;40.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;115.95&#39; cy=&#39;120.27&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.3&#39; cy=&#39;158.48&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.43&#39; cy=&#39;210.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.59&#39; cy=&#39;309.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.93&#39; cy=&#39;357.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.61&#39; cy=&#39;-12.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.35&#39; cy=&#39;17.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.42&#39; cy=&#39;75.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.04&#39; cy=&#39;282.53&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;135.63&#39; cy=&#39;330.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.61&#39; cy=&#39;387.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.35&#39; cy=&#39;417.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.4&#39; cy=&#39;34.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.88&#39; cy=&#39;76.08&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.63&#39; cy=&#39;120.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;140.14&#39; cy=&#39;148.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;149.45&#39; cy=&#39;178.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;143.03&#39; cy=&#39;218.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.52&#39; cy=&#39;248.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.19&#39; cy=&#39;2.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.01&#39; cy=&#39;54.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.84&#39; cy=&#39;125.84&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.4&#39; cy=&#39;154.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.38&#39; cy=&#39;243.64&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.33&#39; cy=&#39;285.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.82&#39; cy=&#39;329.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.47&#39; cy=&#39;368.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.19&#39; cy=&#39;402.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;182.27&#39; cy=&#39;26.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.98&#39; cy=&#39;98.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.15&#39; cy=&#39;207.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;195.78&#39; cy=&#39;296.76&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.64&#39; cy=&#39;-17.64&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.91&#39; cy=&#39;35.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;203.9&#39; cy=&#39;72.93&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.56&#39; cy=&#39;166.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;218.71&#39; cy=&#39;192.46&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;219.24&#39; cy=&#39;229.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.31&#39; cy=&#39;267.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.39&#39; cy=&#39;320.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;201.92&#39; cy=&#39;347.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.64&#39; cy=&#39;382.36&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.68&#39; cy=&#39;7.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.8&#39; cy=&#39;84.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.53&#39; cy=&#39;109.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.91&#39; cy=&#39;143.21&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;229.75&#39; cy=&#39;258.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.03&#39; cy=&#39;280.55&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.35&#39; cy=&#39;350.79&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.68&#39; cy=&#39;407.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;257.7&#39; cy=&#39;45.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;253.02&#39; cy=&#39;133.19&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.35&#39; cy=&#39;195.12&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;253.89&#39; cy=&#39;315.48&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.35&#39; cy=&#39;376.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.63&#39; cy=&#39;-0.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.63&#39; cy=&#39;23.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.27&#39; cy=&#39;67.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.47&#39; cy=&#39;97.77&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.9&#39; cy=&#39;174.33&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.19&#39; cy=&#39;225.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.78&#39; cy=&#39;279.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.63&#39; cy=&#39;399.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;286.96&#39; cy=&#39;127.75&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.67&#39; cy=&#39;222.74&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.72&#39; cy=&#39;256.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;296.38&#39; cy=&#39;295.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;286.04&#39; cy=&#39;349.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.57&#39; cy=&#39;12.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.75&#39; cy=&#39;97.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.28&#39; cy=&#39;126.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;316.39&#39; cy=&#39;165.82&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;308.25&#39; cy=&#39;194.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.71&#39; cy=&#39;248.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.43&#39; cy=&#39;320.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.39&#39; cy=&#39;375.46&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.57&#39; cy=&#39;412.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;325.05&#39; cy=&#39;39.29&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.71&#39; cy=&#39;72.95&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.33&#39; cy=&#39;100.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.43&#39; cy=&#39;213.25&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.16&#39; cy=&#39;285.01&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.22&#39; cy=&#39;346.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.14&#39; cy=&#39;370.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.81&#39; cy=&#39;0.95&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;349.53&#39; cy=&#39;56.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;357.87&#39; cy=&#39;82.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.4&#39; cy=&#39;128.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.4&#39; cy=&#39;157.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.78&#39; cy=&#39;185.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;349.13&#39; cy=&#39;259.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.6&#39; cy=&#39;312.62&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.85&#39; cy=&#39;343.6&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.81&#39; cy=&#39;400.95&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.24&#39; cy=&#39;27.83&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;372.78&#39; cy=&#39;141.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.6&#39; cy=&#39;227.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.21&#39; cy=&#39;292.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.53&#39; cy=&#39;366.55&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;397.55&#39; cy=&#39;5.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.23&#39; cy=&#39;59.36&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.26&#39; cy=&#39;83.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.42&#39; cy=&#39;111.65&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.01&#39; cy=&#39;175&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;397.41&#39; cy=&#39;204.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;389.84&#39; cy=&#39;323.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;397.55&#39; cy=&#39;405.85&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;415&#39; cy=&#39;54.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;412.67&#39; cy=&#39;142.17&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;415.34&#39; cy=&#39;178.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.66&#39; cy=&#39;238.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;413.57&#39; cy=&#39;267.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402.49&#39; cy=&#39;293.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;407.77&#39; cy=&#39;345.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402.13&#39; cy=&#39;376.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_67.5_0.5&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-4.06&#39; cy=&#39;0.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-2.75&#39; cy=&#39;41.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.5&#39; cy=&#39;70.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-12.38&#39; cy=&#39;109.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.04&#39; cy=&#39;259.01&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-14.17&#39; cy=&#39;317.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.06&#39; cy=&#39;400.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.05&#39; cy=&#39;136.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;7.78&#39; cy=&#39;170.46&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;11.5&#39; cy=&#39;200.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;16.41&#39; cy=&#39;236.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.14&#39; cy=&#39;265.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1.59&#39; cy=&#39;293.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.1&#39; cy=&#39;-18.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;34.62&#39; cy=&#39;60.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;22.43&#39; cy=&#39;109.57&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.91&#39; cy=&#39;133.79&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.66&#39; cy=&#39;310.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.47&#39; cy=&#39;339.46&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.1&#39; cy=&#39;381.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;53.03&#39; cy=&#39;16.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.42&#39; cy=&#39;98.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.57&#39; cy=&#39;186.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.96&#39; cy=&#39;212.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;50.78&#39; cy=&#39;254.38&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.67&#39; cy=&#39;334.52&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;53.03&#39; cy=&#39;416.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.22&#39; cy=&#39;155.01&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.64&#39; cy=&#39;231.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;62.26&#39; cy=&#39;284.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.52&#39; cy=&#39;374.16&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.96&#39; cy=&#39;3.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.03&#39; cy=&#39;49.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.13&#39; cy=&#39;84.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.67&#39; cy=&#39;120.11&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.63&#39; cy=&#39;155.45&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.73&#39; cy=&#39;204.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;99.21&#39; cy=&#39;245.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.68&#39; cy=&#39;285.76&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.91&#39; cy=&#39;323.67&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.96&#39; cy=&#39;403.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.58&#39; cy=&#39;-4.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.4&#39; cy=&#39;32.48&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;112.78&#39; cy=&#39;139.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;119.71&#39; cy=&#39;186.69&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;119.05&#39; cy=&#39;302.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.21&#39; cy=&#39;359.95&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.58&#39; cy=&#39;395.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.84&#39; cy=&#39;70.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.9&#39; cy=&#39;112.81&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;127.68&#39; cy=&#39;225.55&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.67&#39; cy=&#39;363.21&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;155.86&#39; cy=&#39;-1.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.58&#39; cy=&#39;22.78&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.37&#39; cy=&#39;116.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;140.16&#39; cy=&#39;158.44&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;148.33&#39; cy=&#39;199.18&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.98&#39; cy=&#39;240.22&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;141.21&#39; cy=&#39;273.38&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.59&#39; cy=&#39;326.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;155.86&#39; cy=&#39;398.41&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.05&#39; cy=&#39;61.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.98&#39; cy=&#39;141.25&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;170.04&#39; cy=&#39;169.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;179.15&#39; cy=&#39;206.31&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.48&#39; cy=&#39;287.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;182.15&#39; cy=&#39;-1.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.69&#39; cy=&#39;28.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;192.55&#39; cy=&#39;61.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.89&#39; cy=&#39;103.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.44&#39; cy=&#39;146.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;187.89&#39; cy=&#39;236.02&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.87&#39; cy=&#39;268.03&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;198.25&#39; cy=&#39;318.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.65&#39; cy=&#39;356.05&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;182.15&#39; cy=&#39;398.7&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.85&#39; cy=&#39;89.97&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;215.11&#39; cy=&#39;176.73&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;216.7&#39; cy=&#39;217.09&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.78&#39; cy=&#39;-19.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.46&#39; cy=&#39;18.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;225.12&#39; cy=&#39;62.55&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.11&#39; cy=&#39;118.2&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;220.99&#39; cy=&#39;145.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.07&#39; cy=&#39;260.79&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.24&#39; cy=&#39;289.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.4&#39; cy=&#39;325.96&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.52&#39; cy=&#39;354.37&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.78&#39; cy=&#39;380.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.46&#39; cy=&#39;418.15&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.02&#39; cy=&#39;46.54&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;243.01&#39; cy=&#39;93.5&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;249.66&#39; cy=&#39;142.47&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;241.84&#39; cy=&#39;188.5&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;248.98&#39; cy=&#39;305.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.75&#39; cy=&#39;-9.74&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.31&#39; cy=&#39;17.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;266.12&#39; cy=&#39;118.75&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.12&#39; cy=&#39;188.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.35&#39; cy=&#39;230.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.78&#39; cy=&#39;261.94&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;266.56&#39; cy=&#39;354.7&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.75&#39; cy=&#39;390.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.31&#39; cy=&#39;417.92&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;293.28&#39; cy=&#39;69.16&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;296.71&#39; cy=&#39;107.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.75&#39; cy=&#39;157.26&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.85&#39; cy=&#39;229.71&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.48&#39; cy=&#39;265.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.1&#39; cy=&#39;309.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;289.86&#39; cy=&#39;336.86&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.66&#39; cy=&#39;30.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.6&#39; cy=&#39;195.25&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;303.68&#39; cy=&#39;374.87&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.94&#39; cy=&#39;11.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;327.89&#39; cy=&#39;72.9&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.35&#39; cy=&#39;116.48&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;333.92&#39; cy=&#39;142.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.19&#39; cy=&#39;175.64&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.26&#39; cy=&#39;235.4&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;325.35&#39; cy=&#39;263.66&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.17&#39; cy=&#39;305.06&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;331.77&#39; cy=&#39;338.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;329.71&#39; cy=&#39;361.38&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.94&#39; cy=&#39;411.43&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.02&#39; cy=&#39;-15.49&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.12&#39; cy=&#39;43.59&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.11&#39; cy=&#39;111.8&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.35&#39; cy=&#39;201.76&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;353.94&#39; cy=&#39;265.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.57&#39; cy=&#39;323.7&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.02&#39; cy=&#39;384.51&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.52&#39; cy=&#39;26.28&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.58&#39; cy=&#39;74.23&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;361.35&#39; cy=&#39;142.13&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;366.24&#39; cy=&#39;180.39&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.3&#39; cy=&#39;228.34&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.33&#39; cy=&#39;298.32&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.91&#39; cy=&#39;370.45&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.94&#39; cy=&#39;0.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;397.25&#39; cy=&#39;41.58&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.5&#39; cy=&#39;70.98&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;387.62&#39; cy=&#39;109.3&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.96&#39; cy=&#39;259.01&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;385.83&#39; cy=&#39;317.72&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.94&#39; cy=&#39;400.14&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.05&#39; cy=&#39;136.35&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;407.78&#39; cy=&#39;170.46&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;411.5&#39; cy=&#39;200.88&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;416.41&#39; cy=&#39;236.99&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.14&#39; cy=&#39;265.1&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;401.59&#39; cy=&#39;293.61&#39; r=&#39;10&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_0_0.95&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-6.29&#39; cy=&#39;218.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.01&#39; cy=&#39;332.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.24&#39; cy=&#39;-18.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;11.51&#39; cy=&#39;25.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.32&#39; cy=&#39;71.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;8.69&#39; cy=&#39;103.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;18.27&#39; cy=&#39;133.35&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;6.75&#39; cy=&#39;159.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;10.65&#39; cy=&#39;182.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.02&#39; cy=&#39;265.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;11.29&#39; cy=&#39;302.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;0.24&#39; cy=&#39;381.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.88&#39; cy=&#39;-0.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.75&#39; cy=&#39;214.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.49&#39; cy=&#39;243.35&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.49&#39; cy=&#39;318.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.37&#39; cy=&#39;348.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.88&#39; cy=&#39;399.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.93&#39; cy=&#39;-5.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;55.57&#39; cy=&#39;22.97&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;43.82&#39; cy=&#39;50.97&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.15&#39; cy=&#39;89.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;41.05&#39; cy=&#39;112.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.29&#39; cy=&#39;171.94&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.42&#39; cy=&#39;227.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.54&#39; cy=&#39;279.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.07&#39; cy=&#39;340.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.93&#39; cy=&#39;394.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.11&#39; cy=&#39;107.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.3&#39; cy=&#39;133.28&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;78.1&#39; cy=&#39;266.44&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60&#39; cy=&#39;318.31&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.44&#39; cy=&#39;11.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.28&#39; cy=&#39;51.94&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.64&#39; cy=&#39;170.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.64&#39; cy=&#39;198.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.8&#39; cy=&#39;232.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.58&#39; cy=&#39;310.23&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.44&#39; cy=&#39;374.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.44&#39; cy=&#39;411.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.72&#39; cy=&#39;-0.67&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.59&#39; cy=&#39;41.64&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;108.22&#39; cy=&#39;84.65&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;101.21&#39; cy=&#39;134.8&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.57&#39; cy=&#39;213.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;119.18&#39; cy=&#39;245.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;117.41&#39; cy=&#39;278.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.92&#39; cy=&#39;338.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.88&#39; cy=&#39;363.97&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.72&#39; cy=&#39;399.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.91&#39; cy=&#39;60.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;129.63&#39; cy=&#39;149.5&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;130.09&#39; cy=&#39;181.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.08&#39; cy=&#39;321.32&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.3&#39; cy=&#39;-1.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.71&#39; cy=&#39;22.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;145.27&#39; cy=&#39;101.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.99&#39; cy=&#39;175.94&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;154.84&#39; cy=&#39;259.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;145.59&#39; cy=&#39;293.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;151.32&#39; cy=&#39;359.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.3&#39; cy=&#39;398.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.32&#39; cy=&#39;61.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;175.25&#39; cy=&#39;94.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;166.66&#39; cy=&#39;140.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;177.63&#39; cy=&#39;197.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.97&#39; cy=&#39;221.67&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.11&#39; cy=&#39;297.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.52&#39; cy=&#39;-18.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.8&#39; cy=&#39;37.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.1&#39; cy=&#39;221.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;192.43&#39; cy=&#39;260.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.07&#39; cy=&#39;323.6&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.52&#39; cy=&#39;381.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.94&#39; cy=&#39;24.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.7&#39; cy=&#39;56.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.26&#39; cy=&#39;90.62&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.76&#39; cy=&#39;121.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.47&#39; cy=&#39;164.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;201.02&#39; cy=&#39;198.15&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;208.78&#39; cy=&#39;292.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.57&#39; cy=&#39;363.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.68&#39; cy=&#39;-16.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.17&#39; cy=&#39;111.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.06&#39; cy=&#39;144.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.78&#39; cy=&#39;183.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235.05&#39; cy=&#39;243.63&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;224.4&#39; cy=&#39;337.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;232.68&#39; cy=&#39;383.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.76&#39; cy=&#39;8.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;247.44&#39; cy=&#39;59.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.85&#39; cy=&#39;82.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.8&#39; cy=&#39;218.31&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;252.25&#39; cy=&#39;277.05&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.93&#39; cy=&#39;320.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;256.84&#39; cy=&#39;366.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.76&#39; cy=&#39;408.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.94&#39; cy=&#39;-6.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.46&#39; cy=&#39;50.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;275.18&#39; cy=&#39;103.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;260.37&#39; cy=&#39;127.79&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.07&#39; cy=&#39;171.05&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;274.49&#39; cy=&#39;209.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.94&#39; cy=&#39;393.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;290.19&#39; cy=&#39;21.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;295.04&#39; cy=&#39;71.41&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;292.4&#39; cy=&#39;146.28&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.65&#39; cy=&#39;183.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;280.55&#39; cy=&#39;247.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.67&#39; cy=&#39;275.97&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.79&#39; cy=&#39;315.64&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.38&#39; cy=&#39;350.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.31&#39; cy=&#39;39.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.03&#39; cy=&#39;117.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.69&#39; cy=&#39;163.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.87&#39; cy=&#39;200.65&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.19&#39; cy=&#39;343.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;301.35&#39; cy=&#39;373.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.59&#39; cy=&#39;-8.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.67&#39; cy=&#39;72.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.9&#39; cy=&#39;139.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;329.08&#39; cy=&#39;233.53&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.99&#39; cy=&#39;272.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.57&#39; cy=&#39;302.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;336.59&#39; cy=&#39;391.64&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.84&#39; cy=&#39;28.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.73&#39; cy=&#39;108.04&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;350.2&#39; cy=&#39;149.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.16&#39; cy=&#39;181.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.26&#39; cy=&#39;235.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.84&#39; cy=&#39;318.72&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.94&#39; cy=&#39;342.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;366&#39; cy=&#39;-19.92&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.58&#39; cy=&#39;29.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;372.79&#39; cy=&#39;68.9&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.29&#39; cy=&#39;132.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.98&#39; cy=&#39;165.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.78&#39; cy=&#39;197.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.85&#39; cy=&#39;269.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;370.73&#39; cy=&#39;299.8&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;366&#39; cy=&#39;380.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;393.71&#39; cy=&#39;218.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.99&#39; cy=&#39;332.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.24&#39; cy=&#39;-18.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;411.51&#39; cy=&#39;25.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.32&#39; cy=&#39;71.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;408.69&#39; cy=&#39;103.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.27&#39; cy=&#39;133.35&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;406.75&#39; cy=&#39;159.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;410.65&#39; cy=&#39;182.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.02&#39; cy=&#39;265.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;411.29&#39; cy=&#39;302.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;400.24&#39; cy=&#39;381.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_22.5_0.95&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-9.86&#39; cy=&#39;182.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-15.99&#39; cy=&#39;213.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.19&#39; cy=&#39;317.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-12.25&#39; cy=&#39;377.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.11&#39; cy=&#39;18.47&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.26&#39; cy=&#39;41.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4.45&#39; cy=&#39;71.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5.45&#39; cy=&#39;129.41&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;16.34&#39; cy=&#39;218.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1.83&#39; cy=&#39;268.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2.63&#39; cy=&#39;340.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;9.11&#39; cy=&#39;418.47&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.4&#39; cy=&#39;108.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.75&#39; cy=&#39;167.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;39.53&#39; cy=&#39;199.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;27.49&#39; cy=&#39;244&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.31&#39; cy=&#39;314.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.58&#39; cy=&#39;370.83&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.44&#39; cy=&#39;-19.44&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.56&#39; cy=&#39;8.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;46.49&#39; cy=&#39;43.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;57.64&#39; cy=&#39;74.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.25&#39; cy=&#39;136.53&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.5&#39; cy=&#39;222.68&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;49&#39; cy=&#39;283.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.35&#39; cy=&#39;316.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.94&#39; cy=&#39;347.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;56.44&#39; cy=&#39;380.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.56&#39; cy=&#39;408.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;66.58&#39; cy=&#39;101.23&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.21&#39; cy=&#39;146.04&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;68.45&#39; cy=&#39;185.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;78.56&#39; cy=&#39;220.23&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;70.8&#39; cy=&#39;250.28&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.89&#39; cy=&#39;286.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.32&#39; cy=&#39;2.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.67&#39; cy=&#39;41.64&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;98.14&#39; cy=&#39;76.28&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;87.29&#39; cy=&#39;333.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.71&#39; cy=&#39;369.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;90.32&#39; cy=&#39;402.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.97&#39; cy=&#39;24.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;102.48&#39; cy=&#39;100.62&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.93&#39; cy=&#39;132.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.51&#39; cy=&#39;170.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.82&#39; cy=&#39;197.15&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.19&#39; cy=&#39;234.14&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.57&#39; cy=&#39;277.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.56&#39; cy=&#39;308.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;116.88&#39; cy=&#39;364.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138.75&#39; cy=&#39;-12.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.64&#39; cy=&#39;70.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;135.22&#39; cy=&#39;141&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138.37&#39; cy=&#39;239.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;134.86&#39; cy=&#39;262&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;124.95&#39; cy=&#39;336.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;138.75&#39; cy=&#39;387.63&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.84&#39; cy=&#39;23.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;140.25&#39; cy=&#39;116.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;147.71&#39; cy=&#39;175.65&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;151.82&#39; cy=&#39;212.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;156.44&#39; cy=&#39;300.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;153.51&#39; cy=&#39;349.05&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.75&#39; cy=&#39;5&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;167.32&#39; cy=&#39;67.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;160.22&#39; cy=&#39;95.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.85&#39; cy=&#39;235.65&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.57&#39; cy=&#39;375.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.75&#39; cy=&#39;405&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;193.93&#39; cy=&#39;38.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;190.22&#39; cy=&#39;103.9&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.05&#39; cy=&#39;142.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.56&#39; cy=&#39;173.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;197.85&#39; cy=&#39;205.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.66&#39; cy=&#39;268.22&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.23&#39; cy=&#39;296.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;199.04&#39; cy=&#39;333.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.2&#39; cy=&#39;0.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.11&#39; cy=&#39;66.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.38&#39; cy=&#39;146.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.92&#39; cy=&#39;250.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.29&#39; cy=&#39;374.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;200.2&#39; cy=&#39;400.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;222.44&#39; cy=&#39;29.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.15&#39; cy=&#39;59.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.09&#39; cy=&#39;80.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.79&#39; cy=&#39;109.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.17&#39; cy=&#39;152.83&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;221.44&#39; cy=&#39;188.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.41&#39; cy=&#39;290.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;223.78&#39; cy=&#39;318.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.47&#39; cy=&#39;355.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.55&#39; cy=&#39;-19.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.46&#39; cy=&#39;8.68&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;248.73&#39; cy=&#39;201.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;249.2&#39; cy=&#39;231.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;255.69&#39; cy=&#39;265.64&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.23&#39; cy=&#39;318.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.55&#39; cy=&#39;380.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;250.46&#39; cy=&#39;408.68&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.96&#39; cy=&#39;5.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.55&#39; cy=&#39;40.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;273.22&#39; cy=&#39;112.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.63&#39; cy=&#39;140.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.11&#39; cy=&#39;172.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.56&#39; cy=&#39;210.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.03&#39; cy=&#39;246.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;271.01&#39; cy=&#39;291.42&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.68&#39; cy=&#39;348.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;278.96&#39; cy=&#39;405.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.2&#39; cy=&#39;41.94&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.09&#39; cy=&#39;79.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.27&#39; cy=&#39;144.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.21&#39; cy=&#39;175.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.46&#39; cy=&#39;280.3&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.88&#39; cy=&#39;337.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.36&#39; cy=&#39;360.32&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;319.54&#39; cy=&#39;47.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;314.65&#39; cy=&#39;114.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;304.35&#39; cy=&#39;209.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;313.51&#39; cy=&#39;236.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.48&#39; cy=&#39;311.87&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.21&#39; cy=&#39;6.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.48&#39; cy=&#39;76.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.6&#39; cy=&#39;140.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;339&#39; cy=&#39;186.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.55&#39; cy=&#39;260.62&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.04&#39; cy=&#39;300.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.8&#39; cy=&#39;337.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.99&#39; cy=&#39;360.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.21&#39; cy=&#39;406.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;342.52&#39; cy=&#39;28.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.36&#39; cy=&#39;95.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;352.23&#39; cy=&#39;222.92&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.19&#39; cy=&#39;278.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.44&#39; cy=&#39;346.44&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.28&#39; cy=&#39;377.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.82&#39; cy=&#39;1.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;366.22&#39; cy=&#39;46.41&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.29&#39; cy=&#39;88.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;360.91&#39; cy=&#39;138.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;363.38&#39; cy=&#39;169.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368&#39; cy=&#39;256.44&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;374.07&#39; cy=&#39;286.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;369.54&#39; cy=&#39;326.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.82&#39; cy=&#39;401.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;390.14&#39; cy=&#39;182.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.01&#39; cy=&#39;213.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.81&#39; cy=&#39;317.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;387.75&#39; cy=&#39;377.39&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.11&#39; cy=&#39;18.47&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.26&#39; cy=&#39;41.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;404.45&#39; cy=&#39;71.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.45&#39; cy=&#39;129.41&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;416.34&#39; cy=&#39;218.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;401.83&#39; cy=&#39;268.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402.63&#39; cy=&#39;340.37&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.11&#39; cy=&#39;418.47&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_45_0.95&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-1.86&#39; cy=&#39;-0.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.57&#39; cy=&#39;39.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-0.37&#39; cy=&#39;65.14&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.13&#39; cy=&#39;92.22&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.3&#39; cy=&#39;120.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.58&#39; cy=&#39;164.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.17&#39; cy=&#39;262.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.52&#39; cy=&#39;297.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-8.15&#39; cy=&#39;326.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.7&#39; cy=&#39;365.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.86&#39; cy=&#39;399.42&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.75&#39; cy=&#39;43.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;14.47&#39; cy=&#39;139.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.19&#39; cy=&#39;222.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;15.52&#39; cy=&#39;300.8&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;37.09&#39; cy=&#39;3.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.38&#39; cy=&#39;186.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.61&#39; cy=&#39;263&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;31.21&#39; cy=&#39;345.6&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;37.09&#39; cy=&#39;403.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.14&#39; cy=&#39;29.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.35&#39; cy=&#39;79.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.26&#39; cy=&#39;113.92&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;46.32&#39; cy=&#39;143.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.18&#39; cy=&#39;196.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;50.08&#39; cy=&#39;230.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;59.92&#39; cy=&#39;259.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.18&#39; cy=&#39;282.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.15&#39; cy=&#39;313.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;44.44&#39; cy=&#39;373.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;72.38&#39; cy=&#39;5.25&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.31&#39; cy=&#39;63.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74.21&#39; cy=&#39;101.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.48&#39; cy=&#39;164.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;76.47&#39; cy=&#39;372.72&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;72.38&#39; cy=&#39;405.25&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.72&#39; cy=&#39;37.9&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;88.18&#39; cy=&#39;204.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.46&#39; cy=&#39;248.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.08&#39; cy=&#39;289.72&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.74&#39; cy=&#39;344.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.71&#39; cy=&#39;43.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;118.18&#39; cy=&#39;76.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;109.96&#39; cy=&#39;137.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.22&#39; cy=&#39;162.35&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.17&#39; cy=&#39;-11.71&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.87&#39; cy=&#39;18.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.42&#39; cy=&#39;121.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;130.31&#39; cy=&#39;166.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.06&#39; cy=&#39;199.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.36&#39; cy=&#39;222.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.17&#39; cy=&#39;253.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;137.59&#39; cy=&#39;287.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;125.22&#39; cy=&#39;315.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;126.94&#39; cy=&#39;353.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;123.17&#39; cy=&#39;388.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.87&#39; cy=&#39;418.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;148.1&#39; cy=&#39;29.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;151.17&#39; cy=&#39;57.97&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;147.32&#39; cy=&#39;89.32&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.05&#39; cy=&#39;141.6&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.79&#39; cy=&#39;178.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.84&#39; cy=&#39;329.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.24&#39; cy=&#39;-12.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.4&#39; cy=&#39;15.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;172.45&#39; cy=&#39;106.44&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;168.75&#39; cy=&#39;205.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;172.56&#39; cy=&#39;243.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.98&#39; cy=&#39;287.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;173.79&#39; cy=&#39;358.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.24&#39; cy=&#39;387.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;178.4&#39; cy=&#39;415.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.36&#39; cy=&#39;45.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;191.74&#39; cy=&#39;75.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;198.89&#39; cy=&#39;127.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;189.99&#39; cy=&#39;163.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;196.32&#39; cy=&#39;219.45&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;194.12&#39; cy=&#39;269.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;187.41&#39; cy=&#39;305.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;194.69&#39; cy=&#39;337.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.44&#39; cy=&#39;1.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;210.42&#39; cy=&#39;99.01&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;217.65&#39; cy=&#39;184.63&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.81&#39; cy=&#39;366.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;207.44&#39; cy=&#39;401.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.6&#39; cy=&#39;-14.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.96&#39; cy=&#39;42.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;227.36&#39; cy=&#39;72.95&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.8&#39; cy=&#39;142.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;227.07&#39; cy=&#39;213.82&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235.04&#39; cy=&#39;247.6&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;226.51&#39; cy=&#39;277.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.98&#39; cy=&#39;304.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;230.48&#39; cy=&#39;345.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.6&#39; cy=&#39;385.79&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;244.23&#39; cy=&#39;98.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.62&#39; cy=&#39;187.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;260.31&#39; cy=&#39;-18.14&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.95&#39; cy=&#39;9.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.68&#39; cy=&#39;38.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.04&#39; cy=&#39;74.05&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;272.37&#39; cy=&#39;125.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;268.91&#39; cy=&#39;217.88&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.52&#39; cy=&#39;241.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.88&#39; cy=&#39;272.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.89&#39; cy=&#39;306.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.96&#39; cy=&#39;335.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;260.31&#39; cy=&#39;381.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.95&#39; cy=&#39;409.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;291.26&#39; cy=&#39;57.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;295.67&#39; cy=&#39;150.17&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;285.05&#39; cy=&#39;188.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;294.61&#39; cy=&#39;244.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.77&#39; cy=&#39;298.83&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;298.25&#39; cy=&#39;372.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.73&#39; cy=&#39;30.3&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.35&#39; cy=&#39;72.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.33&#39; cy=&#39;99.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307.01&#39; cy=&#39;215.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;307&#39; cy=&#39;270.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.88&#39; cy=&#39;324.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.11&#39; cy=&#39;-16.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;321.25&#39; cy=&#39;123.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.94&#39; cy=&#39;153.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.65&#39; cy=&#39;184.13&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;334.78&#39; cy=&#39;231.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;324.22&#39; cy=&#39;296.96&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.59&#39; cy=&#39;345.57&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;330.11&#39; cy=&#39;383.51&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.29&#39; cy=&#39;-10.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;345.75&#39; cy=&#39;16.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.72&#39; cy=&#39;45.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;347.3&#39; cy=&#39;75.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;348.6&#39; cy=&#39;106.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;344.87&#39; cy=&#39;270.68&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;355.24&#39; cy=&#39;305.51&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.29&#39; cy=&#39;389.81&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;345.75&#39; cy=&#39;416.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.67&#39; cy=&#39;144.72&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.58&#39; cy=&#39;173.13&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;367&#39; cy=&#39;202.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;372.61&#39; cy=&#39;238.25&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;373.23&#39; cy=&#39;350.07&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.14&#39; cy=&#39;-0.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.43&#39; cy=&#39;39.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;399.63&#39; cy=&#39;65.14&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;381.87&#39; cy=&#39;92.22&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.7&#39; cy=&#39;120.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.42&#39; cy=&#39;164.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.83&#39; cy=&#39;262.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.48&#39; cy=&#39;297.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;391.85&#39; cy=&#39;326.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.3&#39; cy=&#39;365.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.14&#39; cy=&#39;399.42&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.75&#39; cy=&#39;43.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;414.47&#39; cy=&#39;139.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.19&#39; cy=&#39;222.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;415.52&#39; cy=&#39;300.8&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;stipple_67.5_0.95&#34; width=&#34;400&#34; height=&#34;400&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-3.88&#39; cy=&#39;58.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-7.5&#39; cy=&#39;86.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.16&#39; cy=&#39;134.87&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-1.24&#39; cy=&#39;160.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-19.19&#39; cy=&#39;182.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-0.48&#39; cy=&#39;209.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.88&#39; cy=&#39;261.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-12.17&#39; cy=&#39;296.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-5.9&#39; cy=&#39;329.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-16.74&#39; cy=&#39;368.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;8.74&#39; cy=&#39;32.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;17.7&#39; cy=&#39;309.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.15&#39; cy=&#39;-11.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;36.15&#39; cy=&#39;22.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;35.05&#39; cy=&#39;79.63&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;24.31&#39; cy=&#39;125.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;28.23&#39; cy=&#39;172.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.31&#39; cy=&#39;220.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.37&#39; cy=&#39;275.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.72&#39; cy=&#39;340.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;23.15&#39; cy=&#39;388.6&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.72&#39; cy=&#39;48.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;52.96&#39; cy=&#39;107.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.17&#39; cy=&#39;148.86&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;58.64&#39; cy=&#39;177.54&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;46.61&#39; cy=&#39;202.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;47.46&#39; cy=&#39;254.75&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;42.9&#39; cy=&#39;296.85&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;48.08&#39; cy=&#39;374.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.59&#39; cy=&#39;6.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.65&#39; cy=&#39;79.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.83&#39; cy=&#39;209.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;77.03&#39; cy=&#39;248.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;67.6&#39; cy=&#39;275.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;69.55&#39; cy=&#39;321.88&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;79.35&#39; cy=&#39;375.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.59&#39; cy=&#39;406.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.62&#39; cy=&#39;2.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;82.82&#39; cy=&#39;51.58&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;83.91&#39; cy=&#39;100.51&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;97.51&#39; cy=&#39;128.33&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;81.28&#39; cy=&#39;176.02&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;91.42&#39; cy=&#39;340.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.62&#39; cy=&#39;402.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.9&#39; cy=&#39;43.63&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;106.05&#39; cy=&#39;161.69&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;103.55&#39; cy=&#39;208.15&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;106.88&#39; cy=&#39;238.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;106.93&#39; cy=&#39;295.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;112.63&#39; cy=&#39;375.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.49&#39; cy=&#39;18.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;131.22&#39; cy=&#39;84.8&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;136.78&#39; cy=&#39;127.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.75&#39; cy=&#39;258.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.76&#39; cy=&#39;281.05&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;128.89&#39; cy=&#39;347.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.49&#39; cy=&#39;418.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;148.05&#39; cy=&#39;0.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;146.61&#39; cy=&#39;58.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.53&#39; cy=&#39;96.03&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;144.8&#39; cy=&#39;157.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;142.33&#39; cy=&#39;186.36&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;141.78&#39; cy=&#39;225.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;140.79&#39; cy=&#39;312.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;157.46&#39; cy=&#39;349.76&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;148.05&#39; cy=&#39;400.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.37&#39; cy=&#39;29.68&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;175.66&#39; cy=&#39;217.12&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;162.9&#39; cy=&#39;246.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;163.75&#39; cy=&#39;276.82&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.07&#39; cy=&#39;54.28&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;180.9&#39; cy=&#39;97.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.55&#39; cy=&#39;126.47&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.92&#39; cy=&#39;157.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;181.27&#39; cy=&#39;182.11&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;182.64&#39; cy=&#39;313.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;183.16&#39; cy=&#39;371.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.09&#39; cy=&#39;-17.09&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.12&#39; cy=&#39;13.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;212.35&#39; cy=&#39;53.55&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.24&#39; cy=&#39;103.16&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;213.31&#39; cy=&#39;217.9&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;202.47&#39; cy=&#39;252.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;202.85&#39; cy=&#39;287.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;210.13&#39; cy=&#39;323.78&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.47&#39; cy=&#39;352.38&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;209.09&#39; cy=&#39;382.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;211.12&#39; cy=&#39;413.7&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.34&#39; cy=&#39;32.66&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.7&#39; cy=&#39;131.42&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;235&#39; cy=&#39;159.82&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;231.65&#39; cy=&#39;180.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;233.2&#39; cy=&#39;270.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;228.22&#39; cy=&#39;300.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.67&#39; cy=&#39;338.83&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.59&#39; cy=&#39;366.45&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;246.23&#39; cy=&#39;2.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;246.01&#39; cy=&#39;75.4&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;255.36&#39; cy=&#39;109.65&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;259.98&#39; cy=&#39;139.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;248.11&#39; cy=&#39;222.67&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;246.23&#39; cy=&#39;402.43&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.18&#39; cy=&#39;40.95&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;279.13&#39; cy=&#39;72.94&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;277.34&#39; cy=&#39;163.19&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;264.89&#39; cy=&#39;198.79&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;263.09&#39; cy=&#39;256.21&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;265.25&#39; cy=&#39;280.46&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.55&#39; cy=&#39;321.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.94&#39; cy=&#39;374.2&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.54&#39; cy=&#39;18.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;295.18&#39; cy=&#39;44.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;284.26&#39; cy=&#39;106.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;285.15&#39; cy=&#39;139.5&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;295.84&#39; cy=&#39;234.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;299.47&#39; cy=&#39;317.18&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.81&#39; cy=&#39;360.79&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;282.54&#39; cy=&#39;418.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;317.84&#39; cy=&#39;97.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;318.05&#39; cy=&#39;131.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;306.84&#39; cy=&#39;159.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.24&#39; cy=&#39;184.95&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;301.49&#39; cy=&#39;286.62&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.73&#39; cy=&#39;10.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;337.75&#39; cy=&#39;43.67&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;322.08&#39; cy=&#39;68.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;335.17&#39; cy=&#39;154.59&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;326.53&#39; cy=&#39;225.1&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;332.26&#39; cy=&#39;278.52&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;327.28&#39; cy=&#39;301.93&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;323.43&#39; cy=&#39;334.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.73&#39; cy=&#39;410.89&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;350.63&#39; cy=&#39;83.1&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;341.38&#39; cy=&#39;121.98&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;353.25&#39; cy=&#39;189.99&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;346.97&#39; cy=&#39;251.15&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;358.13&#39; cy=&#39;301.13&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;351.05&#39; cy=&#39;362.61&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.84&#39; cy=&#39;-0.73&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;376.94&#39; cy=&#39;24.32&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.99&#39; cy=&#39;49.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;371.14&#39; cy=&#39;105.48&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;367.39&#39; cy=&#39;148.41&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;376.28&#39; cy=&#39;234.34&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;362.93&#39; cy=&#39;336.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.84&#39; cy=&#39;399.27&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.12&#39; cy=&#39;58.56&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;392.5&#39; cy=&#39;86.29&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.84&#39; cy=&#39;134.87&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;398.76&#39; cy=&#39;160.06&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;380.81&#39; cy=&#39;182.08&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;399.52&#39; cy=&#39;209.77&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;395.12&#39; cy=&#39;261.91&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;387.83&#39; cy=&#39;296.84&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;394.1&#39; cy=&#39;329.24&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;383.26&#39; cy=&#39;368.74&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;408.74&#39; cy=&#39;32.26&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
&amp;lt;circle cx=&#39;417.7&#39; cy=&#39;309.49&#39; r=&#39;19&#39; style=&#39;fill: #000000; stroke: #000000; fill-opacity: 1; stroke-opacity: 1&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#stipple_0_0.05);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_22.5_0.05);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_45_0.05);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_67.5_0.05);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_0_0.25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_22.5_0.25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_45_0.25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_67.5_0.25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_0_0.5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_22.5_0.5);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_45_0.5);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_67.5_0.5);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_0_0.95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_22.5_0.95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_45_0.95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#stipple_67.5_0.95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-stipple.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hex-patterns&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Hex patterns&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;hex_0_0.05&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:1.6; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_22.5_0.05&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:1.6; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_45_0.05&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:1.6; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_67.5_0.05&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:1.6; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_0_0.25&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:8; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_22.5_0.25&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:8; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_45_0.25&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:8; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_67.5_0.25&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:8; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_0_0.5&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:16; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_22.5_0.5&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:16; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_45_0.5&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:16; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_67.5_0.5&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:16; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_0_0.95&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:30.4; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_22.5_0.95&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:30.4; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_45_0.95&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:30.4; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;hex_67.5_0.95&#34; width=&#34;34.6410161513775&#34; height=&#34;60&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#000000; stroke-width:30.4; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;0&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;10&#34; x2=&#34;34.6410161513775&#34; y2=&#34;20&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;0&#34; x2=&#34;17.3205080756888&#34; y2=&#34;10&#34; /&amp;gt;
        &amp;lt;line x1=&#34;17.3205080756888&#34; y1=&#34;50&#34; x2=&#34;17.3205080756888&#34; y2=&#34;60&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;20&#34; x2=&#34;0&#34; y2=&#34;40&#34; /&amp;gt;
        &amp;lt;line x1=&#34;34.6410161513775&#34; y1=&#34;20&#34; x2=&#34;34.6410161513775&#34; y2=&#34;40&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#hex_0_0.05);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_22.5_0.05);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_45_0.05);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_67.5_0.05);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_0_0.25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_22.5_0.25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_45_0.25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_67.5_0.25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_0_0.5);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_22.5_0.5);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_45_0.5);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_67.5_0.5);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_0_0.95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_22.5_0.95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_45_0.95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#hex_67.5_0.95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-hex.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;check-patterns&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Check patterns&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;check_0_10&#34; width=&#34;10&#34; height=&#34;10&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;5&#34; y=&#34;5&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_22.5_10&#34; width=&#34;10&#34; height=&#34;10&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;5&#34; y=&#34;5&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_45_10&#34; width=&#34;10&#34; height=&#34;10&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;5&#34; y=&#34;5&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_67.5_10&#34; width=&#34;10&#34; height=&#34;10&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;5&#34; y=&#34;5&#34; width=&#34;5&#34; height=&#34;5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_0_25&#34; width=&#34;25&#34; height=&#34;25&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;12.5&#34; y=&#34;12.5&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_22.5_25&#34; width=&#34;25&#34; height=&#34;25&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;12.5&#34; y=&#34;12.5&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_45_25&#34; width=&#34;25&#34; height=&#34;25&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;12.5&#34; y=&#34;12.5&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_67.5_25&#34; width=&#34;25&#34; height=&#34;25&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;12.5&#34; y=&#34;12.5&#34; width=&#34;12.5&#34; height=&#34;12.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_0_50&#34; width=&#34;50&#34; height=&#34;50&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;25&#34; y=&#34;25&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_22.5_50&#34; width=&#34;50&#34; height=&#34;50&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;25&#34; y=&#34;25&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_45_50&#34; width=&#34;50&#34; height=&#34;50&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;25&#34; y=&#34;25&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_67.5_50&#34; width=&#34;50&#34; height=&#34;50&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;25&#34; y=&#34;25&#34; width=&#34;25&#34; height=&#34;25&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_0_95&#34; width=&#34;95&#34; height=&#34;95&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;47.5&#34; y=&#34;47.5&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_22.5_95&#34; width=&#34;95&#34; height=&#34;95&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;47.5&#34; y=&#34;47.5&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_45_95&#34; width=&#34;95&#34; height=&#34;95&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;47.5&#34; y=&#34;47.5&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;check_67.5_95&#34; width=&#34;95&#34; height=&#34;95&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#000000; fill-opacity:1;&#34; x=&#34;47.5&#34; y=&#34;47.5&#34; width=&#34;47.5&#34; height=&#34;47.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#check_0_10);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_22.5_10);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_45_10);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_67.5_10);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_0_25);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_22.5_25);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_45_25);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_67.5_25);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_0_50);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_22.5_50);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_45_50);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_67.5_50);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_0_95);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_22.5_95);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_45_95);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#check_67.5_95);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-check.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;gradients&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Gradients&lt;/h3&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;400&#34; viewBox=&#34;0 0 800 400&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#ffffff_#aa7733&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#aa7733;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#ffffff_#aa7733&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#aa7733;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#000000_#aa7733&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#aa7733;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#000000_#aa7733&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#aa7733;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#ffffff_#224466&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#224466;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#ffffff_#224466&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#224466;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#000000_#224466&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#224466;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#000000_#224466&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#224466;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#ffffff_#77aa33&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#77aa33;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#ffffff_#77aa33&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#77aa33;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#000000_#77aa33&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#77aa33;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#000000_#77aa33&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#77aa33;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#ffffff_#ffbb99&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffbb99;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#ffffff_#ffbb99&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffffff;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffbb99;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_0_#000000_#ffbb99&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffbb99;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;grad_45_#000000_#ffbb99&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;0%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#000000;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#ffbb99;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#grad_0_#ffffff_#aa7733);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#ffffff_#aa7733);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#000000_#aa7733);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#000000_#aa7733);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#ffffff_#224466);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#ffffff_#224466);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#000000_#224466);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#000000_#224466);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#ffffff_#77aa33);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#ffffff_#77aa33);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#000000_#77aa33);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#000000_#77aa33);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#ffffff_#ffbb99);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#ffffff_#ffbb99);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_0_#000000_#ffbb99);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#grad_45_#000000_#ffbb99);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-gradients.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;encodingdecoding-patterns-from-colours&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Encoding/decoding patterns from colours&lt;/h2&gt;
&lt;p&gt;A key feature of this set of patterns is that they can be encoded in
an RGB colour. Also, every RGB colour (excluding black, white and fully transparent)
can be decoded to a pattern in this library.&lt;/p&gt;
&lt;p&gt;This encoding/decoding is carried out by the &lt;a href=&#34;https://github.com/coolbutuseless/lofi&#34;&gt;&lt;code&gt;lofi&lt;/code&gt;&lt;/a&gt; package.
Because this has to squeeze multiple continuous variables in to 24-bits, along with
the actual colour of the pattern, there
will be some quantization associated with a pattern-encoded-as-RGB e.g. angle may
only be encoded in 45degree increments.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Encode a stripe pattern into a colour. Arguments to set correspond to 
# arguments from the individual pattern creation function 
# e.g. `create_stripe_pattern()`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hex_colour &amp;lt;- encode_pattern_params_as_hex_colour(
  pattern_name = &amp;#39;stripe&amp;#39;, 
  angle = 135,
  fill_fraction = 0.8,
  colour = &amp;#39;darkblue&amp;#39;
)

hex_colour
[1] &amp;quot;#38E702FF&amp;quot;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Decode this hex colour back into a pattern object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pattern &amp;lt;- decode_pattern_from_rgba_vec(lofi::hex_colour_to_rgba_vec(hex_colour))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render the pattern object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc &amp;lt;- pattern$as_full_svg(width = 400, height = 100)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg viewBox=&#34;0 0 400 100&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;simple-38E702FF&#34; width=&#34;17&#34; height=&#34;17&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#0000AA; stroke-width:27.2; stroke-opacity:1;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;17&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#34;fill: url(#simple-38E702FF) #fff;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-encode-as-colour.svg&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;mapping-from-rgb-space-into-pattern-space&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Mapping from RGB Space into Pattern Space&lt;/h3&gt;
&lt;p&gt;Colours in &lt;em&gt;RGB space&lt;/em&gt; do not really map to anything
coherent in &lt;em&gt;pattern space&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The following shows a viridis palette mapped to patterns. Note that patterns
near each other are possibly of similar type e.g. the last 4 patterns
are all checkerboard.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-10-09-svgpatternsimple_files/figure-html/viridis_img-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the patterns corresponding to 32 cividis colours
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
patterns &amp;lt;- viridis::cividis(32) %&amp;gt;%
  lapply(lofi::hex_colour_to_rgba_vec) %&amp;gt;%
  lapply(decode_pattern_from_rgba_vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;details closed&gt;&lt;summary&gt; Show SVG text (click to open) &lt;/summary&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&amp;gt;
&amp;lt;svg width=&#34;800&#34; height=&#34;800&#34; viewBox=&#34;0 0 800 800&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; xmlns:xlink=&#34;http://www.w3.org/1999/xlink&#34;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;pattern id=&#34;simple-00204DFF&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#00819B; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-00265AFF&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#0099B5; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-002C69FF&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#00B1D3; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-00316FFF&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#00C5DF; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-0B376EFF&#34; width=&#34;100&#34; height=&#34;100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#58DDDD; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-213D6DFF&#34; width=&#34;34&#34; height=&#34;34&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#6D6D55; stroke-width:31.7333333333333; stroke-opacity:0.714285714285714;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;34&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-2F436CFF&#34; width=&#34;238&#34; height=&#34;238&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#6D6D00; stroke-width:253.866666666667; stroke-opacity:0.428571428571429;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;238&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-3A486BFF&#34; width=&#34;68&#34; height=&#34;68&#34; patternTransform=&#34;rotate(135 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;line style=&#34;stroke:#6D49FF; stroke-width:81.6; stroke-opacity:0;&#34; x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;68&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-434F6BFF&#34; width=&#34;102&#34; height=&#34;102&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#6D49FF; fill:#6D49FF; fill-opacity:1; stroke-opacity:1;&#34; cx=&#34;51&#34; cy=&#34;51&#34; r=&#34;29.14&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-4C546CFF&#34; width=&#34;136&#34; height=&#34;136&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#6D6D00; fill:#6D6D00; fill-opacity:0.571428571428571; stroke-opacity:0.571428571428571;&#34; cx=&#34;68&#34; cy=&#34;68&#34; r=&#34;43.17&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-545A6CFF&#34; width=&#34;136&#34; height=&#34;136&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#6D6D00; fill:#6D6D00; fill-opacity:0.285714285714286; stroke-opacity:0.285714285714286;&#34; cx=&#34;68&#34; cy=&#34;68&#34; r=&#34;47.49&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-5B616EFF&#34; width=&#34;102&#34; height=&#34;102&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;circle style=&#34;stroke:#6D6DAA; fill:#6D6DAA; fill-opacity:0.142857142857143; stroke-opacity:0.142857142857143;&#34; cx=&#34;51&#34; cy=&#34;51&#34; r=&#34;38.86&#34; /&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-64666FFF&#34; width=&#34;136&#34; height=&#34;136&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6D6DFF; stroke-width:217.6; stroke-opacity:0.857142857142857;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;136&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;136&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-6B6C71FF&#34; width=&#34;102&#34; height=&#34;102&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6D9255; stroke-width:176.8; stroke-opacity:0.571428571428571;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;102&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;102&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-727274FF&#34; width=&#34;68&#34; height=&#34;68&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6DB600; stroke-width:126.933333333333; stroke-opacity:0.285714285714286;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;68&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;68&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-787877FF&#34; width=&#34;2&#34; height=&#34;2&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6DB6FF; stroke-width:2; stroke-opacity:0;&#34;&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;0&#34; y2=&#34;2&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;0&#34; x2=&#34;2&#34; y2=&#34;0&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-817F79FF&#34; width=&#34;5100&#34; height=&#34;5100&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-44.46&#39; cy=&#39;76.85&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-194.62&#39; cy=&#39;445.13&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-121.61&#39; cy=&#39;1374.06&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-127.79&#39; cy=&#39;2057.62&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-230.71&#39; cy=&#39;2684.1&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-13.63&#39; cy=&#39;3108.48&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-115.93&#39; cy=&#39;3764.07&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-93.59&#39; cy=&#39;4175.15&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-44.46&#39; cy=&#39;5176.85&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;38.43&#39; cy=&#39;856.72&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;236.16&#39; cy=&#39;1434.84&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;51.18&#39; cy=&#39;1759.38&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74.4&#39; cy=&#39;2413.29&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;114.35&#39; cy=&#39;2796.44&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;206.77&#39; cy=&#39;3424.04&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;45.11&#39; cy=&#39;4541.88&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.95&#39; cy=&#39;-160.65&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;379.41&#39; cy=&#39;319.24&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;425.61&#39; cy=&#39;809.67&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;356.37&#39; cy=&#39;1957.78&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;297.47&#39; cy=&#39;4135.95&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;453.75&#39; cy=&#39;4612.96&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;261.95&#39; cy=&#39;4939.35&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;523.9&#39; cy=&#39;1384.61&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;538.56&#39; cy=&#39;2377.37&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;645.77&#39; cy=&#39;2735.83&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;525.41&#39; cy=&#39;3307.74&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;522.46&#39; cy=&#39;3588.27&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;672.38&#39; cy=&#39;4278.97&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;971.05&#39; cy=&#39;50.59&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;883.92&#39; cy=&#39;500.06&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;821.85&#39; cy=&#39;767.89&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;929.81&#39; cy=&#39;1281.85&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;967.05&#39; cy=&#39;1912.41&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;795.82&#39; cy=&#39;3067.97&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;991.2&#39; cy=&#39;3578.76&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;894.71&#39; cy=&#39;3931.56&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;910.28&#39; cy=&#39;4773.67&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;971.05&#39; cy=&#39;5150.59&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1268.85&#39; cy=&#39;306.49&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1154.88&#39; cy=&#39;2676.65&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1143.9&#39; cy=&#39;3278.77&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1123.36&#39; cy=&#39;4412.25&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1300.13&#39; cy=&#39;926.99&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1517.41&#39; cy=&#39;1272.93&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1496.82&#39; cy=&#39;1672.5&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1341.68&#39; cy=&#39;2083.48&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1521.32&#39; cy=&#39;2806.59&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1523.77&#39; cy=&#39;3476.53&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1326.53&#39; cy=&#39;3810.45&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1390.86&#39; cy=&#39;4082.54&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1338.88&#39; cy=&#39;4788.75&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1583.52&#39; cy=&#39;101.04&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1582.33&#39; cy=&#39;651.42&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1707.21&#39; cy=&#39;2281.81&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1772.63&#39; cy=&#39;3158.78&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1728.19&#39; cy=&#39;4312.97&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1687.06&#39; cy=&#39;4602.93&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1583.52&#39; cy=&#39;5201.04&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1905.77&#39; cy=&#39;-77.4&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1917.22&#39; cy=&#39;288.06&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1852.37&#39; cy=&#39;920.49&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1831.09&#39; cy=&#39;1315.75&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2008.22&#39; cy=&#39;2025.98&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1834.31&#39; cy=&#39;2604.19&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1886.92&#39; cy=&#39;3594.4&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2029.99&#39; cy=&#39;4055.76&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1905.77&#39; cy=&#39;5022.6&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2223.85&#39; cy=&#39;975.68&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2107.16&#39; cy=&#39;1576.87&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2198.51&#39; cy=&#39;2499.69&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2053.03&#39; cy=&#39;2988.57&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2186.24&#39; cy=&#39;4745.49&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2516.18&#39; cy=&#39;-111.02&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2524.59&#39; cy=&#39;296.08&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2315.39&#39; cy=&#39;600.58&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2455.57&#39; cy=&#39;2244.73&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2405.93&#39; cy=&#39;2809.6&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2352.13&#39; cy=&#39;3457.98&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2424.21&#39; cy=&#39;3907.1&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2480.74&#39; cy=&#39;4374.99&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2516.18&#39; cy=&#39;4988.98&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2713.34&#39; cy=&#39;793.43&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2659.12&#39; cy=&#39;1264.98&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2560.21&#39; cy=&#39;1668.45&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2764.99&#39; cy=&#39;2623.46&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2746.35&#39; cy=&#39;3028.35&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2737.58&#39; cy=&#39;3540.99&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2953.8&#39; cy=&#39;-170.49&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3025.87&#39; cy=&#39;500.81&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3028.04&#39; cy=&#39;1355.09&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2987.64&#39; cy=&#39;1850.74&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2875.42&#39; cy=&#39;3937.46&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2939.16&#39; cy=&#39;4428.43&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2953.8&#39; cy=&#39;4929.51&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3290.85&#39; cy=&#39;-19.81&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3118.42&#39; cy=&#39;2349.76&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3166.04&#39; cy=&#39;2779.86&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3062.67&#39; cy=&#39;3066.44&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3257.2&#39; cy=&#39;3563.12&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3290.85&#39; cy=&#39;5080.19&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3418.06&#39; cy=&#39;337.01&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3407.23&#39; cy=&#39;880.97&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3359.77&#39; cy=&#39;1250.42&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3534.64&#39; cy=&#39;2010.64&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3530&#39; cy=&#39;2339.74&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3458.43&#39; cy=&#39;3217.66&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3438.42&#39; cy=&#39;3877.47&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3462.18&#39; cy=&#39;4382.33&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3549.16&#39; cy=&#39;4810.09&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3774.1&#39; cy=&#39;604.28&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3798.46&#39; cy=&#39;1121.47&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3621.47&#39; cy=&#39;1626.73&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3698.16&#39; cy=&#39;2672.72&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3754.58&#39; cy=&#39;3512.39&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3816.95&#39; cy=&#39;4530.83&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3874.08&#39; cy=&#39;-101.54&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3849.42&#39; cy=&#39;2208.76&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4058.7&#39; cy=&#39;2700.02&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4043.71&#39; cy=&#39;3258.34&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3862.21&#39; cy=&#39;4135.33&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3874.08&#39; cy=&#39;4998.46&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4176.01&#39; cy=&#39;185.87&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4232.3&#39; cy=&#39;578.36&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4207.85&#39; cy=&#39;1142.78&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4087.67&#39; cy=&#39;1667.92&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4213.62&#39; cy=&#39;2334.63&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4234.14&#39; cy=&#39;3684.35&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4102.38&#39; cy=&#39;4496.86&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4176.01&#39; cy=&#39;5285.87&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4582.71&#39; cy=&#39;56.68&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4478.86&#39; cy=&#39;1637.83&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4518.98&#39; cy=&#39;2011.91&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4585.57&#39; cy=&#39;2539.48&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4526.4&#39; cy=&#39;3007.87&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4558.26&#39; cy=&#39;3914.65&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4479.85&#39; cy=&#39;4392.11&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4417.65&#39; cy=&#39;4817.7&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4582.71&#39; cy=&#39;5156.68&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4776.11&#39; cy=&#39;793.9&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4611.24&#39; cy=&#39;1236.56&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4829.69&#39; cy=&#39;1782.94&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4660.36&#39; cy=&#39;3486.61&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5055.54&#39; cy=&#39;76.85&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4905.38&#39; cy=&#39;445.13&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4978.39&#39; cy=&#39;1374.06&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4972.21&#39; cy=&#39;2057.62&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4869.29&#39; cy=&#39;2684.1&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5086.37&#39; cy=&#39;3108.48&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;4984.07&#39; cy=&#39;3764.07&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5006.41&#39; cy=&#39;4175.15&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5055.54&#39; cy=&#39;5176.85&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5138.43&#39; cy=&#39;856.72&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5336.16&#39; cy=&#39;1434.84&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5151.18&#39; cy=&#39;1759.38&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5174.4&#39; cy=&#39;2413.29&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5214.35&#39; cy=&#39;2796.44&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5306.77&#39; cy=&#39;3424.04&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;5145.11&#39; cy=&#39;4541.88&#39; r=&#39;119&#39; style=&#39;fill: #0049FF; stroke: #0049FF; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-888579FF&#34; width=&#34;822.58064516129&#34; height=&#34;822.58064516129&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-33.47&#39; cy=&#39;2.1&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-37.13&#39; cy=&#39;94.79&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-4.85&#39; cy=&#39;258.69&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-34.72&#39; cy=&#39;359.7&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-8.93&#39; cy=&#39;435.05&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-20.99&#39; cy=&#39;546.96&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-17.18&#39; cy=&#39;611.51&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-37.33&#39; cy=&#39;661.6&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-8.52&#39; cy=&#39;714.31&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-33.47&#39; cy=&#39;824.68&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;26.54&#39; cy=&#39;44.89&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;21.05&#39; cy=&#39;192.53&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;25.98&#39; cy=&#39;349.33&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;32.56&#39; cy=&#39;576.44&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;31.57&#39; cy=&#39;671.67&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;27.39&#39; cy=&#39;764.87&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;60.11&#39; cy=&#39;134.95&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;54.61&#39; cy=&#39;288.92&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;41.43&#39; cy=&#39;468.91&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74.32&#39; cy=&#39;518.15&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.6&#39; cy=&#39;12.93&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;113.82&#39; cy=&#39;87.34&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.98&#39; cy=&#39;159.87&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;111.69&#39; cy=&#39;208.47&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;108.68&#39; cy=&#39;328.5&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;120.66&#39; cy=&#39;379.15&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;84.5&#39; cy=&#39;427.84&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;95.82&#39; cy=&#39;577.88&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;86.25&#39; cy=&#39;654.74&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;100.37&#39; cy=&#39;747.42&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;89.6&#39; cy=&#39;835.51&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.31&#39; cy=&#39;36.09&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;148.7&#39; cy=&#39;285.16&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.11&#39; cy=&#39;511.06&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;158.05&#39; cy=&#39;596.45&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;150.31&#39; cy=&#39;858.67&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;194.61&#39; cy=&#39;168.07&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;205.2&#39; cy=&#39;233.97&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.78&#39; cy=&#39;306.94&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;169.69&#39; cy=&#39;360.74&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;180.74&#39; cy=&#39;419.16&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;176.17&#39; cy=&#39;663.51&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;184.86&#39; cy=&#39;756.74&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;215.59&#39; cy=&#39;67.3&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;238.89&#39; cy=&#39;385.28&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;239.29&#39; cy=&#39;460.58&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;227.43&#39; cy=&#39;518.59&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;214.94&#39; cy=&#39;583.93&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;234.23&#39; cy=&#39;657.65&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.09&#39; cy=&#39;1.44&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;276.08&#39; cy=&#39;155.46&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.77&#39; cy=&#39;244.36&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;270.41&#39; cy=&#39;330.72&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;269.6&#39; cy=&#39;700.34&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.09&#39; cy=&#39;824.02&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.47&#39; cy=&#39;34.84&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;288.8&#39; cy=&#39;97.46&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;315.16&#39; cy=&#39;221.5&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;296.15&#39; cy=&#39;409.55&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;326.38&#39; cy=&#39;462.22&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;305.04&#39; cy=&#39;523.18&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.78&#39; cy=&#39;606.5&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;300.49&#39; cy=&#39;761.89&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;309.47&#39; cy=&#39;857.42&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;365.1&#39; cy=&#39;10.65&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;333.45&#39; cy=&#39;308.51&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;364.2&#39; cy=&#39;391.54&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;359.87&#39; cy=&#39;660.48&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;365.1&#39; cy=&#39;833.23&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;387.34&#39; cy=&#39;118.85&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.8&#39; cy=&#39;167.98&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;402&#39; cy=&#39;240.26&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;378.6&#39; cy=&#39;454.89&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.96&#39; cy=&#39;549.8&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;396.23&#39; cy=&#39;714.08&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;405.64&#39; cy=&#39;780.29&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;424.74&#39; cy=&#39;47.72&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;448.69&#39; cy=&#39;137.17&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;444.34&#39; cy=&#39;321.05&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;450.5&#39; cy=&#39;370.28&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;437.62&#39; cy=&#39;440.32&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;422.4&#39; cy=&#39;498.41&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;440.26&#39; cy=&#39;646.48&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;481.8&#39; cy=&#39;2.73&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;463.68&#39; cy=&#39;211.01&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;486.59&#39; cy=&#39;482.89&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;483.21&#39; cy=&#39;547.8&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;469.79&#39; cy=&#39;713.94&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;481.8&#39; cy=&#39;825.31&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;497.39&#39; cy=&#39;60.65&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;503.69&#39; cy=&#39;271.48&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;514.89&#39; cy=&#39;374.25&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;527.08&#39; cy=&#39;637.79&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;528.64&#39; cy=&#39;698.45&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;508.83&#39; cy=&#39;759.54&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;573.68&#39; cy=&#39;84.91&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;546.55&#39; cy=&#39;147.05&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;544.39&#39; cy=&#39;225.35&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;574.34&#39; cy=&#39;303.02&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;555.95&#39; cy=&#39;462.37&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;561.48&#39; cy=&#39;536.21&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;571.37&#39; cy=&#39;741.83&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;605.15&#39; cy=&#39;-30.88&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;580.14&#39; cy=&#39;26.07&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;611.97&#39; cy=&#39;133.43&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;606.15&#39; cy=&#39;236.14&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;575.84&#39; cy=&#39;405.86&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;611.16&#39; cy=&#39;483.77&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;584.45&#39; cy=&#39;669.68&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;605.15&#39; cy=&#39;791.7&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;580.14&#39; cy=&#39;848.65&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;650.64&#39; cy=&#39;8.08&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;638.65&#39; cy=&#39;75.17&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;649.31&#39; cy=&#39;180.34&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;635.73&#39; cy=&#39;346.77&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;630.23&#39; cy=&#39;592.62&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;652.6&#39; cy=&#39;651.69&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;623.76&#39; cy=&#39;714.17&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;650.64&#39; cy=&#39;830.66&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;666.75&#39; cy=&#39;257.17&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;684.38&#39; cy=&#39;414.31&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;659.69&#39; cy=&#39;491.94&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;669.55&#39; cy=&#39;543.52&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;667.59&#39; cy=&#39;774.57&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;719.07&#39; cy=&#39;-13.09&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;734.47&#39; cy=&#39;47.15&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;716.24&#39; cy=&#39;142.3&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;700.33&#39; cy=&#39;208.08&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;727.57&#39; cy=&#39;263.44&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;736.49&#39; cy=&#39;340.25&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;738.19&#39; cy=&#39;522.52&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;708.95&#39; cy=&#39;594.93&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;734&#39; cy=&#39;651.33&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;717.9&#39; cy=&#39;737.61&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;719.07&#39; cy=&#39;809.49&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;768.85&#39; cy=&#39;172.77&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;744.02&#39; cy=&#39;406.97&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;754.98&#39; cy=&#39;453.95&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;774.64&#39; cy=&#39;763.01&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;789.11&#39; cy=&#39;2.1&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;785.45&#39; cy=&#39;94.79&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;817.73&#39; cy=&#39;258.69&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;787.87&#39; cy=&#39;359.7&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;813.65&#39; cy=&#39;435.05&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;801.59&#39; cy=&#39;546.96&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;805.4&#39; cy=&#39;611.51&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;785.25&#39; cy=&#39;661.6&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;814.06&#39; cy=&#39;714.31&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;789.11&#39; cy=&#39;824.68&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;849.12&#39; cy=&#39;44.89&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;843.63&#39; cy=&#39;192.53&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;848.56&#39; cy=&#39;349.33&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;855.14&#39; cy=&#39;576.44&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;854.15&#39; cy=&#39;671.67&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;849.97&#39; cy=&#39;764.87&#39; r=&#39;19.1935483870968&#39; style=&#39;fill: #492400; stroke: #492400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-908B79FF&#34; width=&#34;1809.67741935484&#34; height=&#34;1809.67741935484&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-58.11&#39; cy=&#39;11.85&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-87.15&#39; cy=&#39;161.08&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-33&#39; cy=&#39;584.62&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-59.82&#39; cy=&#39;798.97&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-50.44&#39; cy=&#39;1070.01&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-55.97&#39; cy=&#39;1222.16&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-38.39&#39; cy=&#39;1385.67&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-24.31&#39; cy=&#39;1559.64&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-58.11&#39; cy=&#39;1821.53&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;19.37&#39; cy=&#39;257.84&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;40.52&#39; cy=&#39;388.63&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;74&#39; cy=&#39;883.9&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;80.71&#39; cy=&#39;1106.18&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;78.1&#39; cy=&#39;1245.81&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;63.2&#39; cy=&#39;1682.59&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.31&#39; cy=&#39;40.01&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;161.83&#39; cy=&#39;198.02&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;171.99&#39; cy=&#39;397.35&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;106.81&#39; cy=&#39;517.93&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;107.23&#39; cy=&#39;709.09&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;165.83&#39; cy=&#39;986.04&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.97&#39; cy=&#39;1556.12&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;133.31&#39; cy=&#39;1849.69&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;271.38&#39; cy=&#39;106.05&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;251.24&#39; cy=&#39;289.57&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;256.29&#39; cy=&#39;527.06&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;185.11&#39; cy=&#39;1158.12&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;189.41&#39; cy=&#39;1369.53&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;262.93&#39; cy=&#39;1510.01&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;198.94&#39; cy=&#39;1671.41&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.31&#39; cy=&#39;-65.41&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;271.79&#39; cy=&#39;752.86&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;328.77&#39; cy=&#39;976.8&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;301.62&#39; cy=&#39;1213.13&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;320.31&#39; cy=&#39;1744.27&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.16&#39; cy=&#39;57.29&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;424.97&#39; cy=&#39;176.08&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;418.68&#39; cy=&#39;280.07&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;384.32&#39; cy=&#39;432.03&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;409.96&#39; cy=&#39;550.42&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;414.49&#39; cy=&#39;714.03&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;414.93&#39; cy=&#39;875.59&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;424.75&#39; cy=&#39;1087.68&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;382.83&#39; cy=&#39;1361.82&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;419.63&#39; cy=&#39;1598&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;368.16&#39; cy=&#39;1866.97&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;520.72&#39; cy=&#39;-23.74&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;525.33&#39; cy=&#39;417.84&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;512.69&#39; cy=&#39;1218.06&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;515.19&#39; cy=&#39;1431.85&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;520.72&#39; cy=&#39;1785.94&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;546.37&#39; cy=&#39;128.68&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;548.74&#39; cy=&#39;291.98&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;566.51&#39; cy=&#39;581.35&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;565.91&#39; cy=&#39;900.03&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;560.81&#39; cy=&#39;1040.22&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;583.65&#39; cy=&#39;1637.42&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;633.88&#39; cy=&#39;17.54&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;654.7&#39; cy=&#39;205.38&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;714.35&#39; cy=&#39;443.63&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;722.81&#39; cy=&#39;569.4&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;648.87&#39; cy=&#39;741.31&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;715.07&#39; cy=&#39;884.2&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;711.97&#39; cy=&#39;1000.17&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;660.17&#39; cy=&#39;1210.29&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;674.23&#39; cy=&#39;1340.78&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;659.32&#39; cy=&#39;1459.67&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;633.88&#39; cy=&#39;1827.22&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;728.6&#39; cy=&#39;-79.24&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;802.73&#39; cy=&#39;87.25&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;780.26&#39; cy=&#39;748.71&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;789.31&#39; cy=&#39;1523.94&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;728.6&#39; cy=&#39;1730.44&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;802.73&#39; cy=&#39;1896.93&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;818.63&#39; cy=&#39;224.49&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;888.26&#39; cy=&#39;352.02&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;818.28&#39; cy=&#39;586.37&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;895.15&#39; cy=&#39;878.18&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;859.54&#39; cy=&#39;1013.25&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;817.87&#39; cy=&#39;1148.16&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;864.88&#39; cy=&#39;1282.72&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;839.25&#39; cy=&#39;1658.16&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;942.02&#39; cy=&#39;28.71&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;973.45&#39; cy=&#39;248.42&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;929.23&#39; cy=&#39;469.68&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;953.76&#39; cy=&#39;672.91&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;990.63&#39; cy=&#39;997.98&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;988.79&#39; cy=&#39;1128.09&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;978.68&#39; cy=&#39;1449.52&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;982.55&#39; cy=&#39;1592.06&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;942.02&#39; cy=&#39;1838.39&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1061.91&#39; cy=&#39;78.96&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1076.63&#39; cy=&#39;401.11&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1058.21&#39; cy=&#39;535.14&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1065.79&#39; cy=&#39;835.44&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1033.83&#39; cy=&#39;1337.31&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1061.91&#39; cy=&#39;1888.64&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1116.46&#39; cy=&#39;275.86&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1110.02&#39; cy=&#39;640.35&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1150.61&#39; cy=&#39;950.7&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1157.7&#39; cy=&#39;1081.08&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1121.81&#39; cy=&#39;1188.88&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1106.07&#39; cy=&#39;1529.83&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1135.33&#39; cy=&#39;1690.87&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1203.32&#39; cy=&#39;86.83&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1258.53&#39; cy=&#39;205.13&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1228.65&#39; cy=&#39;349.46&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1237.43&#39; cy=&#39;496.74&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1189.06&#39; cy=&#39;781.25&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1208.8&#39; cy=&#39;1399.03&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1245.78&#39; cy=&#39;1605.29&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1203.32&#39; cy=&#39;1896.51&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1303.26&#39; cy=&#39;644.88&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1307.03&#39; cy=&#39;906.53&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1279.9&#39; cy=&#39;1039.78&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1331.75&#39; cy=&#39;1258.7&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1311.14&#39; cy=&#39;1489.15&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1325.18&#39; cy=&#39;1707.51&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1428.45&#39; cy=&#39;89.92&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1373.11&#39; cy=&#39;237.43&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1420.91&#39; cy=&#39;469.96&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1446.47&#39; cy=&#39;671.82&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1367.18&#39; cy=&#39;794.62&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1410.44&#39; cy=&#39;1001.39&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1435.39&#39; cy=&#39;1337.74&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1428.45&#39; cy=&#39;1899.59&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1530.59&#39; cy=&#39;317.04&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1530.84&#39; cy=&#39;556.73&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1528.81&#39; cy=&#39;782.23&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1486.1&#39; cy=&#39;1120.34&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1452.89&#39; cy=&#39;1582.05&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1493.11&#39; cy=&#39;1718.93&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1626.07&#39; cy=&#39;18.77&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1556.6&#39; cy=&#39;157.69&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1539.91&#39; cy=&#39;937.77&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1621.23&#39; cy=&#39;1072.44&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1621.82&#39; cy=&#39;1245.09&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1581.85&#39; cy=&#39;1445.57&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1626.07&#39; cy=&#39;1828.44&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1644.18&#39; cy=&#39;270.46&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1717.09&#39; cy=&#39;367.67&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1674.01&#39; cy=&#39;497.29&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1649.51&#39; cy=&#39;647.49&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1719.12&#39; cy=&#39;925.23&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1671.73&#39; cy=&#39;1624.53&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1751.57&#39; cy=&#39;11.85&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1722.53&#39; cy=&#39;161.08&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1776.68&#39; cy=&#39;584.62&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1749.86&#39; cy=&#39;798.97&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1759.24&#39; cy=&#39;1070.01&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1753.71&#39; cy=&#39;1222.16&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1771.29&#39; cy=&#39;1385.67&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1785.37&#39; cy=&#39;1559.64&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1751.57&#39; cy=&#39;1821.53&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1829.05&#39; cy=&#39;257.84&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1850.2&#39; cy=&#39;388.63&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1883.67&#39; cy=&#39;883.9&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1890.39&#39; cy=&#39;1106.18&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1887.78&#39; cy=&#39;1245.81&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1872.88&#39; cy=&#39;1682.59&#39; r=&#39;42.2258064516129&#39; style=&#39;fill: #922400; stroke: #922400; fill-opacity: 0.6; stroke-opacity: 0.6&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-989278FF&#34; width=&#34;2961.29032258064&#34; height=&#34;2961.29032258064&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;circle cx=&#39;-26.54&#39; cy=&#39;-132.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.12&#39; cy=&#39;100.06&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-3.35&#39; cy=&#39;435.5&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-145.5&#39; cy=&#39;589.82&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-79.17&#39; cy=&#39;1168.69&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-54.22&#39; cy=&#39;1472.77&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-77.74&#39; cy=&#39;1784.93&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-63.01&#39; cy=&#39;2019.48&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-137.3&#39; cy=&#39;2331.37&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-134.29&#39; cy=&#39;2642.68&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-26.54&#39; cy=&#39;2829.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;-18.12&#39; cy=&#39;3061.35&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;105.31&#39; cy=&#39;714.91&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;132.8&#39; cy=&#39;1928.36&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;93.76&#39; cy=&#39;2253.83&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.37&#39; cy=&#39;-1.8&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;254.86&#39; cy=&#39;180.57&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;267.81&#39; cy=&#39;525.2&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;237.15&#39; cy=&#39;1113.84&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;229.63&#39; cy=&#39;1382.08&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;204.84&#39; cy=&#39;1635.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;242.19&#39; cy=&#39;2453.45&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;240.44&#39; cy=&#39;2675.07&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;159.37&#39; cy=&#39;2959.49&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;429.61&#39; cy=&#39;-99.42&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;343.2&#39; cy=&#39;919.14&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;431.03&#39; cy=&#39;1929.25&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;377.03&#39; cy=&#39;2226.96&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;431.36&#39; cy=&#39;2582.55&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;429.61&#39; cy=&#39;2861.87&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;496.44&#39; cy=&#39;201.9&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;494.63&#39; cy=&#39;746.28&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;481.62&#39; cy=&#39;1080.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;487.17&#39; cy=&#39;1415.22&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;585.56&#39; cy=&#39;1729.97&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;591.75&#39; cy=&#39;2288.64&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;666.75&#39; cy=&#39;45.12&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;607.8&#39; cy=&#39;468.39&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;679.28&#39; cy=&#39;873.36&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;700.94&#39; cy=&#39;1248.5&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;676.83&#39; cy=&#39;1924.15&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;646.25&#39; cy=&#39;2079.06&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;637.07&#39; cy=&#39;2503.5&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;643.97&#39; cy=&#39;2686.02&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;666.75&#39; cy=&#39;3006.41&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;836.03&#39; cy=&#39;-82.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;808.67&#39; cy=&#39;250.03&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;765.52&#39; cy=&#39;606.29&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;767.48&#39; cy=&#39;1505.23&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;866.49&#39; cy=&#39;1690.1&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;828.43&#39; cy=&#39;2337.11&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;836.03&#39; cy=&#39;2879.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1000.41&#39; cy=&#39;369.36&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;953.88&#39; cy=&#39;800&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;917.51&#39; cy=&#39;1131.33&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;918.47&#39; cy=&#39;1916.49&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;930.94&#39; cy=&#39;2137.21&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;972.09&#39; cy=&#39;2629.1&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1093.09&#39; cy=&#39;-113.05&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1060.12&#39; cy=&#39;150.01&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1106.53&#39; cy=&#39;626.32&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1171.77&#39; cy=&#39;1137.51&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1087.64&#39; cy=&#39;1398.64&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1084.37&#39; cy=&#39;1617.25&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1172.76&#39; cy=&#39;1843.98&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1044.17&#39; cy=&#39;2324.79&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1093.09&#39; cy=&#39;2848.24&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1322.35&#39; cy=&#39;-0.72&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1222.19&#39; cy=&#39;392.94&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1330.31&#39; cy=&#39;615.4&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1261.87&#39; cy=&#39;817.56&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1190.64&#39; cy=&#39;2071.7&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1269.41&#39; cy=&#39;2244.2&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1224.74&#39; cy=&#39;2538.42&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1322.35&#39; cy=&#39;2960.57&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1346.32&#39; cy=&#39;212.14&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1352.47&#39; cy=&#39;1022.53&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1414.39&#39; cy=&#39;1273.1&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1389.84&#39; cy=&#39;1496.53&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1401.37&#39; cy=&#39;2008.38&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1561.4&#39; cy=&#39;-135.11&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1607.54&#39; cy=&#39;118.68&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1561.88&#39; cy=&#39;327.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1608.35&#39; cy=&#39;720.2&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1506.84&#39; cy=&#39;1701.36&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1499.51&#39; cy=&#39;2252.29&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1502.75&#39; cy=&#39;2618.23&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1561.4&#39; cy=&#39;2826.18&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1607.54&#39; cy=&#39;3079.97&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1763.41&#39; cy=&#39;-27.64&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1715.84&#39; cy=&#39;1048&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1699.82&#39; cy=&#39;1270.53&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1744.78&#39; cy=&#39;1481.94&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1648.82&#39; cy=&#39;1910.9&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1750.44&#39; cy=&#39;2085.15&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1735.91&#39; cy=&#39;2487.93&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1763.41&#39; cy=&#39;2933.65&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1883.43&#39; cy=&#39;314.57&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1848.71&#39; cy=&#39;590.75&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1918.1&#39; cy=&#39;802.24&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1840.93&#39; cy=&#39;1681.56&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1914.78&#39; cy=&#39;2218.23&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1846.61&#39; cy=&#39;2732.82&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1997.18&#39; cy=&#39;-18.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2055.64&#39; cy=&#39;541.83&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1956.17&#39; cy=&#39;1134.59&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2028.79&#39; cy=&#39;1367.88&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1961.93&#39; cy=&#39;1942.51&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1964.14&#39; cy=&#39;2382.05&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2006.99&#39; cy=&#39;2594.96&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;1997.18&#39; cy=&#39;2943.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2141.06&#39; cy=&#39;204.23&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2177.52&#39; cy=&#39;740.77&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2119.36&#39; cy=&#39;990&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2208.79&#39; cy=&#39;1202.33&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2204.79&#39; cy=&#39;1736.08&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2202.21&#39; cy=&#39;2070.47&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2216.68&#39; cy=&#39;2663.95&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2302.62&#39; cy=&#39;559.79&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2341.44&#39; cy=&#39;1544.95&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2235.73&#39; cy=&#39;2362.5&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2422.75&#39; cy=&#39;-1.44&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2437.18&#39; cy=&#39;255.35&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2386.83&#39; cy=&#39;857.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2398.39&#39; cy=&#39;1194.69&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2377.21&#39; cy=&#39;1758.1&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2464.03&#39; cy=&#39;2649.65&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2422.75&#39; cy=&#39;2959.85&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2633.48&#39; cy=&#39;-52.8&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2602.26&#39; cy=&#39;538.48&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2636.56&#39; cy=&#39;771.78&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2569.74&#39; cy=&#39;1037.05&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2595.47&#39; cy=&#39;1307.12&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2555.12&#39; cy=&#39;1551.87&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2581.01&#39; cy=&#39;1815.68&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2564.93&#39; cy=&#39;2161.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2551.16&#39; cy=&#39;2453.21&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2633.48&#39; cy=&#39;2908.49&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2679.21&#39; cy=&#39;214.19&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2799.2&#39; cy=&#39;929.71&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2934.75&#39; cy=&#39;-132.13&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2943.17&#39; cy=&#39;100.06&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2957.94&#39; cy=&#39;435.5&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2815.79&#39; cy=&#39;589.82&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2882.12&#39; cy=&#39;1168.69&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2907.07&#39; cy=&#39;1472.77&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2883.55&#39; cy=&#39;1784.93&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2898.28&#39; cy=&#39;2019.48&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2823.99&#39; cy=&#39;2331.37&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2827&#39; cy=&#39;2642.68&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2934.75&#39; cy=&#39;2829.16&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;2943.17&#39; cy=&#39;3061.35&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3066.6&#39; cy=&#39;714.91&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3094.09&#39; cy=&#39;1928.36&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
&amp;lt;circle cx=&#39;3055.05&#39; cy=&#39;2253.83&#39; r=&#39;69.0967741935484&#39; style=&#39;fill: #DB2400; stroke: #DB2400; fill-opacity: 0.533333333333333; stroke-opacity: 0.533333333333333&#39; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-A19876FF&#34; width=&#34;88.3345911860127&#34; height=&#34;153&#34; patternTransform=&#34;rotate(0 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6DB6AA; stroke-width:16.32; stroke-opacity:0;&#34;&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;25.5&#34; x2=&#34;0&#34; y2=&#34;51&#34; /&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;25.5&#34; x2=&#34;88.3345911860127&#34; y2=&#34;51&#34; /&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;127.5&#34; x2=&#34;0&#34; y2=&#34;102&#34; /&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;127.5&#34; x2=&#34;88.3345911860127&#34; y2=&#34;102&#34; /&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;0&#34; x2=&#34;44.1672955930064&#34; y2=&#34;25.5&#34; /&amp;gt;
        &amp;lt;line x1=&#34;44.1672955930064&#34; y1=&#34;127.5&#34; x2=&#34;44.1672955930064&#34; y2=&#34;153&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;51&#34; x2=&#34;0&#34; y2=&#34;102&#34; /&amp;gt;
        &amp;lt;line x1=&#34;88.3345911860127&#34; y1=&#34;51&#34; x2=&#34;88.3345911860127&#34; y2=&#34;102&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-AA9F75FF&#34; width=&#34;147.224318643355&#34; height=&#34;255&#34; patternTransform=&#34;rotate(22.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6DB655; stroke-width:27.2; stroke-opacity:1;&#34;&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;0&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;0&#34; x2=&#34;73.6121593216773&#34; y2=&#34;42.5&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;73.6121593216773&#34; y2=&#34;255&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;85&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;147.224318643355&#34; y1=&#34;85&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-B2A672FF&#34; width=&#34;147.224318643355&#34; height=&#34;255&#34; patternTransform=&#34;rotate(45 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6D92AA; stroke-width:36.2666666666667; stroke-opacity:0.857142857142857;&#34;&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;0&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;0&#34; x2=&#34;73.6121593216773&#34; y2=&#34;42.5&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;73.6121593216773&#34; y2=&#34;255&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;85&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;147.224318643355&#34; y1=&#34;85&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-BAAD70FF&#34; width=&#34;147.224318643355&#34; height=&#34;255&#34; patternTransform=&#34;rotate(67.5 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g style=&#34;stroke:#6D9200; stroke-width:45.3333333333333; stroke-opacity:0.714285714285714;&#34;&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;0&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;42.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;85&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;0&#34; x2=&#34;73.6121593216773&#34; y2=&#34;42.5&#34; /&amp;gt;
        &amp;lt;line x1=&#34;73.6121593216773&#34; y1=&#34;212.5&#34; x2=&#34;73.6121593216773&#34; y2=&#34;255&#34; /&amp;gt;
        &amp;lt;line x1=&#34;0&#34; y1=&#34;85&#34; x2=&#34;0&#34; y2=&#34;170&#34; /&amp;gt;
        &amp;lt;line x1=&#34;147.224318643355&#34; y1=&#34;85&#34; x2=&#34;147.224318643355&#34; y2=&#34;170&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;linearGradient id=&#34;simple-C3B56DFF&#34; x1=&#34;0%&#34; y1=&#34;100%&#34; x2=&#34;100%&#34; y2=&#34;17.92%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#B6B655;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#6D6D55;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;simple-CDBC68FF&#34; x1=&#34;100%&#34; y1=&#34;100%&#34; x2=&#34;0%&#34; y2=&#34;44.5%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#B6FF00;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#6D4900;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;simple-D6C364FF&#34; x1=&#34;100%&#34; y1=&#34;0%&#34; x2=&#34;74.11%&#34; y2=&#34;100%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#DB00FF;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#6D2400;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;linearGradient id=&#34;simple-DECA5FFF&#34; x1=&#34;0%&#34; y1=&#34;0%&#34; x2=&#34;100%&#34; y2=&#34;20.55%&#34;&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#DB49AA;stop-opacity:1&#34; offset=&#34;0%&#34; /&amp;gt;
      &amp;lt;stop style=&#34;stop-color:#49FFFF;stop-opacity:1&#34; offset=&#34;100%&#34; /&amp;gt;
    &amp;lt;/linearGradient&amp;gt;
    &amp;lt;pattern id=&#34;simple-E8D259FF&#34; width=&#34;170&#34; height=&#34;170&#34; patternTransform=&#34;rotate(24.2857142857143 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#49DB55; fill-opacity:0.285714285714286;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;85&#34; height=&#34;85&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#49DB55; fill-opacity:0.285714285714286;&#34; x=&#34;85&#34; y=&#34;85&#34; width=&#34;85&#34; height=&#34;85&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-F2DA50FF&#34; width=&#34;187&#34; height=&#34;187&#34; patternTransform=&#34;rotate(52.8571428571429 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#499200; fill-opacity:0.285714285714286;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;93.5&#34; height=&#34;93.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#499200; fill-opacity:0.285714285714286;&#34; x=&#34;93.5&#34; y=&#34;93.5&#34; width=&#34;93.5&#34; height=&#34;93.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-FBE248FF&#34; width=&#34;204&#34; height=&#34;204&#34; patternTransform=&#34;rotate(78.5714285714286 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#494900; fill-opacity:0.285714285714286;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;102&#34; height=&#34;102&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#494900; fill-opacity:0.285714285714286;&#34; x=&#34;102&#34; y=&#34;102&#34; width=&#34;102&#34; height=&#34;102&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
    &amp;lt;pattern id=&#34;simple-FFEA46FF&#34; width=&#34;221&#34; height=&#34;221&#34; patternTransform=&#34;rotate(90 0 0)&#34; patternUnits=&#34;userSpaceOnUse&#34;&amp;gt;
      &amp;lt;rect style=&#34;fill:#ffffff; fill-opacity:1; stroke:none;&#34; width=&#34;100%&#34; height=&#34;100%&#34; /&amp;gt;
      &amp;lt;g&amp;gt;
        &amp;lt;rect style=&#34;fill:#4924AA; fill-opacity:0.285714285714286;&#34; x=&#34;0&#34; y=&#34;0&#34; width=&#34;110.5&#34; height=&#34;110.5&#34; /&amp;gt;
        &amp;lt;rect style=&#34;fill:#4924AA; fill-opacity:0.285714285714286;&#34; x=&#34;110.5&#34; y=&#34;110.5&#34; width=&#34;110.5&#34; height=&#34;110.5&#34; /&amp;gt;
      &amp;lt;/g&amp;gt;
    &amp;lt;/pattern&amp;gt;
  &amp;lt;/defs&amp;gt;
  &amp;lt;rect style=&#39;fill: url(#simple-00204DFF);&#39; x=&#39;0&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-00265AFF);&#39; x=&#39;200&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-002C69FF);&#39; x=&#39;400&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-00316FFF);&#39; x=&#39;600&#39; y=&#39;0&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-0B376EFF);&#39; x=&#39;0&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-213D6DFF);&#39; x=&#39;200&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-2F436CFF);&#39; x=&#39;400&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-3A486BFF);&#39; x=&#39;600&#39; y=&#39;100&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-434F6BFF);&#39; x=&#39;0&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-4C546CFF);&#39; x=&#39;200&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-545A6CFF);&#39; x=&#39;400&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-5B616EFF);&#39; x=&#39;600&#39; y=&#39;200&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-64666FFF);&#39; x=&#39;0&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-6B6C71FF);&#39; x=&#39;200&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-727274FF);&#39; x=&#39;400&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-787877FF);&#39; x=&#39;600&#39; y=&#39;300&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-817F79FF);&#39; x=&#39;0&#39; y=&#39;400&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-888579FF);&#39; x=&#39;200&#39; y=&#39;400&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-908B79FF);&#39; x=&#39;400&#39; y=&#39;400&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-989278FF);&#39; x=&#39;600&#39; y=&#39;400&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-A19876FF);&#39; x=&#39;0&#39; y=&#39;500&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-AA9F75FF);&#39; x=&#39;200&#39; y=&#39;500&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-B2A672FF);&#39; x=&#39;400&#39; y=&#39;500&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-BAAD70FF);&#39; x=&#39;600&#39; y=&#39;500&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-C3B56DFF);&#39; x=&#39;0&#39; y=&#39;600&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-CDBC68FF);&#39; x=&#39;200&#39; y=&#39;600&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-D6C364FF);&#39; x=&#39;400&#39; y=&#39;600&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-DECA5FFF);&#39; x=&#39;600&#39; y=&#39;600&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-E8D259FF);&#39; x=&#39;0&#39; y=&#39;700&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-F2DA50FF);&#39; x=&#39;200&#39; y=&#39;700&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-FBE248FF);&#39; x=&#39;400&#39; y=&#39;700&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;rect style=&#39;fill: url(#simple-FFEA46FF);&#39; x=&#39;600&#39; y=&#39;700&#39; height=&#39;100&#39; width=&#39;200&#39;&amp;gt;&amp;lt;/rect&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/details&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/svgpatternsimple/README-viridis.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>The {miniverse} - a collection of document creation packages for RStats</title>
      <link>https://coolbutuseless.github.io/2019/10/09/the-miniverse-a-collection-of-document-creation-packages-for-rstats/</link>
      <pubDate>Wed, 09 Oct 2019 06:25:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/09/the-miniverse-a-collection-of-document-creation-packages-for-rstats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;miniverse&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;miniverse &lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;miniverse&lt;/code&gt; is a constellation of packages for creating documents within R.&lt;/p&gt;
&lt;p&gt;The purpose of this &lt;code&gt;miniverse&lt;/code&gt; package is to:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Highlight the common interface used across the packages&lt;/li&gt;
&lt;li&gt;Provide links to the various packages&lt;/li&gt;
&lt;/ol&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;miniverse&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/miniverse&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minipdf&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minihtml&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minicss&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/miniverse&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;32%&#34; /&gt;
&lt;col width=&#34;29%&#34; /&gt;
&lt;col width=&#34;38%&#34; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logopdf.png&#34;&gt; &lt;br/&gt;Create PDF documents&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/minipdf&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/minipdf&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logocss.png&#34;&gt;&lt;br/&gt; Create CSS&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/minicss&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/minicss&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logohtml.png&#34;&gt; &lt;br/&gt; Create HTML documents&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/minihtml&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/minihtml&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logoxml.png&#34;&gt; &lt;br/&gt;Create XML documents&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/minixml&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/minixml&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/miniverse/logosvg.png&#34;&gt; &lt;br/&gt;Create SVG documents&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/minisvg&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/minisvg&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;high-level-document-description&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;High level document description&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;A document is a tree of objects, with a a &lt;em&gt;document&lt;/em&gt; node at the root, and
&lt;em&gt;element&lt;/em&gt; nodes branching from this.&lt;/li&gt;
&lt;li&gt;A document is represented by a document class e.g. &lt;code&gt;HTMLDocument()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Each &lt;em&gt;thing&lt;/em&gt; within a document is represented by an element class e.g. &lt;code&gt;HTMLElement()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Documents and Elements contain:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;attributes&lt;/strong&gt; - information about the item&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;children&lt;/strong&gt; - nested sub-elements of this element&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;initialising-a-new-document&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Initialising a new document&lt;/h1&gt;
&lt;p&gt;New documents can usually be initialised in 2 ways:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;R6 object initialisation&lt;/li&gt;
&lt;li&gt;A function call (which just wraps the R6 initialisation call)&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;Document R6 initialisation&lt;/th&gt;
&lt;th&gt;Document function init&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minipdf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PDFDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pdf_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minicss&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StyleSheet$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_stylesheet()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minihtml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minixml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minisvg&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;initialising-a-bare-element&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Initialising a bare element&lt;/h1&gt;
&lt;p&gt;A bare element can usually be initialised in 3 ways:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;R6 object initialisation&lt;/li&gt;
&lt;li&gt;A function call (which just wraps the R6 initialisation call)&lt;/li&gt;
&lt;li&gt;Using a tag helper method which wraps the R6 initialisation call for a lot
of standard elements. This usually includes autocomplete for the arguments
for each element.&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;16%&#34; /&gt;
&lt;col width=&#34;33%&#34; /&gt;
&lt;col width=&#34;20%&#34; /&gt;
&lt;col width=&#34;29%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;Element R6 initialisation&lt;/th&gt;
&lt;th&gt;Document function init&lt;/th&gt;
&lt;th&gt;Helper&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minipdf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PDFCircle$new()&lt;/code&gt;, &lt;code&gt;PDFRect$new()&lt;/code&gt;, etc&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pdf_doc()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ptag$circle()&lt;/code&gt;, &lt;code&gt;ptag$rect()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minicss&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Style$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_style()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minihtml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_elem()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;htag$title()&lt;/code&gt;, &lt;code&gt;htag$div()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minixml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml_elem()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minisvg&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_elem()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stag$circle()&lt;/code&gt;, &lt;code&gt;stag$rect()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;appending-an-element-to-an-existing-element-or-document&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appending an element to an existing element or document&lt;/h1&gt;
&lt;p&gt;After appending a new element, the returned value is the document that was
being appended to.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;Append bare element to current element&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minipdf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PDFCircle$append()&lt;/code&gt;, &lt;code&gt;PDFRect$append()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minicss&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Style$append()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minihtml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$append()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minixml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$append()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minisvg&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$append()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-an-element-directly-within-an-existing-element-or-document&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Creating an element directly within an existing element or document&lt;/h1&gt;
&lt;p&gt;After creating a new element within an existing element, it is the &lt;em&gt;new&lt;/em&gt;
element that is returned.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;8%&#34; /&gt;
&lt;col width=&#34;47%&#34; /&gt;
&lt;col width=&#34;43%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;Create element within existing element (specific)&lt;/th&gt;
&lt;th&gt;Create element within existing element (generic)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minipdf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PDFDocument$circle()&lt;/code&gt;, &lt;code&gt;PDFDocument$rect()&lt;/code&gt;, etc&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minicss&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StyleSheet$add()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minihtml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$div()&lt;/code&gt;, &lt;code&gt;HTMLDocument$title()&lt;/code&gt;, etc&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$add()&lt;/code&gt;, &lt;code&gt;HTMLDocument$add()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minixml&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$add()&lt;/code&gt;, &lt;code&gt;XMLDocument$add()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minisvg&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$circle()&lt;/code&gt;, &lt;code&gt;SVGDocument$rect()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$add()&lt;/code&gt;, &lt;code&gt;SVGDocument$add()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;update-attributes-and-add-child-elements&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Update attributes and Add Child Elements&lt;/h1&gt;
&lt;p&gt;In general when calling &lt;code&gt;$update()&lt;/code&gt; on a document or element:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Named arguments are added as attributes of the element&lt;/li&gt;
&lt;li&gt;Unnamed arguments are added as children of the element&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;package&lt;/th&gt;
&lt;th&gt;Update attributes and add child elements&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minipdf&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PDFCircle$update()&lt;/code&gt;, &lt;code&gt;PDFRect$update()&lt;/code&gt;, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minicss&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Style$update()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minihtml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$update()&lt;/code&gt;, &lt;code&gt;HTMLDocument$update()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;minixml&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$update()&lt;/code&gt;, &lt;code&gt;XMLDocument$update()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;minisvg&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$update()&lt;/code&gt;, &lt;code&gt;SVGDocument$update()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;logo&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Logo&lt;/h1&gt;
&lt;p&gt;The logo for all the miniverse packages include a drawing of a Mini Cooper S.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {minisvg} - create SVG documents with R</title>
      <link>https://coolbutuseless.github.io/2019/10/08/introducing-minisvg-create-svg-documents-with-r/</link>
      <pubDate>Tue, 08 Oct 2019 20:35:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/08/introducing-minisvg-create-svg-documents-with-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minisvg&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minisvg &lt;img src=&#34;https://coolbutuseless.github.io/img/minisvg/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minisvg&lt;/code&gt; is a package for building SVG documents in R.&lt;/p&gt;
&lt;div id=&#34;overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Need to build&lt;/th&gt;
&lt;th&gt;R6 object&lt;/th&gt;
&lt;th&gt;alternate initialisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;SVG elements&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stag&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;SVG elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_elem()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;SVG document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;quick-examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quick Examples&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;12%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;37%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;SVG Entity&lt;/th&gt;
&lt;th&gt;code&lt;/th&gt;
&lt;th&gt;result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;SVG elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stag$circle(cx=0, cy=0, r=20)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;circle cx=&#34;0&#34; cy=&#34;0&#34; r=&#34;20&#34; /&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;SVG elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SVGElement$new(&#39;circle&#39;, cx=0, cy=0, r=20)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;circle cx=&#34;0&#34; cy=&#34;0&#34; r=&#34;20&#34; /&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;SVG elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_elem(&#39;circle&#39;, cx=0, cy=0, r=20)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;circle cx=&#34;0&#34; cy=&#34;0&#34; r=&#34;20&#34; /&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;SVG document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;doc &amp;lt;- SVGDocument$new(); doc$add(&#39;circle&#39;, cx=0, cy=0, r=20)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;svg&amp;gt; &amp;lt;circle cx=&#34;0&#34; cy=&#34;0&#34; r=&#34;20&#34; /&amp;gt;&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;SVG document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;svg_doc(stag$circle(cx=0, cy=0, r=20))&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;svg&amp;gt; &amp;lt;circle cx=&#34;0&#34; cy=&#34;0&#34; r=&#34;20&#34; /&amp;gt;&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/animation-01-smil.html&#34;&gt;Animating SVG with SMIL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/animation-02-css.html&#34;&gt;Animating SVG with CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/styling-with-css.html&#34;&gt;Styling SVG with CSS&lt;/a&gt; both as an inline style chunk and as an external CSS document.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/transformations.html&#34;&gt;Transformations example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/geometry-example.html&#34;&gt;Some pretty (?) animated geometry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/carpet-01.html&#34;&gt;Creating and Animating the carpet from The Overlook Hotel in The Shining&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minisvg/articles/wallpaper-01.html&#34;&gt;Creating and Animating the a seventies wallpaper pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;minisvg&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/minisvg&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minisvg&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;stag-helper-autocomplete-svg-element-creation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;stag&lt;/code&gt; helper (autocomplete SVG element creation)&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;stag&lt;/code&gt; helper is similar to &lt;code&gt;shiny::tag&lt;/code&gt; and &lt;code&gt;minihtml::htag&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minisvg/stag.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;svg_prop-helper-autocomplete-svg-attribute-creation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;svg_prop&lt;/code&gt; helper (autocomplete SVG attribute creation)&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;svg_prop&lt;/code&gt; helper uses autocomplete to help remember the property attributes
of many SVG elements, along with their possible values.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minisvg/svg_prop.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;interface&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interface&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Individual elements can be created in a number of ways. E.g. creating a &lt;code&gt;defs&lt;/code&gt; block
&lt;ul&gt;
&lt;li&gt;As a stand-alone element
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- SVGElement$new(&#39;defs&#39;, style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- svg_elem(&#39;defs&#39;, style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- stag$defs(style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;As a sub-element of an existing document or element - the element is created,
added to the parent document (or element) and returned.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;doc &amp;lt;- SVGDocument$new(); new_elem &amp;lt;- doc$add(&#39;defs&#39;, style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;doc &amp;lt;- SVGDocument$new(); new_elem &amp;lt;- doc$defs(style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elem &amp;lt;- SVGElement$new(&#39;xxx&#39;); new_elem &amp;lt;- elem$add(&#39;defs&#39;, style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elem &amp;lt;- SVGElement$new(&#39;xxx&#39;); new_elem &amp;lt;- elem$defs(style = &#39;color: black;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$add()&lt;/code&gt; creates an element and adds it to the parent (and returns it)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- doc$add(&#39;defs&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$append()&lt;/code&gt; appends the given elements as children
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- stag$defs(); doc$append(new_elem, ...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$new(name, ...)&lt;/code&gt;, &lt;code&gt;$update(...)&lt;/code&gt; and &lt;code&gt;$add(name, ...)&lt;/code&gt; all accept &lt;code&gt;...&lt;/code&gt; where
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;named arguments&lt;/strong&gt; are added as &lt;em&gt;attributes&lt;/em&gt; of this node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;unnamed argument&lt;/strong&gt; are added as &lt;em&gt;children&lt;/em&gt; of this node&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;hello-world-svg-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hello World SVG Example&lt;/h2&gt;
&lt;p&gt;This first example demonstrates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;initialising a document of a certain size&lt;/li&gt;
&lt;li&gt;using methods on the &lt;code&gt;SVGDocument&lt;/code&gt; object to create a circle&lt;/li&gt;
&lt;li&gt;using the &lt;code&gt;$append()&lt;/code&gt; method to add the border rectangle&lt;/li&gt;
&lt;li&gt;creating the border rectangle using the &lt;code&gt;stag$rect&lt;/code&gt; helper&lt;/li&gt;
&lt;li&gt;using the &lt;code&gt;svg_prop&lt;/code&gt; helper (and autocomplete) to assist in remembering
what the stroke width parameter is called&lt;/li&gt;
&lt;li&gt;adding text&lt;/li&gt;
&lt;li&gt;adding a rotation transformation to the text&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a document, add a border and a circle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc &amp;lt;- SVGDocument$new(width = 400, height = 400)
doc$circle(cx=200, cy=200, r=100, fill = &amp;#39;yellow&amp;#39;)
doc$append(
  stag$rect(
    x = 0, y = 0, width = 400, height = 400, fill = &amp;#39;none&amp;#39;, 
    stroke = &amp;#39;black&amp;#39;, svg_prop$`stroke-width`$set(12)
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add some text to the document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mytext &amp;lt;- doc$text(&amp;quot;Hello world&amp;quot;, x= 160, y = 210, size = 30)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manipulate the text object to add some animation to it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mytext$animateTransform(
  attributeName = &amp;#39;transform&amp;#39;,
  type          = &amp;#39;rotate&amp;#39;,
  from          = &amp;quot;0 200 200&amp;quot;,
  to            = &amp;quot;360 200 200&amp;quot;,
  dur           = 5,
  repeatCount   = &amp;#39;indefinite&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;svg width=&amp;quot;400&amp;quot; height=&amp;quot;400&amp;quot; viewBox=&amp;quot;0 0 400 400&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; xmlns:xlink=&amp;quot;http://www.w3.org/1999/xlink&amp;quot;&amp;gt;
  &amp;lt;circle fill=&amp;quot;yellow&amp;quot; cx=&amp;quot;200&amp;quot; cy=&amp;quot;200&amp;quot; r=&amp;quot;100&amp;quot; /&amp;gt;
  &amp;lt;rect fill=&amp;quot;none&amp;quot; stroke=&amp;quot;black&amp;quot; stroke-width=&amp;quot;12&amp;quot; x=&amp;quot;0&amp;quot; y=&amp;quot;0&amp;quot; width=&amp;quot;400&amp;quot; height=&amp;quot;400&amp;quot; /&amp;gt;
  &amp;lt;text size=&amp;quot;30&amp;quot; x=&amp;quot;160&amp;quot; y=&amp;quot;210&amp;quot;&amp;gt;
    Hello world
    &amp;lt;animateTransform attributeName=&amp;quot;transform&amp;quot; from=&amp;quot;0 200 200&amp;quot; to=&amp;quot;360 200 200&amp;quot; type=&amp;quot;rotate&amp;quot; dur=&amp;quot;5&amp;quot; repeatCount=&amp;quot;indefinite&amp;quot; /&amp;gt;
  &amp;lt;/text&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minisvg/README-helloworld.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;parsing-svg-text-into-a-minisvg-document&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Parsing SVG text into a &lt;code&gt;minisvg&lt;/code&gt; document&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;minisvg&lt;/code&gt; uses &lt;code&gt;xml2&lt;/code&gt; to parse SVGL text (or file) into a &lt;code&gt;minisvg&lt;/code&gt; document.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_svg &amp;lt;- &amp;quot;&amp;lt;svg&amp;gt;&amp;lt;circle cx=&amp;#39;10&amp;#39; cy=&amp;#39;10&amp;#39; r=&amp;#39;5&amp;#39;/&amp;gt;&amp;lt;/svg&amp;gt;&amp;quot;
doc &amp;lt;- minisvg::parse_svg_doc(my_svg)
doc$update(fill = &amp;quot;none&amp;quot;)$
  add(name = &amp;#39;rect&amp;#39;)

print(doc)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;svg width=&amp;quot;400&amp;quot; height=&amp;quot;400&amp;quot; viewBox=&amp;quot;0 0 400 400&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; xmlns:xlink=&amp;quot;http://www.w3.org/1999/xlink&amp;quot; fill=&amp;quot;none&amp;quot;&amp;gt;
  &amp;lt;circle cx=&amp;quot;10&amp;quot; cy=&amp;quot;10&amp;quot; r=&amp;quot;5&amp;quot; /&amp;gt;
  &amp;lt;rect /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;s-wallpaper-is-my-jam&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;70s wallpaper is my jam!&lt;/h2&gt;
&lt;p&gt;This is a reproduction of a 70s wallpaper pattern.&lt;/p&gt;
&lt;p&gt;This example demonstrates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;svg_doc()&lt;/code&gt; as an alternative to &lt;code&gt;SVGDocument$new()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Creating a &lt;code&gt;&amp;lt;defs&amp;gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; object and applying it to a rectangle&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;doc &amp;lt;- svg_doc(width = 800, height = 800) 
doc$rect(x=0, y=0, width=&amp;quot;100%&amp;quot;, height=&amp;quot;100%&amp;quot;, fill=&amp;#39;#9B8A54&amp;#39;)

pat  &amp;lt;- stag$defs()$pattern(id = &amp;#39;motif&amp;#39;, width=400, height=400, patternUnits = &amp;#39;userSpaceOnUse&amp;#39;)
patg &amp;lt;- pat$g()

patg$circle(cx=  0, cy=  0, r=138, fill= &amp;#39;white&amp;#39;)
patg$circle(cx=  0, cy=400, r=138, fill= &amp;#39;white&amp;#39;)
patg$circle(cx=400, cy=  0, r=138, fill= &amp;#39;white&amp;#39;)
patg$circle(cx=400, cy=400, r=138, fill= &amp;#39;white&amp;#39;)
patg$circle(cx=200, cy=200, r=138, fill= &amp;#39;white&amp;#39;)

patg$circle(cx=  0, cy=  0, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=35)
patg$circle(cx=  0, cy=400, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=35)
patg$circle(cx=400, cy=  0, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=35)
patg$circle(cx=400, cy=400, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=35)
patg$circle(cx=200, cy=200, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=35)

patg$circle(cx=200, cy=  0, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=10)
patg$circle(cx=  0, cy=200, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=10)
patg$circle(cx=400, cy=200, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=10)
patg$circle(cx=200, cy=400, r=90, fill= &amp;#39;none&amp;#39;, stroke = &amp;#39;#4a3322&amp;#39;, stroke_width=10)

doc$append(pat)

doc$rect(x=0, y=0, width=&amp;quot;100%&amp;quot;, height=&amp;quot;100%&amp;quot;, fill=pat) &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;svg width=&amp;quot;800&amp;quot; height=&amp;quot;800&amp;quot; viewBox=&amp;quot;0 0 800 800&amp;quot; xmlns=&amp;quot;http://www.w3.org/2000/svg&amp;quot; xmlns:xlink=&amp;quot;http://www.w3.org/1999/xlink&amp;quot;&amp;gt;
  &amp;lt;rect fill=&amp;quot;#9B8A54&amp;quot; x=&amp;quot;0&amp;quot; y=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; /&amp;gt;
  &amp;lt;pattern id=&amp;quot;motif&amp;quot; width=&amp;quot;400&amp;quot; height=&amp;quot;400&amp;quot; patternUnits=&amp;quot;userSpaceOnUse&amp;quot;&amp;gt;
    &amp;lt;g&amp;gt;
      &amp;lt;circle fill=&amp;quot;white&amp;quot; cx=&amp;quot;0&amp;quot; cy=&amp;quot;0&amp;quot; r=&amp;quot;138&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;white&amp;quot; cx=&amp;quot;0&amp;quot; cy=&amp;quot;400&amp;quot; r=&amp;quot;138&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;white&amp;quot; cx=&amp;quot;400&amp;quot; cy=&amp;quot;0&amp;quot; r=&amp;quot;138&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;white&amp;quot; cx=&amp;quot;400&amp;quot; cy=&amp;quot;400&amp;quot; r=&amp;quot;138&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;white&amp;quot; cx=&amp;quot;200&amp;quot; cy=&amp;quot;200&amp;quot; r=&amp;quot;138&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;35&amp;quot; cx=&amp;quot;0&amp;quot; cy=&amp;quot;0&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;35&amp;quot; cx=&amp;quot;0&amp;quot; cy=&amp;quot;400&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;35&amp;quot; cx=&amp;quot;400&amp;quot; cy=&amp;quot;0&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;35&amp;quot; cx=&amp;quot;400&amp;quot; cy=&amp;quot;400&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;35&amp;quot; cx=&amp;quot;200&amp;quot; cy=&amp;quot;200&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;10&amp;quot; cx=&amp;quot;200&amp;quot; cy=&amp;quot;0&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;10&amp;quot; cx=&amp;quot;0&amp;quot; cy=&amp;quot;200&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;10&amp;quot; cx=&amp;quot;400&amp;quot; cy=&amp;quot;200&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
      &amp;lt;circle fill=&amp;quot;none&amp;quot; stroke=&amp;quot;#4a3322&amp;quot; stroke-width=&amp;quot;10&amp;quot; cx=&amp;quot;200&amp;quot; cy=&amp;quot;400&amp;quot; r=&amp;quot;90&amp;quot; /&amp;gt;
    &amp;lt;/g&amp;gt;
  &amp;lt;/pattern&amp;gt;
  &amp;lt;rect fill=&amp;quot;url(&amp;#39;#motif&amp;#39;)&amp;quot; x=&amp;quot;0&amp;quot; y=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; /&amp;gt;
&amp;lt;/svg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minisvg/README-wallpaper.svg&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;references&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;minisvg&lt;/code&gt; R6 interface is inspired by some of the javascript SVG builders
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://svgjs.com&#34;&gt;SVG.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://snapsvg.io/&#34;&gt;Snap SVG&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/SVG/Element&#34;&gt;Mozilla Developer Network SVG docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>The {devoutverse} - a collection of non-standard graphics output devices for RStats</title>
      <link>https://coolbutuseless.github.io/2019/10/08/the-devoutverse-a-collection-of-non-standard-graphics-output-devices-for-rstats/</link>
      <pubDate>Tue, 08 Oct 2019 06:05:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/08/the-devoutverse-a-collection-of-non-standard-graphics-output-devices-for-rstats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;devoutverse&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutverse &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutverse/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;devoutverse&lt;/code&gt; is a collection of packages offering non-standard devices for RStats.
Most are based on &lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;&lt;code&gt;devout&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The purpose of this &lt;code&gt;devoutverse&lt;/code&gt; package is to:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Provide links to the various packages.&lt;/li&gt;
&lt;/ol&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;devoutverse&lt;/code&gt; packages from &lt;a href=&#34;https://github.com/coolbutuseless/&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devoutpdf&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devoutaudio&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;32%&#34; /&gt;
&lt;col width=&#34;29%&#34; /&gt;
&lt;col width=&#34;38%&#34; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutverse/logodevout.png&#34;&gt;&lt;br/&gt; ASCII graphics device&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/devout&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/devout&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutverse/logodevoutpdf.png&#34;&gt; &lt;br/&gt;PDF device&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/devoutpdf&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/devoutpdf&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutverse/logodevoutaudio.png&#34;&gt;&lt;br/&gt; Audio output&lt;br/&gt;&lt;a href=&#34;http://github.com/coolbutuseless/devoutaudio&#34;&gt;Github&lt;/a&gt;&lt;br/&gt; &lt;a href=&#34;http://coolbutuseless.github.io/package/devoutaudio&#34;&gt;Online documentation&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;want-to-build-your-own-device&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Want to build your own device?&lt;/h2&gt;
&lt;p&gt;Best starting point is to read the &lt;a href=&#34;https://coolbutuseless.github.io/package/devout/articles/creating-an-svg-device-01.html&#34;&gt;vignettes for the &lt;code&gt;devout&lt;/code&gt; package&lt;/a&gt;
which steps through the process of building a simple SVG graphics output device.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {devoutpdf} - a hand-crafted PDF graphics device written in plain R</title>
      <link>https://coolbutuseless.github.io/2019/10/07/introducing-devoutpdf-a-hand-crafted-pdf-graphics-device-written-in-plain-r/</link>
      <pubDate>Mon, 07 Oct 2019 20:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/07/introducing-devoutpdf-a-hand-crafted-pdf-graphics-device-written-in-plain-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;devoutpdf&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutpdf &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutpdf&lt;/code&gt; is a hand-crafted PDF graphics device written in plain R.&lt;/p&gt;
&lt;p&gt;It achieves this by invoking the &lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;&lt;code&gt;devout&lt;/code&gt;&lt;/a&gt;
package to do all the interfacing between the C++ side and the R side.&lt;/p&gt;
&lt;p&gt;Drawing commands which sent to the graphics
device are used to construct a &lt;a href=&#34;https://github.com/coolbutuseless/minipdf&#34;&gt;&lt;code&gt;minipdf&lt;/code&gt;&lt;/a&gt; document.&lt;/p&gt;
&lt;div id=&#34;why-would-you-want-this&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Why would you want this?&lt;/h3&gt;
&lt;p&gt;Given that &lt;code&gt;pdf()&lt;/code&gt; and &lt;code&gt;cairo_pdf()&lt;/code&gt; devices come with R, what’s the point of
a third PDF output device?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hacking your own graphics device gives a significant amount of control over the
actual output&lt;/li&gt;
&lt;li&gt;You can learn how a graphics device works - it’s just R, so there’s no C++ code to
sift through.&lt;/li&gt;
&lt;li&gt;Use as a template to write your own graphics device for something bespoke e.g. 
pen plotter output or a laser projection driver!&lt;/li&gt;
&lt;li&gt;Glitch the output at the device level e.g. for each line, perhaps draw
multiple overlapping lines with randomly jittered endpoints to simulate a
‘pencil sketch’ effect.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;the-r-code&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;The R code&lt;/h3&gt;
&lt;p&gt;The R code for this device is a single file about 300 lines long - most of which
is whitespace and comments. Check it out &lt;a href=&#34;https://github.com/coolbutuseless/devoutpdf-prep/blob/master/R/pdfout.R&#34;&gt;on github&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;ToDo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Helvetica font is currently used regardless of what the user specifies. This
is a deficiency that first needs to be fixed in &lt;code&gt;minipdf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devoutpdf&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)    # graphics device shim
devtools::install_github(&amp;quot;coolbutuseless/minipdf&amp;quot;)   # PDF document builder
devtools::install_github(&amp;quot;coolbutuseless/devoutpdf&amp;quot;) # Devout PDF graphics device&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-ggplot-scatterplot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: ggplot scatterplot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutpdf::pdfout(filename = &amp;quot;/img/devoutpdf/test1.pdf&amp;quot;, width=5, height=4)
ggplot(mtcars) + 
  geom_point(aes(mpg, wt)) + 
  labs(title = &amp;quot;test1&amp;quot;) + 
  theme_bw()
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/test1.png&#34; width=&#34;70%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-ggplot-bar-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: ggplot bar plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutpdf::pdfout(filename = &amp;quot;/img/devoutpdf/test2.pdf&amp;quot;, width = 6, height = 4)
ggplot(mtcars) + 
  geom_bar(aes(as.factor(cyl), fill = as.factor(cyl))) + 
  labs(title = &amp;quot;test2&amp;quot;)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/test2.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-ggplot-density-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: ggplot density plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutpdf::pdfout(filename = &amp;quot;/img/devoutpdf/test3.pdf&amp;quot;, width = 6, height = 4)
ggplot(mtcars) + 
  geom_density(aes(mpg, fill = as.factor(cyl)), alpha = 1, size = 2) +
  theme_bw()
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/test3.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-tmap-world-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: tmap world plot&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tmap)
data(&amp;quot;World&amp;quot;)

devoutpdf::pdfout(filename = &amp;quot;/img/devoutpdf/test4.pdf&amp;quot;, width = 5, height = 4)
tm_shape(World) +
    tm_polygons(&amp;quot;HPI&amp;quot;)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/test4.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-base-graphics-pie-chart&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: base graphics pie chart&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devoutpdf::pdfout(filename = &amp;quot;/img/devoutpdf/test5.pdf&amp;quot;, width = 5, height = 4)
pie(c(cool = 4, but = 2, use = 1, less = 8))
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/devoutpdf/test5.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing {devoutaudio} - an experimental package for rendering graphics as audio</title>
      <link>https://coolbutuseless.github.io/2019/10/04/introducing-devoutaudio-an-experimental-package-for-rendering-graphics-as-audio/</link>
      <pubDate>Fri, 04 Oct 2019 22:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/04/introducing-devoutaudio-an-experimental-package-for-rendering-graphics-as-audio/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;devoutaudio&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devoutaudio &lt;img src=&#34;https://coolbutuseless.github.io/img/devoutaudio/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/very-experimental-orange.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutaudio&lt;/code&gt; is an audio output “graphics” device - instead of rendering pixels,
each graphics primitive is rendered as an audio snippet.&lt;/p&gt;
&lt;p&gt;This is a testing ground for some graphics-to-sound ideas and is &lt;strong&gt;very&lt;/strong&gt; experimental.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devoutaudio&lt;/code&gt; is written in plain R, and uses the
&lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;devout&lt;/a&gt; package to interface with the
R internals&lt;/p&gt;
&lt;div id=&#34;point-to-sound-mapping&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Point-to-sound mapping&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;x position is mapped to audio channel position - points on the left of the plot
are rendered mainly in the left channel of audio&lt;/li&gt;
&lt;li&gt;y position is mapped to frequency - the higher the point the higher the frequency&lt;/li&gt;
&lt;li&gt;size is mapped to duration - larger points have a longer sound&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;devoutaudio&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/devoutaudio&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/devoutaudio&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;caveats&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Caveats&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is a very experimental device.&lt;/li&gt;
&lt;li&gt;Only circles are currently mapped to a sound&lt;/li&gt;
&lt;li&gt;Audio is only played on-the-fly and there is no facility to save yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;examples&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Examples&lt;/h1&gt;
&lt;p&gt;In the following examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only audio is produced by the code show, but I’ve included the visual representation
of the plots to assist in interpreting the audio&lt;/li&gt;
&lt;li&gt;because the audio is never saved to file, the audio was captured on-the-fly
from the MacOS sound output device&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;example-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 1&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(devoutaudio)

audio()
plot(1:10)
dev.off()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;audio controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/devoutaudio/mp3/audio1.mp3&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio tag.
&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-10-04-devout-audio-graphics-rendering_files/figure-html/graph1-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 2&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot_df &amp;lt;- mtcars %&amp;gt;% arrange(mpg)

audio()
ggplot(plot_df) +
  geom_point(aes(mpg, wt, size = cyl)) +
  theme(legend.position = &amp;#39;none&amp;#39;)
dev.off()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;audio controls&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/devoutaudio/mp3/audio2.mp3&#34; type=&#34;audio/mpeg&#34;&gt;
Your browser does not support the audio tag.
&lt;/audio&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-10-04-devout-audio-graphics-rendering_files/figure-html/graph2-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Re-introducing devout - a package for creating graphics output devices in plain R</title>
      <link>https://coolbutuseless.github.io/2019/10/03/re-introducing-devout-a-package-for-creating-graphics-output-devices-in-plain-r/</link>
      <pubDate>Thu, 03 Oct 2019 22:27:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/10/03/re-introducing-devout-a-package-for-creating-graphics-output-devices-in-plain-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;devout&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;devout &lt;img src=&#34;https://coolbutuseless.github.io/img/devout/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dev-out-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devout&lt;/code&gt; is a package that enables R graphics devices to be written in plain R.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;devout&lt;/code&gt; uses a pseudo-graphics-device which translates graphics
calls into a call to an R function of your design.&lt;/p&gt;
&lt;p&gt;This means we can create alternative output devices (like &lt;code&gt;pdf()&lt;/code&gt; or &lt;code&gt;png()&lt;/code&gt;) using
only plain R.&lt;/p&gt;
&lt;div id=&#34;how-normal-cc-graphics-devices-work&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;How normal (C/C++) graphics devices work&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt; &lt;span title=&#39;animation&#39;&gt; animation (click to close) &lt;/summary&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/devout/graffle/graphics-device/animo.gif&#34; /&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;how-the-devout-device-enables-plain-r-graphics-devices&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;How the devout device enables plain R graphics devices&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt; &lt;span title=&#39;animation&#39;&gt; animation (click to close) &lt;/summary&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/devout/graffle/devout-device/animo.gif&#34; /&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rdevice()&lt;/code&gt; - a generic device wrapper which will call the given R function to
handle the graphics drawing.&lt;/li&gt;
&lt;li&gt;Two example devices written in plain R (but using the underlying &lt;code&gt;rdevice()&lt;/code&gt;)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;descriptive()&lt;/code&gt; - an output device which dumps information about the device calls.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ascii()&lt;/code&gt; - a graphics device which outputs an ascii representation of the plot
to a file, or to the console/terminal&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;how-do-i-write-my-own-graphics-device&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;How do I write my own graphics device?&lt;/h2&gt;
&lt;p&gt;If you want to write your own graphics device in plain R using &lt;code&gt;devout&lt;/code&gt; you can:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Read the &lt;code&gt;R/ascii-callback.R&lt;/code&gt; included in the package&lt;/li&gt;
&lt;li&gt;Read the vignettes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A series of 4 vignettes are included in this package. They walk through the process
of writing a naive SVG graphics device.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/devout/articles/creating-an-svg-device-01.html&#34;&gt;Creating an SVG device - part 1 - The Callback Function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/devout/articles/creating-an-svg-device-02.html&#34;&gt;Creating an SVG device - part 2 - The Drawing Canvas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/devout/articles/creating-an-svg-device-03.html&#34;&gt;Creating an SVG device - part 3 - Rendering Graphics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/devout/articles/creating-an-svg-device-04.html&#34;&gt;Creating an SVG device - part 4 - %#$^ you I won’t do what you tell me&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/devout&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/devout&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-device-written-in-plain-r-debug-device&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Simple device written in plain R: &lt;code&gt;debug&lt;/code&gt; device&lt;/h1&gt;
&lt;p&gt;The following 5 lines of code are about the simplest device you can write with
&lt;code&gt;devout&lt;/code&gt; in plain R.&lt;/p&gt;
&lt;p&gt;This devices prints each of the device calls that were generated when the
plot was “drawn”.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write a function which takes 3 arguments
# @param device_call name of device function call
# @param args the arguments to that device call
# @param state current state of the graphics device
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
debug_function &amp;lt;- function(device_call, args, state) {
  if (device_call %in% c(&amp;#39;mode&amp;#39;, &amp;#39;strWidthUTF8&amp;#39;, &amp;#39;metricInfo&amp;#39;)) return()
  cat(&amp;quot;[&amp;quot;, device_call, &amp;quot;]: &amp;quot;)
  cat(paste(names(args), args, sep = &amp;quot; = &amp;quot;, collapse = &amp;quot;,  &amp;quot;), &amp;quot;\n&amp;quot;, sep = &amp;quot;&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Call the &amp;#39;rdevice&amp;#39; and tell it that all calls should be passed to 
# the above &amp;#39;debug_function&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rdevice(&amp;#39;debug_function&amp;#39;) 
plot(1:10)
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[ open ]: 
[ activate ]: 
[ holdflush ]: level = 1
[ newPage ]: 
[ clip ]: x0 = 59.04,  y0 = 21526.56,  x1 = 28769.76,  y1 = 59.0400000000009
[ circle ]: x = 1122.4,  y = 20731.4666666667,  r = 2.7
[ circle ]: x = 4076.17777777778,  y = 18522.8740740741,  r = 2.7
[ circle ]: x = 7029.95555555556,  y = 16314.2814814815,  r = 2.7
[ circle ]: x = 9983.73333333334,  y = 14105.6888888889,  r = 2.7
[ circle ]: x = 12937.5111111111,  y = 11897.0962962963,  r = 2.7
[ circle ]: x = 15891.2888888889,  y = 9688.5037037037,  r = 2.7
[ circle ]: x = 18845.0666666667,  y = 7479.91111111111,  r = 2.7
[ circle ]: x = 21798.8444444444,  y = 5271.31851851852,  r = 2.7
[ circle ]: x = 24752.6222222222,  y = 3062.72592592592,  r = 2.7
[ circle ]: x = 27706.4,  y = 854.133333333331,  r = 2.7
[ clip ]: x0 = 0,  y0 = 21600,  x1 = 28800,  y1 = 0
[ line ]: x1 = 4076.17777777778,  y1 = 21526.56,  x2 = 27706.4,  y2 = 21526.56
[ line ]: x1 = 4076.17777777778,  y1 = 21526.56,  x2 = 4076.17777777778,  y2 = 21533.76
[ line ]: x1 = 9983.73333333334,  y1 = 21526.56,  x2 = 9983.73333333334,  y2 = 21533.76
[ line ]: x1 = 15891.2888888889,  y1 = 21526.56,  x2 = 15891.2888888889,  y2 = 21533.76
[ line ]: x1 = 21798.8444444444,  y1 = 21526.56,  x2 = 21798.8444444444,  y2 = 21533.76
[ line ]: x1 = 27706.4,  y1 = 21526.56,  x2 = 27706.4,  y2 = 21533.76
[ textUTF8 ]: x = 4058.17777777778,  y = 21552.48,  str = 2,  rot = 0,  hadj = 0
[ textUTF8 ]: x = 9965.73333333334,  y = 21552.48,  str = 4,  rot = 0,  hadj = 0
[ textUTF8 ]: x = 15873.2888888889,  y = 21552.48,  str = 6,  rot = 0,  hadj = 0
[ textUTF8 ]: x = 21780.8444444444,  y = 21552.48,  str = 8,  rot = 0,  hadj = 0
[ textUTF8 ]: x = 27682.4,  y = 21552.48,  str = 10,  rot = 0,  hadj = 0
[ line ]: x1 = 59.04,  y1 = 18522.8740740741,  x2 = 59.04,  y2 = 854.133333333331
[ line ]: x1 = 59.04,  y1 = 18522.8740740741,  x2 = 51.84,  y2 = 18522.8740740741
[ line ]: x1 = 59.04,  y1 = 14105.6888888889,  x2 = 51.84,  y2 = 14105.6888888889
[ line ]: x1 = 59.04,  y1 = 9688.5037037037,  x2 = 51.84,  y2 = 9688.5037037037
[ line ]: x1 = 59.04,  y1 = 5271.31851851852,  x2 = 51.84,  y2 = 5271.31851851852
[ line ]: x1 = 59.04,  y1 = 854.133333333331,  x2 = 51.84,  y2 = 854.133333333331
[ textUTF8 ]: x = 41.76,  y = 18540.8740740741,  str = 2,  rot = 90,  hadj = 0
[ textUTF8 ]: x = 41.76,  y = 14123.6888888889,  str = 4,  rot = 90,  hadj = 0
[ textUTF8 ]: x = 41.76,  y = 9706.5037037037,  str = 6,  rot = 90,  hadj = 0
[ textUTF8 ]: x = 41.76,  y = 5289.31851851852,  str = 8,  rot = 90,  hadj = 0
[ textUTF8 ]: x = 41.76,  y = 878.133333333331,  str = 10,  rot = 90,  hadj = 0
[ polyline ]: n = 5,  x = c(59.04, 28769.76, 28769.76, 59.04, 59.04),  y = c(21526.56, 21526.56, 59.0400000000009, 59.0400000000009, 21526.56)
[ clip ]: x0 = 0,  y0 = 21600,  x1 = 28800,  y1 = 0
[ textUTF8 ]: x = 14372.4,  y = 21581.28,  str = Index,  rot = 0,  hadj = 0
[ textUTF8 ]: x = 12.96,  y = 10828.8,  str = 1:10,  rot = 90,  hadj = 0
[ holdflush ]: level = -1
[ close ]: &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;ascii-device&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;ascii()&lt;/code&gt; device&lt;/h1&gt;
&lt;p&gt;This is an example of a more complete graphics device. It is written in plain R and
relies on &lt;code&gt;devout&lt;/code&gt; for all the interfacing with C++ and the internals of R.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ascii()&lt;/code&gt; device draws an approximation of the graphics using ASCII characters
on the console (by default) or saved to a text file (if specified).&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No support for: filled polygons, plotmath, alpha blending, angled text, rasters&lt;/li&gt;
&lt;li&gt;You should probably always add &lt;code&gt;theme(legend.position = &#39;none&#39;)&lt;/code&gt; because legends look awful in ascii.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;ggplot2-basic-scatterplot&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;ggplot2&lt;/code&gt;: Basic scatterplot&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;- ggplot(mtcars) + 
  geom_point(aes(mpg, wt)) +
  labs(
    y     = &amp;quot;Car Weight&amp;quot;,
    title    = &amp;quot;Basic scatter plot&amp;quot;,
    subtitle = &amp;quot;Rendered with devout::ascii()&amp;quot;
  )  + 
  theme_bw()

ascii(width = 100)
p
invisible(dev.off())
    Basic scatter plot                                                                              
    Rendered with devout::ascii()                                                                   
    +----------------------------------------------------------------------------------------------+
    |  .#       .       #.        .        .         .        .        .        .        .         |
    O..............................................................................................|
  5 |  .        .        .        .        .         .        .        .        .        .         |
    |  .        .        .        .        .         .        .        .        .        .         |
    |..............................................................................................|
    |  .        .        .        .        .         .        .        .        .        .         |
C 4 O.........................#....................................................................|
a   |  .        .  #     .#       #      # .         .        .        .        .        .         |
r   |..................#.#.#.......................................................................|
    |  .        .        .#       .##  # # .         .        .        .        .        .         |
W   |  .        .        .  #     .        .     #   .#     # .        .        .        .         |
e 3 O..........................................#...................................................|
i   |  .        .        .        .       #.   # #   .        .        .        .        .         |
g   |............................................#.................................................|
h   |  .        .        .        .        .         .#       .        .        .        #         |
t   O.............................................................#................................|
  2 |  .        .        .        .        .         .        .       #.        .        .     #   |
    |  .        .        .        .        .         .        .        .        . #      .         |
    |.............................................................................#................|
    +10O----------------15----------------20----------------25O----------------30----------------35O
                                                 mpg                                                
                                                                                                     &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pie-plot-in-base-r&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;pie&lt;/code&gt; plot in base R&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ascii(width = 100) 
pie(c(cool = 4, but = 2, use = 1, less = 8))
invisible(dev.off())
                                                                                                    
                                                                                                    
                                                                                                    
                                   but     ##############                                           
                                       ####    #         ####  cool                                 
                                    ###        #             ###                                    
                                  ##            #               ##                                  
                          use    ## ###         #                ##                                 
                               ##      ###      #                  #                                
                               #          ###    #                  #                               
                               #########     ### #                  #                               
                              #         ##############################                              
                              #                                     #                               
                               #                                    #                               
                               ##                                  ##                               
                                ##                                ##                                
                                 ##                              ##                                 
                                  ###                          ###                                  
                                    ####                    ####                                    
                                       #####            #####                                       
                                            #############                                           
                                          less                                                      
                                                                                                    
                                                                                                    
                                                                                                     &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;geom_sf-map-of-the-gulf-of-mexico&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;geom_sf()&lt;/code&gt; map of the Gulf of Mexico&lt;/h3&gt;
&lt;details closed&gt;
&lt;p&gt;&lt;summary&gt; &lt;span title=&#39;Simple features example&#39;&gt; geom_sf() example (click to open) &lt;/summary&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example taken from the &lt;a href=&#34;https://www.r-spatial.org/r/2018/10/25/ggplot2-sf.html&#34;&gt;r-spatial website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;This would probably look better with filled polygons, but they are not supported yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(sf)
library(rnaturalearth)
world &amp;lt;- ne_countries(scale = &amp;quot;medium&amp;quot;, returnclass = &amp;quot;sf&amp;quot;)

world_points &amp;lt;- st_centroid(world)
world_points &amp;lt;- cbind(world, st_coordinates(st_centroid(world$geometry)))

ascii(width = 200)
ggplot(data = world) +
  geom_sf() +
  geom_text(data= world_points,aes(x=X, y=Y, label=name),
            color = &amp;quot;darkblue&amp;quot;, fontface = &amp;quot;bold&amp;quot;, check_overlap = FALSE) +
  annotate(geom = &amp;quot;text&amp;quot;, x = -90, y = 26, label = &amp;quot;Gulf of Mexico&amp;quot;, fontface = &amp;quot;italic&amp;quot;, color = &amp;quot;grey22&amp;quot;, size = 6) +
  coord_sf(xlim = c(-102.15, -74.12), ylim = c(7.65, 33.97), expand = FALSE) + 
  theme_bw()
invisible(dev.off())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/devout/gulfofmexico.png&#34;&gt;&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;ideas-for-other-output-devices&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ideas for other Output Devices&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Colour ASCII/ANSI output&lt;/li&gt;
&lt;li&gt;Audio output&lt;/li&gt;
&lt;li&gt;HPGL plotting output&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Numerical_control&#34;&gt;CNC&lt;/a&gt; machine tooling instructions&lt;/li&gt;
&lt;li&gt;Directly drive motors to power an etch-a-sketch&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;news&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;News:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;v0.2.0 - Major refactor. &lt;code&gt;devout&lt;/code&gt; is now a way of writing graphics devices in
plain R with the &lt;code&gt;ascii()&lt;/code&gt; device as an example.&lt;/li&gt;
&lt;li&gt;v0.1.2 - Added support for multiple page output&lt;/li&gt;
&lt;li&gt;v0.1.1 - Added support for path objects, so more map plots now work.&lt;/li&gt;
&lt;li&gt;v0.1.0 - initial release&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `minixml` package for creating XML documents in R</title>
      <link>https://coolbutuseless.github.io/2019/09/30/introducing-the-minixml-package-for-creating-xml-documents-in-r/</link>
      <pubDate>Mon, 30 Sep 2019 21:57:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/09/30/introducing-the-minixml-package-for-creating-xml-documents-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minixml&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minixml &lt;img src=&#34;https://coolbutuseless.github.io/img/minixml/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;a href=&#34;https://travis-ci.org/coolbutuseless/minixml&#34;&gt;&lt;img src=&#34;https://travis-ci.org/coolbutuseless/minixml.svg?branch=master&#34; alt=&#34;Travis build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minixml&lt;/code&gt; is a package for building xml documents in R.&lt;/p&gt;
&lt;div id=&#34;minixml-vs-xml2&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;minixml&lt;/code&gt; vs &lt;code&gt;xml2&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;xml2&lt;/code&gt; is a fantastic package for parsing a pre-existing XML file and navigating through
it, slicing it etc.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minixml&lt;/code&gt; is focussed on &lt;em&gt;creating&lt;/em&gt; XML documents by assembling nodes with attributes
in a programmatic fashion.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Need to build&lt;/th&gt;
&lt;th&gt;R6 object&lt;/th&gt;
&lt;th&gt;alternate initialisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;XML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml_elem()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;XML document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;quick-examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quick Examples&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;11%&#34; /&gt;
&lt;col width=&#34;53%&#34; /&gt;
&lt;col width=&#34;35%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;XML Entity&lt;/th&gt;
&lt;th&gt;code&lt;/th&gt;
&lt;th&gt;result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;XML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;XMLElement$new(&#39;info&#39;, &#34;Hello there&#34;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;info&amp;gt;Hello there&amp;lt;/info&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;XML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xml_elem(&#39;info&#39;, &#39;Hello&#39;)$update(date = &#39;2019&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;info date=&#34;2019&#34;&amp;gt;Hello&amp;lt;/info&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;XML document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;this_xml &amp;lt;- XMLDocument$new(&#39;core&#39;); this_xml$add(&#39;info&#39;, &#39;hello&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;core&amp;gt;&amp;lt;info&amp;gt;hello&amp;lt;/info&amp;gt;&amp;lt;/core&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;minixml&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/minixml&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minixml&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;interface&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interface&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Individual elements can be created in a number of ways.
&lt;ul&gt;
&lt;li&gt;As a stand-alone element
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- XMLElement$new(&#39;info&#39;, type = &#39;meta&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- xml_elem(&#39;info&#39;, type = &#39;meta&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;As a sub-element of an existing document or element - the element is created,
added to the parent document (or element) and returned.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;doc &amp;lt;- XMLDocument$new(&#39;xx&#39;); new_elem &amp;lt;- doc$add(&#39;info&#39;, type = &#39;meta&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elem &amp;lt;- XMLElement$new(&#39;xxx&#39;); new_elem &amp;lt;- elem$add(&#39;info&#39;, type = &#39;meta&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$add()&lt;/code&gt; creates an element and adds it to the parent (and returns it)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- doc$add(&#39;info&#39;, type = &#39;meta&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$append()&lt;/code&gt; appends the given elements as children
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_elem &amp;lt;- xml_elem(&#39;info&#39;, type = &#39;meta&#39;); doc$append(new_elem, ...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$new(name, ...)&lt;/code&gt;, &lt;code&gt;$update(...)&lt;/code&gt; and &lt;code&gt;$add(name, ...)&lt;/code&gt; all accept &lt;code&gt;...&lt;/code&gt; where
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;named arguments&lt;/strong&gt; are added as &lt;em&gt;attributes&lt;/em&gt; of this node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;unnamed argument&lt;/strong&gt; are added as &lt;em&gt;children&lt;/em&gt; of this node&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;doc &amp;lt;- xml_elem(&amp;quot;thing&amp;quot;)
doc$add(&amp;#39;node&amp;#39;)$
  update(style = &amp;quot;color: blue;&amp;quot;)$
  add(&amp;#39;mytag&amp;#39;, &amp;quot;Some example text.&amp;quot;)

doc
&amp;lt;thing&amp;gt;
  &amp;lt;node style=&amp;quot;color: blue;&amp;quot;&amp;gt;
    &amp;lt;mytag&amp;gt;
      Some example text.
    &amp;lt;/mytag&amp;gt;
  &amp;lt;/node&amp;gt;
&amp;lt;/thing&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;parsing-xml-into-a-minixml-document&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Parsing XML into a &lt;code&gt;minixml&lt;/code&gt; document&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;minixml&lt;/code&gt; uses &lt;code&gt;xml2&lt;/code&gt; to parse XML text (or file) into a &lt;code&gt;minixml&lt;/code&gt; document.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_xml &amp;lt;- &amp;quot;&amp;lt;eg&amp;gt;Node contents&amp;lt;/eg&amp;gt;&amp;quot;
doc &amp;lt;- minixml::parse_xml_elem(my_xml)
doc$update(x = 1, y = 2)$
  add(name = &amp;#39;inner&amp;#39;, &amp;#39;inner contents&amp;#39;)

doc
&amp;lt;eg x=&amp;quot;1&amp;quot; y=&amp;quot;2&amp;quot;&amp;gt;
  Node contents
  &amp;lt;inner&amp;gt;
    inner contents
  &amp;lt;/inner&amp;gt;
&amp;lt;/eg&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;more-complex-example-creating-an-xml-x3d-3d-object&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;More complex example: Creating an XML &lt;code&gt;X3D&lt;/code&gt; 3d object&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/X3D&#34;&gt;X3D&lt;/a&gt; is an XML-based 3D object format that is
the successor to &lt;a href=&#34;https://en.wikipedia.org/wiki/VRML&#34;&gt;VRML&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this example, we’ll build a simple 3D cube to view in the browser.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x3d &amp;lt;- xml_elem(&amp;quot;x3d&amp;quot;, width = &amp;quot;300px&amp;quot;, height=&amp;quot;200px&amp;quot;)
shape &amp;lt;- x3d$
  add(&amp;quot;scene&amp;quot;)$
  add(&amp;quot;shape&amp;quot;)

shape$add(&amp;quot;appearance&amp;quot;)$add(&amp;quot;material&amp;quot;, diffuseColor = &amp;quot;0 0 1&amp;quot;)
shape$add(&amp;quot;box&amp;quot;)

x3d
&amp;lt;x3d width=&amp;quot;300px&amp;quot; height=&amp;quot;200px&amp;quot;&amp;gt;
  &amp;lt;scene&amp;gt;
    &amp;lt;shape&amp;gt;
      &amp;lt;appearance&amp;gt;
        &amp;lt;material diffuseColor=&amp;quot;0 0 1&amp;quot; /&amp;gt;
      &amp;lt;/appearance&amp;gt;
      &amp;lt;box /&amp;gt;
    &amp;lt;/shape&amp;gt;
  &amp;lt;/scene&amp;gt;
&amp;lt;/x3d&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;view-the-object&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;View the object&lt;/h3&gt;
&lt;p&gt;To view the X3D object, include it in an HTML document with the &lt;code&gt;x3dom.js&lt;/code&gt;
javascript.&lt;/p&gt;
&lt;p&gt;The following code will run in an R session as an interactive 3d object browser.
On github you’ll just see a short gif.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;html &amp;lt;- glue::glue(&amp;quot;
&amp;lt;html&amp;gt; 
&amp;lt;head&amp;gt; 
  &amp;lt;script type=&amp;#39;text/javascript&amp;#39; src=&amp;#39;http://www.x3dom.org/download/x3dom.js&amp;#39;&amp;gt; &amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body&amp;gt;     {x3d}     &amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;&amp;quot;)

htmltools::html_print(HTML(html))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/minixml/x3d.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `hershey` package - raw data for the Hershey Vector Fonts</title>
      <link>https://coolbutuseless.github.io/2019/09/24/introducing-the-hershey-package-raw-data-for-the-hershey-vector-fonts/</link>
      <pubDate>Tue, 24 Sep 2019 19:35:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/09/24/introducing-the-hershey-package-raw-data-for-the-hershey-vector-fonts/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;hershey&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;hershey &lt;img src=&#34;https://coolbutuseless.github.io/img/hershey/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;a href=&#34;https://travis-ci.org/coolbutuseless/hershey&#34;&gt;&lt;img src=&#34;https://travis-ci.org/coolbutuseless/hershey.svg?branch=master&#34; alt=&#34;Travis build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;hershey&lt;/code&gt; package contains the &lt;a href=&#34;https://en.wikipedia.org/wiki/Hershey_fonts&#34;&gt;Hershey vector fonts&lt;/a&gt; in a number of formats for more convenient use within Rstats.&lt;/p&gt;
&lt;p&gt;The Hershey fonts were developed in the 1960s. Each glyph is defined as collections of staight line segments - hand calculated by Hershey by sketching them on grid paper!&lt;/p&gt;
&lt;p&gt;This package makes available the coordinates of the stroke endpoints for every glyph.&lt;/p&gt;
&lt;p&gt;You may need this package if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you like retro vector fonts&lt;/li&gt;
&lt;li&gt;you need a vector font so you can have complete control of the output&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-09-24-hershey-package_files/figure-html/example_header-1.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;details closed&gt;
&lt;summary&gt; &lt;span title=&#34;Click to open/close&#34; style=&#34;color: #496B80;&#34;&gt; Slideshow (click to open/close)&lt;/span&gt; &lt;/summary&gt;
&lt;img src = &#34;/img/hershey/fontname/animo.gif&#34;&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;details closed&gt;
&lt;summary&gt; &lt;span title=&#34;Click to open/close&#34; style=&#34;color: #496B80;&#34;&gt; Animated Rendering 1 (click to open/close) &lt;/span&gt; &lt;/summary&gt;
&lt;img src = &#34;/img/hershey/fontdraw/animo.gif&#34;&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;details open&gt;
&lt;summary&gt; &lt;span title=&#34;Click to open/close&#34; style=&#34;color: #496B80;&#34;&gt; Animated Rendering 2 (click to open/close) &lt;/span&gt; &lt;/summary&gt;
&lt;img src = &#34;/img/hershey/fontdraw2/animo.gif&#34;&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/hershey&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/hershey&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hershey_raw&lt;/code&gt;: the original encoding for every glyph (See the &lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/hershey-font-format.html&#34;&gt;vignette&lt;/a&gt; for how to parse).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hershey&lt;/code&gt;: a data.frame of the vector strokes for every glyph.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hershey_svg&lt;/code&gt;: a list of SVG paths for every glyph.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vignettes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/animated-stroke-rendering.html&#34;&gt;Animated stroke rendering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/generate-sample-sheet.html&#34;&gt;How to generate a sample sheet for a font&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/hershey-font-format.html&#34;&gt;Description of the raw Hershey font format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/render-glyph-to-svg.html&#34;&gt;Rendering a glyph to SVG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/hershey/articles/visualise-stroke-order.html&#34;&gt;Visualise stroke order&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;glyph-representations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Glyph Representations&lt;/h2&gt;
&lt;p&gt;The following are examples of the representation of the letter &lt;code&gt;A&lt;/code&gt; (glyph 34 in the &lt;code&gt;rowmant&lt;/code&gt; font)&lt;/p&gt;
&lt;div id=&#34;hershey---first-4-strokes-in-the-data.frame-representation&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;hershey&lt;/code&gt; - First 4 strokes in the data.frame representation&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hershey %&amp;gt;% 
  filter(font == &amp;#39;rowmant&amp;#39;, char == &amp;#39;A&amp;#39;) %&amp;gt;%
  filter(stroke %in% 0:3)
# A tibble: 8 x 11
      x     y  left right width stroke   idx glyph font    ascii char 
  &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;fct&amp;gt;  &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;   &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;
1     0    12   -10    10    20 0          1    34 rowmant    65 A    
2    -7    -8   -10    10    20 0          2    34 rowmant    65 A    
3    -1     9   -10    10    20 1          3    34 rowmant    65 A    
4     5    -9   -10    10    20 1          4    34 rowmant    65 A    
5     0     9   -10    10    20 2          5    34 rowmant    65 A    
6     6    -9   -10    10    20 2          6    34 rowmant    65 A    
7     0    12   -10    10    20 3          7    34 rowmant    65 A    
8     7    -9   -10    10    20 3          8    34 rowmant    65 A    &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;hershey_raw---original-encoding&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;hershey_raw&lt;/code&gt; - Original encoding&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hershey_raw$rowmant[[34]]
[1] &amp;quot; 3001 36H\\RFKZ RQIW[ RRIX[ RRFY[ RMUVU RI[O[ RT[[[ RKZJ[ RKZM[ RWZU[ RWYV[ RXYZ[&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;hershey_svg---svg-path-version&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;&lt;code&gt;hershey_svg&lt;/code&gt; - SVG Path version&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hershey_svg$rowmant[[34]]
[1] &amp;quot;M0-12L-7 8M-1-9L5 9M0-9L6 9M0-12L7 9M-5 3L4 3M-9 9L-3 9M2 9L9 9M-7 8L-8 9M-7 8L-5 9M5 8L3 9M5 7L4 9M6 7L8 9&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;drawing-strokes-with-ggplot&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Drawing strokes with &lt;code&gt;ggplot&lt;/code&gt;&lt;/h4&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;hershey %&amp;gt;% 
  filter(font == &amp;#39;rowmant&amp;#39;, char == &amp;#39;A&amp;#39;) %&amp;gt;%
  ggplot(aes(x, y, group = stroke)) + 
  geom_path() + 
  geom_point() + 
  coord_equal() + 
  theme_minimal() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-09-24-hershey-package_files/figure-html/example_rep-1.png&#34; width=&#34;50%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;font-sample-sheets&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Font Sample Sheets&lt;/h2&gt;
&lt;p&gt;Font sample sheets show the representation of every glyph in a font.
Click to view the sample sheets for every font in PDF format.&lt;/p&gt;
&lt;details closed&gt;
&lt;summary&gt; &lt;span title=&#34;Click to open/close&#34; style=&#34;color: #496B80;&#34;&gt; Example font: Cursive (click to reveal) &lt;/span&gt; &lt;/summary&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/hershey/font/cursive.png&#34;&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-all-the-as&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: All the ’A’s&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;glyph_df &amp;lt;- hershey %&amp;gt;% 
  filter(char == &amp;#39;A&amp;#39;) 
  
ggplot(glyph_df) + 
  geom_path(aes(x, y, group = stroke)) + 
  coord_equal() + 
  theme_void() + 
  facet_wrap(~font)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-09-24-hershey-package_files/figure-html/a-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-futura&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Futura!&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;glyph_df &amp;lt;- hershey %&amp;gt;% 
  filter(font == &amp;#39;futuram&amp;#39;, glyph %in% c(32:46)) 
  
ggplot(glyph_df) + 
  geom_path(aes(x, y, group = stroke)) + 
  coord_equal() + 
  theme_void() + 
  facet_wrap(~glyph, labeller = label_both, ncol = 5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-09-24-hershey-package_files/figure-html/futura-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-render-text-string&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: Render text string&lt;/h2&gt;
&lt;p&gt;The function &lt;code&gt;create_string_df()&lt;/code&gt; will create a data.frame of all the characters
in the given string. It will offset each character by the known widths of the
preceding characters to create a well-spaced set of points.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;string_df &amp;lt;- hershey::create_string_df(text = &amp;quot;#RStats&amp;quot;, font = &amp;#39;cursive&amp;#39;)

ggplot(string_df, aes(x, y, group = interaction(char_idx, stroke))) +
  geom_path() +
  geom_point(size = 1) + 
  coord_equal() +
  theme_void()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-09-24-hershey-package_files/figure-html/string-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;references&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Hershey_fonts&#34;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://coopertype.org/event/the_hershey_fonts&#34;&gt;A great presentation about Hershey and the era of the font&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://paulbourke.net/dataformats/hershey/&#34;&gt;Paul Burke’s description of the format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A more modern vector font by &lt;a href=&#34;https://inconvergent.net/&#34;&gt;inconvergent&lt;/a&gt;: &lt;a href=&#34;https://github.com/inconvergent/gridfont&#34;&gt;gridfont&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;logo-design&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Logo design&lt;/h3&gt;
&lt;p&gt;The logo is just the letter &lt;code&gt;H&lt;/code&gt; from the &lt;code&gt;rowmant&lt;/code&gt; font. Each stroke is coloured
by the stroke number within the glyph and the endpoints are shown.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;use-restrictions-on-hershey-fonts&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use Restrictions on Hershey Fonts&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Totally free&lt;/strong&gt; (except if you convert them to the proprietary US NTIS format)&lt;/p&gt;
&lt;details closed&gt;
&lt;p&gt;&lt;summary&gt; &lt;span title=&#34;Click to open/close&#34; style=&#34;color: #496B80;&#34;&gt;The following use restriction was noted in the original font distribution.&lt;/span&gt;&lt;/summary&gt;&lt;/p&gt;
&lt;pre&gt;
    USE RESTRICTION:
    This distribution of the Hershey Fonts may be used by anyone for
    any purpose, commercial or otherwise, providing that:
        1. The following acknowledgements must be distributed with
            the font data:
            - The Hershey Fonts were originally created by Dr.
                A. V. Hershey while working at the U. S.
                National Bureau of Standards.
            - The format of the Font data in this distribution
                was originally created by
                    James Hurt
                    Cognition, Inc.
                    900 Technology Park Drive
                    Billerica, MA 01821
                    (mit-eddie!ci-dandelion!hurt)
        2. The font data in this distribution may be converted into
            any other format *EXCEPT* the format distributed by
            the U.S. NTIS (which organization holds the rights
            to the distribution and use of the font data in that
            particular format). Not that anybody would really
            *want* to use their format... each point is described
            in eight bytes as &#34;xxx yyy:&#34;, where xxx and yyy are
            the coordinate values as ASCII numbers.
&lt;/pre&gt;
&lt;/details&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `minihtml` package for creating HTML documents in R</title>
      <link>https://coolbutuseless.github.io/2019/09/19/introducing-the-minihtml-package-for-creating-html-documents-in-r/</link>
      <pubDate>Thu, 19 Sep 2019 19:35:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/09/19/introducing-the-minihtml-package-for-creating-html-documents-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minihtml&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minihtml &lt;img src=&#34;https://coolbutuseless.github.io/img/minihtml/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minihtml&lt;/code&gt; is a package for building html documents in R.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minihtml&lt;/code&gt; objects are compatible with &lt;a href=&#34;https://cran.r-project.org/package=shiny&#34;&gt;shiny&lt;/a&gt; - see the
&lt;a href=&#34;https://coolbutuseless.github.io/package/minihtml/articles/shiny.html&#34;&gt;vignette&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Need to build&lt;/th&gt;
&lt;th&gt;R6 object&lt;/th&gt;
&lt;th&gt;alternate initialisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;HTML elements&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;htag&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;HTML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_elem()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;HTML document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLDocument$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_doc()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;quick-examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quick Examples&lt;/h2&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;11%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;37%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;HTML Entity&lt;/th&gt;
&lt;th&gt;code&lt;/th&gt;
&lt;th&gt;result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;HTML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;htag$a(href = &#39;http://example.com&#39;, &#34;click here&#34;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;a href=&#34;http://example.com&#34;&amp;gt;click here&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;HTML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HTMLElement$new(&#39;p&#39;, &#34;Hello there&#34;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;p&amp;gt;Hello there&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;HTML elements&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_elem(&#39;p&#39;, &#39;Hello there&#39;)$update(style = &#39;display:none&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;p style=&#34;display:none&#34;&amp;gt;Hello there&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;HTML document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html &amp;lt;- HTMLDocument$new(); html$add(&#39;p&#39;, &#39;hello&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;html&amp;gt; &amp;lt;p&amp;gt;hello&amp;lt;/p&amp;gt; &amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;HTML document&lt;/td&gt;
&lt;td&gt;&lt;code&gt;html_doc(htag$h1(&#34;Big&#34;), htag$p(&#34;Hello&#34;))&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;html&amp;gt; &amp;lt;h1&amp;gt;Big&amp;lt;/h1&amp;gt; &amp;lt;p&amp;gt;Hello&amp;lt;/p&amp;gt; &amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;minihtml&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/minihtml&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minihtml&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;htag-helper-autocomplete-html-tags-and-attributes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;htag&lt;/code&gt; helper (autocomplete HTML tags and attributes)&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;htag&lt;/code&gt; helper is similar to &lt;code&gt;shiny::tag&lt;/code&gt; but offers autocomplete to assist
in writing the code:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minihtml/htag.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;interface&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interface&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Individual elements can be created in a number of ways. E.g. creating a div
&lt;ul&gt;
&lt;li&gt;As a stand-alone element
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_div &amp;lt;- HTMLElement$new(&#39;div&#39;, class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_div &amp;lt;- html_elem(&#39;div&#39;, class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_div &amp;lt;- htag$div(class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;As a sub-element of an existing document or element - the element is created,
added to the parent document (or element) and returned.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;doc &amp;lt;- HTMLDocument$new(); new_div &amp;lt;- doc$add(&#39;div&#39;, class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;doc &amp;lt;- HTMLDocument$new(); new_div &amp;lt;- doc$div(class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elem &amp;lt;- HTMLElement$new(&#39;xxx&#39;); new_div &amp;lt;- elem$add(&#39;div&#39;, class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;elem &amp;lt;- HTMLElement$new(&#39;xxx&#39;); new_div &amp;lt;- elem$div(class = &#39;demo&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$add()&lt;/code&gt; creates an element and adds it to the parent (and returns it)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_div &amp;lt;- doc$add(&#39;div&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$append()&lt;/code&gt; appends the given elements as children
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new_div &amp;lt;- htag$div(); doc$append(new_div, ...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$new(name, ...)&lt;/code&gt;, &lt;code&gt;$update(...)&lt;/code&gt; and &lt;code&gt;$add(name, ...)&lt;/code&gt; all accept &lt;code&gt;...&lt;/code&gt; where
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;named arguments&lt;/strong&gt; are added as &lt;em&gt;attributes&lt;/em&gt; of this node&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;unnamed argument&lt;/strong&gt; are added as &lt;em&gt;children&lt;/em&gt; of this node&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;all-in-one-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;All-in-one example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialse an HTML document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my_div &amp;lt;- htag$div()  #  or use `html_elem(&amp;#39;div&amp;#39;)`

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add a header and body to the html (and then keep the reference these)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
top    &amp;lt;- my_div$div()
bottom &amp;lt;- my_div$div()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add a title to the header, and an H1 to the body
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
top$h1(&amp;quot;Hello RStats&amp;quot;)$update(style = &amp;quot;color: #345678&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a &amp;#39;div&amp;#39; directly within the body, and a &amp;#39;p&amp;#39; within that &amp;#39;div&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bottom$
  update(class=&amp;quot;main&amp;quot;)$
  p(&amp;quot;I needed a more intuitive (to me) method of writing html in R&amp;quot;, style = &amp;#39;font-family: monospace&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# independently create another div
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
div2 &amp;lt;- htag$div(
  htag$p(
    &amp;quot;This is a small demo of the &amp;quot;,
    htag$span(&amp;quot;minihtml&amp;quot;, style = &amp;#39;color: red&amp;#39;),
    &amp;quot;package in action&amp;quot;),
  htag$hr(),
  htag$div(
    htag$button(&amp;quot;And it has a cool button!!&amp;quot;),
    htag$span(&amp;quot;The button - it does nothing&amp;quot;, style = &amp;#39;font-size: 6px&amp;#39;)
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manually append this div to the body
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bottom$append(div2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Because github README&amp;#39;s don&amp;#39;t allow inline styles, the following is a
# screenshot of the rendered HTML
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
my_div&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Raw HTML output. hidden by default --&gt;
&lt;details closed&gt;
&lt;p&gt;&lt;summary&gt; &lt;span title=&#34;Raw HTML&#34;&gt; Raw HTML &lt;/span&gt; &lt;/summary&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1 style=&amp;quot;color: #345678&amp;quot;&amp;gt;
      Hello RStats
    &amp;lt;/h1&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;main&amp;quot;&amp;gt;
    &amp;lt;p style=&amp;quot;font-family: monospace&amp;quot;&amp;gt;
      I needed a more intuitive (to me) method of writing html in R
    &amp;lt;/p&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;
        This is a small demo of the 
        &amp;lt;span style=&amp;quot;color: red&amp;quot;&amp;gt;
          minihtml
        &amp;lt;/span&amp;gt;
        package in action
      &amp;lt;/p&amp;gt;
      &amp;lt;hr /&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;button&amp;gt;
          And it has a cool button!!
        &amp;lt;/button&amp;gt;
        &amp;lt;span style=&amp;quot;font-size: 6px&amp;quot;&amp;gt;
          The button - it does nothing
        &amp;lt;/span&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;!-- Github doesn&#39;t like inline HTML styling. So insert a screenshot --&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minihtml/example1.png&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `minizdog` package for creating zdog 3d illustrations in R</title>
      <link>https://coolbutuseless.github.io/2019/09/17/introducing-the-minizdog-package-for-creating-zdog-3d-illustrations-in-r/</link>
      <pubDate>Tue, 17 Sep 2019 21:05:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/09/17/introducing-the-minizdog-package-for-creating-zdog-3d-illustrations-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minizdog&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minizdog &lt;img src=&#34;https://coolbutuseless.github.io/img/minizdog/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minizdog&lt;/code&gt; is a package for building &lt;a href=&#34;https://zzz.dog&#34;&gt;Zdog&lt;/a&gt; illustrations in R.&lt;/p&gt;
&lt;p&gt;This package was inspired by &lt;a href=&#34;https://twitter.com/OganM&#34;&gt;OganM&lt;/a&gt;’s package called &lt;a href=&#34;https://github.com/oganm/rdog&#34;&gt;rdog&lt;/a&gt;. That package is much more feature complete,
with better documentation and examples and other stuff.&lt;/p&gt;
&lt;p&gt;This package is part of an ongoing exploration of writing document interfaces with
R and &lt;a href=&#34;https://cran.r-project.org/package=R6&#34;&gt;R6&lt;/a&gt; - every drawing feature is
mapped to an R6 object, and these objects are nested within each other to create
the document.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/minizdog&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minizdog&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;all-in-one-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;All-in-one example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialize a document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zdog &amp;lt;- ZdogIllustration$new(zoom = 2, yincrement = 0.03)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a circle as a separate object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ell &amp;lt;- minizdog::ZdogEllipse$new(diameter = 20, stroke = 5, color = &amp;#39;#636&amp;#39;)$
  translate(z = -20)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a rectangle directly as a child of the illustration
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zdog$rect(width = 20, height = 20, stroke = 3)$
  update(fill = TRUE, color = &amp;#39;#e62&amp;#39;)$
  translate(z = -10)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a polygon using the `ztag` helper
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
poly &amp;lt;- ztag$polygon(radius = 40, sides = 6)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# create some text
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
text &amp;lt;- ZdogText$new(value = &amp;quot;#RStats\\n\\nmini\\nzdog&amp;quot;)$
  update(color = &amp;#39;#00f&amp;#39;, textAlign = &amp;#39;center&amp;#39;, fontSize = 20)$
  translate(y = 15)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Append the standalone elements to the main document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zdog$append(ell)
zdog$append(poly)
zdog$append(text)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# If running in Rstudio this will open the zdog illustration in the viewer pane.
# Github limits what a README can show, so this is just a GIF animation of
# what the above javascript creates
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
zdog$show()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/minizdog/badlogo-o.gif&#34;&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;as.character(zdog) # will print just the javascript code
zdog$as_html()     # wraps the javascript in some html boilerplate&lt;/code&gt;&lt;/pre&gt;
&lt;details close&gt;
&lt;p&gt;&lt;summary&gt; &lt;span title=&#34;as.character(zdog) output (JS)&#34;&gt; as.character(zdog) output (JS)&lt;/span&gt; &lt;/summary&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let isSpinning = true;
Zfont.init(Zdog);
var default_font = new Zdog.Font({
  src: &amp;#39;https://cdn.jsdelivr.net/gh/jaames/zfont/demo/fredokaone.ttf&amp;#39;
});
      
let Ill01 = new Zdog.Illustration({
  element: &amp;#39;.zdog-canvas&amp;#39;,
  zoom: 2,
  centered: true,
  dragRotate: true,
  onDragStart: function() {isSpinning = false;}
});
  let Rect01 = new Zdog.Rect({
    stroke: 3,
    width: 20,
    height: 20,
    addTo: Ill01,
    fill: true,
    color: &amp;#39;#e62&amp;#39;,
    translate: { z: -10 }
  });
  let Ellipse01 = new Zdog.Ellipse({
    stroke: 5,
    color: &amp;#39;#636&amp;#39;,
    diameter: 20,
    translate: { z: -20 },
    addTo: Ill01
  });
  let Polygon01 = new Zdog.Polygon({
    radius: 40,
    sides: 6,
    addTo: Ill01
  });
  let Text01 = new Zdog.Text({
    value: &amp;#39;#RStats\n\nmini\nzdog&amp;#39;,
    fontSize: 20,
    textAlign: &amp;#39;center&amp;#39;,
    textBaseline: &amp;#39;left&amp;#39;,
    font: default_font,
    color: &amp;#39;#00f&amp;#39;,
    translate: { y: 15 },
    addTo: Ill01
  });
function animate() {
  // rotate illo each frame
  if (isSpinning) {
    Ill01.rotate.x += 0;
    Ill01.rotate.y += 0.03;
    Ill01.rotate.z += 0;
  }
  Ill01.updateRenderGraph();
  // animate next frame
  requestAnimationFrame( animate );
}
// start animation
animate();&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;details open&gt;
&lt;p&gt;&lt;summary&gt; &lt;span title=&#34;zdog$as_html() output&#34;&gt; zdog$as.html() output &lt;/span&gt; &lt;/summary&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang=&amp;#39;en&amp;#39;&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta charset=&amp;#39;UTF-8&amp;#39;&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;canvas id=&amp;#39;canvas&amp;#39; class=&amp;#39;zdog-canvas&amp;#39; width = &amp;#39;300&amp;#39;, height = &amp;#39;300&amp;#39;&amp;gt;
Your viewer doesn&amp;#39;t support HTML5 canvas
&amp;lt;/canvas&amp;gt;

&amp;lt;script src=&amp;#39;https://unpkg.com/zdog@1/dist/zdog.dist.min.js&amp;#39;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;#39;https://cdn.jsdelivr.net/npm/zfont/dist/zfont.min.js&amp;#39;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;
let isSpinning = true;
Zfont.init(Zdog);
var default_font = new Zdog.Font({
  src: &amp;#39;https://cdn.jsdelivr.net/gh/jaames/zfont/demo/fredokaone.ttf&amp;#39;
});
      
let Ill01 = new Zdog.Illustration({
  element: &amp;#39;.zdog-canvas&amp;#39;,
  zoom: 2,
  centered: true,
  dragRotate: true,
  onDragStart: function() {isSpinning = false;}
});
  let Rect01 = new Zdog.Rect({
    stroke: 3,
    width: 20,
    height: 20,
    addTo: Ill01,
    fill: true,
    color: &amp;#39;#e62&amp;#39;,
    translate: { z: -10 }
  });
  let Ellipse01 = new Zdog.Ellipse({
    stroke: 5,
    color: &amp;#39;#636&amp;#39;,
    diameter: 20,
    translate: { z: -20 },
    addTo: Ill01
  });
  let Polygon01 = new Zdog.Polygon({
    radius: 40,
    sides: 6,
    addTo: Ill01
  });
  let Text01 = new Zdog.Text({
    value: &amp;#39;#RStats\n\nmini\nzdog&amp;#39;,
    fontSize: 20,
    textAlign: &amp;#39;center&amp;#39;,
    textBaseline: &amp;#39;left&amp;#39;,
    font: default_font,
    color: &amp;#39;#00f&amp;#39;,
    translate: { y: 15 },
    addTo: Ill01
  });
function animate() {
  // rotate illo each frame
  if (isSpinning) {
    Ill01.rotate.x += 0;
    Ill01.rotate.y += 0.03;
    Ill01.rotate.z += 0;
  }
  Ill01.updateRenderGraph();
  // animate next frame
  requestAnimationFrame( animate );
}
// start animation
animate();
&amp;lt;/script&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `minicss` package for creating CSS styles and stylesheets in R</title>
      <link>https://coolbutuseless.github.io/2019/09/11/introducing-the-minicss-package-for-creating-css-styles-and-stylesheets-in-r/</link>
      <pubDate>Wed, 11 Sep 2019 22:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/09/11/introducing-the-minicss-package-for-creating-css-styles-and-stylesheets-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minicss&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minicss &lt;img src=&#34;https://coolbutuseless.github.io/img/minicss/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/mini-verse-blue.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/very-experimental-orange.svg&#34; /&gt;
&lt;a href=&#34;https://travis-ci.org/coolbutuseless/minicss&#34;&gt;&lt;img src=&#34;https://travis-ci.org/coolbutuseless/minicss.svg?branch=master&#34; alt=&#34;Travis build status&#34; /&gt;&lt;/a&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The goal of &lt;code&gt;minicss&lt;/code&gt; is to be able to programatically create CSS styles and style sheets
from within R.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minicss&lt;/code&gt; objects and output are compabile with Shiny (see the &lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/shiny.html&#34;&gt;vignette&lt;/a&gt;)&lt;/p&gt;
&lt;div id=&#34;overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;minicss&lt;/code&gt; is a collection of R6 objects a user creates and encapsulates within
one other to build CSS style sheets&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;Need to build…&lt;/th&gt;
&lt;th&gt;R6 object&lt;/th&gt;
&lt;th&gt;alternate initialisation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;CSS Properties&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_prop&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;CSS Selectors&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Selector$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_sel()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;KeyFrames&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Keyframe$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_keyframe()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Keyframes$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_keyframes()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;CSS Styles&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Style$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_style()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;CSS Style Sheets&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StyleSheet$new()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_stylesheet()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div id=&#34;quick-examples&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Quick examples&lt;/h3&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;17%&#34; /&gt;
&lt;col width=&#34;50%&#34; /&gt;
&lt;col width=&#34;32%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;CSS Entity&lt;/th&gt;
&lt;th&gt;code&lt;/th&gt;
&lt;th&gt;result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Properties&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_prop$&#39;font-family&#39;$cursive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;font-family: cursive;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_prop$&#39;animation-delay&#39;$set(12)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;animation-delay: 12;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Selectors&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_sel(&#39;#cindy&#39;)$child_of(&#39;#carol&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#carol &amp;gt; #cindy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;Inline Styles&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_style(colour=&#39;red&#39;)$update(margin=0)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;color: red; margin: 0;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;CSS Styles&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_style(&#34;.red&#34;, colour=&#39;red&#39;, width=&#39;100%&#39;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.red { color: red; width: 100% }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_style(&#34;.big&#34;, css_prop$&#39;font-size&#39;$set(&#39;12px&#39;))&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.big { font-size: 12px; }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;Style Sheets&lt;/td&gt;
&lt;td&gt;&lt;code&gt;css_stylesheet(style1, style2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.style1 {color:red;}  .style2{color:blue;}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/minicss&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minicss&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;p&gt;The CSS specification is a bit wart-y,
so there are plenty of weird cases that need to be explicitly handled. Some of
these cases are currently handled by &lt;code&gt;minicss&lt;/code&gt;, and I’ll add others as
they’re needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;vignettes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vignettes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/Selectors.html&#34;&gt;CSS Selectors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/Properties.html&#34;&gt;CSS Property helper &lt;code&gt;css_prop&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/Styles.html&#34;&gt;Styles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/StyleSheets.html&#34;&gt;StyleSheets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/package/minicss/articles/animation.html&#34;&gt;Keyframes and Animation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;example-all-in-one-example&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Example: All-in-one example&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Build some selectors
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sel1 &amp;lt;- Selector$new(&amp;#39;h1&amp;#39;)$class(&amp;#39;demo&amp;#39;)
sel2 &amp;lt;- css_sel(&amp;quot;h2&amp;quot;)$class(&amp;#39;highlight&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Build some keyframes for animating elements
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kf1 &amp;lt;- Keyframe$new(&amp;#39;from&amp;#39;, color = &amp;#39;#123456&amp;#39;)
kf2 &amp;lt;- css_keyframe(&amp;#39;to&amp;#39;, color = &amp;#39;#1289ae&amp;#39;)$translateX(10, &amp;#39;px&amp;#39;)
keyframes  &amp;lt;- Keyframes$new(&amp;quot;pulser&amp;quot;, kf1, kf2)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Build some styles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
style1 &amp;lt;- Style$new(
  sel1, 
  css_prop$animation(name = &amp;#39;pulser&amp;#39;, duration = 0.8, direction = &amp;#39;alternate&amp;#39;)
)
style2 &amp;lt;- Style$new(&amp;#39;.mini&amp;#39;, background_color = &amp;#39;green&amp;#39;)
style3 &amp;lt;- Style$new(sel2, css_prop$`text-decoration`$underline)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a style sheet
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stylesheet &amp;lt;- css_stylesheet(style1, style2, style3, keyframes)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Change my mind about the background colour of &amp;#39;style2&amp;#39;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
style2$update(background_colour = &amp;#39;#a0a0ff&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an inline style
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline_style &amp;lt;- Style$new(border = &amp;quot;1px solid #123456&amp;quot;)$
  update(width = &amp;quot;50%&amp;quot;, padding = &amp;#39;10px&amp;#39;)$
  as_inline()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Insert the stylesheet in an example HTML document
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
html &amp;lt;- glue::glue(&amp;quot;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
{stylesheet}
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div style=&amp;#39;{inline_style}&amp;#39;&amp;gt;
&amp;lt;h1 class = &amp;#39;demo&amp;#39;&amp;gt; Hello #Rstats&amp;lt;/h1&amp;gt;
&amp;lt;h2 class=&amp;#39;highlight&amp;#39;&amp;gt; A minicss demo! &amp;lt;/h2&amp;gt;
This is an example of using &amp;lt;span class=&amp;#39;mini&amp;#39;&amp;gt;minicss&amp;lt;/span&amp;gt; to manipulate CSS.
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Example&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
h1.demo { animation: pulser 0.8s infinite alternate; }
.mini { background-color: #a0a0ff; }
h2.highlight { text-decoration: underline; }
@keyframes pulser {
    from { color: #123456; }
    to {
        color: #1289ae;
        transform: translateX(10px);
    }
}
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div style=&amp;#39;border: 1px solid #123456; width: 50%; padding: 10px;&amp;#39;&amp;gt;
&amp;lt;h1 class = &amp;#39;demo&amp;#39;&amp;gt; Hello #Rstats&amp;lt;/h1&amp;gt;
&amp;lt;h2 class=&amp;#39;highlight&amp;#39;&amp;gt; A minicss demo! &amp;lt;/h2&amp;gt;
This is an example of using &amp;lt;span class=&amp;#39;mini&amp;#39;&amp;gt;minicss&amp;lt;/span&amp;gt; to manipulate CSS.
&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Example&lt;/title&gt;
  &lt;style&gt;
h1.demo { animation: pulser 0.8s infinite alternate; }
.mini { background-color: #a0a0ff; }
h2.highlight { text-decoration: underline; }
@keyframes pulser {
    from { color: #123456; }
    to {
        color: #1289ae;
        transform: translateX(10px);
    }
}
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div style=&#39;border: 1px solid #123456; width: 50%; padding: 10px;&#39;&gt;
&lt;h1 class = &#39;demo&#39;&gt; Hello #Rstats&lt;/h1&gt;
&lt;h2 class=&#39;highlight&#39;&gt; A minicss demo! &lt;/h2&gt;
This is an example of using &lt;span class=&#39;mini&#39;&gt;minicss&lt;/span&gt; to manipulate CSS.
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `minipdf` package for writing raw PDFs</title>
      <link>https://coolbutuseless.github.io/2019/08/14/introducing-the-minipdf-package-for-writing-raw-pdfs/</link>
      <pubDate>Wed, 14 Aug 2019 14:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/08/14/introducing-the-minipdf-package-for-writing-raw-pdfs/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minipdf&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minipdf &lt;img src=&#34;https://coolbutuseless.github.io/img/minipdf/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minipdf&lt;/code&gt; is a package for creating simple, single-page PDF documents written in pure R.&lt;/p&gt;
&lt;p&gt;This package is very, very far from supporting the full &lt;a href=&#34;https://www.adobe.com/devnet/pdf/pdf_reference.html&#34;&gt;PDF spec&lt;/a&gt;
(which is over 750 pages!), but it supports enough to draw simple figures - for
example the package logo was created with the package itself.&lt;/p&gt;
&lt;div id=&#34;supported-features&#34; class=&#34;section level4&#34;&gt;
&lt;h4&gt;Supported features&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Documents with a single page only&lt;/li&gt;
&lt;li&gt;Only one font per document (set during initialization)&lt;/li&gt;
&lt;li&gt;Objects: Text, lines, polylines, polygons, rectangles and circles&lt;/li&gt;
&lt;li&gt;Attributes: Fill colour (including alpha), stroke colour (including alpha), linewidth, linetype&lt;/li&gt;
&lt;li&gt;Clipping regions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Currently there is no support for annotations or any sort of text layout.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PDFDocument&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;an R6 class for building a PDF document&lt;/li&gt;
&lt;li&gt;object methods: &lt;code&gt;add_line()&lt;/code&gt;, &lt;code&gt;add_rect()&lt;/code&gt;, &lt;code&gt;add_polyline()&lt;/code&gt;, &lt;code&gt;add_polygon()&lt;/code&gt;, &lt;code&gt;add_text()&lt;/code&gt;,
&lt;code&gt;add_circle()&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;other methods: &lt;code&gt;set_clip_rect()&lt;/code&gt;, &lt;code&gt;write_pdf()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A suite of functions that wrap the R6 class for easier use with a pipe.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/minipdf&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minipdf&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future-possibilities&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future possibilities&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Better text handling (multiple fonts per document)&lt;/li&gt;
&lt;li&gt;Annotations&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;shoulders-of-giants&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shoulders of Giants&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=R6&#34;&gt;R6 authors&lt;/a&gt; for putting together such an intuitive OO system for R&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/RaphaelS101&#34;&gt;Raphael Sonabend&lt;/a&gt; for writing the &lt;a href=&#34;https://cran.r-project.org/package=R62S3&#34;&gt;R62S3&lt;/a&gt; package - this package automatically creates wrappers for R6 methods so that they be called as regular functions. I’ve re-implemented a cut-down version of &lt;code&gt;R62S3::R62Fun()&lt;/code&gt; as part of &lt;code&gt;minipdf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;references&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.adobe.com/devnet/pdf/pdf_reference.html&#34;&gt;PDF specification document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://preserve.mactech.com/articles/mactech/Vol.15/15.09/PDFIntro/index.html&#34;&gt;PDF: An Introduction for Programmers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.idrsolutions.com/2010/09/grow-your-own-pdf-file-part-1-pdf-objects-and-data-types/&#34;&gt;Make your own PDF file&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-simple-pdf-with-the-r6-interface&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a simple PDF with the R6 interface&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Initialise the document
# Draw a pretty geometric pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc &amp;lt;- minipdf::PDFDocument$new(width = 400, height = 400)

for (i in seq(0, 400, 20)) {
  pdfdoc$add_line(i    ,     0,   400,     i, stroke = &amp;#39;#00000020&amp;#39;)
  pdfdoc$add_line(400  ,     i, 400-i,   400, stroke = &amp;#39;#00000020&amp;#39;)
  pdfdoc$add_line(400-i,   400,     0, 400-i, stroke = &amp;#39;#00000020&amp;#39;)
  pdfdoc$add_line(0    , 400-i,     i,     0, stroke = &amp;#39;#00000020&amp;#39;)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Draw a circle in the centre with some text around
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$add_circle(200, 200, 50, fill = &amp;quot;#12345680&amp;quot;, stroke = NULL)

ncolours &amp;lt;- 40
pal &amp;lt;- rainbow(ncolours)
for (i in seq(ncolours)) {
  pdfdoc$add_text(&amp;quot;                        #Rstats&amp;quot;, x = 200, y = 200, 
                  angle = (1 - i)/ncolours * 360, fill = pal[i])
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write the PDF to file
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$write_pdf(&amp;quot;/img/minipdf/example1.pdf&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minipdf/example1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-a-simple-pdf-with-the-pipe-compatible-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating a simple PDF with the pipe-compatible functions&lt;/h2&gt;
&lt;p&gt;For those more used to working with pipes, there are pipe-friendly versions of
most methods. These all take the R6 &lt;code&gt;PDFDocument&lt;/code&gt; class as their first argument.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pdfdoc &amp;lt;- create_pdfdoc(width = 400, height = 400, font = &amp;#39;Helvetica-Bold&amp;#39;)

pal &amp;lt;- viridisLite::viridis(80)
i   &amp;lt;- 0
for (x in seq(20, 400, 40)) {
  for (y in seq(100, 400, 40)) {
    i &amp;lt;- i + 1
    pdfdoc &amp;lt;- pdfdoc %&amp;gt;% 
      add_circle(x, y, r = 20, fill = pal[i])
  }
}

pdfdoc &amp;lt;- pdfdoc %&amp;gt;%
  add_text(&amp;quot;Pipe-friendly!&amp;quot;, x = 10, y = 20, size = 65, stroke = &amp;#39;grey50&amp;#39;, fill = &amp;#39;lightblue&amp;#39;, text_mode = 2) %&amp;gt;%
  add_rect(0, 0, 400, 400, fill = NULL, stroke = &amp;#39;grey70&amp;#39;)

pdfdoc %&amp;gt;% write_pdf(&amp;quot;/img/minipdf/example-pipe.pdf&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minipdf/example-pipe.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-the-logo-for-this-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating the logo for this package&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Design inspiration: the whole decade of the 1970s.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the hexagonal clipping path
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
spacing &amp;lt;- 200
w &amp;lt;- sqrt(3) * spacing
h &amp;lt;- 2       * spacing

qh &amp;lt;- h/4
hw &amp;lt;- w/2

path &amp;lt;- glue(&amp;quot;
{hw} {     0} m
{ 0} {    qh} l
{ 0} {3 * qh} l
{hw} {4 * qh} l
{ w} {3 * qh} l
{ w} {    qh} l
{hw} {     0} l
&amp;quot;)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Setup circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
o1 &amp;lt;- 80
o2 &amp;lt;- 60
o3 &amp;lt;- 40
o4 &amp;lt;- 30

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the PDF document with hexagonal clipping path
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc &amp;lt;- PDFDocument$new(width = w, height = h, font = &amp;#39;Courier-Bold&amp;#39;)
pdfdoc$add_clip_stream(clip_path = path)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solid Background colour
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$add_rect(0, 0, w, h, fill = &amp;quot;#A84128&amp;quot;, stroke = NULL)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Circles. Lots of circles
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$add_circle(x = hw + o1, y = 2*qh + o1, r = o1    , fill = &amp;#39;#f8b918&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw + o1, y = 2*qh - o1, r = o1    , fill = &amp;#39;#f8b918&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o1, y = 2*qh + o1, r = o1    , fill = &amp;#39;#f8b918&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o1, y = 2*qh - o1, r = o1    , fill = &amp;#39;#f8b918&amp;#39;, stroke = NULL)

pdfdoc$add_circle(x = hw + o2, y = 2*qh + o2, r = o2-8.5, fill = &amp;#39;#ee9421&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw + o2, y = 2*qh - o2, r = o2-8.5, fill = &amp;#39;#ee9421&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o2, y = 2*qh + o2, r = o2-8.5, fill = &amp;#39;#ee9421&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o2, y = 2*qh - o2, r = o2-8.5, fill = &amp;#39;#ee9421&amp;#39;, stroke = NULL)

pdfdoc$add_circle(x = hw + o3, y = 2*qh + o3, r = o3-17 , fill = &amp;#39;#e75920&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw + o3, y = 2*qh - o3, r = o3-17 , fill = &amp;#39;#e75920&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o3, y = 2*qh + o3, r = o3-17 , fill = &amp;#39;#e75920&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o3, y = 2*qh - o3, r = o3-17 , fill = &amp;#39;#e75920&amp;#39;, stroke = NULL)

pdfdoc$add_circle(x = hw + o4, y = 2*qh + o4, r = 10    , fill = &amp;#39;#Af2a33&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw + o4, y = 2*qh - o4, r = 10    , fill = &amp;#39;#Af2a33&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o4, y = 2*qh + o4, r = 10    , fill = &amp;#39;#Af2a33&amp;#39;, stroke = NULL)
pdfdoc$add_circle(x = hw - o4, y = 2*qh - o4, r = 10    , fill = &amp;#39;#Af2a33&amp;#39;, stroke = NULL)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Label
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$add_text(&amp;quot;minipdf&amp;quot;, x = hw+5, y = 15, fill = &amp;#39;#ffffff&amp;#39;, size = 44, angle = 30)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write the PDF to file
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pdfdoc$write_pdf(&amp;quot;/img/minipdf/logo.pdf&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minipdf/logo.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `lofi` package for low-fidelity/low-bit data representations</title>
      <link>https://coolbutuseless.github.io/2019/08/06/introducing-the-lofi-package-for-low-fidelity/low-bit-data-representations/</link>
      <pubDate>Tue, 06 Aug 2019 19:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/08/06/introducing-the-lofi-package-for-low-fidelity/low-bit-data-representations/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;lofi&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;lofi &lt;img src=&#34;https://coolbutuseless.github.io/img/lofi/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;http://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;http://img.shields.io/badge/dependencies-zero-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The goal of &lt;code&gt;lofi&lt;/code&gt; is to squeeze multiple, low-fidelity representations of colours
and numbers into the 32-bits of a single, standard integer in R.&lt;/p&gt;
&lt;p&gt;This low-fidelity representation of values (a.k.a. &lt;em&gt;lofi&lt;/em&gt;) is usually only an
approximation of the original values, and reconstructed values will most likely
be slightly different from the original.&lt;/p&gt;
&lt;p&gt;Visit the &lt;a href=&#34;https://coolbutuseless.github.io/package/lofi/&#34;&gt;webpage&lt;/a&gt; for more
in-depth documentation.&lt;/p&gt;
&lt;div id=&#34;whats-in-the-box&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in the box&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pack()&lt;/code&gt; and &lt;code&gt;unpack()&lt;/code&gt; are the key functions for packing/unpacking multiple
values into the bits of an integer&lt;/li&gt;
&lt;li&gt;There is a suite of low-level functions for handling each particular supported type
e.g. &lt;code&gt;dbl_to_lofi()&lt;/code&gt; and &lt;code&gt;lofi_to_dbl()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/lofi&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/lofi&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;pack-and-unpack&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;pack()&lt;/code&gt; and &lt;code&gt;unpack()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;pack()&lt;/code&gt; function will encode a set of values into the bits
of a single integer. The &lt;code&gt;unpack()&lt;/code&gt; function will reconstruct the original values
from this single integer.&lt;/p&gt;
&lt;p&gt;The schematic below illustrates the method by which a list of values is packed into
a single integer and then unpacked back into the list of values. &lt;code&gt;pack()&lt;/code&gt; and
&lt;code&gt;unpack()&lt;/code&gt; in turn rely on some lower level functions &lt;code&gt;X_to_lofi()&lt;/code&gt; and &lt;code&gt;lofi_to_X()&lt;/code&gt;
(as indicated in the yellow boxes).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/lofi/pack-unpack.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The key to the process is the &lt;strong&gt;packing specification&lt;/strong&gt; (a.k.a. &lt;code&gt;pack_spec&lt;/code&gt;)
which defines the type of value you want to store how many bits are
used to store each value.&lt;/p&gt;
&lt;p&gt;Steps for using this package:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Define a &lt;code&gt;pack_spec&lt;/code&gt; defining how each value is converted to lofi&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;pack()&lt;/code&gt; on a named list of values, along with the &lt;code&gt;pack_spec&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Receive back a single integer containing all the packed lofi bits&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;unpack()&lt;/code&gt; on the single integer (along with the &lt;code&gt;pack_spec&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Receive a list of reconstructed values which are the same as the original values -
but maybe with some loss of precision.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;pack_spec&lt;/code&gt; defines information on packing the following types:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;type&lt;/th&gt;
&lt;th&gt;lossless?&lt;/th&gt;
&lt;th&gt;nbits&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;th&gt;signed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;pack standard integer&lt;/td&gt;
&lt;td&gt;optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;logical&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;standard 1-bit logical. zero-padded if needed&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;choice&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;almost like a factor representation&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;double&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;pack a standard double&lt;/td&gt;
&lt;td&gt;optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;colour&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;3-24&lt;/td&gt;
&lt;td&gt;pack a hex colour e.g. #123456&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;scaled&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;pack a range into the given bits&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;custom&lt;/td&gt;
&lt;td&gt;Possibly&lt;/td&gt;
&lt;td&gt;1-32&lt;/td&gt;
&lt;td&gt;user specified functions used to pack/unpack&lt;/td&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The integer, logical and choice types are lossless, and original values can be perfectly reconstructed
by &lt;code&gt;unpack()&lt;/code&gt;. The double, colour and scaled types all quantize the inputs in some
way and lose information - thus the original value is always &lt;em&gt;imperfectly&lt;/em&gt; reconstructed (except
in very particular circumstances).&lt;/p&gt;
&lt;p&gt;For information on the specification for each type, see &lt;code&gt;?lofi::pack&lt;/code&gt; or &lt;a href=&#34;https://coolbutuseless.github.io/package/lofi/articles/packing-specification.html&#34;&gt;&lt;code&gt;vignette(&#34;packing-specification&#34;, package=&#39;lofi&#39;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;example---packunpack-the-first-row-of-iris-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - &lt;code&gt;pack/unpack&lt;/code&gt; the first row of &lt;code&gt;iris&lt;/code&gt; data&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;iris&lt;/code&gt; dataset gives the measurements in cm of the variables sepal length and width,
and petal length and width, respectively, for 50 flowers from each of 3 species of iris.
The first rows of the data are shown below:&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-1&#34;&gt;Table 1: &lt;/span&gt;First rows of iris data&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;Sepal.Length&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Sepal.Width&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Petal.Length&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Petal.Width&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Species&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;5.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;setosa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4.9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;setosa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;setosa&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code&gt;pack_spec&lt;/code&gt; for the data seen in iris is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Sepal.Length&lt;/code&gt; is a floating point value with 1 decimal place with a maximum value of 7.9.
This could be multiplied by 10, converted to an integer and stored in 7 bits.&lt;/li&gt;
&lt;li&gt;Similarly for &lt;code&gt;Sepal.Width&lt;/code&gt;, &lt;code&gt;Petal.Length&lt;/code&gt; and &lt;code&gt;Petal.Width&lt;/code&gt; - after multiplying by 10, and
treating as an integer, these values could all by stored in 6, 7, and 5 bits respectively.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Species&lt;/code&gt; is a choice from 3 options, so in the best case we only need 2 bits to store this information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The defined &lt;code&gt;pack_spec&lt;/code&gt; is stored as a list:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Can perfectly pack &amp;#39;iris&amp;#39; into 27 bits per row.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pack_spec &amp;lt;- list(
  Sepal.Length = list(type = &amp;#39;integer&amp;#39;, nbits = 7, mult = 10, signed = FALSE),
  Sepal.Width  = list(type = &amp;#39;integer&amp;#39;, nbits = 6, mult = 10, signed = FALSE),
  Petal.Length = list(type = &amp;#39;integer&amp;#39;, nbits = 7, mult = 10, signed = FALSE),
  Petal.Width  = list(type = &amp;#39;integer&amp;#39;, nbits = 5, mult = 10, signed = FALSE),
  Species      = list(type = &amp;#39;choice&amp;#39; , nbits = 2,
                      options = c(&amp;#39;setosa&amp;#39;, &amp;#39;versicolor&amp;#39;, &amp;#39;virginica&amp;#39;))
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now take the first row of &lt;code&gt;iris&lt;/code&gt; and &lt;code&gt;pack()&lt;/code&gt; it:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lofi::pack(iris[1, ], pack_spec)
[1] 54052616&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the first row of iris has now been packed into the integer: &lt;strong&gt;54052616&lt;/strong&gt;.&lt;br /&gt;
If this integer is viewed as the 32 bits which make it up, the different lofi data
representations can be identified:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/lofi/iris-bits.png&#34; /&gt;&lt;/p&gt;
&lt;p&gt;If the integer is now &lt;strong&gt;&lt;code&gt;unpack()ed&lt;/code&gt;&lt;/strong&gt;, we get back the original data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lofi::unpack(54052616L, pack_spec)
$Sepal.Length
[1] 5.1

$Sepal.Width
[1] 3.5

$Petal.Length
[1] 1.4

$Petal.Width
[1] 0.2

$Species
[1] &amp;quot;setosa&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For an example of using &lt;code&gt;lofi&lt;/code&gt; to pack an entire data.frame see &lt;a href=&#34;https://coolbutuseless.github.io/package/lofi/articles/packing-a-data-frame.html&#34;&gt;&lt;code&gt;vignette(&#34;packing-a-data-frame&#34;, package=&#39;lofi&#39;)&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Using random bits to generate random numbers</title>
      <link>https://coolbutuseless.github.io/2019/07/19/using-random-bits-to-generate-random-numbers/</link>
      <pubDate>Fri, 19 Jul 2019 05:40:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/07/19/using-random-bits-to-generate-random-numbers/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Problem: How do you randomly generate any possible floating point number,
including NAs and Infs?&lt;/p&gt;
&lt;p&gt;Details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I wanted everything from the super small &lt;code&gt;3.1e-15&lt;/code&gt; to the super large &lt;code&gt;6.6e230&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I wanted &lt;code&gt;Inf&lt;/code&gt; and &lt;code&gt;NA&lt;/code&gt; to be possible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://twitter.com/Emil_Hvitfeldt&#34;&gt;Emil Hvitfeldt&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/@michael_chirico&#34;&gt;Michael Chirico&lt;/a&gt; for their assistance, ideas and feedback!&lt;/p&gt;
&lt;div id=&#34;attempt-1---runif&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Attempt 1 - &lt;code&gt;runif()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;My first attempt using &lt;code&gt;runif()&lt;/code&gt; to generate any possible number between 0 and
the maximum double was &lt;strong&gt;never going to work&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rand_uniform &amp;lt;- function(N) {
  runif(N, min = 0, max = .Machine$double.xmax)
}

rand_uniform(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 4.773031e+307 6.689646e+307 1.029815e+308 1.632679e+308 3.625622e+307
 [6] 1.615029e+308 1.698236e+308 1.187912e+308 1.130954e+308 1.110728e+307&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given that the maximum double value on R is approx &lt;code&gt;2x10^308&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;50% of all numbers in the range &lt;code&gt;[0, max_double]&lt;/code&gt; are above &lt;code&gt;1x10^308&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;99% of all numbers in the range &lt;code&gt;[0, max_double]&lt;/code&gt; are above &lt;code&gt;2x10^306&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So 99.99% of all numbers sampled from a uniform distribution in the range &lt;code&gt;[0, max_double]&lt;/code&gt;
will be above &lt;code&gt;2x10^304&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is never going to give me the diversity of floating point numbers I wanted.&lt;/p&gt;
&lt;p&gt;Also, &lt;code&gt;runif()&lt;/code&gt; will never generate an &lt;code&gt;NA&lt;/code&gt; or &lt;code&gt;Inf&lt;/code&gt; value.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;attempt-2---random-magnitude-and-significand-in-base-10&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Attempt 2 - random magnitude and significand in base 10&lt;/h1&gt;
&lt;p&gt;Separately draw random numbers for the leading part and exponential part of the
double&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rand_power10 &amp;lt;- function(N) {
  runif(N, -1, 1) * 10^runif(N, -308, 308)
}

rand_power10(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] -3.530508e+267 -3.094719e-178   1.009171e+93 -5.093762e-232  2.188117e-144
 [6]  -3.229847e-73  7.712072e-301   3.498596e-73 -1.287197e+227   2.507201e-99&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Gives a better spread of random doubles&lt;/li&gt;
&lt;li&gt;Not sure that it will ever generate &lt;code&gt;NA&lt;/code&gt; or &lt;code&gt;Inf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Misses out some numbers - e.g. &lt;code&gt;1.5 x 10^308&lt;/code&gt; will never be output by this method&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;attempt-3---random-magnitude-and-significand-in-base-2&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Attempt 3 - random magnitude and significand in base 2&lt;/h1&gt;
&lt;p&gt;Separately draw random numbers for the leading part and exponential part of the
double, but do this as powers of 2, no powers of 10&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rand_power2 &amp;lt;- function(N) {
  runif(N, -1, 1) * 2^runif(N, -1024, 1024)
}

rand_power2(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] -2.635011e+196   9.186218e+89 -3.482499e+172  -3.126403e+32   1.375545e+18
 [6]  8.286859e+177  7.923594e-295  -7.186193e-15  7.487349e+142 -1.174630e+118&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Gives a great spread of random doubles&lt;/li&gt;
&lt;li&gt;I think this covers the entire range of values&lt;/li&gt;
&lt;li&gt;Not sure that it will ever generate &lt;code&gt;NA&lt;/code&gt; or &lt;code&gt;Inf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;attempt-4---generate-64-random-bits---1-bit-at-atime&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Attempt 4 - Generate 64 random bits - 1 bit at atime&lt;/h1&gt;
&lt;p&gt;Generate any possible 64-bit pattern and cast it to a double precision floating points value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rand_bits1 &amp;lt;- function(N) {
  readBin(
    packBits(
      sample(as.raw(c(0, 1)), 64 * N, replace = TRUE),
      type = &amp;#39;raw&amp;#39;
    ),
    what = &amp;#39;double&amp;#39;,
    n    = N
  )
}

rand_bits1(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] -1.764955e-298 -2.887630e+176 -1.333649e+299  3.632060e-292   5.835171e-46
 [6] -1.699497e-298  1.461211e-180 -1.370493e-195  5.631333e-256 -1.145778e-215&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Guaranteed to be able to generate every possible 64bit number&lt;/li&gt;
&lt;li&gt;Can generate &lt;code&gt;NA&lt;/code&gt; and &lt;code&gt;Inf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;attempt-5---generate-64-random-bits---8-bits-at-a-time&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Attempt 5 - Generate 64 random bits - 8 bits at a time&lt;/h1&gt;
&lt;p&gt;Generate any possible 64-bit pattern and cast it to a double precision floating points value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rand_bits8 &amp;lt;- function(N) {
  readBin(
    sample(as.raw(0:255), N * 8, replace = TRUE),
    what = &amp;#39;double&amp;#39;,
    n    = N
  )
}

rand_bits8(10)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] -5.384031e+226  -4.136980e+04  4.671568e+278 -1.640025e-283   1.392010e-49
 [6]  7.343209e+243  -3.141708e-65 -2.390032e+198 -2.806815e-299  3.123026e+131&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Guaranteed to be able to generate every possible 64bit number&lt;/li&gt;
&lt;li&gt;Can generate &lt;code&gt;NA&lt;/code&gt; and &lt;code&gt;Inf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Benchmark&lt;/h1&gt;
&lt;p&gt;Quick benchmark of the various methods&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-07-19-random-numbers-by-generating-random-bits_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>poissoned - a package for poisson disc sampling</title>
      <link>https://coolbutuseless.github.io/2019/06/25/poissoned-a-package-for-poisson-disc-sampling/</link>
      <pubDate>Tue, 25 Jun 2019 05:40:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/06/25/poissoned-a-package-for-poisson-disc-sampling/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;poissoned&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;poissoned&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;!-- badges: end --&gt;
&lt;p&gt;&lt;code&gt;poissoned&lt;/code&gt; is an Rstats implementation of the poisson disk sampling algorithm from
&lt;a href=&#34;https://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf&#34;&gt;Bridson’s paper - Fast Poisson Disk Sampling in Arbitrary Dimensions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only implemented the 2d case&lt;/li&gt;
&lt;li&gt;adjusted the algorithm in order to ensure repeatable/tileable samples with
minimal artifacts at the joins&lt;/li&gt;
&lt;li&gt;similar in purpose to &lt;a href=&#34;https://twitter.com/W_R_Chase&#34;&gt;Will Chase’s&lt;/a&gt; package &lt;a href=&#34;https://github.com/will-r-chase/poissondisc&#34;&gt;{poissondisc}&lt;/a&gt;. However, &lt;code&gt;poissoned&lt;/code&gt;
has a a completely different implementation which ends up being much faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/poissoned&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/poissoned&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic Usage&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(poissoned)

set.seed(1)
points &amp;lt;- poissoned::poisson_disc(ncols = 50, nrows = 35, cell_size = 10, verbose = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;poisson_disc(): 500x350, minimum distance = 14.14&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(points) +
  geom_point(aes(x, y)) +
  theme_bw() +
  coord_fixed() +
  theme(
    panel.grid = element_blank(),
    axis.title = element_blank()
  ) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-06-25-poisson-disc-sampling_files/figure-html/example-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;tileability&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Tileability&lt;/h1&gt;
&lt;p&gt;The points generated from &lt;code&gt;poissoned::poisson_disc()&lt;/code&gt; are tileable in that there
should be minimal artifacts at the joins.&lt;/p&gt;
&lt;p&gt;In the graph below, the initial set of points (highlighted in blue) were manually replicated
and offset eight times.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-06-25-poisson-disc-sampling_files/figure-html/tileability-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tileability---details&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Tileability - details&lt;/h1&gt;
&lt;p&gt;Tileability is achieved by copying edge points to outside the opposite edge - this
simulates a toroidal coordinate system such that the canvas wraps around on itself.&lt;/p&gt;
&lt;p&gt;These boundary points are retrievable by setting &lt;code&gt;keep_boundary = TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the following plot, the dashed line indicates the limits of the point set,
and the blue points are transated points copied from the opposite edge.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;points &amp;lt;- poissoned::poisson_disc(ncols = 30, nrows = 20, cell_size = 10, keep_boundary = TRUE, verbose = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;poisson_disc(): 300x200, minimum distance = 14.14&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;points$boundary &amp;lt;- with(points, x &amp;lt; 0 | y &amp;lt; 0 | x &amp;gt; 300 | y &amp;gt; 200)

ggplot(points) +
  geom_rect(xmin = 0, xmax = 300, ymin = 0, ymax = 200, fill = NA, colour = &amp;#39;#a0a0a0&amp;#39;, linetype = 2) + 
  geom_point(aes(x, y, colour = boundary)) +
  theme_void() +
  coord_fixed() +
  theme(legend.position = &amp;#39;none&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-06-25-poisson-disc-sampling_files/figure-html/tileability_details-1.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Drawing Fractals with grid graphics - part 2</title>
      <link>https://coolbutuseless.github.io/2019/04/29/drawing-fractals-with-grid-graphics-part-2/</link>
      <pubDate>Mon, 29 Apr 2019 16:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/29/drawing-fractals-with-grid-graphics-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;l-system-fractals-with-grid-graphics-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;L-system fractals with &lt;code&gt;grid&lt;/code&gt; graphics in R&lt;/h2&gt;
&lt;p&gt;This is a follow-up to the &lt;a href=&#34;https://coolbutuseless.github.io/2019/04/27/drawing-fractals-with-grid-graphics-part-1/&#34;&gt;prior post&lt;/a&gt; - by changing
the axiom and the L-system production rules you can change the type of fractal produced&lt;/p&gt;
&lt;p&gt;Rather than simply calculating and drawing lines, I am interested in how viewports
in the &lt;code&gt;grid&lt;/code&gt; system work. So to draw L-systems, the movement and rotation of lines
are carried out by pushing new viewports on the viewing stack.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sierpinski-arrowhead-l-system-axiom-rules-and-drawingviewport-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sierpinski Arrowhead L-system: Axiom, Rules and drawing/viewport functions&lt;/h2&gt;
&lt;p&gt;See &lt;a href=&#34;https://en.wikipedia.org/wiki/L-system&#34;&gt;wikipedia&lt;/a&gt; for the background on this
L-system.&lt;/p&gt;
&lt;p&gt;Summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start with the string `A’ (the &lt;em&gt;axiom&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;At every iteration:
&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;A&lt;/code&gt; by &lt;code&gt;B-A-B&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;B&lt;/code&gt; by &lt;code&gt;A+B+A&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;When drawing:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; mean ‘move forward’&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+/-&lt;/code&gt; mean to ‘rotate right/left’ by 60 degrees&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Sierpinski
#  - axiom and rules
#  - Reference: https://en.wikipedia.org/wiki/L-system
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
axiom  &amp;lt;- el(strsplit(&amp;#39;A&amp;#39;, &amp;#39;&amp;#39;))

rules &amp;lt;- list(
  &amp;#39;A&amp;#39; = el(strsplit(&amp;#39;B-A-B&amp;#39;, &amp;#39;&amp;#39;)),
  &amp;#39;B&amp;#39; = el(strsplit(&amp;#39;A+B+A&amp;#39;, &amp;#39;&amp;#39;))
)


f &amp;lt;- function() {
  grid.lines(x = c(0.5, 0.5), y = c(0, length))
  pushViewport(
    viewport(x = 0.5, y = length, clip = &amp;#39;off&amp;#39;, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}

plus &amp;lt;- function() {
  pushViewport(
    viewport(angle =  60, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}

minus &amp;lt;- function() {
  pushViewport(
    viewport(angle = -60, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}&lt;/code&gt;&lt;/pre&gt;
&lt;video loop style=&#34;float: left;&#34; autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/grid/sierpinski-arrowhead.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;div style = &#34;clear: both;&#34;&gt;



&lt;/div&gt;
&lt;div id=&#34;dragon-curve&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dragon Curve&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Start with the string `FX’ (the &lt;em&gt;axiom&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;At every iteration:
&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;X&lt;/code&gt; by &lt;code&gt;X+YF+&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;Y&lt;/code&gt; by &lt;code&gt;-FX-Y&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;When drawing:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F&lt;/code&gt; meanss ‘move forward’&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+/-&lt;/code&gt; mean to ‘rotate right/left’ by 90 degrees&lt;/li&gt;
&lt;li&gt;‘X’ and ‘Y’ do not correspond to drawing actions&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;axiom  &amp;lt;- el(strsplit(&amp;#39;FX&amp;#39;, &amp;#39;&amp;#39;))

rules &amp;lt;- list(
  &amp;#39;X&amp;#39; = el(strsplit(&amp;#39;X+YF+&amp;#39;, &amp;#39;&amp;#39;)),
  &amp;#39;Y&amp;#39; = el(strsplit(&amp;#39;-FX-Y&amp;#39;, &amp;#39;&amp;#39;))
)


f &amp;lt;- function() {
  grid.lines(x = c(0.5, 0.5), y = c(0, length))
  pushViewport(
    viewport(x = 0.5, y = length, clip = &amp;#39;off&amp;#39;, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}

plus &amp;lt;- function() {
  pushViewport(
    viewport(angle = -90, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}

minus &amp;lt;- function() {
  pushViewport(
    viewport(angle = 90, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}&lt;/code&gt;&lt;/pre&gt;
&lt;video loop style=&#34;float: left;&#34; autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/grid/dragon.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;div style = &#34;clear: both;&#34;&gt;





&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rendering other L-systems with grid graphics&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Drawing Fractals with grid graphics - part 1</title>
      <link>https://coolbutuseless.github.io/2019/04/27/drawing-fractals-with-grid-graphics-part-1/</link>
      <pubDate>Sat, 27 Apr 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/27/drawing-fractals-with-grid-graphics-part-1/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;grid-graphics-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;grid&lt;/code&gt; graphics in R&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;grid&lt;/code&gt; graphics is one of the graphics systems within R - &lt;code&gt;ggplot&lt;/code&gt; and &lt;code&gt;trellis&lt;/code&gt; are both built upon the &lt;code&gt;grid&lt;/code&gt; system.&lt;/p&gt;
&lt;p&gt;This is some exploratory code to figure out some of the capabilities of &lt;code&gt;grid&lt;/code&gt;, by using
it to draw fractals using L-systems.&lt;/p&gt;
&lt;p&gt;Rather than simply calculating and drawing lines, I am interested in how viewports
in the &lt;code&gt;grid&lt;/code&gt; system work. So to draw L-systems, the movement and rotation of lines
are carried out by pushing new viewports on the viewing stack.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;l-systems&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;L-systems&lt;/h1&gt;
&lt;p&gt;L-systems are a means of generating strings from other strings (see &lt;a href=&#34;https://en.wikipedia.org/wiki/L-system&#34;&gt;wikipedia&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;When these strings are interpreted as drawing instructions, they can make some great looking fractals.&lt;/p&gt;
&lt;p&gt;There are some really nice examples of L-system output (using R) on &lt;a href=&#34;https://twitter.com/aschinchon&#34;&gt;aschinchon’s&lt;/a&gt; &lt;a href=&#34;https://fronkonstin.com/2017/07/18/plants&#34;&gt;blog&lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;l-system-expansion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;L-system Expansion&lt;/h2&gt;
&lt;p&gt;The following function will expand an L-system given its axiom and production rules.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Expand an L-system
#&amp;#39;
#&amp;#39; @param axiom l-system axiom (vector of characters)
#&amp;#39; @param rules list of expansion rules
#&amp;#39; @param depth number of iterations
#&amp;#39;
#&amp;#39; @return vector of characters representing the expanded l-system
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
expand_system &amp;lt;- function(axiom, rules, depth) {
  string &amp;lt;- axiom
  for (i in seq_len(depth)) {
    string &amp;lt;- map(string, ~rules[[.x]] %||% .x) %&amp;gt;%
      flatten_chr()
  }
  string
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;sierpinski-l-system-axiom-rules-and-drawingviewport-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sierpinski L-system: Axiom, Rules and drawing/viewport functions&lt;/h2&gt;
&lt;p&gt;See &lt;a href=&#34;https://en.wikipedia.org/wiki/L-system&#34;&gt;wikipedia&lt;/a&gt; for the background on this
L-system.&lt;/p&gt;
&lt;p&gt;Summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start with the string `F-G-G’&lt;/li&gt;
&lt;li&gt;At every iteration:
&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;F&lt;/code&gt; by &lt;code&gt;F-G+F+G-F&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;G&lt;/code&gt; by &lt;code&gt;GG&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;When drawing:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt; mean ‘move forward’&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+/-&lt;/code&gt; mean to ‘rotate right/left’&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Sierpinski
#  - axiom and rules
#  - Reference: https://en.wikipedia.org/wiki/L-system
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
axiom  &amp;lt;- strsplit(&amp;#39;F-G-G&amp;#39;, &amp;#39;&amp;#39;)[[1]]

rules &amp;lt;- list(
  &amp;#39;F&amp;#39; = el(strsplit(&amp;#39;F-G+F+G-F&amp;#39;, &amp;#39;&amp;#39;)),
  &amp;#39;G&amp;#39; = el(strsplit(&amp;#39;GG&amp;#39;       , &amp;#39;&amp;#39;))
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Move forward
#  - Draw a line in the current viewport
#  - advance a viewport to the end of this line
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forward &amp;lt;- function() {
  grid.lines(x = c(0.5, 0.5), y = c(0, length))
  pushViewport(
    viewport(x = 0.5, y = length, clip = &amp;#39;off&amp;#39;, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
  invisible()
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;#39;+&amp;#39;
#   - push a viewport which is rotated right 120 degrees
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rotate_right &amp;lt;- function() {
  pushViewport(
    viewport(angle =  120, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# &amp;#39;-&amp;#39;
#   - push a viewport which is rotated left 120 degrees
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rotate_left &amp;lt;- function() {
  pushViewport(
    viewport(angle = -120, clip = &amp;#39;off&amp;#39;, x = 0.5, y = 0, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;)),
    recording = FALSE
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;render-the-sierpinski-l-system-at-depth-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Render the Sierpinski L-system at &lt;code&gt;depth = 3&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Sizing of elements depends on how deep we go
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
depth &amp;lt;- 3
length &amp;lt;- c(0.32, 0.16, 0.08, 0.04, 0.02, 0.01)[depth]

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Expand the L-system
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
string &amp;lt;- expand_system(axiom, rules, depth = depth)
cat(paste(string, collapse = &amp;quot;&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;F-G+F+G-F-GG+F-G+F+G-F+GG-F-G+F+G-F-GGGG+F-G+F+G-F-GG+F-G+F+G-F+GG-F-G+F+G-F+GGGG-F-G+F+G-F-GG+F-G+F+G-F+GG-F-G+F+G-F-GGGGGGGG-GGGGGGGG&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up a new grid page in a pleasing orientation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
grid.newpage()
pushViewport(viewport(x=0.75, y=0.5, just = c(&amp;#39;centre&amp;#39;, &amp;#39;bottom&amp;#39;), angle = 120))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# For each rule in the L-system string, following the rules to 
# maniuplate the viewport and draw the lines
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i in seq_along(string)) {
  symbol &amp;lt;- string[i]
  # cat(i, symbol, &amp;quot;\n&amp;quot;)

  switch(
    symbol,
    &amp;#39;F&amp;#39; = forward(),
    &amp;#39;G&amp;#39; = forward(),
    &amp;#39;+&amp;#39; = rotate_right(),
    &amp;#39;-&amp;#39; = rotate_left()
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-27-drawing-fractals-with-grid-graphics-part1_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-sierpinski-l-system---by-draw-step&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated Sierpinski L-System - by draw step&lt;/h2&gt;
&lt;p&gt;An animation showing the drawing process evolve for depth = 2&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;F-G+F+G-F-GG+F-G+F+G-F+GG-F-G+F+G-F-GGGG-GGGG&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src =&#34;/img/grid/sierpinski-step.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-sierpinski-l-system---by-draw-step-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated Sierpinski L-System - by draw step&lt;/h2&gt;
&lt;p&gt;An animation showing the drawing process evolve for depth = 5&lt;/p&gt;
&lt;video loop style=&#34;float: left;&#34; autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/grid/sierpinski-xdubstep.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;div style = &#34;clear: both;&#34;&gt;


&lt;/div&gt;
&lt;div id=&#34;animated-sierpinski-l-system---by-depth&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated Sierpinski L-System - by depth&lt;/h2&gt;
&lt;p&gt;This gif was created by rendering the L-system at multiple depths and combining individual images into a gif.&lt;/p&gt;
&lt;p&gt;&lt;img src =&#34;/img/grid/sierpinski.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rendering other L-systems with grid graphics&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the ggreverse package for turning ggplots back in to code</title>
      <link>https://coolbutuseless.github.io/2019/04/26/introducing-the-ggreverse-package-for-turning-ggplots-back-in-to-code/</link>
      <pubDate>Fri, 26 Apr 2019 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/26/introducing-the-ggreverse-package-for-turning-ggplots-back-in-to-code/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggreverse&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggreverse&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/Status-alpha-orange.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/Version-0.1.0-blue.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggreverse&lt;/code&gt; takes a ggplot object and returns the code to create that plot.&lt;/p&gt;
&lt;p&gt;This package was written as a learning exercise to help me figure out
some of the internal structure of a ggplot object.&lt;/p&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Reverse engineering of facetting and scales from a plot object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aes_string()&lt;/code&gt; is currently unsupported.&lt;/li&gt;
&lt;li&gt;Using tidyeval in &lt;code&gt;aes()&lt;/code&gt; calls is currently unsupported.&lt;/li&gt;
&lt;li&gt;Lots of other stuff :)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/ggreverse&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-ggreverseconvert_to_code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example &lt;code&gt;ggreverse::convert_to_code()&lt;/code&gt;&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create a ggplot&lt;/li&gt;
&lt;li&gt;Convert the ggplot back into code using &lt;code&gt;ggreverse&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Convert the code back into a plot&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggreverse)

plot_df &amp;lt;- mtcars

# Create a ggplot2 plot object
p &amp;lt;- ggplot(plot_df) +
  geom_point(aes(mpg, wt), size = 3) +
  labs(title = &amp;quot;hello&amp;quot;) +
  theme_bw() + 
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-26-ggreverse-package-turns-plots-back-in-to-code_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Convert the plot object back into code
plot_code &amp;lt;- ggreverse::convert_to_code(p)
plot_code&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: Could not use colored = TRUE, as the package prettycode is not
installed. Please install it if you want to see colored output or see `?
print.vertical` for more information.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;ggplot(data = plot_df) +
  geom_point(mapping = aes(x = mpg, y = wt), size = 3, position = position_identity(), stat = &amp;quot;identity&amp;quot;) +
  labs(title = &amp;quot;hello&amp;quot;, x = &amp;quot;mpg&amp;quot;, y = &amp;quot;wt&amp;quot;) +
  theme_bw(11) +
  coord_fixed()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Parse the plot code back into a plot - which should match the original plot
eval(parse(text = plot_code))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-26-ggreverse-package-turns-plots-back-in-to-code_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sessioninfo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;SessionInfo&lt;/h2&gt;
&lt;p&gt;Developed against:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;R 3.5.3&lt;/li&gt;
&lt;li&gt;ggplot2 v3.1.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Reverse engineer the ggplot call from a ggplot object</title>
      <link>https://coolbutuseless.github.io/2019/04/26/reverse-engineer-the-ggplot-call-from-a-ggplot-object/</link>
      <pubDate>Fri, 26 Apr 2019 06:25:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/26/reverse-engineer-the-ggplot-call-from-a-ggplot-object/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;idea&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Idea&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/tjmahr&#34;&gt;tjmahr&lt;/a&gt; posted a neat hack to embed auto-embed the text used to create
a ggplot as the title of the plot itself.&lt;/p&gt;
&lt;p&gt;I wondered if you could somehow extract the ggplot call text from a ggplot object itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;proof-of-concept-reverse-engineering-a-ggplot-call&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Proof-of-concept: Reverse engineering a ggplot call&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)
library(dplyr)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse_mapping -&amp;gt;  &amp;quot;aes(x = ..., y = ...)&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_mapping &amp;lt;- function(mapping) {
  aes_args &amp;lt;- paste(names(mapping), stringr::str_sub(as.character(mapping), start=2), sep = &amp;quot;=&amp;quot;, collapse = &amp;quot;, &amp;quot;)
  aes_text &amp;lt;- glue::glue(&amp;quot;aes({aes_args})&amp;quot;)
  aes_text
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse aesthetic params -&amp;gt;  &amp;quot;size = 3&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_aes_params &amp;lt;- function(aes_params) {
  if (length(aes_params) == 0) {
    NULL
  } else {
    paste(names(aes_params), unname(aes_params), sep = &amp;quot;=&amp;quot;, collapse = &amp;quot;, &amp;quot;)
  }
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# reverse_layer -&amp;gt; &amp;quot;geom_point(aes(mpg, wt), size = 3)&amp;quot;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_layer &amp;lt;- function(layer) {
  geom_name &amp;lt;- ggplot2:::snakeize(class(layer$geom)[1])

  aes_text        &amp;lt;- reverse_mapping(layer$mapping)
  aes_params_text &amp;lt;- reverse_aes_params(layer$aes_params)
  geom_args &amp;lt;- paste(c(aes_text, aes_params_text), collapse = &amp;quot;, &amp;quot;)


  glue::glue(&amp;quot;{geom_name}({geom_args})&amp;quot;)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Reverse plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_plot &amp;lt;- function(p) {
  layers &amp;lt;- p$layers %&amp;gt;% map_chr(reverse_layer)

  plot_text &amp;lt;- paste(c(&amp;quot;ggplot(data)&amp;quot;, layers), collapse = &amp;quot;+\n&amp;quot;)
  styler::style_text(plot_text)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a plot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(p &amp;lt;- ggplot(mtcars) +
  geom_point(aes(mpg, wt), size = 3) +
  geom_line(aes(mpg, wt)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-26-reverse-engineer-ggplot-call_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Determine the ggplot call from the ggplot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reverse_plot(p)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: Could not use colored = TRUE, as the package prettycode is not
installed. Please install it if you want to see colored output or see `?
print.vertical` for more information.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;ggplot(data) +
  geom_point(aes(x = mpg, y = wt), size = 3) +
  geom_line(aes(x = mpg, y = wt))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Every possible scatterplot from a data.frame (32 thousand plots of `mtcars`)</title>
      <link>https://coolbutuseless.github.io/2019/04/25/every-possible-scatterplot-from-a-data.frame-32-thousand-plots-of-mtcars/</link>
      <pubDate>Thu, 25 Apr 2019 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/25/every-possible-scatterplot-from-a-data.frame-32-thousand-plots-of-mtcars/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;question-is-it-possible-to-generate-every-possible-scatterplot-from-a-data.frame&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Question: Is it possible to generate every possible scatterplot from a data.frame?&lt;/h1&gt;
&lt;p&gt;Is it?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;answer-yes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Answer: Yes&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Yes, is is possible to generate every possible scatterplot from a data.frame.&lt;/li&gt;
&lt;li&gt;Even on limited subset of aesthetics, there are still 32 &lt;em&gt;thousand&lt;/em&gt; possible
scatterplots.&lt;/li&gt;
&lt;li&gt;Code included below&lt;/li&gt;
&lt;li&gt;Constraints:
&lt;ul&gt;
&lt;li&gt;Not mapping &lt;code&gt;alpha&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;stroke&lt;/code&gt; or &lt;code&gt;group&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Each variable could be used in only one aesthetic mapping on a
single plot e.g. a variable couldn’t
be mapped to both &lt;code&gt;shape&lt;/code&gt; and &lt;code&gt;colour&lt;/code&gt; simultaneously.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Challenges:
&lt;ul&gt;
&lt;li&gt;Keeping the combinational explosion to a minimum - wrote a recursive function
for assigning variables to aesthetics&lt;/li&gt;
&lt;li&gt;Allowing optional aesthetics to &lt;em&gt;not&lt;/em&gt; be mapped to a variable&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;sample-of-900-scatterplots-out-of-32850&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Sample of ~900 scatterplots (out of 32,850)&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Image title describes the mapping of variables to aesthetics.&lt;/li&gt;
&lt;li&gt;Click on the images below to see bigger versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-0.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-0.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-1.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-1.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-2.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-2.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-3.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-3.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-4.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-4.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-5.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-5.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-6.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-6.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-7.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-7.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/img/everyplot/out-8.png&#34;&gt; &lt;img src=&#34;https://coolbutuseless.github.io/img/everyplot/out-8.jpg&#34; style=&#34;width:30%;&#34;&gt; &lt;/a&gt;&lt;/p&gt;
&lt;div id=&#34;code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;prepare-data-for-plotting&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Prepare data for plotting&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Tools to prepare a dataset for plotting
#  - is_categorical() - rough test to see if variable is categorical
#  - enfactor()       - convert a variable to a factor if it has few unique values
#  - enfactor_df()    - convert variables in a data.frame to a factor
#  - get_cat_vars()   - get names of categorical variables in a data.frame
#  - get_cont_vars()  - get names of continuous variables in a data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
is_categorical &amp;lt;- function(x) {is.factor(x) || is.character(x)}
enfactor       &amp;lt;- function(x) {if (is_categorical(x) || n_distinct(x) &amp;gt; 10) x else as.factor(x)}
enfactor_df    &amp;lt;- function(df) {map_df(df, enfactor)}
get_cat_vars   &amp;lt;- function(df) { df %&amp;gt;% keep(is_categorical) %&amp;gt;% names() }
get_cont_vars  &amp;lt;- function(df) { df %&amp;gt;%  discard(is_categorical) %&amp;gt;% names() }


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Prepare the dataset to plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_df   &amp;lt;- enfactor_df(mtcars)
all_vars  &amp;lt;- colnames(plot_df)
cat_vars  &amp;lt;- get_cat_vars(plot_df)
cont_vars &amp;lt;- get_cont_vars(plot_df)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;determine-every-combination-of-variable-to-aesthetic-mapping-for-geom_point&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Determine every combination of variable-to-aesthetic mapping for &lt;code&gt;geom_point()&lt;/code&gt;&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Assign variables to an aesthetic
#&amp;#39;
#&amp;#39; - Assigning N variables to M aesthetics
#&amp;#39; - Allows &amp;#39;optional&amp;#39; aesthetics to be not assigned
#&amp;#39;
#&amp;#39; @param cols the column names in the data.frame
#&amp;#39; @param aesthetic the list of aesthetics
#&amp;#39; @param current_vars vector of current variable names
#&amp;#39; @param depth = current recursion depth
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
assign_vars &amp;lt;- function(cols, aesthetics, current_vars = c(), depth = 1L) {
  if (depth &amp;gt; aesthetics$N) {
    if (length(current_vars) == aesthetics$N) {
      return(list(current_vars))
    } else {
      print(&amp;quot;ugh&amp;quot;)
      print(current_vars)
      return(NULL)
    }
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Recursively assign the remaining columns to an aesthetic
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  res &amp;lt;- cols %&amp;gt;% 
    imap(~assign_vars(cols[-.y], aesthetics, c(current_vars, .x), depth + 1L))
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If we&amp;#39;re run out of variables, but still have some aesthetics, 
  # then mark the aesthetics as being mapped to &amp;#39;.na&amp;#39;.  Filter later.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (depth &amp;gt; length(aesthetics$required_aes)) {
    extra &amp;lt;- assign_vars(cols, aesthetics, c(current_vars, &amp;#39;.na&amp;#39;), depth + 1L)
    res &amp;lt;- c(res, list(extra))
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Flatten and return
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  res &amp;lt;- unlist(res, recursive = FALSE)
  res
}



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# What are all the aesthetics for &amp;#39;geom_point&amp;#39;?
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aesthetics &amp;lt;- list(
  required_aes = c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;), 
  optional_aes = list(
    shape  = 19, 
    colour = &amp;quot;black&amp;quot;, 
    size   = 1.5, 
    fill   = NA, 
    alpha  = NA, 
    stroke = 0.5
  )
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Going to drop some aesthetics from consideration
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aesthetics$optional_aes$fill   &amp;lt;- NULL
aesthetics$optional_aes$stroke &amp;lt;- NULL
aesthetics$optional_aes$alpha  &amp;lt;- NULL


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# What are the aesthetic names?
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aes_names &amp;lt;- c(aesthetics$required_aes, names(aesthetics$optional_aes))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# How many aesthetics must we map to in total?
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aesthetics$N &amp;lt;- length(aesthetics$required_aes) + length(aesthetics$optional_aes)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create all the possible variable-aesthetic mappings
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
combos &amp;lt;- assign_vars(cols = all_vars, aesthetics = aesthetics)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Post-filtering to keep only combos where shape is a categorical variable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
combos &amp;lt;- combos %&amp;gt;% 
  keep(~.x[3] == &amp;#39;na&amp;#39; || .x[3] %in% cat_vars)

aes_names&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;x&amp;quot;      &amp;quot;y&amp;quot;      &amp;quot;shape&amp;quot;  &amp;quot;colour&amp;quot; &amp;quot;size&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(combos)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;hp&amp;quot;  

[[2]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;drat&amp;quot;

[[3]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;wt&amp;quot;  

[[4]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;qsec&amp;quot;

[[5]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;am&amp;quot;  

[[6]]
[1] &amp;quot;mpg&amp;quot;  &amp;quot;cyl&amp;quot;  &amp;quot;vs&amp;quot;   &amp;quot;disp&amp;quot; &amp;quot;gear&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;length(combos)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 32850&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;createsave-a-plot-using-a-particular-variable-aesthetic-mapping&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Create/save a plot using a particular variable-aesthetic mapping&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Given an argument &amp;#39;combo&amp;#39; and a vector of the aesthetic names,
# create an argument suitable for &amp;#39;aes()&amp;#39; in a ggplot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_aes_args &amp;lt;- function(combo, aes_names) {
  combo %&amp;gt;%
    set_names(aes_names) %&amp;gt;%
    discard(~.x == &amp;#39;.na&amp;#39;) %&amp;gt;%
    map(as.name)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Given an argument &amp;#39;combo&amp;#39; and a vector of the aesthetic names,
# create (and execute) an &amp;#39;aes()&amp;#39; call to create an mapping object for ggplot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_aes &amp;lt;- function(combo, aes_names) {
  aes_args &amp;lt;- create_aes_args(combo, aes_names)
  do.call(&amp;#39;aes&amp;#39;, aes_args)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot a single combo
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_combo &amp;lt;- function(idx) {
  combo    &amp;lt;- combos[[idx]]
  this_aes &amp;lt;- create_aes(combo, aes_names)
  
  aes_args &amp;lt;- create_aes_args(combo, aes_names)
  title    &amp;lt;- paste(names(aes_args), unname(aes_args), sep = &amp;quot;:&amp;quot;, collapse = &amp;quot;, &amp;quot;)
  
  ggplot(plot_df) +
    geom_point(mapping = this_aes) + 
    theme_bw() +
    labs(title = title) + 
    theme(
      legend.position = &amp;#39;none&amp;#39;,
      axis.text       = element_blank(),
      axis.ticks      = element_blank(),
      axis.title      = element_blank(),
      panel.grid      = element_blank(),
      panel.border    = element_blank()
    )
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save a single combo to file
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
save_combo &amp;lt;- function(idx) {
  p &amp;lt;- plot_combo(idx)
  filename &amp;lt;- file.path(&amp;quot;everyplot&amp;quot;, sprintf(&amp;quot;%05i.png&amp;quot;, idx))
  ggsave(filename = filename, plot = p, width = 4, height = 3)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;save-a-sample-of-the-32850-plot-combinations&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Save a sample of the 32,850 plot combinations&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)
idxs &amp;lt;- sample(length(combos), size = 10*96)

idxs %&amp;gt;% walk(save_combo)

# ImageMagick from the commandline
# montage *.png -tile 8x12 -geometry 400x250 -define png:format=png32 -dither None -colors 16 -depth 4 out/out.png&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>GIF image writing in pure R</title>
      <link>https://coolbutuseless.github.io/2019/04/23/gif-image-writing-in-pure-r/</link>
      <pubDate>Tue, 23 Apr 2019 07:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/23/gif-image-writing-in-pure-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;While working on fast output of images for the &lt;a href=&#34;https://github.com/coolbutuseless/foist&#34;&gt;foist package&lt;/a&gt;,
I realised the GIF format was simple enough to write quickly, so I worked on an R implementation
of a GIF image writer, before translating to C++ for speed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;BrodieG&lt;/a&gt; for some optimization of the code!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-in-an-uncompressed-gif&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s in an uncompressed GIF?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Header
&lt;ul&gt;
&lt;li&gt;“GIF89a” to indicate this is a GIF file&lt;/li&gt;
&lt;li&gt;width + height. 2 bytes each. Little endian.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Palette
&lt;ul&gt;
&lt;li&gt;Only going to support 128 colour palette&lt;/li&gt;
&lt;li&gt;i.e. 128x 3 bytes representing 128 RGB triplets&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Uncompressed data blocks
&lt;ul&gt;
&lt;li&gt;GIFs with 2^n colours require up to 2^(n+1) bits to encode because of
control codes like &lt;code&gt;CLEAR&lt;/code&gt; and &lt;code&gt;STOP&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;So, by limiting GIF to 128 colours/levels, each uncompressed pixel will fit
in a single byte. See &lt;a href=&#34;https://en.wikipedia.org/wiki/GIF#Uncompressed_GIF&#34;&gt;wikipedia&lt;/a&gt; for more detailed info on uncompressed gifs.&lt;/li&gt;
&lt;li&gt;To prevent the LZW decompressor from actually kicking-in during the decode process,
need to send a CLEAR token every 126 bytes&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;test-matrix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Test matrix&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ncol &amp;lt;- 255
nrow &amp;lt;- 160
int_mat &amp;lt;- matrix(0:127, nrow = nrow, ncol = ncol, byrow = TRUE)
dbl_mat &amp;lt;- int_mat/127
int_vec &amp;lt;- as.vector(t(int_mat))  # In row-major ordering&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;r-gif-encoder&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;R GIF encoder&lt;/h2&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;128 colour levels only&lt;/li&gt;
&lt;li&gt;No animation&lt;/li&gt;
&lt;li&gt;Data is not compressed&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Write a matrix to an uncompressed GIF using just R
#&amp;#39;
#&amp;#39; @param int_vec integer vector with values in range [0, 127]
#&amp;#39; @param nrow number of rows
#&amp;#39; @param ncol number of cols
#&amp;#39; @param filename output filename
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
write_gif_R &amp;lt;- function(int_vec, nrow, ncol, filename) {
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Calculate Width low/high bytes, Height low/high bytes
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  w_lo &amp;lt;- bitwAnd(ncol, 0xff)
  w_hi &amp;lt;- bitwAnd(bitwShiftR(ncol, 8), 0xff)
  
  h_lo &amp;lt;- bitwAnd(nrow, 0xff)
  h_hi &amp;lt;- bitwAnd(bitwShiftR(nrow, 8), 0xff)
  
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # GIF header is &amp;quot;GIF89a&amp;quot;
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  header &amp;lt;- c(0x47, 0x49, 0x46, 0x38, 0x39, 0x61)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Size = width, height (2-bytes each, little endian)
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  size &amp;lt;- c(w_lo, w_hi, h_lo, h_hi)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # 0xF6 = global colour table with 7 bits per colour.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  global_colour_table_header = c(0xf6, 0x00, 0x00)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # RGB triplets for every second colour in the first viridis palette
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  palette &amp;lt;- t(viridis::viridis.map[seq(1,256,2),1:3] * 255)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Description of data
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  image_descriptor_header &amp;lt;- c(0x2c,                   # Data start
                               0x00, 0x00, 0x00, 0x00, # start position
                               w_lo, w_hi, h_lo, h_hi, # end position
                               0x00,                   # No local colour table
                               0x07)                  # Code size 2^7
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Written at end of GIF file
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gif_terminator &amp;lt;- 0x3B
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Maximum length of a data chunk = 2^7 - 2 = 126 bytes
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  N &amp;lt;- 126
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # A chunk of data consists of
  #   - 1 byte for length
  #   - 1 byte for CLEAR code (0x80)
  #   - N bytes of data.  N &amp;lt;= 126
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  extract_chunk &amp;lt;- function(i) {
    indices &amp;lt;- seq(0, N-1) + i*N + 1
    c(N+1, 0x80, int_vec[indices])
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Number of full chunks
  # Remaining bytes that don&amp;#39;t make a full chunk
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  N_full_chunks   &amp;lt;- length(int_vec) %/% N
  remaining_bytes &amp;lt;- length(int_vec) %%  N
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Extract all the data for the full chunks
  # Faster method from @BrodieGaslam
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # full_chunk_data &amp;lt;- unlist(lapply(seq(N_full_chunks) - 1, extract_chunk))
  full_chunk_data &amp;lt;- rbind(
    rep(N+1, N_full_chunks), rep(0x80, N_full_chunks),
    matrix(int_vec[seq_len(N*N_full_chunks)], nrow = N)
  )
  dim(full_chunk_data) &amp;lt;- NULL
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Create a chunk for the leftover data
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  rem_data &amp;lt;- c(remaining_bytes + 1, 
                       0x80,
                       int_vec[seq(remaining_bytes) + N_full_chunks * N])
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # This is the last data chunk which contains just the STOP code
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  data_end &amp;lt;- c(0x01, 0x81, 0x00)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Write all the data to file
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  writeBin(
    as.raw(c(header, 
      size, 
      global_colour_table_header, 
      palette, 
      image_descriptor_header,
      full_chunk_data, 
      rem_data, 
      data_end,
      gif_terminator)),
    con      = filename,
    size     = 1,
    useBytes = TRUE
  )
  
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;write_gif_R(int_vec, nrow, ncol, &amp;quot;test-r.gif&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src = &#34;/img/gif/test-r.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The above R code was turned into C++ code and included in &lt;a href=&#34;https://github.com/coolbutuseless/foist&#34;&gt;foist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;caTools&lt;/code&gt; package also includes a GIF encoder&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;tmp &amp;lt;- tempfile()
res &amp;lt;- bench::mark(
  write_gif_R(int_vec, nrow, ncol, tmp),
  foist::write_gif(dbl_mat, tmp),
  caTools::write.gif(dbl_mat, tmp)
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;(#tab:benchmark_grey)Benchmark results&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;write_gif_R(int_vec, nrow, ncol, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.54ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.15ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;462&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.19MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;foist::write_gif(dbl_mat, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;323.43µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;363.27µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2605&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.19KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;caTools::write.gif(dbl_mat, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.99ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.35MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;Loading required namespace: tidyr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-23-gif-encoder-in-pure-R_files/figure-html/benchmark_grey-1.png&#34; width=&#34;1056&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It’s possible to write a GIF encoder in pure R (if compression is excluded)&lt;/li&gt;
&lt;li&gt;Handling all the data in Rcpp (like &lt;a href=&#34;https://github.com/coolbutuseless/foist&#34;&gt;foist&lt;/a&gt; does) makes things super fast.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;caTools::write.gif()&lt;/code&gt; is relatively slow and uses a load of memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Twitter #rstats activity</title>
      <link>https://coolbutuseless.github.io/2019/04/09/twitter-#rstats-activity/</link>
      <pubDate>Tue, 09 Apr 2019 19:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/09/twitter-#rstats-activity/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;when-is-twitter-rstats-active&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;When is Twitter #rstats active?&lt;/h2&gt;
&lt;p&gt;Living in Australia, I sometimes feel I’m not on twitter when all the #rstats
action is happening.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/mkearney/rtweet/&#34;&gt;rtweet&lt;/a&gt; is a package I’ve been meaning to
look at for a while, so this seemed like a good introductory exercise.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;rtweet&lt;/code&gt; authorisation process is totally painless, and spawns a browser
session to get you started with the twitter API without even having to think.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;grab-a-lot-of-tweets&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Grab a lot of tweets&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Pick a query string&lt;/li&gt;
&lt;li&gt;Ask for lots of tweets (18000 is the API limit)&lt;/li&gt;
&lt;li&gt;There is no step 3&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(ggplot2)
library(lubridate)
library(rtweet)
library(tidyr)

lotsa_tweets &amp;lt;- rtweet::search_tweets(q = &amp;#39;#rstats&amp;#39;, n = 17500)
dim(lotsa_tweets)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 13234    90&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;how-far-back-did-we-get-rstats-tweets&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;How far back did we get #rstats tweets?&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lotsa_tweets %&amp;gt;%
  mutate(delta = as.numeric(difftime(max(created_at), created_at, units = &amp;#39;days&amp;#39;))) %&amp;gt;%
  ggplot() +
  geom_histogram(aes(delta), binwidth = 1, fill = &amp;#39;grey80&amp;#39;, colour = &amp;#39;black&amp;#39;) + 
  theme_bw() + 
  labs(
    x     = &amp;quot;Days before now&amp;quot;,
    title = &amp;quot;Prior days with tweets - about 6 days&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-09-twitter-rstats-activity_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-the-graph-of-twitter-activity-in-local-timezones&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s the graph of twitter activity in local timezones?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AEST = Australian Eastern Standard Time&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  - Keep all the tweets in the last 6 hours
#  - Calculate tweet time in a few different timezones
#  - Keep just the &amp;quot;hour&amp;quot; of the tweet
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
last_day &amp;lt;- lotsa_tweets %&amp;gt;% 
  filter(created_at &amp;gt; max(created_at) - ddays(6)) %&amp;gt;%
  mutate(
    UTC     = hour(created_at             ),
    AEST    = hour(created_at + dhours(10)),
    NewYork = hour(created_at - dhours( 4)),
    SF      = hour(created_at - dhours( 7))
  ) %&amp;gt;%
  select(UTC, AEST, NewYork, SF) %&amp;gt;%
  gather(tz, time) &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(last_day) + 
  geom_histogram(aes(time), binwidth = 1) + 
  facet_wrap(~tz, scales = &amp;#39;free_x&amp;#39;) + 
  theme_bw() +
  scale_x_continuous(breaks = c(0, 3, 6, 9, 12, 15, 18, 21)) + 
  labs(
    x        = &amp;quot;Hour of day in this time zone&amp;quot;,
    title    = &amp;quot;#Rstats activity on twitter&amp;quot;,
    subtitle = &amp;quot;Identical data plotted against local time in 4 timezones&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-09-twitter-rstats-activity_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Outputting data to images</title>
      <link>https://coolbutuseless.github.io/2019/04/08/outputting-data-to-images/</link>
      <pubDate>Mon, 08 Apr 2019 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/08/outputting-data-to-images/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-saving-lots-of-r-matrices-and-arrays-to-image-files&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Saving &lt;em&gt;lots&lt;/em&gt; of R matrices and arrays to image files&lt;/h2&gt;
&lt;p&gt;A current project generates 100s (even 1000s) of matrices which I’d like to
view outside of R i.e. I’d like to save all these matrices as image files and
then process them with other tools.&lt;/p&gt;
&lt;p&gt;This post benchmarks some ways of saving a matrix or an array as an image file.&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My machine has an SSD.&lt;/li&gt;
&lt;li&gt;Timing will fluctuate due to all sorts of disk related IO factors - I’m not too
concerned at this stage, I just want a rough idea on ranking by speed.&lt;/li&gt;
&lt;li&gt;Compressed data may be actually written to disk faster (less to write), but it takes time
to actually compress the data (more work to do). So there’s probably a sweet spot in there.&lt;/li&gt;
&lt;li&gt;I don’t want to use a lossy format, but I’ve included &lt;code&gt;jpeg&lt;/code&gt; output for comparison, as the
jpeg library itself has been optimized over decades and is very, very fast.&lt;/li&gt;
&lt;li&gt;All my data is in matrix objects - if a library needs to convert to some particular data structure
before output, then that’s part of its benchmark time.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;data-setup&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Data Setup&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ncol    &amp;lt;- 1024
nrow    &amp;lt;- 640
int_vec &amp;lt;- rep.int(seq(ncol) - 1, nrow) %% 256L
int_mat &amp;lt;- matrix(int_vec, nrow = nrow, ncol = ncol, byrow = TRUE)
dbl_mat &amp;lt;- int_mat/255

r       &amp;lt;- dbl_mat
g       &amp;lt;- matrix(rep(seq(0, 255, length.out = nrow)/255, each = ncol), nrow, ncol, byrow = TRUE)
b       &amp;lt;- dbl_mat[, rev(seq(ncol(dbl_mat)))  ]

dbl_arr &amp;lt;- array(c(r, g, b), dim = c(nrow, ncol, 3))&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div style=&#34;width:45%;float:left;&#34;&gt;
&lt;h4&gt;
dbl_mat
&lt;/h4&gt;
&lt;img src = &#34;/img/matrix-to-image/grey_png.png&#34;   title = &#34;dbl_mat&#34; width = &#34;100%&#34;&gt;
&lt;/div&gt;
&lt;div style=&#34;width:45%;float:right;&#34;&gt;
&lt;h4&gt;
dbl_arr
&lt;/h4&gt;
&lt;img src = &#34;/img/matrix-to-image/colour_png.png&#34; title = &#34;dbl_arr&#34; width = &#34;100%&#34;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;comparing-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Comparing packages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=png&#34;&gt;png&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=jpeg&#34;&gt;jpeg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=pixmap&#34;&gt;pixmap&lt;/a&gt; - Requires that arrays and matrices are first converted to pixmap objects.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=rtiff&#34;&gt;rtiff&lt;/a&gt; - Requires that arrays are first converted to pixmap objects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;writing-a-matrix-as-a-grey-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Writing a matrix as a grey image&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Integer matrix saved to image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tmp &amp;lt;- tempfile()

res &amp;lt;- bench::mark(
  png    = png::writePNG                       (dbl_mat, tmp),
  jpeg   = jpeg::writeJPEG                     (dbl_mat, tmp),
  pixmap = pixmap::write.pnm(pixmap::pixmapGrey(dbl_mat),tmp),
  rtiff  = rtiff::writeTiff(                    dbl_mat, tmp),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-3&#34;&gt;Table 1: &lt;/span&gt;Saving a 1024x640 matrix as a grey image&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;png::writePNG(dbl_mat, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.23ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.14ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;670.8KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jpeg::writeJPEG(dbl_mat, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.09ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.15ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;122&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;661.2KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pixmap::write.pnm(pixmap::pixmapGrey(dbl_mat), tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20.46ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26.18ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32.3MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rtiff::writeTiff(dbl_mat, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;105.61ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113.2ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;94.2MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;Loading required namespace: tidyr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-08-outputting-data-to-images_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;writing-an-array-as-an-rgb-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Writing an array as an RGB image&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Write an RGB integer array to image
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pm &amp;lt;- pixmap::pixmapRGB(dbl_arr)

res &amp;lt;- bench::mark(
  png            = png::writePNG                      (dbl_arr,  tmp),
  jpeg           = jpeg::writeJPEG                    (dbl_arr,  tmp),
  pixmap         = pixmap::write.pnm(pixmap::pixmapRGB(dbl_arr), tmp),
  rtiff          = rtiff::writeTiff (pixmap::pixmapRGB(dbl_arr), tmp),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-5&#34;&gt;Table 2: &lt;/span&gt;Saving a 1024x640x3 array as an RGB image&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;png::writePNG(dbl_arr, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.3ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50.5ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.88MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jpeg::writeJPEG(dbl_arr, tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.7ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.88MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pixmap::write.pnm(pixmap::pixmapRGB(dbl_arr), tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;124ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;199.8ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;135.04MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rtiff::writeTiff(pixmap::pixmapRGB(dbl_arr), tmp)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;107.5ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;115.5ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;60.02MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-08-outputting-data-to-images_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;png&lt;/code&gt; output is fast.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jpeg&lt;/code&gt; output is very, very fast.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pixmap&lt;/code&gt; and &lt;code&gt;rtiff&lt;/code&gt; are both slow and allocate &lt;strong&gt;~2 orders of magnitude&lt;/strong&gt; more memory
than &lt;code&gt;jpeg&lt;/code&gt; or &lt;code&gt;png&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Red/Blue Analglyphs with ggplot2 and ggthreed</title>
      <link>https://coolbutuseless.github.io/2019/04/02/red/blue-analglyphs-with-ggplot2-and-ggthreed/</link>
      <pubDate>Tue, 02 Apr 2019 20:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/02/red/blue-analglyphs-with-ggplot2-and-ggthreed/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggthreed-v0.1.2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ggthreed v0.1.2&lt;/h2&gt;
&lt;p&gt;ggthreed now includes a &lt;code&gt;stat_anaglyph()&lt;/code&gt; for creating red/blue anaglyph plots.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from github&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/threed&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/ggthreed&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;redblue-anaglyphs-with-stat_anaglyph&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Red/blue anaglyphs with &lt;code&gt;stat_anaglyph()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Grab your glasses and lower your expectations!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src = &#34;/img/ggthreed/glasses.jpg&#34;&gt;&lt;/p&gt;
&lt;div id=&#34;usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Works with point, line and polygon geoms. Although “works” may be a strong term -
the 3d effect is very weak even if you tweak all the parameters&lt;/li&gt;
&lt;li&gt;It might work with other geoms, but no guarantees that it produces anything
worth looking at.&lt;/li&gt;
&lt;li&gt;parameters:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;zoffset&lt;/code&gt;, &lt;code&gt;zscale&lt;/code&gt; - for determining how &lt;code&gt;z&lt;/code&gt; aesthetic influences position&lt;/li&gt;
&lt;li&gt;&lt;code&gt;red&lt;/code&gt;, &lt;code&gt;blue&lt;/code&gt; - hex colours to use for red/blue&lt;/li&gt;
&lt;li&gt;&lt;code&gt;switch&lt;/code&gt; - switch position of the colours&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-redblue-anaglyphs-with-points.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example red/blue anaglyphs with points.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  geom_point(aes(mpg, y = wt, z = disp), stat = &amp;#39;anaglyph&amp;#39;, alpha = 0.5, zscale = 10) +
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-02-red-blue-anaglyphs-with-ggplot2_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-of-combined-3d-projection-and-anaglyph&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example of combined 3d projection and anaglyph&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(threed)

camera_to_world &amp;lt;- look_at_matrix(eye = c(1.5, 1.75, 3), at = c(0, 0, 0))

obj &amp;lt;- threed::mesh3dobj$cube %&amp;gt;%
  transform_by(invert_matrix(camera_to_world)) %&amp;gt;%
  translate_by(c(0, 0, -3)) %&amp;gt;%
  perspective_projection()

ggplot(obj, aes(x, y, z = z, group = element_id)) +
  geom_polygon(fill = NA, colour=&amp;#39;black&amp;#39;, aes(size = hidden), stat = &amp;#39;anaglyph&amp;#39;,
               zscale = 0.05, zoffset = -1.4, zinvert = FALSE) +
  scale_linetype_manual(values = c(&amp;#39;TRUE&amp;#39; = &amp;quot;FF&amp;quot;, &amp;#39;FALSE&amp;#39; = &amp;#39;solid&amp;#39;)) +
  scale_size_manual(values = c(&amp;#39;TRUE&amp;#39; = 0.1, &amp;#39;FALSE&amp;#39; = 0.5)) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-04-02-red-blue-anaglyphs-with-ggplot2_files/figure-html/gallery-cube-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-icosahedron&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Animated Icosahedron&lt;/h2&gt;
&lt;p&gt;See &lt;code&gt;vignette(&#39;animated-anaglyph&#39;, package=&#39;ggthreed&#39;)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggthreed/animated-anaglyph.gif&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>ggdebug - v0.1.1</title>
      <link>https://coolbutuseless.github.io/2019/04/01/ggdebug-v0.1.1/</link>
      <pubDate>Mon, 01 Apr 2019 20:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/04/01/ggdebug-v0.1.1/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggdebug-v0.1.1&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggdebug v0.1.1&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-alpha-orange.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggdebug&lt;/code&gt; is a package for debugging ggplot2 stats.&lt;/p&gt;
&lt;p&gt;I created this package to help in developing new &lt;code&gt;ggplot2&lt;/code&gt; stats, and trying
to decipher and understand how existing ones work.&lt;/p&gt;
&lt;p&gt;ggdebug v0.1.1 now includes a function for determining the name of the Geom which
is being used with the current Stat - &lt;code&gt;ggdebug::get_geom()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/ggdebug&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/ggdebug&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;determine-the-geom-from-within-a-stat&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Determine the Geom from within a Stat&lt;/h2&gt;
&lt;p&gt;For good reasons(?) within the Grammar of Graphics, the Stat and the Geom should
work independently.&lt;/p&gt;
&lt;p&gt;For other reasons, I sometimes want to do weird things within a Stat depending on
which Geom it is being used with.&lt;/p&gt;
&lt;p&gt;Finding the name of the Geom is not obvious, so I’ve included &lt;code&gt;get_geom()&lt;/code&gt; which
interrogates the frame stack to find the Layer which contains the Stat, and finds
the name of the Geom contained within that Layer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If anyone knows of a better way of doing this, please get in touch!&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a Stat to test with
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stat_oath_breaker &amp;lt;- function(mapping = NULL, data = NULL,
                              geom     = &amp;quot;point&amp;quot;,
                              position = &amp;quot;identity&amp;quot;,
                              ...,
                              show.legend = NA,
                              inherit.aes = TRUE) {
  layer(
    data        = data,
    mapping     = mapping,
    stat        = StatOathBreaker,
    geom        = geom,
    position    = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      na.rm = FALSE,
      ...
    )
  )
}

StatOathBreaker &amp;lt;- ggproto(
  &amp;quot;StatOathBreaker&amp;quot;, Stat,
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Call `get_geom()` from within the Stat
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  setup_params = function(data, params) {
    message(&amp;quot;StatOathBreaker being used with: &amp;quot;, ggdebug::get_geom())
    params
  },
  
  compute_layer = function(data, scales, params) {
    data
  }
)


ggplot(mtcars) +
  geom_line(aes(mpg, wt), stat = &amp;#39;oath_breaker&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;StatOathBreaker being used with: GeomLine&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>ggdebug - a package for debugging ggplot stats</title>
      <link>https://coolbutuseless.github.io/2019/03/26/ggdebug-a-package-for-debugging-ggplot-stats/</link>
      <pubDate>Tue, 26 Mar 2019 20:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/26/ggdebug-a-package-for-debugging-ggplot-stats/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggdebug&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggdebug&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-alpha-orange.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggdebug&lt;/code&gt; is a package for debugging ggplot2 stats.&lt;/p&gt;
&lt;p&gt;I created this package to help in developing new &lt;code&gt;ggplot2&lt;/code&gt; stats, and trying
to decipher and understand how existing ones work.&lt;/p&gt;
&lt;p&gt;What’s in the box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;create_stat_with_caching()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Capture arguments and the return values internal to Stat methods&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inject_data_into_stat_function()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inject arguments and return values directly into Stat methods&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This package wouldn’t be possible without:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt; by Hadley Wickham&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;Brodie Gaslam’s&lt;/a&gt; great guide to &lt;a href=&#34;https://htmlpreview.github.io/?https://github.com/brodieG/ggbg/blob/development/inst/doc/extensions.html#stat-compute&#34;&gt;ggplot2 internals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/hrbrmstr&#34;&gt;boBRudis’s&lt;/a&gt; post on &lt;a href=&#34;https://rud.is/books/creating-ggplot2-extensions/demystifying-ggplot2.html&#34;&gt;demystifying ggplot2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the development version from &lt;a href=&#34;https://github.com/coolbutuseless/ggdebug&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/ggdebug&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;debug-geom_histogram-statbin&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Debug &lt;code&gt;geom_histogram&lt;/code&gt; + &lt;code&gt;StatBin&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The following example shows how &lt;code&gt;ggdebug&lt;/code&gt; can be used to capture the data during
creation of &lt;code&gt;geom_histogram()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;geom_histogram()&lt;/code&gt; uses a default Stat of &lt;code&gt;StatBin&lt;/code&gt;. Instead we create a
debugging version of this Stat and use it explicitly.&lt;/p&gt;
&lt;p&gt;The captured data is available by calling
&lt;code&gt;ggdebug::get_cache_data()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a new stat which is identical to StatBin, but captures the
# data for all the methods.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StatBinDebug &amp;lt;- ggdebug::create_stat_with_caching(
  StatBin
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the plot using the new Stat
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(mtcars) +
  geom_histogram(aes(mpg, fill = as.factor(cyl)), stat = StatBinDebug, bins = 10) +
  theme_bw() +
  facet_wrap(~cyl)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-26-ggdebug_files/figure-html/example1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Get the data we captured from this process
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cdata &amp;lt;- ggdebug::get_data_cache()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Interrogate the captured data. 
# Each method has its only entry in the data cache, and 
# within each entry there are both the `args` and the `return` value
# for this method
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
names(cdata)
[1] &amp;quot;parameters&amp;quot;    &amp;quot;compute_group&amp;quot; &amp;quot;compute_panel&amp;quot; &amp;quot;compute_layer&amp;quot;
[5] &amp;quot;finish_layer&amp;quot; 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# arguments and the return value for the &amp;#39;parameters()&amp;#39; method
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cdata$parameters
$args
$args$extra
[1] FALSE


$return
 [1] &amp;quot;binwidth&amp;quot; &amp;quot;bins&amp;quot;     &amp;quot;center&amp;quot;   &amp;quot;boundary&amp;quot; &amp;quot;closed&amp;quot;   &amp;quot;pad&amp;quot;     
 [7] &amp;quot;breaks&amp;quot;   &amp;quot;origin&amp;quot;   &amp;quot;right&amp;quot;    &amp;quot;drop&amp;quot;     &amp;quot;width&amp;quot;   

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The &amp;#39;data&amp;#39; argument passed in to the &amp;#39;compute_layer()&amp;#39; method
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
head(cdata$compute_layer$args$data)
     x fill PANEL group
1 21.0    6     2     2
2 21.0    6     2     2
3 22.8    4     1     1
4 21.4    6     2     2
5 18.7    8     3     3
6 18.1    6     2     2

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The return value from the &amp;#39;finish_layer()&amp;#39; method
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
head(cdata$finish_layer$return)
     fill y count        x      xmin     xmax   density    ncount  ndensity
1 #F8766D 0     0 10.44444  9.138889 11.75000 0.0000000 0.0000000 0.0000000
2 #F8766D 0     0 13.05556 11.750000 14.36111 0.0000000 0.0000000 0.0000000
3 #F8766D 0     0 15.66667 14.361111 16.97222 0.0000000 0.0000000 0.0000000
4 #F8766D 0     0 18.27778 16.972222 19.58333 0.0000000 0.0000000 0.0000000
5 #F8766D 2     2 20.88889 19.583333 22.19444 0.0696325 0.6666667 0.6666667
6 #F8766D 3     3 23.50000 22.194444 24.80556 0.1044487 1.0000000 1.0000000
  PANEL group ymin ymax colour size linetype alpha
1     1     1    0    0     NA  0.5        1    NA
2     1     1    0    0     NA  0.5        1    NA
3     1     1    0    0     NA  0.5        1    NA
4     1     1    0    0     NA  0.5        1    NA
5     1     1    0    2     NA  0.5        1    NA
6     1     1    0    3     NA  0.5        1    NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;inject-data-into-geom_histogram-statbin&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Inject data into &lt;code&gt;geom_histogram&lt;/code&gt; + &lt;code&gt;StatBin&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ggdebug&lt;/code&gt; also allows you to inject arguments and override return values within
methods inside a Stat.&lt;/p&gt;
&lt;p&gt;In this example, we take the above histogram, and at the last stage (&lt;code&gt;finish_layer&lt;/code&gt;)
we inject a modified return value to override the real one.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# From the above debugging example, grab the return value from `finish_layer`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
finish_layer_return_value &amp;lt;- cdata$finish_layer$return

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Change the visual properties for the bar with the greatest height
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
finish_layer_return_value &amp;lt;- finish_layer_return_value %&amp;gt;% 
  group_by(group) %&amp;gt;%
  mutate(
    fill   = ifelse(count == max(count), &amp;#39;#000000&amp;#39;, fill  ),
    colour = ifelse(count == max(count), &amp;#39;#ff0000&amp;#39;, colour),
    size   = ifelse(count == max(count), 1        , size  )
  ) %&amp;gt;%
  ungroup()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a modified version of StatBin which only returns our version of the 
# dataset from `finishlayer`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StatBinInject &amp;lt;- inject_data_into_stat_function(
  StatBin, &amp;#39;finish_layer&amp;#39;,
  return_value = finish_layer_return_value
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Recreate the plot using the injected data as the return from `finish_layer`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(mtcars) +
  geom_histogram(aes(mpg, fill = as.factor(cyl)), stat = StatBinInject, bins = 5) +
  theme_bw() +
  facet_wrap(~cyl) +
  labs(title = &amp;quot;Use injected data to highlight the maximum bar within each group&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-26-ggdebug_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;inject-tetris-pieces-into-geom_histogram-statbin&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Inject tetris pieces into &lt;code&gt;geom_histogram&lt;/code&gt; + &lt;code&gt;StatBin&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create 3 tetris pieces
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tetris &amp;lt;- tribble(
  ~fill    , ~xmin, ~xmax, ~ymin, ~ymax,
  &amp;#39;#ff0000&amp;#39;, 10, 19, 6, 7,
  &amp;#39;#ff0000&amp;#39;, 13, 16, 6, 8,
  &amp;#39;#00ff00&amp;#39;, 25, 28, 6, 8,
  &amp;#39;#00ff00&amp;#39;, 28, 31, 7, 9,
  &amp;#39;#0000ff&amp;#39;, 25, 34, 6, 7,
  &amp;#39;#0000ff&amp;#39;, 28, 31, 6, 8
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Assign each piece to a different panel
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tetris &amp;lt;- tetris %&amp;gt;% mutate(
  PANEL    = factor(c(1, 1, 2, 2, 3, 3), levels = 1:3), 
  group    = 1,
  linetype = 1,
  x        = xmax,
  y        = ymax
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add the tetris data to the original data returned by `finish_layer`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
finish_layer_return_value &amp;lt;- bind_rows(
  tetris, 
  cdata$finish_layer$return
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a StatBin that only returns this modified data from `finish_layer`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StatBinInject &amp;lt;- inject_data_into_stat_function(
  StatBin, &amp;#39;finish_layer&amp;#39;,
  return_value = finish_layer_return_value
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the plot to generate tetris pieces injected into the data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(mtcars) +
  geom_histogram(aes(mpg, fill = as.factor(cyl)), stat = StatBinInject, bins = 5) +
  theme_bw() +
  facet_wrap(~cyl) +
  labs(title = &amp;quot;Use injected data to inject tetris pieces&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-26-ggdebug_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>ggecho - an experimental ggplot stat for blurring elements</title>
      <link>https://coolbutuseless.github.io/2019/03/22/ggecho-an-experimental-ggplot-stat-for-blurring-elements/</link>
      <pubDate>Fri, 22 Mar 2019 21:25:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/22/ggecho-an-experimental-ggplot-stat-for-blurring-elements/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;ggecho&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;ggecho&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-alpha-orange.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggecho&lt;/code&gt; is a &lt;code&gt;ggplot2&lt;/code&gt; Stat which echoes the plotting data.&lt;/p&gt;
&lt;p&gt;This can be used to create a blur effect for &lt;code&gt;geom_point()&lt;/code&gt;, &lt;code&gt;geom_line()&lt;/code&gt; and &lt;code&gt;geom_text()&lt;/code&gt; (and probably
some other geoms where the &lt;code&gt;size&lt;/code&gt; parameter directly determines the area of the displayed element).&lt;/p&gt;
&lt;p&gt;This ggplot2 stat works by duplicating/echoing the original data passed to ggplot, and adjusting
each data echo by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;size (&lt;code&gt;size_increment&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;alpha (&lt;code&gt;alpha_factor&lt;/code&gt;), and&lt;/li&gt;
&lt;li&gt;position (&lt;code&gt;x_offset&lt;/code&gt; &amp;amp; &lt;code&gt;y_offset&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This package wouldn’t be possible without:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt; by Hadley Wickham&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;Brodie Gaslam’s&lt;/a&gt; great guide to &lt;a href=&#34;https://htmlpreview.github.io/?https://github.com/brodieG/ggbg/blob/development/inst/doc/extensions.html#stat-compute&#34;&gt;ggplot2 internals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/hrbrmstr&#34;&gt;boBRudis’s&lt;/a&gt; post on &lt;a href=&#34;https://rud.is/books/creating-ggplot2-extensions/demystifying-ggplot2.html&#34;&gt;demystifying ggplot2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install thedevelopment version from &lt;a href=&#34;https://github.com/coolbutuseless/ggecho&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/ggecho&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-blurred-points-and-lines&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple blurred points and lines&lt;/h2&gt;
&lt;p&gt;This is a basic example which shows you how to solve a common problem:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggecho)

ggplot(mtcars) +
  geom_point(aes(mpg, wt, size = disp), stat = &amp;quot;echo&amp;quot;) +
  theme_bw() +
  theme(legend.position = &amp;#39;none&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-22-ggecho_files/figure-html/example-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  geom_line(aes(mpg, wt, colour = as.factor(am)), stat = &amp;quot;echo&amp;quot;) +
  theme_bw() +
  theme(legend.position = &amp;#39;none&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-22-ggecho_files/figure-html/example-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  stat_echo(aes(mpg, wt, size = disp), geom = &amp;quot;point&amp;quot;, size_increment = 2, alpha_factor = 0.5, 
            x_offset = 0.5, y_offset = 1, n = 10) +
  theme_bw() +
  theme(legend.position = &amp;#39;none&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-22-ggecho_files/figure-html/example-3.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;blurred-text&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Blurred text&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;text_df &amp;lt;- data.frame(x = c(0.3, 0.7), y = c(0.25, 0.25), label = c(&amp;#39;hello&amp;#39;, &amp;#39;#rstats&amp;#39;))

ggplot(text_df) + 
  geom_text(aes(x, y, label = label), size = 20, stat = &amp;#39;echo&amp;#39;, 
            size_increment = 2, y_offset = 0.0, n = 20, alpha_factor = 0.6) + 
  theme_void() + 
  xlim(0.1, 0.9) + ylim(0.1, 0.4)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-22-ggecho_files/figure-html/text-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>geom_blurry() - proof of concept</title>
      <link>https://coolbutuseless.github.io/2019/03/19/geom_blurry-proof-of-concept/</link>
      <pubDate>Tue, 19 Mar 2019 20:35:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/19/geom_blurry-proof-of-concept/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;&lt;a href=&#34;https://twitter.com/Emil_Hvitfeldt&#34;&gt;Emil Hvitfeldt&lt;/a&gt; wondered on twitter whether
there was a convenient way to blur points in ggplot.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Is there a way to apply blur to &lt;a href=&#34;https://twitter.com/hashtag/ggplot2?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#ggplot2&lt;/a&gt; elements? I would like to be able to get something like the first image without having to modify the svg after creating 😅&lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; &lt;a href=&#34;https://t.co/vWACdGyl9g&#34;&gt;pic.twitter.com/vWACdGyl9g&lt;/a&gt;&lt;/p&gt;&amp;mdash; Emil Hvitfeldt (@Emil_Hvitfeldt) &lt;a href=&#34;https://twitter.com/Emil_Hvitfeldt/status/1107751830098862080?ref_src=twsrc%5Etfw&#34;&gt;March 18, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;I created a proof-of-concept geom to plot blurry points. Not-at-all configurable
at the moment, but it shows that it could be an interesting way of showing …
something. Maybe uncertainty?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  geom_blurry(aes(mpg, wt, alpha = disp)) +
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-19-geom-blurry_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;ideas&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ideas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Make blur an aesthetic e.g. &lt;code&gt;aes(x = wt, y = mpg, blur = disp)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set a blur size limit? i.e. some way to set the extra radius for the blur e.g. &lt;code&gt;geom_blurry(aes(...), blur_size = 4)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Would this be possible to do as a &lt;code&gt;stat_blurry()&lt;/code&gt; so that it could work with
multiple geoms. Somehow. No idea at the moment.&lt;/li&gt;
&lt;li&gt;This is probably do-able directly in grid somehow?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix: Code&lt;/h2&gt;
&lt;p&gt;The code used is included below and available as &lt;a href=&#34;https://gist.github.com/coolbutuseless/9d6cb5fe83c69f4c81a7bd1908366f4b&#34;&gt;a gist on github&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;geom_blurry &amp;lt;- function(mapping = NULL, data = NULL,
                        stat = &amp;quot;identity&amp;quot;, position = &amp;quot;identity&amp;quot;,
                        ...,
                        na.rm = FALSE,
                        show.legend = NA,
                        inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = stat,
    geom = GeomBlurry,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      na.rm = na.rm,
      ...
    )
  )
}


GeomBlurry &amp;lt;- ggproto(
  &amp;quot;GeomBlurry&amp;quot;, Geom,
  required_aes = c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;),
  non_missing_aes = c(&amp;quot;size&amp;quot;, &amp;quot;shape&amp;quot;, &amp;quot;colour&amp;quot;),
  default_aes = aes(
    shape = 19, colour = &amp;quot;black&amp;quot;, size = 1.5, fill = NA,
    alpha = NA, stroke = 0.5
  ),

  draw_panel = function(data, panel_params, coord, na.rm = FALSE) {
    if (is.character(data$shape)) {
      data$shape &amp;lt;- translate_shape_string(data$shape)
    }

    coords &amp;lt;- coord$transform(data, panel_params)

    my_alpha &amp;lt;- coords$alpha
    my_alpha[is.na(my_alpha)] &amp;lt;- 1.0
    ggplot2:::ggname(
      &amp;quot;geom_blurry&amp;quot;,
      grid::grobTree(

        grid::pointsGrob(
          coords$x, coords$y,
          pch = coords$shape,
          gp = grid::gpar(
            col      = alpha(coords$colour, my_alpha * 0.1),
            fill     = alpha(coords$fill  , my_alpha * 0.1),
            fontsize = (coords$size + 3) * .pt + coords$stroke * .stroke / 2,
            lwd      = coords$stroke * .stroke / 2
          )
        ),

        grid::pointsGrob(
          coords$x, coords$y,
          pch = coords$shape,
          gp = grid::gpar(
            col      = alpha(coords$colour, my_alpha * 0.3),
            fill     = alpha(coords$fill  , my_alpha * 0.3),
            fontsize = (coords$size + 2) * .pt + coords$stroke * .stroke / 2,
            lwd      = coords$stroke * .stroke / 2
          )
        ),

        grid::pointsGrob(
          coords$x, coords$y,
          pch = coords$shape,
          gp = grid::gpar(
            col      = alpha(coords$colour, my_alpha * 0.5),
            fill     = alpha(coords$fill  , my_alpha * 0.5),
            fontsize = (coords$size + 1) * .pt + coords$stroke * .stroke / 2,
            lwd      = coords$stroke * .stroke / 2
          )
        ),

        grid::pointsGrob(
          coords$x, coords$y,
          pch = coords$shape,
          gp = grid::gpar(
            col      = alpha(coords$colour, coords$alpha),
            fill     = alpha(coords$fill  , coords$alpha),
            fontsize = coords$size * .pt + coords$stroke * .stroke / 2,
            lwd      = coords$stroke * .stroke / 2
          )
        )

      )
    )
  },

  draw_key = draw_key_point
)

translate_shape_string &amp;lt;- function(shape_string) {
  # strings of length 0 or 1 are interpreted as symbols by grid
  if (nchar(shape_string[1]) &amp;lt;= 1) {
    return(shape_string)
  }

  pch_table &amp;lt;- c(
    &amp;quot;square open&amp;quot;           =  0,
    &amp;quot;circle open&amp;quot;           =  1,
    &amp;quot;triangle open&amp;quot;         =  2,
    &amp;quot;plus&amp;quot;                  =  3,
    &amp;quot;cross&amp;quot;                 =  4,
    &amp;quot;diamond open&amp;quot;          =  5,
    &amp;quot;triangle down open&amp;quot;    =  6,
    &amp;quot;square cross&amp;quot;          =  7,
    &amp;quot;asterisk&amp;quot;              =  8,
    &amp;quot;diamond plus&amp;quot;          =  9,
    &amp;quot;circle plus&amp;quot;           = 10,
    &amp;quot;star&amp;quot;                  = 11,
    &amp;quot;square plus&amp;quot;           = 12,
    &amp;quot;circle cross&amp;quot;          = 13,
    &amp;quot;square triangle&amp;quot;       = 14,
    &amp;quot;triangle square&amp;quot;       = 14,
    &amp;quot;square&amp;quot;                = 15,
    &amp;quot;circle small&amp;quot;          = 16,
    &amp;quot;triangle&amp;quot;              = 17,
    &amp;quot;diamond&amp;quot;               = 18,
    &amp;quot;circle&amp;quot;                = 19,
    &amp;quot;bullet&amp;quot;                = 20,
    &amp;quot;circle filled&amp;quot;         = 21,
    &amp;quot;square filled&amp;quot;         = 22,
    &amp;quot;diamond filled&amp;quot;        = 23,
    &amp;quot;triangle filled&amp;quot;       = 24,
    &amp;quot;triangle down filled&amp;quot;  = 25
  )

  shape_match &amp;lt;- charmatch(shape_string, names(pch_table))

  invalid_strings &amp;lt;- is.na(shape_match)
  nonunique_strings &amp;lt;- shape_match == 0

  if (any(invalid_strings)) {
    bad_string &amp;lt;- unique(shape_string[invalid_strings])
    n_bad &amp;lt;- length(bad_string)

    collapsed_names &amp;lt;- sprintf(&amp;quot;\n* &amp;#39;%s&amp;#39;&amp;quot;, bad_string[1:min(5, n_bad)])

    more_problems &amp;lt;- if (n_bad &amp;gt; 5) {
      sprintf(&amp;quot;\n* ... and %d more problem%s&amp;quot;, n_bad - 5, ifelse(n_bad &amp;gt; 6, &amp;quot;s&amp;quot;, &amp;quot;&amp;quot;))
    }

    stop(
      &amp;quot;Can&amp;#39;t find shape name:&amp;quot;,
      collapsed_names,
      more_problems,
      call. = FALSE
    )
  }

  if (any(nonunique_strings)) {
    bad_string &amp;lt;- unique(shape_string[nonunique_strings])
    n_bad &amp;lt;- length(bad_string)

    n_matches &amp;lt;- vapply(
      bad_string[1:min(5, n_bad)],
      function(shape_string) sum(grepl(paste0(&amp;quot;^&amp;quot;, shape_string), names(pch_table))),
      integer(1)
    )

    collapsed_names &amp;lt;- sprintf(
      &amp;quot;\n* &amp;#39;%s&amp;#39; partially matches %d shape names&amp;quot;,
      bad_string[1:min(5, n_bad)], n_matches
    )

    more_problems &amp;lt;- if (n_bad &amp;gt; 5) {
      sprintf(&amp;quot;\n* ... and %d more problem%s&amp;quot;, n_bad - 5, ifelse(n_bad &amp;gt; 6, &amp;quot;s&amp;quot;, &amp;quot;&amp;quot;))
    }

    stop(
      &amp;quot;Shape names must be unambiguous:&amp;quot;,
      collapsed_names,
      more_problems,
      call. = FALSE
    )
  }

  unname(pch_table[shape_match])
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `analemmatic` Package for Creating Analemmatic Sundials</title>
      <link>https://coolbutuseless.github.io/2019/03/19/introducing-the-analemmatic-package-for-creating-analemmatic-sundials/</link>
      <pubDate>Tue, 19 Mar 2019 19:48:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/19/introducing-the-analemmatic-package-for-creating-analemmatic-sundials/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;The &lt;code&gt;analemmatic&lt;/code&gt; package creates &lt;a href=&#34;https://en.wikipedia.org/wiki/Analemmatic_sundial&#34;&gt;analemmatic sundials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Given a city, &lt;code&gt;analemmatic&lt;/code&gt; will get its latitude and &lt;a href=&#34;https://en.wikipedia.org/wiki/Magnetic_declination&#34;&gt;magnetic declination&lt;/a&gt;
from an internal dataset and use this to construct an &lt;a href=&#34;https://en.wikipedia.org/wiki/Analemmatic_sundial&#34;&gt;analemmatic sundial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Analemmatic sundials are neat because they are a flat (horizontal) sundial with a vertical gnomon. They are often scaled up
and uses as sculptures in parks such that the human standing in a specific location casts the shadow for the sundial.&lt;/p&gt;
&lt;p&gt;The sundials output by this package include a marker for magnetic north to help you align them for local conditions.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/analemmatic&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;remotes&amp;quot;)
remotes::install_github(&amp;quot;coolbutuseless/analemmatic&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This package stands on the shoulders of giants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggplot2&#34;&gt;ggplot2&lt;/a&gt; - for all the plotting&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ggforce&#34;&gt;ggforce&lt;/a&gt; - for &lt;code&gt;geom_ellipse()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=oce&#34;&gt;oce&lt;/a&gt; - for magnetic declination calculation&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=maps&#34;&gt;maps&lt;/a&gt; - for lat/long data for 40k cities&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-an-analemmatic-sundial-for-brisbane-australia&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: An analemmatic sundial for Brisbane, Australia&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(analemmatic)
# For manual plotting see `analemmatic:::cities` data.
# create_sundial(latitude = -27.5, magnetic_declination = 11) # Brisbane

create_sundial_for_city(&amp;#39;Brisbane&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-19-analemmatic-sundials-in-R_files/figure-html/example-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Print out the image&lt;/li&gt;
&lt;li&gt;Use a compass to align the magnetic north arrow on the printed page with a compass&lt;/li&gt;
&lt;li&gt;Place a tall, thin object (the gnomon) on the page such that it is positioned at the current date (this will take some
guesswork/eyeballing for any date which isn’t the 1st of the month)&lt;/li&gt;
&lt;li&gt;Read off the solar time from the shadow cast!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is 6:30am in the middle of March in Brisbane, Australia&lt;/p&gt;
&lt;p&gt;&lt;img src = &#39;/img/analemmatic/sunrise2.jpg&#39;&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>group_map() in dplyr 0.8.1 (still in development)</title>
      <link>https://coolbutuseless.github.io/2019/03/17/group_map-in-dplyr-0.8.1-still-in-development/</link>
      <pubDate>Sun, 17 Mar 2019 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/17/group_map-in-dplyr-0.8.1-still-in-development/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;The release of &lt;code&gt;dplyr&lt;/code&gt; v0.8.0 brought some new group functionality - described in
the &lt;a href=&#34;https://www.tidyverse.org/articles/2018/12/dplyr-0-8-0-release-candidate/&#34;&gt;release notes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since then, &lt;a href=&#34;https://twitter.com/romain_francois&#34;&gt;romain francois&lt;/a&gt; has worked on some changes
to the group operation in &lt;a href=&#34;https://github.com/tidyverse/dplyr/pull/4251&#34;&gt;this pull request #4251&lt;/a&gt;,
and things have changed a bit.&lt;/p&gt;
&lt;p&gt;The group operations which have just been modified from 0.8.0 and ready for release whenever
v0.8.1 comes out are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;group_split()&lt;/code&gt; - split a data.frame by the grouping columns into a list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_data()&lt;/code&gt; - a data.frame of just the grouping variables and the corresponding row indices for the members of the group in the original data.frame.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_keys()&lt;/code&gt; - identical to &lt;code&gt;group_data()&lt;/code&gt; except lacking that &lt;code&gt;.rows&lt;/code&gt; (row indicies) data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_map()&lt;/code&gt; - map a function over each group and return a list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_modify()&lt;/code&gt; - map a function over each group and return a single data.frame&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a short post to convince myself I understand what &lt;code&gt;group_map()&lt;/code&gt; does.&lt;/p&gt;
&lt;div id=&#34;group_map-diagram&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_map()&lt;/code&gt; diagram&lt;/h2&gt;
&lt;p&gt;At its heart &lt;code&gt;group_map()&lt;/code&gt; is going the equivalent of a &lt;code&gt;purrr::map2()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The two lists that it is mapping over are:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;the list of data.frames split by the grouping variables&lt;/li&gt;
&lt;li&gt;the list of all combinations of the grouping variables&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following diagram hopefully illustrates how I think of &lt;code&gt;group_map()&lt;/code&gt;&lt;/p&gt;
&lt;object id=&#34;svg1&#34; data=&#34;/img/dplyr/untitled.svg&#34; type=&#34;image/svg+xml&#34;&gt;
&lt;/object&gt;
&lt;p&gt;In the rest of this post I’ll break down the process step-by-step.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;test-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Test Data&lt;/h2&gt;
&lt;p&gt;A very simple data.frame to use as the test data. &lt;strong&gt;Note&lt;/strong&gt;: There is an empty factor
level in the &lt;code&gt;type&lt;/code&gt; variable!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- tibble(
  type  = factor(c(&amp;#39;a&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;b&amp;#39;), levels = c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)),
  value = c(1, 2, 3, 4, 5)
)

test_df&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 5 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 a         1
2 a         2
3 b         3
4 b         4
5 b         5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_split()&lt;/code&gt; splits the data into a list of data.frames&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one data.frame for each combination of grouping variables (as specified by &lt;code&gt;group_by()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;.drop = FALSE&lt;/code&gt; in the call to &lt;code&gt;group_by()&lt;/code&gt; if you want to keep empty factor levels.&lt;/li&gt;
&lt;li&gt;because &lt;code&gt;keep = FALSE&lt;/code&gt; was specified in &lt;code&gt;group_split()&lt;/code&gt;, the grouping column is not kept in the split data.frames&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;data_list &amp;lt;- test_df %&amp;gt;% 
  group_by(type, .drop = FALSE) %&amp;gt;%
  group_split(keep = FALSE)

data_list&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
# A tibble: 2 x 1
  value
  &amp;lt;dbl&amp;gt;
1     1
2     2

[[2]]
# A tibble: 3 x 1
  value
  &amp;lt;dbl&amp;gt;
1     3
2     4
3     5

[[3]]
# A tibble: 0 x 1
# … with 1 variable: value &amp;lt;dbl&amp;gt;

attr(,&amp;quot;ptype&amp;quot;)
# A tibble: 0 x 1
# … with 1 variable: value &amp;lt;dbl&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_keys&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_keys()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_keys()&lt;/code&gt; returns a data.frame with just the grouping columns - keeping only one row
for each combination of grouping variables.&lt;/p&gt;
&lt;p&gt;Transpose the result to get a list of values - one list entry for each row.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: I used to use a &lt;code&gt;transpose()&lt;/code&gt; here, but because it drops factor levels,
I’ve changed this to a &lt;code&gt;pmap(list)&lt;/code&gt; instead which preserves factor levels. (thanks to &lt;a href=&#34;https://twitter.com/JennyBryan&#34;&gt;jennybryan&lt;/a&gt;)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;groups_list &amp;lt;- test_df %&amp;gt;%
  group_by(type, .drop = FALSE) %&amp;gt;%
  group_keys() %&amp;gt;%
  pmap(list)

groups_list&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
[[1]]$type
[1] a
Levels: a b c


[[2]]
[[2]]$type
[1] b
Levels: a b c


[[3]]
[[3]]$type
[1] c
Levels: a b c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;calling-map2-over-the-split-data.frames-and-the-group-information-for-each-split-data.frame&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Calling &lt;code&gt;map2&lt;/code&gt; over the split data.frames and the group information for each split data.frame&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;my_func &amp;lt;- function(.x, .y) {
  glue(&amp;quot;Group &amp;#39;{.y$type}&amp;#39; has {nrow(.x)} rows&amp;quot;)
}

map2(data_list, groups_list, my_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
Group &amp;#39;a&amp;#39; has 2 rows

[[2]]
Group &amp;#39;b&amp;#39; has 3 rows

[[3]]
Group &amp;#39;c&amp;#39; has 0 rows&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_map-is-a-shortcut-for-all-the-above&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_map()&lt;/code&gt; is a shortcut for all the above!&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_map()&lt;/code&gt; does all this for you - at a high level you can think of it as doing the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;splits the data.frame by the grouping variables&lt;/li&gt;
&lt;li&gt;creates a list of all combinations of grouping variables&lt;/li&gt;
&lt;li&gt;calls &lt;code&gt;map2()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type, .drop = FALSE) %&amp;gt;%
  group_map(my_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
Group &amp;#39;a&amp;#39; has 2 rows

[[2]]
Group &amp;#39;b&amp;#39; has 3 rows

[[3]]
Group &amp;#39;c&amp;#39; has 0 rows&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>group_split/map/modify() in dplyr 0.8.1 (still in development)</title>
      <link>https://coolbutuseless.github.io/2019/03/15/group_split/map/modify-in-dplyr-0.8.1-still-in-development/</link>
      <pubDate>Fri, 15 Mar 2019 20:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/15/group_split/map/modify-in-dplyr-0.8.1-still-in-development/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;The release of &lt;code&gt;dplyr&lt;/code&gt; v0.8.0 brought some new group functionality - described in
the &lt;a href=&#34;https://www.tidyverse.org/articles/2018/12/dplyr-0-8-0-release-candidate/&#34;&gt;release notes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since then, &lt;a href=&#34;https://twitter.com/romain_francois&#34;&gt;romain francois&lt;/a&gt; has worked on some changes
to the group operation in &lt;a href=&#34;https://github.com/tidyverse/dplyr/pull/4251&#34;&gt;this pull request #4251&lt;/a&gt;,
and things have changed a bit.&lt;/p&gt;
&lt;p&gt;The group operations which have just been modified from 0.8.0 and ready for release whenever
v0.8.1 comes out are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;group_split()&lt;/code&gt; - split a data.frame by the grouping columns into a list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_data()&lt;/code&gt; - a data.frame of just the grouping variables and the corresponding row indices for the members of the group in the original data.frame.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_keys()&lt;/code&gt; - identical to &lt;code&gt;group_data()&lt;/code&gt; except lacking that &lt;code&gt;.rows&lt;/code&gt; (row indicies) data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_map()&lt;/code&gt; - map a function over each group and return a list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_modify()&lt;/code&gt; - map a function over each group and return a single data.frame&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a short post to try and figure out what they now do!&lt;/p&gt;
&lt;div id=&#34;tldr&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;tl;dr!&lt;/h2&gt;
&lt;p&gt;You can safely not-read the rest of this post except for this table.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The addition of the &lt;code&gt;keep&lt;/code&gt; argument to the &lt;code&gt;group_modify/map/split&lt;/code&gt; lets
you be explicit about whether the &lt;code&gt;.x&lt;/code&gt; list of subset data.frames
includes/excludes the grouping columns.&lt;/li&gt;
&lt;li&gt;The addition of the &lt;code&gt;.drop&lt;/code&gt; argument to &lt;code&gt;group_by()&lt;/code&gt; lets you control whether or
not empty groups are kept in the process.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;13%&#34; /&gt;
&lt;col width=&#34;46%&#34; /&gt;
&lt;col width=&#34;26%&#34; /&gt;
&lt;col width=&#34;13%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;equivalent to (approx)&lt;/th&gt;
&lt;th&gt;returns&lt;/th&gt;
&lt;th&gt;default ‘keep’&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_split()&lt;/td&gt;
&lt;td&gt;base::split()&lt;/td&gt;
&lt;td&gt;list of split data.frames&lt;/td&gt;
&lt;td&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;group_data()&lt;/td&gt;
&lt;td&gt;distinct(grouping_cols)&lt;/td&gt;
&lt;td&gt;data.frame of just group cols&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_keys()&lt;/td&gt;
&lt;td&gt;group_data() without the &lt;code&gt;.rows&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;data.frame of just group cols&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;group_map()&lt;/td&gt;
&lt;td&gt;map2(.x = group_split(), .y = group_keys(), .fun)&lt;/td&gt;
&lt;td&gt;list of whatever you want&lt;/td&gt;
&lt;td&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_modify()&lt;/td&gt;
&lt;td&gt;map2_dfr(.x = group_split(), .y = group_keys(), .fun)&lt;/td&gt;
&lt;td&gt;single data.frame&lt;/td&gt;
&lt;td&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;test-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Test Data&lt;/h2&gt;
&lt;p&gt;A very simple data.frame to use as the test data. &lt;strong&gt;Note&lt;/strong&gt;: There is an empty factor
level for the &lt;code&gt;type&lt;/code&gt; variable!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- tibble(
  type  = factor(c(&amp;#39;a&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;b&amp;#39;), levels = c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)),
  value = c(1, 2, 3, 4)
)

test_df&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 4 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 a         1
2 a         2
3 b         3
4 b         4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_split()&lt;/code&gt; breaks up a data.frame into a list of subset data.frames by
the grouping variable. It is the tidyverse equivalent of &lt;code&gt;split()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_split()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
# A tibble: 2 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 a         1
2 a         2

[[2]]
# A tibble: 2 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 b         3
2 b         4

attr(,&amp;quot;ptype&amp;quot;)
# A tibble: 0 x 2
# … with 2 variables: type &amp;lt;fct&amp;gt;, value &amp;lt;dbl&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_split---keep-empty-groups&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_split()&lt;/code&gt; - keep empty groups&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type, .drop = FALSE) %&amp;gt;%
  group_split()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
# A tibble: 2 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 a         1
2 a         2

[[2]]
# A tibble: 2 x 2
  type  value
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 b         3
2 b         4

[[3]]
# A tibble: 0 x 2
# … with 2 variables: type &amp;lt;fct&amp;gt;, value &amp;lt;dbl&amp;gt;

attr(,&amp;quot;ptype&amp;quot;)
# A tibble: 0 x 2
# … with 2 variables: type &amp;lt;fct&amp;gt;, value &amp;lt;dbl&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_data()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_data()&lt;/code&gt; returns a data.frame with just the distinct grouping variables.
It includes a &lt;code&gt;.rows&lt;/code&gt; column which is a list-column of indices into the original data.frame
which belong to each group&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_data()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2 x 2
  type  .rows    
  &amp;lt;fct&amp;gt; &amp;lt;list&amp;gt;   
1 a     &amp;lt;int [2]&amp;gt;
2 b     &amp;lt;int [2]&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_keys&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_keys()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_keys()&lt;/code&gt; is basically &lt;code&gt;group_data()&lt;/code&gt; without the &lt;code&gt;.rows&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_keys()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2 x 1
  type 
  &amp;lt;fct&amp;gt;
1 a    
2 b    &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_map&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_map()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_map()&lt;/code&gt; applies a function to each subset of a data.frame split by the
grouping variable. It returns a list.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;group_map()&lt;/code&gt; is the approximate equivalent of &lt;code&gt;purrr::map2(.x = group_split(.data), .y = transpose(group_keys(.data)), .fun)&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_map(~.x)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
# A tibble: 2 x 1
  value
  &amp;lt;dbl&amp;gt;
1     1
2     2

[[2]]
# A tibble: 2 x 1
  value
  &amp;lt;dbl&amp;gt;
1     3
2     4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_modify&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_modify()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_modify()&lt;/code&gt; applies a function to each subset of a data.frame split by the
grouping variable.&lt;/p&gt;
&lt;p&gt;The applied function must return a data.frame &lt;em&gt;without&lt;/em&gt; the grouping columns.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;group_modify()&lt;/code&gt; is the approximate equivalent of &lt;code&gt;purrr::map2_dfr(.x = group_split(.data), .y = transpose(group_keys(.data)), .fun)&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_modify(~tibble(new = 1))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2 x 2
# Groups:   type [2]
  type    new
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt;
1 a         1
2 b         1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_modify---trying-to-access-a-grouping-column-in-.x-when-keep-false&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_modify()&lt;/code&gt; - trying to access a grouping column in &lt;code&gt;.x&lt;/code&gt; when &lt;code&gt;keep = FALSE&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In the following code, we should get a warning/error. This is because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the grouping variable is &lt;code&gt;type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;default &lt;code&gt;keep&lt;/code&gt; is set to &lt;code&gt;FALSE&lt;/code&gt;, which means that &lt;code&gt;.x&lt;/code&gt; will not contain the grouping column&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_modify(~tibble(
    total   = sum(.x$value),
    newtype = paste0(.x$type, &amp;quot;1&amp;quot;))
  )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: Unknown or uninitialised column: &amp;#39;type&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;type&amp;#39;.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2 x 3
# Groups:   type [2]
  type  total newtype
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;  
1 a         3 1      
2 b         7 1      &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_modify---accessing-a-grouping-column-in-.y-always-works&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_modify()&lt;/code&gt; - accessing a grouping column in &lt;code&gt;.y&lt;/code&gt; always works&lt;/h2&gt;
&lt;p&gt;The grouping variable is always available from the &lt;code&gt;.y&lt;/code&gt;, regardless of the &lt;code&gt;keep&lt;/code&gt; setting&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_modify(~tibble(
    total   = cumsum(.x$value),
    newtype = paste0(.y$type, &amp;quot;1&amp;quot;))
  )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 4 x 3
# Groups:   type [2]
  type  total newtype
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;  
1 a         1 a1     
2 a         3 a1     
3 b         3 b1     
4 b         7 b1     &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_modify---accessing-a-grouping-column-in-.x-when-keep-true&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_modify()&lt;/code&gt; - accessing a grouping column in &lt;code&gt;.x&lt;/code&gt; when &lt;code&gt;keep = TRUE&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;By setting &lt;code&gt;keep = TRUE&lt;/code&gt;, we ensure that the &lt;code&gt;.x&lt;/code&gt; includes the grouping column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_modify(~tibble(
    total   = cumsum(.x$value),
    newtype = paste0(.x$type, &amp;quot;1&amp;quot;)
  ), keep = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 4 x 3
# Groups:   type [2]
  type  total newtype
  &amp;lt;fct&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;  
1 a         1 a1     
2 a         3 a1     
3 b         3 b1     
4 b         7 b1     &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The addition of the &lt;code&gt;keep&lt;/code&gt; argument to the &lt;code&gt;group_modify/map/split&lt;/code&gt; lets
you be explicit about whether the &lt;code&gt;.x&lt;/code&gt; list of subset data.frames
includes/excludes the grouping columns.&lt;/li&gt;
&lt;li&gt;The addition of the &lt;code&gt;.drop&lt;/code&gt; argument to &lt;code&gt;group_by()&lt;/code&gt; lets you control whether or
not empty groups are kept in the process.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col width=&#34;13%&#34; /&gt;
&lt;col width=&#34;46%&#34; /&gt;
&lt;col width=&#34;26%&#34; /&gt;
&lt;col width=&#34;13%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;equivalent to (approx)&lt;/th&gt;
&lt;th&gt;returns&lt;/th&gt;
&lt;th&gt;default ‘keep’&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_split()&lt;/td&gt;
&lt;td&gt;base::split()&lt;/td&gt;
&lt;td&gt;list of split data.frames&lt;/td&gt;
&lt;td&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;group_data()&lt;/td&gt;
&lt;td&gt;distinct(grouping_cols)&lt;/td&gt;
&lt;td&gt;data.frame of just group cols&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_keys()&lt;/td&gt;
&lt;td&gt;group_data() without the &lt;code&gt;.rows&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;data.frame of just group cols&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;group_map()&lt;/td&gt;
&lt;td&gt;map2(.x = group_split(), .y = group_keys(), .fun)&lt;/td&gt;
&lt;td&gt;list of whatever you want&lt;/td&gt;
&lt;td&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;group_modify()&lt;/td&gt;
&lt;td&gt;map2_dfr(.x = group_split(), .y = group_keys(), .fun)&lt;/td&gt;
&lt;td&gt;single data.frame&lt;/td&gt;
&lt;td&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Anonymous Functions in R - Part 3: Introducing the &#39;anon&#39; package</title>
      <link>https://coolbutuseless.github.io/2019/03/14/anonymous-functions-in-r-part-3-introducing-the-anon-package/</link>
      <pubDate>Thu, 14 Mar 2019 20:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/14/anonymous-functions-in-r-part-3-introducing-the-anon-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;An &lt;a href=&#34;https://en.wikipedia.org/wiki/Anonymous_function&#34;&gt;Anonymous Function&lt;/a&gt; (also known as a &lt;em&gt;lambda expression&lt;/em&gt;) is a
function definition that is not bound to an identifier. That is, it is a
function that is created and used, but never assigned to a variable.&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&#34;https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-1/&#34;&gt;prior post&lt;/a&gt; I discussed how I am not completely ssatisfied with &lt;code&gt;purrr&lt;/code&gt;/&lt;code&gt;rlang&lt;/code&gt;’s
anonymous function syntax as it has no capability for naming the
function arguments anything other than &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&#34;https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-2/&#34;&gt;follow-up post&lt;/a&gt;, I looked at alternate syntaxes for creating anonymous functions.&lt;/p&gt;
&lt;p&gt;In this post, I&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;outline what I think would unify the anonymous function implementations&lt;/li&gt;
&lt;li&gt;introduce the &lt;a href=&#34;https://github.com/coolbutuseless/anon&#34;&gt;‘anon’ package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;thoughts-on-a-unifying-anonymous-function-implementation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Thoughts on a unifying anonymous function implementation&lt;/h2&gt;
&lt;p&gt;After looking at the other syntaxes for creating anonymous functions, my ideas
for a unifying anonymous function implementation are as follows:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Use a short function to create other anonymous functions
&lt;ul&gt;
&lt;li&gt;This is mostly personal preference.&lt;/li&gt;
&lt;li&gt;Overloading an existing operator seems fraught with compatibility issues.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Support both &lt;strong&gt;implicit&lt;/strong&gt; and &lt;strong&gt;explicit&lt;/strong&gt; formal arguments.
&lt;ul&gt;
&lt;li&gt;Supporting only one or the other limits the flexibility.&lt;/li&gt;
&lt;li&gt;I want the generation of arguments to work automatically when it’s obvious what is meant, but still retain
the ability to be explicit when more clarifying information is needed about the ordering/existence of variables as
the formal arguments.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;explicit formal arguments&lt;/strong&gt; allow multiple representations i.e. to be
familiar across more existing packages, the following should all create the same
anonymous function
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;f(x, y, x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(x, y ~ x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(x, y, ~x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(x + y ~ x + y)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Try and match &lt;code&gt;purrr&lt;/code&gt;/&lt;code&gt;rlang&lt;/code&gt;’s syntax as close as possible
&lt;ul&gt;
&lt;li&gt;This seems to be the most popular anonymous function syntax, so don’t rock
the boat by being too different.&lt;/li&gt;
&lt;li&gt;Yet still be valid without the leading tilde&lt;/li&gt;
&lt;li&gt;I.e. the following should all create the same anonymous function
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;f(x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(~x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(~.x + .y)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;introducing-the-anon-package-for-anonymous-functions-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introducing the &lt;code&gt;anon&lt;/code&gt; package for anonymous functions in R&lt;/h2&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/status-rough-red.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;anon&lt;/code&gt; package provides two functions to help define succinct anonymous functions (also called &lt;em&gt;lambdas&lt;/em&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;features&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Features&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;anon&lt;/code&gt; provides two user-facing functions:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;lambda()&lt;/code&gt; for easily and compactly creating
lambda expressions in R, while being broadly compatible with a number of existing
lambda syntaxes. This function is also aliased to &lt;code&gt;L()&lt;/code&gt; for the sake of brevity.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;patch_purrr_mapper()&lt;/code&gt; to patch &lt;code&gt;purrr&lt;/code&gt; to allow &lt;code&gt;anon&lt;/code&gt; to convert formulas to functions instead of &lt;code&gt;rlang::as_function()&lt;/code&gt;. Using &lt;code&gt;anon&lt;/code&gt; to convert formulas-to-functions enables:
&lt;ul&gt;
&lt;li&gt;automatic argument extraction (rather than forcing the arguments to be &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;explicit arguments through the use of 2 sided formulas i.e. the formal arguments are extracted from
the expression on the LHS of a two-sided formula e.g. &lt;code&gt;a:b ~ a + b + 1&lt;/code&gt; becomes &lt;code&gt;function(a, b) {a + b + 1}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Installation&lt;/h1&gt;
&lt;p&gt;You can install &lt;code&gt;anon&lt;/code&gt; from &lt;a href=&#34;https://github.com/coolbutuseless/anon&#34;&gt;github&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;remotes::install_github(&amp;quot;coolbutuseless/anon&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-use-of-lambdal-for-creating-anonymous-functions&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example use of &lt;code&gt;lambda()&lt;/code&gt;/&lt;code&gt;L()&lt;/code&gt; for creating anonymous functions&lt;/h1&gt;
&lt;p&gt;The following calls all create the same anonymous function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;function(x, y) x + y&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(.x + .y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(~x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(x, y, x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(x, y ~ x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(x, y, ~x + y)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;L(x:y ~ x + y)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-use-of-patch_purrr_mapper-to-enable-extended-functionality-for-lambdas-in-purrr&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example use of &lt;code&gt;patch_purrr_mapper()&lt;/code&gt; to enable extended functionality for lambdas in &lt;code&gt;purrr&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;By running &lt;code&gt;patch_purrr_mapper()&lt;/code&gt; an extra S3 method is added for &lt;code&gt;purrr::as_mapper()&lt;/code&gt; i.e.
&lt;code&gt;as_mapper.formula()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By doing so, any &lt;em&gt;formula-used-as-function&lt;/em&gt; in &lt;code&gt;purrr&lt;/code&gt;
will be passed to &lt;code&gt;anon::as_function_formula()&lt;/code&gt; which allows for more expressiveness
than &lt;code&gt;rlang::as_function()&lt;/code&gt;. i.e.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Can use any name for the variables, not just &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Can set explicit formal arguments (by specifying the LHS of the formula)&lt;/li&gt;
&lt;li&gt;If no explicit formal arguments are given, then all variable names on the RHS of the
formula are used as formal arguments. The order of the formal arguments is the same
as the order of appearance of the variables.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;.x&lt;/code&gt; or &lt;code&gt;.y&lt;/code&gt; appear on the RHS and no explicit formal arguments are given on the LHS,
then they are used as the first formal arguments (regardless of the order in which they appear on the RHS)&lt;/li&gt;
&lt;li&gt;You can use &lt;code&gt;.&lt;/code&gt; as a stand-in for the first argument.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(purrr)
anon::patch_purrr_mapper()

z &amp;lt;- 10L

map_int(1:3, ~. + 1L)
[1] 2 3 4

map_int(1:3, ~.x + 1L)
[1] 2 3 4

map_int(1:3, ~ value + 1L)
[1] 2 3 4

map_int(1:3, val ~ val + 1L)
[1] 2 3 4

map_int(1:3, val ~ val + z)
[1] 11 12 13

map2_dbl(1:3, 4:6, ~ .x / .y)
[1] 0.25 0.40 0.50

map2_dbl(1:3, 4:6, ~ a / b)
[1] 0.25 0.40 0.50

map2_dbl(1:3, 4:6, ~ b / a)
[1] 0.25 0.40 0.50

map2_dbl(1:3, 4:6, b:a ~ a / b)
[1] 4.0 2.5 2.0

pmap_int(list(1:2, 3:4, 5:6, 7:8), ~a * b * c * d)
[1] 105 384&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Anonymous Functions in R - Part 2</title>
      <link>https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-2/</link>
      <pubDate>Wed, 13 Mar 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;An &lt;a href=&#34;https://en.wikipedia.org/wiki/Anonymous_function&#34;&gt;Anonymous Function&lt;/a&gt; (also known as a &lt;em&gt;lambda experssion&lt;/em&gt;) is a
function definition that is not bound to an identifier. That is, it is a
function that is created and used, but never assigned to a variable.&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&#34;https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-1/&#34;&gt;prior post&lt;/a&gt; I discussed how I am not completely satisfied with &lt;code&gt;purrr&lt;/code&gt;/&lt;code&gt;rlang&lt;/code&gt;’s
anonymous function syntax as it has no capability for naming the
function arguments anything other than &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this post, I’ll look at alternate syntaxes for creating anonymous functions.&lt;/p&gt;
&lt;div id=&#34;implementations-of-anonymous-functions-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Implementations of anonymous functions in R&lt;/h2&gt;
&lt;p&gt;There are many implementations of helpers to create anonymous functions.&lt;/p&gt;
&lt;p&gt;Base R has its own mechanism, and all the other implementations try and keep
the syntax shorter by dropping the requirement to actually type &lt;code&gt;function()&lt;/code&gt; when
creating the anonymous function.&lt;/p&gt;
&lt;p&gt;The following table lists the implementations of anonymous functions I could find in R,
and their syntax for creating an anonymous function with 2 arguments.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Formal Arguments&lt;/strong&gt; column indicates how the arguments for the anonymous
function are derived. Some packages support both implicit and explicit argument
naming (e.g. &lt;code&gt;gsubfn&lt;/code&gt; and &lt;code&gt;pryr&lt;/code&gt;). If the formal arguments are not explicitly stated,
then the argument list may be inferred by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;convention e.g. &lt;code&gt;rlang::as_function()&lt;/code&gt; assumes arguments are &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;inference e.g. &lt;code&gt;pryr::f()&lt;/code&gt; uses all variables found in the expression as formal arguments.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- (My first table created with the [gt package](https://github.com/rstudio/gt/)!) --&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;Package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Function Name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;1-arg&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;2-args&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Explicit Arg Names&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Formal Arguments&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Extra chars for implicit args&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Core Syntax&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Core Syntax Nchars&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;formals/body separator&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;comments&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;author&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base r&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;function&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;function(x) x + 1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;function(x, y) x + y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;function()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R Core&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rlang&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as_function&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as_function(~.x + 1))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as_function(~.x+.y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Implicit. Only .x or .y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.x&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(~)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;used within purrr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lionel Henry et al&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://cran.r-project.org/package=rlang&#34; class=&#34;uri&#34;&gt;https://cran.r-project.org/package=rlang&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pryr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f (implicit args)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Implicit. Inferred from expression&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hadley Wickham&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://cran.r-project.org/package=pryr&#34; class=&#34;uri&#34;&gt;https://cran.r-project.org/package=pryr&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pryr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f (explicit args)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x, x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x, y, x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;,&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;nofrills&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fn(x ~ x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fn(x, y ~ x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(~)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Fully NSE aware (!!)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eugene Ha&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://cran.r-project.org/package=nofrills&#34; class=&#34;uri&#34;&gt;https://cran.r-project.org/package=nofrills&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gsubfn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula (implicit args)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula(~ x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula(~ x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Implicit. Inferred from RHS of formula&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(~)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;G. Grothendieck&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://cran.r-project.org/package=gsubfn&#34; class=&#34;uri&#34;&gt;https://cran.r-project.org/package=gsubfn&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gsubfn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula (explicit args)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula(x ~ x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.function.formula(x + y ~ x + y + z)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit. Inferred from LHS of formula&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(~)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;wrapr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x, x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x, y, x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;,&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;John Mount et al&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://cran.r-project.org/package=wrapr&#34; class=&#34;uri&#34;&gt;https://cran.r-project.org/package=wrapr&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lambda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(.(x) + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(.(x) + .(y))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Implicit. Inferred from expression&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.(x)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jim Hester&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/jimhester/lambda&#34; class=&#34;uri&#34;&gt;https://github.com/jimhester/lambda&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lambdass&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~~&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~~ ..1 + 1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~~ ..1 + ..2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Implicit. Only ..N arg syntax allowed&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;..1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~~&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TobCap&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/TobCap/lambdass&#34; class=&#34;uri&#34;&gt;https://github.com/TobCap/lambdass&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lambdass&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f.()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f.(x, x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f.(x, y, x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;,&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lambdass&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;%-&amp;gt;%&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x) %-&amp;gt;% {x + 1}&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(x, y) %-&amp;gt;% {x + y}&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f()%-&amp;gt;%{}&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;`%-&amp;gt;%&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;functional&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“-&amp;gt;”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;x ~ y -&amp;gt; x + y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;messes with &amp;lt;- operator!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Konrad Rudolph&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/klmr/functional&#34; class=&#34;uri&#34;&gt;https://github.com/klmr/functional&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Not packaged&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x ~ x + 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x + y ~ x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit. Inferred from LHS of formula&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(~)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Edward Visel&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://alistaire.rbind.io/blog/anonymous-functions/&#34; class=&#34;uri&#34;&gt;https://alistaire.rbind.io/blog/anonymous-functions/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Not packaged&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x:x + 1)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lambda(x, y:x + y)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f(:)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;,&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Code no longer available&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Koji MAKIYAMA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://rpubs.com/hoxo_m/lambdaR&#34; class=&#34;uri&#34;&gt;https://rpubs.com/hoxo_m/lambdaR&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Not packaged&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[] -&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[x] -&amp;gt; x + 1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[x, y] -&amp;gt; x + y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Explicit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[]-&amp;gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;`-&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Speculative Future R syntax&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lionel Henry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://lionel-.github.io/2016/02/15/ideas-for-an-updated-r-syntax/&#34; class=&#34;uri&#34;&gt;https://lionel-.github.io/2016/02/15/ideas-for-an-updated-r-syntax/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;features-of-an-anonymous-function-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Features of an anonymous function syntax&lt;/h2&gt;
&lt;p&gt;I’ve tried to come up with a taxonomy to help classify the various syntaxes. I
can’t say I was hugely successful, but it helped me organise my thoughts a little.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explicit Arguments&lt;/strong&gt;: The syntax has a list of formal arguments provided separate to the body of the function
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Arguments provided as a separate list
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;Base R&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Arguments are parsed out of a separate expression (which is not the expression which becomes the body of the anonymous function)
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;gsubfn&lt;/code&gt; where names are parsed out of the expression on the LHS of the formula&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implicit Arguments&lt;/strong&gt;: The syntax only provides the body of the anonymous function, and the
formal arguments are never separately listed
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Arguments are pre-defined
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;rlang::as_function&lt;/code&gt; pre-defines &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt; as the formal args.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;lambdass&lt;/code&gt; package uses the the &lt;code&gt;..1&lt;/code&gt;, &lt;code&gt;..2&lt;/code&gt; argument form in one of its implementations.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Arguments are parsed from the expression which becomes the function body
&lt;ul&gt;
&lt;li&gt;.e.g the one-sided formula from &lt;code&gt;gsubfn&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implicit Arguments with discrimination&lt;/strong&gt;: arguments are parsed from the given expression, and there
is some way to indicate whether this is a variable from the enclosing environment or is a formal argument.
&lt;ul&gt;
&lt;li&gt;Only Jim Hester’s &lt;code&gt;lambda&lt;/code&gt; does this. Variables specified using the &lt;code&gt;bquote()&lt;/code&gt; syntax of &lt;code&gt;.(x)&lt;/code&gt; are
considered formal arguments, everything else is a variable from the enclosing environment.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Function Creation&lt;/strong&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;strong&gt;Function Call&lt;/strong&gt;: Use a short function call to hide the explicit call to &lt;code&gt;function()&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;This is the most common route of creation e.g. &lt;code&gt;rlang::as_function()&lt;/code&gt;, &lt;code&gt;pryr::f()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exsiting Operator&lt;/strong&gt;: Existing operator is repurposed to create function
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;lambdass&lt;/code&gt; hijacks the operation of &lt;code&gt;~&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;e.g. Lionel Henry’s syntax idea hijacks the &lt;code&gt;-&amp;gt;&lt;/code&gt; operator&lt;/li&gt;
&lt;li&gt;e.g. Konrad Rudolph’s &lt;code&gt;functional&lt;/code&gt; package/module also hijacks the &lt;code&gt;-&amp;gt;&lt;/code&gt; operator and thus is only useable in code
which uses &lt;code&gt;=&lt;/code&gt; for assignment.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New operator&lt;/strong&gt;: New operator used to create function
&lt;ul&gt;
&lt;li&gt;Only &lt;code&gt;lambdass&lt;/code&gt; does this with the &lt;code&gt;%-&amp;gt;%&lt;/code&gt; infix operator&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;notes-on-current-implementations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes on current implementations&lt;/h2&gt;
&lt;p&gt;Some of my thoughts/notes on the current implementations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Base R&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Some would consider having to write out &lt;code&gt;function() {}&lt;/code&gt; makes this a &lt;em&gt;verbose&lt;/em&gt; syntax. Others would say I’m wrong.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;function()&lt;/code&gt; text and the separate explicit list of formal arguments seems mostly
redundant for a large percentage of cases where anonymous functions must be used i.e. single formal argument and small function body.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;rlang::as_function()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Very handy within the &lt;code&gt;purrr&lt;/code&gt; family of functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BUT&lt;/strong&gt;: No ability to customise argument names!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;pryr::f()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Supports both implicit and explicit formal arguments&lt;/li&gt;
&lt;li&gt;Doesn’t use the leading &lt;code&gt;~&lt;/code&gt; like &lt;code&gt;purrr/rlang&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;nofrills::fn()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Only explicit formal arguments&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;~&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Full support for &lt;code&gt;tidyverse&lt;/code&gt; style Non-standard evaluation! This seems like overkill
for my use case.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;gsubfn::as.function.formula()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Supports both implicit and explicit formal arguments&lt;/li&gt;
&lt;li&gt;Uses a leading &lt;code&gt;~&lt;/code&gt; like &lt;code&gt;purrr/rlang&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When using explicit formal args, the LHS (confusingly) looks like an expression itself!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;wrapr::lambda()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Explicit formal arguments only&lt;/li&gt;
&lt;li&gt;Doesn’t use leading &lt;code&gt;~&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jim Hester’s lambda&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;I like that it allows you to explicitly indicate variables in the expression body
that should be formal arguments using &lt;code&gt;bquote()&lt;/code&gt; substitution syntax. I just find
the &lt;code&gt;bquote()&lt;/code&gt; substitution syntax too fiddly/verbose!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;lambdass::f.()&lt;/code&gt;&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Explicit formal arguments only&lt;/li&gt;
&lt;li&gt;The other two forms for creating anonymous functions are a bit too funky for my liking!
&lt;ul&gt;
&lt;li&gt;Overriding the operation of &lt;code&gt;~&lt;/code&gt; seems fraught with issues&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;%-&amp;gt;%&lt;/code&gt; operator seems too fiddly/verbose&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;functional&lt;/code&gt; module&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;The use of the forward assignment operator looks nice and mimics how other languages might do an anonymous function.&lt;/li&gt;
&lt;li&gt;However, because it uses the &lt;code&gt;-&amp;gt;&lt;/code&gt;, it actually messes with &lt;code&gt;&amp;lt;-&lt;/code&gt; as well, so you have to use &lt;code&gt;=&lt;/code&gt; to do actual assignment in your code if you use this.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;thoughts-on-unifying-implementation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Thoughts on unifying implementation&lt;/h2&gt;
&lt;p&gt;After having looked at the existing implementations, here is my short list of what I
think is needed for a good anonymous function implementation in R&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a function call to create the anonymous function - don’t use operator overloading or create a new operator.&lt;/li&gt;
&lt;li&gt;Allow both explicit and implicit formal arguments to give brevity when formal arguments
are obvious, but flexibilty to explicitly define things&lt;/li&gt;
&lt;li&gt;Compatibility with &lt;code&gt;rlang&lt;/code&gt; syntax. Ultimately, &lt;code&gt;purrr::map&lt;/code&gt; is where I
want to use anonymous functions the most, so it’d be nice if this could be a drop-in replacement.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;next-steps&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;Future post: What might a unifying implementation look like?&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Anonymous Functions in R - Part 1</title>
      <link>https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-1/</link>
      <pubDate>Wed, 13 Mar 2019 05:50:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/13/anonymous-functions-in-r-part-1/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;An &lt;a href=&#34;https://en.wikipedia.org/wiki/Anonymous_function&#34;&gt;Anonymous Function&lt;/a&gt; (also known as a &lt;em&gt;lambda experssion&lt;/em&gt;) is a
function definition that is not bound to an identifier. That is, it is a
function that is created and used, but never assigned to a variable.&lt;/p&gt;
&lt;div id=&#34;base-r-anonymous-function-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R anonymous function syntax&lt;/h2&gt;
&lt;p&gt;An example in R where anonymous functions are used is in &lt;code&gt;*apply()&lt;/code&gt; family of functions. In the
following example a function is defined which takes one argument, adds one to it,
and then returns it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sapply(1:2, function(x) x + 1L)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that this is everything needed for a function definition (formal arugments, a body). It is never actually assigned to a variable, but
used immediately by &lt;code&gt;sapply()&lt;/code&gt; on each element of the given vector.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;purrrs-anonymous-function-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;purrr&lt;/code&gt;’s anonymous function syntax&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://cran.r-project.org/package=purrr&#34;&gt;purrr package&lt;/a&gt; uses the &lt;a href=&#34;https://cran.r-project.org/package=rlang&#34;&gt;rlang package&lt;/a&gt; to
help define anonymous functions in a very brief way.&lt;/p&gt;
&lt;p&gt;Instead of having to type &lt;code&gt;function(x) {...}&lt;/code&gt;, a function is constructed from a user-specified, one-sided formula. Because &lt;code&gt;purrr/rlang&lt;/code&gt; enforces some constraints on the type of arguments the function definition is very abbreviated:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;purrr::map_int(1:2, ~.x + 1L)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code, the one-sided formula &lt;code&gt;~.x + 1&lt;/code&gt; is expanded by &lt;code&gt;rlang::as_function()&lt;/code&gt; into a full function which looks something like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;function(.x) {
  .x + 1
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The advantage of &lt;code&gt;purrr&lt;/code&gt;’s syntax is that it’s very brief. It allows the user
to define functions quickly and with a minimum of characters by:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Not having to specify &lt;code&gt;function()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pre-defining the arguments to the function to be &lt;code&gt;.x&lt;/code&gt; (and maybe &lt;code&gt;.y&lt;/code&gt; and some other things), and
not giving the user any option to change the defaults.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;my-issue-with-purrrs-anonymous-function-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My issue with &lt;code&gt;purrr&lt;/code&gt;’s anonymous function syntax&lt;/h2&gt;
&lt;p&gt;I realised recently, that while I like the brevity of the anonymous function
syntax in &lt;code&gt;purrr&lt;/code&gt;/&lt;code&gt;rlang&lt;/code&gt; I felt it a little &lt;em&gt;too&lt;/em&gt; constraining because the
two argument names can only be &lt;code&gt;.x&lt;/code&gt; and &lt;code&gt;.y&lt;/code&gt;. This can be a problem as it
can limit the readability of the function quite a bit.&lt;/p&gt;
&lt;p&gt;For example, if mapping over vectors of &lt;code&gt;volumes&lt;/code&gt; and &lt;code&gt;surface_areas&lt;/code&gt;, then a &lt;code&gt;map2&lt;/code&gt; call might look like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ratios &amp;lt;- purrr::map2(volumes, surface_areas, ~.x/.y)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looking at the anonymous function in isolation, &lt;code&gt;~.x/.y&lt;/code&gt; isn’t really that informative on what
we are calculating, and it would be nice if we could instead call something like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ratios &amp;lt;- purrr::map2(volumes, surface_areas, ~vol/area)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;alternatives-to-purrrs-anonymous-function-syntax&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Alternatives to &lt;code&gt;purrr&lt;/code&gt;’s anonymous function syntax&lt;/h2&gt;
&lt;p&gt;I’ve since been on a hunt for an alternative syntax that allows for named arguments
while still retaining some of the brevity of the &lt;code&gt;purrr/rlang&lt;/code&gt; implementation.&lt;/p&gt;
&lt;p&gt;I’ve listed all the ones I could find below, and in a future post I will try and compare
them to find what syntax is possible and/or useful within the realms of R. Stay tuned…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base R
&lt;ul&gt;
&lt;li&gt;Built-in support for anonymous functions i.e. &lt;code&gt;function(x) x + 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;CRAN
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=rlang&#34;&gt;rlang package&lt;/a&gt;
&lt;!-- * [lambda.r package (CRAN)](https://cran.r-project.org/package=lambda.r) --&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=wrapr&#34;&gt;wrapr package (CRAN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=gsubfn&#34;&gt;gsubfn package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/egnha/nofrills&#34;&gt;nofrills package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Non-CRAN package
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/jimhester/lambda&#34;&gt;jimhester’s lambda package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/TobCap/lambdass&#34;&gt;lambdass - lambda syntax sugar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Not packaged
&lt;ul&gt;
&lt;li&gt;Edward Visel blog post: &lt;a href=&#34;https://alistaire.rbind.io/blog/anonymous-functions/&#34;&gt;Part 1&lt;/a&gt; and &lt;a href=&#34;https://alistaire.rbind.io/blog/anonymous-functions-2&#34;&gt;Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Defunct
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://lionel-.github.io/2016/02/15/ideas-for-an-updated-r-syntax/&#34;&gt;lionel henry blogpost on updated R syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/hoxo_m/lambdaR&#34;&gt;lambdaR package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/tidyverse/magrittr/tree/lambda&#34;&gt;Old magrittr branch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>image2xlsx package: Converting an image to an excel spreadsheet</title>
      <link>https://coolbutuseless.github.io/2019/03/09/image2xlsx-package-converting-an-image-to-an-excel-spreadsheet/</link>
      <pubDate>Sat, 09 Mar 2019 06:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/09/image2xlsx-package-converting-an-image-to-an-excel-spreadsheet/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;!-- README.md is generated from README.Rmd. Please edit that file --&gt;
&lt;div id=&#34;image2xlsx&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;image2xlsx&lt;/h1&gt;
&lt;!-- badges: start --&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/cool-useless-green.svg&#34; /&gt;
&lt;img src=&#34;https://img.shields.io/badge/status-rough-red.svg&#34; /&gt;
&lt;!-- badges: end --&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;image2xlsx&lt;/code&gt; provides a single function to turn an image into an excel (xlsx) spreadsheet.&lt;/p&gt;
&lt;p&gt;It stands on the shoulders of the following giants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=openxlsx&#34;&gt;openxlsx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=magick&#34;&gt;magick + imagemagick&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=dplyr&#34;&gt;dplyr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=tidyr&#34;&gt;tidyr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=raster&#34;&gt;raster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from &lt;a href=&#34;https://github.com/coolbutuseless/image2xlsx&#34;&gt;GitHub&lt;/a&gt; with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/image2xlsx&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rlogo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rlogo&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(image2xlsx)
image2xlsx(&amp;quot;working/RStudio.png&amp;quot;, &amp;quot;man/figures/rlogo.xlsx&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A screenshot of &lt;code&gt;rlogo.xlsx&lt;/code&gt; opened in LibreOffice&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/image2xlsx/rlogo.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;bender-bending-rodríguez&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bender Bending Rodríguez&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(image2xlsx)
image2xlsx(&amp;quot;working/bender.jpg&amp;quot;, &amp;quot;man/figures/bender.xlsx&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A screenshot of &lt;code&gt;bender.xlsx&lt;/code&gt; opened in LibreOffice&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/image2xlsx/bender.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;grappling-hook&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Grappling Hook!&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(image2xlsx)
image2xlsx(&amp;quot;working/mabel.png&amp;quot;, &amp;quot;man/figures/mabel.xlsx&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A screenshot of &lt;code&gt;mabel.xlsx&lt;/code&gt; opened in LibreOffice&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/image2xlsx/mabel.png&#34; width=&#34;100%&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Custom axis breaks on facetted ggplot</title>
      <link>https://coolbutuseless.github.io/2019/03/07/custom-axis-breaks-on-facetted-ggplot/</link>
      <pubDate>Thu, 07 Mar 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/07/custom-axis-breaks-on-facetted-ggplot/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;I needed to create a facetted ggplot with custom x-axis breaks on every single plot.&lt;/p&gt;
&lt;p&gt;The x-axis had units of hours and some plots spanned multiple days, and other spanned
just a few hours. For the facets that spanned multiple days I wanted breaks
at every 24 hours, but for the shorter times I needed breaks every hour.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-07-custom-breaks-facetted-ggplot2_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggplot2&lt;/code&gt; allows you to use a function to set the &lt;code&gt;breaks&lt;/code&gt; for
the x-axis, so I could just check what the limits of the plot are and do
two different things depending on the upper limit.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;breaks_fun &amp;lt;- function(x) {
  if (max(x) &amp;gt; 24) {
    seq(0, 120, 24)
  } else {
    seq(0, 8, 1)
  }
}

ggplot(df) + 
  geom_point(aes(x, y)) + 
  facet_wrap(~id, scales = &amp;#39;free_x&amp;#39;) + 
  theme_bw() + 
  scale_x_continuous(breaks = breaks_fun, limits = c(0, NA)) + 
  labs(
    title = &amp;quot;Custom x-axis breaks for each facet&amp;quot;,
    subtitle = &amp;quot;Based upon maximum value on the x-axis&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-07-custom-breaks-facetted-ggplot2_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;And then I could use a global variable to keep track of which plot is being
addressed and customise x-axis breaks even further.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;count &amp;lt;- 0
breaks_fun &amp;lt;- function(x) {
  count &amp;lt;&amp;lt;- count + 1L
  switch(
    count,
    c(1, 3, 5, 7, 9),
    c(45, 55),
    c(0, 50, 100),
    seq(0, 8, 0.2)
  )
}

ggplot(df) + 
  geom_point(aes(x, y)) + 
  facet_wrap(~id, scales = &amp;#39;free_x&amp;#39;) + 
  theme_bw() + 
  scale_x_continuous(breaks = breaks_fun, limits = c(0, NA)) + 
  labs(
    title = &amp;quot;Custom x-axis breaks for each facet&amp;quot;, 
    subtitle = &amp;quot;Based upon plot index&amp;quot;
  )&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-07-custom-breaks-facetted-ggplot2_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
</description>

    </item>
    
    <item>
      <title>Converting an image to an excel spreadsheet</title>
      <link>https://coolbutuseless.github.io/2019/03/03/converting-an-image-to-an-excel-spreadsheet/</link>
      <pubDate>Sun, 03 Mar 2019 09:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/03/03/converting-an-image-to-an-excel-spreadsheet/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;convert-an-image-to-an-excel-spreadsheet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convert an image to an excel spreadsheet&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;openxlsx&lt;/code&gt; is a pretty powerful package to read/write XLSX spreadsheet files.
Attributes and styles can be set programmatically for each cell from within R.&lt;/p&gt;
&lt;p&gt;So I’m going to use it to convert a JPG into a spreadsheet.&lt;/p&gt;
&lt;p&gt;FAQ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Why?&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Because.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(raster)
library(openxlsx)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read the R logo from the jpeg package
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
jpeg_filename &amp;lt;- system.file(&amp;quot;img&amp;quot;, &amp;quot;Rlogo.jpg&amp;quot;, package=&amp;quot;jpeg&amp;quot;)

rlogo &amp;lt;- image_read(jpeg_filename) %&amp;gt;% 
  image_scale(&amp;quot;50%&amp;quot;) %&amp;gt;%
  image_data()


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Turn it into a raster object - this will get us hex colour codes at 
# every location
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size  &amp;lt;- dim(rlogo[1,,])
rlogo &amp;lt;- as.raster(as.integer(rlogo)/255)
plot(rlogo)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-03-03-convert-image-to-excel_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Turn the cell data into a data.frame (ready for openxslx)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rlogo &amp;lt;- as.character(rlogo)
dim(rlogo) &amp;lt;- size 
rlogo &amp;lt;- as.data.frame(rlogo)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Figure out the hex colour code for every cell
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
colours &amp;lt;- rlogo %&amp;gt;% 
  gather(col, colour) %&amp;gt;%
  group_by(col) %&amp;gt;%
  mutate(row = seq(n())) %&amp;gt;%
  ungroup() %&amp;gt;%
  mutate(col = readr::parse_number(col))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a blank data.frame the same size as the colours data.frame
# i.e the cells of this spreadsheet will only contain blanks, and then I&amp;#39;ll
# set the &amp;quot;fill&amp;quot; colour to create the pixels
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
blank &amp;lt;- rlogo
blank[] &amp;lt;- &amp;quot;&amp;quot;


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 1. Create a workbook
# 2. Add a worksheet
# 3. Add blank data of the required size to the worksheet
# 4. set the column widths so that the aspect ratio of final image is OK
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wb &amp;lt;- createWorkbook(&amp;quot;coolbutuseless&amp;quot;)
addWorksheet(wb, &amp;quot;Rlogo&amp;quot;, gridLines = TRUE)
writeData(wb, sheet = 1, blank, colNames = FALSE)
setColWidths(wb, shee=1, cols=seq(size[1]), widths = 2)



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set the style of the cells (in order to define the colour)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (col_df in split(colours, colours$colour)) {
  cell_style &amp;lt;- createStyle(fgFill = col_df$colour[[1]])
  addStyle(wb, sheet = 1, cell_style, rows = col_df$col, cols = col_df$row, gridExpand = FALSE)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Save the workbook
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# openxlsx::saveWorkbook(wb, &amp;quot;crap.xlsx&amp;quot;, overwrite = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Grab this excel spreadsheet &lt;a href=&#34;https://www.dropbox.com/s/hi1l7e4zzynrpw5/crap.xlsx?dl=0&#34;&gt;from my dropbox&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src = &#34;/img/excel/rlogo-xlsx.png&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>object of type &#39;closure&#39; is not(?) subsettable</title>
      <link>https://coolbutuseless.github.io/2019/02/12/object-of-type-closure-is-not-subsettable/</link>
      <pubDate>Tue, 12 Feb 2019 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/02/12/object-of-type-closure-is-not-subsettable/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;r-error-messages-a-visual-overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;R Error messages: A visual overview&lt;/h2&gt;
&lt;p&gt;&lt;img src = &#34;/img/function-subset/mystery.jpg&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;r-error-message-object-of-type-closure-is-not-subsettable&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;R Error message: &lt;code&gt;object of type &#39;closure&#39; is not subsettable&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;A common error in R is &lt;code&gt;object of type &#39;closure&#39; is not subsettable&lt;/code&gt;.
This message means that you have a variable which represents a function,
and you’re mistakenly using square brackets to try and subset it, thinking that
it represents a data.frame or vector or something e.g.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# `mean` here refers the built-in base R function
mean[1:3]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Error in mean[1:3]: object of type &amp;#39;closure&amp;#39; is not subsettable&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In general if you get this error it means you’re trying to subset a function (or
somehow access an item within a function using &lt;code&gt;$&lt;/code&gt;) which (most of the time) doesn’t make much sense in
normal R code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-if-objects-of-type-closure-were-subsettable&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What if objects of type ‘closure’ &lt;em&gt;were&lt;/em&gt; subsettable?&lt;/h2&gt;
&lt;p&gt;While riffing on a joke tweet, &lt;a href=&#34;https://twitter.com/lksmth&#34;&gt;Luke Smith&lt;/a&gt; wondered
on twitter if there was any actual case for make closures subsettable:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Can anyone think of an actual reason to do something like this?  Looking at  you &lt;a href=&#34;https://twitter.com/coolbutuseless?ref_src=twsrc%5Etfw&#34;&gt;@coolbutuseless&lt;/a&gt; &lt;a href=&#34;https://t.co/1R9rHkrosE&#34;&gt;https://t.co/1R9rHkrosE&lt;/a&gt;&lt;/p&gt;&amp;mdash; Luke Smith (@lksmth) &lt;a href=&#34;https://twitter.com/lksmth/status/1094004477038858240?ref_src=twsrc%5Etfw&#34;&gt;February 8, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;The rest of this post is my idea for something vaguely useful you could do with subsetting a function/closure in R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;using-subset-syntax-to-manipulate-formal-arguments-of-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using subset syntax to manipulate formal arguments of functions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Aim:&lt;/strong&gt; manipulate formal arguments of a function using &lt;code&gt;[ ]&lt;/code&gt; or &lt;code&gt;$&lt;/code&gt; syntax&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E.g:&lt;/strong&gt; Use &lt;code&gt;rnorm$mean &amp;lt;- 100&lt;/code&gt; to change the default mean for the &lt;code&gt;rnorm()&lt;/code&gt; function.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Tell R that we want to make `[`  and `$` generic
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[`   &amp;lt;- function(...) {UseMethod(&amp;quot;[&amp;quot;  )}
`[&amp;lt;-` &amp;lt;- function(...) {UseMethod(&amp;quot;[&amp;lt;-&amp;quot;)}
`$`   &amp;lt;- function(...) {UseMethod(&amp;quot;$&amp;quot;  )}
`$&amp;lt;-` &amp;lt;- function(...) {UseMethod(&amp;quot;$&amp;lt;-&amp;quot;)}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Enable subset with [] on a function so we can:
#&amp;#39; Determine the current default value for a given formal argument
#&amp;#39; 
#&amp;#39; e.g.   rnorm[&amp;#39;mean&amp;#39;]
#&amp;#39;
#&amp;#39; @param func function
#&amp;#39; @param arg_name name of formal argument (character)
#&amp;#39;
#&amp;#39; @return current value of formal argument (or warning if not exists)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[.function` &amp;lt;- `[.closure` &amp;lt;- function(func, arg_name) {
  if (arg_name %in% names(formals(func))) {
    formals(func)[[arg_name]]
  } else {
    warning(&amp;quot;No such formal argument: &amp;quot;, arg_name)
  }
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Same as above except allow:   rnorm$mean
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`$.function` &amp;lt;- `$.closure` &amp;lt;- function(func, arg_name) {
  func[as.character(substitute(arg_name))]
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Enable subset assignment on a function so we can:
# Set the given formal argument of the function to the new default value
#
#&amp;#39; e.g.   rnorm[&amp;#39;mean&amp;#39;] &amp;lt;- 100
#&amp;#39;
#&amp;#39; @param func function
#&amp;#39; @param arg_name name of formal argument (character)
#&amp;#39; @param value new default value for formal argument
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`[&amp;lt;-.function` &amp;lt;- `[&amp;lt;-.closure` &amp;lt;- function(func, arg_name, value) {
  fargs             &amp;lt;- formals(func)
  fargs[[arg_name]] &amp;lt;- value
  formals(func)     &amp;lt;- fargs
  
  func
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Same as above except allow:   rnorm$mean &amp;lt;- 100
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`$&amp;lt;-.function` &amp;lt;- `$&amp;lt;-.closure` &amp;lt;- function(func, arg_name, value) {
  func[as.character(substitute(arg_name))] &amp;lt;- value
  func
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-changing-the-default-values-of-rnorm-using-function-subsetting&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: changing the default values of &lt;code&gt;rnorm()&lt;/code&gt; using function subsetting&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Find the default &amp;#39;mean&amp;#39; for this function using &amp;#39;$&amp;#39; syntax
rnorm$mean
## [1] 0

# Set new values for the default `n` and `mean`
rnorm$n     &amp;lt;- 5
rnorm$mean &amp;lt;- 100

# Looking at the function, we can see that the default arguments have been changed
rnorm
## function (n = 5, mean = 100, sd = 1) 
## .Call(C_rnorm, n, mean, sd)
## &amp;lt;environment: namespace:stats&amp;gt;

# And calling it, runs it with the new defaults
rnorm()
## [1]  99.37355 100.18364  99.16437 101.59528 100.32951&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;You can make objects of type ‘closure’ subsettable.&lt;/li&gt;
&lt;li&gt;If ‘closure’ objects are made subsettable, then you can reason about them and
manipulate their arguments and code in a (possibly) intuitive manner.&lt;/li&gt;
&lt;li&gt;You’d probably never want to actually do this because it’s going to be super unsafe behaviour most of the time
i.e. 99.9999999% of the cases, the user expects an error if they try and subset a function, not some weird
thing to do with formal arguments as I’ve defined here.&lt;/li&gt;
&lt;li&gt;TL;DR - Fun, but don’t do it (unless you really want to)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;summary---please-dont&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary - Please don’t&lt;/h2&gt;
&lt;p&gt;&lt;img src = &#34;/img/function-subset/vomit.gif&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>8 out of 10 cats does countdown - part 2</title>
      <link>https://coolbutuseless.github.io/2019/02/11/8-out-of-10-cats-does-countdown-part-2/</link>
      <pubDate>Mon, 11 Feb 2019 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/02/11/8-out-of-10-cats-does-countdown-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;an-error-in-the-previous-solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;An error in the previous solution&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/ClausEkstrom&#34;&gt;Claus Ekstrom&lt;/a&gt; pointed out to me that
&lt;a href=&#34;&#34;&gt;my previous solution&lt;/a&gt; won’t actually find all possible solutions to
the Countdown numbers puzzle. i.e.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Just recoded your implementation in RCPP and it is blazingly fast. But ... the algorithm is not optimal since it works successively on the current value, and you could start in several places. Eg., the numbers 1 1 1 1 1 100, target 404. Add the 4 1s, add up 100+1 and multiply. &lt;a href=&#34;https://t.co/f3Q9uVLVkV&#34;&gt;pic.twitter.com/f3Q9uVLVkV&lt;/a&gt;&lt;/p&gt;&amp;mdash; Claus Ekstrøm (@ClausEkstrom) &lt;a href=&#34;https://twitter.com/ClausEkstrom/status/1093823065845305344?ref_src=twsrc%5Etfw&#34;&gt;February 8, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;This post includes a totally re-written solution which correctly finds all solutions.&lt;/p&gt;
&lt;p&gt;In doing the re-write, this proper solution can be even faster than the old one!&lt;/p&gt;
&lt;p&gt;Timing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runtime for 6 input numbers is about 10 seconds (if limited to only finding integer solutions)&lt;/li&gt;
&lt;li&gt;If you’d like all ~8 million results of all possible expressions involving the 6 numbers (including floating point and NaNs),
the runtime is about 50 seconds.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;alternate-solutions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Alternate solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A solution with &lt;code&gt;purrr&lt;/code&gt; - &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/2019/01/04/mathgenius.html&#34; class=&#34;uri&#34;&gt;http://staff.math.su.se/hoehle/blog/2019/01/04/mathgenius.html&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;I initially started down a similar route but found it became pretty clunky/slow&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A java solution on stackoverflow &lt;a href=&#34;https://stackoverflow.com/questions/21461084/how-to-find-the-exact-set-of-operations-for-a-specific-number/21463659#21463659&#34;&gt;here&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Haven’t looked because I don’t know enough java :)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle-recap-8-out-of-10-cats-does-countdown&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Puzzle Recap: 8 out of 10 cats does Countdown&lt;/h2&gt;
&lt;p&gt;The number puzzle segment of the show goes something like this:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;6 numbers are selected randomly&lt;/li&gt;
&lt;li&gt;A target number is displayed.&lt;/li&gt;
&lt;li&gt;Panellists must use basic arithmetic to produce the target number from some/all
of the 6 given numbers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below on the left is the setup for a typical puzzle, and on the right are some attempts by panellists at a solution, with a correct solution shown on the RHS of the whiteboard&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/left.jpg&#34; width=&#34;45%&#34; style=&#34;float: left;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/right.jpg&#34; width=&#34;45%&#34; style=&#34;float: right;&#34;&gt;&lt;/p&gt;
&lt;div style = &#34;clear: both;&#34;&gt;


&lt;p&gt;For this example problem the given numbers and target are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Given numbers: 50, 9, 4, 5, 9, 3&lt;/li&gt;
&lt;li&gt;Target: 952&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution on the RHS of the whiteboard is:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;((50 * 5) - 9 - 3) * 4&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 952&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assumptions that are never really stated, but all puzzles seem to adhere by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only using +, -, *, /&lt;/li&gt;
&lt;li&gt;Intermediate results are always integers&lt;/li&gt;
&lt;li&gt;Not necessary to use all the given numbers&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution #2&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Generate all possible expression trees&lt;/li&gt;
&lt;li&gt;Build up expressions from the leaves, doing simple evaluations at each node&lt;/li&gt;
&lt;li&gt;i.e. Never try and evaluate the full expression from scratch - always evaluate it
as a simple operation of the values returned in the subtrees.&lt;/li&gt;
&lt;li&gt;Uses memoisation to cache the results of subtrees so that similar subtrees are
only ever evaluated once.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate and evaluate all possible expressions from the given numbers
#
# @param nums vector of integers
# @param integer_only only generate integer solutions?  default: TRUE
# 
# @return list with 2 elements. &amp;#39;exprs&amp;#39; which is the character vector of all
#         possible expressions.  &amp;#39;values&amp;#39; which is the numeric vector of the
#         evaluation of each of those expressions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generate_exprs_ &amp;lt;- function(nums, integer_only = TRUE) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Recursive function termination condition - only 1 number given
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (length(nums) == 1L) {
    return(list(exprs = as.character(nums), values = nums))
  } 
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # For the given length of &amp;#39;nums&amp;#39;, what are all the possible ways
  # we could split these numbers into 2 groups?
  # See appendix for definition
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  splits &amp;lt;- all_splits[[length(nums)]]
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # This is where I&amp;#39;ll be storing the solutions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  exprs  &amp;lt;- character(0)
  values &amp;lt;- numeric(0)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Evaluate every possible combination of numbers for every possible 
  # arithmetic op.  For non-commutative operations, need to evaluate a second
  # time with arguments in reverse order
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (split in splits) {
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Generate all the possible subtrees from this node
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    lhs &amp;lt;- generate_exprs(nums[split[[1]]], integer_only) # use memoised version
    rhs &amp;lt;- generate_exprs(nums[split[[2]]], integer_only) # use memoised version
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Build the expression string for each possible combination of 
    # left and right expression subtrees
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    L &amp;lt;- rep(lhs$exprs, times = length(rhs$exprs))
    R &amp;lt;- rep(rhs$exprs, each  = length(lhs$exprs))
    exprs &amp;lt;- c(
      exprs,
      paste0(&amp;quot;(&amp;quot;, L, &amp;quot; - &amp;quot;, R, &amp;quot;)&amp;quot;),
      paste0(&amp;quot;(&amp;quot;, L, &amp;quot; / &amp;quot;, R, &amp;quot;)&amp;quot;),
      paste0(&amp;quot;(&amp;quot;, L, &amp;quot; + &amp;quot;, R, &amp;quot;)&amp;quot;),
      paste0(&amp;quot;(&amp;quot;, L, &amp;quot; * &amp;quot;, R, &amp;quot;)&amp;quot;),
      paste0(&amp;quot;(&amp;quot;, R, &amp;quot; - &amp;quot;, L, &amp;quot;)&amp;quot;),
      paste0(&amp;quot;(&amp;quot;, R, &amp;quot; / &amp;quot;, L, &amp;quot;)&amp;quot;)
    )
    
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Perform each possible operation on each possible combination of 
    # left and right value subtrees
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    L &amp;lt;- rep(lhs$values, times = length(rhs$values))
    R &amp;lt;- rep(rhs$values, each  = length(lhs$values))
    values&amp;lt;- c(
      values,
      L - R,
      L / R,
      L + R,
      L * R,
      R - L,
      R / L
    )
  }
  
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Filter solutions to only keep unique solutions.
  # Filter out non-integer solutions if requested.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (integer_only) {
    accept &amp;lt;- !duplicated(exprs) &amp;amp; is.finite(values) &amp;amp; values == round(values)
  } else {
    accept &amp;lt;- !duplicated(exprs)
  }
  
  list(exprs=exprs[accept], values=values[accept])
} 



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Memoise the generation of expressions for any list of numbers
# This eliminates having to ever calculate the expressions for the same list
# of numbers a second time.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generate_exprs &amp;lt;- memoise::memoise(generate_exprs_)



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Recursively generate all possible expressions for a set of numbers.
#
# For a given list of numbers, generate all expressions for these numbers
# and all possible sub-sets of these numbers. this way if nums = c(1, 3, 4)
# and target = 12, the solutions will include (1 * 3 * 4) as well as (3 * 4)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
generate_all_exprs &amp;lt;- function(nums, integer_only = TRUE) {
  
  exprs  &amp;lt;- character(0)
  values &amp;lt;- numeric(0)
  
  if (length(nums) == 1L)  {
    return(list(exprs = as.character(nums), values = nums))
  }
  
  nums &amp;lt;- sort(nums)
  
  # Solve the sub-problems
  for (i in seq_along(nums)) {
    this_res &amp;lt;- generate_all_exprs(nums[-i], integer_only)
    exprs    &amp;lt;- c(exprs , this_res$exprs )
    values   &amp;lt;- c(values, this_res$values)
  }
  
  # Solve this problem
  this_res &amp;lt;- generate_exprs(nums, integer_only)
  exprs    &amp;lt;- c(exprs , this_res$exprs )
  values   &amp;lt;- c(values, this_res$values)
  
  
  accept &amp;lt;- !duplicated(exprs)
  
  list(exprs = exprs[accept], values = values[accept])
}



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Solve the countown problem
#
# Generate all possible expressions with an integer result and then filter
# only for those which evaluate to the target number
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solve_countdown &amp;lt;- function(nums, target) {
  res &amp;lt;- generate_all_exprs(sort(nums), integer_only = TRUE)
  res$exprs[res$values == target]
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;generate_all_exprs(1:2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $exprs
## [1] &amp;quot;2&amp;quot;       &amp;quot;1&amp;quot;       &amp;quot;(1 - 2)&amp;quot; &amp;quot;(1 + 2)&amp;quot; &amp;quot;(1 * 2)&amp;quot; &amp;quot;(2 - 1)&amp;quot; &amp;quot;(2 / 1)&amp;quot;
## 
## $values
## [1]  2  1 -1  3  2  1  2&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;generate_all_exprs(1:2, integer_only = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $exprs
## [1] &amp;quot;2&amp;quot;       &amp;quot;1&amp;quot;       &amp;quot;(1 - 2)&amp;quot; &amp;quot;(1 / 2)&amp;quot; &amp;quot;(1 + 2)&amp;quot; &amp;quot;(1 * 2)&amp;quot; &amp;quot;(2 - 1)&amp;quot;
## [8] &amp;quot;(2 / 1)&amp;quot;
## 
## $values
## [1]  2.0  1.0 -1.0  0.5  3.0  2.0  1.0  2.0&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;system.time({
  nums   &amp;lt;- c(50, 9, 4, 5, 9, 3)
  target &amp;lt;- 952
  res    &amp;lt;- solve_countdown(nums, target)
})&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##    user  system elapsed 
##   6.800   0.401   7.218&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;system.time({
  target &amp;lt;- 404
  nums   &amp;lt;- c(1, 1, 1, 1, 1, 100)
  res    &amp;lt;- solve_countdown(nums, target)
})&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##    user  system elapsed 
##   1.204   0.120   1.346&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;((1 + 1) * ((1 + 1) * (1 + 100)))&amp;quot; &amp;quot;((1 + 1) * ((1 + 100) * (1 + 1)))&amp;quot;
## [3] &amp;quot;((1 + 100) * (1 + (1 + (1 + 1))))&amp;quot; &amp;quot;((1 + 100) * ((1 + 1) + (1 + 1)))&amp;quot;
## [5] &amp;quot;((1 + 100) * ((1 + 1) * (1 + 1)))&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Can generate all possible simple arithmetic expressions for 6 numbers in around ~10 seconds (if we limit the results such that must be an integer).&lt;/li&gt;
&lt;li&gt;If we allow all floating point and NA/Inf expressions, then full generation of all arithmetic expressions for 6 numbers
takes about &amp;lt; 1 minute.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&#34;all_splits&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;all_splits&lt;/code&gt;&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Split &amp;#39;n&amp;#39; indices into all possible 2 group combinations 
# with &amp;#39;ngroup&amp;#39; numbers in the first group
#
# @param n maximum index. 
# @param ngroup number of indices in the first group
# @return list of lists. each innermost list has 2 vectors of disjoint indicies
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
split_sets &amp;lt;- function(n, by) {
  mat &amp;lt;- combn(seq(n), by)
  if (by == n/2) {
    mat &amp;lt;- mat[, seq(ncol(mat)/2), drop = FALSE]
  }
  
  res &amp;lt;- apply(mat, 2, list)
  res &amp;lt;- lapply(res, function(x) {list(x[[1]], setdiff(seq(n), x[[1]]))})
  res
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate all possible split sets for the given n
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
all_split_sets &amp;lt;- function(n) {
  nn &amp;lt;- n - 1
  nn &amp;lt;- min(floor(n/2), n-1)
  seq(nn) %&amp;gt;% 
    purrr::map(~split_sets(n, by = .x)) %&amp;gt;%
    unlist(recursive = FALSE)
}


all_splits &amp;lt;- 1:6 %&amp;gt;% purrr::map(all_split_sets)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>8 out of 10 cats does countdown</title>
      <link>https://coolbutuseless.github.io/2019/02/04/8-out-of-10-cats-does-countdown/</link>
      <pubDate>Mon, 04 Feb 2019 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/02/04/8-out-of-10-cats-does-countdown/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;out-of-10-cats-does-countdown&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;8 out of 10 cats does Countdown&lt;/h2&gt;
&lt;p&gt;“8 out of 10 cats does Countdown” is a UK panel comedy show in which they play
games with words and numbers while also telling rude jokes and generally
mucking about. It’s an adults-only version of the much more sedate “Countdown” show.&lt;/p&gt;
&lt;video width=&#34;48%&#34; loop style=&#34;float: left;&#34; autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/hula.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;video width=&#34;45%&#34; loop style=&#34;float: right;&#34; autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/jimmy.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;div style = &#34;clear: both;&#34;&gt;

&lt;/div&gt;
&lt;div id=&#34;the-countdown-number-puzzle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The ‘Countdown’ number puzzle&lt;/h2&gt;
&lt;p&gt;The number puzzle segment of the show goes something like this:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;6 numbers are selected randomly&lt;/li&gt;
&lt;li&gt;A target number is displayed.&lt;/li&gt;
&lt;li&gt;Panellists must use basic arithmetic to produce the target number from some/all
of the 6 given numbers&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below on the left is the setup for a typical puzzle, and on the right are some attempts by panellists at a solution, with a correct solution shown on the RHS of the whiteboard&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/left.jpg&#34; width=&#34;45%&#34; style=&#34;float: left;&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/right.jpg&#34; width=&#34;45%&#34; style=&#34;float: right;&#34;&gt;&lt;/p&gt;
&lt;div style = &#34;clear: both;&#34;&gt;


&lt;p&gt;For this example problem the given numbers and target are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Given numbers: 50, 9, 4, 5, 9, 3&lt;/li&gt;
&lt;li&gt;Target: 952&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution on the RHS of the whiteboard is:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;((50 * 5) - 9 - 3) * 4&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 952&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assumptions that are never really stated, but all puzzles seem to adhere by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only using +, -, *, /&lt;/li&gt;
&lt;li&gt;Intermediate results are always integers&lt;/li&gt;
&lt;li&gt;Not necessary to use all the given numbers&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;finding-all-solutions-by-recursive-backtracking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Finding all solutions by recursive backtracking&lt;/h2&gt;
&lt;p&gt;My solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build every possible expression by nesting from right-to-left/inner-to-outer sub-expressions&lt;/li&gt;
&lt;li&gt;Abandon the expression early if it ever evaluates to a result that is not an integer&lt;/li&gt;
&lt;li&gt;Takes ~5 seconds to find all solutions to a puzzle from Countdown&lt;/li&gt;
&lt;li&gt;The code is &lt;a href=&#34;https://gist.github.com/coolbutuseless/3f4e8a2181b6d18a5e823b3449f84999&#34;&gt;on github&lt;/a&gt; if
you felt like having a go.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Inner recursive routine for solving Countdown numbers puzzle
#&amp;#39;
#&amp;#39; @param nums What numbers are left to select from?
#&amp;#39; @param value the current calculated value
#&amp;#39; @param expr the current readable expression
#&amp;#39; @param verbose output solutions as they are found? default: FALSE
#&amp;#39;
#&amp;#39; @return Character vector of solutions if any are found, otherwise NULL
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solve_inner &amp;lt;- function(nums, value, expr = value, target, verbose = FALSE) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Recursion termination conditions:
  #  1 -  Target number has been achieved
  #  2 -  Target number not achieved, and no more numbers to use
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (value == target) {
    if (verbose) {
      cat(expr, &amp;quot;\n&amp;quot;)
    }
    return(expr)
  } else if (length(nums) == 0L) {
    return()
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # &amp;#39;all_res&amp;#39; will accumulate all solutions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  all_res &amp;lt;- c()
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Generate all possible arithmetic expressions from the current state
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  for (op in c(&amp;#39;+&amp;#39;, &amp;#39;-&amp;#39;, &amp;#39;*&amp;#39;, &amp;#39;/&amp;#39;)) {
    for(num_idx in seq_along(nums)) {
      
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # Evaluate expression, and if it&amp;#39;s still an integer result, then recurse
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      new_value &amp;lt;- switch(
        op,
        &amp;#39;+&amp;#39; = nums[num_idx] + value,
        &amp;#39;-&amp;#39; = nums[num_idx] - value,
        &amp;#39;*&amp;#39; = nums[num_idx] * value,
        &amp;#39;/&amp;#39; = ifelse(nums[num_idx] %% value == 0L, nums[num_idx] %/% value, NA_integer_)
      )
      
      if (!is.na(new_value)) {
        res &amp;lt;- solve_inner(
          nums    = nums[-num_idx], 
          value   = new_value, 
          expr    = paste(&amp;quot;(&amp;quot;, nums[num_idx], &amp;#39; &amp;#39;, op, &amp;#39; &amp;#39;, expr, &amp;quot;)&amp;quot;, sep = &amp;#39;&amp;#39;),
          target  = target,
          verbose = verbose
        )
        if (!is.null(res)) { all_res &amp;lt;- c(all_res, res) }
      }    
      
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # For non-commutative operations, also recurse with arguments swapped
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (op %in% c(&amp;#39;-&amp;#39;, &amp;#39;/&amp;#39;)) {
        new_value &amp;lt;- switch(
          op,
          &amp;#39;-&amp;#39; = value - nums[num_idx],
          &amp;#39;/&amp;#39; = ifelse(value &amp;amp;&amp;amp; nums[num_idx] == 0L, value %/% nums[num_idx], NA_integer_)
        )
        
        if (!is.na(new_value)) {
          res &amp;lt;- solve_inner(
            nums    = nums[-num_idx], 
            value   = new_value, 
            expr    = paste(&amp;quot;(&amp;quot;, expr, &amp;#39; &amp;#39;, op, &amp;#39; &amp;#39;, nums[num_idx], &amp;quot;)&amp;quot;, sep = &amp;#39;&amp;#39;),
            target  = target,
            verbose = verbose
          )
          if (!is.null(res)) { all_res &amp;lt;- c(all_res, res) }
        }    
      }
    } # num_idx loop
  }   # op loop
  
  all_res 
}




#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Solve the countdown numbers puzzle for the given set of numbers and target
#&amp;#39;
#&amp;#39; @param nums integer vector
#&amp;#39; @param target target number (integer)
#&amp;#39; @param verbose output solutions as they are found? default: FALSE
#&amp;#39;
#&amp;#39; @return Character vector of solutions if any are found, otherwise NULL
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solve_countdown &amp;lt;- function(nums, target, verbose = FALSE) {
  nums   &amp;lt;- as.integer(nums)
  target &amp;lt;- as.integer(target)
  seq_along(nums) %&amp;gt;% 
    purrr::map(~solve_inner(nums[-.x], value = nums[.x], target = target, verbose = verbose)) %&amp;gt;%
    purrr::flatten_chr() %&amp;gt;%
    unique()
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;a-small-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A small example&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;nums   &amp;lt;- c(2, 3, 4, 5)
target &amp;lt;- 11 
solve_countdown(nums, target)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;(5 + (4 + 2))&amp;quot;       &amp;quot;(4 + (5 + 2))&amp;quot;       &amp;quot;(5 + (3 * (4 - 2)))&amp;quot;
##  [4] &amp;quot;(5 - (3 * (2 - 4)))&amp;quot; &amp;quot;(5 + (3 * 2))&amp;quot;       &amp;quot;(3 + (4 * 2))&amp;quot;      
##  [7] &amp;quot;((4 + (5 * 2)) - 3)&amp;quot; &amp;quot;(4 - (3 - (5 * 2)))&amp;quot; &amp;quot;(4 + ((5 * 2) - 3))&amp;quot;
## [10] &amp;quot;(5 + (3 * (4 / 2)))&amp;quot; &amp;quot;(5 + (2 * 3))&amp;quot;       &amp;quot;((5 * 3) - 4)&amp;quot;      
## [13] &amp;quot;(5 + (2 + 4))&amp;quot;       &amp;quot;(2 + (5 + 4))&amp;quot;       &amp;quot;(3 + (2 * 4))&amp;quot;      
## [16] &amp;quot;(4 + (2 + 5))&amp;quot;       &amp;quot;(2 + (4 + 5))&amp;quot;       &amp;quot;((4 + (2 * 5)) - 3)&amp;quot;
## [19] &amp;quot;(4 - (3 - (2 * 5)))&amp;quot; &amp;quot;(4 + ((2 * 5) - 3))&amp;quot; &amp;quot;((3 * 5) - 4)&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;an-example-from-the-show&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;An example from the show&lt;/h2&gt;
&lt;p&gt;This is the example from the show at the top of this post. The second solution in
the results matches the answer given on the show.&lt;/p&gt;
&lt;p&gt;Finding all solutions takes about 5 seconds on my machine.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;nums   &amp;lt;- c(50, 9, 4, 5, 9, 3)
target &amp;lt;- 952 
solve_countdown(nums, target)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;((5 * ((4 * 50) - 9)) - 3)&amp;quot;       &amp;quot;(4 * (((5 * 50) - 9) - 3))&amp;quot;      
##  [3] &amp;quot;(((4 * ((5 * 50) - 9)) - 9) - 3)&amp;quot; &amp;quot;(((4 * ((5 * 50) - 9)) - 3) - 9)&amp;quot;
##  [5] &amp;quot;(4 * (((5 * 50) - 3) - 9))&amp;quot;       &amp;quot;(4 * ((3 * (9 * 9)) - 5))&amp;quot;       
##  [7] &amp;quot;(4 * ((9 * (5 + (3 * 9))) - 50))&amp;quot; &amp;quot;(4 * ((9 * (3 * 9)) - 5))&amp;quot;       
##  [9] &amp;quot;((5 * ((50 * 4) - 9)) - 3)&amp;quot;       &amp;quot;(4 * (((50 * 5) - 9) - 3))&amp;quot;      
## [11] &amp;quot;(((4 * ((50 * 5) - 9)) - 9) - 3)&amp;quot; &amp;quot;(((4 * ((50 * 5) - 9)) - 3) - 9)&amp;quot;
## [13] &amp;quot;(4 * (((50 * 5) - 3) - 9))&amp;quot;       &amp;quot;(4 * ((9 * (5 + (9 * 3))) - 50))&amp;quot;
## [15] &amp;quot;(4 * ((9 * (9 * 3)) - 5))&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;an-impossible-puzzle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;An impossible puzzle&lt;/h2&gt;
&lt;p&gt;Sometimes the target number is impossible to achieve&lt;/p&gt;
&lt;video width=&#34;45%&#34; loop autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/impossible.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;div style = &#34;clear: both;&#34;&gt;



&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;solve_countdown(c(50, 2, 6, 5, 1, 5), 959)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;## character(0)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Could easily adapt to find:
&lt;ul&gt;
&lt;li&gt;closest result to given target if no exact result exists&lt;/li&gt;
&lt;li&gt;results within some threshold distance of the target&lt;/li&gt;
&lt;li&gt;include fractional intermediate results&lt;/li&gt;
&lt;li&gt;non-integer targets and given numbers&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Code is &lt;a href=&#34;https://gist.github.com/coolbutuseless/3f4e8a2181b6d18a5e823b3449f84999&#34;&gt;on github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ideas for speeding this up are welcomed.&lt;/li&gt;
&lt;li&gt;Alternate solution techniques are extremely welcomed! e.g.
&lt;ul&gt;
&lt;li&gt;Is this type of program solvable via &lt;a href=&#34;https://dirkschumacher.github.io/ompr/&#34;&gt;ompr&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;Could you just generate all possible expressions as strings in one go, and then evaluate them all?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;video width=&#34;45%&#34; loop autoplay&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/8-out-of-10-cats/clapping.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Interleaving vectors and matrices - part 3</title>
      <link>https://coolbutuseless.github.io/2019/01/31/interleaving-vectors-and-matrices-part-3/</link>
      <pubDate>Thu, 31 Jan 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/01/31/interleaving-vectors-and-matrices-part-3/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Yesterday’s request for help got some great replies on twitter. I’ve collected them in this
post and benchmarked them.&lt;/p&gt;
&lt;p&gt;No one (besides myself) had the sheer audacity to inflict a &lt;code&gt;for&lt;/code&gt; loop upon the world.&lt;/p&gt;
&lt;p&gt;Huge thanks to the following people for their ideas! (in order of appearance)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/_StuartLee&#34;&gt;Stuart Lee&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/groundwalkergmb&#34;&gt;Gabe Becker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/kara_woo&#34;&gt;Kara Woo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/mdsumner&#34;&gt;Michael Sumner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/CookieSci&#34;&gt;Jake Westfall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;Brodie Gaslam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/knapply_&#34;&gt;Brendan Knapp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/alistaire&#34;&gt;Edward Visel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/davidmasp&#34;&gt;David Mas-Ponte&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;interleaving-a-row-vector-with-a-matrix-of-the-same-width&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interleaving a row-vector with a matrix of the same width&lt;/h2&gt;
&lt;p&gt;I have a vector a row-vector and matrix of equal width&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vec &amp;lt;- c(101, 102, 103)
mat &amp;lt;- matrix(c( 1,  2,  3,
                 4,  5,  6,
                 7,  8,  9,
                10, 11, 12), nrow = 4, byrow = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Expected output after interleaving by column&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;my-solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My solution&lt;/h2&gt;
&lt;p&gt;This was my initial solution. I was concerned about whether the &lt;code&gt;for&lt;/code&gt; loop
could be done away with.&lt;/p&gt;
&lt;p&gt;I did try a couple of solutions with an explicit &lt;code&gt;rep()&lt;/code&gt; to try and avoid the &lt;code&gt;for&lt;/code&gt;
loop, but found the overhead of the extra memory allocation slowed things down.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Interleave a matrix and a row-vector of the same width
#&amp;#39;
#&amp;#39;  * Create an empty matrix of double the width
#&amp;#39;  * Copy over the given matrix
#&amp;#39;  * Copy over the vector (using a for loop. quelle horreur!)
#&amp;#39;
#&amp;#39; @param m NxM matrix
#&amp;#39; @param v vector of length M
#&amp;#39;
#&amp;#39; @return N x M*2 matrix
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
interleave_coolbutuseless &amp;lt;- function(mat, vec) {
  res &amp;lt;- matrix(0, ncol = 2L * ncol(mat), nrow = nrow(mat))
  res[,c(T, F)] &amp;lt;- mat
  for (i in seq_along(vec)) {
    res[,2L * i] &amp;lt;- vec[i]
  }
  
  res
}

interleave_coolbutuseless(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-stuart-lee&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/_StuartLee&#34;&gt;Stuart Lee&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_stuartlee &amp;lt;- function(mat, vec) { 
  res &amp;lt;- matrix(0, ncol = 2L * ncol(mat), nrow = nrow(mat)) 
  res[, c(TRUE, FALSE)] &amp;lt;- mat 
  res[, c(FALSE, TRUE)] &amp;lt;- sort(rep(vec, nrow(mat))) 
  res 
}

interleave_stuartlee(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-gabe-becker&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/groundwalkergmb&#34;&gt;Gabe Becker&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_groundwalkgmb &amp;lt;- function(mat, vec) {
  vm       &amp;lt;- matrix(rep(vec, nrow(mat)), ncol = ncol(mat), byrow=TRUE) 
  res      &amp;lt;- rbind(mat, vm) 
  dim(res) &amp;lt;- c(nrow(mat), 2L * ncol(mat))
  res
}

interleave_groundwalkgmb(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solutions-by-kara-woo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solutions by &lt;a href=&#34;https://twitter.com/kara_woo&#34;&gt;Kara Woo&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_kara_woo_1 &amp;lt;- function(mat, vec) { 
  t(apply(mat, 1, function(x) unlist(purrr::map2(x, vec, c)))) 
}

interleave_kara_woo_1(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_kara_woo_2 &amp;lt;- function(mat, vec) { 
  t(apply(mat, 1, function(x) unlist(mapply(c, x, vec)))) 
}

interleave_kara_woo_2(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-michael-sumner&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/mdsumner&#34;&gt;Michael Sumner&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_mdsumner &amp;lt;- function(mat, vec) {
  matrix(
    rbind(
      mat, 
      matrix(rep(vec, each = nrow(mat)), ncol = ncol(mat))
    ), 
    nrow = nrow(mat)
  )
}

interleave_mdsumner(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-jake-westfall&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/CookieSci&#34;&gt;Jake Westfall&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_CookieSci &amp;lt;- function(mat, vec) {
  Reduce(cbind, vec, mat)[,c(rbind(seq(vec), seq(vec)+length(vec)))]
}

interleave_CookieSci(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-brodie-gaslam&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/BrodieGaslam&#34;&gt;Brodie Gaslam&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_BrodieGaslam &amp;lt;- function(mat, vec) {
  matrix( aperm( array(c(mat, rep(vec, each=nrow(mat))), dim=c(dim(mat), 2)), c(1, 3, 2) ), nrow(mat) )
}

interleave_BrodieGaslam(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-brendan-knapp&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/knapply_&#34;&gt;Brendan Knapp&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_knapply &amp;lt;- function(mat, vec) { 
  matrix(rbind(mat, matrix(vec, nrow = nrow(mat), ncol = ncol(mat), byrow = TRUE)), nrow = nrow(mat)) 
}

interleave_knapply(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solutions-by-edward-visel&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solutions by &lt;a href=&#34;https://twitter.com/alistaire&#34;&gt;Edward Visel&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_alistaire_1 &amp;lt;- function(mat, vec) { 
  res &amp;lt;- array(dim = dim(mat) * 1:2)
  abind::afill(res, T, c(T, F)) &amp;lt;- mat
  abind::afill(res, T, c(F, T)) &amp;lt;- t(array(vec, rev(dim(mat))))
  
  res
}

interleave_alistaire_1(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_alistaire_2 &amp;lt;- function(mat, vec) { 
  res &amp;lt;- array(dim = dim(mat) * 1:2)
  res[, c(T, F)] &amp;lt;- mat
  res[, c(F, T)] &amp;lt;- t(array(vec, rev(dim(mat))))
  
  res
}

interleave_alistaire_2(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-by-david-mas-ponte&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution by &lt;a href=&#34;https://twitter.com/davidmasp&#34;&gt;David Mas-Ponte&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave_davidmaasp &amp;lt;- function(mat, vec) { 
  new_idx         &amp;lt;- (1:ncol(mat)*2)-1 
  inter_idx       &amp;lt;- (1:ncol(mat)*2) 
  res             &amp;lt;- matrix(0, ncol = 2L * ncol(mat), nrow = nrow(mat))
  res[,new_idx]   &amp;lt;- mat
  res[,inter_idx] &amp;lt;- matrix(rep(vec, nrow(mat)), byrow=TRUE, ncol=length(vec)) 
  res 
}


interleave_davidmaasp(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103
[4,]   10  101   11  102   12  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmarking&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Benchmarking&lt;/h1&gt;
&lt;p&gt;I’m only benchmarking for my my target problem size, but changing the dimensions of the
initial matrix and vector changes the benchmarking results. Buyer beware!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 1000
M &amp;lt;- 10
mat &amp;lt;- matrix(seq(M*N), nrow = N, ncol = M)
vec &amp;lt;- seq(M) + 100


res &amp;lt;- bench::mark(
  interleave_coolbutuseless(mat, vec),
  interleave_stuartlee(mat, vec), #
  interleave_groundwalkgmb(mat, vec),# 
  interleave_kara_woo_1(mat, vec),
  interleave_kara_woo_2(mat, vec),
  interleave_mdsumner(mat, vec), 
  interleave_CookieSci(mat, vec),
  interleave_BrodieGaslam(mat, vec),
  interleave_knapply(mat, vec),
  interleave_alistaire_1(mat, vec),
  interleave_alistaire_2(mat, vec),
  interleave_davidmaasp(mat, vec),
  
  check = TRUE
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-17&#34;&gt;Table 1: &lt;/span&gt;Benchmarking results&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_coolbutuseless(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;134.49µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5502&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;199.78KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_stuartlee(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;532.61µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1604&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;394.38KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_groundwalkgmb(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;237.49µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3288&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;348.19KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_kara_woo_1(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;127.77ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;757.59KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_kara_woo_2(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;37.27ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;946.52KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_mdsumner(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;496.8µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1639&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;484.12KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_CookieSci(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;831.47µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;922&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.39MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_BrodieGaslam(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;689.41µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1070&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;725.27KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_knapply(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;258.12µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3060&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;406.51KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_alistaire_1(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.94ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;186&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;767.38KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_alistaire_2(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;321.57µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2372&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;516.99KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;interleave_davidmaasp(mat, vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225.02µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3472&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;320.55KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;Loading required namespace: tidyr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-31-interleaving-vectors-and-matrices-3_files/figure-html/unnamed-chunk-17-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;and-the-winner-is&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;And the winner is …&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There’s not that much speed difference between the fastest methods.&lt;/li&gt;
&lt;li&gt;Across a wider variety of benchmarks than I’ve shown here, Gabe Becker’s solution was often fastest.&lt;/li&gt;
&lt;li&gt;My &lt;code&gt;for&lt;/code&gt; loop method is on par with others for my target dimensions
(and has the added bonus of lowest memory allocatiions).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Interleaving vectors and matrices - part 2</title>
      <link>https://coolbutuseless.github.io/2019/01/30/interleaving-vectors-and-matrices-part-2/</link>
      <pubDate>Wed, 30 Jan 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/01/30/interleaving-vectors-and-matrices-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;I’m looking for a better, neater, more R-like solution to this - please &lt;a href=&#34;https://twitter.com/coolbutuseless&#34;&gt;hit me up on twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the moment, I can’t even include a benchmark screenshot as I only have just the one idea on how to do this!&lt;/p&gt;
&lt;div id=&#34;interleaving-a-vector-with-a-matrix-of-the-same-width&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interleaving a vector with a matrix of the same width&lt;/h2&gt;
&lt;p&gt;I have a vector a row-vector and matrix of equal width&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vec &amp;lt;- c(101, 102, 103)
mat &amp;lt;- matrix(c(1, 2, 3,
                4, 5, 6,
                7, 8, 9), nrow = 3, byrow = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Expected output after interleaving by column&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;my-solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My solution&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Interleave a matrix and a row-vector of the same width
#&amp;#39;
#&amp;#39;  * Create an empty matrix of double the width
#&amp;#39;  * Copy over the given matrix
#&amp;#39;  * Copy over the vector (using a for loop. quelle horreur!)
#&amp;#39;
#&amp;#39; @param m NxM matrix
#&amp;#39; @param v vector of length M
#&amp;#39;
#&amp;#39; @return N x M*2 matrix
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
interleave &amp;lt;- function(m, v) {
  res &amp;lt;- matrix(0, ncol = 2L * ncol(m), nrow = nrow(m))
  res[,c(T, F)] &amp;lt;- m
  for (i in seq_along(v)) {
    res[,2L * i] &amp;lt;- v[i]
  }
  
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;interleave(mat, vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1  101    2  102    3  103
[2,]    4  101    5  102    6  103
[3,]    7  101    8  102    9  103&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Summary&lt;/h1&gt;
&lt;p&gt;Anyone have any better ideas?&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Interleaving vectors and matrices (part 1)</title>
      <link>https://coolbutuseless.github.io/2019/01/29/interleaving-vectors-and-matrices-part-1/</link>
      <pubDate>Tue, 29 Jan 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/01/29/interleaving-vectors-and-matrices-part-1/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;interleaving-2-vectors---simplest-solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interleaving 2 vectors - simplest solution&lt;/h2&gt;
&lt;p&gt;I have 2 vectors of equal length that I want to interleave&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First input: 1, 2, 3&lt;/li&gt;
&lt;li&gt;Second input: 4, 5, 6&lt;/li&gt;
&lt;li&gt;Desired output: 1, 4, 2, 5, 3, 6&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The simplest base R solution is to &lt;code&gt;rbind()&lt;/code&gt; the 2 inputs and then unravel the matrix.&lt;/p&gt;
&lt;p&gt;And when I say “simplest” solution, I mean “thing that is shortest but totally non-obvious”.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;v1 &amp;lt;- c(1L, 2L, 3L)
v2 &amp;lt;- c(4L, 5L, 6L)

c(rbind(v1, v2))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1 4 2 5 3 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;interleaving-2-vectors---faster-solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Interleaving 2 vectors - faster solution&lt;/h2&gt;
&lt;p&gt;Both &lt;code&gt;rbind&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; copy the data, and copying takes time.&lt;/p&gt;
&lt;p&gt;Rather than using &lt;code&gt;c()&lt;/code&gt; to turn the matrix into a vector, you could also just
unset the &lt;code&gt;dim&lt;/code&gt; attribute on the matrix. This will give the same result, but
avoid doing any memory allocation associated with the &lt;code&gt;c&lt;/code&gt; call.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- rbind(v1, v2)
attributes(res) &amp;lt;- NULL
res&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1 4 2 5 3 6&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Large-ish example
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
v1 &amp;lt;- v2 &amp;lt;- integer(10000)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Benchmark
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bench_res &amp;lt;- bench::mark(
  c(rbind(v1, v2)),
  `remove dims` = {
    res &amp;lt;- rbind(v1, v2)
    attributes(res) &amp;lt;- NULL
    res
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-4&#34;&gt;Table 1: &lt;/span&gt;bench::mark() comparing interleaving methods. Removing attributes saves on memory allocation and is therefore much faster than &lt;code&gt;c()&lt;/code&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;c(rbind(v1, v2))&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;129.2µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7523.19&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;156.3KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;{&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;res &amp;lt;- rbind(v1, v2)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;attributes(res) &amp;lt;- NULL&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;res&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;} 51.8µs 18293.02 78.2KB&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;Loading required namespace: tidyr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-29-interleaving-vectors-and-matrices-1_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Don’t write a for loop to interleave two vectors of equal length.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Puzzle Solving: Dominosa</title>
      <link>https://coolbutuseless.github.io/2019/01/28/puzzle-solving-dominosa/</link>
      <pubDate>Mon, 28 Jan 2019 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2019/01/28/puzzle-solving-dominosa/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;puzzle-solving---dominosa&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Puzzle solving - Dominosa&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Dominosa&lt;/strong&gt; is a game/puzzle from &lt;a href=&#34;https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/dominosa.html&#34;&gt;Simon Tathams’ Portable Puzzle Collection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Dominosa&lt;/em&gt; there is a complete set of dominoes up to a certain number (A
classic domino set goes from &lt;code&gt;0, 0&lt;/code&gt; up to &lt;code&gt;6, 6&lt;/code&gt;). The &lt;strong&gt;initial board&lt;/strong&gt; represents
the dominoes laid out in a grid - we have the numbers, but not the outline of the dominos.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;aim&lt;/strong&gt; of the puzzle is to determine the locations/orientations of all the dominos so that every possible
domino appears exactly once.&lt;/p&gt;
&lt;p&gt;In the images below, the left-hand image is the beginning puzzle board,
the right-hand image is the solution. (Note: For this example, I’m using a smaller board which
only includes all dominos from &lt;code&gt;0, 0&lt;/code&gt; up to &lt;code&gt;3, 3&lt;/code&gt;)&lt;/p&gt;
&lt;div&gt;
&lt;div style=&#34;float: left ; font-weight:bold;&#34;&gt;
Puzzle Grid
&lt;/div&gt;
&lt;div style=&#34;float: right; font-weight:bold;&#34;&gt;
Solution (i.e. domino placement)
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;clear: both;&#34;&gt;

&lt;/div&gt;
&lt;p&gt;&lt;img src = &#34;/img/dominosa/grid.png&#34;     widt
h = &#34;40%&#34; style=&#34;float: left;&#34;&gt;
&lt;img src = &#34;/img/dominosa/solution.png&#34; width = &#34;40%&#34; style=&#34;float: right;&#34;&gt;&lt;/p&gt;
&lt;div style = &#34;clear: both;&#34; /&gt;

&lt;p&gt;As can be seen in the solution there are 10 distinct tiles in the solution.
These span from &lt;code&gt;0, 0&lt;/code&gt; up to &lt;code&gt;3, 3&lt;/code&gt; with each tile only appearing once.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;representation-of-puzzle-and-solution-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Representation of puzzle and solution in R&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The puzzle grid&lt;/strong&gt; will be represented by a matrix the same dimensions as the grid.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid &amp;lt;- matrix(as.integer(c(
  3, 2, 2, 1, 1, 
  0, 3, 0, 2, 2,
  0, 3, 2, 1, 3, 
  1, 0, 1, 0, 3
)), byrow = TRUE, nrow = 4)

grid&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5]
[1,]    3    2    2    1    1
[2,]    0    3    0    2    2
[3,]    0    3    2    1    3
[4,]    1    0    1    0    3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_dominosa_plot(grid)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution&lt;/strong&gt; will be represented as a matrix with the following structure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An integer matrix of size N x 3. Where N = number of dominoes in puzzle.&lt;/li&gt;
&lt;li&gt;Each row represents one domino&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;rowname&lt;/code&gt; of a row is the pair of numbers on this domino (in sorted order)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;row&lt;/code&gt; and &lt;code&gt;col&lt;/code&gt; are the starting location for the domino (i.e. the upper-left-most position of the domino)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;direction&lt;/code&gt; indicates whether the domino is horizontal (&lt;code&gt;direction = 0&lt;/code&gt;) or vertical (&lt;code&gt;direction = 1&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution to the example problem is shown below.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sol&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;   row col direction
00   2   1         1
01   4   1         0
02   1   3         1
03   4   4         0
11   1   4         0
12   3   3         1
13   3   4         0
22   2   4         0
23   1   1         0
33   2   2         1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_dominosa_plot(grid, sol)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solver&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solver&lt;/h2&gt;
&lt;p&gt;The solver is implemented via recursion with backtracking. &lt;code&gt;NA&lt;/code&gt; is used to mark
grid locations which are already part of a potential solution, and are also used to
mark out-of-bounds areas (off the edge of the initial grid).&lt;/p&gt;
&lt;p&gt;At every location try and place a tile both horizontally and vertically. If both
of the grid locations are &lt;em&gt;not&lt;/em&gt; &lt;code&gt;NA&lt;/code&gt; then place a tile, add it to the solution and
recurse to the next level.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Recursive solver with backtracking
#&amp;#39;
#&amp;#39; @param grid grid of numbers. NA indicates out-of-bounds or that location is already
#&amp;#39;             part of the solution.
#&amp;#39; @param row current row
#&amp;#39; @param col current col
#&amp;#39; @param sol current solutuion. Nx3 matrix.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solve_dominosa_core &amp;lt;- function(grid, row = 1L, col = 1L, sol = NULL) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If the entire matrix &amp;#39;grid&amp;#39; is NA, then all positions are consumed into 
  # dominoes, and we have a solution!  Return in sorted order.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (all(is.na(grid))) {
    sol &amp;lt;- sol[order(rownames(sol)),]
    return(sol)
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If we&amp;#39;re off the end of a row, then jump to the start of the next row
  # If we&amp;#39;re off the bottom of &amp;#39;grid&amp;#39;, then we&amp;#39;re out of bounds without a solution
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (col &amp;gt; ncol(grid) - 1L) {col &amp;lt;- 1L;  row &amp;lt;- row + 1L}
  if (row &amp;gt; nrow(grid) - 1L) {stop(&amp;quot;Out of bounds. No solution found&amp;quot;)}
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If the current position is NA, then it has already been consumed into a 
  # domino, so just jump over to the next one
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (is.na(grid[row, col])) {
    res &amp;lt;- solve_dominosa_core(grid, row, col + 1L, sol)
    return(res)
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Next tile oriented horizontally
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pair      &amp;lt;- grid[row, col + 0:1]
  pair_name &amp;lt;- paste(sort(pair), collapse = &amp;#39;&amp;#39;)
  if (all(!is.na(pair)) &amp;amp;&amp;amp; !pair_name %in% rownames(sol)) {
    # Add the current location+direction to the solution matrix
    this_sol &amp;lt;- matrix(c(row, col, 0L), nrow = 1L)
    rownames(this_sol) &amp;lt;- pair_name
    next_sol &amp;lt;- rbind(sol, this_sol)
    
    # Set the current location+direction in the grid to NA
    next_grid   &amp;lt;- grid
    next_grid[row, col + 0:1] &amp;lt;- NA
    
    # keep solving
    res &amp;lt;- solve_dominosa_core(next_grid, row, col + 2L, next_sol)
    if (!is.null(res)) { return(res) }
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Next tile oriented vertically
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pair      &amp;lt;- grid[row + 0:1, col]
  pair_name &amp;lt;- paste(sort(pair), collapse = &amp;#39;&amp;#39;)
  if (all(!is.na(pair)) &amp;amp;&amp;amp; !pair_name %in% rownames(sol)) {
    # Add the current location+direction to the solution matrix
    this_sol  &amp;lt;- matrix(c(row, col, 1L), nrow = 1L)
    rownames(this_sol) &amp;lt;- pair_name
    next_sol &amp;lt;- rbind(sol, this_sol)
    
    # Set the current location+direction in the grid to NA
    next_grid &amp;lt;- grid
    next_grid[row + 0:1, col] &amp;lt;- NA
    
    # keep solving
    res &amp;lt;- solve_dominosa_core(next_grid, row, col + 1L, next_sol)
    if (!is.null(res)) { return(res) }
  }
}



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Solve the given dominosa grid
#&amp;#39;
#&amp;#39; @param grid grid of numbers
#&amp;#39; 
#&amp;#39; @return solution matrix (with rownames)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
solve_dominosa &amp;lt;- function(grid) {
  
  # Add border around grid so that I don&amp;#39;t have to do as much bounds checking
  grid &amp;lt;- rbind(cbind(grid, NA), NA)
  res  &amp;lt;- solve_dominosa_core(grid)
  
  if (!is.null(res)) {
    colnames(res) &amp;lt;- c(&amp;#39;row&amp;#39;, &amp;#39;col&amp;#39;, &amp;#39;direction&amp;#39;)
  }
  
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;small-puzzle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Small Puzzle&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5]
[1,]    3    2    2    1    1
[2,]    0    3    0    2    2
[3,]    0    3    2    1    3
[4,]    1    0    1    0    3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_dominosa_plot(grid)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sol &amp;lt;- solve_dominosa(grid)
sol&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;   row col direction
00   2   1         1
01   4   1         0
02   1   3         1
03   4   4         0
11   1   4         0
12   3   3         1
13   3   4         0
22   2   4         0
23   1   1         0
33   2   2         1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_dominosa_plot(grid, sol)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-6-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;larger-puzzle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Larger Puzzle&lt;/h2&gt;
&lt;p&gt;Testing the solver works on a &lt;a href=&#34;https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/dominosa.html#6:51663500166636421341312305221441054342200453065053214256&#34;&gt;larger puzzle&lt;/a&gt; [clink the link to view an interactive version of the puzzle at Simon Tatham’s puzzle page]&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grid &amp;lt;- matrix(c(
  5, 1, 6, 6, 3, 5, 0, 0,
  1, 6, 6, 6, 3, 6, 4, 2,
  1, 3, 4, 1, 3, 1, 2, 3, 
  0, 5, 2, 2, 1, 4, 4, 1,
  0, 5, 4, 3, 4, 2, 2, 0, 
  0, 4, 5, 3, 0, 6, 5, 0,
  5, 3, 2, 1, 4, 2, 5, 6
), nrow = 7, byrow = TRUE)

create_dominosa_plot(grid)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sol &amp;lt;- solve_dominosa(grid)

create_dominosa_plot(grid, sol)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2019-01-28-dominosa_files/figure-html/unnamed-chunk-7-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;A fun exercise in recursive backtracking.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-plot_dominosa&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix: &lt;code&gt;plot_dominosa()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a plot of a dominosa grid and solution
#&amp;#39;
#&amp;#39; @param grid Puzzle grid (matrix)
#&amp;#39; @param sol Solution matrix
#&amp;#39;
#&amp;#39; @return ggplot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_dominosa_plot &amp;lt;- function(grid, sol = NULL) {
  grid_df &amp;lt;- tibble(
    value =  c(grid), 
    row   = rep(seq(nrow(grid)), ncol(grid)), 
    col   = rep(seq(ncol(grid)), each = nrow(grid))
  )
  
  grid_df &amp;lt;- grid_df %&amp;gt;% mutate(
    row   = max(row) + 1L - row
  )
  
  p &amp;lt;- ggplot(grid_df) + 
    geom_tile(aes(col, row), width = 0.9, height = 0.9, fill = &amp;#39;grey90&amp;#39;) +
    geom_text(aes(col, row, label = value)) +
    theme_void() + 
    coord_equal()
  
  if (!is.null(sol)) {
    sol_df &amp;lt;- as.tbl(as.data.frame(sol)) %&amp;gt;%
      mutate(
        row     = max(row) + 1L - row,
        row_end = if_else(direction == 1, row - 1L, row),
        col_end = if_else(direction == 0, col + 1L, col)
      ) %&amp;gt;% mutate(
        col      = col     - 0.42,
        row      = row     + 0.42,
        col_end  = col_end + 0.42,
        row_end  = row_end - 0.42
      )
    
    p &amp;lt;- p + geom_rect(data = sol_df, aes(xmin = col, xmax = col_end, ymin = row, ymax = row_end), 
                       fill = NA, colour = &amp;#39;grey20&amp;#39;, size = 2)
  }
  
  p
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>split-apply-combine with `group_map`</title>
      <link>https://coolbutuseless.github.io/2018/12/31/split-apply-combine-with-group_map/</link>
      <pubDate>Mon, 31 Dec 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/12/31/split-apply-combine-with-group_map/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;split-apply-combine&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine&lt;/h2&gt;
&lt;p&gt;I tend to do quite a lot of coding where data is split into groups, operations
performed independently on each group, and then the data re-assembled into
a single entity.&lt;/p&gt;
&lt;p&gt;This is the classic &lt;strong&gt;split-apply-combine&lt;/strong&gt; as outlined in
&lt;a href=&#34;https://www.jstatsoft.org/article/view/v040i01/v40i01.pdf&#34;&gt;Hadley Wickham’s JStatSoft paper (pdf)&lt;/a&gt; and
discussed in &lt;a href=&#34;https://speakerdeck.com/jennybc/ubc-stat545-split-apply-combine-intro&#34;&gt;Jenny Bryan’s Stat545 notes&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;group_by-do-is-basically-deprecated&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_by&lt;/code&gt; + &lt;code&gt;do&lt;/code&gt; is “basically deprecated”&lt;/h2&gt;
&lt;p&gt;The original way I performed &lt;em&gt;split-apply-combine&lt;/em&gt; in the tidyverse was with
&lt;code&gt;group_by&lt;/code&gt; and &lt;code&gt;do&lt;/code&gt;,&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df &amp;lt;- dplyr::tribble(
  ~type, ~value,
  NA   , 1,
  NA   , 2,
  1    , 3,
  1    , 4,
  2    , 5, 
  2    , 6
)

# Note: the actual applied functions are much much much more complex than this
trivial_func &amp;lt;- function(x) {
  x %&amp;gt;% mutate(output = value + 1)
}


df %&amp;gt;%
  group_by(type) %&amp;gt;%
  do(trivial_func(.))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 3
# Groups:   type [3]
   type value output
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;  &amp;lt;dbl&amp;gt;
1     1     3      4
2     1     4      5
3     2     5      6
4     2     6      7
5    NA     1      2
6    NA     2      3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However &lt;code&gt;dplyr::do()&lt;/code&gt; is “basically deprecated” (according
to Hadley Wickham on twitter).&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/ijlyttle?ref_src=twsrc%5Etfw&#34;&gt;@ijlyttle&lt;/a&gt; btw dplyr::do() is now basically deprecated in favour of the purrr approach&lt;/p&gt;&amp;mdash; Hadley Wickham (@hadleywickham) &lt;a href=&#34;https://twitter.com/hadleywickham/status/719542847045636096?ref_src=twsrc%5Etfw&#34;&gt;April 11, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;My &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;Search for a replacement to dplyr+do in early 2018&lt;/a&gt;
wasn’t really successful, and in the end I proposed a addition to tidyr called
&lt;code&gt;chop&lt;/code&gt; (see the &lt;a href=&#34;https://github.com/tidyverse/tidyr/pull/434&#34;&gt;defunct pull request&lt;/a&gt;, and
the &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/07/chop-a-tidyverse-style-split/&#34;&gt;blog post&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dplyr-v0.8-to-the-rescue&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;dplyr v0.8&lt;/code&gt; to the rescue!&lt;/h2&gt;
&lt;p&gt;In late 2018 &lt;a href=&#34;https://github.com/romainfrancois&#34;&gt;Romain Francois&lt;/a&gt; implemented
a much better idea with a much better name in the &lt;code&gt;dplyr 0.8&lt;/code&gt; development branch.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.tidyverse.org/articles/2018/12/dplyr-0-8-0-release-candidate/&#34;&gt;v0.8 release candidate&lt;/a&gt; details
two functions I am particularly keen to try:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;group_split()&lt;/code&gt; - Split data frame by groups&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_map()&lt;/code&gt; and &lt;code&gt;group_walk&lt;/code&gt; - purrr-style functions that can be used to iterate on grouped tibbles&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;group_split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As detailed in 2 prior posts (&lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-1-runtime/&#34;&gt;here&lt;/a&gt;
and &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-2-idiosyncrasies/&#34;&gt;here&lt;/a&gt;), the
base &lt;code&gt;split()&lt;/code&gt; function has a lot of issue which make it problematic to use with the tidyverse - especially the
fact that it drops &lt;code&gt;NA&lt;/code&gt; groups completely!&lt;/p&gt;
&lt;p&gt;The new &lt;code&gt;group_split()&lt;/code&gt; is a super-charged, tidyverse-aware version of &lt;code&gt;split()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Combined with &lt;code&gt;purrr::map_dfr()&lt;/code&gt;, this looks it’s going to be part of
my preferred &lt;em&gt;split-apply-combine&lt;/em&gt; technique.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df %&amp;gt;%
  group_split(type) %&amp;gt;%
  purrr::map_dfr(trivial_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 3
   type value output
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;  &amp;lt;dbl&amp;gt;
1     1     3      4
2     1     4      5
3     2     5      6
4     2     6      7
5    NA     1      2
6    NA     2      3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;group_map&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;group_map()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;group_map()&lt;/code&gt; is a way of applying a function to each group.&lt;/p&gt;
&lt;p&gt;The applied function should take at least 2 arguments:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;The data.frame for a single group, but &lt;strong&gt;without&lt;/strong&gt; the grouping columns.&lt;/li&gt;
&lt;li&gt;A single-row data frame with the group columns for just this group&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;trivial_func2 &amp;lt;- function(df, group_info) {
  df %&amp;gt;% mutate(
    inner_cols = ncol(df),
    group_rows = nrow(group_info),
    is_grouped = is_grouped_df(df)
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df %&amp;gt;%
  group_by(type) %&amp;gt;%
  group_map(trivial_func2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
# A tibble: 2 x 4
  value inner_cols group_rows is_grouped
  &amp;lt;dbl&amp;gt;      &amp;lt;int&amp;gt;      &amp;lt;int&amp;gt; &amp;lt;lgl&amp;gt;     
1     3          1          1 FALSE     
2     4          1          1 FALSE     

[[2]]
# A tibble: 2 x 4
  value inner_cols group_rows is_grouped
  &amp;lt;dbl&amp;gt;      &amp;lt;int&amp;gt;      &amp;lt;int&amp;gt; &amp;lt;lgl&amp;gt;     
1     5          1          1 FALSE     
2     6          1          1 FALSE     

[[3]]
# A tibble: 2 x 4
  value inner_cols group_rows is_grouped
  &amp;lt;dbl&amp;gt;      &amp;lt;int&amp;gt;      &amp;lt;int&amp;gt; &amp;lt;lgl&amp;gt;     
1     1          1          1 FALSE     
2     2          1          1 FALSE     &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Things to note in the output:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The data.frames passed into &lt;code&gt;trivial_func2()&lt;/code&gt; are
&lt;ul&gt;
&lt;li&gt;ungrouped.&lt;/li&gt;
&lt;li&gt;missing the grouping column (&lt;code&gt;type&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;group_info&lt;/code&gt; is a single row data.frame with just the group information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This style of splitting the &lt;em&gt;grouping-columns&lt;/em&gt; from the &lt;em&gt;data-within-each-group&lt;/em&gt; is
similar to my mental model of how &lt;code&gt;tidyr::nest()/unnest()&lt;/code&gt; handles data. It’s not quite
how I think about &lt;em&gt;my&lt;/em&gt; data, so I think &lt;code&gt;group_split()&lt;/code&gt; will be my jam.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tldr&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;group_by()&lt;/code&gt; + &lt;code&gt;do()&lt;/code&gt; is “mostly deprecated”&lt;/li&gt;
&lt;li&gt;&lt;code&gt;group_split()&lt;/code&gt; + &lt;code&gt;purrr::map_dfr()&lt;/code&gt; is an &lt;strong&gt;excellent&lt;/strong&gt; replacement.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>R packages - internal and external data</title>
      <link>https://coolbutuseless.github.io/2018/12/10/r-packages-internal-and-external-data/</link>
      <pubDate>Mon, 10 Dec 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/12/10/r-packages-internal-and-external-data/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Packages in R can contain blobs of data - in fact some packages are &lt;em&gt;only&lt;/em&gt;
data without any code e.g. &lt;a href=&#34;https://cran.r-project.org/package=nycflights13&#34;&gt;&lt;code&gt;{nycflights13}&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Data in a package is classed as being &lt;em&gt;internal&lt;/em&gt; or &lt;em&gt;external&lt;/em&gt; to the package. In broad terms,
&lt;em&gt;internal&lt;/em&gt; data is data that the functions in the package use, and &lt;em&gt;external&lt;/em&gt;
data is the data you’d like the user to see.&lt;/p&gt;
&lt;p&gt;A recent issue is that I wanted data in the &lt;a href=&#34;https://github.com/coolbutuseless/phon&#34;&gt;&lt;code&gt;{phon}&lt;/code&gt;&lt;/a&gt;
package to be &lt;strong&gt;both&lt;/strong&gt; &lt;em&gt;external&lt;/em&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;em&gt;internal&lt;/em&gt;. That is, all the internal functions
rely on a particular dataset, but I want to make that dataset easily accessible to users as well.&lt;/p&gt;
&lt;p&gt;Now that I’ve figured out how to do it, I’m writing this post so that I don’t forget!&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://twitter.com/_ColinFay&#34;&gt;Colin Fay&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/hadleywickham&#34;&gt;Hadley Wickham&lt;/a&gt;
for their wizardly help!&lt;/p&gt;
&lt;p&gt;Hadley’s &lt;a href=&#34;http://r-pkgs.had.co.nz/data.html&#34;&gt;R Packages Book&lt;/a&gt; is a great source of background reading on this topic.&lt;/p&gt;
&lt;div id=&#34;internal-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Internal Data&lt;/h2&gt;
&lt;p&gt;Internal data is data within the package, but not (generally) made available
to the user.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://cran.r-project.org/package=usethis&#34;&gt;&lt;code&gt;{usethis}&lt;/code&gt;&lt;/a&gt; has a handy function to
help setup this data called &lt;code&gt;usethis::use_data()&lt;/code&gt;. The following code snippet
saves the data objects &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; to be internal data for your package:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;usethis::use_data(x, y, internal = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All functions within the package can now freely access the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; variables, but
the user won’t see them.&lt;/p&gt;
&lt;p&gt;If the user would like to access this data, then they could use the triple-colon accessor&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mypackage:::x&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;external-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;External data&lt;/h2&gt;
&lt;p&gt;External data is data contained in the package that is made available to the user,
but is not (generally) available to the functions within the package.&lt;/p&gt;
&lt;p&gt;Again, &lt;code&gt;usethis::use_data()&lt;/code&gt; can be used to set up the data:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;usethis::use_data(a, b, internal = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the package is loaded, the variables &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; will be made available
to the user&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(mypackage)
a

#&amp;gt; &amp;quot;this is string a&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;accessing-external-data-as-if-it-were-internal-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Accessing external data as if it were internal data&lt;/h2&gt;
&lt;p&gt;Data which is setup to be &lt;em&gt;external&lt;/em&gt; can be used internally within the package
if you explicitly namespace every occurrence. I.e. if the &lt;em&gt;external&lt;/em&gt; data is
called &lt;code&gt;x&lt;/code&gt;, then everywhere it is accessed within functions within the package
it should be accessed via &lt;code&gt;mypackage::x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are other ways to do this, but this method is:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: lower-alpha&#34;&gt;
&lt;li&gt;known to work&lt;/li&gt;
&lt;li&gt;known to pass &lt;code&gt;devtools::check()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;accepted by CRAN - see for example &lt;a href=&#34;https://cran.r-project.org/package=proustr&#34;&gt;&lt;code&gt;{proustr}&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://twitter.com/_ColinFay&#34;&gt;Colin Fay&lt;/a&gt; for showing me this solution.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;exporting-internal-data-to-make-it-seem-like-external-data.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Exporting internal data to make it seem like external data.&lt;/h2&gt;
&lt;p&gt;If data is set up to be internal to the package, in order for a user to access it&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;use &lt;em&gt;triple-colon&lt;/em&gt; accessor e.g. &lt;code&gt;mypackage:::x&lt;/code&gt;, or&lt;/li&gt;
&lt;li&gt;explicitly export the data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first method is a little non-standard for day-to-day usage, and mostly you
would like to avoid having to mess with the “hidden” functions and methods using
the triple-colon accessor.&lt;/p&gt;
&lt;p&gt;The second method, from &lt;a href=&#34;https//twitter.com/hadleywickham&#34;&gt;Hadley Wickham&lt;/a&gt;,
is to explicitly export the data as follows (if using roxygen)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#&amp;#39; Cool data which is used internally in the package
#&amp;#39; @name x
#&amp;#39; @export
&amp;quot;x&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now while the &lt;a href=&#34;http://r-pkgs.had.co.nz/data.html&#34;&gt;R Packages book&lt;/a&gt; insists that
you “Never @export a data set”, this seems like the exception to the rule.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;should-i-externalise-internal-data-or-internalise-external-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Should I externalise internal data? Or internalise external data?&lt;/h2&gt;
&lt;p&gt;I don’t know if there’s a better method (in terms of hackishness and/or pleasing the CRAN gods)
but keeping data internal and manually exporting seems like less work, so that’s
the one I’m going with.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>phon - a package for rhymes etc</title>
      <link>https://coolbutuseless.github.io/2018/12/03/phon-a-package-for-rhymes-etc/</link>
      <pubDate>Mon, 03 Dec 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/12/03/phon-a-package-for-rhymes-etc/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;phon&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;phon &lt;img src=&#34;https://coolbutuseless.github.io/img/phon/logo.png&#34; align=&#34;right&#34; height=230/&gt;&lt;/h1&gt;
&lt;p&gt;The goal of &lt;code&gt;phon&lt;/code&gt; is to make available the CMU Pronouncing Dictionary
(&lt;a href=&#34;http://www.speech.cs.cmu.edu/cgi-bin/cmudict&#34;&gt;&lt;strong&gt;cmudict&lt;/strong&gt;&lt;/a&gt;) in an R friendly
format, and to collect some tools which use the pronunciation information.&lt;/p&gt;
&lt;p&gt;The CMU Pronouncing Dictionary includes pronunciations for 130,000 words. By matching
the phonemes between words, &lt;code&gt;phon&lt;/code&gt; provides&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;phonemes(&#39;threw&#39;)&lt;/code&gt; - Returns the phonemes for the pronunciation of “threw”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;homophones(&#39;steak&#39;)&lt;/code&gt; - Returns words which are homophones of “steak”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rhymes(&#39;carry&#39;)&lt;/code&gt; - Returns words which rhyme with “carry”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sounds_like(&#39;statistics&#39;, 3)&lt;/code&gt; - Returns words with a similar sound to
“statistics” by limiting the mismatches in phonemes the other word can have.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contains_pronunciation(&#39;through&#39;)&lt;/code&gt; - Returns words which sound like they
contain the given word&lt;/li&gt;
&lt;li&gt;&lt;code&gt;syllables(&#34;useless&#34;)&lt;/code&gt; Returns the count of syllables in “useless”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a companion package to the &lt;a href=&#34;http://syn.njtierney.com/&#34;&gt;syn&lt;/a&gt; package.
&lt;code&gt;syn&lt;/code&gt; finds related words based upon meanings, while &lt;code&gt;phon&lt;/code&gt; finds related words based upon
pronunciation.&lt;/p&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;phon&lt;/code&gt; from github with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;quot;coolbutuseless/phon&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;phonemes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Phonemes&lt;/h2&gt;
&lt;p&gt;Phonemes are the sounds which make up a word.&lt;/p&gt;
&lt;p&gt;The phonetic encoding in &lt;code&gt;phon&lt;/code&gt; come from the CMU Pronouncing Dictionary
(&lt;a href=&#34;http://www.speech.cs.cmu.edu/cgi-bin/cmudict&#34;&gt;&lt;strong&gt;cmudict&lt;/strong&gt;&lt;/a&gt;)
which encodes words using &lt;a href=&#34;https://en.wikipedia.org/wiki/ARPABET&#34;&gt;ARPABET&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::phonemes(&amp;quot;cellar&amp;quot;)
[1] &amp;quot;S EH L ER&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since some words have mutliple pronunciations, the results of &lt;code&gt;phon::phonemes()&lt;/code&gt;
is always returned as a list, e.g. &lt;em&gt;carry&lt;/em&gt; has two slightly different
pronunciations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::phonemes(&amp;quot;carry&amp;quot;)
[1] &amp;quot;K AE R IY&amp;quot; &amp;quot;K EH R IY&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ARPABET phonetic encoding includes stress markers as suffixes to vowel phonemes. The markers are:&lt;/p&gt;
&lt;ol start=&#34;0&#34; style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;No stress&lt;/li&gt;
&lt;li&gt;Primary stress&lt;/li&gt;
&lt;li&gt;Secondary stress&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can ask for phonemes with/without the stress markers, e.g.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::phonemes(&amp;quot;fantastic&amp;quot;)
[1] &amp;quot;F AE N T AE S T IH K&amp;quot;

phon::phonemes(&amp;quot;fantastic&amp;quot;, keep_stresses = TRUE)
[1] &amp;quot;F AE0 N T AE1 S T IH0 K&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;syllables&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Syllables&lt;/h2&gt;
&lt;p&gt;The number of syllables in a word is the count of the number of phonemes with
stress markers in the word.&lt;/p&gt;
&lt;p&gt;This is pre-calculated and available through the &lt;code&gt;phon::syllables()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::syllables(&amp;quot;average&amp;quot;)
[1] 3

phon::syllables(&amp;quot;antidisestablishmentarianism&amp;quot;)
[1] 12&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;matching-pronunciation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Matching Pronunciation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;phon&lt;/code&gt; allows you to search for the sound of one word within another.&lt;/p&gt;
&lt;p&gt;In the following example, &lt;code&gt;phon::contains_pronunciation()&lt;/code&gt; finds all the words that
include the pronunciation of &lt;em&gt;“through”&lt;/em&gt; within their pronunciation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::contains_pronunciation(&amp;quot;through&amp;quot;)
 [1] &amp;quot;bathroom&amp;quot;      &amp;quot;bathrooms&amp;quot;     &amp;quot;breakthrough&amp;quot;  &amp;quot;breakthroughs&amp;quot;
 [5] &amp;quot;drive-thru&amp;quot;    &amp;quot;drive-thrus&amp;quot;   &amp;quot;overthrew&amp;quot;     &amp;quot;threw&amp;quot;        
 [9] &amp;quot;throop&amp;quot;        &amp;quot;throughout&amp;quot;    &amp;quot;throughput&amp;quot;    &amp;quot;throughs&amp;quot;     
[13] &amp;quot;throughway&amp;quot;    &amp;quot;thru&amp;quot;          &amp;quot;thruway&amp;quot;      &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use the &lt;code&gt;keep_stresses&lt;/code&gt; argument to match with/without the stresses included (default is
to ignore the stresses).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;homophones&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Homophones&lt;/h2&gt;
&lt;p&gt;Homophones are words with the same pronunciation but different spelling.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::homophones(&amp;quot;steak&amp;quot;)
[1] &amp;quot;stake&amp;quot;

phon::homophones(&amp;quot;carry&amp;quot;)
 [1] &amp;quot;carey&amp;quot;  &amp;quot;carie&amp;quot;  &amp;quot;carrey&amp;quot; &amp;quot;carrie&amp;quot; &amp;quot;cary&amp;quot;   &amp;quot;kairey&amp;quot; &amp;quot;kari&amp;quot;   &amp;quot;karry&amp;quot; 
 [9] &amp;quot;kary&amp;quot;   &amp;quot;kerrey&amp;quot; &amp;quot;kerri&amp;quot;  &amp;quot;kerry&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rhymes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rhymes&lt;/h2&gt;
&lt;p&gt;To find rhymes, &lt;code&gt;phon&lt;/code&gt; compares trailing phonemes. If the phonemes at the end of a
word in the dictionary match those at the end of the given word, then they rhyme.&lt;/p&gt;
&lt;p&gt;The rhymes are returned in multiple vectors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Words with the most matching trailing phonemes are returned first.&lt;/li&gt;
&lt;li&gt;Subsequent vectors have fewer matching trailing phonemes.&lt;/li&gt;
&lt;li&gt;The names of the list are the number of trailing phonemes which match.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::rhymes(&amp;quot;drudgery&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$`3`
 [1] &amp;quot;challengery&amp;quot;  &amp;quot;forgery&amp;quot;      &amp;quot;gingery&amp;quot;      &amp;quot;injury&amp;quot;       &amp;quot;margery&amp;quot;     
 [6] &amp;quot;marjorie&amp;quot;     &amp;quot;marjory&amp;quot;      &amp;quot;menagerie&amp;quot;    &amp;quot;neurosurgery&amp;quot; &amp;quot;perjury&amp;quot;     
[11] &amp;quot;surgery&amp;quot;     

$`2`
  [1] &amp;quot;acary&amp;quot;           &amp;quot;accessory&amp;quot;       &amp;quot;adoree&amp;quot;          &amp;quot;adultery&amp;quot;       
  [5] &amp;quot;advisory&amp;quot;        &amp;quot;alimentary&amp;quot;      &amp;quot;alphandery&amp;quot;      &amp;quot;ambery&amp;quot;         
  [9] .... (results trimmed)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The phonemes for “drudgery” are “D R AH1 JH ER0 IY0”&lt;/li&gt;
&lt;li&gt;In the first vector, the words match the &lt;em&gt;-gery&lt;/em&gt; sound, i.e the last 3 phonemes.&lt;/li&gt;
&lt;li&gt;In the second vector the words only match the &lt;em&gt;-ery&lt;/em&gt; sound, i.e. the last 2 phonemes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;similar-sounding-words&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Similar sounding words&lt;/h2&gt;
&lt;p&gt;Similar sounding words are found by comparing words with the same number
of phonemes but with a number of mismatches allowed.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;phon::sounds_like(&amp;quot;statistics&amp;quot;, phoneme_mismatches = 5)
 [1] &amp;quot;anaesthetics&amp;quot; &amp;quot;anesthetics&amp;quot;  &amp;quot;centronics&amp;quot;   &amp;quot;gymnastics&amp;quot;   &amp;quot;heuristics&amp;quot;  
 [6] &amp;quot;onomastics&amp;quot;   &amp;quot;scientific&amp;#39;s&amp;quot; &amp;quot;scientifics&amp;quot;  &amp;quot;statistics&amp;#39;&amp;quot;  &amp;quot;stochastics&amp;quot; 
[11] &amp;quot;subsistence&amp;quot;  &amp;quot;synbiotics&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>grrr - a package for changing default function arguments</title>
      <link>https://coolbutuseless.github.io/2018/11/20/grrr-a-package-for-changing-default-function-arguments/</link>
      <pubDate>Tue, 20 Nov 2018 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/11/20/grrr-a-package-for-changing-default-function-arguments/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;raison-dêtre---stringsasfactors-true-sucks&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;raison d’être - &lt;code&gt;stringsAsFactors = TRUE&lt;/code&gt; sucks&lt;/h2&gt;
&lt;video width=&#34;75%&#34; loop&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/grrr/crying.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;p&gt;This package can change default arguments
in pre-existing functions to be almost anything.&lt;/p&gt;
&lt;p&gt;So you can change &lt;code&gt;stringsAsFactors = FALSE&lt;/code&gt; whereever you please!&lt;/p&gt;
&lt;p&gt;This is based on a &lt;a href=&#34;https://coolbutuseless.github.io/2018/04/11/changing-the-default-arguments-to-a-function/&#34;&gt;blog post from earlier this year&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;install.packages(&amp;quot;coolbutuseless/grrr&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-1-change-mean-to-use-na.rm-true-by-default&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 1: Change &lt;code&gt;mean&lt;/code&gt; to use &lt;code&gt;na.rm = TRUE&lt;/code&gt; by default&lt;/h2&gt;
&lt;p&gt;A call to &lt;code&gt;mean&lt;/code&gt; will not remove &lt;code&gt;NA&lt;/code&gt; values from the input i.e. &lt;code&gt;na.rm = FALSE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can switch this default to &lt;code&gt;na.rm = TRUE&lt;/code&gt; so that &lt;code&gt;NA&lt;/code&gt; values are &lt;em&gt;always&lt;/em&gt;
removed:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grrr::update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=TRUE)

mean(c(1, 3, 5, NA))
[1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2-change-quantile-to-not-have-a-default-value-for-na.rm&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 2: Change &lt;code&gt;quantile&lt;/code&gt; to not have a default value for &lt;code&gt;na.rm&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;A problem with changing the default value to be different, is that while the
code may work on your machine, it will still have the old behaviour for any
one else running the code.&lt;/p&gt;
&lt;p&gt;A safer way to change the default value would be to remove it altogether!&lt;/p&gt;
&lt;p&gt;This way, you are forced to explicitly set a good/sane default value every time
the function is called.&lt;/p&gt;
&lt;p&gt;In the following call, the default value &lt;code&gt;na.rm&lt;/code&gt; is removed, and thus an error
will occur anytime we use the function without explictly setting the value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grrr::update_function_arguments(&amp;#39;quantile.default&amp;#39;, &amp;#39;stats&amp;#39;, na.rm=)

quantile(1:10)
Error in quantile.default(1:10): argument &amp;quot;na.rm&amp;quot; is missing, with no default&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-3-print-warnings-when-defaults-are-used&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example 3: Print warnings when defaults are used&lt;/h2&gt;
&lt;p&gt;The problem with unsetting the default value is that there may be numerous places
in packages that make use this assumption you’ve just removed! So you’ll end up with errors in places
you can’t access to fix.&lt;/p&gt;
&lt;p&gt;In this example, the &lt;code&gt;stringsAsFactors&lt;/code&gt; argument to &lt;code&gt;data.frame()&lt;/code&gt; is being changed
to print a message if an explicit value isn’t given (but it will still go ahead
and use the default anyway).&lt;/p&gt;
&lt;p&gt;This way, you’ll be notified when it happens, but no error will occur.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grrr::update_function_arguments(
  function_name    = &amp;#39;data.frame&amp;#39;, 
  package_name     = &amp;#39;base&amp;#39;, 
  stringsAsFactors = { message(&amp;quot;Using default stringsAsFactors in data.frame()&amp;quot;); default.stringsAsFactors() } 
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;data.frame(x = 1:3, y = c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;))
Using default stringsAsFactors in data.frame()
  x y
1 1 a
2 2 b
3 3 c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;faq&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;FAQ&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&#34;why-not-just-re-assign-the-function-in-the-global-namespace&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why not just re-assign the function in the global namespace?&lt;/h2&gt;
&lt;p&gt;Because that won’t fix places which call the function explicitly e.g. 
&lt;code&gt;stats::quantile()&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-not-use-purrrpartial&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why not use &lt;code&gt;purrr::partial()&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Because that won’t change the function where it lives.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;warning&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Warning&lt;/h2&gt;
&lt;p&gt;This package uses &lt;code&gt;unlockBinding()&lt;/code&gt; and &lt;code&gt;assignInNamespace()&lt;/code&gt; and messes with
the internals of other packages which is generally frowned upon.&lt;/p&gt;
&lt;p&gt;Furthermore, &lt;code&gt;assignInNamespace()&lt;/code&gt; actually has some checks
to prevent what I’m trying to do. So there is now &lt;code&gt;grrr::sudo_assignInNamespace()&lt;/code&gt;
which drops some sanity checks. #madness&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>ggthreed - 3d pie charts</title>
      <link>https://coolbutuseless.github.io/2018/11/13/ggthreed-3d-pie-charts/</link>
      <pubDate>Tue, 13 Nov 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/11/13/ggthreed-3d-pie-charts/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;should-i-write-a-geom-for-3d-pie-charts&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Should I write a &lt;code&gt;geom&lt;/code&gt; for 3d pie charts?&lt;/h2&gt;
&lt;video width=&#34;75%&#34;  autoplay loop&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/ggthreed/announce/stop.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;div id=&#34;introducing-the-ggthreed-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introducing the &lt;code&gt;ggthreed&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/coolbutuseless/ggthreed&#34;&gt;&lt;code&gt;ggthreed&lt;/code&gt;&lt;/a&gt; is a collection of &lt;a href=&#34;https://github.com/tidyverse/ggplot2&#34;&gt;&lt;code&gt;ggplot2&lt;/code&gt;&lt;/a&gt;
geoms which use the &lt;a href=&#34;https://github.com/coolbutuseless/threed&#34;&gt;&lt;code&gt;threed&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;At present it consists of just a single geom: &lt;code&gt;geom_threedpie()&lt;/code&gt; which creates
3d pie charts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I am fully aware of the crimes against visualisation I am committing here.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The code is available on &lt;a href=&#34;https://github.com/coolbutuseless/ggthreed&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install from github&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;install.packages(&amp;quot;coolbutuseless/threed&amp;quot;)
install.packages(&amp;quot;coolbutuseless/ggthreed&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example---simple-pie-chart&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example - Simple Pie Chart&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) + 
  geom_threedpie(aes(x = as.factor(cyl))) + 
  theme_void() + 
  theme(legend.position = &amp;#39;bottom&amp;#39;)
Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-13-ggthreed-3d-pie-charts_files/figure-html/example-simple-1.png&#34; width=&#34;500&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example---facetted-pie-chart&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example - Facetted Pie Chart&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(diamonds)  +
  geom_threedpie(aes(as.factor(cut))) +
  facet_wrap(~clarity, labeller = label_both) +
  labs(title = &amp;quot;Distribution of Diamond Cuts by Clarity&amp;quot;) +
  scale_fill_brewer(name = &amp;quot;Cut&amp;quot;, palette = &amp;#39;Set2&amp;#39;) +
  theme_void()
Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.

Warning: Unknown or uninitialised column: &amp;#39;subgroup&amp;#39;.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-13-ggthreed-3d-pie-charts_files/figure-html/example-facet-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example---pie-appearance&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Example - Pie appearance&lt;/h1&gt;
&lt;p&gt;User adjustable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pie height&lt;/li&gt;
&lt;li&gt;pie tilt&lt;/li&gt;
&lt;li&gt;start of first pie slice&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/ggthreed/announce/pie-anim.gif&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;mission-accomplished&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Mission Accomplished&lt;/h2&gt;
&lt;video width=&#34;75%&#34;  autoplay loop&gt;
&lt;source src=&#34;https://coolbutuseless.github.io/img/ggthreed/announce/clapping.mp4&#34; type=&#34;video/mp4&#34;&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>threed - drawing a cube in ggplot2</title>
      <link>https://coolbutuseless.github.io/2018/11/12/threed-drawing-a-cube-in-ggplot2/</link>
      <pubDate>Mon, 12 Nov 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/11/12/threed-drawing-a-cube-in-ggplot2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This post explores how to plot a cube in &lt;a href=&#34;https://github.com/tidyverse/ggplot2&#34;&gt;&lt;code&gt;ggplot2&lt;/code&gt;&lt;/a&gt;
using the &lt;a href=&#34;https://github.com/coolbutuseless/threed&#34;&gt;&lt;code&gt;threed&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ggplot2&lt;/code&gt; doesn’t include any notion of a 3rd spatial axis, so instead, after
manipulating a 3d object, we use perspective projection to “flatten” its faces and
vertices onto a 2d plane. These projected faces/vertices are what ggplot2 will plot.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;prepare-an-object-for-plotting&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Prepare an object for plotting&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create an object (here the standard 2x2x2 cube is being used)&lt;/li&gt;
&lt;li&gt;Define where camera is located, and where it is looking&lt;/li&gt;
&lt;li&gt;Transform the object into camera space&lt;/li&gt;
&lt;li&gt;Perspective transform the data&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The `threed` package has some builtin objects in `threed::mesh3dobj`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
obj &amp;lt;- threed::mesh3dobj$cube

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define camera &amp;#39;lookat&amp;#39; matrix i.e. camera-to-world transform
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
camera_to_world &amp;lt;- threed::look_at_matrix(eye = c(1.5, 1.75, 4), at = c(0, 0, 0))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Transform the object into camera space and do perspective projection
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
obj &amp;lt;- obj %&amp;gt;%
  transform_by(invert_matrix(camera_to_world)) %&amp;gt;%
  perspective_projection()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;as.data.frame(obj) %&amp;gt;% knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;element_id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;element_type&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;vorder&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;y&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;z&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;vertex&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;vnx&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;vny&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;vnz&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fnx&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fny&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fnz&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fcx&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fcy&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;fcz&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;zorder&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;zorder_var&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;hidden&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0945866&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0706857&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.581399&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1855445&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1356142&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9732328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1523493&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1540033&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9762544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0748818&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0756647&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1077957&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2603509&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.631559&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2154400&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3088482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9263900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1523493&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1540033&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9762544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0748818&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0756647&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2693976&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2400504&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.687219&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.4345424&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3475777&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8308806&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1523493&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1540033&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9762544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0748818&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0756647&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2325119&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1270569&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.623552&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3706042&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1407513&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9180640&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1523493&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1540033&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9762544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0748818&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0756647&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.630932&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1077957&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2603509&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.631559&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2154400&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3088482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9263900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9394660&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3426420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0013440&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2085811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3483420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1903526&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.823482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1812743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2777220&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9434035&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9394660&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3426420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0013440&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2085811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1921159&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1435705&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.951750&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6699657&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4605475&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.5822731&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9394660&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3426420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0013440&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2085811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2693976&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2400504&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.687219&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.4345424&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3475777&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8308806&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9394660&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3426420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0013440&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2085811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.773502&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2325119&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1270569&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.623552&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3706042&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1407513&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9180640&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9631644&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1369155&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2314485&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2119637&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0287422&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2693976&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2400504&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.687219&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.4345424&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3475777&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8308806&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9631644&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1369155&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2314485&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2119637&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0287422&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1921159&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1435705&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.951750&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6699657&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4605475&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.5822731&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9631644&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1369155&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2314485&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2119637&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0287422&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1538294&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3715328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.806364&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3411191&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1021382&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9344547&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9631644&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1369155&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2314485&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2119637&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0287422&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.767221&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0945866&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0706857&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.581399&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1855445&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1356142&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9732328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6370835&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0905625&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.7654561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2099435&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0306140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2890497&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2575617&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.721140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1542710&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1026941&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9826771&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6370835&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0905625&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.7654561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2099435&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0306140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3483420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1903526&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.823482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1812743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2777220&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9434035&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6370835&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0905625&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.7654561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2099435&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0306140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1077957&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2603509&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.631559&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2154400&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3088482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9263900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6370835&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0905625&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.7654561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2099435&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0306140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.689395&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0945866&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0706857&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.581399&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1855445&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1356142&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9732328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.5988573&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8008558&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0006763&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2067093&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2325119&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1270569&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.623552&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3706042&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1407513&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9180640&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.5988573&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8008558&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0006763&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2067093&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1538294&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3715328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.806364&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3411191&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1021382&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9344547&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.5988573&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8008558&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0006763&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2067093&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2890497&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2575617&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.721140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1542710&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1026941&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9826771&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.5988573&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.8008558&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0006763&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2067093&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.683114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2890497&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2575617&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.721140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1542710&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.1026941&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.9826771&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2439436&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2465920&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9379147&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0728616&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0737928&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1538294&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3715328&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.806364&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.3411191&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1021382&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9344547&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2439436&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2465920&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9379147&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0728616&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0737928&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1921159&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1435705&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.951750&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.6699657&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4605475&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.5822731&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2439436&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2465920&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9379147&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0728616&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0737928&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.3483420&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1903526&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.823482&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1812743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2777220&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9434035&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2439436&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.2465920&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.9379147&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0728616&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.0737928&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.825684&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-the-points-for-the-vertices-of-the-object&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Plot the points for the vertices of the object&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;threed&lt;/code&gt; defines a &lt;code&gt;fortify.mesh3d()&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;If a &lt;code&gt;mesh3d&lt;/code&gt; object is given as the data for a&lt;code&gt;ggplot2&lt;/code&gt; call, &lt;code&gt;ggplot2&lt;/code&gt; will
automatically use &lt;code&gt;fortify()&lt;/code&gt; to convert into a data.frame.&lt;/li&gt;
&lt;li&gt;i.e. because &lt;code&gt;threed&lt;/code&gt; defines &lt;code&gt;fortify.mesh3d()&lt;/code&gt;, we can call &lt;code&gt;ggplot2&lt;/code&gt; directly with a &lt;code&gt;mesh3d&lt;/code&gt; object.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y)) +
  geom_point() +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-the-outline-of-each-polygon&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Plot the outline of each polygon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Each element has a unique &lt;code&gt;element_id&lt;/code&gt;, and this is used as the &lt;code&gt;group&lt;/code&gt; aesthetic
to inform ggplot that it should draw one polygon for each element.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;fill = NA, colour = &#39;black&#39;&lt;/code&gt; to draw only the borders of each polygon.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = element_id)) +
  geom_polygon(fill = NA, colour = &amp;#39;black&amp;#39;, size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dotted-rendering-of-hidden-lines&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dotted rendering of hidden lines&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;To draw &lt;em&gt;hidden&lt;/em&gt; elements in a different way, use the &lt;code&gt;hidden&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hidden&lt;/code&gt; is a boolean variable indicating if a triangle or quad element is facing
away from the camera.&lt;/li&gt;
&lt;li&gt;Here a different &lt;code&gt;linetype&lt;/code&gt; is used for hidden elements&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = element_id)) +
  geom_polygon(fill = NA, colour=&amp;#39;black&amp;#39;, aes(linetype = hidden,  size = hidden)) +
  scale_linetype_manual(values = c(&amp;#39;TRUE&amp;#39; = &amp;quot;dotted&amp;quot;, &amp;#39;FALSE&amp;#39; = &amp;#39;solid&amp;#39;)) +
  scale_size_manual(values = c(&amp;#39;TRUE&amp;#39; = 0.2, &amp;#39;FALSE&amp;#39; = 0.5)) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hidden-line-removal&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hidden line removal&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Here a zero-width &lt;code&gt;linetype&lt;/code&gt; is used for hidden elements to hide them.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = element_id)) +
  geom_polygon(fill = NA, colour = &amp;#39;black&amp;#39;, aes(size = hidden)) +
  scale_size_manual(values = c(&amp;#39;TRUE&amp;#39; = 0, &amp;#39;FALSE&amp;#39; = 0.5)) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-filled-polygons&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive Filled Polygons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;When filling polygons, &lt;code&gt;ggplot2&lt;/code&gt; will draw them in the order of the &lt;code&gt;group&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;If we group by &lt;code&gt;element_id&lt;/code&gt; then the polygons are drawn in the order in which
they were defined. This means that polygons which are further away will
be draw over the top of ones which are actually close to the eye.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;The result will look weird - Almost Escher-esque!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = element_id)) +
  geom_polygon(fill = &amp;#39;lightblue&amp;#39;, colour = &amp;#39;black&amp;#39;, size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;filled-polygons---1-drop-hidden-elements-so-they-never-get-drawn&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filled Polygons - (1) Drop hidden elements so they never get drawn&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;First method&lt;/strong&gt; for drawing filled polygons:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;drop hidden elements manually&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Do this by explicitly converting the &lt;code&gt;mesh3d&lt;/code&gt; object to a data.frame, and then filtering
to keep only the elements which aren’t hidden.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;mesh3d&lt;/code&gt; objects converted to data.frames, &lt;code&gt;hidden&lt;/code&gt; is defined as &lt;code&gt;TRUE&lt;/code&gt; for
any face which has a normal which points towards the negative Z axis (i.e. away
from the viewing plane).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;obj_df &amp;lt;- as.data.frame(obj) %&amp;gt;%
  filter(!hidden)

ggplot(obj_df, aes(x, y, group = element_id)) +
  geom_polygon(fill = &amp;#39;lightblue&amp;#39;, colour = &amp;#39;black&amp;#39;, size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;filled-polygons---2-assign-hidden-elements-a-fill-of-na-so-they-get-drawn-invisibly&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filled Polygons - (2) Assign hidden elements a fill of &lt;code&gt;NA&lt;/code&gt; so they get drawn invisibly&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Second method&lt;/strong&gt; for drawing filled polygons:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;draw hidden elements invisibly&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Do this by explicitly converting the &lt;code&gt;mesh3d&lt;/code&gt; object to a data.frame, and
then manually setting the variables mapped to &lt;code&gt;fill&lt;/code&gt; and &lt;code&gt;colour&lt;/code&gt; to
be &lt;code&gt;NA&lt;/code&gt; for hidden elements&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;obj_df &amp;lt;- as.data.frame(obj) %&amp;gt;%
  mutate(
    shade      = ifelse(hidden, NA, &amp;#39;lightblue&amp;#39;),
    linecolour = ifelse(hidden, NA, &amp;#39;black&amp;#39;)
  )

ggplot(obj_df, aes(x, y, group = element_id)) +
  geom_polygon(aes(fill = I(shade), colour = I(linecolour)), size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;filled-polygons---3-use-the-zorder-variable-to-control-draw-order&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filled Polygons - (3) Use the &lt;code&gt;zorder&lt;/code&gt; variable to control draw order&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Third method&lt;/strong&gt; for drawing filled polygons:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Draw the elements from furtherest to nearest&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Exploit the fact that elements are drawn in the order of the &lt;code&gt;group&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;When converting a &lt;code&gt;mesh3d&lt;/code&gt; to a data.frame, a &lt;code&gt;zorder&lt;/code&gt; variable is created starting at
&lt;code&gt;1&lt;/code&gt; for the furtherest element, up to &lt;code&gt;n&lt;/code&gt; for the closest element.&lt;/li&gt;
&lt;li&gt;i.e. change the &lt;code&gt;group&lt;/code&gt; variable from &lt;code&gt;element_id&lt;/code&gt; to &lt;code&gt;zorder&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = zorder)) +
  geom_polygon(fill = &amp;#39;lightblue&amp;#39;, colour=&amp;#39;black&amp;#39;, size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;fake-shaded-polygon&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Fake-shaded polygon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The normal to each face is included in the data.frame representation as &lt;code&gt;fnx, fny, fnz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;By calculating dot products to a light source positioned in the scene, the fraction
illumination could be calculated for each element.&lt;/li&gt;
&lt;li&gt;Here, the shading is being completely faked by using the sum &lt;code&gt;fny + fnz&lt;/code&gt; to shade the polygons.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(obj, aes(x, y, group = zorder)) +
  geom_polygon(aes(fill = fny + fnz), colour = &amp;#39;black&amp;#39;, size = 0.2) +
  theme_void() +
  theme(legend.position = &amp;#39;none&amp;#39;) +
  coord_equal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-12-drawing-a-cube-with-ggplot2-threed_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Parsing a favicon with {minitypes}</title>
      <link>https://coolbutuseless.github.io/2018/11/06/parsing-a-favicon-with-minitypes/</link>
      <pubDate>Tue, 06 Nov 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/11/06/parsing-a-favicon-with-minitypes/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minitypes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minitypes&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-alpha-orange.svg&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minitypes&lt;/code&gt; is a package of type conversion tools for R atomic vectors.&lt;/p&gt;
&lt;p&gt;This package is built upon R’s type conversion tools and aims to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a consistent interface for converting between types&lt;/li&gt;
&lt;li&gt;add handling for types not handled by R explicitly e.g. &lt;code&gt;uint8&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s available from &lt;a href=&#34;https://github.com/coolbutuseless/minitypes&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;worked-example---parsing-an-ico-favicon&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Worked Example - Parsing an ICO favicon&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Read in a favicon file (ICO) as raw bytes (ICO values are represented in little-endian byte order)&lt;/li&gt;
&lt;li&gt;Manually parse the ICO header (see e.g. &lt;a href=&#34;https://en.wikipedia.org/wiki/ICO_(file_format)&#34;&gt;ICO format&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Parse out the pixels and plot&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;read-the-favicon-as-raw-bytes&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Read the favicon as raw bytes&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# cran.r-project favicon!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# https://cran.r-project.org/favicon.ico
ico_filename &amp;lt;- &amp;quot;../../static/img/minitypes/favicon.ico&amp;quot;
ico          &amp;lt;- readBin(ico_filename, &amp;#39;raw&amp;#39;, n = file.size(ico_filename))

head(ico, 50)
 [1] 00 00 01 00 02 00 10 10 00 00 01 00 20 00 68 04 00 00 26 00 00 00 20 20 00
[26] 00 01 00 20 00 a8 10 00 00 8e 04 00 00 28 00 00 00 10 00 00 00 20 00 00 00&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minitypes/favicon.ico&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;read-the-header-to-find-where-the-iamge-data-starts&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Read the header to find where the iamge data starts&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Reserved - must always be zero
raw_to_uint16(ico[1:2], endian = &amp;#39;little&amp;#39;)  
[1] 0

# image type. 1 = ICO, 2 = CUR
raw_to_uint16(ico[3:4], endian = &amp;#39;little&amp;#39;)  
[1] 1

# number of images in the file
raw_to_uint16(ico[5:6], endian = &amp;#39;little&amp;#39;)  
[1] 2

# width, height
raw_to_uint8(ico[7:8], endian = &amp;#39;little&amp;#39;) 
[1] 16 16

# number of color planes
raw_to_uint16(ico[11:12], endian = &amp;#39;little&amp;#39;) 
[1] 1

# bits per pixel
raw_to_uint16(ico[13:14], endian = &amp;#39;little&amp;#39;) 
[1] 32

# number of bytes of image data
raw_to_int32(ico[15:18], endian = &amp;#39;little&amp;#39;) 
[1] 1128

# Image data offset
raw_to_int32(ico[19:22], endian = &amp;#39;little&amp;#39;) 
[1] 38&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;read-one-channel-of-the-image-data&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Read one channel of the image data&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# read 4bytes per pixel for 16x16 pixels.
# Skip to the image data offset (+38), and jump over the BMP data header(?) (+44)
image &amp;lt;- raw_to_int32(ico[38 + 44 - 1 + seq_len(16*16*4)])

# Reshape to be a 16x16 matrix, keeping only the lowest byte.
image &amp;lt;- (matrix(image %% 256, 16, 16, byrow=TRUE))[16:1,]

# plot as raster
rim &amp;lt;- raster(image)
plot(rim, col = grey(seq(1, 0, length.out = 16)), ann = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-06-parsing-favicon-with-minitypes_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Minitypes - vector type conversion</title>
      <link>https://coolbutuseless.github.io/2018/11/06/minitypes-vector-type-conversion/</link>
      <pubDate>Tue, 06 Nov 2018 06:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/11/06/minitypes-vector-type-conversion/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;minitypes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;minitypes&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/lifecycle-alpha-orange.svg&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;minitypes&lt;/code&gt; is a package of type conversion tools for R atomic vectors.&lt;/p&gt;
&lt;p&gt;This package is built upon R’s type conversion tools and aims to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a consistent interface for converting between types&lt;/li&gt;
&lt;li&gt;add handling for types not handled by R explicitly e.g. &lt;code&gt;uint8&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s available from &lt;a href=&#34;https://github.com/coolbutuseless/minitypes&#34;&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;supported-types&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Supported Types:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;raw byte
&lt;ul&gt;
&lt;li&gt;This is R’s builtin &lt;code&gt;raw&lt;/code&gt; byte format.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chr&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Ascii/utf8 representation.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;1 bit:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;logical&lt;/code&gt; - R’s built-in logical type e.g. &lt;code&gt;c(T, T, F)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bit&lt;/code&gt; - compact bit representation (from the &lt;a href=&#34;https://cran.r-project.org/package=bit&#34;&gt;bit package&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bitstring&lt;/code&gt; - character representaction of bits e.g. &lt;code&gt;110&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;8 bit
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uint8&lt;/code&gt; - R’s built-in integer type. Checked to be within range [0 - 255]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int8&lt;/code&gt; - R’s built-in integer type. Checked to be within range [-128, 127]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hex8&lt;/code&gt; - 2 character hexadecimal representation of a &lt;code&gt;uint8&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;16 bit
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uint16&lt;/code&gt; - R’s built-in integer type. Checked to be within range [0 - 2^16-1]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int16&lt;/code&gt; - R’s built-in integer type. Checked to be within range [-2^15, 2^15-1]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hex16&lt;/code&gt; - 4 character hexadecimal representation of a &lt;code&gt;uint16&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;24 bit
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uint24&lt;/code&gt; - R’s built-in integer type. Checked to be within range [0 - 2^24-1]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hex24&lt;/code&gt; - 6 character hexadecimal representation of a &lt;code&gt;uint24&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;32 bit
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;int32&lt;/code&gt; - R’s built-in integer type&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install minitypes from github with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/minitypes&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;r &amp;lt;- as.raw(c(1, 2, 0, 255))

raw_to_uint8(r)
[1]   1   2   0 255

raw_to_uint16(r, endian = &amp;#39;little&amp;#39;)
[1]   513 65280

int32_to_raw(1L, endian = &amp;#39;big&amp;#39;)
[1] 00 00 00 01

raw_to_bitstring(r)
[1] &amp;quot;00000001000000100000000011111111&amp;quot;

logical_to_raw(c(T, F, F), pad = &amp;#39;left&amp;#39;)
logical_to_raw(): padding logical_vec length to a multiple of 8.
[1] 04

convert_type(&amp;quot;1111111100010011&amp;quot;, src_type=&amp;#39;bitstring&amp;#39;, dst_type=&amp;#39;uint8&amp;#39;)
[1] 255  19

convert_type(c(1L, 2L, 3L), src_type = &amp;#39;int32&amp;#39;, dst_type = &amp;#39;uint8&amp;#39;, endian = &amp;#39;big&amp;#39;)
 [1] 0 0 0 1 0 0 0 2 0 0 0 3

bitstring_to_logical(&amp;quot;100 011&amp;quot;)
[1]  TRUE FALSE FALSE FALSE  TRUE  TRUE

int32_to_bitstring(1L, endian = &amp;#39;big&amp;#39;)
[1] &amp;quot;00000000000000000000000000000001&amp;quot;

int32_to_bitstring(1L, endian = &amp;#39;little&amp;#39;)
[1] &amp;quot;00000001000000000000000000000000&amp;quot;

int32_to_bitstring(1L, endian = &amp;#39;little&amp;#39;, first_bit = &amp;#39;lsb&amp;#39;)
[1] &amp;quot;10000000000000000000000000000000&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;useless-tricks---na_integer_-na_character_-bit-representation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Useless tricks - &lt;code&gt;NA_integer_&lt;/code&gt; &amp;amp; &lt;code&gt;NA_character_&lt;/code&gt; bit representation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;NA_integer_&lt;/code&gt; and &lt;code&gt;NA_character_&lt;/code&gt; are just specific bit patterns within each of
those types.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;convert_type(NA_integer_, &amp;#39;int32&amp;#39;, &amp;#39;bitstring&amp;#39;, endian = &amp;#39;big&amp;#39;, first_bit = &amp;#39;msb&amp;#39;)
[1] &amp;quot;10000000000000000000000000000000&amp;quot;

convert_type(NA_character_, &amp;#39;chr&amp;#39;, &amp;#39;bitstring&amp;#39;, endian = &amp;#39;big&amp;#39;, first_bit = &amp;#39;msb&amp;#39;)
[1] &amp;quot;0100111001000001&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;worked-example---parsing-a-colour-table-from-a-gif&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Worked Example - Parsing a colour table from a ‘gif’&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Read in a GIF file as raw bytes (GIF data is stored in little endian format)&lt;/li&gt;
&lt;li&gt;Manually parse the GIF header (see e.g. &lt;a href=&#34;http://www.onicos.com/staff/iz/formats/gif.html&#34;&gt;GIF format&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Parse out the global colour table and plot the palette&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A scarlet tanager!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gif_filename &amp;lt;- &amp;quot;../../static/img/minitypes/bird.gif&amp;quot;
gif          &amp;lt;- readBin(gif_filename, &amp;#39;raw&amp;#39;, n = file.size(gif_filename))

head(gif, 50)
 [1] 47 49 46 38 39 61 e0 01 40 01 f7 00 00 03 02 02 0c 0b 03 0a 06 07 13 0b 05
[26] 14 13 03 1c 1b 04 1d 1b 0b 18 16 07 0b 0a 17 13 0e 19 18 15 19 0e 11 09 38&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/minitypes/bird.gif&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Subset out the header components and convert to the correct type
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw_to_chr(gif[1:6])  # &amp;quot;GIF89a&amp;quot; (text)
[1] &amp;quot;GIF89a&amp;quot;

raw_to_uint16(gif[7:8], endian = &amp;#39;little&amp;#39;)  # width (integer)
[1] 480

raw_to_uint16(gif[9:10], endian = &amp;#39;little&amp;#39;)  # height (integer)
[1] 320

# Is a global colour table present?
colour_table_info &amp;lt;- raw_to_uint8(gif[11])  
if (bitwAnd(colour_table_info, 128L)) { print(&amp;quot;GCT present&amp;quot;) }
[1] &amp;quot;GCT present&amp;quot;

# read 255 RGB triplets has 6-char-hex (i.e. hex24) starting at position 14
colour_table &amp;lt;- raw_to_hex24(gif[seq_len(255*3) + 13L], endian = &amp;#39;big&amp;#39;)
colour_table &amp;lt;- sort(paste0(&amp;#39;#&amp;#39;, colour_table))

head(colour_table)
[1] &amp;quot;#030202&amp;quot; &amp;quot;#0a0607&amp;quot; &amp;quot;#0b0a17&amp;quot; &amp;quot;#0c0b03&amp;quot; &amp;quot;#0d1226&amp;quot; &amp;quot;#0e1025&amp;quot;

image(x = 1, y = 1:255, z = matrix(1:255, nrow = 1), col = colour_table, axes = FALSE, ann = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-11-06-minitypes-package_files/figure-html/gif-colour-table-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>facet_inception()</title>
      <link>https://coolbutuseless.github.io/2018/10/31/facet_inception/</link>
      <pubDate>Wed, 31 Oct 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/31/facet_inception/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;facetting-a-facetted-facet-ggplot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;facetting a facetted facet ggplot&lt;/h2&gt;
&lt;p&gt;In this post, I use &lt;a href=&#34;https://github.com/thomasp85/patchwork&#34;&gt;patchwork&lt;/a&gt; to nest
three levels of facetted ggplots.&lt;/p&gt;
&lt;p&gt;The plots shown below are:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;The diamonds data set: price vs carat&lt;/li&gt;
&lt;li&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;, then facetted within each &lt;code&gt;cut&lt;/code&gt; by &lt;code&gt;color&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;, then facetted within each &lt;code&gt;cut&lt;/code&gt; by &lt;code&gt;color&lt;/code&gt;, then each of those facets are factted by &lt;code&gt;clarity&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;core-plot-function&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;core plot function&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is the core plot that will be used at different facetting levels
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
create_plot &amp;lt;- function(.data, title = &amp;quot;Diamonds&amp;quot;, theme_size = 12) {
  ggplot(.data) + 
      geom_point(aes(carat, price, color=cut), alpha = 0.3, size = 0.3) + 
      theme_bw() + 
      labs(title = title) + 
      theme_bw(theme_size) +
      theme(axis.text = element_blank(), legend.position = &amp;#39;none&amp;#39;) + 
      scale_color_manual(values = c(&amp;#39;Fair&amp;#39;=&amp;quot;#1B9E77&amp;quot;, &amp;#39;Good&amp;#39;=&amp;quot;#D95F02&amp;quot;, &amp;#39;Very Good&amp;#39;=&amp;quot;#7570B3&amp;quot;, 
                                    &amp;#39;Premium&amp;#39;=&amp;quot;#E7298A&amp;quot;, &amp;#39;Ideal&amp;#39;=&amp;quot;#66A61E&amp;quot;))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_plot(diamonds)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork-facet-inception/diamonds.png&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;facet_inception&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;facet_inception()&lt;/code&gt;&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Create a nested facetted plot
#&amp;#39;
#&amp;#39; @param .data data.frame
#&amp;#39; @param cols character vector of columns to use for facetting
#&amp;#39; @param title title for plot
#&amp;#39; @param theme_size the base size for the theme
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
facet_inception &amp;lt;- function(.data, cols, title = NULL, theme_size) {
  if (length(cols) == 1) {
    create_plot(.data, title, theme_size) +
      facet_wrap(cols[1], labeller = label_both) 
  } else {
    this_col &amp;lt;- cols[1]
    cols     &amp;lt;- cols[-1]
    sub_data &amp;lt;- split(.data, .data[[this_col]])
    sub_plots &amp;lt;- sub_data %&amp;gt;% 
      purrr::imap(~facet_inception(.x, cols, paste(title, paste0(this_col, &amp;#39;: &amp;#39;, .y), collapse = &amp;quot;, &amp;quot;), theme_size = theme_size))
    patchwork::wrap_plots(sub_plots)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;the-diamonds-data-set-price-vs-carat---facetted-by-cut.&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;.&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;facet_inception(diamonds, c(&amp;#39;cut&amp;#39;), theme_size = 12)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork-facet-inception/diamonds-cut.png&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-diamonds-data-set-price-vs-carat---facetted-by-cut-then-facetted-within-each-cut-by-color&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;, then facetted within each &lt;code&gt;cut&lt;/code&gt; by &lt;code&gt;color&lt;/code&gt;&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;facet_inception(diamonds, c(&amp;#39;cut&amp;#39;, &amp;#39;color&amp;#39;), theme_size = 12)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork-facet-inception/diamonds-cut-color.png&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-diamonds-data-set-price-vs-carat---facetted-by-cut-then-facetted-within-each-cut-by-color-then-each-of-those-facets-are-factted-by-clarity.&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;The diamonds data set: price vs carat - facetted by &lt;code&gt;cut&lt;/code&gt;, then facetted within each &lt;code&gt;cut&lt;/code&gt; by &lt;code&gt;color&lt;/code&gt;, then each of those facets are factted by &lt;code&gt;clarity&lt;/code&gt;.&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;facet_inception(diamonds, c(&amp;#39;cut&amp;#39;, &amp;#39;color&amp;#39;, &amp;#39;clarity&amp;#39;), theme_size = 4)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork-facet-inception/diamonds-cut-color-clarity.png&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;animated-gif&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Animated Gif&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork-facet-inception/diamonds.gif&#34; width=&#34;100%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Creating fractals with ggplot2 and patchwork</title>
      <link>https://coolbutuseless.github.io/2018/10/30/creating-fractals-with-ggplot2-and-patchwork/</link>
      <pubDate>Tue, 30 Oct 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/30/creating-fractals-with-ggplot2-and-patchwork/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;creating-fractals-with-ggplot2-and-patchwork&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating fractals with &lt;code&gt;ggplot2&lt;/code&gt; and &lt;code&gt;patchwork&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Today in my ongoing quest to generate fractals in Rstats using every available avenue: creating a Sierpinski Triangle and Sierpinski Carpet using &lt;a href=&#34;https://github.com/thomasp85/patchwork&#34;&gt;patchwork&lt;/a&gt; to layout reptitions of 2 simple plots.&lt;/p&gt;
&lt;p&gt;Methods for generating fractals so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski Triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/&#34;&gt;Another sierpinski triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski triangle using character strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices---sierpinski-carpet/&#34;&gt;Using R matrices to create a sierpinski carpet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/06/hilbert-curves/&#34;&gt;Generating hilbert curves with an ad-hoc L-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/07/barnsley-ferns-fractal/&#34;&gt;Barnsley ferns generated by iterated affine transformations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/09/ikeda-map-fractal/&#34;&gt;Ikeda map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today:&lt;/strong&gt; Use &lt;code&gt;patchwork&lt;/code&gt; to iteratively composite two basic plots into Sierpinski Triangle and Sierpinski Carpet&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;background&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/thomasp85/patchwork&#34;&gt;patchwork&lt;/a&gt; is a great library written by &lt;a href=&#34;https://twitter.com/thomasp85&#34;&gt;Thomas Lin Pedersen&lt;/a&gt; for compositing multiple plots.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/Atsushi776&#34;&gt;Atusy&lt;/a&gt; on twitter &lt;a href=&#34;https://twitter.com/Atsushi776/status/1056853873405526016&#34;&gt;posted a golden spiral&lt;/a&gt; created from multiple plots using &lt;code&gt;patchwork&lt;/code&gt;
and posted his code &lt;a href=&#34;https://gist.github.com/atusy/f3aa8161b9a4093e04745529679418fa&#34;&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This inspired me to continue my series on creating fractals out of constructs in R.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;setup&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;Create the plots to use as the building blocks of the fractals&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A blank plot&lt;/li&gt;
&lt;li&gt;A plot with a single rectangle&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a blank plot
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
b &amp;lt;- ggplot() + 
  annotate(&amp;#39;rect&amp;#39;, xmin=0, ymin=0, xmax=1, ymax=1, fill=NA) +
  theme_void() 


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define a plot with just a rectangle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot() + 
  annotate(&amp;#39;rect&amp;#39;, xmin=0, ymin=0, xmax=1, ymax=1) + 
  theme_void()

p&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-30-patchwork-fractal_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sierpinski-triangle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sierpinski Triangle&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function to stack + pack a single plot onto itself
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
f &amp;lt;- function(p) {
  wrap_plots(
    wrap_plots(b, p, b, widths = c(0.5, 1, 0.5)),
    wrap_plots(p, p),
    ncol = 1L
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f(p)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-30-patchwork-fractal_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f(f(p))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-30-patchwork-fractal_files/figure-html/unnamed-chunk-3-2.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Rendered offline. Takes about 15 minutes to render/save the plot object
f(f(f(f(f(f(f((p))))))))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork/patchwork-fractal-7.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sierpinski-carpet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sierpinski Carpet&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a 3x3 grid repetition of the given plot, but leave a blank plot in the middle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
f &amp;lt;- function(p) wrap_plots(p, p, p, p, b, p, p, p, p, ncol = 3L)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f(p)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-30-patchwork-fractal_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f(f(p))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-30-patchwork-fractal_files/figure-html/unnamed-chunk-6-2.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Rendered offline. Takes about 20 minutes to render/save the plot object
f(f(f(f(p))))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/patchwork/carpet-4.png&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>engroupify: A function to transform other functions to be aware of dplyr groups</title>
      <link>https://coolbutuseless.github.io/2018/10/11/engroupify-a-function-to-transform-other-functions-to-be-aware-of-dplyr-groups/</link>
      <pubDate>Thu, 11 Oct 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/11/engroupify-a-function-to-transform-other-functions-to-be-aware-of-dplyr-groups/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;I needed to create a special mutate function that uses the dplyr groups
if they’re defined, otherwise it should calculate over the entire data.&lt;/p&gt;
&lt;p&gt;I couldn’t find anything online on how to do this, so I came with a solution.&lt;/p&gt;
&lt;p&gt;It doesn’t seem there’s a blessed/sanctioned way of doing this.&lt;/p&gt;
&lt;p&gt;I worked out the method to use in &lt;a href=&#34;https://coolbutuseless.github.io/2018/10/09/writing-a-function-which-respects-dplyrgroup_by/&#34;&gt;my previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then I realised I wanted to do this to a few other functions, so I thought
I’d have a shot at making a function that converts other functions into ones
which respect dplyr groups.&lt;/p&gt;
&lt;div id=&#34;example-function-reverse-the-order-of-rows-of-a-data.frame&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example function: Reverse the order of rows of a data.frame&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Simple function to flip the order of rows in a data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
flip &amp;lt;- function(.data, ...) {
  .data[rev(seq(nrow(.data))), , drop=FALSE]
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mtcars %&amp;gt;%
  head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 11
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The entire data is flipped (as expected). 
# Nothing special has been done with groups
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mtcars %&amp;gt;%
  head() %&amp;gt;% 
  group_by(am) %&amp;gt;%
  flip()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 11
# Groups:   am [2]
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
1  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1
2  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
3  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
4  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
5  21       6   160   110  3.9   2.88  17.0     0     1     4     4
6  21       6   160   110  3.9   2.62  16.5     0     1     4     4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;engroupify&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;engroupify()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;engroupify()&lt;/code&gt; function takes a function name as an argument, and returns
a new version of the function which takes any dplyr groups into account&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Make a function which operates on data.frames respect dplyr `group_by()`
#&amp;#39;
#&amp;#39; @param fsym function name as a symbol which takes &amp;#39;.data&amp;#39; as its first argument
#&amp;#39; 
#&amp;#39; @return new function which respects dplyr groups
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
engroupify &amp;lt;- function(fsym) {
  
  fname &amp;lt;- rlang::ensym(fsym)

  new_body &amp;lt;- bquote({
      if (dplyr::is_grouped_df(.data)) {
        indices &amp;lt;- group_indices(.data)
        .data   &amp;lt;- do(.data, .(fname)(., ...))
        .data  &amp;lt;- .data[order(order(indices)), , drop = FALSE]
        return(.data)
      }

      .(fname)(.data, ...)
  })
  
  rlang::new_function(rlang::fn_fmls(fsym), new_body)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a new version of flip which respects dplyr groups
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gflip &amp;lt;- engroupify(flip)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The intial data
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mtcars %&amp;gt;%
  head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 11
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using the new `gflip()` function to flip the data within groups!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mtcars %&amp;gt;%
  head() %&amp;gt;%
  group_by(am) %&amp;gt;%
  gflip()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 11
# Groups:   am [2]
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt;
1  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4
3  21       6   160   110  3.9   2.62  16.5     0     1     4     4
4  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2
6  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Still hoping to find out how this should be done properly within dplyr.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Writing a function which respects `dplyr::group_by()`</title>
      <link>https://coolbutuseless.github.io/2018/10/09/writing-a-function-which-respects-dplyrgroup_by/</link>
      <pubDate>Tue, 09 Oct 2018 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/09/writing-a-function-which-respects-dplyrgroup_by/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;I need to create a special mutate function that uses the dplyr groups
if they’re defined, otherwise it should calculate over the entire data.&lt;/p&gt;
&lt;p&gt;I couldn’t find anything online on how to do this, so I’ve come with a solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does anyone know the correct/sanctioned way of handling this?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thanks to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;romainfrancois for pointing out that the ‘indices’ attribute is undocumented, and
I should use ‘group_indices()’ instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;the-naive-function-totally-unaware-of-grouping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The naive function (totally unaware of grouping)&lt;/h2&gt;
&lt;p&gt;For this example, I’m writing a clone of &lt;code&gt;dplyr::add_tally()&lt;/code&gt; called &lt;code&gt;add_n()&lt;/code&gt;&lt;br /&gt;
(my real problem is much more complicated).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_n &amp;lt;- function(df) {
  df$n &amp;lt;- nrow(df)
  df
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This function works great on an ungrouped dataset…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  head() %&amp;gt;%
  add_n()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 12
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb     n
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4     6
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4     6
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1     6
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1     6
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2     6
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1     6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… but on a grouped data set I don’t get the counting done &lt;em&gt;per group&lt;/em&gt;, just the
overall count.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  head() %&amp;gt;%
  group_by(cyl) %&amp;gt;%
  add_n()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 12
# Groups:   cyl [3]
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb     n
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4     6
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4     6
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1     6
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1     6
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2     6
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1     6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-group-aware-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The group-aware function&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_n &amp;lt;- function(df) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If df is grouped, then use &amp;#39;do()&amp;#39; to apply the function to all groups.
  # Note: As the data is re-organised by the grouping variable(s) during the 
  #       &amp;#39;do()&amp;#39;, use the group_indices() to put the data back in the original order 
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (dplyr::is_grouped_df(df)) {
    indices &amp;lt;- group_indices(df) 
    df      &amp;lt;- do(df, add_n(.)) 
    df      &amp;lt;- df[order(order(indices)), , drop = FALSE]
    return(df)
  } 
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # This is just the body of the naive version of the function
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  df$n &amp;lt;- nrow(df)
  df
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This function works great on an ungrouped dataset…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  head() %&amp;gt;%
  add_n()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 12
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb     n
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4     6
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4     6
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1     6
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1     6
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2     6
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1     6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… and also works properly to create per-group counts, with the data kept in
its original order.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% 
  head() %&amp;gt;%
  group_by(cyl) %&amp;gt;%
  add_n()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 6 x 12
# Groups:   cyl [3]
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb     n
  &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
1  21       6   160   110  3.9   2.62  16.5     0     1     4     4     4
2  21       6   160   110  3.9   2.88  17.0     0     1     4     4     4
3  22.8     4   108    93  3.85  2.32  18.6     1     1     4     1     1
4  21.4     6   258   110  3.08  3.22  19.4     1     0     3     1     4
5  18.7     8   360   175  3.15  3.44  17.0     0     0     3     2     1
6  18.1     6   225   105  2.76  3.46  20.2     1     0     3     1     4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `memoisetools` package</title>
      <link>https://coolbutuseless.github.io/2018/10/08/introducing-the-memoisetools-package/</link>
      <pubDate>Mon, 08 Oct 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/08/introducing-the-memoisetools-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;memoisetools-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;memoisetools&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;memoisetools&lt;/code&gt; is a collection of additional caches and helper functions to
work alongside the &lt;a href=&#34;https://github.com/r-lib/memoise&#34;&gt;&lt;code&gt;memoise&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This package introduces new caches, new &lt;code&gt;memoise()&lt;/code&gt; alternatives and functions
for interrogating caches and expiring old objects from a cache.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New caches:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cache_filesystem2()&lt;/code&gt; - with object timestamping, compression
of objects by default, and expiration of results not accessed for a certain time.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cache_memory2()&lt;/code&gt; - with object timestamping, faster &lt;code&gt;xxhash64&lt;/code&gt;
used by default, and expiration of results not accessed for a certain time.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;New &lt;code&gt;memoise::memoise()&lt;/code&gt; alternatives
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;memoise_with_result_size_limit()&lt;/code&gt; - only store results below a certain
size in the cache&lt;/li&gt;
&lt;li&gt;&lt;code&gt;memoise_with_mixed_backend()&lt;/code&gt; - have 2 caches in a memoised function, with
small results saved in the first cache, and large objects saved in the
second cache.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Helper functions
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;get_memoise_info()&lt;/code&gt; - to print and return information about the cache(s)
of a memoised function e.g. how many objects, total size, etc&lt;/li&gt;
&lt;li&gt;&lt;code&gt;expire_cache()&lt;/code&gt; - If the cache for a memoised functionhas a timestamp,
then this function will deleted cached results older than the specified age&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/memoisetools&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;get_memoise_info&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;get_memoise_info()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;get_memoise_info()&lt;/code&gt; returns information about the caches used by a memoised function.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cache&lt;/code&gt; - Cache type. Either ‘memory’, ‘filesystem’ or ‘gcs or aws’&lt;/li&gt;
&lt;li&gt;Storage location
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;env&lt;/code&gt; - For ‘memory’ cache, the R environment in which objects are stored&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path&lt;/code&gt; - For ‘filesystem’ caches, the path to the cache directory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cache_name&lt;/code&gt; - For ‘gcs or aws’ caches, the name of the cache&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;algo&lt;/code&gt; - Hashing algorithm for creating keys&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bytes&lt;/code&gt; - Size (in bytes) of the cache&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n&lt;/code&gt; - Number of objects in the cache&lt;/li&gt;
&lt;li&gt;&lt;code&gt;has_timestamp&lt;/code&gt; - Does the cache include timestamp information?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compress&lt;/code&gt; - Value for ‘compress’ variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: because memoised functions could have multiple caches (e.g. &lt;code&gt;memoise_with_mixed_backend&lt;/code&gt;),
this function returns a list of info for each cache.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;memoised_rnorm &amp;lt;- memoise::memoise(rnorm)

x &amp;lt;- memoised_rnorm(1000)
y &amp;lt;- memoised_rnorm(12)
z &amp;lt;- memoised_rnorm(1)

memoisetools::get_memoise_info(memoised_rnorm)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Registered S3 method overwritten by &amp;#39;pryr&amp;#39;:
  method      from
  print.bytes Rcpp&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;cache: memory, env: &amp;lt;environment&amp;gt;, algo: sha512, bytes: 9728, n: 3, has_timestamp: FALSE, compress: FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;cache_filesystem2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cache_filesystem2()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is a replacement for &lt;code&gt;memoise::cache_filesystem()&lt;/code&gt; with the following changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use a &lt;code&gt;tempdir()&lt;/code&gt; if no path specified&lt;/li&gt;
&lt;li&gt;Full absolute path to cache is used, even if initialised with a relative path.&lt;br /&gt;
This avoids issues as detailed in this &lt;a href=&#34;https://github.com/r-lib/memoise/issues/51#issuecomment-319993161&#34;&gt;memoise issue on github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;By default objects saved to filesystem are compressed using gzip compression.
(The corresponding &lt;a href=&#34;https://github.com/r-lib/memoise/pull/70&#34;&gt;memoise PR on github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A separate data structure keeps track of the time of all reads/writes to the cache.&lt;/li&gt;
&lt;li&gt;The addition of timestamps allows for expiring objects older than a certain age.
See the function &lt;code&gt;memoisetools::expire_cache()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the cache &lt;code&gt;has_key&lt;/code&gt; method now uses the timestamp cache to determine if a given
key exists or not. This makes it faster to check if a key exists (as no filesystem
access is needed), but will cause an error if they file doesn’t &lt;em&gt;actually&lt;/em&gt; exist
e.g. if you’ve deleted the file manually.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;cache_memory2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cache_memory2()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is a replacement for &lt;code&gt;memoise::cache_memory()&lt;/code&gt; with the following changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A separate data structure keeps track of the time of all reads/writes to the cache.&lt;/li&gt;
&lt;li&gt;The addition of timestamps allows for expiring objects older than a certain age.
See the function &lt;code&gt;memoisetools::expire_cache()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use the faster hash &lt;code&gt;xxhash64&lt;/code&gt; by default&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;expiring-objects-from-the-cache&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Expiring objects from the cache&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;cache_filesystem2()&lt;/code&gt; and &lt;code&gt;cache_memory2()&lt;/code&gt;, objects older than a specified
age can be retired from the cache. I.e. if they have not been read or written
more recently than the specified time, they will be deleted.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;memoised_rnorm &amp;lt;- memoise::memoise(rnorm, cache = memoisetools::cache_memory2()) 

memoised_rnorm(1) # stored in cache. 
[1] -1.450964
memoised_rnorm(2) # stored in cache
[1]  0.3509097 -0.1745469
Sys.sleep(1)      # wait a little bit
memoised_rnorm(1) # recent access to this cached data means it won&amp;#39;t be expired
[1] -1.450964

# The following expiry will only delete the cached result for `memoised_rnorm(2)`
# as it has not been read/written in over 1 second
memoisetools::expire_cache(memoised_rnorm, age_in_seconds = 1, verbose = TRUE)
cache_memory2: Expired 1 objects

memoised_rnorm(1) # this result is still in the cache
[1] -1.450964
memoised_rnorm(2) # this is a fresh result as the cached version was removed
[1] -0.5914285 -1.3340273&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;memoise_with_result_size_limit&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;memoise_with_result_size_limit()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is a replacement for &lt;code&gt;memoise::memoise()&lt;/code&gt; which places a limit on how large
an object can be before it is no longer stored in the cache (but simply recalculated
each time).&lt;/p&gt;
&lt;p&gt;By default, &lt;code&gt;memoise::memoise()&lt;/code&gt; will store all results regardless of size.
This works for the majority of cases where you have enough memory and results
are never too large.&lt;/p&gt;
&lt;p&gt;For the problem I was working on, the function produced many small results and a few very very large results
(greater than 2GB is size). If all the big results were cached I’d run out of memory!&lt;/p&gt;
&lt;p&gt;In the following example, results over 1000 bytes will not be cached.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;memoised_rnorm &amp;lt;- memoisetools::memoise_with_result_size_limit(rnorm, result_size_limit = 1000)

memoised_rnorm(1) # small enough to cache
[1] -1.097299
memoised_rnorm(1) # getting cached result
[1] -1.097299

head(memoised_rnorm(1000)) # too big to be cached
[1]  2.0361036 -0.3264896  0.7740052  0.7850064  0.7632461  0.2948088
head(memoised_rnorm(1000)) # so each run produces fresh result
[1]  1.4251896 -1.7347494 -0.8374046 -0.7157526  0.3748210  2.3833280&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;memoise_with_mixed_backend&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;memoise_with_mixed_backend()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is an adjusted version of &lt;code&gt;memoise::memoise()&lt;/code&gt; which requires &lt;strong&gt;two&lt;/strong&gt; caches
to be set, along with a &lt;strong&gt;size limit&lt;/strong&gt;. Objects smaller than the size limit go
to the first cache, and objects larger than the size limit go to the second cache.&lt;/p&gt;
&lt;p&gt;This allows you to cache small results in memory, and send large results to the
filesystem, s3 or google cloud storage.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;memoised_rnorm &amp;lt;- memoisetools::memoise_with_mixed_backend(
  rnorm,
  cache1 = memoisetools::cache_memory2(),
  cache2 = memoisetools::cache_filesystem2(),
  result_size_limit = 1000
)

a &amp;lt;- memoised_rnorm(1) # These 3 results cached to memory
b &amp;lt;- memoised_rnorm(2)
c &amp;lt;- memoised_rnorm(3)

x &amp;lt;- memoised_rnorm(1000)  # These 2 results cached to filesystem
y &amp;lt;- memoised_rnorm(2000)

memoisetools::get_memoise_info(memoised_rnorm)
cache: memory, env: &amp;lt;environment&amp;gt;, algo: xxhash64, bytes: 1648, n: 3, has_timestamp: TRUE, compress: FALSE
cache: filesystem, path: /private/var/folders/5p/78cv9fvn4xn_rbgxpx51q5n80000gn/T/Rtmp4L9t5x, algo: xxhash64, bytes: 23315, n: 2, has_timestamp: TRUE, compress: TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;todo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ToDo&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Once the &lt;a href=&#34;https://github.com/jimhester/archive&#34;&gt;&lt;code&gt;archive&lt;/code&gt; package&lt;/a&gt; matures
a little, a more extensive suite of compression options would be great i.e.
using lz4 and zstd compression.&lt;/li&gt;
&lt;li&gt;Proper support for Google Cloud Storage and Amazon S3 backends in &lt;code&gt;get_cache_info()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;More tools for manipulating caches?
&lt;ul&gt;
&lt;li&gt;Delete all objects over a certain size.&lt;/li&gt;
&lt;li&gt;Delete oldest objects in order to keep the cache under a certain size.&lt;/li&gt;
&lt;li&gt;Cache the object size as the results are created and cached? (so we don’t recalculate it
each time &lt;code&gt;get_cache_info()&lt;/code&gt; is called)&lt;/li&gt;
&lt;li&gt;Move caches between backends e.g. move a filesystem cache to memory.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Using LZ4 and Zstandard to compress files with `saveRDS()`</title>
      <link>https://coolbutuseless.github.io/2018/10/02/using-lz4-and-zstandard-to-compress-files-with-saverds/</link>
      <pubDate>Tue, 02 Oct 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/02/using-lz4-and-zstandard-to-compress-files-with-saverds/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;serializing-objects-to-file&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Serializing objects to file&lt;/h2&gt;
&lt;p&gt;A standard way to serialize R objects to file is to use &lt;code&gt;saveRDS()&lt;/code&gt; and &lt;code&gt;readRDS()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A number of standard compression schemes are offered withni &lt;code&gt;saveRDS()&lt;/code&gt; in order to save disk space,
I’ve swiped some benchmarks from &lt;a href=&#34;https://www.rootusers.com/gzip-vs-bzip2-vs-xz-performance-comparison/&#34;&gt;here&lt;/a&gt;
and pulled out the numbers corresponding to the default options in R&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gzip&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;fast, but no very efficient&lt;/li&gt;
&lt;li&gt;Default compression level in &lt;code&gt;gzfile()&lt;/code&gt;: 6&lt;/li&gt;
&lt;li&gt;Compression/decompression speeds: 19 MB/s and 95 MB/s respecively&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bzip2&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;slower than gzip, but better compression&lt;/li&gt;
&lt;li&gt;Default compression level in &lt;code&gt;bzfile()&lt;/code&gt;: 9&lt;/li&gt;
&lt;li&gt;Compression/decompression speeds: 7 MB/s and 24 MB/s respecively&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xz&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;very very slow. great compression&lt;/li&gt;
&lt;li&gt;Default compression level in &lt;code&gt;xzfile()&lt;/code&gt;: 6&lt;/li&gt;
&lt;li&gt;Compression/decompression speeds: 1.4 MB/s and 53 MB/s respecively&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;new-compression-algorithms---lz4-and-zstandard&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;New compression algorithms - LZ4 and Zstandard&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;LZ4&lt;/code&gt; and &lt;code&gt;Zstandard&lt;/code&gt; are two recent compression schemes. Both are &lt;strong&gt;very&lt;/strong&gt; fast and
highly configurable in terms of the compression/speed tradeoffs they offer.&lt;/p&gt;
&lt;p&gt;Because they’re not benchmarked on the same corpus, the compression/decompression
speeds should be compared with caution, but they’re both easily an order of magnitude
faster than gzip/bzip2/xz.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LZ4
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://lz4.github.io/lz4/&#34;&gt;LZ4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;has compression/decompression speeds of 750 MB/s and 3700 MB/s respectively&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Zstd
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://facebook.github.io/zstd/&#34;&gt;Zstandard&lt;/a&gt; is a facebook project&lt;/li&gt;
&lt;li&gt;has a better compression ratio than LZ4&lt;/li&gt;
&lt;li&gt;has compression/decompression speeds of 470 MB/s, 1380 MB/s&lt;/li&gt;
&lt;li&gt;is tunable to run as fast as gzip or as high a compression as xz (almost).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;the-archive-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;archive&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/jimhester_&#34;&gt;jimhester&lt;/a&gt; has a work-in-progress package called
&lt;a href=&#34;https://github.com/jimhester/archive&#34;&gt;&lt;code&gt;archive&lt;/code&gt;&lt;/a&gt; which is a wrapper around the very
capable &lt;a href=&#34;https://libarchive.org&#34;&gt;&lt;code&gt;libarchive&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/jimhester/archive&#34;&gt;archive&lt;/a&gt; package then lets you create
standard R &lt;code&gt;connection&lt;/code&gt; objects that do inline compression of the data using
&lt;code&gt;libarchive&lt;/code&gt;. You can then use these &lt;code&gt;connection&lt;/code&gt; objects in any file function
that supports them e.g. &lt;code&gt;saveRDS()&lt;/code&gt;, &lt;code&gt;write.csv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libarchive&lt;/code&gt; itself supports a very wide range of archvie formats and compression schemes including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zstd&lt;/li&gt;
&lt;li&gt;lz4&lt;/li&gt;
&lt;li&gt;zip&lt;/li&gt;
&lt;li&gt;rar&lt;/li&gt;
&lt;li&gt;lzip&lt;/li&gt;
&lt;li&gt;lzma&lt;/li&gt;
&lt;li&gt;tar&lt;/li&gt;
&lt;li&gt;lha&lt;/li&gt;
&lt;li&gt;7-zip&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;savecrds-and-readcrds---writing-r-objects-with-compression&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;saveCRDS()&lt;/code&gt; and &lt;code&gt;readCRDS()&lt;/code&gt; - writing R objects with compression&lt;/h2&gt;
&lt;p&gt;In order to support writing compressed archives, I’ve written two simple wrapper
function which initialise a compressed connection and then use that with R’s
builtin serialisation functions (&lt;code&gt;saveRDS()&lt;/code&gt; and &lt;code&gt;readRDS()&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Currently there can be some flakiness with &lt;code&gt;archive&lt;/code&gt; when specifying formats/filters that aren’t
supported by the current compiled version of &lt;code&gt;libarchive&lt;/code&gt;. This can cause
segfaults, so I’m being extra paranoid about the formats/filters supported.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Write compressed RDS streams
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
saveCRDS &amp;lt;- function(object, filename, filter=NULL) {
  stopifnot(filter %in% c(&amp;#39;zstd&amp;#39;, &amp;#39;lz4&amp;#39;))
  con = archive::file_write(file = filename, filter=filter)
  open(con)
  saveRDS(object, con)
  close(con)
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Read compressed RDS streams
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
readCRDS &amp;lt;- function(filename) {
  con &amp;lt;- archive::file_read(file = filename)
  res &amp;lt;- readRDS(con)
  close(con)
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;saving-a-compressed-version-of-a-10-mb-low-complexity-matrix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Saving a compressed version of a 10 MB low complexity matrix&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Testing on highly compressible test data&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;N &amp;lt;- 3200
test_data &amp;lt;- matrix(sample(as.raw(c(0, 0, 1)), size=N*N, replace=TRUE), nrow=N, ncol=N)
pryr::object_size(test_data)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Registered S3 method overwritten by &amp;#39;pryr&amp;#39;:
  method      from
  print.bytes Rcpp&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10.2 MB&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_dir   &amp;lt;- tempdir()

res &amp;lt;- bench::mark(
  saveRDS (test_data, file     = file.path(test_dir, &amp;quot;test.rds&amp;quot;     ), compress = FALSE),
  saveRDS (test_data, file     = file.path(test_dir, &amp;quot;test.rds.gz&amp;quot;  ), compress = &amp;#39;gzip&amp;#39;),
  saveRDS (test_data, file     = file.path(test_dir, &amp;quot;test.rds.bz2&amp;quot; ), compress = &amp;#39;bzip2&amp;#39;),
  saveRDS (test_data, file     = file.path(test_dir, &amp;quot;test.rds.xz&amp;quot;  ), compress = &amp;#39;xz&amp;#39;),
  
  saveCRDS(test_data, filename = file.path(test_dir, &amp;#39;test.rds.lz4&amp;#39; ), filter=&amp;#39;lz4&amp;#39;),
  saveCRDS(test_data, filename = file.path(test_dir, &amp;#39;test.rds.zstd&amp;#39;), filter=&amp;#39;zstd&amp;#39;),
  
  min_time=2, check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-4&#34;&gt;Table 1: &lt;/span&gt;bench::mark() summary&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;compression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;filesize (MB)&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median time (s)&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;uncompressed&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.24&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.6ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;60.07&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.2KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gzip&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.60&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.5s&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.67&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.63KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;bzip2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.52&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;851.4ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.17&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.59KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xz&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.29&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.8s&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.07&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.59KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lz4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.90&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45.6ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.03&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.4KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zstd&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.94&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;59.7ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16.42&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.38MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The following is a plot of the &lt;code&gt;bench::mark()&lt;/code&gt; results on this data, with
compressed filesize on the x-axis, and the median compression time (in seconds)
on the y-axis (on a log scale).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-10-02-compressed-files_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;On &lt;strong&gt;this data&lt;/strong&gt;, running on &lt;strong&gt;my machine&lt;/strong&gt;, it appears:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;uncompressed data is saved in about 100th of a second&lt;/li&gt;
&lt;li&gt;to a first approximation, &lt;code&gt;xz&lt;/code&gt;, &lt;code&gt;gzip&lt;/code&gt;, &lt;code&gt;bzip2&lt;/code&gt; and &lt;code&gt;zstd&lt;/code&gt; all compress to roughly the same size (with their default compression levels)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lz4&lt;/code&gt; has the largest compressed filesize, but the fastest speed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xz&lt;/code&gt; has the smallest compressed filesize, but by far the longest compression time&lt;/li&gt;
&lt;li&gt;Compare to writing the uncompressed data
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lz4&lt;/code&gt; and &lt;code&gt;zstd&lt;/code&gt; are 3-5x slower&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bzip2&lt;/code&gt; and &lt;code&gt;gzip&lt;/code&gt; are ~2 orders of magnitude slower&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xz&lt;/code&gt; is ~3 orders of magnitude slower&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Expand the tests to cover more data sizes, and more complex data.&lt;/li&gt;
&lt;li&gt;There’s no configuration of LZ4/Zstandard compression options in &lt;code&gt;archive&lt;/code&gt; yet,
so there’s a whole range of time/compression tradeoffs that are currently
unavailable using these compression methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Memoisation</title>
      <link>https://coolbutuseless.github.io/2018/10/01/memoisation/</link>
      <pubDate>Mon, 01 Oct 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/10/01/memoisation/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;memoisation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Memoisation&lt;/h2&gt;
&lt;p&gt;Memoisation allows the caching of the output for a function for a given set of inputs.&lt;/p&gt;
&lt;p&gt;That is, for a set of arguments the result is only ever calculated &lt;em&gt;once&lt;/em&gt;
and then stored in a cache. If those set of arguments ever happen again, then the
result is pulled from the cache rather than the function being re-run.&lt;/p&gt;
&lt;p&gt;This technique is really useful when a function takes a long time to execute.&lt;/p&gt;
&lt;p&gt;There are at least 2 memoisation packages in R:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=memoise&#34;&gt;&lt;code&gt;memoise&lt;/code&gt;&lt;/a&gt; by
Hadley Wickham [aut], Jim Hester [aut, cre], Kirill Müller [aut], Daniel Cook [aut].&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=R.cache&#34;&gt;&lt;code&gt;R.cache&lt;/code&gt;&lt;/a&gt; by Henrik Bengtsson [aut, cre, cph]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will use &lt;code&gt;memoise&lt;/code&gt; simply because I’m more familiar with it.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;my-problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My problem&lt;/h2&gt;
&lt;p&gt;A part of my solution method for nonograms was to generate all possible patterns
for a particular row based upon the clues. (First discussed in &lt;a href=&#34;https://coolbutuseless.github.io/2018/09/20/find-all-sequences-of-a-given-length-with-the-given-sum/&#34;&gt;this post&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The problem boils down to the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Find all integer sequences (of the target length) which add to the target sum&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;integer&lt;/strong&gt; here means positive, non-zero whole number&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;target length&lt;/strong&gt; is
&lt;ul&gt;
&lt;li&gt;always greater than 1&lt;/li&gt;
&lt;li&gt;never greater than 35 (for the nonograms I’m attempting to solve)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;target sum&lt;/strong&gt; is never less than the &lt;strong&gt;target length&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Find all permutations of all vectors of positive integers of a given length 
#&amp;#39; which sum to a given value
#&amp;#39;
#&amp;#39; e.g. find_integers_with_sum(4, 2) gives
#&amp;#39;    1, 3
#&amp;#39;    2, 2
#&amp;#39;    3, 1
#&amp;#39;
#&amp;#39; @param target_length target length
#&amp;#39; @param target_sum target sum
#&amp;#39; @return matrix or raw values, with each row being a solution
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
find_integers_with_sum &amp;lt;- function(target_sum, target_length) {

  if (target_length == 1L) {
    return(matrix(as.raw(target_sum)))
  }

  max_choice &amp;lt;- target_sum - target_length + 1L
  solutions  &amp;lt;- vector(&amp;#39;list&amp;#39;, max_choice)
  lens       &amp;lt;- integer(max_choice)


  for (this_value in seq_len(max_choice)) {
    solution                &amp;lt;- find_integers_with_sum(target_sum - this_value, target_length - 1L)
    solutions[[this_value]] &amp;lt;- solution
    lens[this_value]        &amp;lt;- nrow(solution)
  }


  cbind(as.raw(rep.int(seq_len(max_choice), lens)), do.call(rbind, solutions), deparse.level = 0L)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_integers_with_sum(target_sum=4, target_length=2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2]
[1,]   01   03
[2,]   02   02
[3,]   03   01&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-challenge&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The challenge&lt;/h2&gt;
&lt;p&gt;When the &lt;code&gt;target_sum&lt;/code&gt; and &lt;code&gt;target_length&lt;/code&gt; get “large”, the number of solutions
becomes &lt;strong&gt;huge&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;find_integers_with_sum(25, 10)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;1,307,504 solutions&lt;/li&gt;
&lt;li&gt;10 seconds to generate.&lt;/li&gt;
&lt;li&gt;13MB matrix&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;find_integers_with_sum(30, 10)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;10 million solutions&lt;/li&gt;
&lt;li&gt;60 seconds to generate&lt;/li&gt;
&lt;li&gt;100MB matrix&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;find_integers_with_sum(35, 10)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;over 52 million solutions&lt;/li&gt;
&lt;li&gt;takes forever to generate (I’ve honestly never done it without memoising!)&lt;/li&gt;
&lt;li&gt;525MB matrix&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The way &lt;code&gt;find_integers_with_sums()&lt;/code&gt; recurses to find its solution means that it’s
calling itself in a nested way to solve smaller and smaller versions of the problem.&lt;/p&gt;
&lt;p&gt;This means that inner-most, smallest versions of the problem are solved mutiple
times, but are always producing the same result.&lt;/p&gt;
&lt;p&gt;This function will benefit from cacheing those inner results.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;memoisation-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Memoisation&lt;/h2&gt;
&lt;p&gt;To memoise this function, I will be using the &lt;a href=&#34;https://cran.r-project.org/package=memoise&#34;&gt;&lt;code&gt;memoise&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will consider three possible backends:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;In-memory&lt;/li&gt;
&lt;li&gt;Filesystem in RAM disk (on OSX)
&lt;ul&gt;
&lt;li&gt;diskutil erasevolume HFS+ ‘ramdisk’ &lt;code&gt;hdiutil attach -nomount ram://1165430&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Filesystem on SSD&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I will be using &lt;code&gt;find_integers_with_sum(30, 10)&lt;/code&gt; as my test case.&lt;/p&gt;
&lt;div id=&#34;no-cache&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;No cache&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Before doing anything else, I&amp;#39;m keeping a copy of the original un-cached function
find_integers_with_sum_ &amp;lt;- find_integers_with_sum

# run without memoisation
system.time({find_integers_with_sum(30, 10)})
system.time({find_integers_with_sum(30, 10)})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;in-memory-cache&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;In-memory cache&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_integers_with_sum  &amp;lt;- memoise(find_integers_with_sum_, cache = cache_memory())
system.time({find_integers_with_sum(30, 10)})
system.time({find_integers_with_sum(30, 10)})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;filesystem-on-ram-disk&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Filesystem on Ram disk&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;path &amp;lt;- &amp;quot;/Volumes/ramdisk&amp;quot;
unlink(path, recursive = TRUE)
find_integers_with_sum  &amp;lt;- memoise::memoise(find_integers_with_sum_, cache=cache_filesystem(path))
system.time({find_integers_with_sum(30, 10)})
system.time({find_integers_with_sum(30, 10)})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;filesystem-on-ssd&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Filesystem on SSD&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;path &amp;lt;- tempdir()
unlink(path, recursive = TRUE)
find_integers_with_sum  &amp;lt;- memoise::memoise(find_integers_with_sum_, cache=cache_filesystem(path))
system.time({find_integers_with_sum(30, 10)})
system.time({find_integers_with_sum(30, 10)})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;timing-summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Timing Summary&lt;/h2&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-8&#34;&gt;Table 1: &lt;/span&gt;Run times&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;cache&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;first_run&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;second_run&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;None&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;60.00&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;60.000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Memory&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.60&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Ram disk&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.28&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.130&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;SSD&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.46&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.130&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Memoise in memory just uses a standard R environment to store objects&lt;/li&gt;
&lt;li&gt;Memoise to filesystem uses &lt;code&gt;saveRDS()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Memory cache is fastest (obviously).&lt;/li&gt;
&lt;li&gt;No difference in speed between RAM disk and SSD
&lt;ul&gt;
&lt;li&gt;This may just be the SSD aggressively using its own disk cache? Not sure.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The filesystem cache in &lt;code&gt;memoise&lt;/code&gt; does not do any compression.
&lt;ul&gt;
&lt;li&gt;On slower drives, it may be worth compressing the data&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Consider trying the following modifications to &lt;code&gt;memoise&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Add compression option to the filesystem cache (and s3 and gcs caches)&lt;/li&gt;
&lt;li&gt;Revisit a way for caches to have limitations on the maximum size of a result
which gets cached. I tried this in a &lt;a href=&#34;https://coolbutuseless.github.io/2018/09/24/memoise-with-object-size-limit/&#34;&gt;recent post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Investigate a multi-tiered cache with small results saved to ram and bigger
results saved to the filesystem.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Writing a nonogram solver in R</title>
      <link>https://coolbutuseless.github.io/2018/09/28/writing-a-nonogram-solver-in-r/</link>
      <pubDate>Fri, 28 Sep 2018 19:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/28/writing-a-nonogram-solver-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;nonograms&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Nonograms&lt;/h2&gt;
&lt;p&gt;Nonograms are picture logic puzzles in which cells in a grid must be colored or
left blank according to numbers at the side of the grid to reveal a hidden picture.&lt;/p&gt;
&lt;p&gt;That is, the numbers on the side of the image (the &lt;em&gt;clues&lt;/em&gt;) are the
&lt;strong&gt;run-length encoding&lt;/strong&gt; of the filled-in squares for each row and column.&lt;/p&gt;
&lt;p&gt;By simultaneously satisfying the &lt;em&gt;clues&lt;/em&gt; for the rows and columns, a picture is revealed!&lt;/p&gt;
&lt;div style=&#34;float: left;&#34;&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-blank.png&#34; width=&#34;45%&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-solved.png&#34; width=&#34;45%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this short series of posts I will:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Introduce the nonogram package (&lt;a href=&#34;https://coolbutuseless.github.io/2018/09/26/nonograms-in-r---nonogram-package/&#34;&gt;previous post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Show how to make nonograms by hand, or from an existing image (&lt;a href=&#34;https://coolbutuseless.github.io/2018/09/27/creating-nonograms-with-nonogram-and-magick-packages/&#34;&gt;previous post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Describe the solution techniqe behind the package (this post).&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;the-nonogram-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;nonogram&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;nonogram&lt;/code&gt; package contains tools for plotting, solving and creating nonogram puzzles.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;nonogram&lt;/code&gt; from github with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/nonogram&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;nomenclature&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Nomenclature&lt;/h2&gt;
&lt;div id=&#34;clue&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;clue&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;A clue is sequence of integers which are the run-length encoding of the filled-in
squares in a row or column.&lt;/p&gt;
&lt;p&gt;E.g. &lt;strong&gt;&lt;code&gt;1,2&lt;/code&gt;&lt;/strong&gt; is a &lt;em&gt;clue&lt;/em&gt; which means that there is 1 filled-in square in this row
(or column) followed by some blank squares, and then two filled-in squares in a row&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;pattern&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;em&gt;pattern&lt;/em&gt; is a sequence of filled-in and blank squares which make up a row or
column.&lt;/p&gt;
&lt;p&gt;E.g. the clue &lt;code&gt;1,2&lt;/code&gt; (on a board 8 squares wide) is satisfied by each
of the following patterns, represented as a matrix and shown graphically&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    1    0    1    1    0    0    0
[2,]    0    0    1    0    0    1    1    0
[3,]    0    1    0    0    0    0    1    1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern-set&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;pattern set&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;em&gt;pattern set&lt;/em&gt; is the complete set of all possible patterns which satisfy a clue.&lt;/p&gt;
&lt;p&gt;E.g. the pattern set for the clue &lt;code&gt;2,3&lt;/code&gt; on a board 8 squares wide is shown below
as a matrix as well as graphically.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    1    1    0    1    1    1    0
[2,]    1    1    0    1    1    1    0    0
[3,]    1    1    0    0    1    1    1    0
[4,]    0    1    1    0    0    1    1    1
[5,]    0    0    1    1    0    1    1    1
[6,]    1    1    0    0    0    1    1    1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;pattern-sets&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;pattern sets&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;For each clue along the rows, and each clue along the columns, there is a &lt;em&gt;pattern set&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;row pattern sets&lt;/em&gt; is the collection of the &lt;em&gt;pattern set&lt;/em&gt;s for every row.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;column pattern sets&lt;/em&gt; is the collection of the &lt;em&gt;pattern set&lt;/em&gt;s for every column.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;puzzle&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;A puzzle is collection of clues, represented in the &lt;code&gt;nonogram&lt;/code&gt; package as a list of
vectors.&lt;/p&gt;
&lt;p&gt;E.g. the puzzle for the &lt;strong&gt;duck&lt;/strong&gt; image shown at the top is:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle &amp;lt;- list(
  row_clues = list(3L, 2:1, 3:2, c(2L, 2L), 6L, c(1L, 5L), 6L, 1L, 2L), 
  col_clues = list(1:2, c(3L, 1L), c(1L, 5L), c(7L, 1L), 5L, 3L, 4L, 3L)
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle-string&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;&lt;code&gt;puzzle string&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;For storage and transfer, it’s sometimes easier to deal with the puzzle just
as a string.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;puzzle string&lt;/em&gt; is a compact string representation of the puzzle.&lt;/p&gt;
&lt;p&gt;It consists of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the numbers for each clue separated by a comma&lt;/li&gt;
&lt;li&gt;each clue separated by a colon&lt;/li&gt;
&lt;li&gt;the row and column clues (in that order) separated by a dash&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an example, the following is the puzzle string for the &lt;strong&gt;duck&lt;/strong&gt; nonogram&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;quot;3:2,1:3,2:2,2:6:1,5:6:1:2-1,2:3,1:1,5:7,1:5:3:4:3&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-technique&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution technique&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;For each clue generate its pattern set&lt;/li&gt;
&lt;li&gt;Within each pattern set, find if any locations are a constant colour, and
use this fact to elimintate patterns in the other direction&lt;/li&gt;
&lt;li&gt;On the remaining (hopefully small) number of choices within each pattern set
for each clue, do a recursive search with back-tracking to find a solution&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-step-1-generate-all-possible-patterns-for-a-clue&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution step 1: Generate all possible patterns for a clue&lt;/h2&gt;
&lt;p&gt;This was the most difficult part of this solution technique, as the number of
possible combinations, and the resulting &lt;code&gt;pattern set&lt;/code&gt;, can be &lt;strong&gt;huge&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Most grids in print max out at about 35 squares along each side. There are plenty
of larger ones, but I optimised the solver only up to this size.&lt;/p&gt;
&lt;p&gt;For a small puzzle, like the &lt;strong&gt;duck&lt;/strong&gt; a the clue in the first column (&lt;code&gt;1,2&lt;/code&gt;) has
21 possible patterns I’ve plotted them below&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For the larger &lt;code&gt;gchq&lt;/code&gt; puzzle below, the clue &lt;code&gt;1,1,2,1,1,2&lt;/code&gt; to fit in the
puzzle width of 25 squares has 18,564 patterns, some of which are shown below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;576&#34; /&gt;&lt;/p&gt;
&lt;p&gt;For a clue of &lt;code&gt;1,1,2,1,1,2,1,1,1,1&lt;/code&gt; in a puzzle that is 35 squares wide, there
are &lt;strong&gt;1,961,256&lt;/strong&gt; patterns.&lt;/p&gt;
&lt;p&gt;In the end, I’ve settled upon the following solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;recursively build the solution&lt;/li&gt;
&lt;li&gt;with back-tracking whenever a valid pattern is impossible from a particular location&lt;/li&gt;
&lt;li&gt;store all values as lists of matrices which allowed for fast filtering out of impossible pattern combinations&lt;/li&gt;
&lt;li&gt;have a cache of patterns for smaller clues and puzzle widths rather than recalcualting every time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If I ever revisit this problem, I have an idea for a solution using the
&lt;a href=&#34;https://cran.r-project.org/package=memoise&#34;&gt;memoise package&lt;/a&gt;. But the problem
with cacheing &lt;em&gt;everything&lt;/em&gt; is that some of the pattern sets are &lt;em&gt;HUGE&lt;/em&gt; - more than
a gigabyte - and I don’t want to cache all those.&lt;/p&gt;
&lt;p&gt;If I ever wanted to solve bigger nonograms,
I’d need to use another solution technique altogether - the up-front generation of all
possible clues just takes up too much time and memory.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-step-2-filter-the-pattern-sets&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution step 2: Filter the pattern sets&lt;/h2&gt;
&lt;p&gt;For very &lt;em&gt;very&lt;/em&gt; small nonograms, it might be possible to try every combination
of patterns in a row and exhaustively search for a solution.&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;duck&lt;/strong&gt; problem the total number of combinations for all patterns for all
rows is 8x10^6 (8 million). If you could try 10,000 patterns/sec, you could
try them all in about 15 minutes.&lt;/p&gt;
&lt;p&gt;For some of the larger nonograms there are more than 1x10^100 (not a typo) combinations to try if you
wanted to brute force a solution!&lt;/p&gt;
&lt;p&gt;To initally filter the set of all patterns into a more tractable solution, I
look for locations within each pattern set which can only be one colour and use that to
filter the orthogonal data set.&lt;/p&gt;
&lt;p&gt;E.g. The pattern set for the third row in the &lt;strong&gt;duck&lt;/strong&gt; puzzle with clue &lt;code&gt;3,2&lt;/code&gt; is shown below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The third column is always filled-in! Which means that I now look at the pattern
sets for the third column and keep only ones with that location filled in.&lt;/p&gt;
&lt;p&gt;The clue for the third column is &lt;code&gt;1,5&lt;/code&gt; which looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-28-creating-a-nonogram-solver-in-R_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Only two patterns have the required filled-in square in the 3rd row, the others
can be eliminated from consideration.&lt;/p&gt;
&lt;p&gt;This process is repeated until there are no more occurrences.&lt;/p&gt;
&lt;p&gt;Sometimes by doing this filtering there is only one possible pattern left for
each row and column, in which case we have found a solution!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-step-3-recursively-build-the-solution-by-rows-with-back-tracking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution step 3: Recursively build the solution by rows with back-tracking&lt;/h2&gt;
&lt;p&gt;If there are still multiple patterns to try for each row we now try all of them
in turn by choosing them one row at a time.&lt;/p&gt;
&lt;p&gt;But as each row is selected, a cross-check is done to see that at least one
pattern in each column can fit that sequence of rows.&lt;/p&gt;
&lt;p&gt;If it fails then we stop that search path, select a different
row from the pattern set and continue.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Creating nonograms with &#39;nonogram&#39; and &#39;magick&#39; packages</title>
      <link>https://coolbutuseless.github.io/2018/09/27/creating-nonograms-with-nonogram-and-magick-packages/</link>
      <pubDate>Thu, 27 Sep 2018 19:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/27/creating-nonograms-with-nonogram-and-magick-packages/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;nonograms&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Nonograms&lt;/h2&gt;
&lt;p&gt;Nonograms are picture logic puzzles in which cells in a grid must be colored or
left blank according to numbers at the side of the grid to reveal a hidden picture.&lt;/p&gt;
&lt;p&gt;That is, the numbers on the side of the image (the &lt;em&gt;clues&lt;/em&gt;) are the
&lt;strong&gt;run-length encoding&lt;/strong&gt; of the filled-in squares for each row and column.&lt;/p&gt;
&lt;p&gt;By simultaneously satisfying the &lt;em&gt;clues&lt;/em&gt; for the rows and columns, a picture is revealed!&lt;/p&gt;
&lt;div style=&#34;float: left;&#34;&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-blank.png&#34; width=&#34;45%&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-solved.png&#34; width=&#34;45%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this short series of posts I will:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Introduce the nonogram package (&lt;a href=&#34;https://coolbutuseless.github.io/2018/09/26/nonograms-in-r---nonogram-package/&#34;&gt;see yesterday’s post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Show how to make nonograms by hand, or from an existing image (today’s post).&lt;/li&gt;
&lt;li&gt;Describe the solution techniqe behind the package (future post).&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;the-nonogram-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;nonogram&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;nonogram&lt;/code&gt; package contains tools for plotting, solving and creating nonogram puzzles.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;nonogram&lt;/code&gt; from github with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/nonogram&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-your-own-puzzles&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Create your own puzzles&lt;/h1&gt;
&lt;p&gt;To make, print and solve your own nonograms, you just need to create a &lt;em&gt;puzzle string&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;puzzle string&lt;/code&gt; format used to define puzzles is quite simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the numbers for each clue are separated by a comma&lt;/li&gt;
&lt;li&gt;each clue is separated by a colon&lt;/li&gt;
&lt;li&gt;the clues for the rows come first, then a dash, then the clues for the columns&lt;/li&gt;
&lt;li&gt;row clues are read from left to right&lt;/li&gt;
&lt;li&gt;column clues are read from top to bottom&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle_string &amp;lt;- &amp;quot;3:1:1,1-3:1:1,1&amp;quot;
solution      &amp;lt;- solve_puzzle(puzzle_string)
create_puzzle_plot(puzzle_string, solution)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-your-own-puzzles-from-an-image-using-the-magick-package&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Create your own puzzles from an image using the &lt;code&gt;magick&lt;/code&gt; package&lt;/h1&gt;
&lt;div id=&#34;load-an-image-with-magick&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Load an image with &lt;code&gt;magick&lt;/code&gt;&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Load an image&lt;/li&gt;
&lt;li&gt;Make it grayscale&lt;/li&gt;
&lt;li&gt;Shrink it to nonogram size. e.g. 25x20&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(magick)
im &amp;lt;- magick::image_read(system.file(&amp;quot;img&amp;quot;, &amp;quot;Rlogo.jpg&amp;quot;, package=&amp;quot;jpeg&amp;quot;))
im&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;50&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;im &amp;lt;- im %&amp;gt;% 
  image_quantize(max=2, colorspace = &amp;#39;gray&amp;#39;, dither=TRUE) %&amp;gt;%
  image_scale(geometry = geometry_size_pixels(width=25, height=20, preserve_aspect=FALSE)) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;125&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;from-the-image-create-an-integer-matrix-with-just-zeros-and-ones&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;From the image, create an integer matrix with just zeros and ones&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manipulating the image data to to matrix and then threshold, invert + tranpose
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mat &amp;lt;- t(1L - 1L * (im[[1]][1,,] &amp;gt; 180))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# nonogram has a method for plotting a matrix in a standard way
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nonogram::create_matrix_plot(mat)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-the-puzzle-from-the-matrix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create the puzzle from the matrix&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle        &amp;lt;- create_puzzle_from_matrix(mat)
puzzle_string &amp;lt;- convert_puzzle_to_puzzle_string(puzzle)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; puzzle&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;list(row_clues = list(8L, 13L, 17L, c(4L, 14L), c(3L, 3L, 3L), 
    c(3L, 2L, 10L, 2L), c(2L, 2L, 11L, 2L), c(2L, 2L, 12L, 1L
    ), c(2L, 2L, 12L, 1L), c(3L, 1L, 4L, 4L, 1L), c(3L, 2L, 4L, 
    4L, 1L), c(2L, 2L, 12L, 1L), c(3L, 2L, 11L, 1L), c(6L, 9L, 
    1L), c(11L, 7L), c(10L, 5L), 16L, c(7L, 5L), 4:5, 4:5), col_clues = list(
    3L, 8L, 4:5, c(3L, 3L), c(3L, 5L, 3L), c(2L, 3L, 6L), c(3L, 
    2L, 5L), c(2L, 2L, 4L), 4:3, 5:4, c(4L, 15L), c(4L, 15L), 
    c(4L, 15L), c(4L, 15L), c(4L, 4L, 3L, 2L), c(4L, 4L, 4L, 
    2L), c(4L, 4L, 6L), c(3L, 4L, 7L), c(3L, 15L), c(2L, 8L, 
    6L), c(3L, 7L, 6L), c(2L, 5L, 1L, 4L), c(2L, 1L, 2L), 2:1, 
    6L))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; puzzle_string&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;8:13:17:4,14:3,3,3:3,2,10,2:2,2,11,2:2,2,12,1:2,2,12,1:3,1,4,4,1:3,2,4,4,1:2,2,12,1:3,2,11,1:6,9,1:11,7:10,5:16:7,5:4,5:4,5-3:8:4,5:3,3:3,5,3:2,3,6:3,2,5:2,2,4:4,3:5,4:4,15:4,15:4,15:4,15:4,4,3,2:4,4,4,2:4,4,6:3,4,7:3,15:2,8,6:3,7,6:2,5,1,4:2,1,2:2,1:6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-blank-plot-of-just-the-clues&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a blank plot of just the clues&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_puzzle_plot(puzzle, show_clues=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-plot-of-the-matrix-and-clues&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a plot of the matrix and clues&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_puzzle_plot(puzzle, mat, show_clues=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-27-creating-nonogram-puzzles_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Nonograms in R - &#39;nonogram&#39; package</title>
      <link>https://coolbutuseless.github.io/2018/09/26/nonograms-in-r-nonogram-package/</link>
      <pubDate>Wed, 26 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/26/nonograms-in-r-nonogram-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;nonograms---make-run-length-encoding-fun-again&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Nonograms - Make Run-Length Encoding Fun Again&lt;/h2&gt;
&lt;p&gt;Nonograms are picture logic puzzles in which cells in a grid must be colored or
left blank according to numbers at the side of the grid to reveal a hidden picture.&lt;/p&gt;
&lt;p&gt;That is, the numbers on the side of the image (the &lt;em&gt;clues&lt;/em&gt;) are the
&lt;strong&gt;run-length encoding&lt;/strong&gt; of the filled-in squares for each row and column.&lt;/p&gt;
&lt;p&gt;By simultaneously satisfying the &lt;em&gt;clues&lt;/em&gt; for the rows and columns, a picture is revealed!&lt;/p&gt;
&lt;div style=&#34;float: left;&#34;&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-blank.png&#34; width=&#34;45%&#34;&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/nonogram/example-solved.png&#34; width=&#34;45%&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this short series of posts I will:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Introduce the nonogram package&lt;/li&gt;
&lt;li&gt;Show how to make nonograms by hand, or from an existing image&lt;/li&gt;
&lt;li&gt;Describe the solution techniqe behind the package&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;the-nonogram-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The &lt;code&gt;nonogram&lt;/code&gt; package&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;nonogram&lt;/code&gt; package contains tools for plotting, solving and creating nonogram puzzles.&lt;/p&gt;
&lt;p&gt;You can install &lt;code&gt;nonogram&lt;/code&gt; from github with:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;coolbutuseless/nonogram&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;basic-example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic example&lt;/h2&gt;
&lt;p&gt;This is a basic example which shows you how to plot and solve a simple puzzle.&lt;/p&gt;
&lt;p&gt;For this example I’ll be using one of the puzzles supplied in the package.&lt;/p&gt;
&lt;div id=&#34;use-one-of-the-puzzle-strings-in-the-package&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Use one of the puzzle strings in the package&lt;/h3&gt;
&lt;p&gt;There are 2 lists of puzzles in the package:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;puzzle_string_examples&lt;/code&gt; - 5 puzzles. Used during development.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;puzzle_string_library&lt;/code&gt; - ~4000 puzzles. Not tested.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle_string &amp;lt;- puzzle_string_examples[[&amp;#39;duck&amp;#39;]] 
puzzle        &amp;lt;- convert_puzzle_string_to_puzzle(puzzle_string)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle-and-puzzle-string-representation&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Puzzle and Puzzle String representation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;puzzle string&lt;/code&gt; representation is a ‘human-friendly’ version of a puzzle&lt;/li&gt;
&lt;li&gt;The actual &lt;code&gt;puzzle&lt;/code&gt; representation is a list in R&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; puzzle_string&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;3:2,1:3,2:2,2:6:1,5:6:1:2-1,2:3,1:1,5:7,1:5:3:4:3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;
&amp;gt; puzzle&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;list(row_clues = list(3L, 2:1, 3:2, c(2L, 2L), 6L, c(1L, 5L), 
    6L, 1L, 2L), col_clues = list(1:2, c(3L, 1L), c(1L, 5L), 
    c(7L, 1L), 5L, 3L, 4L, 3L))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-the-unsolved-puzzle&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Plot the unsolved puzzle&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_puzzle_plot(puzzle, title=&amp;quot;Duck&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-26-nonogram-package_files/figure-html/duck-unsolved-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solve-the-puzzle&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Solve the puzzle&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;solution_matrix &amp;lt;- solve_puzzle(puzzle) 
solution_matrix&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
 [1,]    0    1    1    1    0    0    0    0
 [2,]    1    1    0    1    0    0    0    0
 [3,]    0    1    1    1    0    0    1    1
 [4,]    0    0    1    1    0    0    1    1
 [5,]    0    0    1    1    1    1    1    1
 [6,]    1    0    1    1    1    1    1    0
 [7,]    1    1    1    1    1    1    0    0
 [8,]    0    0    0    0    1    0    0    0
 [9,]    0    0    0    1    1    0    0    0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;plot-the-solved-puzzle&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Plot the solved puzzle&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_puzzle_plot(puzzle, solution_matrix, title=&amp;quot;Duck&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-26-nonogram-package_files/figure-html/duck-solution-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;another-example-with-verbose-output-of-stats-and-timings&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Another example with verbose output of stats and timings&lt;/h2&gt;
&lt;p&gt;Another example of solving a nonogram is shown below, this time &lt;code&gt;verbose&lt;/code&gt; mode
is enabled and you can see the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes 0.02 seconds to generate the possible pattern sets for all the clues&lt;/li&gt;
&lt;li&gt;Initially there are 5.8x10^39 combinations of row patterns to try.&lt;/li&gt;
&lt;li&gt;By doing filtering, we bring this down to 1 - which means we’ve solved the puzzle!&lt;/li&gt;
&lt;li&gt;Doing that filtering took 0.01 seconds.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;puzzle &amp;lt;- nonogram::puzzle_string_examples[[&amp;#39;R&amp;#39;]]
puzzle
[1] &amp;quot;7:13:17:11,7:3,3,3:3,2,10,2:2,2,11,2:3,2,12,1:3,1,4,5,1:3,1,4,4,1:3,1,4,4,1:2,2,11,1:3,2,10,2:6,9,2:11,6:10,5:15:6,5:4,5:4,5-4:8:10:3,3:3,5,3:2,2,5:3,2,5:5,4:4,3:5,4:4,15:4,15:4,15:4,15:3,3,3,2:4,3,3,1:3,3,6:3,4,7:3,15:2,8,6:3,6,6:2,4,1,3:2,1,2:2,2:7&amp;quot;

puzzle %&amp;gt;%
  nonogram::solve_puzzle(verbose = TRUE) %&amp;gt;%
  nonogram::create_puzzle_plot(puzzle, ., show_clues=TRUE)
------------------------------------------------------------
Creating all possible pattern sets. This can take up to a minute (and lots of ram) for some puzzles ...
Creation of all possible pattern sets from the given clues: 0.02 seconds
Starting (Row) x (Column) combinations: 5.8e+39 x 1.21e+37
Filtered (Row) x (Column) combinations:    1 x    1
Total solution time: 0.01 seconds
------------------------------------------------------------&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-26-nonogram-package_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;p&gt;Possible ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;refactor the function which generates all possible patterns so that it can be memoised.
&lt;ul&gt;
&lt;li&gt;then re-write &lt;code&gt;memoise::memoise&lt;/code&gt; to allow memory limits on cacheing&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Try an alternate solution strategy which doesn’t involve the up-front creation
of all possible pattern sets - this is a real memory/cpu drain.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;appendix&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Appendix&lt;/h3&gt;
&lt;p&gt;Nonograms are also known by many other names, including Paint by Numbers,
Griddlers, Pic-a-Pix, Picross, PrismaPixels, Pixel Puzzles, Crucipixel, Edel,
FigurePic, Hanjie, HeroGlyphix, Illust-Logic, Japanese Crosswords,
Japanese Puzzles, Kare Karala!, Logic Art, Logic Square, Logicolor, Logik-Puzzles,
Logimage, Oekaki Logic, Oekaki-Mate, Paint Logic, Picture Logic, Tsunamii,
Paint by Sudoku and Binary Coloring Books.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Memoise with object size limit</title>
      <link>https://coolbutuseless.github.io/2018/09/24/memoise-with-object-size-limit/</link>
      <pubDate>Mon, 24 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/24/memoise-with-object-size-limit/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I have a function which takes 2 arguments and returns a matrix.&lt;/li&gt;
&lt;li&gt;Returned values for the most common inputs are under 1MB but some input values
result in returned matrices up to 5GB in size (thanks to a combinatorial explosion!)&lt;/li&gt;
&lt;li&gt;I would like to &lt;a href=&#34;http://en.wikipedia.org/wiki/Memoization&#34;&gt;memoise&lt;/a&gt; the function
using the &lt;a href=&#34;https://github.com/r-lib/memoise&#34;&gt;memoise package&lt;/a&gt;, but there doesn’t
seem to be a way to limit memory usage (someone please correct me on twitter if there is a way!)&lt;/li&gt;
&lt;li&gt;The following is an adapted version of &lt;code&gt;memoise::memoise()&lt;/code&gt; which only caches
objects if they are less than the given &lt;code&gt;object_size_limit&lt;/code&gt;, which is set
to a default of 1MB.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I made the tiniest of tweaks the core &lt;code&gt;memoise::memoise()&lt;/code&gt; function to:
&lt;ul&gt;
&lt;li&gt;Add an extra function argument &lt;code&gt;object_size_limit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check the object size before storing&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; A version of &amp;#39;memoise::memoise&amp;#39; with limits on individual object size
#&amp;#39;
#&amp;#39; @param f     Function of which to create a memoised copy.
#&amp;#39; @param ... optional variables specified as formulas with no RHS to use as
#&amp;#39; additional restrictions on caching. See Examples for usage.
#&amp;#39; @param envir Environment of the returned function.
#&amp;#39; @param cache Cache function.
#&amp;#39; @param object_size_limit maximum size of objects stored in cache.
#&amp;#39;        Default: 1048576 bytes (1MB)
#&amp;#39;
#&amp;#39;
#&amp;#39; @import memoise
#&amp;#39; @importFrom stats setNames
#&amp;#39; @importFrom digest digest
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
memoise_with_size_limit &amp;lt;- function (f, ..., envir = environment(f), 
                                     cache = memoise::cache_memory(), 
                                     object_size_limit = 1048576L) {
  f_formals &amp;lt;- formals(args(f))
  if (memoise::is.memoised(f)) {
    stop(&amp;quot;`f` must not be memoised.&amp;quot;, call. = FALSE)
  }
  f_formal_names &amp;lt;- names(f_formals)
  f_formal_name_list &amp;lt;- lapply(f_formal_names, as.name)
  init_call_args &amp;lt;- setNames(f_formal_name_list, f_formal_names)
  init_call &amp;lt;- memoise:::make_call(quote(`_f`), init_call_args)
  memoise:::validate_formulas(...)
  additional &amp;lt;- list(...)
  memo_f &amp;lt;- eval(bquote(function(...) {
    called_args &amp;lt;- as.list(match.call())[-1]
    default_args &amp;lt;- Filter(function(x) !identical(x, quote(expr = )),
                           as.list(formals()))
    default_args &amp;lt;- default_args[setdiff(names(default_args),
                                         names(called_args))]
    args &amp;lt;- c(lapply(called_args, eval, parent.frame()),
              lapply(default_args, eval, envir = environment()))
    hash &amp;lt;- `_cache`$digest(c(body(`_f`), args, lapply(`_additional`,
                                                       function(x) eval(x[[2L]], environment(x)))))
    if (`_cache`$has_key(hash)) {
      res &amp;lt;- `_cache`$get(hash)
    }
    else {
      res &amp;lt;- withVisible(.(init_call))
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # Check size and only store if &amp;lt; object_size_limit
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      if (pryr::object_size(res) &amp;lt; .(object_size_limit)) {
        `_cache`$set(hash, res)
      }
    }
    if (res$visible) {
      res$value
    }
    else {
      invisible(res$value)
    }
  }, as.environment(list(init_call = init_call, object_size_limit = object_size_limit))))
  formals(memo_f) &amp;lt;- f_formals
  attr(memo_f, &amp;quot;memoised&amp;quot;) &amp;lt;- TRUE
  if (is.null(envir)) {
    envir &amp;lt;- baseenv()
  }
  memo_f_env &amp;lt;- new.env(parent = envir)
  memo_f_env$`_cache` &amp;lt;- cache
  memo_f_env$`_f` &amp;lt;- f
  memo_f_env$`_additional` &amp;lt;- additional
  environment(memo_f) &amp;lt;- memo_f_env
  class(memo_f) &amp;lt;- c(&amp;quot;memoised&amp;quot;, &amp;quot;function&amp;quot;)
  memo_f
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Is there a way to do this with the additonal &lt;code&gt;...&lt;/code&gt; argument to &lt;code&gt;memoise()&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;You could really go-to-town customising memoise:
&lt;ul&gt;
&lt;li&gt;Add ability to remove objects from the cache&lt;/li&gt;
&lt;li&gt;Add ability to store last access time for an object, and hence remove objects
which have not been accessed in some time.&lt;/li&gt;
&lt;li&gt;Write a version which lets you set the maximum size of the entire cache, and then
&lt;ul&gt;
&lt;li&gt;not adding any more objects to the cache&lt;/li&gt;
&lt;li&gt;making room by deleting objects from the cache which haven’t been accessed recently&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>The Zombie/Vampire Apocalypse - A use case for strict membership tests</title>
      <link>https://coolbutuseless.github.io/2018/09/21/the-zombie/vampire-apocalypse-a-use-case-for-strict-membership-tests/</link>
      <pubDate>Fri, 21 Sep 2018 06:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/21/the-zombie/vampire-apocalypse-a-use-case-for-strict-membership-tests/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-in-isnt-strict-enough-for-some-of-my-use-cases&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: &lt;code&gt;%in%&lt;/code&gt; isn’t strict enough for some of my use cases&lt;/h2&gt;
&lt;p&gt;This is a &lt;strong&gt;second attempt&lt;/strong&gt; at creating a stricter version of &lt;code&gt;%in%&lt;/code&gt; to test
membership. (My first attempt is &lt;a href=&#34;https://coolbutuseless.github.io/2018/09/07/a-stricter-in/&#34;&gt;here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;My problems with &lt;code&gt;%in%&lt;/code&gt; arise because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It silently promotes arguments of different types.
&lt;ul&gt;
&lt;li&gt;I’d actually like an error if doing membership tests of vectors of different types&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;It is not robust to variations which might arise as the data evolves
&lt;ul&gt;
&lt;li&gt;See Zombies/Vampires use case below&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the following use-case, I show why &lt;code&gt;%in%&lt;/code&gt; isn’t ideal with data sets which
evolve and update.&lt;/p&gt;
&lt;p&gt;Rather than R letting you know when your membership test
is no longer up-to-date, the user must remain vigilant with every data update
to ensure that it is still valid i.e.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Did the categories change?&lt;/li&gt;
&lt;li&gt;Did I account for all spelling variations?&lt;/li&gt;
&lt;li&gt;Did the underlying format of the data change?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I would like a membership test which fails very noisily if an assumption made
about the data is no longer true.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-zombievampire-apocalypse---a-use-case-for-strict-membership-tests&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The Zombie/Vampire Apocalypse - A use case for strict membership tests&lt;/h2&gt;
&lt;div id=&#34;testing-for-membership-testing-with-in&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Testing for membership (testing with &lt;code&gt;%in%&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Every week you get an updated list of team members.&lt;/li&gt;
&lt;li&gt;Your job is to find the dangerous ones and recommend them to HR for review.&lt;/li&gt;
&lt;li&gt;You wrote a script (using &lt;code&gt;%in%&lt;/code&gt;) to find the dangerous team members.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your script to find dangerous team members
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(affliction %in% c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 1 x 2
  name  affliction
  &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;     
1 carl  zombie    &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-changes-testing-with-in&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership changes (testing with &lt;code&gt;%in%&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Debbie from the workshop is found to be a vampire.&lt;/li&gt;
&lt;li&gt;However, you weren’t notified of the new classification, so according to your
standard script only Carl is dangerous.&lt;/li&gt;
&lt;li&gt;The next nightshift with Debbie is going to be interesting!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - debbie-the-vampire joins the team
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your script to find dangerous team members doesn&amp;#39;t do its job and Debbie 
# (a vampire) isn&amp;#39;t considered as dangerous!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(affliction %in% c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 1 x 2
  name  affliction
  &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;     
1 carl  zombie    &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-typos-testing-with-in&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership typos (testing with &lt;code&gt;%in%&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;After the incident with Debbie, you’ve now updated your classification to include ‘vampire’ as a dangerous affliction.&lt;/li&gt;
&lt;li&gt;Evan has also been diagnosied as a vampire.&lt;/li&gt;
&lt;li&gt;However, the work-experience data-entry person has entered his affliction
as ‘Vampire’.&lt;/li&gt;
&lt;li&gt;So according to your standard script only Carl and Debbie are dangerous.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - Evan-the-Vampire joins the team
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;,
  &amp;#39;evan&amp;#39;    ,  &amp;quot;Vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your script to find dangerous team members doesn&amp;#39;t do its job and Evan 
# (a vampire) isn&amp;#39;t considered dangerous because of different capitalisation!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(affliction %in% c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;, &amp;#39;vampire&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 2 x 2
  name   affliction
  &amp;lt;chr&amp;gt;  &amp;lt;chr&amp;gt;     
1 carl   zombie    
2 debbie vampire   &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-changes-from-text-to-a-number-testing-with-in&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership changes from text to a number (testing with &lt;code&gt;%in%&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;For privacy reasons, management has decided to have all afflictions represented
by 0 or 1, where 0 is healthy and 1 represents dangerous afflictions&lt;/li&gt;
&lt;li&gt;You diligently update your scripts.&lt;/li&gt;
&lt;li&gt;However, the work-experience data-entry person didn’t get the memo and still
has afflictions represented by strings.&lt;/li&gt;
&lt;li&gt;You now think nobody is dangerous!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - Data has not yet been updated to numeric coding
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;,
  &amp;#39;evan&amp;#39;    ,  &amp;quot;Vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your code has been updated to expect numeric coding of afflications, but
# thre is a type mismatch and now no one is considered dangerous
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(affliction == 1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 0 x 2
# … with 2 variables: name &amp;lt;chr&amp;gt;, affliction &amp;lt;chr&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;strict-membership-testing-with-is_within&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Strict membership testing with &lt;code&gt;is_within()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I need a function which takes 3 arguments
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;the input values&lt;/li&gt;
&lt;li&gt;an ‘ingroup’ which defines what is to be matched against&lt;/li&gt;
&lt;li&gt;an ‘outgroup’ which defines what it must not match against&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;By explicitly specifying the allowed and dis-allowed values, &lt;code&gt;is_within()&lt;/code&gt; can
be much more robust to unexpected and unhandled values.&lt;/li&gt;
&lt;li&gt;Because there are now 3 arguments, this can no longer be an infix operator like
&lt;code&gt;%in%&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; A strict version of &amp;#39;%in%&amp;#39; where both the in-group and out-group must be completely specified
#&amp;#39;
#&amp;#39; The membership test is strict.
#&amp;#39;   - if &amp;#39;universe&amp;#39; is defined, then `outgroup = setdiff(universe, ingroup)`
#&amp;#39;   - Every value of &amp;#39;x&amp;#39; must exist within either &amp;#39;ingroup&amp;#39; or &amp;#39;outgroup&amp;#39;
#&amp;#39;   - &amp;#39;ingroup&amp;#39; and &amp;#39;outgroup&amp;#39; must be disjoint sets
#&amp;#39;   - May specify only one of &amp;#39;outgroup&amp;#39; or &amp;#39;universe&amp;#39;

#&amp;#39;
#&amp;#39; @param x input values.
#&amp;#39; @param ingroup vector of values against which elements of &amp;#39;x&amp;#39; should be checked
#&amp;#39;           for membership.
#&amp;#39; @param outgroup vector of values to which the elements of &amp;#39;x&amp;#39; should not belong
#&amp;#39; @param universe vector of all possible values to expect
#&amp;#39;
#&amp;#39;
#&amp;#39; @return A logical vector the same length as &amp;#39;x&amp;#39; which is TRUE if the
#&amp;#39; correponding value in x is a member of &amp;#39;ingroup&amp;#39; and is not a member
#&amp;#39; of &amp;#39;outgroup&amp;#39;.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
is_within &amp;lt;- function(x, ingroup, outgroup=NULL, universe=NULL) {

  if (!xor(is.null(outgroup), is.null(universe))) {
    stop(&amp;quot;is_within(): Must only specify one (and only one) of &amp;#39;outgroup&amp;#39; or &amp;#39;universe&amp;#39;&amp;quot;)
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Define outgroup to be disjoint from ingroup if &amp;#39;universe&amp;#39; given,
  # otherwise check that given ingroup/group are disjoint
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (!is.null(universe)) {
    outgroup &amp;lt;- setdiff(universe, ingroup)
  } else {
    if (length(intersect(ingroup, outgroup)) &amp;gt; 0L) {
      stop(&amp;quot;is_within(): &amp;#39;ingroup&amp;#39; and &amp;#39;outgroup&amp;#39; must not have overlapping elements. The following elements were found in both - &amp;quot;, 
           deparse(intersect(ingroup, outgroup)))
    }
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check classes match
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (length(intersect(class(x), intersect(class(ingroup), class(outgroup)))) == 0L) {
    stop(&amp;quot;is_within(): Classes must be identical. x: &amp;quot;, deparse(class(x)),
         &amp;quot; ingroup: &amp;quot;, deparse(class(ingroup)), &amp;quot; outgroup: &amp;quot;, deparse(class(outgroup)))
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check inputs have length &amp;gt;= 1
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (length(x)       == 0L) { stop(&amp;quot;is_within(): &amp;#39;x&amp;#39; must have at least 1 element&amp;quot;)}
  if (length(ingroup) == 0L) { stop(&amp;quot;is_within(): &amp;#39;ingroup&amp;#39; must have at least 1 element&amp;quot;)}
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Actually perform the membership tests
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  res &amp;lt;- x %in% ingroup
  neg &amp;lt;- x %in% outgroup
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check: input values must appear in one of &amp;#39;ingroup&amp;#39; or &amp;#39;outgroup&amp;#39;, but not both.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (any(!xor(res, neg))) {
    stop(&amp;quot;is_within(): All elements should appear in the &amp;#39;ingroup&amp;#39; or &amp;#39;outgroup&amp;#39; vectors. The following input elements were not found in either - &amp;quot;, deparse(x[!xor(res, neg)]))
  }
  
  
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;use-case-for-strict-membership-tests-using-is_within&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use case for strict membership tests using &lt;code&gt;is_within()&lt;/code&gt;&lt;/h2&gt;
&lt;div id=&#34;testing-for-membership-testing-with-is_within&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Testing for membership (testing with &lt;code&gt;is_within()&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Every week you get an updated list of team members.&lt;/li&gt;
&lt;li&gt;Your job is to find the dangerous ones and recommend them to HR for review.&lt;/li&gt;
&lt;li&gt;You wrote a script to find the dangerous team members using &lt;code&gt;belong()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your script to find dangerous team members using `is_within()`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(is_within(affliction, ingroup = c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;), outgroup=c(&amp;quot;healthy&amp;quot;, &amp;quot;cough&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 1 x 2
  name  affliction
  &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;     
1 carl  zombie    &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-changes-testing-with-is_within&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership changes (testing with &lt;code&gt;is_within()&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Debbie from the workshop is found to be a vampire.&lt;/li&gt;
&lt;li&gt;However, you weren’t notified of the new classification!&lt;/li&gt;
&lt;li&gt;Luckily, &lt;code&gt;is_within()&lt;/code&gt; ensures that all input values must be classified, and
so raises an error to let you know that your script is out of date.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - debbie-the-vampire joins the team
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using `is_within()` your script fails noisily because &amp;#39;vampire&amp;#39; is not
# defined in the ingroup or outgroup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(is_within(affliction, ingroup = c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;), outgroup=c(&amp;quot;healthy&amp;quot;, &amp;quot;cough&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in is_within(affliction, ingroup = c(&amp;quot;zombie&amp;quot;, &amp;quot;werewolf&amp;quot;), outgroup = c(&amp;quot;healthy&amp;quot;, : is_within(): All elements should appear in the &amp;#39;ingroup&amp;#39; or &amp;#39;outgroup&amp;#39; vectors. The following input elements were not found in either - &amp;quot;vampire&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-typos-testing-with-is_within&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership typos (testing with &lt;code&gt;is_within()&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You’ve updated your classification to include ‘vampire’ as a dangerous affliction.&lt;/li&gt;
&lt;li&gt;Evan has also been diagnosied as a vampire.&lt;/li&gt;
&lt;li&gt;However, the work-experience data-entry person has entered his affliction as ‘Vampire’.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;is_within()&lt;/code&gt; finds that “Vampire” is not categorisable and raises an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - Evan-the-Vampire joins the team
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;,
  &amp;#39;evan&amp;#39;    ,  &amp;quot;Vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using `is_within()` your script fails noisily because &amp;#39;Vampire&amp;#39; (with a
# capital &amp;#39;V&amp;#39;) is not defined in the ingroup or outgroup
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(is_within(affliction, ingroup = c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;, &amp;#39;vampire&amp;#39;), outgroup=c(&amp;quot;healthy&amp;quot;, &amp;quot;cough&amp;quot;)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in is_within(affliction, ingroup = c(&amp;quot;zombie&amp;quot;, &amp;quot;werewolf&amp;quot;, &amp;quot;vampire&amp;quot;), : is_within(): All elements should appear in the &amp;#39;ingroup&amp;#39; or &amp;#39;outgroup&amp;#39; vectors. The following input elements were not found in either - &amp;quot;Vampire&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-changes-from-text-to-a-number-testing-with-is_within&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership changes from text to a number (testing with &lt;code&gt;is_within()&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;For privacy reasons, management has decided to have all afflictions represented
by 0 or 1, where 0 is healthy and 1 represents dangerous afflictions&lt;/li&gt;
&lt;li&gt;You diligently update your scripts.&lt;/li&gt;
&lt;li&gt;The work-experience data-entry person didn’t get the memo and still
has afflictions represented by strings.&lt;/li&gt;
&lt;li&gt;Because of the mismatch in input types, &lt;code&gt;is_within()&lt;/code&gt; raises an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Team Members - Data has not yet been updated to numeric coding
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;,
  &amp;#39;evan&amp;#39;    ,  &amp;quot;Vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your script to find dangerous team members fails  noisily 
# because of the type mismatch
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(is_within(affliction, ingroup = 0L, outgroup=1L))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in is_within(affliction, ingroup = 0L, outgroup = 1L): is_within(): Classes must be identical. x: &amp;quot;character&amp;quot; ingroup: &amp;quot;integer&amp;quot; outgroup: &amp;quot;integer&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;membership-changes---vampires-are-now-not-dangerous-testing-with-is_within&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Membership changes - vampires are now not dangerous (testing with &lt;code&gt;is_within()&lt;/code&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;After reading Twilight, management has decided vampirism is no longer a dangerous affliction.&lt;/li&gt;
&lt;li&gt;You update your script to add ‘vampire’ in with the ‘healthy’ group.&lt;/li&gt;
&lt;li&gt;However, you weren’t paying attention and left ‘vampire’ also grouped in with
zombies and werewolves.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;is_within()&lt;/code&gt; detects you’ve specified the term ‘vampire’ in two locations and raises an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;team &amp;lt;- tribble(
  ~name     ,  ~affliction,
  &amp;quot;adam&amp;quot;    ,  &amp;quot;healthy&amp;quot;,
  &amp;quot;barbara&amp;quot; ,  &amp;quot;cough&amp;quot;,
  &amp;quot;carl&amp;quot;    ,  &amp;quot;zombie&amp;quot;,
  &amp;#39;debbie&amp;#39;  ,  &amp;quot;vampire&amp;quot;,
  &amp;#39;evan&amp;#39;    ,  &amp;quot;Vampire&amp;quot;
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Your code has been updated to expect numeric coding of afflications
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
team %&amp;gt;% 
  filter(is_within(affliction, ingroup = c(&amp;#39;zombie&amp;#39;, &amp;#39;werewolf&amp;#39;, &amp;#39;vampire&amp;#39;), outgroup=c(&amp;quot;healthy&amp;quot;, &amp;quot;cough&amp;quot;, &amp;#39;vampire&amp;#39;)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in is_within(affliction, ingroup = c(&amp;quot;zombie&amp;quot;, &amp;quot;werewolf&amp;quot;, &amp;quot;vampire&amp;quot;), : is_within(): &amp;#39;ingroup&amp;#39; and &amp;#39;outgroup&amp;#39; must not have overlapping elements. The following elements were found in both - &amp;quot;vampire&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Summary&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;This seems like a much more useful/useable solution than
&lt;a href=&#34;https://coolbutuseless.github.io/2018/09/07/a-stricter-in/&#34;&gt;Strict ‘%IN%’&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I’m still not 100% happy with the name of the function (&lt;code&gt;is_within&lt;/code&gt;) or its
arguments (&lt;code&gt;ingroup&lt;/code&gt; and &lt;code&gt;outgroup&lt;/code&gt;).
&lt;ul&gt;
&lt;li&gt;It sort of reads OK: “is x within the ingroup, but never the outgroup”&lt;/li&gt;
&lt;li&gt;It’s hard trying to find the right verb/phase! And the verb/pharse needs to make sense when negated.&lt;/li&gt;
&lt;li&gt;Suggestions welcomed!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>strict `case_when` - bugfix</title>
      <link>https://coolbutuseless.github.io/2018/09/20/strict-case_when-bugfix/</link>
      <pubDate>Thu, 20 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/20/strict-case_when-bugfix/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;bugfix---actually-handling-nas-in-input&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bugfix - actually handling NAs in input&lt;/h2&gt;
&lt;p&gt;I previously talked about why I wanted a &lt;code&gt;strict_case_when()&lt;/code&gt;
&lt;a href=&#34;https://coolbutuseless.github.io/2018/09/06/strict-case_when/&#34;&gt;a few week’s ago&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve since found a major bug for inputs which contain &lt;code&gt;NA&lt;/code&gt; and posting an
update to fix this.&lt;/p&gt;
&lt;p&gt;This code is available as &lt;a href=&#34;https://gist.github.com/coolbutuseless/7f86eedceb5c0ce6de8bf2dc6b3a0844&#34;&gt;a github gist&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;strict_case_when&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;strict_case_when()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strict_case_when()&lt;/code&gt; is a thin wrapper around &lt;code&gt;dplyr::case_when()&lt;/code&gt; which:
&lt;ul&gt;
&lt;li&gt;disallows a fall-through ‘TRUE’ value on the LHS.&lt;/li&gt;
&lt;li&gt;disallows input values which do not match any rules.&lt;/li&gt;
&lt;li&gt;disallows input values which match more than one rule&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Stricter version of case_when()
#&amp;#39;     - disallows a fall-through &amp;#39;TRUE&amp;#39; value on the LHS. 
#&amp;#39;     - disallows input values which do not match any rules. 
#&amp;#39;     - disallows input values which match more than one rule
#&amp;#39;
#&amp;#39; @param ... arguments to case_when
#&amp;#39;    
#&amp;#39; @return A vector of length 1 or n, matching the length of the logical input 
#&amp;#39; or output vectors, with the type (and attributes) of the first RHS. 
#&amp;#39; Inconsistent lengths or types will generate an error.
#&amp;#39;
#&amp;#39; @import dplyr 
#&amp;#39; @import rlang
#&amp;#39; @import purrr
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when &amp;lt;- function(...) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Allow case_when to do its thing!
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  res &amp;lt;- dplyr::case_when(...)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If `case_when` runs ok, then it means I can make the assumption that all
  # its input arguments are well-formed formulas, with a proper LHS
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  formulas &amp;lt;- rlang::list2(...)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check for fall-through &amp;#39;TRUE&amp;#39; value
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  lhs &amp;lt;- formulas %&amp;gt;% purrr::map(rlang::f_lhs)
  if (any(purrr::map_lgl(lhs, isTRUE))) {
    stop(&amp;quot;strict_case_when(): fall-through &amp;#39;TRUE&amp;#39; is not allowed&amp;quot;, call. = FALSE)
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Count how many times each input is matched by a rule.
  # Have to evaluate this in the right environment.
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  match_counts &amp;lt;- formulas %&amp;gt;%
    purrr::map(~rlang::eval_bare(rlang::f_lhs(.x), env = environment(.x))) %&amp;gt;%
    purrr::transpose() %&amp;gt;%
    purrr::map(flatten_lgl) %&amp;gt;%
    purrr::map_int(sum, na.rm=TRUE)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check if an input values unmatched
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (any(match_counts == 0L)) {
    stop(&amp;quot;strict_case_when(): no matches found at the following input indices: &amp;quot;, 
         deparse(which(match_counts == 0L)), call. = FALSE) 
  }
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Check if any input values matched multiple times
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (any(match_counts &amp;gt; 1L)) {
    stop(&amp;quot;strict_case_when(): multiple matches found at the following input indices: &amp;quot;, 
         deparse(which(match_counts &amp;gt; 1L)), call. = FALSE) 
  }
  
  
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-strict_case_when&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;strict_case_when()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The following test cases show how &lt;code&gt;strict_case_when()&lt;/code&gt;
appropriately throws errors for each of the issues I care about.&lt;/p&gt;
&lt;div id=&#34;a-good-example.-shouldnt-throw-error.&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;A good example. Shouldn’t throw error.&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A good example. Shouldn&amp;#39;t throw error.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;mammal&amp;quot; &amp;quot;mammal&amp;quot; &amp;quot;bird&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;no-bare-true-lhs-allowed&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;no bare ‘TRUE’ LHS allowed&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #1 handled - no &amp;#39;TRUE&amp;#39; LHS allowed
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;catt&amp;#39; ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  TRUE             ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): fall-through &amp;#39;TRUE&amp;#39; is not allowed&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;all-input-values-must-match-one-rule&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;All input values &lt;strong&gt;must&lt;/strong&gt; match one rule&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #2 handled - catch unmatched values
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dogg&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): no matches found at the following input indices: 2L&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;input-values-cannot-match-more-than-one-rule&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Input values cannot match more than one rule&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #3 handled - multiple matches raise an error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;insect&amp;#39;,
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): multiple matches found at the following input indices: 3L&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;bugfix-20180920---now-handling-nas-correctly&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Bugfix 20180920 - now handling &lt;code&gt;NA&lt;/code&gt;s correctly&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# It&amp;#39;s an error if NAs are present but not handled - Bugfix 20180920
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;, NA)

strict_case_when(
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;insect&amp;#39;,
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): no matches found at the following input indices: 4L&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Now works if NAs handled - Bugfix 20180920
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;insect&amp;#39;,
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  is.na(animal)     ~ &amp;#39;unknown&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;mammal&amp;quot;  &amp;quot;mammal&amp;quot;  &amp;quot;insect&amp;quot;  &amp;quot;unknown&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;More bugfixes probably :)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Find all sequences of a given length with the given sum</title>
      <link>https://coolbutuseless.github.io/2018/09/20/find-all-sequences-of-a-given-length-with-the-given-sum/</link>
      <pubDate>Thu, 20 Sep 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/20/find-all-sequences-of-a-given-length-with-the-given-sum/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;This problem popped up as a necessary step to solving a type of puzzle (which
I’ll post about soon).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From the set of all positive (non-zero) integers, find all the sequences of the
specified length which have the given sum.&lt;/li&gt;
&lt;li&gt;Need all orderings&lt;/li&gt;
&lt;li&gt;sums usually range from 10 to 30&lt;/li&gt;
&lt;li&gt;lengths usually range from 2 to 10&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-all-the-length3-vectors-which-sum-to-5-one-sequence-per-row&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example: All the length=3 vectors which sum to 5 (one sequence per row)&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3]
[1,]    1    1    3
[2,]    1    2    2
[3,]    1    3    1
[4,]    2    1    2
[5,]    2    2    1
[6,]    3    1    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-solution---generate-all-sequences-then-filter&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive solution - generate all sequences, then filter&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use expand grid to expand all possible sequences.&lt;/li&gt;
&lt;li&gt;Then filter where &lt;code&gt;rowSums()&lt;/code&gt; is equal to the required &lt;code&gt;target_sum&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Scales really badly as the sum and length targets get bigger&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_sequences_with_sum_naive &amp;lt;- function(target_sum, target_length) {
  res &amp;lt;- do.call(expand.grid, replicate(n=target_length, seq(target_sum - target_length + 1L), simplify = FALSE))
  res[rowSums(res) == target_sum,]
}

find_sequences_with_sum_naive(5, 3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;   Var1 Var2 Var3
3     3    1    1
5     2    2    1
7     1    3    1
11    2    1    2
13    1    2    2
19    1    1    3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;iterative-solution-with-back-tracking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Iterative solution with back-tracking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;build up vectors one digit at a time&lt;/li&gt;
&lt;li&gt;stop if the required length or sum is exceeded and try a different sequence&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_sequences_with_sum &amp;lt;- function(target_sum, target_length, current_vec=c(), N=0L, S=0L) {

  stopifnot(target_sum &amp;gt;= target_length)
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # If we&amp;#39;re at the right length, have we found a solution?
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  if (N == target_length) {
    if (S == target_sum) {
      return(list(current_vec))
    } else {
      return()
    }
  }

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Limit the choices in the next iteration to just ones that are possible
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  max_choice &amp;lt;- (target_sum - S) - (target_length - N) + 1L
  choices &amp;lt;- 1:max_choice

  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # For each choice, add it to the current_vec and see if that is a pathway
  # to a solution
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  solutions &amp;lt;- list()
  for (new_val in choices) {
    this_solution &amp;lt;- find_sequences_with_sum(target_sum, target_length, c(current_vec, new_val), N=N+1L, S=S+new_val)
    solutions &amp;lt;- c(solutions, this_solution)
  }

  solutions
}


do.call(rbind, find_sequences_with_sum(5, 3)) &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3]
[1,]    1    1    3
[2,]    1    2    2
[3,]    1    3    1
[4,]    2    1    2
[5,]    2    2    1
[6,]    3    1    1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;quick-benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quick benchmark&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;For small problems, results are roughly similar.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;small-example&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Small example&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-20-find-all-sequences-with-given-sum_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;find_sequences_with_sum_naive(5, 3)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;321.3µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2956.288&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64.9KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;find_sequences_with_sum(5, 3)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;77.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12581.641&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;medium-sized-example&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Medium-sized example&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Once the problem becomes moderately large, the back-tracking solution
(to no-one’s surprise) is faster and uses less memory.&lt;/li&gt;
&lt;li&gt;in this case, ~3x as fast and ~1000x less memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-20-find-all-sequences-with-given-sum_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;find_sequences_with_sum_naive(13, 7)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;197.1ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.048857&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;104MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;find_sequences_with_sum(13, 7)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.4ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;70.538884&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;142KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use the back-tracking solution&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Intersection of multiple vectors</title>
      <link>https://coolbutuseless.github.io/2018/09/17/intersection-of-multiple-vectors/</link>
      <pubDate>Mon, 17 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/17/intersection-of-multiple-vectors/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem---finding-the-intersection-of-multiple-integer-vectors&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem - Finding the intersection of multiple integer vectors&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I want to find the intersection of multiple integer vectors&lt;/li&gt;
&lt;li&gt;Unbounded number of vectors, but usually 4-10&lt;/li&gt;
&lt;li&gt;Unbounded size, but usually 10 to a million elements&lt;/li&gt;
&lt;li&gt;Duplicated elements allowed in output&lt;/li&gt;
&lt;li&gt;Order not important&lt;/li&gt;
&lt;li&gt;Submissions welcomed! (including alternate test sets that demonstrate a
different dominant solution)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;test-set&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Test set&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Benchmarking data:
&lt;ul&gt;
&lt;li&gt;10 vectors&lt;/li&gt;
&lt;li&gt;Varying lengths&lt;/li&gt;
&lt;li&gt;Elements sampled from range (1, 1e5)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;I realise that this benchmarking data ignores the following cases
&lt;ul&gt;
&lt;li&gt;a few short vectors&lt;/li&gt;
&lt;li&gt;very long vectors&lt;/li&gt;
&lt;li&gt;vectors already sorted by size&lt;/li&gt;
&lt;li&gt;vectors with large overlap&lt;/li&gt;
&lt;li&gt;vectors with no overlap&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)

source &amp;lt;- seq.int(1e5)
a &amp;lt;- sample(source, size=1.0e5, replace=TRUE)
b &amp;lt;- sample(source, size=0.9e5, replace=TRUE)
c &amp;lt;- sample(source, size=0.8e5, replace=TRUE)
d &amp;lt;- sample(source, size=0.7e5, replace=TRUE)
e &amp;lt;- sample(source, size=0.6e5, replace=TRUE)
f &amp;lt;- sample(source, size=0.5e5, replace=TRUE)
g &amp;lt;- sample(source, size=0.4e5, replace=TRUE)
h &amp;lt;- sample(source, size=0.3e5, replace=TRUE)
i &amp;lt;- sample(source, size=0.2e5, replace=TRUE)
j &amp;lt;- sample(source, size=0.1e5, replace=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;for-loop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;for&lt;/code&gt; loop&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;intersection_0_forloop &amp;lt;- function(...) {
  ll &amp;lt;- list(...)
  working_set &amp;lt;- ll[[1]]
  for (l in ll[-1]) {
    working_set &amp;lt;- intersect(working_set, l)
  }
  
  working_set
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(unique(intersection_0_forloop(a, b, c, d, e, f, g, h, i)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1258  4071  5370  7151  7749 14098 20244 23662 28383 32717 32730 40064
[13] 40376 44214 49955 53971 54336 54986 59242 61623 63523 67816 71673 82711
[25] 82976 83606 86895 90685 91729 92002 95154&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;reduce&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;Reduce()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Acculmulate &lt;code&gt;intersect()&lt;/code&gt; vector by vector using &lt;code&gt;Reduce()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Under the hood, this works identical to the &lt;code&gt;for&lt;/code&gt; loop example above…&lt;/li&gt;
&lt;li&gt;… but it’s much better looking :)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;intersection_1_reduce &amp;lt;- function(...) {
  Reduce(intersect, list(...))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(unique(intersection_1_reduce(a, b, c, d, e, f, g, h, i)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1258  4071  5370  7151  7749 14098 20244 23662 28383 32717 32730 40064
[13] 40376 44214 49955 53971 54336 54986 59242 61623 63523 67816 71673 82711
[25] 82976 83606 86895 90685 91729 92002 95154&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;sort-by-length-and-then-reduce&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sort by length and then &lt;code&gt;Reduce()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Acculmulate &lt;code&gt;intersect()&lt;/code&gt; vector by vector using &lt;code&gt;Reduce()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start with the shortest vector first.&lt;/li&gt;
&lt;li&gt;By ensuring that the intermediate result is always as short as possible, it should
reduce the memory allocations.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;intersection_2_reduce_sorted &amp;lt;- function(...) {
  ll   &amp;lt;- list(...)
  lens &amp;lt;- vapply(ll, length, integer(1))
  ll   &amp;lt;- ll[order(lens)]
  Reduce(intersect, ll)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(unique(intersection_2_reduce_sorted(a, b, c, d, e, f, g, h, i)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1258  4071  5370  7151  7749 14098 20244 23662 28383 32717 32730 40064
[13] 40376 44214 49955 53971 54336 54986 59242 61623 63523 67816 71673 82711
[25] 82976 83606 86895 90685 91729 92002 95154&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;tally-vector&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tally vector&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Initialise a &lt;code&gt;tally&lt;/code&gt; vector wtih length equal to the maximum integer across
all the vectors.&lt;/li&gt;
&lt;li&gt;For each element in each vector, increase the &lt;code&gt;tally&lt;/code&gt; for that element by 1.&lt;/li&gt;
&lt;li&gt;Find all counts in the &lt;code&gt;tally&lt;/code&gt; vector which match the number of vectors given.&lt;/li&gt;
&lt;li&gt;This will be increasingly inefficient as &lt;code&gt;maxval&lt;/code&gt; gets larger and larger.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;intersection_3_tally &amp;lt;- function(...) {
  ll     &amp;lt;- list(...)
  maxval &amp;lt;- max(vapply(ll, max, integer(1)))
  tally  &amp;lt;- integer(maxval)
  for (elements in ll) {
    tally[elements] &amp;lt;- tally[elements] + 1L
  }
  which(tally == length(ll))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(unique(intersection_3_tally(a, b, c, d, e, f, g, h, i)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1258  4071  5370  7151  7749 14098 20244 23662 28383 32717 32730 40064
[13] 40376 44214 49955 53971 54336 54986 59242 61623 63523 67816 71673 82711
[25] 82976 83606 86895 90685 91729 92002 95154&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rcpp-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rcpp function&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An Rcpp integer-only version of &lt;code&gt;intersect()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An R wrapper to go with it.&lt;/li&gt;
&lt;li&gt;side effect: original vectors are sorted numerically.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(
&amp;quot;std::vector&amp;lt;int&amp;gt; intersection_rcpp_core(IntegerVector v1, IntegerVector v2) {
  std::sort(v1.begin(), v1.end());
  std::sort(v2.begin(), v2.end());
  std::vector&amp;lt;int&amp;gt; v_intersection;

  std::set_intersection(v1.begin(), v1.end(),
                        v2.begin(), v2.end(),
                        std::back_inserter(v_intersection));
                        
  return v_intersection;
}
&amp;quot;)


intersection_4_rcpp &amp;lt;- function(...) {
  Reduce(intersection_rcpp_core, list(...))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sort(unique(intersection_4_rcpp(a, b, c, d, e, f, g, h, i)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1258  4071  5370  7151  7749 14098 20244 23662 28383 32717 32730 40064
[13] 40376 44214 49955 53971 54336 54986 59242 61623 63523 67816 71673 82711
[25] 82976 83606 86895 90685 91729 92002 95154&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;bm &amp;lt;- bench::mark(
  intersection_0_forloop      (a, b, c, d, e, f, g, h, i, j),
  intersection_1_reduce       (a, b, c, d, e, f, g, h, i, j),
  intersection_2_reduce_sorted(a, b, c, d, e, f, g, h, i, j),
  intersection_3_tally        (a, b, c, d, e, f, g, h, i, j),
  intersection_4_rcpp         (a, b, c, d, e, f, g, h, i, j),
  check = FALSE
)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mem_alloc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;intersection_0_forloop(a, b, c, d, e, f, g, h, i, j)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64.17ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.42914&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.55MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;intersection_1_reduce(a, b, c, d, e, f, g, h, i, j)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69.37ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.69209&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.56MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;intersection_2_reduce_sorted(a, b, c, d, e, f, g, h, i, j)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.66ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.68236&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.24MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;intersection_3_tally(a, b, c, d, e, f, g, h, i, j)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.41ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;133.20700&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.24MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;intersection_4_rcpp(a, b, c, d, e, f, g, h, i, j)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.89ms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;339.86518&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;356.72KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-17-intersection-of-multiple-vectors_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Under-the-hood, the &lt;code&gt;for&lt;/code&gt; loop and the &lt;code&gt;Reduce()&lt;/code&gt; methods are identical and this
is evidenced by their identical runtimes.&lt;/li&gt;
&lt;li&gt;Sorting input vectors by length results in a 2x speed-up over the base case for
this benchmark example (which is pretty pathological with the vectors in order
of decreasing size)&lt;/li&gt;
&lt;li&gt;Using a tally vector instead of the builtin &lt;code&gt;intersect()&lt;/code&gt; results in a ~9x speedup over the
base case.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Rcpp&lt;/code&gt; is clearly the fastest with least memory use.
&lt;ul&gt;
&lt;li&gt;This could be extended to be a pure &lt;code&gt;Rcpp&lt;/code&gt; function with the functionality
of the &lt;code&gt;Reduce()&lt;/code&gt; done in &lt;code&gt;C++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Could also implement the tally/memory technique in &lt;code&gt;Rcpp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Contributions welcomed!&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>A stricter `%in%`</title>
      <link>https://coolbutuseless.github.io/2018/09/07/a-stricter-in/</link>
      <pubDate>Fri, 07 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/07/a-stricter-in/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-in-isnt-strict-enough-for-some-of-my-use-cases&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: &lt;code&gt;%in%&lt;/code&gt; isn’t strict enough for some of my use cases&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;%in%&lt;/code&gt; will silently ignore&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;arguments of different types&lt;/li&gt;
&lt;li&gt;RHS arguments that don’t match any of the possible LHS inputs&lt;/li&gt;
&lt;li&gt;Empty RHS or LHS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, the following is a non-sensical filter in which none of the elements we’re trying to
match against are actually in the &lt;code&gt;Species&lt;/code&gt; vector!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;iris %&amp;gt;% 
  filter(Species %in% c(&amp;#39;leaf&amp;#39;, &amp;#39;tree&amp;#39;, &amp;#39;butterfly&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# A tibble: 0 x 5
# … with 5 variables: Sepal.Length &amp;lt;dbl&amp;gt;, Sepal.Width &amp;lt;dbl&amp;gt;,
#   Petal.Length &amp;lt;dbl&amp;gt;, Petal.Width &amp;lt;dbl&amp;gt;, Species &amp;lt;fct&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/jonocarroll&#34;&gt;jonocarrol&lt;/a&gt; has brought up this issue as a
pretty neat &lt;a href=&#34;https://github.com/tidyverse/forcats/issues/126&#34;&gt;PR to the forcats package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m not trying to be as elegant as he is, so I’m just going to make something
work in isolation.&lt;/p&gt;
&lt;p&gt;My use case:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;comparing atomic vectors only, usually character strings&lt;/li&gt;
&lt;li&gt;lhs and rhs arguments must be of the same class&lt;/li&gt;
&lt;li&gt;lhs and rhs arguments must have at last 1 element each&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;some-test-cases.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Some test cases.&lt;/h2&gt;
&lt;div id=&#34;cases-which-should-run-without-error&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Cases which should run without error&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %in% 2:4            # Good&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE  TRUE  TRUE  TRUE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;) %in% &amp;#39;a&amp;#39;            # Good&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1]  TRUE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;cases-for-which-id-like-an-explicit-error&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Cases for which I’d like an explicit error&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;) %in% &amp;#39;A&amp;#39;            # Bad: Some RHS values not in LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %in% c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;)    # Bad: type mismatch&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE FALSE FALSE FALSE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %in% 5:8            # Bad: Some RHS values not in LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE FALSE FALSE FALSE  TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1           %in% 1:5            # Bad: type mismatch&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %in% integer(0)     # Bad: empty RHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE FALSE FALSE FALSE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;integer(0)  %in% 1:5            # Bad: empty LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;logical(0)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1           %in% list(1, 2, 3)  # Bad: RHS not atomic&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;in---a-stricter-in&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;%IN%&lt;/code&gt; - a stricter &lt;code&gt;%in%&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;%IN%&lt;/code&gt; expects the following&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LHS and RHS are atomic&lt;/li&gt;
&lt;li&gt;LHS and RHS are not empty&lt;/li&gt;
&lt;li&gt;LHS and RHS are identical classes&lt;/li&gt;
&lt;li&gt;All elenents in the RHS are in the LHS&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Stricter version of %in%
#&amp;#39;
#&amp;#39; Check arguments for type mismatch, emptiness, atomic-ness and assert that
#&amp;#39; all elements in RHS are also in the LHS
#&amp;#39;
#&amp;#39; @param lhs left-hand side
#&amp;#39; @param rhs right-hand side
#&amp;#39; 
#&amp;#39; @return A logical vector the same length as &amp;#39;lhs&amp;#39; which is TRUE if the 
#&amp;#39; correponding value in the lhs exists somewhere in the rhs.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&amp;#39;%IN%&amp;#39; &amp;lt;- function(lhs, rhs) {
  if (!is.atomic(lhs) || !is.atomic(rhs)) {
    stop(&amp;quot;%IN%: LHS and RHS must be atomic&amp;quot;)
  }
  if (length(rhs) == 0) {
    stop(&amp;quot;%IN%: RHS has no elements&amp;quot;)
  }
  if (length(lhs) == 0) {
    stop(&amp;quot;%IN%: LHS has no elements&amp;quot;)
  }
  if (!identical(class(lhs), class(rhs))) {
    stop(&amp;quot;%IN%: Classes not identical. LHS: &amp;quot;, deparse(class(lhs)), &amp;quot; RHS: &amp;quot;, deparse(class(rhs)))
  }
  if (!all(rhs %in% lhs)) {
    stop(&amp;quot;%IN%: Some RHS elements not in LHS - &amp;quot;, deparse(setdiff(rhs, lhs), nlines=1))
  }
  lhs %in% rhs
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Negated version
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
&amp;#39;%NOTIN%&amp;#39; &amp;lt;- Negate(&amp;#39;%IN%&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;how-in-handles-cases-which-should-run-without-error&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;How &lt;code&gt;%IN%&lt;/code&gt; handles cases which should run without error&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %IN% 2:4            # Good&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE  TRUE  TRUE  TRUE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;) %IN% &amp;#39;a&amp;#39;            # Good&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1]  TRUE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;how-in-handles-cases-for-which-id-like-an-explicit-error&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;How &lt;code&gt;%IN%&lt;/code&gt; handles cases for which I’d like an explicit error&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;) %IN% &amp;#39;A&amp;#39;            # Bad: Some RHS values not in LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in c(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;) %IN% &amp;quot;A&amp;quot;: %IN%: Some RHS elements not in LHS - &amp;quot;A&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %IN% c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;)    # Bad: type mismatch&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in 1:5 %IN% c(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;): %IN%: Classes not identical. LHS: &amp;quot;integer&amp;quot; RHS: &amp;quot;character&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %IN% 5:8            # Bad: Some RHS values not in LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in 1:5 %IN% 5:8: %IN%: Some RHS elements not in LHS - 6:8&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1           %IN% 1:5            # Bad: type mismatch&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in 1 %IN% 1:5: %IN%: Classes not identical. LHS: &amp;quot;numeric&amp;quot; RHS: &amp;quot;integer&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1:5         %IN% integer(0)     # Bad: empty RHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in 1:5 %IN% integer(0): %IN%: RHS has no elements&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;integer(0)  %IN% 1:5            # Bad: empty LHS&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in integer(0) %IN% 1:5: %IN%: LHS has no elements&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;1           %IN% list(1, 2, 3)  # Bad: RHS not atomic&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in 1 %IN% list(1, 2, 3): %IN%: LHS and RHS must be atomic&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I feel that this version of &lt;code&gt;%IN%&lt;/code&gt; may be a little too strict to be useful.&lt;/li&gt;
&lt;li&gt;Not sure I’m really attached to the name &lt;code&gt;%IN%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I assume the &lt;a href=&#34;https://github.com/r-lib/vctrs&#34;&gt;vctrs package&lt;/a&gt; will solve all of this for me soon :)&lt;/li&gt;
&lt;li&gt;Waiting for someone to tell me that &lt;code&gt;%IN%&lt;/code&gt; is equivalent to some base R function I’ve never heard of ;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>strict `case_when`</title>
      <link>https://coolbutuseless.github.io/2018/09/06/strict-case_when/</link>
      <pubDate>Thu, 06 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/06/strict-case_when/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-case_when-isnt-strict-enough&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: &lt;code&gt;case_when()&lt;/code&gt; isn’t strict enough&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;case_when()&lt;/code&gt; is fantastic, but in some cases I’d like it to be a little bit
stricter on what it allows.&lt;/p&gt;
&lt;p&gt;I want to eliminate ways in which errors or oversights can creep in, so I’d like
special handling for the following cases:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;the fall-through/catch-all value of &lt;code&gt;TRUE&lt;/code&gt; should be disallowed by default.&lt;/li&gt;
&lt;li&gt;all input values should match one rule&lt;/li&gt;
&lt;li&gt;no input value should match more than one rule&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Before starting, let me state clearly that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;case_when()&lt;/code&gt; is awesome&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;case_when()&lt;/code&gt; is 1000x better than nested &lt;code&gt;ifelse()&lt;/code&gt; statements&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;use-case&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use case&lt;/h2&gt;
&lt;p&gt;My main use case for this strict version is ensuring that continuous values
are correctly turned into categories, when using complicated rules involving
multiple variables.&lt;/p&gt;
&lt;p&gt;In these cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;every input value should match a category&lt;/li&gt;
&lt;li&gt;every input value should match &lt;strong&gt;only one&lt;/strong&gt; category&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given these assumptions, there are quite a few problems with how I’ve written
the following code to map size to a categorical.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;size &amp;lt;- seq(0, 20, 0.5)

case_when(
  between(size,  1, 5 ) ~ &amp;#39;small&amp;#39;,
  between(size,  6, 12) ~ &amp;#39;medium&amp;#39;,
  between(size, 11, 20) ~ &amp;#39;big&amp;#39;,
  TRUE                  ~ &amp;#39;huge&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Issues:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;I’m missing a rule to cope with the input value of zero. This will fall through
to the default response of ‘huge’&lt;/li&gt;
&lt;li&gt;There’s no rule to handle the value of 5.5.&lt;/li&gt;
&lt;li&gt;There are multiple rules to handle the value of 11.5&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;case_when-issue-1---use-of-true-fall-through&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;case_when()&lt;/code&gt; issue #1 - use of &lt;code&gt;TRUE&lt;/code&gt; fall-through&lt;/h2&gt;
&lt;p&gt;The use of a final &lt;code&gt;TRUE&lt;/code&gt; value to catch all unmatched values can lead to
unexpected results.&lt;/p&gt;
&lt;p&gt;In the following example, I have made a typo in defining the rule for &lt;code&gt;cat&lt;/code&gt;.
Since &lt;code&gt;cat&lt;/code&gt; is not matched by the first rule (or any other rules),
it falls through to the default classification of &lt;code&gt;bird&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

case_when(
  animal == &amp;#39;catt&amp;#39; ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  TRUE             ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;bird&amp;quot;   &amp;quot;mammal&amp;quot; &amp;quot;bird&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;case_when-issue-2---every-input-value-should-match-a-rule&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;case_when()&lt;/code&gt; issue #2 - Every input value should match a rule&lt;/h2&gt;
&lt;p&gt;By default, &lt;code&gt;case_when()&lt;/code&gt; returns an NA for values that are not captured by
a rule.&lt;/p&gt;
&lt;p&gt;In the following, I’ve again made a typo. This time an input of &lt;code&gt;dog&lt;/code&gt; matches
none of the rules and is returned as &lt;code&gt;NA&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

case_when(
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dogg&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;mammal&amp;quot; NA       &amp;quot;bird&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A proposed solution is offered in this &lt;a href=&#34;https://github.com/tidyverse/dplyr/issues/3545&#34;&gt;github issue&lt;/a&gt;.
But it appears to not work. I’ve posted a follow-up on the github issue, and
I’ll wait to see if anyone can clarify.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;case_when-issue-3---every-input-value-should-match-only-1-rule&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;case_when()&lt;/code&gt; issue #3 - Every input value should match only 1 rule&lt;/h2&gt;
&lt;p&gt;By default, &lt;code&gt;case_when()&lt;/code&gt; returns the result for the first rule which matches
an input value.&lt;/p&gt;
&lt;p&gt;In the following, I’ve again made an error with the ruleset, and there are two
rules which match an input of &lt;code&gt;eagle&lt;/code&gt;. The first one is obviously wrong, but
this is what will be returned and any later matching rule is ignored.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)

case_when(
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;insect&amp;#39;,
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;mammal&amp;quot; &amp;quot;mammal&amp;quot; &amp;quot;insect&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not something &lt;code&gt;case_when()&lt;/code&gt; does, and is succinctly discussed
in this &lt;a href=&#34;https://github.com/tidyverse/dplyr/issues/3522&#34;&gt;github issue&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strict_case_when()&lt;/code&gt; is a thin wrapper around &lt;code&gt;case_when()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It’s going to call &lt;code&gt;case_when()&lt;/code&gt; first and let that function verify/test all the inputs are correct and calculate a response.&lt;/li&gt;
&lt;li&gt;After &lt;code&gt;case_when()&lt;/code&gt; succeeds, then we are assured that all the arguments are well-formed - this will make &lt;em&gt;my&lt;/em&gt; checking code easier to write.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Stricter version of case_when()
#&amp;#39;
#&amp;#39; @param ... arguments to case_when
#&amp;#39; @param .strict_mode Turn on strict mode. Default: TRUE
#&amp;#39;   This mode 
#&amp;#39;     - disallows a fall-through &amp;#39;TRUE&amp;#39; value on the LHS. 
#&amp;#39;     - disallows input values which do not match any rules. 
#&amp;#39;     - disallows input values which match more than one rule
#&amp;#39;    
#&amp;#39;
#&amp;#39; @return A vector of length 1 or n, matching the length of the logical input 
#&amp;#39; or output vectors, with the type (and attributes) of the first RHS. 
#&amp;#39; Inconsistent lengths or types will generate an error.
#&amp;#39;
#&amp;#39; @import dplyr 
#&amp;#39; @import rlang
#&amp;#39; @import purrr
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when &amp;lt;- function(..., .strict_mode=TRUE) {
  
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Allow case_when to do its thing!
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  res &amp;lt;- dplyr::case_when(...)
  
  if (.strict_mode) {
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # If `case_when` runs ok, then it means I can make the assumption that all
    # its input arguments are well-formed formulas, with a proper LHS
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    formulas &amp;lt;- rlang::list2(...)
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Count how many times each input is matched by a rule.
    # Have to evaluate this in the right environment.
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    match_counts &amp;lt;- formulas %&amp;gt;%
      purrr::map(~rlang::eval_bare(rlang::f_lhs(.x), env = environment(.x))) %&amp;gt;%
      purrr::reduce(`+`)
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Check for fall-through &amp;#39;TRUE&amp;#39; value
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    lhs &amp;lt;- formulas %&amp;gt;% purrr::map(rlang::f_lhs)
    if (any(purrr::map_lgl(lhs, isTRUE))) {
      stop(&amp;quot;strict_case_when(): fall-through &amp;#39;TRUE&amp;#39; is not allowed&amp;quot;, call. = FALSE)
    }
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Check if an input values unmatched
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (any(match_counts == 0L)) {
      stop(&amp;quot;strict_case_when(): no matches found at the following input indices: &amp;quot;, 
           deparse(which(match_counts == 0L)), call. = FALSE) 
    }
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Check if any input values matched multiple times
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (any(match_counts &amp;gt; 1L)) {
      stop(&amp;quot;strict_case_when(): multiple matches found at the following input indices: &amp;quot;, 
           deparse(which(match_counts &amp;gt; 1L)), call. = FALSE) 
    }
  }
  
  
  res
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-strict_case_when&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;strict_case_when()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Here again are the 3 test cases from earlier. This shows how &lt;code&gt;strict_case_when()&lt;/code&gt;
appropriately throws errors for each of the issues.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animal &amp;lt;- c(&amp;#39;cat&amp;#39;, &amp;#39;dog&amp;#39;, &amp;#39;eagle&amp;#39;)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A good example. Shouldn&amp;#39;t throw error.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;mammal&amp;quot; &amp;quot;mammal&amp;quot; &amp;quot;bird&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #1 handled - no &amp;#39;TRUE&amp;#39; LHS allowed
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;catt&amp;#39; ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  TRUE             ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): fall-through &amp;#39;TRUE&amp;#39; is not allowed&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #2 handled - catch unmatched values
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dogg&amp;#39;  ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): no matches found at the following input indices: 2L&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Issue #3 handled - multiple matches raise an error
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strict_case_when(
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;insect&amp;#39;,
  animal == &amp;#39;cat&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;dog&amp;#39;   ~ &amp;#39;mammal&amp;#39;,
  animal == &amp;#39;eagle&amp;#39; ~ &amp;#39;bird&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error: strict_case_when(): multiple matches found at the following input indices: 3L&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Awaiting someone to point out that this is equivalent to a base R function
I’ve never heard of before… ;)&lt;/li&gt;
&lt;li&gt;Waiting to see if anyone can clarify &lt;a href=&#34;https://github.com/tidyverse/dplyr/issues/3545&#34;&gt;this github issue&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>bits and bit reversal</title>
      <link>https://coolbutuseless.github.io/2018/09/04/bits-and-bit-reversal/</link>
      <pubDate>Tue, 04 Sep 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/09/04/bits-and-bit-reversal/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(bench)
library(Rcpp)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;I have a sequence of values in R and I want to reverse the bits in each value.&lt;/p&gt;
&lt;p&gt;Problem dimensions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only considering &lt;code&gt;raw&lt;/code&gt; values&lt;/li&gt;
&lt;li&gt;Up to ~10^5 raw values to reverse&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;bit-reversal---overview&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bit reversal - overview&lt;/h2&gt;
&lt;p&gt;For a vector of raw bytes I want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the output of &lt;code&gt;rawToBits()&lt;/code&gt; but with each byte bit-reversed i.e. &lt;strong&gt;most significant bit first&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;with all raw-bits-representing bytes concatentated together into a single vector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is, each byte within a vector of values is unmoved, but each byte has its
bits reversed.&lt;/p&gt;
&lt;p&gt;So instead of&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rawToBits(as.raw(c(15, 1)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 01 01 01 01 00 00 00 00 01 00 00 00 00 00 00 00&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… I want:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;00 00 00 00 01 01 01 01  00 00 00 00 00 00 00 01&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;lookup-table-in-pure-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Lookup table in pure R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Using a method from the &lt;a href=&#34;https://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable&#34;&gt;bithacks page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;There are only 256 possible raw values, just define the bit reversed version and look it up&lt;/li&gt;
&lt;li&gt;Adapted table to pure R&lt;/li&gt;
&lt;li&gt;Minor issues:
&lt;ul&gt;
&lt;li&gt;Can’t use a &lt;code&gt;raw&lt;/code&gt; value as an index, so need to convert it to &lt;code&gt;integer&lt;/code&gt; first&lt;/li&gt;
&lt;li&gt;Need to handle zero values - so add 1 to the index&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;reverse_bit_lookup &amp;lt;- as.raw(
  c(0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48,
    0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8,
    0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14,
    0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc,
    0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c,
    0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92,
    0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a,
    0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56,
    0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae,
    0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01,
    0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1,
    0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69,
    0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85,
    0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35,
    0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43,
    0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3,
    0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b,
    0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
    0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77,
    0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f,
    0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff))


raw_vec &amp;lt;- as.raw(c(15, 1))
reverse_bit_lookup[as.integer(raw_vec) + 1L]&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] f0 80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;lookup-table-in-rcpp&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Lookup table in Rcpp&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Using a method from the &lt;a href=&#34;https://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable&#34;&gt;bithacks page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Rcpp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This is the same method as the lookup table in R, just with the speed of Rcpp&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(code=&amp;#39;
RawVector reverse_lookup_Rcpp(RawVector x) {
  unsigned int N = x.size();
  RawVector reversed(N);

  static const unsigned char BitReverseTable256[256] = {
# define R2(n)     n,     n + 2*64,     n + 1*64,     n + 3*64
# define R4(n) R2(n), R2(n + 2*16), R2(n + 1*16), R2(n + 3*16)
# define R6(n) R4(n), R4(n + 2*4 ), R4(n + 1*4 ), R4(n + 3*4 )
  R6(0), R6(2), R6(1), R6(3)
};

  for (unsigned int i=0; i&amp;lt;N; ++i) {
    reversed[i] = BitReverseTable256[x[i]]; 
  }

  return reversed;
}&amp;#39;)

reverse_lookup_Rcpp(raw_vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] f0 80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;bit-bit-twiddling-in-rcpp&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;64bit bit-twiddling in Rcpp&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Using a method from the &lt;a href=&#34;https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64Bits&#34;&gt;bithacks page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Uses 64bit operations to reverse the bits in a byte.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(code=&amp;#39;
RawVector reverse_twiddle64_Rcpp(RawVector x) {
  unsigned int N = x.size();
  RawVector reversed(N);

  for (unsigned int i=0; i&amp;lt;N; ++i) {
    reversed[i] = ((x[i] * 0x80200802ULL) &amp;amp; 0x0884422110ULL) * 0x0101010101ULL &amp;gt;&amp;gt; 32;
  }

  return reversed;
}&amp;#39;)

reverse_twiddle64_Rcpp(raw_vec)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] f0 80&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark-using-benchmark&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark using &lt;code&gt;bench::mark()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;raw_vec &amp;lt;- as.raw(1:10000 %% 256)
bm1 &amp;lt;- bench::mark(
  reverse_bit_lookup[as.integer(raw_vec) + 1L],
  reverse_lookup_Rcpp(raw_vec),
  reverse_twiddle64_Rcpp(raw_vec)
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-09-04-bit-reversal_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expression&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;itr/sec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;reverse_bit_lookup[as.integer(raw_vec) + 1]&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;80.2µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11941.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;reverse_lookup_Rcpp(raw_vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.1µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;73295.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;reverse_twiddle64_Rcpp(raw_vec)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11.4µs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;78641.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Rcpp&lt;/code&gt; methods are ~6x faster than the pure R lookup&lt;/li&gt;
&lt;li&gt;Thanks to hadley for the “+1L” correction.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Idiomatic Rcpp patches welcomed
&lt;ul&gt;
&lt;li&gt;Only if they give a speed boost ;)&lt;/li&gt;
&lt;li&gt;I know that I write my C++ code like it’s just C&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>gganimate with sprites</title>
      <link>https://coolbutuseless.github.io/2018/08/13/gganimate-with-sprites/</link>
      <pubDate>Mon, 13 Aug 2018 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/08/13/gganimate-with-sprites/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(raster)
library(gganimate)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;sprites&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Sprites&lt;/h2&gt;
&lt;p&gt;A sprite is a 2d bitmap often used by games to represent objects. A number
of sprites displayed in sequence creates an animation.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;puzzle-bobble-sprite-extraction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Puzzle bobble sprite extraction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Grab a sprite sheet for your favourite game from &lt;a href=&#34;https://www.spriters-resource.com&#34;&gt;spriters resource&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I will be using a Bubble Bobble dinosaur&lt;/li&gt;
&lt;li&gt;Work out how to cut out sprites by subsetting the sheet of sprites&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Not going to directly link in to script to avoid hitting server
# https://www.spriters-resource.com/resources/sheets/12/12593.png
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sprite_sheet &amp;lt;- png::readPNG(&amp;quot;12593.png&amp;quot;)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set up the extraction parameters
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Nframes       &amp;lt;- 16      # number of frames to extract
width         &amp;lt;- 28      # width of a frame
sprite_frames &amp;lt;- list()  # storage for the extracted frames

# Not equal sized frames in the sprite sheet. Need to compensate for each frame
offset &amp;lt;- c(3, 4, 6, 7, 7, 6, 5, 5, 6, 6, 7, 7, 7, 6, 7, 8)

# Manually extract each frame
for (i in seq(Nframes)) {
  sprite_frames[[i]] &amp;lt;- sprite_sheet[13:40, (width*(i-1)) + (1:width) + offset[i], 1:3]
}

# Test plot
plot(as.raster(sprite_frames[[15]]), interpolate=FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-13-gganimate-sprites_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;convert-sprites-to-data.frames&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convert sprites to data.frames&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Convert the sprite to a data.frame of values for &lt;code&gt;geom_tile()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove the background colour&lt;/li&gt;
&lt;li&gt;Calculate a lookup table of colours to use with &lt;code&gt;scale_fill_manual&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Stack all the individual frames together&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function to convert a sprite frame to a data.frame
# and remove any background pixels i.e. #82ABE7
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sprite_frame_to_df &amp;lt;- function(frame) {
  plot_df &amp;lt;- data_frame(
    fill  = as.vector(as.raster(frame)),
    x = rep(1:width, width),
    y = rep(width:1, each=width)
  ) %&amp;gt;%
    filter(fill != &amp;#39;#82ABE7&amp;#39;)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert all sprite frames to sprite data.frames
# and set the &amp;#39;idx&amp;#39; column to the frame number
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sprite_dfs &amp;lt;- sprite_frames %&amp;gt;%
  map(sprite_frame_to_df) %&amp;gt;%
  imap(~mutate(.x, idx=.y))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Work out the spirte colours for scale_fill_manual
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fill_manual_values &amp;lt;- unique(sprite_dfs[[1]]$fill)
fill_manual_values &amp;lt;- setNames(fill_manual_values, fill_manual_values)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Stack all the sprites into a mega data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mega_df &amp;lt;- dplyr::bind_rows(sprite_dfs)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;ggplot---facet-in-space&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ggplot - facet-in-space&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the basic ggplot object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p &amp;lt;- ggplot(mega_df, aes(x, y, fill=fill)) +
  geom_tile(width=0.9, height=0.9) +
  coord_equal(xlim=c(1, width), ylim=c(1, width)) +
  scale_fill_manual(values = fill_manual_values) +
  theme_bw() +
  theme(legend.position = &amp;#39;none&amp;#39;)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Facet by time
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p +
  facet_wrap(~idx)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-13-gganimate-sprites_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;gganimate---facet-in-time&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;gganimate - facet-in-time&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Facet by time with gganimate
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
panim &amp;lt;- p +
  transition_manual(idx, seq_along(sprite_frames)) +
  labs(title = &amp;quot;gganimate bubble bobble&amp;quot;)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create and save animation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gganimate::animate(panim, fps=8, width=400, height=400)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;nframes and fps adjusted to match transition&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-13-gganimate-sprites_files/figure-html/unnamed-chunk-5-1.gif&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# gganimate::anim_save(&amp;quot;bubble_bobble.gif&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>gganimate with bitmap fonts</title>
      <link>https://coolbutuseless.github.io/2018/08/12/gganimate-with-bitmap-fonts/</link>
      <pubDate>Sun, 12 Aug 2018 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/08/12/gganimate-with-bitmap-fonts/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I finally got the time to play with the &lt;a href=&#34;https://github.com/thomasp85/gganimate&#34;&gt;gganimate&lt;/a&gt;
package by &lt;a href=&#34;https://www.twitter.com/thomasp85&#34;&gt;Thomas Lin Pederson&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The API is really well designed and Thomas has deconstructed the grammar of animation into
a clean/orthogonal set of functions.&lt;/p&gt;
&lt;p&gt;I put together the little animation shown below, and this is a short guide on how I got there.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/gganimate/hellothere.gif&#34; width=&#34;85%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;



&lt;/div&gt;
&lt;div id=&#34;bitmap-fonts&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Bitmap fonts&lt;/h2&gt;
&lt;p&gt;In a bitmap font, a character is defined by a binary matrix - where the matrix is 1 the
underlying pixel is turned on, otherwise it is turned off.&lt;/p&gt;
&lt;p&gt;An example matrix of an 8x8 binary matrix to define the letter &lt;code&gt;a&lt;/code&gt; is shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    0    0    0    0    0    0    0
[2,]    0    0    0    0    0    0    0    0
[3,]    0    0    1    1    1    1    0    0
[4,]    0    0    0    0    0    1    1    0
[5,]    0    0    1    1    1    1    1    0
[6,]    0    1    1    0    0    1    1    0
[7,]    0    0    1    1    1    1    1    0
[8,]    0    0    0    0    0    0    0    0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This matrix can be easily plotted with the &lt;code&gt;raster&lt;/code&gt; package&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;withr::with_package(&amp;#39;raster&amp;#39;, {
  plot(raster(char_matrix$a), col=c(1,0), legend=FALSE, ann=FALSE, axes=FALSE)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Rather than individually creating bitmap font matrices, I’m actually reading
in bitmap font files from disk. I haven’t packaged that code up yet, but hopefully
will do so soon. For this post I’ll just use some manually created character data stored in &lt;code&gt;char_df&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;rendering-a-bitmap-font-character-with-ggplot2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rendering a bitmap font character with &lt;code&gt;ggplot2&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To work with &lt;code&gt;ggplot2&lt;/code&gt;, the matrix for an 8x8 character is turned into
a data.frame.&lt;/p&gt;
&lt;p&gt;The data.frame is the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; co-ordinates of all the locations of &lt;code&gt;1&lt;/code&gt; in the bitmap matrix.&lt;/p&gt;
&lt;p&gt;Here is a data.frame for the same &lt;code&gt;a&lt;/code&gt;, now ready for &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   x y
1  2 5
2  3 5
3  4 5
4  5 5
5  5 4
6  6 4
7  2 3
8  3 3
9  4 3
10 5 3
11 6 3
12 1 2
13 2 2
14 5 2
15 6 2
16 2 1
17 3 1
18 4 1
19 5 1
20 6 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This data.frame is plotted using &lt;code&gt;ggplot2::geom_tile()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(char_df$a, aes(x, y)) + 
  geom_tile() + 
  coord_equal() +
  theme_minimal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;The tile size is set a bit smaller than 1 to get the retro pixel look:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(char_df$a, aes(x, y)) + 
  geom_tile(width=0.9, height=0.9) + 
  coord_equal() +
  theme_minimal()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;preparing-a-data.frame-for-gganimate&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Preparing a data.frame for gganimate&lt;/h2&gt;
&lt;p&gt;The data.frame for gganimate is going to consist of 3 characters (a, b, c), displayed one-at-a-time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a data.frame for each bitmap character&lt;/li&gt;
&lt;li&gt;Give each character an &lt;code&gt;idx&lt;/code&gt; which will let gganimate control when it is displayed&lt;/li&gt;
&lt;li&gt;Stack them all into a single data.frame with &lt;code&gt;dplyr::bind_rows()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot_df &amp;lt;- dplyr::bind_rows(
  char_df$a %&amp;gt;% mutate(idx = 1),
  char_df$b %&amp;gt;% mutate(idx = 2),
  char_df$c %&amp;gt;% mutate(idx = 3)
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Plotting without &lt;code&gt;gganimate&lt;/code&gt; results in the 3 letters being superimposed. Not really very useful,
but a stepping stone to the actual animation.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;- ggplot(plot_df, aes(x, y)) + 
  geom_tile(width=0.9, height=0.9) + 
  coord_equal() +
  theme_minimal()

p&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Below I facet by &lt;code&gt;idx&lt;/code&gt; to separate out each character in space. &lt;code&gt;gganimate&lt;/code&gt; will use the &lt;code&gt;idx&lt;/code&gt; column to separate the characters in time using &lt;code&gt;transition_states()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p + 
  facet_wrap(~idx) + 
  theme_bw() &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;plotting-with-gganimate---facetting-in-time&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Plotting with &lt;code&gt;gganimate&lt;/code&gt; - facetting in time!&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gganimate&lt;/code&gt; takes a standard ggplot and separates out
the individual states (i.e. the &lt;code&gt;idx&lt;/code&gt; variable) by rendering them at different times.&lt;/p&gt;
&lt;p&gt;By analogy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ggplot2::facet_wrap()&lt;/code&gt; renders the data at different locations in &lt;em&gt;space&lt;/em&gt; dependent upon the facetting variable&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gganimate::transition_states()&lt;/code&gt; renders the data at different &lt;em&gt;times&lt;/em&gt; dependent upon the &lt;code&gt;states&lt;/code&gt; variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;panim &amp;lt;- p +
  transition_states(
    states            = idx, # variable in data
    transition_length = 1,   # all states display for 1 time unit
    state_length      = 1    # all transitions take 1 time unit
  ) +
  enter_fade() +             # How new blocks appear
  exit_fade() +              # How blocks disappear
  ease_aes(&amp;#39;sine-in-out&amp;#39;)    # Tweening movement

panim&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-9-1.gif&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;controlling-the-animation-length-and-image-size&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Controlling the animation length and image size&lt;/h2&gt;
&lt;p&gt;By default, the animation is scaled into 100 frames of PNG output at 10 frames-per-second. These png files
are then rendered to an animated gif using &lt;a href=&#34;https://github.com/r-rust/gifski&#34;&gt;gifski&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By default the individual images are rendered using R’s built-in &lt;code&gt;png()&lt;/code&gt; which has a default output size of 480x480 pixels.&lt;/p&gt;
&lt;p&gt;To render the gif differently (e.g. shorter duration, faster playback, smaller image size), you can
call &lt;code&gt;animate()&lt;/code&gt; directly on the plot object&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;animate(panim, fps=20, nframes=50, width=200, height=200)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-12-gganimate-with-bitmap-fonts_files/figure-html/unnamed-chunk-10-1.gif&#34; /&gt;&lt;!-- --&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;to-do&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;To Do&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Package up the code for parsing bitmap font files&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>ggplot2 stat_summary problem</title>
      <link>https://coolbutuseless.github.io/2018/08/06/ggplot2-stat_summary-problem/</link>
      <pubDate>Mon, 06 Aug 2018 06:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/08/06/ggplot2-stat_summary-problem/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When using &lt;code&gt;stat_summary()&lt;/code&gt; it transforms all
the values first and then calculates the summary.&lt;/p&gt;
&lt;p&gt;However, I would like the &lt;code&gt;stat_summary&lt;/code&gt; calculated on the original data and
then transformed.&lt;/p&gt;
&lt;p&gt;Below I’ll try and illustrate the problem, and propose a work-around.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: it appears my &lt;a href=&#34;https://github.com/tidyverse/ggplot2/issues/2804&#34;&gt;github issue&lt;/a&gt; has been closed.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;ggplot2stat_summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;ggplot2::stat_summary&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ggplot2&lt;/code&gt; has the ability to summarise data with &lt;code&gt;stat_summary&lt;/code&gt;. This particular &lt;code&gt;Stat&lt;/code&gt;
will calculate a summary of your data at each unique &lt;code&gt;x&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;The following creates a scatter plot of some points with a mean calculated
at each &lt;code&gt;x&lt;/code&gt; and connected by a line.&lt;/p&gt;
&lt;p&gt;Note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the true mean at &lt;code&gt;x=0&lt;/code&gt; is 1&lt;/li&gt;
&lt;li&gt;the raw &lt;code&gt;plot_df&lt;/code&gt; data and the manually calculated &lt;code&gt;mean_df&lt;/code&gt; summary are included in the appendix at the end of this post.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;- ggplot(plot_df, aes(x, y)) + 
  geom_point(alpha=0.4) +
  stat_summary(fun.y = mean, geom=&amp;#39;line&amp;#39;) +
  scale_y_continuous(breaks=1:9) + 
  theme_bw() + 
  ggtitle(&amp;quot;Using stat_summary to draw a mean line\nNote that mean is 1 at x=1&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p + scale_y_sqrt(breaks=1:9) +
  ggtitle(&amp;quot;Using stat_summary to draw a mean line - `scale_y_sqrt()`\nNote that mean at x=1 is no longer 1 !!&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-problem-summary-values-are-calculated-after-transform-not-before.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The problem: Summary values are calculated after transform, not before.&lt;/h2&gt;
&lt;p&gt;My issue with &lt;code&gt;stat_summary&lt;/code&gt; is that I would like the summary values to be calcualted before the transform is performed,
but &lt;code&gt;stat_summary&lt;/code&gt; summary values are calculated &lt;strong&gt;after&lt;/strong&gt; the data is transformed.&lt;/p&gt;
&lt;p&gt;There doesn’t appear to be an option to change this, and I suspect because it’s not in keeping with the grammar of graphics upon
which ggplot2 is based.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-the-different-between-summary-after-transform-and-transform-after-summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s the different between &lt;code&gt;summary-after-transform&lt;/code&gt; and &lt;code&gt;transform-after-summary&lt;/code&gt;?&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;y &amp;lt;- c(0, 0, 0, 0, 1, 1, 5)
sqrt(mean(y)) # transform-after-summary (what i want to do)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(sqrt(y)) # summary-after-transform (what stat_summary does)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 0.6051526&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-the-difference-on-a-plot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s the difference on a plot?&lt;/h2&gt;
&lt;p&gt;So how does &lt;code&gt;stat_summary&lt;/code&gt; way of calculating the &lt;em&gt;summary-after-transform&lt;/em&gt; differ
from my desired calculation of &lt;em&gt;transform-after-summary&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;The following plot shows the correct mean (dashed blue line) and the the &lt;code&gt;stat_summary&lt;/code&gt; mean line.
The correct mean has been calculated manually on the original data prior to any transformation.&lt;/p&gt;
&lt;p&gt;Note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At &lt;code&gt;x=0&lt;/code&gt; the correct mean (blue) passes through 1, whereas the &lt;code&gt;stat_summary()&lt;/code&gt; mean (black) passes through 0.6.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(plot_df, aes(x, y)) + 
  geom_point(alpha=0.6) +
  stat_summary(fun.y = mean, geom=&amp;#39;line&amp;#39;) + 
  geom_point(data=mean_df, size=3, alpha=0.3, colour=&amp;#39;blue&amp;#39;) +
  geom_line (data=mean_df, linetype = 2, colour=&amp;#39;blue&amp;#39;) +
  scale_y_sqrt(breaks=0:9) +
  ggtitle(&amp;quot;Blue dashed line is true mean line (transform-after-summary)\nBlack line is stat_summary result (summary-after-transform)&amp;quot;)  + 
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;coord_trans-isnt-what-i-want&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;coord_trans()&lt;/code&gt; isn’t what I want&lt;/h2&gt;
&lt;p&gt;I do not want curved lines between points - even though that may be technically correct (the best kind of correct) as
the curved lines are not-friendly to the particular non-technical audience.&lt;/p&gt;
&lt;p&gt;So the &lt;code&gt;coord_trans()&lt;/code&gt; solution below is not acceptable:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(plot_df, aes(x, y)) + 
  geom_point(alpha=0.6) +
  stat_summary(fun.y = mean, geom=&amp;#39;line&amp;#39;) + 
  geom_line (data=mean_df, linetype = 2, colour=&amp;#39;blue&amp;#39;, size=3, alpha=0.3) +
  ggtitle(&amp;quot;Using coord_trans\nBlue dashed line is true mean line (transform-after-summary)\nBlack line is stat_summary result (summary-after-transform)&amp;quot;)  + 
  theme_bw() + 
  coord_trans(y=&amp;#39;sqrt&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;specialhacked-summary-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Special/hacked summary function&lt;/h2&gt;
&lt;p&gt;As proposed on the &lt;a href=&#34;https://github.com/tidyverse/ggplot2/issues/2804&#34;&gt;github issue&lt;/a&gt;,
a carefully crafted summary function could work in some situations:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

plot_df &amp;lt;- data.frame(
  x = rep(1:3, each=7),
  y = c(0, 0, 0, 0, 1, 1, 5,    1, 1, 1, 1, 2, 2, 2,      2, 3, 4, 5, 6, 7, 8)
)


ggplot(plot_df, aes(x, y)) +
  geom_point(alpha=0.4) +
  stat_summary(fun.y = function(x) sqrt(mean(x^2)), geom=&amp;#39;line&amp;#39;) +
  scale_y_sqrt(breaks=1:9) +
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;However it is problematic in 2 ways:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;The format of the summary function now depends on the scale uses i.e. the summary function needs to be tailored to the scale transform.&lt;/li&gt;
&lt;li&gt;This won’t work if
&lt;ul&gt;
&lt;li&gt;the transform is non-invertible (e.g. sqrt(-2))&lt;/li&gt;
&lt;li&gt;the transform creates infiniteis (e.g. log(0))&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following plot shows that even with a carefully crafted summary function,
the mean displayed will be incorrect because &lt;code&gt;log10(0)&lt;/code&gt; is infinite, and
infinite values get discarded by default in &lt;code&gt;Stat$compute_layer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This means the graph ends up plotting (at x=1) the mean of &lt;code&gt;c(1, 1, 5)&lt;/code&gt; which is 2.3.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(ggplot2)

plot_df &amp;lt;- data.frame(
  x = rep(1:3, each=7),
  y = c(0, 0, 0, 0, 1, 1, 5,    1, 1, 1, 1, 2, 2, 2,      2, 3, 4, 5, 6, 7, 8)
)


ggplot(plot_df, aes(x, y)) +
  geom_point(alpha=0.4) +
  stat_summary(fun.y = function(x) log10(mean(10^x)), geom=&amp;#39;line&amp;#39;) +
  scale_y_log10(breaks=1:9) +
  theme_bw() + 
  ggtitle(&amp;quot;With log transforrm\nBecause infinites are dropped in compute_layer\nWe can&amp;#39;t recover the original data&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;proposed-fix-stat_summary_two---do-transform-after-summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Proposed fix: &lt;code&gt;stat_summary_two&lt;/code&gt; - do &lt;em&gt;transform-after-summary&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Below is my adapted version of &lt;code&gt;stat_summary&lt;/code&gt; - the key user-facing change is the addition &lt;code&gt;transform.after.summary&lt;/code&gt; option. This defaults to TRUE, but can be set to FALSE to mimic the behaviour of the original &lt;code&gt;stat_summary&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By the time &lt;code&gt;ggplot&lt;/code&gt; processing gets to &lt;code&gt;compute_panel&lt;/code&gt; it has already transformed the data. To work around this,
we manually apply the inverse transform to get back the original data. This original data is them summarised and the results
are transformed back into the requested scale.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Summarise y values at unique/binned x
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stat_summary_two &amp;lt;- function(mapping = NULL, data = NULL,
                         geom = &amp;quot;pointrange&amp;quot;, position = &amp;quot;identity&amp;quot;,
                         ...,
                         fun.data = NULL,
                         fun.y = NULL,
                         fun.ymax = NULL,
                         fun.ymin = NULL,
                         fun.args = list(),
                         na.rm = FALSE,
                         transform.after.summary = TRUE,
                         show.legend = NA,
                         inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatSummaryTwo,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      fun.data = fun.data,
      fun.y = fun.y,
      fun.ymax = fun.ymax,
      fun.ymin = fun.ymin,
      fun.args = fun.args,
      na.rm = na.rm,
      transform.after.summary = transform.after.summary,
      ...
    )
  )
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ggproto Stat
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StatSummaryTwo &amp;lt;- ggproto(
  &amp;quot;StatSummaryTwo&amp;quot;, Stat,
  required_aes = c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;),
  
  compute_panel = function(data, scales, fun.data = NULL, fun.y = NULL,
                           fun.ymax = NULL, fun.ymin = NULL, fun.args = list(),
                           na.rm = FALSE, transform.after.summary = TRUE) {
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # The `data` we have in this function has already been transformed, so
    # let&amp;#39;s untransform it
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (transform.after.summary) {
      data$y &amp;lt;- scales$y$trans$inverse(data$y)
    }
    
    fun &amp;lt;- ggplot2:::make_summary_fun(fun.data, fun.y, fun.ymax, fun.ymin, fun.args)
    res &amp;lt;- ggplot2:::summarise_by_x(data, fun)
    
    if (transform.after.summary) {
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # Transform the summary of the raw data into the final scale
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      res$y    &amp;lt;- scales$y$trans$transform(res$y)
      res$ymin &amp;lt;- scales$y$trans$transform(res$ymin)
      res$ymax &amp;lt;- scales$y$trans$transform(res$ymax)
    }
    
    res
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(plot_df, aes(x, y)) + 
  geom_point(alpha=0.6) +
  stat_summary(fun.y = mean, geom=&amp;#39;line&amp;#39;) +
  stat_summary_two(fun.y = mean, geom=&amp;#39;line&amp;#39;, colour=&amp;#39;darkgreen&amp;#39;, linetype=2) +
  scale_y_sqrt(breaks=0:9) +
  ggtitle(&amp;quot;Green dotted line: correct mean result - `stat_summary_two` (transform-after-summary)\nBlack line: incorrect `stat_summary` result (summary-after-transform)&amp;quot;)  + 
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;when-stat_summary_two-will-fail&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;When &lt;code&gt;stat_summary_two&lt;/code&gt; will fail&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;stat_summary_two&lt;/code&gt; relies on being able to take the inverse transform to get
back the original data, but that won’t always work.&lt;/p&gt;
&lt;p&gt;Consider the following example where a transform followed by its inverse doesn’t
get us the original data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;transform &amp;lt;- function(x) {sqrt(x)}
inverse   &amp;lt;- function(x) {x * x}

original &amp;lt;- -2:2
inverse(transform(original))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] NaN NaN   0   1   2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that there can still be original that we cannot recover
to use for the summary calculation in &lt;code&gt;stat_summary_two&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;another-proposed-fix-make-scaling-keep-original-data---stat_summary_three&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Another proposed fix: make scaling keep original data - &lt;code&gt;stat_summary_three&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Below is another version of &lt;code&gt;stat_summary&lt;/code&gt;. This version is more robust than
&lt;code&gt;stat_summary_two&lt;/code&gt; in that there is no need to inverse transform the data to
get back the original values to summarise.&lt;/p&gt;
&lt;p&gt;In this version, &lt;code&gt;scales_transform_df&lt;/code&gt; has been changed to keep the original version of any variable that
was transformed.&lt;/p&gt;
&lt;p&gt;Again, changes need to be made in &lt;code&gt;StatSummaryThree$compute_panel&lt;/code&gt; to ensure the original data is used
(rather than then transformed data) when &lt;code&gt;transform.after.summary=TRUE&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;scales_transform_df &amp;lt;- function(scales, df) {
  if (ggplot2:::empty(df) || length(scales$scales) == 0) return(df)

  transformed &amp;lt;- unlist(lapply(scales$scales, function(s) s$transform_df(df = df)),
    recursive = FALSE)

  # Keep copies of original/untransformed vars
  varnames &amp;lt;- names(transformed)
  orig &amp;lt;- df[varnames]
  colnames(orig) &amp;lt;- paste(varnames, &amp;quot;orig&amp;quot;, sep=&amp;#39;.&amp;#39;)

  plyr::quickdf(c(transformed, df[setdiff(names(df), names(transformed))], orig))
}

# Inject this function into the ggplot2 package
assignInNamespace(&amp;quot;scales_transform_df&amp;quot;, scales_transform_df, envir=as.environment(&amp;quot;package:ggplot2&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Summarise y values at unique/binned x
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stat_summary_three &amp;lt;- function(mapping = NULL, data = NULL,
                         geom = &amp;quot;pointrange&amp;quot;, position = &amp;quot;identity&amp;quot;,
                         ...,
                         fun.data = NULL,
                         fun.y = NULL,
                         fun.ymax = NULL,
                         fun.ymin = NULL,
                         fun.args = list(),
                         na.rm = FALSE,
                         transform.after.summary = TRUE,
                         show.legend = NA,
                         inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatSummaryThree,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      fun.data = fun.data,
      fun.y = fun.y,
      fun.ymax = fun.ymax,
      fun.ymin = fun.ymin,
      fun.args = fun.args,
      na.rm = na.rm,
      transform.after.summary = transform.after.summary,
      ...
    )
  )
}


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ggproto Stat
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
StatSummaryThree &amp;lt;- ggproto(
  &amp;quot;StatSummaryThree&amp;quot;, Stat,
  required_aes = c(&amp;quot;x&amp;quot;, &amp;quot;y&amp;quot;),
  
  compute_panel = function(data, scales, fun.data = NULL, fun.y = NULL,
                           fun.ymax = NULL, fun.ymin = NULL, fun.args = list(),
                           
                           na.rm = FALSE, transform.after.summary = TRUE) {
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # The `data` we have in this function has already been transformed, so
    # use the original data (which we kept in `transform_df`)
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (transform.after.summary) {
      data$y &amp;lt;- data$y.orig
    }
    
    fun &amp;lt;- ggplot2:::make_summary_fun(fun.data, fun.y, fun.ymax, fun.ymin, fun.args)
    res &amp;lt;- ggplot2:::summarise_by_x(data, fun)
    
    if (transform.after.summary) {
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      # Transform the summary of the raw data into the final scale
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      res$y    &amp;lt;- scales$y$trans$transform(res$y)
      res$ymin &amp;lt;- scales$y$trans$transform(res$ymin)
      res$ymax &amp;lt;- scales$y$trans$transform(res$ymax)
    }
    
    res
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(plot_df, aes(x, y)) + 
  geom_point(alpha=0.6) +
  stat_summary(fun.y = mean, geom=&amp;#39;line&amp;#39;) +
  stat_summary_three(fun.y = mean, geom=&amp;#39;line&amp;#39;, colour=&amp;#39;darkgreen&amp;#39;, linetype=2) +
  scale_y_sqrt(breaks=0:9) +
  ggtitle(&amp;quot;Green dotted line: correct mean result - `stat_summary_three` (transform-after-summary)\nBlack line: incorrect `stat_summary` result (summary-after-transform)&amp;quot;)  + 
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-08-06-ggplot-stat-summary-before-transform_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It’d be nice to have summary stats work on original data rather than transformed data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix: Data&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the plotting data.frame
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plot_df &amp;lt;- data.frame(
  x = rep(1:3, each=7),
  y = c(0, 0, 0, 0, 1, 1, 5,    1, 1, 1, 1, 2, 2, 2,      2, 3, 4, 5, 6, 7, 8)
)



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Calculate the median at each time point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mean_df &amp;lt;- plot_df %&amp;gt;%
  group_by(x) %&amp;gt;%
  summarise(
    y = mean(y),
  ) %&amp;gt;%
  ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-17&#34;&gt;Table 1: &lt;/span&gt;First rows of raw &lt;code&gt;plot_df&lt;/code&gt; data&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-17&#34;&gt;Table 1: &lt;/span&gt;&lt;code&gt;mean_df&lt;/code&gt;: Expected mean at each ‘x’&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.428571&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Encoding and Rendering Grade 1 Braille</title>
      <link>https://coolbutuseless.github.io/2018/07/31/encoding-and-rendering-grade-1-braille/</link>
      <pubDate>Tue, 31 Jul 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/31/encoding-and-rendering-grade-1-braille/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Braille is a tactile writing system used by people who are visually impaired.&lt;/p&gt;
&lt;p&gt;A pattern of 2x3 dots is used to encode symbols, letters, words and language. The current(?) standard(?)
for the English language is &lt;a href=&#34;http://www.iceb.org/Rules%20of%20Unified%20English%20Braille%202013.pdf&#34;&gt;Unified English Braille&lt;/a&gt;,
although &lt;a href=&#34;https://en.wikipedia.org/wiki/Nemeth_Braille&#34;&gt;Nemeth Braille&lt;/a&gt; seems to be a slightly different standard
which still appears popular for encoding mathematical notion.&lt;/p&gt;
&lt;p&gt;Disclaimer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m only looking at simple Grade 1 encoding (i.e. letter-by-letter transcription)&lt;/li&gt;
&lt;li&gt;I realise there are Braille symbols in unicode, but I’m thinking beyond
screen/paper representations, so I want to render my own symbols.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;braille-subset---just-the-lowercase-letters&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Braille subset - just the lowercase letters&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/braille/alphabet.png&#34; width=&#34;45%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;


&lt;/div&gt;
&lt;div id=&#34;defining-a-braille-symbol&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Defining a Braille symbol&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A Braille symbol is made up of 6 dots.&lt;/li&gt;
&lt;li&gt;Therefore, we need only 6 bits to encode it&lt;/li&gt;
&lt;li&gt;Let’s round it up to 8 bits, and store the definition for each symbol in a byte.&lt;/li&gt;
&lt;li&gt;Assign each of the dots a numerical value.&lt;/li&gt;
&lt;li&gt;The numerical representation of a symbol is the sum of its dots&lt;/li&gt;
&lt;li&gt;e.g. 
&lt;ul&gt;
&lt;li&gt;the letter &lt;code&gt;g&lt;/code&gt; is represented by setting the upper 4 dots&lt;/li&gt;
&lt;li&gt;sum of upper 4 dots = 1 + 2 + 4 + 8 = 15&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To turn a symbol back into a sequence of ON/OFF values, use &lt;code&gt;intToBits&lt;/code&gt; e.g.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dots &amp;lt;- intToBits(15)[1:6]
matrix(dots, ncol=2, byrow=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2]
[1,]   01   01
[2,]   01   01
[3,]   00   00&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;exploiting-redundancy&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Exploiting redundancy&lt;/h2&gt;
&lt;p&gt;In the table of all the alphabet Braille symbols in the image above, you can
see that the second set of 10 symbols is just a copy of the first set with
the bottom left dot turned on.&lt;/p&gt;
&lt;p&gt;Similarly the third set of 10 symbols is a copy of the first set but with &lt;em&gt;both&lt;/em&gt;
bottom dots turned on.&lt;/p&gt;
&lt;p&gt;So for my current purposes, it’s only necessary to carefully define the first row,
and then just calculate all other rows from it.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;the-alphabet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The alphabet&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create the first 10 letters of the alphabet by summing the dots in each.&lt;/li&gt;
&lt;li&gt;Create subsequent rows by adding the extra dots that are set for that row.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set1 &amp;lt;- c(1, 5, 3, 11, 9, 7, 15, 13, 6, 14)
set2 &amp;lt;- set1 + 16
set3 &amp;lt;- set1 + 48
set4 &amp;lt;- set1 + 32

# Definition of the first 40 symbols
symbols &amp;lt;- c(set1, set2, set3, set4)

symbols&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1]  1  5  3 11  9  7 15 13  6 14 17 21 19 27 25 23 31 29 22 30 49 53 51 59 57
[26] 55 63 61 54 62 33 37 35 43 41 39 47 45 38 46&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;lookup-table&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Lookup table&lt;/h2&gt;
&lt;p&gt;For historical reasons, the letter &lt;code&gt;w&lt;/code&gt; is totally out of sequence, so the mapping
from letter to symbol is a bit weird.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;letter_to_symbol_idx &amp;lt;- setNames(1:26,letters)
letter_to_symbol_idx[&amp;#39;w&amp;#39;] &amp;lt;- 40
letter_to_symbol_idx[&amp;#39;x&amp;#39;] &amp;lt;- 23
letter_to_symbol_idx[&amp;#39;y&amp;#39;] &amp;lt;- 24
letter_to_symbol_idx[&amp;#39;z&amp;#39;] &amp;lt;- 25

letter_to_symbol_idx&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z 
 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 40 23 24 25 &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;simple-braille-renderer-grade-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Simple Braille Renderer (Grade 1)&lt;/h2&gt;
&lt;p&gt;Split a word into characters and find all the symbols for these characters&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;this_word     &amp;lt;- &amp;quot;braille&amp;quot;
chars         &amp;lt;- strsplit(tolower(this_word),&amp;#39;&amp;#39;)[[1]] 
symbol_idx    &amp;lt;- letter_to_symbol_idx[chars]
these_symbols &amp;lt;- symbols[symbol_idx]

these_symbols&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1]  5 29  1  6 21 21  9&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turn the symbols into ON/OFF dot definitions&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dots &amp;lt;- these_symbols %&amp;gt;% map(~intToBits(.x)[1:6] &amp;gt; 0)
dots&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[[1]]
[1]  TRUE FALSE  TRUE FALSE FALSE FALSE

[[2]]
[1]  TRUE FALSE  TRUE  TRUE  TRUE FALSE

[[3]]
[1]  TRUE FALSE FALSE FALSE FALSE FALSE

[[4]]
[1] FALSE  TRUE  TRUE FALSE FALSE FALSE

[[5]]
[1]  TRUE FALSE  TRUE FALSE  TRUE FALSE

[[6]]
[1]  TRUE FALSE  TRUE FALSE  TRUE FALSE

[[7]]
[1]  TRUE FALSE FALSE  TRUE FALSE FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-data-frame-of-dots-positions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a data frame of dots positions&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Define x and y positions of each dot
x &amp;lt;- c(0, 1, 0, 1, 0, 1)
y &amp;lt;- c(2, 2, 1, 1, 0, 0)


# merge each dot with its (x, y) coordiante,
# and add some spacing to the x cordinate so that
# the characters appear one after the other
plot_df &amp;lt;- data.frame(
  dot = unlist(dots),
  x   = x + rep(seq(dots), e=6) * 3,
  y   = y
)

knitr::kable(head(plot_df))&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;dot&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;x&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;y&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;ggplot&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;ggplot&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Simple plot
ggplot(plot_df) + 
  geom_point(aes(x, y, size=dot)) + 
  coord_equal() + 
  theme_void() +
  ggtitle(this_word) + 
  theme(legend.position = &amp;#39;none&amp;#39;) +
  expand_limits(y=c(-0.5, 2.5))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-31-braille_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-31-braille_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-simple-braille-renderer-grade-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable Simple Braille Renderer (Grade 1)&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats
library(tidyverse)
d=c(1,5,3,11,9,7,15,13,6,14)
d=c(d,d+16,d+48,d+32)
L=setNames(c(1:22,40,23:25),letters)
D=map(d[L[strsplit(&amp;#39;braille&amp;#39;,&amp;#39;&amp;#39;)[[1]]]],~intToBits(.x)[1:6]&amp;gt;0)
P=data.frame(D=unlist(D),x=0:1+rep(seq(D),e=6)*3,y=rep(2:0,e=2))
ggplot(P)+geom_point(aes(x,y,size=D))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: Using size for a discrete variable is not advised.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-31-braille_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-free-to-a-good-home&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea (free to a good home)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Translation of R plotmath expressions to &lt;a href=&#34;https://en.wikipedia.org/wiki/Nemeth_Braille&#34;&gt;Nemeth Braille&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>pipe - rewriting nested function calls with pipes</title>
      <link>https://coolbutuseless.github.io/2018/07/27/pipe-rewriting-nested-function-calls-with-pipes/</link>
      <pubDate>Fri, 27 Jul 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/27/pipe-rewriting-nested-function-calls-with-pipes/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;pipe---replacing-nested-function-calls-with-the-pipe-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;pipe()&lt;/code&gt; - Replacing nested function calls with the pipe operator&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is the inverse of &lt;a href=&#34;https://coolbutuseless.github.io/2018/07/26/unpipe---rewriting-an-expression-without-the-pipes/&#34;&gt;yesterday’s code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I’m trying to wrap my head around some parts of the &lt;code&gt;rlang&lt;/code&gt; package so I
set myself a task to focus my exploration: &lt;strong&gt;Auto-rewrite nested function calls into a chain of piped function calls&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;pipe&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;pipe()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# pipe - Auto-rewrite a nested function calls as a chain of piped function calls
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pipe &amp;lt;- function(ee) {
  if (!rlang::is_call(ee)) { 
    return(ee) 
  }
  
  this_fn &amp;lt;- rlang::call_name(ee)
  updated_args &amp;lt;- rlang::call_args(ee) %&amp;gt;% map(pipe)
  
  if (identical(this_fn, &amp;quot;%&amp;gt;%&amp;quot;) || length(updated_args)==0) {
    rlang::call2(this_fn, !!!updated_args)
  } else {
    arg1       &amp;lt;- updated_args[[1]]
    other_args &amp;lt;- updated_args[-1] 
    rlang::call2(as.name(&amp;quot;%&amp;gt;%&amp;quot;), arg1, rlang::call2(this_fn, !!!other_args)  )
  } 
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;nested_funcs &amp;lt;- quote(mean(runif(sample.int(10, sf())), na.rm=TRUE))

pipe(nested_funcs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10 %&amp;gt;% sample.int(sf()) %&amp;gt;% runif() %&amp;gt;% mean(na.rm = TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Re-defining &#39;return()&#39;</title>
      <link>https://coolbutuseless.github.io/2018/07/27/re-defining-return/</link>
      <pubDate>Fri, 27 Jul 2018 18:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/27/re-defining-return/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;R has a number of reserved words which are core to the language and cannot be redefined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;According to &lt;a href=&#34;https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Reserved-words&#34;&gt;R langauge definition&lt;/a&gt;
these are:&lt;/p&gt;
&lt;p&gt;if else repeat while function for in next break
TRUE FALSE NULL Inf NaN
NA NA_integer_ NA_real_ NA_complex_ NA_character_
… ..1 ..2 etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;return()&lt;/code&gt; is not reserved which means we can redefine it. Note: This is a &lt;strong&gt;bad idea&lt;/strong&gt; (tm)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;why-you-might-think-this-is-useful.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why you might think this is useful.&lt;/h2&gt;
&lt;p&gt;I immediately thought that redefining &lt;code&gt;return()&lt;/code&gt; could be useful by allowing you
to intercept the return and do some logging or add meta-information (like a timestamp).&lt;/p&gt;
&lt;p&gt;However, this won’t work, because if you redefine &lt;code&gt;return()&lt;/code&gt; then when your custom
function returns to the function from which it was called, it keeps executing
that original function! i.e. it doesn’t actually do the real return!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;return &amp;lt;- function(x) {print(&amp;quot;Write something to a log file...&amp;quot;)}

myfun &amp;lt;- function(x) {
  return(x)
  print(&amp;quot;This line should not run&amp;quot;)
}

myfun(1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;Write something to a log file...&amp;quot;
[1] &amp;quot;This line should not run&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;malicious-redefinition&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Malicious redefinition&lt;/h2&gt;
&lt;p&gt;And so the only point seems to be able to write malicious code that will
never return properly but will definitely corrupt any results when the original function drops
off the end.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# redefine &amp;#39;return&amp;#39; and make things awful for everyone
return &amp;lt;- function(x) {
  switch(typeof(x),
         &amp;#39;double&amp;#39;    = x + runif(1, max=100),
         &amp;#39;integer&amp;#39;   = x + as.integer(runif(1, max=100)),
         &amp;#39;character&amp;#39; = {x[1] &amp;lt;- &amp;#39;always&amp;#39;; x},
         &amp;#39;logical&amp;#39;   = !x,
         x)
}


myfun &amp;lt;- function(x) {
  return(x)
}

myfun(c(1L, 2L, 3L))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 27 28 29&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;myfun(c(TRUE, TRUE, FALSE))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE FALSE  TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;myfun(c(&amp;quot;never&amp;quot;, &amp;quot;do&amp;quot;, &amp;quot;this&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;always&amp;quot; &amp;quot;do&amp;quot;     &amp;quot;this&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;prevention&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Prevention?&lt;/h2&gt;
&lt;p&gt;So how could we prevent redefinition of &lt;code&gt;return()&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/geospacedman&#34;&gt;geospacedman&lt;/a&gt;’s solution from twitter was neat: always use &lt;code&gt;base::return(x)&lt;/code&gt; to
return from a function.&lt;/p&gt;
&lt;p&gt;This should be perfectly safe and unsinkable. (Narrator: it is not.)&lt;/p&gt;
&lt;p&gt;By default ‘return()’ will be the one defined in the .Globalenv&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;return &amp;lt;- function(x) { stop(&amp;quot;&amp;lt;nelson&amp;gt;Ha Ha!&amp;lt;/nelson&amp;gt;&amp;quot;) }

myfun &amp;lt;- function(x) { return(x) }
myfun(1:3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Error in return(x): &amp;lt;nelson&amp;gt;Ha Ha!&amp;lt;/nelson&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can force it to call the &lt;code&gt;return()&lt;/code&gt; defined in ‘base’ package.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;myfun &amp;lt;- function(x) { base::return(x) }
myfun(1:3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we could overwrite the version of &lt;code&gt;return()&lt;/code&gt; in the ‘base’ package.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;unlockBinding(&amp;quot;return&amp;quot;, baseenv()) # Tip: Don&amp;#39;t do this

evil_return &amp;lt;- function(x) { 
  warning(&amp;quot;&amp;lt;nelson&amp;gt;Ha Ha!&amp;lt;/nelson&amp;gt;&amp;quot;) 
  x
}
  
assign(&amp;quot;return&amp;quot;, evil_return, pos=baseenv())


myfun &amp;lt;- function(x) { base::return(x) }
myfun(1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;[1] 1
Warning message:
In base::return(x) : &amp;lt;nelson&amp;gt;Ha Ha!&amp;lt;/nelson&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;its-evilness-all-the-way-down&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;It’s evilness all the way down&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We could also redefine &lt;code&gt;::&lt;/code&gt; so that the &lt;code&gt;return()&lt;/code&gt; function in ‘base’ is never touched&lt;/li&gt;
&lt;li&gt;We’re screwed.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;evil_return &amp;lt;- function(x) { 4:6 }

`::` &amp;lt;- function(pkg, name) { evil_return }


myfun &amp;lt;- function(x) { base::return(x) }
myfun(1:3)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 4 5 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;the-only-code-where-it-is-sensible-to-re-define-return&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The only code where it is sensible to re-define &lt;code&gt;return()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The following is the only #rstats code in existence where 
# you are allowed to redefine the value of &amp;#39;return&amp;#39; 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return  &amp;lt;- function(return) {return + 1}

totally_sensible_function &amp;lt;- function() {
  &amp;#39;+&amp;#39; &amp;lt;- `*`
  `1` &amp;lt;- 2
  return &amp;lt;- `1` + `1` + `1` + `1`
  return(return)
}

totally_sensible_function()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 17&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;code-smells&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code smells&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/jennybryan&#34;&gt;JennyBryan’s&lt;/a&gt; great User2018 talk on code smells
suggested using the s3 class system to make code more readable.&lt;/li&gt;
&lt;li&gt;Pro Tip: If you’re redefining return, there ain’t nothing going to reduce that code smell.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;return           &amp;lt;- function(x) { UseMethod(&amp;#39;return&amp;#39;) }
return.default   &amp;lt;- function(x) {x}
return.integer   &amp;lt;- function(x) {x + 1}
return.numeric   &amp;lt;- function(x) {x + 2}
return.character &amp;lt;- function(x) {x[1] &amp;lt;- &amp;#39;hello&amp;#39;; x}
return.logical   &amp;lt;- function(x) {!x}

myfun &amp;lt;- function(x) {
  return(x)
}

myfun(1L)
[1] 2
myfun(1.0)
[1] 3
myfun(&amp;quot;goodbye&amp;quot;)
[1] &amp;quot;hello&amp;quot;
myfun(TRUE)
[1] FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Redefining &lt;code&gt;return()&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It’s a bad idea.&lt;/li&gt;
&lt;li&gt;Don’t do it.&lt;/li&gt;
&lt;li&gt;It has no upsides.&lt;/li&gt;
&lt;li&gt;The only use-cases seem to be malicious&lt;/li&gt;
&lt;li&gt;There’s no way to prevent it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>unpipe - rewriting an expression without the pipes</title>
      <link>https://coolbutuseless.github.io/2018/07/26/unpipe-rewriting-an-expression-without-the-pipes/</link>
      <pubDate>Thu, 26 Jul 2018 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/26/unpipe-rewriting-an-expression-without-the-pipes/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;playing-with-rlang-package---removing-the-pipe-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Playing with &lt;code&gt;rlang&lt;/code&gt; package - Removing the pipe operator&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I’m trying to wrap my head around some parts of the &lt;code&gt;rlang&lt;/code&gt; package so I
set myself a task to focus my exploration: &lt;strong&gt;Auto-rewrite a chain of piped functions as a set of nested function calls&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;unpipe&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;unpipe&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# unpipe - rewrite a chain of piped functions as a set of nested function calls
#
# A recursive function that descends through the language tree and flips 
# arguments
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
unpipe &amp;lt;- function(ee) {
  if (!rlang::is_call(ee)) { 
    return(ee) 
  }
  
  this_fn &amp;lt;- rlang::call_name(ee)
  updated_args &amp;lt;- rlang::call_args(ee) %&amp;gt;% map(unpipe)
  
  if (identical(this_fn, &amp;quot;%&amp;gt;%&amp;quot;)) {
    lhs &amp;lt;- updated_args[[1]]
    rhs &amp;lt;- updated_args[[2]]
    if (rlang::is_call(rhs)) {
      rlang::call2(call_name(rhs), !!!c(lhs, call_args(rhs)))
    } else {
      rlang::call2(rhs, lhs)
    }
  } else {
    rlang::call2(this_fn, !!!updated_args)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Improbable test chain with a variety of lhs/rhs arguments to a pipe
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chain &amp;lt;- quote(
  1:3 %&amp;gt;% 
    mean(na.rm=TRUE) %&amp;gt;% 
    print %&amp;gt;% 
    filter(hello == median(zz))
)


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# unpipe this chain
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
chain&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;1:3 %&amp;gt;% mean(na.rm = TRUE) %&amp;gt;% print %&amp;gt;% filter(hello == median(zz))&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;unpipe(chain)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;filter(print(mean(1:3, na.rm = TRUE)), hello == median(zz))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-unpipe&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable &lt;code&gt;unpipe()&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats #unpipe
library(rlang)
U=function(ee){A=call_args;N=call_name;C=call2;I=is_call
if(!I(ee)){return(ee)}
f=N(ee)
u=purrr::map(A(ee),U)
if(f==&amp;quot;%&amp;gt;%&amp;quot;){l=u[[1]]
r=u[[2]]
if(I(r)){C(N(r),!!!c(l,A(r)))}else{C(r,l)}}else{C(f,!!!u)}}

U(quote(1:3 %&amp;gt;% mean(na.rm=TRUE) %&amp;gt;% print))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;print(mean(1:3, na.rm = TRUE))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Shortest unique prefix - it&#39;s a builtin function</title>
      <link>https://coolbutuseless.github.io/2018/07/24/shortest-unique-prefix-its-a-builtin-function/</link>
      <pubDate>Tue, 24 Jul 2018 20:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/24/shortest-unique-prefix-its-a-builtin-function/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;shortest-unique-prefix---hack-part-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shortest unique prefix - hack part #3&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I want to find the shortest unique prefix for each string in a vector (N &amp;lt; 20)
&lt;ul&gt;
&lt;li&gt;i.e. in a vector of strings, what’s the shortest a string can be and still
match only itself&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;This isn’t a computational bottleneck in the overall process, so there’s no need for heroic/drastic solutions.&lt;/li&gt;
&lt;li&gt;I wasn’t going to write a &lt;em&gt;trie&lt;/em&gt; implementation just to solve this problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/23/shortest-unique-prefix/&#34;&gt;Yesterday’s solution&lt;/a&gt; got a bit ugly.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/24/shortest-unique-prefix---second-attempt/&#34;&gt;Earlier today&lt;/a&gt; I got all cute using &lt;code&gt;charmatch()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And now I’ve just discovered that there’s a function in base R that already does this. (Thanks to &lt;a href=&#34;https://twitter.com/mdsumner&#34;&gt;mdsummer&lt;/a&gt; for pointing this out)&lt;/p&gt;
&lt;p&gt;Feeling a bit silly now.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;abbreviate(c(&amp;quot;ab&amp;quot;, &amp;quot;apple&amp;quot;, &amp;quot;apart&amp;quot;, &amp;#39;b&amp;#39;, &amp;#39;ag&amp;#39;), use.classes = FALSE, minlength = 1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;   ab apple apart     b    ag 
 &amp;quot;ab&amp;quot; &amp;quot;app&amp;quot; &amp;quot;apa&amp;quot;   &amp;quot;b&amp;quot;  &amp;quot;ag&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;abbreviate(c(&amp;#39;blue&amp;#39;, &amp;#39;black&amp;#39;, &amp;#39;bold&amp;#39;)          , use.classes = FALSE, minlength = 1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; blue black  bold 
&amp;quot;blu&amp;quot; &amp;quot;bla&amp;quot;  &amp;quot;bo&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Shortest unique prefix - second attempt</title>
      <link>https://coolbutuseless.github.io/2018/07/24/shortest-unique-prefix-second-attempt/</link>
      <pubDate>Tue, 24 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/24/shortest-unique-prefix-second-attempt/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;shortest-unique-prefix---hack-part-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shortest unique prefix - hack part #2&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I want to find the shortest unique prefix for each string in a vector (N &amp;lt; 20)
&lt;ul&gt;
&lt;li&gt;i.e. in a vector of strings, what’s the shortest a string can be and still
match only itself&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;This isn’t a computational bottleneck in the overall process, so there’s no need for heroic/drastic solutions.&lt;/li&gt;
&lt;li&gt;I wasn’t going to write a &lt;em&gt;trie&lt;/em&gt; implementation just to solve this problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/23/shortest-unique-prefix/&#34;&gt;Yesterday’s solution&lt;/a&gt; got a bit ugly.&lt;/p&gt;
&lt;p&gt;Today I remembered &lt;strong&gt;there’s always the function you need in base R&lt;/strong&gt;, and found &lt;code&gt;pmatch()&lt;/code&gt; and &lt;code&gt;charmatch()&lt;/code&gt; which
do partial string matching.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;charmatch&lt;/code&gt; seeks matches for the elements of its first argument among those of its second.
If there is a single exact match or a unique partial match, then the index of the matching value is returned.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;charmatch&lt;/code&gt; does all the heavy lifting of matching a full set of prefixes against the full set of strings. Since
the creation of all the prefixes is done from shortest to longest, then the first prefix that matches only a single
string is the shortest unique prefix for that string.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Shortest Unique Prefix
#
# - Number of strings is always &amp;lt; 20
# - &amp;#39;strings&amp;#39; input does not contain duplicates
# - this isn&amp;#39;t a computational bottleneck in the process, so any neat solution
#   is acceptable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
find_shortest_unique_prefix &amp;lt;- function(strings) {
  
  stopifnot(!any(duplicated(strings)))
  
  # Calculate all possible prefixes of all strings
  all_prefixes &amp;lt;- strings %&amp;gt;% 
    map(str_sub, end=seq(max(nchar(strings)))) %&amp;gt;%
    flatten_chr()
  
  # find &amp;#39;charmatch&amp;#39;es
  matches &amp;lt;- charmatch(all_prefixes, strings) 
  idx     &amp;lt;- !duplicated(matches) &amp;amp; matches!=0
  
  all_prefixes[idx]
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_shortest_unique_prefix(c(&amp;quot;ab&amp;quot;, &amp;quot;apple&amp;quot;, &amp;quot;apart&amp;quot;, &amp;#39;b&amp;#39;, &amp;#39;ag&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;ab&amp;quot;  &amp;quot;app&amp;quot; &amp;quot;apa&amp;quot; &amp;quot;b&amp;quot;   &amp;quot;ag&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_shortest_unique_prefix(c(&amp;#39;blue&amp;#39;, &amp;#39;black&amp;#39;, &amp;#39;bold&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;blu&amp;quot; &amp;quot;bla&amp;quot; &amp;quot;bo&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Shortest unique prefix</title>
      <link>https://coolbutuseless.github.io/2018/07/23/shortest-unique-prefix/</link>
      <pubDate>Mon, 23 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/23/shortest-unique-prefix/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;shortest-unique-prefix---hack&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Shortest unique prefix - hack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I want to find the shortest unique prefix for each string in a vector (N &amp;lt; 20).&lt;/li&gt;
&lt;li&gt;This isn’t a computational bottleneck, so no need for heroic/drastic solutions.&lt;/li&gt;
&lt;li&gt;I wasn’t going to write a &lt;em&gt;trie&lt;/em&gt; implementation just to solve this problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately, this got a bit ugly :( .Anyone got a more elegant solution?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Shortest Unique Prefix
#
# - Number of strings is always &amp;lt; 20
# - &amp;#39;strings&amp;#39; input does not contain duplicates
# - this isn&amp;#39;t a computational bottleneck
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
find_shortest_unique_prefix &amp;lt;- function(strings) {
  
  # Determine uniqueness boolean vector of a set of arguments
  is_unique &amp;lt;- function(...) {x &amp;lt;- list(...); !(duplicated(x) | duplicated(x, fromLast=TRUE))}
  
  # for each possible prefix length, truncate all the strings
  # and see which of them are unique
  prefix_uniqueness &amp;lt;- strings %&amp;gt;% 
    map(str_sub, end=seq(max(nchar(strings)))) %&amp;gt;%
    pmap(is_unique) %&amp;gt;%
    transpose() 
  
  # Find the first occurrence of each string being unique
  shortest_prefix_length &amp;lt;- prefix_uniqueness %&amp;gt;% 
    map_int(
      ~.x %&amp;gt;% flatten_lgl() %&amp;gt;% which.max()
    )
  
  # Trim all the strings to the shortest prefix length
  shortest_prefix &amp;lt;- stringr::str_sub(strings, end=shortest_prefix_length)
  
  shortest_prefix
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_shortest_unique_prefix(c(&amp;quot;ab&amp;quot;, &amp;quot;apple&amp;quot;, &amp;quot;apart&amp;quot;, &amp;#39;b&amp;#39;, &amp;#39;ag&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;ab&amp;quot;  &amp;quot;app&amp;quot; &amp;quot;apa&amp;quot; &amp;quot;b&amp;quot;   &amp;quot;ag&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;find_shortest_unique_prefix(c(&amp;#39;blue&amp;#39;, &amp;#39;black&amp;#39;, &amp;#39;bold&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;blu&amp;quot; &amp;quot;bla&amp;quot; &amp;quot;bo&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducting the &#39;funcmath&#39; package for creating plotmath expression</title>
      <link>https://coolbutuseless.github.io/2018/07/18/introducting-the-funcmath-package-for-creating-plotmath-expression/</link>
      <pubDate>Wed, 18 Jul 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/18/introducting-the-funcmath-package-for-creating-plotmath-expression/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rationale&lt;/h2&gt;
&lt;p&gt;“That’s a compact and expressive DSL you have there for writing math equations
given the constraints of the R language, it’d be a shame if someone were to
expand it into an almost redundant and useless set of functions.” - &lt;strong&gt;#rstats mafia&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;funcmath&lt;/code&gt; is a small library for building plotmath expressions via functions.&lt;/p&gt;
&lt;p&gt;Some programmers use the term &lt;em&gt;convenience functions&lt;/em&gt;
i.e. “A convenience function is a non-essential subroutine in a programming
library or framework which is intended to ease commonly performed tasks.”&lt;/p&gt;
&lt;p&gt;&lt;code&gt;funcmath&lt;/code&gt; is a set of &lt;em&gt;inconvenience functions&lt;/em&gt; to expand the compact plotmath syntax
into a set of functions.&lt;/p&gt;
&lt;p&gt;For example, instead of a nice compact plotmath expression such as:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;m &amp;lt;- bquote(frac(alpha/beta, (1 + 2)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… why not use defined symbols in &lt;code&gt;funcmath&lt;/code&gt; (such as &lt;code&gt;alpha&lt;/code&gt;) and infix functions like &lt;code&gt;%/%&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;m &amp;lt;- frac(alpha %/% beta, b(1 %+% 2)) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-18-funcmath-package-for-creating-plotmath-expressions_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/funcmath&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;actual-rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Actual rationale&lt;/h2&gt;
&lt;p&gt;This work arose out of my attempts at creating fractals with plotmath expressions,
and was not really meant as a way of creating &lt;em&gt;actual&lt;/em&gt; math expressions.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example #1&lt;/h2&gt;
&lt;p&gt;A plotmath expression created using &lt;code&gt;bquote()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# http://lukemiller.org/index.php/2017/05/r-plotmath-functions-combined-with-variable-values/
mymean  &amp;lt;- 1.2345678
mySE    &amp;lt;- 0.55555
mylabel &amp;lt;- bquote(Delta*italic(T)[max]~.(format(mymean,digits=3))*&amp;#39;&amp;#39;%+-%&amp;#39;&amp;#39;*
                .(format(mySE,digits=2))*degree*C)
# plot(mylabel, cex=2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same plotmath expression created via &lt;code&gt;funcmath&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Delta %*% 
  italic(&amp;#39;T&amp;#39;) %_% &amp;#39;max&amp;#39; %space% format(mymean,digits=3) %+-% 
  (format(mySE,digits=2) %*% degree) %*% &amp;#39;C&amp;#39; %&amp;gt;% 
  plot(cex=2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-18-funcmath-package-for-creating-plotmath-expressions_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-2---sierpinski-fractal&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example #2 - Sierpinski Fractal&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;s &amp;lt;- function(x) { x %_% x %^% x }

plot(s(s(s(mu))))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-18-funcmath-package-for-creating-plotmath-expressions_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-3---beta-distribution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example #3 - Beta distribution&lt;/h2&gt;
&lt;p&gt;An issue with the normal way of building plotmaths expressions is that
it is usually all done in one statement, which makes debugging complex math problematic. e.g. beta distribution&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# https://blog.snap.uaf.edu/2013/03/25/mathematical-notation-in-r-plots/
expr.beta &amp;lt;- expression(italic(paste(displaystyle(f(x)~&amp;quot;=&amp;quot;~frac(Gamma(alpha+beta),Gamma(alpha)*Gamma(beta))*x^{alpha-1}*(1-x)^{beta-1})
                    ~~~~displaystyle(list(paste(0&amp;lt;=x) &amp;lt;=1, paste(0&amp;lt;alpha) &amp;lt;infinity, paste(0&amp;lt;beta) &amp;lt;infinity))
                    )))

plot(expr.beta, cex=1.25)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-18-funcmath-package-for-creating-plotmath-expressions_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;p&gt;By exploding plotmath into a set of functions, &lt;code&gt;funcmath&lt;/code&gt; allows you to compose individual parts of an math expression and then
combine them later. Individual parts can be tested separately and finally merged into the total required expression.&lt;/p&gt;
&lt;p&gt;The result is more verbose, uglier and requires learning a whole new set of functions - this is called a &lt;em&gt;win-win-win&lt;/em&gt; situation!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lhs          &amp;lt;- &amp;#39;f&amp;#39; %*% b(&amp;#39;x&amp;#39;)
numerator    &amp;lt;- Gamma %*% b(alpha %+% beta)
denominator  &amp;lt;- (Gamma %*% b(alpha)) %*% (Gamma %*% b(beta))
right        &amp;lt;- &amp;#39;x&amp;#39; %^% (alpha %-% 1) %*% b(1 %-% &amp;#39;x&amp;#39;) %^% (beta %-% 1)
limitx       &amp;lt;- 0 %&amp;lt;=%  &amp;#39;x&amp;#39;  %&amp;lt;=% 1
limitalpha   &amp;lt;- 0 %&amp;lt;&amp;lt;% alpha %&amp;lt;&amp;lt;% infinity
limitbeta    &amp;lt;- 0 %&amp;lt;&amp;lt;% beta  %&amp;lt;&amp;lt;% infinity

limits       &amp;lt;- list_(limitx, limitalpha, limitbeta)

total        &amp;lt;- lhs %eq% (numerator %frac% denominator) %*% right %space4% limits 

styled_total &amp;lt;- italic(displaystyle(total))


plot(styled_total, cex=1.25)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-18-funcmath-package-for-creating-plotmath-expressions_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;turn-the-expression-back-into-a-parseable-string&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Turn the expression back into a parseable string&lt;/h2&gt;
&lt;p&gt;It is possible to turn the created plotmath back into a parseable character string.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pstring &amp;lt;- as_parseable_string(styled_total) 
cat(pstring)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;italic({displaystyle({{{{{f}*{({x})}}=={frac({{Gamma}*{({{alpha}+{beta}})}},{{{Gamma}*{({alpha})}}*{{Gamma}*{({beta})}}})}}*{{{{x}^{{alpha}-{1}}}*{({{1}-{x}})}}^{{beta}-{1}}}}~{~{~{~{list({list({{{0}&amp;lt;={x}}&amp;lt;={1}},{{{0}&amp;lt;{alpha}}&amp;lt;{infinity}})},{{{0}&amp;lt;{beta}}&amp;lt;{infinity}})}}}}})})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;issues&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Issues&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;There are a &lt;strong&gt;lot&lt;/strong&gt; of namespace clashes e.g. &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;paste&lt;/code&gt;, &lt;code&gt;%*%&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;Some names have an appended underscore to avoid clashing with a builtin/common
function i.e. &lt;code&gt;list_&lt;/code&gt; instead of &lt;code&gt;list&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Ikeda map (fractal)</title>
      <link>https://coolbutuseless.github.io/2018/07/09/ikeda-map-fractal/</link>
      <pubDate>Mon, 09 Jul 2018 19:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/09/ikeda-map-fractal/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;generating-an-ikeda-map&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Generating an Ikeda Map&lt;/h2&gt;
&lt;p&gt;Today in my ongoing quest to generate fractals in Rstats using every available avenue: generating an Ikeda map.&lt;/p&gt;
&lt;p&gt;Methods for generating fractals so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski Triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/&#34;&gt;Another sierpinski triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski triangle using character strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices---sierpinski-carpet/&#34;&gt;Using R matrices to create a sierpinski carpet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/06/hilbert-curves/&#34;&gt;Generating hilbert curves with an ad-hoc L-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/07/barnsley-ferns-fractal/&#34;&gt;Barnsley ferns generated by iterated affine transformations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today: Ikeda map&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;ikeda-map&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Ikeda map&lt;/h2&gt;
&lt;p&gt;An &lt;a href=&#34;https://en.wikipedia.org/wiki/Ikeda_map&#34;&gt;Ikeda map&lt;/a&gt; is a model of light going acound a nonlinear optical resonator. To be honest, the wiki page and the original paper by Ikeda are impenetrable to me!&lt;/p&gt;
&lt;p&gt;However, creating the map is relatively straightforward.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Start at a random point&lt;/li&gt;
&lt;li&gt;Update the position of the point&lt;/li&gt;
&lt;li&gt;Continue updating the point’s position for N steps&lt;/li&gt;
&lt;li&gt;Draw the path joining all the positions of this point&lt;/li&gt;
&lt;li&gt;Repeat steps 1-4&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#&amp;#39; Computing a single path from the given starting point
#&amp;#39;
#&amp;#39; @param u ikeda parameter
#&amp;#39; @param x,y starting point
#&amp;#39; @param N is the number of iterations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compute_ikeda_trajectory &amp;lt;- function(u=0.918, x1, y1, N) {
  x    &amp;lt;- y &amp;lt;- double(N)
  x[1] &amp;lt;- x1
  y[1] &amp;lt;- y1

  for (i in 2:N) {
    t    &amp;lt;- 0.4 - 6/(1 + x[i-1]*x[i-1] + y[i-1]*y[i-1])
    x[i] &amp;lt;- 1 + u * (x[i-1] * cos(t) - y[i-1] * sin(t))
    y[i] &amp;lt;-     u * (x[i-1] * sin(t) + y[i-1] * cos(t))
  }

  data_frame(x=x, y=y)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate P random starting points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
P &amp;lt;- 2000  # Number of starting  points
N &amp;lt;- 1000  # Number of iterations of each point
set.seed(1)
x &amp;lt;- rnorm(P) * 10
y &amp;lt;- rnorm(P) * 10


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate the P paths from the random starting points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res &amp;lt;- seq(P) %&amp;gt;%
  map(~compute_ikeda_trajectory(u=0.928, x[.x], y[.x], N))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot all the paths
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
par(pty=&amp;#39;s&amp;#39;,bg=&amp;#39;black&amp;#39;)
plot(0, type=&amp;#39;n&amp;#39;, as=1, xlim=c(-10, 10), ylim=c(-10, 10))
res %&amp;gt;% walk(~lines(.x, col=&amp;#39;#ffffff08&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-08-ikeda-map_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-ikeda-map&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable Ikeda map&lt;/h2&gt;
&lt;p&gt;This one was a hell of a squeeze to get it into a tweet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;1e3&lt;/code&gt; instead of &lt;code&gt;1000&lt;/code&gt; to save a single character.&lt;/li&gt;
&lt;li&gt;Drop leading &lt;code&gt;0&lt;/code&gt; from &lt;code&gt;0.9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;rep(0,N)&lt;/code&gt; instead of &lt;code&gt;double(N)&lt;/code&gt; to save a single character&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;lst&lt;/code&gt; instead of &lt;code&gt;tibble&lt;/code&gt; or &lt;code&gt;data.frame&lt;/code&gt; to save at least 3 chars&lt;/li&gt;
&lt;li&gt;Dropping from &lt;code&gt;10&lt;/code&gt; to &lt;code&gt;9&lt;/code&gt; as a multiplier to trip a single digit each time.&lt;/li&gt;
&lt;li&gt;Came out at exactly 280 characters!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update&lt;/strong&gt; Thanks to &lt;a href=&#34;https://twitter.com/carroll_jono&#34;&gt;Jonathan Carroll&lt;/a&gt; for pointing out a shorter way to call &lt;code&gt;map2&lt;/code&gt; it’s
down to 272 characters which means I can include the &lt;strong&gt;#rstats&lt;/strong&gt; hashtag! (which then brings it back up to 280 characters)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats
library(tidyverse)
N=1e3
x=y=rep(0,N)
F=function(X,Y){x[1]=X
y[1]=Y
for(i in 2:N){X=x[i-1];Y=y[i-1]
t=.4-6/(1+X^2+Y^2)
S=sin(t);C=cos(t)
x[i]=1+.9*(X*C-Y*S)
y[i]=.9*(X*S+Y*C)}
lst(x,y)}
r=rnorm
plot(0,as=1,yli=c(-9,9))
walk(map2(r(N)*9,r(N)*9,F),~lines(.x,co=&amp;#39;#00000010&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-08-ikeda-map_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Barnsley Ferns (fractal)</title>
      <link>https://coolbutuseless.github.io/2018/07/07/barnsley-ferns-fractal/</link>
      <pubDate>Sat, 07 Jul 2018 07:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/07/barnsley-ferns-fractal/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;barnsley-fern-via-iterated-affine-transformations-matrix-ops&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Barnsley fern via iterated affine transformations (matrix ops)&lt;/h2&gt;
&lt;p&gt;Today in my ongoing quest to generate fractals in Rstats using every available avenue: generating Barnsley ferns via iterated affine transformations (matrix ops)&lt;/p&gt;
&lt;p&gt;Methods for generating fractals so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski Triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/&#34;&gt;Another sierpinski triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski triangle using character strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices---sierpinski-carpet/&#34;&gt;Using R matrices to create a sierpinski carpet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/06/hilbert-curves/&#34;&gt;Generating hilbert curves with an ad-hoc L-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today: Barnsley fern generated by iterated affine transformations&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;barnsley-ferns&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Barnsley ferns&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Barnsley_fern&#34;&gt;Barnsley ferns&lt;/a&gt; are fractals generated by an iterated function system.&lt;/p&gt;
&lt;p&gt;Generation of the fractal consists of just 2 repeated steps:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Randomly choose an affine transformation from a set of transformations.&lt;/li&gt;
&lt;li&gt;Apply the transformation to the current point to find the next point.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 4 Transformations i.e. p(n+1) = A * p(n) + a
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A &amp;lt;- matrix(c( 0   ,  0   ,  0   , 0.16), nrow=2); a = c(0, 0.00); pa = 0.01
B &amp;lt;- matrix(c( 0.85, -0.04,  0.04, 0.85), nrow=2); b = c(0, 1.60); pb = 0.85
C &amp;lt;- matrix(c( 0.20,  0.23, -0.26, 0.22), nrow=2); c = c(0, 1.60); pc = 0.07
D &amp;lt;- matrix(c(-0.15,  0.26,  0.28, 0.24), nrow=2); d = c(0, 0.44); pd = 0.07
K &amp;lt;- list(A, B, C, D)
k &amp;lt;- list(a, b, c, d)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Each iteration produces a single point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
N &amp;lt;- 100000

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Each iteration uses a randomly selected transformation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
s &amp;lt;- sample(1:4, N, prob = c(pa, pb, pc, pd), replace = TRUE)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Allocate space for the iterated points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
P &amp;lt;- matrix(0, nrow=2, ncol=N+1)
for (i in seq(N)) {
  M = K[[s[i]]]
  m = k[[s[i]]]
  P[,i+1] = M %*% P[,i] + m
}

plot(P[1,], P[2,],as=1,pch=&amp;#39;.&amp;#39;,an=F,ax=F)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-07-barnsley-fern_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;mutant-varieties&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Mutant Varieties&lt;/h2&gt;
&lt;p&gt;By tweaking the affine transformations, new fern varieties can be created.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;A &amp;lt;- matrix(c( 0    ,  0    ,  0    , 0.25),nr=2); a = c( 0    , -0.4 ); pa = 0.02
B &amp;lt;- matrix(c( 0.95 ,  0.005, -0.005, 0.93),nr=2); b = c(-0.002,  0.5 ); pb = 0.84
C &amp;lt;- matrix(c( 0.035, -0.2  ,  0.16 , 0.04),nr=2); c = c(-0.09 ,  0.02); pc = 0.07
D &amp;lt;- matrix(c(-0.04 ,  0.2  ,  0.16 , 0.04),nr=2); d = c( 0.083,  0.12); pd = 0.07&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-07-barnsley-fern_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-barnsley-fern&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable barnsley fern&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats
m=matrix
z=0.2
K=list(m(c(0,0,0,z),2),m(c(0.8,-z,z,0.8),2),m(c(z,z,-z,z),2),m(c(-z,z,z,z),2))
k=list(c(0,0),c(0,2),c(0,2),c(0,0.4))
N=1e5
s=sample(1:4,N,T,c(1,85,7,7)/100)
P=m(0,2,N+1)
for (i in 1:N)P[,i+1]=K[[s[i]]]%*%P[,i]+k[[s[i]]]
plot(t(P),as=1,pch=&amp;#39;.&amp;#39;,ax=F,an=F)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-07-barnsley-fern_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Hilbert Curves</title>
      <link>https://coolbutuseless.github.io/2018/07/06/hilbert-curves/</link>
      <pubDate>Fri, 06 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/06/hilbert-curves/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;hilbert-curves-with-an-ad-hoc-l-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hilbert curves with an ad-hoc L-system&lt;/h2&gt;
&lt;p&gt;Today in my ongoing quest to generate fractals in Rstats using every available avenue: generating a hilbert curve using an ad-hoc L-system&lt;/p&gt;
&lt;p&gt;Methods for generating fractals so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski Triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/&#34;&gt;Another sierpinski triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski triangle using character strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices---sierpinski-carpet/&#34;&gt;Using R matrices to create a sierpinski carpet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today: Generating hilbert curves with an ad-hoc L-system&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;hilbert-curve&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hilbert Curve&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&#34;https://en.wikipedia.org/wiki/Hilbert_curve&#34;&gt;Hilbert Curve&lt;/a&gt; is a fractal space-filling curve
that looks like a classic 70s wallpaper pattern.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/hilbert/hilbert.png&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;


&lt;/div&gt;
&lt;div id=&#34;l-systems&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;L-systems&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/L-system&#34;&gt;L-systems&lt;/a&gt; consist of:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;strong&gt;Alphabet&lt;/strong&gt; - the set of symbols to be manipulated&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Axiom&lt;/strong&gt; - the initial state of the system&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production Rules&lt;/strong&gt; - how to map from one state to the next&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is, starting with an &lt;em&gt;axiom&lt;/em&gt;, subsequent iterations are generated by applying the
&lt;em&gt;Production Rules&lt;/em&gt; over and over. Once the required number of iterations are performed,
the vector of &lt;em&gt;alphabet&lt;/em&gt; characters is rendered graphically (somehow!)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;hilbert-curves-using-l-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hilbert curves using L-system&lt;/h2&gt;
&lt;p&gt;I’m following the L-system for Hilbert curves as described in &lt;a href=&#34;https://arxiv.org/pdf/1304.6296.pdf&#34;&gt;Arie Bos’ paper&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The alphabet -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 - start code&lt;/li&gt;
&lt;li&gt;1/-1 - right/left&lt;/li&gt;
&lt;li&gt;2/-2 - up/down&lt;/li&gt;
&lt;li&gt;3/-3 - right/left&lt;/li&gt;
&lt;li&gt;4/-4 - up/down&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Production rules:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/hilbert/production-rules.png&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;




&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 2. Axiom
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
axiom  &amp;lt;- c(0)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3. Production rules
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr &amp;lt;- list(
  &amp;#39;-4&amp;#39; = -c(3, 2, 1, -4),
  &amp;#39;-3&amp;#39; = -c(4, 2, 1, -4),
  &amp;#39;-2&amp;#39; = -c(1, 3, 4, -1),
  &amp;#39;-1&amp;#39; = -c(2, 3, 4, -1),
   &amp;#39;0&amp;#39; =  c(0, 3, 4, -1),
   &amp;#39;1&amp;#39; =  c(2, 3, 4, -1),
   &amp;#39;2&amp;#39; =  c(1, 3, 4, -1),
   &amp;#39;3&amp;#39; =  c(4, 2, 1, -4),
   &amp;#39;4&amp;#39; =  c(3, 2, 1, -4)
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Function to apply the Production rule
# i.e. lookup each current character and replace it with the 
#      nominated 4 characters
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T &amp;lt;- . %&amp;gt;% purrr::map(~pr[[as.character(.x)]]) %&amp;gt;% flatten_dbl() 

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Apply the production rule a number of times
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
H &amp;lt;- T(T(T(T(T(T(axiom))))))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Table to interpret the alphabet in terms of x,y offsets 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dh &amp;lt;- tribble(
  ~H, ~x, ~y,
  -4,  0, -1,
  -3, -1,  0,
  -2,  0, -1,
  -1, -1,  0,
   0,  0,  0,
   1,  1,  0,
   2,  0,  1,
   3,  1,  0,
   4,  0,  1
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Map the entire string to a path of points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dha &amp;lt;- dh %&amp;gt;% 
  right_join(data_frame(H=H), by=&amp;#39;H&amp;#39;) %&amp;gt;%
  mutate(
    x = cumsum(x),
    y = cumsum(y)
  )&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot it!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggplot(dha) +
  geom_path(aes(x, y)) +
  theme_void() + 
  coord_fixed()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-06-hilbert-curves_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-version---hilbert-curves-in-2d-using-l-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable Version - Hilbert curves in 2D using L-system&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats
library(tidyverse)
A=B=c(2,3,4,-1)
B[1]=1
C=D=c(4,2,1,-4)
D[1]=3
T=.%&amp;gt;%map(~list(-D,-C,-B,-A,c(0,3,4,-1),A,B,C,D)[.x+5])%&amp;gt;%unlist
E=c(0,1,0,1);G=rev(E);M=tibble(H=-4:4,x=c(-E,0,G),y=c(-G,0,E))
M=M[match(T(T(T(T(T(T(0)))))),M$H),-1]
S=cumsum
plot(S(M$x),S(M$y),t=&amp;#39;l&amp;#39;,as=1)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-06-hilbert-curves_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Fractals with matrices - sierpinski carpet</title>
      <link>https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices-sierpinski-carpet/</link>
      <pubDate>Thu, 05 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/05/fractals-with-matrices-sierpinski-carpet/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Today in my ongoing quest to generate fractals in Rstart using every available avenue: generating a sierpinski carpet with matrices.&lt;/p&gt;
&lt;p&gt;Methods so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski Triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/&#34;&gt;Another sierpinski triangle in plotmath&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/07/04/text-fractals---sierpinski/&#34;&gt;Sierpinski triangle using characters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Today: Using R matrices to create a sierpinski carpet&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#rstats #fractal
library(raster)

f &amp;lt;- function(x) {
  z &amp;lt;- x
  z[] &amp;lt;- &amp;#39; &amp;#39;
  rbind(
    cbind(x,x,x),
    cbind(x,z,x),
    cbind(x,x,x)
  )
}

m=matrix(&amp;#39;#&amp;#39;)
m=f(f(f(f(f(m)))))
g=matrix(m==&amp;#39;#&amp;#39;, nrow=nrow(m))
plot(raster(g), ann=F, axes=F, box=F, legend=F)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-05-matrix-fractals_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
</description>

    </item>
    
    <item>
      <title>Text fractals - sierpinski</title>
      <link>https://coolbutuseless.github.io/2018/07/04/text-fractals-sierpinski/</link>
      <pubDate>Wed, 04 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/04/text-fractals-sierpinski/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
s &amp;lt;- function(x, y) {c(x + lag(x, d=0), 1) %% 2}
r &amp;lt;- Reduce(s, 1:63, 1, acc=T)
r &amp;lt;- r %&amp;gt;% map(~paste(ifelse(.x%%2, &amp;#39;#&amp;#39;, &amp;#39; &amp;#39;), collapse=&amp;#39;&amp;#39;))
cat(paste(r, sep=&amp;#39;&amp;#39;, collapse=&amp;#39;\n&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#
##
# #
####
#   #
##  ##
# # # #
########
#       #
##      ##
# #     # #
####    ####
#   #   #   #
##  ##  ##  ##
# # # # # # # #
################
#               #
##              ##
# #             # #
####            ####
#   #           #   #
##  ##          ##  ##
# # # #         # # # #
########        ########
#       #       #       #
##      ##      ##      ##
# #     # #     # #     # #
####    ####    ####    ####
#   #   #   #   #   #   #   #
##  ##  ##  ##  ##  ##  ##  ##
# # # # # # # # # # # # # # # #
################################
#                               #
##                              ##
# #                             # #
####                            ####
#   #                           #   #
##  ##                          ##  ##
# # # #                         # # # #
########                        ########
#       #                       #       #
##      ##                      ##      ##
# #     # #                     # #     # #
####    ####                    ####    ####
#   #   #   #                   #   #   #   #
##  ##  ##  ##                  ##  ##  ##  ##
# # # # # # # #                 # # # # # # # #
################                ################
#               #               #               #
##              ##              ##              ##
# #             # #             # #             # #
####            ####            ####            ####
#   #           #   #           #   #           #   #
##  ##          ##  ##          ##  ##          ##  ##
# # # #         # # # #         # # # #         # # # #
########        ########        ########        ########
#       #       #       #       #       #       #       #
##      ##      ##      ##      ##      ##      ##      ##
# #     # #     # #     # #     # #     # #     # #     # #
####    ####    ####    ####    ####    ####    ####    ####
#   #   #   #   #   #   #   #   #   #   #   #   #   #   #   #
##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##  ##
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
################################################################&lt;/code&gt;&lt;/pre&gt;
</description>

    </item>
    
    <item>
      <title>Plotmath fractals 2</title>
      <link>https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/</link>
      <pubDate>Tue, 03 Jul 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/03/plotmath-fractals-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;tweetable-fractal-in-plotmath---sierpinski-triangle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable Fractal in Plotmath - Sierpinski triangle&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;s &amp;lt;- function(x) bquote(.(x)[.(x)]^.(x))
x &amp;lt;- s(s(s(s(s(s(bquote(mu)))))))
plot(0, type=&amp;quot;n&amp;quot;, xlim=c(0,1), ylim=c(0,1), axes=F, ann=F)
text(0.5, 0.5, x, cex=1.5)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/plotmath-fractal/sierpinski-tweet.png&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;



&lt;p&gt;And this is what the plotmath looks like for this sierpinski triangle&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(((((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^(((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu)[((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu]^((mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu)
[(mu[mu]^mu)[mu[mu]^mu]^mu[mu]^mu]^(mu[mu]^mu)
[mu[mu]^mu]^mu[mu]^mu&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Plotmath fractals</title>
      <link>https://coolbutuseless.github.io/2018/07/02/plotmath-fractals/</link>
      <pubDate>Mon, 02 Jul 2018 21:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/07/02/plotmath-fractals/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;plotmath&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Plotmath&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;plotmath&lt;/code&gt; is a little &lt;em&gt;domain specific language&lt;/em&gt; within R used to define and display
mathematical formula.&lt;/p&gt;
&lt;p&gt;It looks just like R code, but is interpreted in a different context in order to make a
math equation.&lt;/p&gt;
&lt;p&gt;Writing &lt;code&gt;x ^ 2&lt;/code&gt; in R usually tries to evaluate what x-squared is, but in a plotmath expression,
the symbols are interpreted as their relative arrangement in a mathematical formula.&lt;/p&gt;
&lt;p&gt;Rendering the plotmath expression &lt;code&gt;x ^ 2&lt;/code&gt; instructs the plotmath rendering engine (usually via &lt;code&gt;plot()&lt;/code&gt; or &lt;code&gt;ggplot()&lt;/code&gt;)
to write an &lt;code&gt;x&lt;/code&gt; and then write &lt;code&gt;2&lt;/code&gt; as a superscript (as indicated by the &lt;code&gt;^&lt;/code&gt;). This produces the following:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-02-plotmath-1_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-plotmath-expressions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating Plotmath Expressions&lt;/h2&gt;
&lt;p&gt;The most flexible way to create a plotmath expression is to use &lt;code&gt;bquote()&lt;/code&gt; (For a great introduction,
see &lt;a href=&#34;https://trinkerrstuff.wordpress.com/2018/03/15/2246/&#34;&gt;TRinkers R Blog&lt;/a&gt; )&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;bquote(infinity &amp;gt; italic(&amp;quot;Any number you can think of&amp;quot;)^2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-02-plotmath-1_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;recursive-plotmath&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Recursive Plotmath&lt;/h2&gt;
&lt;p&gt;You can put plotmath within other plotmath expressions by using &lt;code&gt;bquote()&lt;/code&gt; or &lt;code&gt;substitute()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;first_plotmath  &amp;lt;- bquote(x ^ 2)
second_plotmath &amp;lt;- bquote(y ^ .(first_plotmath)) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-07-02-plotmath-1_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;mega-plotmath&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Mega Plotmath&lt;/h2&gt;
&lt;p&gt;Once we can put plotmath into other plotmath expressions, we can apply the
same manipulation over and over to build bigger and bigger structures.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;square &amp;lt;- function(x) { bquote(frac(.(x), .(x)) + frac(.(x), .(x))) }

x &amp;lt;- bquote(frac(alpha + beta, gamma - delta))
x &amp;lt;- square(x)
x &amp;lt;- square(x)
x &amp;lt;- square(x)
x &amp;lt;- square(x)
x &amp;lt;- square(x)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/plotmath-fractal/square.gif&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;


&lt;/div&gt;
&lt;div id=&#34;fractal-plotmath---sierpinkski-triangle&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Fractal Plotmath - Sierpinkski triangle&lt;/h2&gt;
&lt;p&gt;If the iterated plotmath expression contains an offset and a translate then you can create the classic sierpinski triangle.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sierpinski   &amp;lt;- function(x) { bquote(atop(.(x), .(x) * .(x))) }

x &amp;lt;- bquote(alpha^2)
x &amp;lt;- sierpinski(x)
x &amp;lt;- sierpinski(x)
x &amp;lt;- sierpinski(x)
x &amp;lt;- sierpinski(x)
x &amp;lt;- sierpinski(x)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/plotmath-fractal/sierpinski.gif&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;



&lt;p&gt;And this is what the plotmath looks like for this sierpinski triangle&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;x&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;atop(atop(atop(atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
    alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * alpha^2)), atop(atop(alpha^2, 
    alpha^2 * alpha^2), atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, 
    alpha^2 * alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
    atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
        alpha^2))), atop(atop(atop(alpha^2, alpha^2 * alpha^2), 
    atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
        alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
    alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * alpha^2)) * 
    atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, alpha^2 * 
        alpha^2) * atop(alpha^2, alpha^2 * alpha^2))) * atop(atop(atop(alpha^2, 
    alpha^2 * alpha^2), atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, 
    alpha^2 * alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
    atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
        alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
    alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * alpha^2)))), 
    atop(atop(atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
        alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * alpha^2)), 
        atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
            alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * alpha^2)) * 
            atop(atop(alpha^2, alpha^2 * alpha^2), atop(alpha^2, 
                alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
                alpha^2))), atop(atop(atop(alpha^2, alpha^2 * 
        alpha^2), atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, 
        alpha^2 * alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2))) * atop(atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)))) * atop(atop(atop(atop(alpha^2, alpha^2 * 
        alpha^2), atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, 
        alpha^2 * alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2))), atop(atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2))) * atop(atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)), atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)) * atop(atop(alpha^2, alpha^2 * alpha^2), 
        atop(alpha^2, alpha^2 * alpha^2) * atop(alpha^2, alpha^2 * 
            alpha^2)))))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Benchmark mutate - vector, matrix, data.frame</title>
      <link>https://coolbutuseless.github.io/2018/05/12/benchmark-mutate-vector-matrix-data.frame/</link>
      <pubDate>Sat, 12 May 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/12/benchmark-mutate-vector-matrix-data.frame/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I’m looking at some numeric code that’s going to be in an inner loop and just wanted to
get an idea of the relative speed differences of different approaches (Rcpp may be an option in the future, but not right now.)&lt;/p&gt;
&lt;p&gt;Benchmark Context:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The vector lengths are in the range 1000-10000&lt;/li&gt;
&lt;li&gt;This operation will be performed of the order of 1000 times.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key question:&lt;/strong&gt; Is the speed gained by working with raw lists of vectors worth losing the convenience/safety of the data.frame?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This is an exploration for my particular use case, on my particular computer and not meant as definitive answer as to which is the fastest approach in all situations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Data structures I’m considering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List of vectors of the same length&lt;/li&gt;
&lt;li&gt;Matrix&lt;/li&gt;
&lt;li&gt;data.frame&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While I’m not considering raw/naked vectors
(as I need at least &lt;em&gt;some&lt;/em&gt; structure to my data structures!),
I have included them in the benchmark as a baseline i.e. &lt;code&gt;v3 &amp;lt;- v1 + v2&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-test-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create test data&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;create_test_data()&lt;/code&gt; is used to generate data for the benchmark&lt;/li&gt;
&lt;li&gt;I have included an example small dataset in the 4 different formats&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Create a list of N vectors of length L 
#-----------------------------------------------------------------------------
create_test_data &amp;lt;- function(N, L) {
  set.seed(1)
  seq(N) %&amp;gt;% 
    purrr::map(~runif(L)) %&amp;gt;% 
    set_names(letters[1:N])
}


vs  &amp;lt;- create_test_data(3, 5) 
mat &amp;lt;- do.call(cbind, vs)
df  &amp;lt;- data.frame(vs) 
v1  &amp;lt;- vs[[1]]
v2  &amp;lt;- vs[[2]]

vs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$a
[1] 0.2655087 0.3721239 0.5728534 0.9082078 0.2016819

$b
[1] 0.89838968 0.94467527 0.66079779 0.62911404 0.06178627

$c
[1] 0.2059746 0.1765568 0.6870228 0.3841037 0.7698414&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mat&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;             a          b         c
[1,] 0.2655087 0.89838968 0.2059746
[2,] 0.3721239 0.94467527 0.1765568
[3,] 0.5728534 0.66079779 0.6870228
[4,] 0.9082078 0.62911404 0.3841037
[5,] 0.2016819 0.06178627 0.7698414&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;df&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;          a          b         c
1 0.2655087 0.89838968 0.2059746
2 0.3721239 0.94467527 0.1765568
3 0.5728534 0.66079779 0.6870228
4 0.9082078 0.62911404 0.3841037
5 0.2016819 0.06178627 0.7698414&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark-dataset---length-1000&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark dataset - length = 1000&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;dataset: 3 vectors with 1000 elements each&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- microbenchmark(
  v3          &amp;lt;- v1          + v2,
  vs[[3L]]    &amp;lt;- vs[[1L]]    + vs[[2L]],
  vs[[&amp;#39;c&amp;#39;]]   &amp;lt;- vs[[&amp;#39;a&amp;#39;]]   + vs[[&amp;#39;b&amp;#39;]],
  vs$c        &amp;lt;- vs$a        + vs$b,
  mat[,3L]    &amp;lt;- mat[,1L]    + mat[,2L],
  df[[3L]]    &amp;lt;- df[[1L]]    + df[[2L]],
  df[[&amp;#39;c&amp;#39;]]   &amp;lt;- df[[&amp;#39;a&amp;#39;]]   + df[[&amp;#39;b&amp;#39;]],
  df$c        &amp;lt;- df$a        + df$b,
  df[,3L]     &amp;lt;- df[,1L]     + df[,2L],
  df          &amp;lt;- mutate(df, c = a + b),
  df %&amp;gt;% mutate(c = a + b),
  times = 1000
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-05-12-matrix-vs-dataframe-benchmark_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;960&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmark-dataset---length-10000&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmark dataset - length = 10000&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;dataset: 3 vectors with 10000 elements each&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-05-12-matrix-vs-dataframe-benchmark_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;960&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;results&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;For this particular use case, on my machine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raw lists of vectors are about an order of magnitude faster than matrix or data.frame operations&lt;/li&gt;
&lt;li&gt;data.frame operations via base R are about an order of magnitude faster than dplyr&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this particular task, I think the order of magnitude speedup of using raw lists is
worth the hassle/danger/inconvenience of manually handling vectors in lists.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Challenge: Simultaneous parallel min() and which.min()</title>
      <link>https://coolbutuseless.github.io/2018/05/12/challenge-simultaneous-parallel-min-and-which.min/</link>
      <pubDate>Sat, 12 May 2018 12:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/12/challenge-simultaneous-parallel-min-and-which.min/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-p.which.min&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: &lt;code&gt;p.which.min()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Input: &lt;code&gt;vs&lt;/code&gt; A list of N vectors of numeric values (each the same length, L)&lt;/li&gt;
&lt;li&gt;Output: For each index along the vectors (1..L)
&lt;ul&gt;
&lt;li&gt;the minimum value out of the N vectors at this index&lt;/li&gt;
&lt;li&gt;the index of the vector that had the minimum (1..N)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Conditions:
&lt;ul&gt;
&lt;li&gt;If there are multiple vectors with the same minimum at the given index,
it doesn’t matter which is returned.&lt;/li&gt;
&lt;li&gt;The values are floating points (not integers).&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This problem is a combination of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;* find the parallel `min`, and
* find the parallel `which.min`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;.. and so it shall be named &lt;strong&gt;&lt;code&gt;p.which.min()&lt;/code&gt;&lt;/strong&gt; !!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;preamble&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Preamble&lt;/h2&gt;
&lt;p&gt;Some R functions discussed below operate on lists of vectors, others operator on matrixes. The following
2 functions switch between the two data representations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vs_to_mat &amp;lt;- function(vs) { do.call(cbind, vs) }
mat_to_vs &amp;lt;- function(mat) {lapply(seq_len(ncol(mat)), function(i) mat[,i])}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An example with N=3, L=5&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vs &amp;lt;- list(
  c(3, 4, 6, 9, 2), 
  c(9, 9, 7, 6, 1),
  c(2, 2, 7, 4, 8)
)

mat &amp;lt;- vs_to_mat(vs)
mat&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;     [,1] [,2] [,3]
[1,]    3    9    2
[2,]    4    9    2
[3,]    6    7    7
[4,]    9    6    4
[5,]    2    1    8&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, the parallel minimum across all vectors is &lt;code&gt;c(2, 2, 6, 4, 1)&lt;/code&gt; and the index of the
vector in which the minimum occurs is &lt;code&gt;c(3, 3, 1, 3, 2)&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# desired result
list(
  min   = c(2, 2, 6, 4, 1),
  index = c(3, 3, 1, 3, 2)
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-test-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create test data&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is the function used to create benchmarking data, e.g. &lt;code&gt;create_test_data(N=100, L=100)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Create a list of N numeric vectors, each with L elements
#-----------------------------------------------------------------------------
create_test_data &amp;lt;- function(N, L) {
  set.seed(1)
  seq(N) %&amp;gt;% purrr::map(~runif(L))
}


#-----------------------------------------------------------------------------
# Benchmarking data
#-----------------------------------------------------------------------------
vs.bench  &amp;lt;- create_test_data(300, 300)
mat.bench &amp;lt;- vs_to_mat(vs.bench)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;find-the-parallel-minimum-the-pmin-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Find the parallel minimum: The &lt;code&gt;pmin()&lt;/code&gt; function&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;pmin&lt;/code&gt; function is part of base R and are exactly what is needed
for the first part of this problem.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pmin&lt;/code&gt; returns the &lt;strong&gt;parallel minima of the input values&lt;/strong&gt;. That is, it will return the value of
the minimum at each index (but not the index of the vector from which it came)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pmin&lt;/code&gt; takes a &lt;code&gt;...&lt;/code&gt; argument, so either pass in all the vectors one-at-a-time in the function call
or wrap it with a &lt;code&gt;do.call()&lt;/code&gt; i.e. &lt;code&gt;do.call(pmin.int, vs)&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pmin(c(3, 4, 6, 9, 2), c(9, 9, 7, 6, 1), c(2, 2, 7, 4, 8))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2 2 6 4 1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;do.call(pmin, vs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2 2 6 4 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is also a built-in &lt;code&gt;pmin.int&lt;/code&gt;. The &lt;code&gt;int&lt;/code&gt; suffix stands for &lt;code&gt;internal&lt;/code&gt;, not &lt;code&gt;integer&lt;/code&gt;!
This is a faster version of the &lt;code&gt;pmin&lt;/code&gt; function when all arguments are atomic vectors
and there are no classes.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;do.call(pmin.int, vs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2 2 6 4 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-05-12-parallel-which-max_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;find-the-parallel-which.min-the-max.col-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Find the parallel &lt;code&gt;which.min&lt;/code&gt;: The &lt;code&gt;max.col&lt;/code&gt; function&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;max.col(matrix)&lt;/code&gt; function finds the maximum position for each row of a matrix. For some
reason there is no corresponding &lt;code&gt;min.col&lt;/code&gt;, but this can be faked with &lt;code&gt;max.col(-matrix)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This only operates on a matrix, so the &lt;code&gt;vs&lt;/code&gt; list will need to be converted to a matrix&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mat &amp;lt;- vs_to_mat(vs)
max.col(-mat)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 3 3 1 3 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;r-solution---using-pmin.int-and-max.col&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;R solution - using &lt;code&gt;pmin.int&lt;/code&gt; and &lt;code&gt;max.col&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Find parallel min and which.min over a list of vectors
#-----------------------------------------------------------------------------
p.which.min &amp;lt;- function(vs) {
  mins  &amp;lt;- do.call(pmin.int, vs)
  mat   &amp;lt;- vs_to_mat(vs)
  index &amp;lt;- max.col(-mat) 
  list(
    min   = mins,
    index = index
  )
}

p.which.min(vs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$min
[1] 2 2 6 4 1

$index
[1] 3 3 1 3 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-rcpp-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive Rcpp code&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Initial Rcpp code for&lt;/li&gt;
&lt;li&gt;Anyone have a more idiomatic approach?&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(&amp;#39;
List p_which_min_Rcpp(List vs) {

  int N           = vs.size();
  NumericVector v = vs[0];
  int L           = v.size();

  NumericVector min_so_far(L);
  IntegerVector min_index(L);  // Automatically initialised to zero
  
  // Initialise the &amp;quot;min so far&amp;quot; to just be the first vector
  min_so_far = v;
   
  // Iterate over each vector in turn (starting from the second one)
  for (int i=1; i&amp;lt;N; i++) {
    NumericVector vi = vs[i];
    for (int j=0; j&amp;lt;L; j++) {
      if (vi[j] &amp;lt; min_so_far[j]) {
        min_so_far[j] = vi[j];
        min_index[j]  = i;
      }
    }
  }
  
  List ret;
  ret[&amp;quot;min&amp;quot;]   = min_so_far;
  ret[&amp;quot;index&amp;quot;] = min_index + 1;  // convert to R based indexing
  return ret;
}&amp;#39;)

p_which_min_Rcpp(vs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$min
[1] 2 2 6 4 1

$index
[1] 3 3 1 3 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmarking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmarking&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Unit: microseconds
             expr      min       lq      mean    median        uq      max
      p.which.min 1034.128 1558.653 1850.7818 1651.3805 1814.9050 9661.718
 p_which_min_Rcpp   73.336   84.684  106.9455   93.4695  108.6985 1276.364
 neval
   200
   200&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-05-12-parallel-which-max_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusions-and-extensions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusions and Extensions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Anyone know of a better pure R solution?&lt;/li&gt;
&lt;li&gt;Would still like an idiomatic Rcpp version.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Hi-res c64 images with Rstats &#39;r64&#39; package</title>
      <link>https://coolbutuseless.github.io/2018/05/10/hi-res-c64-images-with-rstats-r64-package/</link>
      <pubDate>Thu, 10 May 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/10/hi-res-c64-images-with-rstats-r64-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;hires-bitmap&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Hires bitmap&lt;/h2&gt;
&lt;p&gt;In this post, the &lt;a href=&#34;https://github.com/coolbutuseless/r64&#34;&gt;&lt;code&gt;r64&lt;/code&gt; package&lt;/a&gt; will be used to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generate a 320x200 hires Rstats logo in bitmap form suitable for the c64.&lt;/li&gt;
&lt;li&gt;incorporate those bytes into an R program using the &lt;code&gt;r64&lt;/code&gt; package and the R-specific &lt;code&gt;.rbyte&lt;/code&gt; directive.&lt;/li&gt;
&lt;li&gt;compile the code and run it in an emulator (VICE).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;converting-an-image-into-a-monochrome-bitmap-matix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Converting an image into a monochrome bitmap matix&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use imagemagick to convert an image into:
&lt;ul&gt;
&lt;li&gt;320x200&lt;/li&gt;
&lt;li&gt;monochrome&lt;/li&gt;
&lt;li&gt;dithered&lt;/li&gt;
&lt;li&gt;keeping aspect ratio while padding to the correct size&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Create a 320x200 binary matrix out of an image file
#&amp;#39; 
#&amp;#39; @param image_filename full path to an image that can be read by imagemagick
#&amp;#39; @param dither boolean. floyd steinberg dithering?  default: TRUE
#&amp;#39; @param invert boolean. invert the image? default TRUE
#&amp;#39;
#&amp;#39; @return a 200x320 binary matrix (values of only 0 and 1) representing the 
#&amp;#39;         dithered black and white image
#-----------------------------------------------------------------------------
create_bw_matrix_image &amp;lt;- function(image_filename = system.file(&amp;#39;img/Rlogo.jpg&amp;#39;,package=&amp;#39;jpeg&amp;#39;), dither=TRUE, invert=FALSE, padding=&amp;#39;white&amp;#39;) {
  
  # Temporary output file
  monochrome_filename &amp;lt;- tempfile(fileext=&amp;quot;.pgm&amp;quot;)
  
  # The size of the hires bitmap screen on a c64
  width   &amp;lt;- 320
  height  &amp;lt;- 200
  
  # I couldn&amp;#39;t work out how to do all the manipulation 
  # just using the &amp;#39;magick&amp;#39; package (e.g. -extent), so
  # construct a imagemagick convert command in the shell
  dither_    &amp;lt;- ifelse(dither, &amp;quot;-dither FloydSteinberg&amp;quot;, &amp;quot;&amp;quot;)
  monochrome &amp;lt;- &amp;quot;-colors 2 -colorspace gray -normalize&amp;quot;
  command    &amp;lt;- glue::glue(&amp;quot;convert {shQuote(image_filename)} -resize {width}x{height} -background {padding} -gravity center -extent {width}x{height} {monochrome} {dither_} {monochrome_filename}&amp;quot;)
  
  system(command)
  
  im &amp;lt;- magick::image_read(monochrome_filename) %&amp;gt;%
    magick::as_EBImage() %&amp;gt;%
    as.matrix()
  
  # Return just the matrix data part
  bw_matrix &amp;lt;- t(im@.Data)
  
  if (invert) {
    bw_matrix &amp;lt;- 1L - bw_matrix
  }
  
  bw_matrix
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;convert-a-01-matrix-into-a-bytestream-ready-for-the-c64&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Convert a 0/1 matrix into a bytestream ready for the c64&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The hires bitmap is encoded one character at a time, rather than 1 row at a time&lt;/li&gt;
&lt;li&gt;This means extra work needs to be done to turn a matrix of 0/1 into a bytestream
image for the c64&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Convert a sequence of eight 0/1 values into a byte
#-----------------------------------------------------------------------------
bits_to_byte &amp;lt;- function(eight_bits) {
  stopifnot(length(eight_bits) == 8)
  stopifnot(all(eight_bits %in% c(0, 1)))
  as.integer(sum(2^seq.int(7, 0)  * eight_bits))
}


#-----------------------------------------------------------------------------
# Convert a row of a binary matrix into a vector of bytes.
#-----------------------------------------------------------------------------
row_to_bytes &amp;lt;- function(row) {
  split(row, ceiling(seq_along(row)/8)) %&amp;gt;%
    purrr::map_int(bits_to_byte)
}


#-----------------------------------------------------------------------------
#&amp;#39; Turn a binary matrix into bytes for a c64 bitmap
#-----------------------------------------------------------------------------
create_c64_byte_image &amp;lt;- function(bw_matrix) {
  stopifnot(max(bw_matrix) == 1)
  stopifnot(identical(dim(bw_matrix), c(200L, 320L)))
  
  # Turn each row of bits into a row of bytes
  byte_image &amp;lt;- t(apply(bw_matrix, 1, row_to_bytes))
  
  # Reorder the bytes to use as a c64 bitmap.
  # The ordering of a c64 bitmap is unconventional by modern standards!
  c64_byte_image &amp;lt;- seq(1, 200-8+1, 8) %&amp;gt;%
    purrr::map(~as.vector(byte_image[.x:(.x+7),])) %&amp;gt;%
    purrr::flatten_int()
  
  c64_byte_image
}


bw_matrix &amp;lt;- create_bw_matrix_image(dither=FALSE, invert=FALSE)
c64_image &amp;lt;- create_c64_byte_image(bw_matrix)

# View a matrix as an image
# plot(t(EBImage::as.Image(bw_matrix)))
# View cut-down matrix as ascii
# cat(paste(apply(bw_matrix[c(T, F, F, F, F, F, F, F), c(T, F, F, F, T, F, F, F)], 1, paste, collapse=&amp;#39;&amp;#39;), collapse=&amp;quot;\n&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-an-image-of-the-r-logo&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create an image of the R logo&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;bw_matrix &amp;lt;- create_bw_matrix_image(image_filename = system.file(&amp;#39;img/Rlogo.jpg&amp;#39;,package=&amp;#39;jpeg&amp;#39;), dither=TRUE)
c64_image &amp;lt;- create_c64_byte_image(bw_matrix)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;asm &amp;lt;- &amp;#39;*=$0801
.byte $0c, $08, $0a, $00, $9e, $20  ; 10 SYS 2080
.byte $32, $30, $38, $30, $00, $00
.byte $00

*=$0820

  ;===========================================================================
  ; Set VICII to Bank0
  ;
  ; $dd00
  ;   %xxxxxx11 -&amp;gt; bank0  ; #$03
  ;   %xxxxxx10 -&amp;gt; bank1
  ;   $xxxxxx01 -&amp;gt; bank2
  ;   $xxxxxx00 -&amp;gt; bank3
  ;===========================================================================
  lda $dd00
  ora #$03
  sta $dd00
  
  ;===========================================================================
  ; Reference: http://codebase64.org/doku.php?id=base:vicii_memory_organizing
  ; Screen, character memory and bitmap addresses: $d018
  ;  7654 321 0
  ;  ^    ^   ^-- Unused
  ;  |    |
  ;  |    ------- Bitmap mode and character dot data base address
  ;  |
  ;  ------------ Video matrix base address
  ;
  ;===========================================================================


  ;===========================================================================
  ;  Set bitmap to BANK0 + $2000
  ; 
  ; $d018
  ;   %xxxx0xxx -&amp;gt; bitmap offset $0000      #$00
  ;   %xxxx1xxx -&amp;gt; bitmap offset $2000      #$08
  ;
  ;   %0000xxxx -&amp;gt; screenmem is at $0000
  ;   %0001xxxx -&amp;gt; screenmem is at $0400
  ;   %0010xxxx -&amp;gt; screenmem is at $0800
  ;   %0011xxxx -&amp;gt; screenmem is at $0c00    #$30
  ;   %0100xxxx -&amp;gt; screenmem is at $1000
  ;   %0101xxxx -&amp;gt; screenmem is at $1400
  ;   %0110xxxx -&amp;gt; screenmem is at $1800
  ;   %0111xxxx -&amp;gt; screenmem is at $1c00
  ;   %1000xxxx -&amp;gt; screenmem is at $2000
  ;   %1001xxxx -&amp;gt; screenmem is at $2400
  ;   %1010xxxx -&amp;gt; screenmem is at $2800
  ;   %1011xxxx -&amp;gt; screenmem is at $2c00
  ;   %1100xxxx -&amp;gt; screenmem is at $3000
  ;   %1101xxxx -&amp;gt; screenmem is at $3400
  ;   %1110xxxx -&amp;gt; screenmem is at $3800
  ;   %1111xxxx -&amp;gt; screenmem is at $3c00
  ;===========================================================================
  lda $d018
  ora #$08   ; Set bitmap offset to $2000
  ora #$30   ; set screenmem to $0c00
  sta $d018


  ;===========================================================================
  ;  Set screen to bitmap mode
  ; 
  ; $d011 - Screen Control register 1
  ;   Bits 0-2  YSCROLL Vertical Raster Scroll
  ;   Bit  3    RSEL    Screen height  0=24, 1=25
  ;   Bit  4    DEN     0=Screen off, 1=Screen on
  ;   Bit  5    BMM     0=Text mode, 1=bitmap mode
  ;   Bit  6    ECM     1 = Extended background mode
  ;   Bit  7    RST8    When read, is the top bit of the current raster line
  ;                     When written is the top bit of the raster line at which to
  ;                     generate interupt
  ;
  ; $d016 - Screen Control register 2
  ;   Bits 0-2   XSCROLL Horizontal Raster Scroll
  ;   Bit  3     CSEL    Screen width  0 = 38, 1 = 40
  ;   Bit  4     MCM     1 = Multi-colour Character Mode on
  ;   Bit  5     RES
  ;
  ; Standard screen modes - https://www.c64-wiki.com/wiki/Standard_Bitmap_Mode
  ;   Mode   ECM BMM MCM    Result
  ;      0     0   0   0    Standard character mode
  ;      1     0   0   1    Multicolor Character Mode
  ;      2     0   1   0    Standard Bitmap Mode
  ;      3     0   1   1    Extended Background Colour mode
  ;===========================================================================
  lda $d011
  and #$BF    ; Unset bit 6 (ECM = 0) -&amp;gt; NOT extended background mode
  ora #$20    ; Set   bit 5 (BMM = 1) -&amp;gt; bitmap mode
  sta $d011  

  lda $d016
  and #$ef    ; Unset bit 4 (MCM = 0) -&amp;gt; NOT multicolor character mode
  sta $d016

  jsr initcolour  ; set screenmem colour

end: 
  jmp end


;--------------------------------------------------------------
; Initialise colour in each 8x8 block to black
; The screen mem colour sets the fg/bg colour at each location
; Bits 0-3   =&amp;gt;  colour for &amp;quot;0&amp;quot;
; Bits 4-7   =&amp;gt;  colour for &amp;quot;1&amp;quot;
;
; e.g.     0001 0000   = #$10
;         white black
;          fg    bg
;--------------------------------------------------------------
initcolour: 
           inc $d020
               ldx #$00
           lda #$10   ; white fg, black background
colourloop:
           sta $0c00,x
           sta $0cfa,x
           sta $0df4,x
           sta $0eee,x
           inx
           cpx #$fa
           bne colourloop
           rts


;--------------------------------------------------------------
; Include the bitmap data where the VICII will find it.
;--------------------------------------------------------------
* = $2000
  .rbyte c64_image
&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;compile-asm-code-to-prg&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compile ASM code to PRG&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(r64)

## Manual compilation steps if debugging
# line_tokens &amp;lt;- r64::create_line_tokens(asm)
# prg_df      &amp;lt;- r64::create_prg_df(line_tokens)
# prg_df      &amp;lt;- r64::process_symbols(prg_df)
# prg_df      &amp;lt;- r64::process_zero_padding(prg_df)

# compile code in a single step
prg_df       &amp;lt;- r64::compile(asm)

# Save code to file
prg_filename &amp;lt;- &amp;quot;../prg/bitmap.prg&amp;quot;
r64::save_prg(prg_df, prg_filename)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the &lt;code&gt;prg&lt;/code&gt; directory in this package for ready-to-run PRGs of this code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;run-code-in-an-emulator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Run code in an emulator&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;system(paste(&amp;quot;/usr/local/opt/vice/x64.app/Contents/MacOS/x64 -VICIIfilter 0 -silent&amp;quot;, prg_filename), wait=FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;img/r64/bitmap.png&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;c64 screenshot in vice&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;other-examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Other examples&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;img/r64/bitmap_meme.png&#34; alt=&#34;c64 screenshot in vice&#34; /&gt;
&lt;img src=&#34;img/r64/bitmap_yul.png&#34; alt=&#34;c64 screenshot in vice&#34; /&gt;
&lt;img src=&#34;img/r64/bitmap_geom_c64.png&#34; alt=&#34;c64 screenshot in vice&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Introducing the `tapir` package: Text-based Arbitrary Precision Integers in R</title>
      <link>https://coolbutuseless.github.io/2018/05/07/introducing-the-tapir-package-text-based-arbitrary-precision-integers-in-r/</link>
      <pubDate>Mon, 07 May 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/07/introducing-the-tapir-package-text-based-arbitrary-precision-integers-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rationale&lt;/h2&gt;
&lt;p&gt;This is a toy library written in order bootstrap another idea, without having to carry a dependency on a real
arbitrary precision library like &lt;a href=&#34;https://cran.r-project.org/package=gmp&#34;&gt;gmp&lt;/a&gt; or &lt;a href=&#34;https://cran.r-project.org/package=Rmpfr&#34;&gt;Rmpfr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The algorithms are straight-forward implementations of naive algorithms and are orders of magnitute slower than &lt;code&gt;gmp&lt;/code&gt; even
for small/moderate sized integers.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/tapir&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;supported-data-types&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Supported data types&lt;/h2&gt;
&lt;p&gt;The only supported datatype is an unsigned integer represented in a character string. e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“1234”&lt;/li&gt;
&lt;li&gt;“9237409238740928374029374293”&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;supported-operations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Supported operations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%add%&lt;/code&gt; - Addition&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%sub%&lt;/code&gt; - Subtration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%sub%&lt;/code&gt; - Multiplication&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%div%&lt;/code&gt; - Division&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%mod%&lt;/code&gt; - Modulo operator&lt;/li&gt;
&lt;li&gt;Logical
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%gt%&lt;/code&gt; - greater than&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%gte%&lt;/code&gt; - greater than or equal to&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%eq%&lt;/code&gt; - equal to&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%lt%&lt;/code&gt; - less than&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%lte%&lt;/code&gt; - less than or equal to&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;helper-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Helper functions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rbigint(digits)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Create a big integer with the given number of digits&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a &amp;lt;- rbigint(30)
b &amp;lt;- rbigint(20)
a&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;481566380993563946785704271523&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;36545007522668563750&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a %mul% b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;17598847016074070094422556163003416290166435091250&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a %div% b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;13177350714&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a %mod% b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;21591977069287254023&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a %add% b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;481566381030108954308372835273&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a %sub% b&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;481566380957018939263035707773&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Challenge: Adding Large Integers in R</title>
      <link>https://coolbutuseless.github.io/2018/05/04/challenge-adding-large-integers-in-r/</link>
      <pubDate>Fri, 04 May 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/04/challenge-adding-large-integers-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;challenge&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Challenge&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Write R code to add 2 BigInts (arbitrarily large integers)&lt;/li&gt;
&lt;li&gt;Integer input is as a string containing just the digits 0-9 e.g. &lt;code&gt;&#34;28349823749234234238077632&#34;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Integer output should be the same.&lt;/li&gt;
&lt;li&gt;Contributions welcome!
&lt;ul&gt;
&lt;li&gt;No calling out to C libraries or using &lt;code&gt;Rcpp&lt;/code&gt; :)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;prep-work-create-random-large-integers&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Prep work: Create random large integers&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Guarantee that there are no leading zeros (as &lt;code&gt;gmp&lt;/code&gt; will interpret as octal)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rbigint &amp;lt;- function(size) {
  paste(c(
    sample(1:9, size = 1),
    sample(0:9, size = size-1, replace = TRUE)
  ), collapse=&amp;#39;&amp;#39;)
}

rbigint(50)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;60736670197966208346760834361818514898029183539092&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-for-loop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive: for loop&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Split each number into individual digits&lt;/li&gt;
&lt;li&gt;Pad out each list of digits with zeros so that they’re the same length&lt;/li&gt;
&lt;li&gt;Loop over the digits, adding them 1 pair at a time, and including any carry
from the previous pair.&lt;/li&gt;
&lt;li&gt;Paste it all back together&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_naive &amp;lt;- function(a, b) {
  # Split the numbers into individiual integer digits
  A &amp;lt;- as.integer(rev(strsplit(a, &amp;#39;&amp;#39;)[[1]]))
  B &amp;lt;- as.integer(rev(strsplit(b, &amp;#39;&amp;#39;)[[1]]))
  
  # Pad shorter number with zeros
  zeros &amp;lt;- integer(abs(length(A) - length(B)))
  if (length(A) &amp;lt; length(B)) {
    A &amp;lt;- c(A, zeros)
  } else {
    B &amp;lt;- c(B, zeros)
  }
  
  # Allocate a place to store the sum of each pair (plus an extra in case there&amp;#39;s a carry)
  digits &amp;lt;- integer(length(A) + 1L)
  
  # Initialise carry so that it&amp;#39;s valid for the first pair 
  carry  &amp;lt;- 0L
  
  # loop: add with carry
  for (i in seq_len(length(A))) {
    digit     &amp;lt;- A[i] + B[i] + carry
    carry     &amp;lt;- digit %/% 10L
    digits[i] &amp;lt;- digit %%  10L
  }
  digits[i+1] &amp;lt;- carry
  
  # Turn integer vector back into a string
  result &amp;lt;- paste(rev(digits), collapse = &amp;#39;&amp;#39;)
  sub(&amp;quot;^0+&amp;quot;, &amp;#39;&amp;#39;, result) # Remove leading zeros for neatness
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;example-with-naive-for-loop-method.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example with Naive for loop method.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)
a &amp;lt;- rbigint(20)
b &amp;lt;- rbigint(30)
c(a, b)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;93601612044959684488&amp;quot;           &amp;quot;541980325995339865878675962957&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_naive(a, b)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;541980326088941477923635647445&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Compare to `gmp` library 
as.character(gmp::as.bigz(a) + gmp::as.bigz(b))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;541980326088941477923635647445&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-4&#34;&gt;Table 1: &lt;/span&gt;Summary: add_naive()&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;a&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93601612044959684488441980325995339865878675962957115502275657603788636504508662&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;b&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;619962190997946745702920553840252622081750166387242310689911201222781979348&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;add_naive&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93602232007150682435187683246549180118500757713123502744586347514989859286488010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gmp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93602232007150682435187683246549180118500757713123502744586347514989859286488010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;identical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-vectorised&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive Vectorised&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_vectorised &amp;lt;- function(a, b) {
  # Split the numbers into individiual integer digits
  A &amp;lt;- as.integer(strsplit(a, &amp;#39;&amp;#39;)[[1]])
  B &amp;lt;- as.integer(strsplit(b, &amp;#39;&amp;#39;)[[1]])
  
  # Pad shorter number with zeros
  zeros &amp;lt;- integer(abs(length(A) - length(B)))
  if (length(A) &amp;lt; length(B)) {
    A &amp;lt;- c(zeros, A)
  } else {
    B &amp;lt;- c(zeros, B)
  }

  # Vectorised addition of each pair of digits
  digits &amp;lt;- A + B
  carry  &amp;lt;- digits %/% 10L
  digits &amp;lt;- digits %%  10L
  digits &amp;lt;- c(0L, digits)
  
  # If there&amp;#39;s any carry, then add it in
  while (any(carry &amp;gt; 0L)) {
    carry  &amp;lt;- tail(c(carry, 0L), length(A) + 1)
    digits &amp;lt;- digits + carry
    carry  &amp;lt;- digits %/% 10L
    digits &amp;lt;- digits %%  10L
  }

  # Turn integer vector back into a string
  result &amp;lt;- paste(digits, collapse=&amp;#39;&amp;#39;)
  sub(&amp;quot;^0+&amp;quot;, &amp;#39;&amp;#39;, result) # Remove leading zeros for neatness
}&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-6&#34;&gt;Table 2: &lt;/span&gt;Summary: add_vectorised()&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;a&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93601612044959684488441980325995339865878675962957115502275657603788636504508662&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;b&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;619962190997946745702920553840252622081750166387242310689911201222781979348&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;add_vectorised&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93602232007150682435187683246549180118500757713123502744586347514989859286488010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gmp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;93602232007150682435187683246549180118500757713123502744586347514989859286488010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;identical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;vectorised-chunks&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Vectorised chunks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rather than looking at one digit at a time, look at chunks of 8 digits at a time.&lt;/li&gt;
&lt;li&gt;Any addition of a pair of chunks of this size will still fit in an R integer&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;add_vectorised_chunked &amp;lt;- function(a, b) {
  max_chunk_int &amp;lt;- 100000000L

  # Pad shorter number with zeros
  zeros &amp;lt;- paste(rep(&amp;#39;0&amp;#39;, abs(nchar(a) - nchar(b))), collapse=&amp;#39;&amp;#39;)
  if (nchar(a) &amp;lt; nchar(b)) {
    a &amp;lt;- paste0(zeros, a)
  } else {
    b &amp;lt;- paste0(zeros, b)
  }
  
  n &amp;lt;- seq(1, nchar(a), 8)
  
  # split into chunks
  A &amp;lt;- rev(as.integer(stringr::str_sub(a, -n-8+1, -n)))
  B &amp;lt;- rev(as.integer(stringr::str_sub(b, -n-8+1, -n)))
  
  # vectorised addition of chunks and calculation of carry
  digits &amp;lt;- A + B
  carry  &amp;lt;- digits %/% max_chunk_int
  digits &amp;lt;- digits %%  max_chunk_int
  digits &amp;lt;- c(0L, digits)
  
  # If there&amp;#39;s any carry, then add it in
  while (any(carry &amp;gt; 0L)) {
    carry  &amp;lt;- tail(c(carry, 0L), length(A) + 1)
    digits &amp;lt;- digits + carry
    carry  &amp;lt;- digits %/% max_chunk_int
    digits &amp;lt;- digits %%  max_chunk_int
  }

  # Turn integer vector back into a string
  result &amp;lt;- paste(sprintf(&amp;quot;%08i&amp;quot;, digits), collapse=&amp;#39;&amp;#39;)
  sub(&amp;quot;^0+&amp;quot;, &amp;#39;&amp;#39;, result) # Remove leading zeros for neatness
}&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-9&#34;&gt;Table 3: &lt;/span&gt;Summary: add_vectorised_chunked()&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;a&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;9360161204495968448844&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;b&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;298032599533986587867596295711&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;add_vectorised_chunked&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;298032608894147792363564744555&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;gmp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;298032608894147792363564744555&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;identical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;benchmarking&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Benchmarking&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Warning: `as_data_frame()` is deprecated, use `as_tibble()` (but mind the new semantics).
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-05-04-adding-large-integers-in-r_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;gmp&lt;/code&gt; library was always expected to be the fastest (written in C)&lt;/li&gt;
&lt;li&gt;Not that much difference between the &lt;em&gt;naive&lt;/em&gt; and &lt;em&gt;vectorised&lt;/em&gt; code (without chunking)&lt;/li&gt;
&lt;li&gt;The extra workin chunking in the vectorised addition only pays off for big integers with more than 100 digits.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Finding names in R packages which could be domain names (using rvest and the tidyverse)</title>
      <link>https://coolbutuseless.github.io/2018/05/02/finding-names-in-r-packages-which-could-be-domain-names-using-rvest-and-the-tidyverse/</link>
      <pubDate>Wed, 02 May 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/05/02/finding-names-in-r-packages-which-could-be-domain-names-using-rvest-and-the-tidyverse/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Twitter likes to turn things which look like URLs into URLS.&lt;/p&gt;
&lt;p&gt;I tweeted some rstats code last week and twitter decided that &lt;code&gt;seq.int&lt;/code&gt; was actually &lt;a href=&#34;seq.int&#34;&gt;http://seq.int&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&#34;https://en.wikipedia.org/wiki/.int&#34;&gt;wikipedia&lt;/a&gt;, the &lt;code&gt;.int&lt;/code&gt; TLD has the “strictest application policies of all TLDs”, so there’s no
chance of registering that particular domain.&lt;/p&gt;
&lt;p&gt;Out of the other standard R packages in base in the tidyverse, which ones could be domain names?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;valid-top-level-domains-tlds&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Valid Top Level Domains (TLDs)&lt;/h2&gt;
&lt;p&gt;According to &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains&#34;&gt;wikipedia&lt;/a&gt; the list changes frequently,
so I’m just going to grab them today as a snapshot in time.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
library(xml2)
library(rvest)

#-----------------------------------------------------------------------------
# - Read in HTML
# - Extract tables with TLDs
#
# - https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains
#-----------------------------------------------------------------------------
html   &amp;lt;- xml2::read_html(&amp;quot;../../static/img/TLDs/List_of_Internet_top-level_domains&amp;quot;)
tables &amp;lt;- rvest::html_nodes(html, &amp;#39;table&amp;#39;)


#-----------------------------------------------------------------------------
# Extract all the TLDs from the html tables
#-----------------------------------------------------------------------------
tlds &amp;lt;- tables[7:65] %&amp;gt;%
  purrr::map_dfr(~rvest::html_table(.x, fill=TRUE)[,1:2] %&amp;gt;% 
                   set_names(c(&amp;#39;name&amp;#39;, &amp;#39;tld_info&amp;#39;))) %&amp;gt;%
  as.tbl() %&amp;gt;%
  filter(grepl(&amp;quot;^\\.&amp;quot;, name)) %&amp;gt;%
  mutate(
    name     = stringr::str_sub(name, start=2),
    tld_info = gsub(&amp;quot;\n&amp;quot;, &amp;#39; &amp;#39;, tld_info)
  ) %&amp;gt;%
  replace_na(list(tld_info=&amp;#39;&amp;#39;))&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;Sample of TLDs&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;tld_info&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;dnp&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Dai Nippon Printing Co.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;tips&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;general help topics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rsvp&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Invitations and replies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;energy&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;energy industry and marketing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;dental&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;dentists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;attorney&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;attorneys and legal organizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;swatch&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;The Swatch Group Ltd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;style&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fashion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rich&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;businesses catering to the wealthy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;hotels&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;names-in-base-tidyverse-and-misc-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Names in base, tidyverse and misc packages&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Packages from which to extract names
#-----------------------------------------------------------------------------
packages &amp;lt;- c(
  &amp;#39;base&amp;#39;, &amp;#39;graphics&amp;#39;, &amp;#39;grDevices&amp;#39;, 
  &amp;#39;stats&amp;#39;, &amp;#39;stats4&amp;#39;, &amp;#39;utils&amp;#39;, &amp;quot;broom&amp;quot;, 
  &amp;quot;cli&amp;quot;, &amp;quot;crayon&amp;quot;, &amp;quot;dplyr&amp;quot;, &amp;quot;dbplyr&amp;quot;, &amp;quot;forcats&amp;quot;, &amp;quot;ggplot2&amp;quot;, 
  &amp;quot;haven&amp;quot;, &amp;quot;hms&amp;quot;, &amp;quot;httr&amp;quot;, &amp;quot;jsonlite&amp;quot;, &amp;quot;lubridate&amp;quot;, &amp;quot;magrittr&amp;quot;, 
  &amp;quot;modelr&amp;quot;, &amp;quot;purrr&amp;quot;, &amp;quot;readr&amp;quot;, &amp;quot;reprex&amp;quot;, &amp;quot;rlang&amp;quot;, 
  &amp;quot;rstudioapi&amp;quot;, &amp;quot;rvest&amp;quot;, &amp;quot;stringr&amp;quot;, &amp;quot;tibble&amp;quot;, &amp;quot;tidyr&amp;quot;, &amp;quot;xml2&amp;quot;, 
  &amp;#39;Hmisc&amp;#39;, &amp;#39;zoo&amp;#39;, &amp;#39;knitr&amp;#39;, &amp;#39;Rcpp&amp;#39;, &amp;#39;shiny&amp;#39;, &amp;#39;xtable&amp;#39;, 
  &amp;#39;data.table&amp;#39;, &amp;#39;devtools&amp;#39;, &amp;#39;testthat&amp;#39;, &amp;#39;roxygen2&amp;#39;
)


#-----------------------------------------------------------------------------
# Helper function for extracting names from a package
#-----------------------------------------------------------------------------
extract_names_from_package &amp;lt;- function(package_name) {
  data_frame(
    package   = package_name,
    function_ = ls(asNamespace(package_name))
  )
}


#-----------------------------------------------------------------------------
# Extract names from all named packages
#-----------------------------------------------------------------------------
all_names &amp;lt;- packages %&amp;gt;% 
  purrr::map_dfr(extract_names_from_package)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Keep only those which contain a &amp;quot;.&amp;quot;
#-----------------------------------------------------------------------------
possible_tlds &amp;lt;- all_names %&amp;gt;%
  filter(grepl(&amp;quot;\\.&amp;quot;, function_)) %&amp;gt;%
  mutate(
    tld = purrr::map_chr(strsplit(function_, &amp;#39;\\.&amp;#39;), tail, 1)
  )


#-----------------------------------------------------------------------------
# Keep only those whose last part of their name matches a TLD
#-----------------------------------------------------------------------------
possible_tlds %&amp;gt;% 
  inner_join(tlds, by=c(tld=&amp;#39;name&amp;#39;)) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;function_&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;tld&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;tld_info&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;individuals, by name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;do.call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.link&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;link&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;connecting to information[75]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;entertainment and vlogs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;format.info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;is.call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;is.na&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;na&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Namibia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;is.name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;individuals, by name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;match.call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;match.fun&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fun&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;month.abb&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;abb&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ABB Ltd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;month.name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;name&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;individuals, by name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;print.by&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;by&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Belarus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sys.call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;call&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;base&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sys.info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;graphics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;layout.show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;entertainment and vlogs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;graphics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;plot.design&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;design&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;graphic art and fashion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;graphics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;plot.new&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;new&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;general&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;grDevices&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dev.new&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;new&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;general&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;grDevices&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dev.off&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;off&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;grDevices&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;graphics.off&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;off&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;grDevices&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;quartz.save&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;save&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ansari.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bartlett.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;binom.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Box.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;chisq.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cor.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fisher.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fligner.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;friedman.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;glm.fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Fitness and exercise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;kruskal.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ks.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lm.fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Fitness and exercise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;make.link&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;link&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;connecting to information[75]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mantelhaen.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mauchly.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mcnemar.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mood.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;na.fail&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fail&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;general&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;oneway.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pairwise.prop.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pairwise.t.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pairwise.wilcox.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;poisson.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;power.anova.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;power.prop.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;power.t.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PP.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;predict.ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Argentina&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;predict.smooth.spline.fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;fit&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Fitness and exercise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;print.ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Argentina&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;print.family&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;family&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;families&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;prop.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;prop.trend.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;quade.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;shapiro.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;spec.ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ar&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Argentina&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;t.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;var.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;wilcox.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bug.report&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;report&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;business services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bug.report.info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;create.post&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;post&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;postal services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;help.search&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;search&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;index.search&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;search&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;process.events&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;events&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;happenings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;utils&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;url.show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;show&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;entertainment and vlogs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;broom&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tidy.map&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;map&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ggplot2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;+.gg&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;gg&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Guernsey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ggplot2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fortify.map&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;map&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;ggplot2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;is.zero&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;zero&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rlang&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;print.box&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;box&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;individuals and businesses, in order to promote personal cloud storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rvest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;format.select&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;select&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sas.codes&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;codes&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;computer and/or encryption code enthusiasts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;smean.sd&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;sd&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Sudan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;spearman.test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;test&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;string.bounding.box&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;box&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;individuals and businesses, in order to promote personal cloud storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;xy.group&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;group&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zoo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.yearmon.date&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;date&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;online dating&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;zoo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.yearqtr.date&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;date&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;online dating&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;shiny&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.exists.ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Côte d’Ivoire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;shiny&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.path.ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Côte d’Ivoire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;shiny&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;find.file.ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;ci&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Côte d’Ivoire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xtable&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as.is&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;is&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;Iceland&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;xtable&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sanitize.final&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;final&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;devtools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;file.info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;devtools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;print.doctor&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;doctor&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;roxygen2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;object_defaults.data&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;data&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;roxygen2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;object_usage.data&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;data&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Impossible
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;is.na&lt;/code&gt; is not supported as the registry requires at least 3 characters.
in the first part&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.call&lt;/code&gt; is by amazon registry and i can’t see how to even try and register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.off&lt;/code&gt; - I couldn’t find a registry that sold it.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.test&lt;/code&gt; (like &lt;code&gt;.example&lt;/code&gt;) is purely for testing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.map&lt;/code&gt; and &lt;code&gt;.new&lt;/code&gt; seems to be associated with google registry.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Expensive
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lm.fit&lt;/code&gt; was quoted as available for &lt;strong&gt;$1200&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;match.fun&lt;/code&gt; quoted as available for &lt;strong&gt;$7500&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Taken
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;as.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;is.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sys.info&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;na.fail&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Possible
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;glm.fit&lt;/code&gt; for just &lt;strong&gt;$64&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POSIXct.date&lt;/code&gt; and &lt;code&gt;POSIXlt.date&lt;/code&gt; may be available. &lt;strong&gt;$30&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spline.fit&lt;/code&gt; for &lt;strong&gt;$33&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>`uint8` package for an unsigned 8bit integer type in R</title>
      <link>https://coolbutuseless.github.io/2018/04/29/uint8-package-for-an-unsigned-8bit-integer-type-in-r/</link>
      <pubDate>Sun, 29 Apr 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/29/uint8-package-for-an-unsigned-8bit-integer-type-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;uint8---an-8-bit-unsigned-integer-type-for-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;uint8&lt;/code&gt; - An 8-bit unsigned integer type for R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An 8-bit unsigned integer type for R based upon the &lt;code&gt;raw&lt;/code&gt; type.&lt;/li&gt;
&lt;li&gt;Each value is stored in a single byte (whereas &lt;code&gt;integer&lt;/code&gt; values in R are stored in 4 bytes),
so there can be memory savings.&lt;/li&gt;
&lt;li&gt;Stores only values 0-255&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;NA&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, or &lt;code&gt;Inf&lt;/code&gt; allowed&lt;/li&gt;
&lt;li&gt;Basic arithmethic&lt;/li&gt;
&lt;li&gt;The aim is to have similar behaviour to the &lt;code&gt;uint8_t&lt;/code&gt; type in C.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rationale&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;An experiment to see if there’s more useful data type for working with 8-bit data
(without dropping down to the level of &lt;code&gt;Rcpp&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/uint8&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;features&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;uint8&lt;/code&gt; is stored in a single byte (but there is, of course, overhead
associated with atomic vector metainfo).&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;uint8&lt;/code&gt; can result in 25% of the memory use of R &lt;code&gt;integer&lt;/code&gt; values. e.g.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pryr::object_size(1:10000)&lt;/code&gt; =&amp;gt; 40 kB&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pryr::object_size(uint8(1:10000))&lt;/code&gt; =&amp;gt; 10.2 kB&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Specific S3 methods written for:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uint8()&lt;/code&gt; (data creation)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%%&lt;/code&gt;, &lt;code&gt;%/%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:&lt;/code&gt; (sequence creation)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;any()&lt;/code&gt;, &lt;code&gt;all()&lt;/code&gt;, &lt;code&gt;as.bitstring()&lt;/code&gt;, &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;order()&lt;/code&gt;, &lt;code&gt;sign()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;A lot of things come for free because of the use of the built-in R &lt;code&gt;raw&lt;/code&gt; type
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;as.integer()&lt;/code&gt;, &lt;code&gt;as.numeric()&lt;/code&gt;, &lt;code&gt;as.character()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%in%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;limitations&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Can’t use a &lt;code&gt;uint8&lt;/code&gt; for subscripts (similar limitation in the &lt;code&gt;bit64&lt;/code&gt; package for &lt;code&gt;integer64&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;:&lt;/code&gt; operator only dispatches on its first argument, so &lt;code&gt;uint8(1):10&lt;/code&gt; will work,
but &lt;code&gt;1:uint8(10)&lt;/code&gt; won’t.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;comparison-to-raw&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Comparison to &lt;code&gt;raw&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;raw&lt;/code&gt; allows for 8-bit data, but doesn’t support any arithmetic operators&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uint8&lt;/code&gt; support basic arithmetic&lt;/li&gt;
&lt;li&gt;&lt;code&gt;raw&lt;/code&gt; accepts values outside the range 0-255 by setting them to zero&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uint8&lt;/code&gt; accepts values outside the range 0-255 by calculating the value modulo 256.
e.g. &lt;code&gt;uint8(-10)&lt;/code&gt; is &lt;code&gt;246&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;raw&lt;/code&gt; accepts &lt;code&gt;NA&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Inf&lt;/code&gt; by setting them to zero.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uint8&lt;/code&gt; disallows &lt;code&gt;NA&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt; and &lt;code&gt;Inf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;examples&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;b02 &amp;lt;- as.uint8(  2)
b0a &amp;lt;- as.uint8( 10)
bff &amp;lt;- as.uint8(255)


# Addition is modulo 256
bff + b0a   # (255 + 10) %% 256 =&amp;gt; 9&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 9&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Division result trucated to integer value
b0a/b02   # 10/2 =&amp;gt; 5&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 5&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;bff/b0a   # 255/10 =&amp;gt; 25.5 =&amp;gt; 25&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 25&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# exponentiation is modulo 256
b02 ^ b0a   # 2^10 =&amp;gt; 1024.    1024 %% 256 =&amp;gt; 0&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 0&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# initialisation is modulo 256
as.uint8(seq(200, 300, 5))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] 200 205 210 215 220 225 230 235 240 245 250 255   4   9  14  19  24  29  34
[20]  39  44&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;future&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Flesh out the supported functions as needed&lt;/li&gt;
&lt;li&gt;Investigate if there’s any point to an actual &lt;code&gt;Rcpp&lt;/code&gt; backend for speed or accuracy of behaviour.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>r64 package - a c64/6502 assembler</title>
      <link>https://coolbutuseless.github.io/2018/04/25/r64-package-a-c64/6502-assembler/</link>
      <pubDate>Wed, 25 Apr 2018 15:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/25/r64-package-a-c64/6502-assembler/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;r64---a-c646502-assembler-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;&lt;code&gt;r64&lt;/code&gt; - a c64/6502 assembler in R&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Package home is on &lt;a href=&#34;https://github.com/coolbutuseless/r64&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Full documentation is available here: &lt;a href=&#34;https://coolbutuseless.github.io/package/r64&#34;&gt;coolbutuseless.github.io/package/r64&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;rationale&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Rationale&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Who &lt;em&gt;doesn’t&lt;/em&gt; want a compiler for a &lt;strong&gt;1 MHz&lt;/strong&gt; 8-bit computer with 16 colours and a max resolution of 320x200?&lt;/li&gt;
&lt;li&gt;A 6502 assembler in R will allow for preparing/calculating
data in R and then incorporating directly into the assembly code. e.g. 
&lt;ul&gt;
&lt;li&gt;creating character sets&lt;/li&gt;
&lt;li&gt;computing animation paths&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;features&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;p&gt;General features&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basic syntax only. Similar to TASS64 syntax.&lt;/li&gt;
&lt;li&gt;Settable program counter
&lt;ul&gt;
&lt;li&gt;e.g. `* = $0801`&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Defined variables
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;border = $d020&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Low/High byte extraction from symbol (similar to TASS)
&lt;ul&gt;
&lt;li&gt;e.g. &lt;code&gt;lda #&amp;lt;routine&lt;/code&gt; will store the low byte of the address of symbol &lt;code&gt;routine&lt;/code&gt; in the &lt;code&gt;A&lt;/code&gt; register&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For integration with R&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.rtext&lt;/code&gt; directive to include an &lt;code&gt;R&lt;/code&gt; string as text data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.rbyte&lt;/code&gt; directive to include an &lt;code&gt;R&lt;/code&gt; integer vector as bytes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{...}&lt;/code&gt; to delimit code to be evaluated at run time to manipulate labels and variables e.g. &lt;code&gt;lda {border + 1}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;installation&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;r64&lt;/code&gt; depends on a lot of tidyverse packages as well as the &lt;a href=&#34;https://github.com/coolbutuseless/minilexer&#34;&gt;minilexer&lt;/a&gt;
package (for splitting the c64 asm code into tokens).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/minilexer&amp;#39;) # for lexing the 6502 assembly into tokens
devtools::install_github(&amp;#39;coolbutuseless/r64&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;a-simple-6502-program&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A simple 6502 program&lt;/h2&gt;
&lt;p&gt;The following c64/6502 ASM code will clear the screen and then
write &lt;code&gt;Hello #rstats!&lt;/code&gt; at the top&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;asm &amp;lt;- &amp;#39;
*=$0801
  .byte $0c, $08, $0a, $00, $9e, $20  ; 10 SYS 2080
  .byte $32, $30, $38, $30, $00, $00
  .byte $00

*=$0820
      lda #$93        ; Clear the screen
      jsr $ffd2

      ldx #$00        ; initialise the offset pointer into our message
loop  lda message,x   ; load a character and write it to screen 
      and #$3f        ; Manually place chars on screen
      sta $0400,x
      inx
      cpx #$0e
      bne loop

      rts

message
    .text &amp;quot;Hello #rstats!&amp;quot;
&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;compile-the-program-and-run-it-using-vice&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compile the program and run it using VICE&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prg_df       &amp;lt;- r64::compile(asm)
prg_filename &amp;lt;- tempfile()
r64::save_prg(prg_df, prg_filename)
# system(paste(&amp;quot;/usr/local/opt/vice/x64.app/Contents/MacOS/x64&amp;quot;, prg_filename), wait=FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;img/r64/helloworld.gif&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;helloworld output&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;output-from-animation-using-a-custom-character-set&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Output from animation using a custom character set&lt;/h2&gt;
&lt;div class=&#34;figure&#34;&gt;
&lt;img src=&#34;img/r64/spiral-two-sine.gif&#34; alt=&#34;&#34; /&gt;
&lt;p class=&#34;caption&#34;&gt;custom charset&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;breakdown-of-assembly-process&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Breakdown of assembly process&lt;/h2&gt;
&lt;p&gt;The compiler makes a few passes through the data to resolve symbol values.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;r64::compile()&lt;/code&gt; function is just a wrapper which calls the following 4 functions&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;line_tokens &amp;lt;- r64::create_line_tokens(asm)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;For each line in the input break it into tokens.&lt;/li&gt;
&lt;li&gt;Filter any rows that contain no instructions&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prg_df &amp;lt;- r64::create_prg_df(line_tokens)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Create a data.frame from &lt;code&gt;line_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This is the key data structure for the compilation process&lt;/li&gt;
&lt;li&gt;The compilation process is just a matter of manipulating this data.frame and merging with information about the instructions&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prg_df &amp;lt;- r64::process_symbols(prg_df)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Resolve labels to their actual addresses&lt;/li&gt;
&lt;li&gt;Replace any defined variables with their values&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prg_df &amp;lt;- r64::process_zero_padding(prg_df)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;If there are gaps between blocks of code, insert zero bytes&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An example of the final form of the &lt;code&gt;prg_df&lt;/code&gt; data.frame is show below. The actual contents of the c64 &lt;code&gt;prg&lt;/code&gt; file
is just the sequence of values in the &lt;code&gt;hexbytes&lt;/code&gt; column.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;prg_df %&amp;gt;%
  select(addr, label, line, opcommand, op, ophex, nbytes, hexbytes) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;addr&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;line&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;opcommand&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;op&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;ophex&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;nbytes&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;hexbytes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2049&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;* = $0801&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2049&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.byte $0c $08 $0a $00 $9e $20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;0c, 08, 0a, 00, 9e, 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2055&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.byte $32 $30 $38 $30 $00 $00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;32, 30, 38, 30, 00, 00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2061&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.byte $00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2062&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;(zero padding)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2080&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;* = $0820&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2080&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lda #$93&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lda #$93&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a9, 93&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2082&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;jsr $ffd2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;jsr $ffd2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;jsr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20, d2, ff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2085&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ldx #$00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ldx #$00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ldx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a2, 00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2087&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;loop&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;loop lda message x&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lda message x&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lda&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bd&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bd, 35, 08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2090&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;and #$3f&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;and #$3f&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;and&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;29, 3f&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2092&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sta $0400 x&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sta $0400 x&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sta&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;9d&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;9d, 00, 04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2095&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;inx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;inx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;inx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2096&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cpx #$0e&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cpx #$0e&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cpx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e0, 0e&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bne loop&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bne loop&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bne&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;d0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;d0, f3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2100&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;60&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2101&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;message&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;message&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2101&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.text “Hello #rstats!”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c8, 45, 4c, 4c, 4f, 20, 23, 52, 53, 54, 41, 54, 53, 21&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Generating Executable ASCII art</title>
      <link>https://coolbutuseless.github.io/2018/04/12/generating-executable-ascii-art/</link>
      <pubDate>Thu, 12 Apr 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/12/generating-executable-ascii-art/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Images can be converted to an ASCII representation - it’s a hack that’s as &lt;a href=&#34;http://www.chris.com/ascii/joan/www.geocities.com/SoHo/7373/history.html&#34;&gt;old as the hills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;This post’s contributions:
&lt;ul&gt;
&lt;li&gt;Tweet-sized ascii image generator in R&lt;/li&gt;
&lt;li&gt;Executable art&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Notes/References
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.penceland.com/ScarecrowASCIIref.html&#34;&gt;Scarecrow’s ASCII reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.researchgate.net/publication/262159666_ASCII_art_generation_using_the_local_exhaustive_search_on_the_GPU&#34;&gt;ASCII art generation using the local exhaustive search on the GPU&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;tweet-sized-ascii-image-generator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweet sized ascii image generator&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;C=strsplit(&amp;#39;851+-. &amp;#39;,&amp;#39;&amp;#39;)[[1]]
i=jpeg::readJPEG(system.file(&amp;#39;img/Rlogo.jpg&amp;#39;,package=&amp;#39;jpeg&amp;#39;))[c(T,F),,2]
i[]=C[findInterval(i,quantile(i,p=seq(0,1,,length(C))))]
cat(apply(i,1,paste,collapse=&amp;#39;&amp;#39;),sep=&amp;#39;\n&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;                  --        -  --   -    ++++++++++++++++++      --  --     -   -  - -+             
                 -    - +  -- ++++155555555555555555555555555555551+++   -+-    +--  +              
                - +- -  -++15555555555151111111111155555555555555555558851++ -- ++ -  -             
                + - ++15511111111111111111111111111111111111111155555555555885+++ -  - -            
          --  +  +1511111111115555555511111111111111555555555555551111155555555888+ -    -  - -     
          - - +1111111++15555555511+++++1155555555588888888888555555555555515555558881+   +-        
           +111111+++58855551+++++++1155588888888888888888888888888888888885555515558888+ -         
        -+11111++18855551+++++++11588888888885+++-  -     --      - -++15888888855555558881   +     
+---  -+1111+++5855551+++++++1588888885++ -+   --------------------         -+188888555558881  - -- 
-+ + +1111+++888551+++++++158888881+ -   -+-   -                --- ----+--+--++ -+58855558888+  +  
-  -+111+++885551+++++++5888888+     -+115555555555555555555555555555555555551++-    +1885558885   +
  ++111++588551+++++++588888++ +--  - +51++11111111111111111111111111111++++155885+ +-- +55555888 - 
  +111++88855+++++++588888+-  - --    +51+885555555555555555555555555555588888515888+---  +1555888+ 
 +111++88551+++++++58888+ +-  + --    +51+88111111111++++++++++++++++11111111158855888-+-   +555885 
+111++58851+++++++88888+ +- +  +--    +51+881111111++1888888888888855551111111111585888  - - -15588+
+111++88551++++++58888 +-   + +       +51+88111111+188888888888888888855551111111155888++   +--15581
+111+58851++++++18888+ -              +51+8811111115888+        --+-+5851185111111155888      ++5588
+111+58851++++++18888+ -              +51+8811111115888+----     -    +51+88111111115888      --+188
+511158851++++++18888 -               +51+88111111+5888+       - +-   +51+88111111+15888       -+185
+5511188551++++++8888-                +51+8811111115888+--------+-++  11++88111111+18885-  --  -158+
 +511158551++++++58881 -   +- +       +51+8811111115888+          -++11++88111111++5888+--  +- +188-
  5551558551++++++5888+ -  +-- -      +51+88111111155555555555555551++++8811111+++8888+--+    +158+ 
 -+5555555551++++++5888+    -+--      +51+881111111588511++++++++++1888851+++++188888+ -+    +158+ -
+  +1555555555++++++15888+ - ++-      +51+881111111111555555555555551+++11158888888+-+- -+ -+188+   
-  - +5555555551+++++115885+- -  -  - +51+88111111111+++++++++111111+18888888885+--+--+  -+1585+    
-- ++-+555555555511+++1115888+  - -   +51+881111111++155588555555111558881+--  -  -+---+11188+ -    
-    -  +585555555111+++11155885+-+  ++51+88111111+188888888888855515855555585++ - -+111588+   +    
     -   ++58855555511111+1115555885+++51+88111111158881- ---+5885155588881+15885+1115888+- -- -    
         + - +588555555511111111555555551+88111111158881-  -  -+555+5511155888588858881             
          -  +- +888888555555111111155551+88111111+58881+++++++++5551581111115858881 - -   -        
          - -+    -+188888885555555511551+881111111588885555111111585158111111585888+  -            
        - -+  --  - -+ -+5888888888855551+88111111158885111115555888551581111111858885-             
                             ++5888888851+88111111+588888888888888885851581111111555888+-  -  --    
                          -  -+      ++51+881111111588888551+++ -    1551181111111585888+ +  ---    
                        +      -      +51+8811111115888+ -- -+-  -    +851181111111585888+  ----    
                        +-   +-  -   -+51+85+++++++5888+ -+-  --- -  - +85118++++++++55888+----+    
                                -   --+5118588585885888+        ---     +8555888888888888881- --    
                                +  ++-+8888888888888888+          --     +8888888888888888885+      &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-executable-in-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s executable in R?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R has a bunch of unary operators that can be strung together and still make valid executable code.&lt;/li&gt;
&lt;li&gt;Some transitions between operators are not allowed
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;++&lt;/code&gt; before digits, OK. e.g. &lt;code&gt;++1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;++&lt;/code&gt; after digits, Bad. e.g. &lt;code&gt;1++&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!&lt;/code&gt; before digits, OK. e.g. &lt;code&gt;!!1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!&lt;/code&gt; after digits, Bad. e.g. &lt;code&gt;1!!&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Going to construct an ascii image just out of valid executable ascii by abusing this!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;+++++++++++++++1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;+++++++++-----------1&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] -1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;++++!!++++!+++++1-----!!!-----3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;executable-ascii-art&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Executable ASCII art&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Set up a transition table of operators and digits e.g.
&lt;ul&gt;
&lt;li&gt;Can transition from &lt;code&gt;!&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt;, but not vice versa&lt;/li&gt;
&lt;li&gt;Table manually tweaked to get OK looking output.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;For each pixel in the image:
&lt;ul&gt;
&lt;li&gt;Find its quantized value (calculated via &lt;code&gt;findInterval()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Based upon the previous character, pick from the allowable characters
at the index corresponding to the quantized value&lt;/li&gt;
&lt;li&gt;Repeat until done.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Ensure each line ends in a &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt; so the entire output can be
evaluated as a single expression.&lt;/li&gt;
&lt;li&gt;Ensure the entire output ends in a digit so it’s a valid expression.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Transistion Matrix (stored in a compact form)
#  - name of list item is the previous character value
#  - contents of the list item is the allowable characters to transition to
#    These characters are listed in order of visual density
#-----------------------------------------------------------------------------
next_char &amp;lt;- list(
  &amp;#39; &amp;#39; = &amp;#39; -+&amp;#39;,
  &amp;#39;0&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;1&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;2&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;3&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;4&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;5&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;6&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;7&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;8&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;9&amp;#39; = &amp;#39;-+|17235469*80&amp;amp;&amp;#39;,
  &amp;#39;+&amp;#39; = &amp;#39; -+!10&amp;#39;,
  &amp;#39;-&amp;#39; = &amp;#39; -+!10&amp;#39;,
  &amp;#39;!&amp;#39; = &amp;#39; -+!10&amp;#39;,
  &amp;#39;*&amp;#39; = &amp;#39; -+!10&amp;#39;,
  &amp;#39;|&amp;#39; = &amp;#39; -+!10&amp;#39;,
  &amp;#39;&amp;amp;&amp;#39; = &amp;#39; -+!10&amp;#39;
) %&amp;gt;% purrr::map(~rev(strsplit(.x, &amp;#39;&amp;#39;)[[1]]))


#-----------------------------------------------------------------------------
# What are the lengths of the allowed &amp;#39;next_char&amp;#39; transitions
#-----------------------------------------------------------------------------
char_lengths &amp;lt;- next_char %&amp;gt;% 
  purrr::map_int(length) %&amp;gt;% 
  unique() 


#-----------------------------------------------------------------------------
# Set a gamma value. This is a hack so we don&amp;#39;t have a linear intensity mapping,
# because the mapping from image value to displayed character is going to 
# depend a lot of font, image darkness, users display settings, 
# number of distinct characters to choose from, etc
#-----------------------------------------------------------------------------
gamma &amp;lt;- 1.3


asciify &amp;lt;- function(jpeg_filename, gamma) {
  #-----------------------------------------------------------------------------
  # Create a quantized version of the image for each transition length
  # i.e. if there are only 5 possible next characters, then we should pick 
  # which one based upon an image quantized to 5 levels.
  #-----------------------------------------------------------------------------
  qimage &amp;lt;- list()
  
  
  #-----------------------------------------------------------------------------
  # Read image
  #-----------------------------------------------------------------------------
  image &amp;lt;- jpeg::readJPEG(jpeg_filename)
  
  
  #-----------------------------------------------------------------------------
  # If this is an RGB array, so just select the &amp;#39;G&amp;#39; plane as an approximation
  # of image grayscale intensity 
  # (I&amp;#39;m too lazy to do a proper conversion for this hack)
  #-----------------------------------------------------------------------------
  if (length(dim(image))==3) {
    image &amp;lt;- image[,,2]
  }
  
  #-----------------------------------------------------------------------------
  # Only keep every second row of the image. Because ascii characters 
  # are taller than they are wide, we need a lower resolution in the Y direction
  # otherwise the image looks too tall/stretched.
  #-----------------------------------------------------------------------------
  image &amp;lt;- image[c(T,F),]
  
  #-----------------------------------------------------------------------------
  # For each possible length of allowed &amp;#39;next_char&amp;#39; choices, create a quantized
  # image
  #-----------------------------------------------------------------------------
  for (char_length in char_lengths) {
    probs &amp;lt;- seq(0, 1, length.out = char_length + 1)
    j     &amp;lt;- image
    j[]   &amp;lt;- findInterval(image, quantile(image, probs = probs^gamma), rightmost.closed = TRUE)
    qimage[[char_length]] &amp;lt;- j
  }
  
  
  #-----------------------------------------------------------------------------
  # Function to select a next_char based upon the prev_char and 
  # position in the image (row, col)
  #-----------------------------------------------------------------------------
  select_next_char &amp;lt;- function(row, col, prev_char) {
    
    # What are the allowable next characters?
    available_chars &amp;lt;- next_char[[prev_char]]
    N               &amp;lt;- length(available_chars)
    
    # Which quantised image should be used as the reference?
    this_qimage     &amp;lt;- qimage[[N]]
    
    # What is the level/value at the current location
    level           &amp;lt;- this_qimage[row, col]
    level           &amp;lt;- min(level, N)
    
    available_chars[level]
  }
  
  
  #-----------------------------------------------------------------------------
  # Initialise the prev_char before we begin
  #-----------------------------------------------------------------------------
  prev_char &amp;lt;- &amp;#39;+&amp;#39;
  
  
  #-----------------------------------------------------------------------------
  # Create the output matrix
  #-----------------------------------------------------------------------------
  ascii &amp;lt;- image
  
  
  #-----------------------------------------------------------------------------
  # Iterate over the entire image choosing a character to represent the pixel
  # at each point
  #-----------------------------------------------------------------------------
  for (row in seq(nrow(image))) {
    for (col in seq(ncol(image))) {
      if (col == ncol(image)) {
        # If we&amp;#39;re at the end of a row, must end in a + or -
        this_char &amp;lt;- &amp;#39;+&amp;#39;
      } else {
        # Otherwise choose a character based upon the previous one
        this_char &amp;lt;- select_next_char(row, col, prev_char)
      }
      ascii[row, col] &amp;lt;- this_char
      prev_char       &amp;lt;- this_char
    }
  }
  
  
  #-----------------------------------------------------------------------------
  # Ensure the ascii ends in a digit so that it&amp;#39;s a valid expression
  #-----------------------------------------------------------------------------
  ascii[nrow(ascii), ncol(ascii)] &amp;lt;- 0
  
  #-----------------------------------------------------------------------------
  # Collapse it all into a image for display
  #-----------------------------------------------------------------------------
  ascii &amp;lt;- paste(
    apply(ascii, 1, paste, collapse=&amp;#39;&amp;#39;),
    collapse=&amp;quot;\n&amp;quot;
  ) 
  
  ascii
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Copy and paste this ascii image into your R session to execute it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ascii &amp;lt;- asciify(jpeg_filename = system.file(&amp;#39;img/Rlogo.jpg&amp;#39;,package=&amp;#39;jpeg&amp;#39;), gamma=1.3)
cat(ascii, &amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;                                           -+++++++++++++--                                        +
                                -+!!!!!!!!!!!!!!!!!!!19999999999993277-                            +
                          -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!19999*19327---                    +
                     -!!!!!!!!!++++++++!+++++++++++++++++++++!!!!!!!!!1999*1*1377--                +
                 -+!!!!!++++++!!1996444433333333354446666666666444453544666999*18*+                +
              -!!!!!!++++!1*199645322223354469999*1*1*1*1*1*1*1*1*1*1999964446699*18837-           +
            -+!!!++++1*199943222222334699*180000000000000000000000088888*1*199964699*1882--        +
         -+!++++++1*196632222223356*000000&amp;amp;0842271-                   -+180888*1999469*1885-       +
----   -!++++++18*194327222223680000&amp;amp;0927---                                 -!188*19966*1803-     +
--    -!+++-+1*19652777222398000&amp;amp;037--                                            -18*1996*1802-   +
-   -+!++-+18*16327722226800&amp;amp;087-     -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!19994271-    -1*196*006-  +
   -++++-!0*16327772229800&amp;amp;027----    -!++++++++++++++++++++++++++++++++++++!!1*192----  -1999808--+
  -!+++-18*1437777226800&amp;amp;071-         -!++0866666466666666666666666666699*1000636*182111-  -1968087+
 -!+++-18*142777222*00&amp;amp;02---          -!++0855355554322222222222222233455543346884980*---    -16804+
-+!++-18*142777722*00&amp;amp;07---           -!++085555343225*1*1*1*1*1*1*16444355353534*1980*       -1600+
+!++++08943277722980&amp;amp;0---             -!++0855555523*0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;008*!!14354555349*0&amp;amp;+-      -!1&amp;amp;+
+!+++!0*14277722380&amp;amp;02--              -!++085555553680&amp;amp;+             -1955845555553990&amp;amp;1-       -!0+
+!!!+18*14277722480&amp;amp;07--              -!++085555553680&amp;amp;+----          -142*14545553490&amp;amp;0-       -!0+
+!!!+!0*14277722480&amp;amp;0--               -!++0855553336*0&amp;amp;+              -!!+185553553390&amp;amp;0-       -+0+
-!!!!!1*143277223*0001-               -!++085555553680&amp;amp;+------------  -!++0*+!!+!+++10&amp;amp;!-       -!0+
 -!!!!18*1527772248003--              -!++0855555336*0&amp;amp;+            -!++-0045544522*0&amp;amp;0711-    -+08+
  -!!!!1*16527722268002--             -!++085555534999*!!!!!!!!!!!!!++-+084535322380&amp;amp;07117-    -1&amp;amp;-+
   -!!!!1*16422722248003-             -!++085555454488633333333333348&amp;amp;084332722480&amp;amp;007---     -1&amp;amp;- +
-   -1964999643222223980*-            -!++0855555333544999999999969642223549880&amp;amp;0&amp;amp;07171---  -+007- +
-    -19966999443222234988971--       -!++0855555433522222222335554323800&amp;amp;0&amp;amp;0&amp;amp;097117117-  -!!097-  +
--     -199999944532223356*082-       -!++085555543223*1*1*1*1444333498004211-          -!!007--   +
-        +1999666444332335449*1*+--   -!++0855554323*0&amp;amp;0&amp;amp;0&amp;amp;0008*!!144*!!!199*127--   -!+1&amp;amp;02-      +
           -1*1996664553333554699*162726328855555536*0&amp;amp;+-     -1*13996*00*!+!1*0*+!!!!0&amp;amp;071---     +
             -1*1*199964443333544669999632885555533480&amp;amp;+-       +193*15554980*1800*0&amp;amp;03-           +
                -18*1*199966445355444466328855555536*0&amp;amp;+--------+1*139*!+!+++!168004--             +
                    -1888*1*19996644444632885555533680&amp;amp;164444444549*139*!++++!!19*002-             +
                        -!088888*1*1*19632885555553680&amp;amp;1335544699888*136*!++!!!!19*0041-           +
                              -!000088*!++085555343680&amp;amp;08000000000009*136*!+++!!!1*180*--          +
                                      -!++085543353680&amp;amp;08943227--    -1934*!++!+++1*18087--        +
                                      -!++085534533680&amp;amp;+              -1944845445336868002-        +
                                      -!++092222222680&amp;amp;+               -1954*++++++++19*00211117-  +
                                      -!+!1*1*1*1*1*10&amp;amp;+                -196*1*1*1*1*1*1*0041---   +
                                      -00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;03-                -0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0097-    0 &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(parse(text=ascii))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;tweetable-executable-ascii-of-the-mona-lisa&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Tweetable Executable ASCII of the Mona Lisa&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is about 230 ascii characters&lt;/li&gt;
&lt;li&gt;You’ll need to squint to try and make it look like the Mona Lisa&lt;/li&gt;
&lt;li&gt;Copy and paste this ascii image into your R session to execute it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ascii &amp;lt;- asciify(&amp;quot;../../static/img/ascii-mona/mona-tiny.jpg&amp;quot;, gamma=0.7) 
cat(ascii, &amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;-+++++!+-++++++--+
-      +0&amp;amp;1|     +
--    +- -08+    +
!+!-!181170&amp;amp;!----+
!14711*099*093944+
+!!!185-   -+!-  +
!++!1*13|+1649&amp;amp;06+
!+!16808800*1*0&amp;amp;!+
!1869*1&amp;amp;0&amp;amp;00998&amp;amp;1+
!0&amp;amp;1892- -!+!0&amp;amp;0&amp;amp;+
0&amp;amp;00&amp;amp;!10080000&amp;amp;0&amp;amp;+
0&amp;amp;08*10&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00 &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(parse(text=ascii))  &lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;executable-ascii-of-the-mona-lisa&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Executable ASCII of the Mona Lisa&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Copy and paste this ascii image into your R session to execute it&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ascii &amp;lt;- asciify(&amp;quot;../../static/img/ascii-mona/mona-small.jpg&amp;quot;, gamma=0.7) 
cat(ascii, &amp;quot;\n&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;+++++++++++!!!!!!!++++++!++!!!!+!!!!!+++++++!++!!!!!!!!+++++++!++++++++++++++++++++-++++
++++-+++++++++++!+++++++++++!!+++!!+++++++++++!+++++++++++++++++++++++!+++++++++++++++++
+--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++-+--+++-+++++++++++++++++++++++++++++++++--------+++++---+-+++---+
+---------------------------------+++----++!!!+----------------------------------------+
------                               -1080000000&amp;amp;009711111|-----------------------     +
---                                +08*1*188800&amp;amp;0&amp;amp;0&amp;amp;08|                                +
-                                 +1*195988888800&amp;amp;0&amp;amp;0&amp;amp;07+                              +
-                                +11+       -180000&amp;amp;0&amp;amp;0&amp;amp;-                              +
-                               +12+          -18&amp;amp;00&amp;amp;0&amp;amp;08+                             +
+-                            -1091|          -+!180&amp;amp;0&amp;amp;0&amp;amp;+                             +
++!---              -----    -!1&amp;amp;!----    -++--+!1880&amp;amp;0&amp;amp;0*--                           +
!-!+----------    -++--+-----!!1&amp;amp;1964*!  +1599*1*1800&amp;amp;0&amp;amp;087|--                         +
+++-------------++---++++!!+!1*0&amp;amp;!       ----!!-+18800&amp;amp;0086|--------                   +
+!!-----------++-+---+!!!+!!1*00&amp;amp;!              -18000&amp;amp;0&amp;amp;0*-                           +
+!++!+-+!!!!!!-------+!!1*199*08&amp;amp;17|    -!     -!108800&amp;amp;0089377532711721|-----++!!++++++
+!+!+!+-!16644*+---++!!1*19*19800&amp;amp;12|  +0*-  -!!1800800&amp;amp;008*+---++---+!!!!--++--+!-++!!+
++!!!!!+-+!!+!!+--++!!19999669*0&amp;amp;082737746641249*088800&amp;amp;0&amp;amp;0*!--++----+++!!!+++--+++!!!!+
+-++!!154*16699446445533222259*0&amp;amp;0&amp;amp;097134432249*1888880&amp;amp;0&amp;amp;00972344455532354233334455456+
++!!!!1*!++!!!!!!!196966444556980&amp;amp;00&amp;amp;0511736*1*1888880000&amp;amp;0&amp;amp;152547746644496537222232346+
+--++!!!16696466444553227777349880&amp;amp;00&amp;amp;0&amp;amp;08888888*1*1888000&amp;amp;0&amp;amp;!+--+--1445335545772465366+
+-!169*196964553333222771172249080088800*+!!199996698*0800&amp;amp;0&amp;amp;152546*19*1*!!164664354634+
!19999*1*1996432111111171117754*10088888831723555549*1*19*100844566569955665549*1949456+
!+++++++-+++++!!!!!!--------++!1808*1*14|-        -!1*19669980842375335521756625*199454+
!--++++++!!!!!!!!+18*16*19*134988*14|              -1*!!+!!!1*0096421|-----+!!+-!18*+!!+
!+++!!!1953355354498*18809*1888*14+                -!194345499*009457|----++-++!1664464+
++++!!1*14644546999999*09680*1861-                  -!!+++-----+!!165|--           -++++
!!!!!!!19*!++++!+!!!!!!!108*189|                    -!-       -+!!!1*18471|        -++++
!!!!!!!!!!!!16522332235*08988*1+                    ---+!!!!1*1888080080&amp;amp;16377|      -++
!!!--++++++!!!!!!!!++!108*18*1665|                 -!!19*1*1669*180&amp;amp;00&amp;amp;00&amp;amp;0*1962|--    +
!!!!+!!+++++++++!!!!!1&amp;amp;08809699966643|          -!!1*08434349699*1*0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;099996471117+
1*145442353354444646900888*!!19999644455444664469888895353665355569*0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;09999666511+
199994522227255544468888*08699*1*1644444466669*1800866544*!!+--+!!1*00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;196669644*+
1999*1666666666699*088*188899*19*1966669999*1*1800*19669942213249*00880&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;166995724+
18*19*!!!!!!!!1668088*1*0089*08*1*1*1*1*1*1*188008*189*1635136698888880&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;166962499+
1*19*----------1&amp;amp;1*1999*180*1088888*088*1*18880&amp;amp;0880880944699988888*180&amp;amp;00&amp;amp;0&amp;amp;0871125454+
+------------+00*!!144669*080088808008*1*0880&amp;amp;0008080&amp;amp;0*199*08*1*19*1800&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;11112225+
188888*1*18800*19644464499*080880000&amp;amp;1888*1&amp;amp;0&amp;amp;0&amp;amp;0800&amp;amp;088*1888*1669*1880000&amp;amp;0&amp;amp;0&amp;amp;08888*18+
!!!!!!!!19*08*1966646646666*08800000888880&amp;amp;0&amp;amp;0&amp;amp;000&amp;amp;0&amp;amp;00888889666669*100&amp;amp;0000&amp;amp;0&amp;amp;08666666+
16666666*08*1*!!!!!!!!!1*19*18880&amp;amp;008800&amp;amp;0&amp;amp;0&amp;amp;0000&amp;amp;0000888089999999999*0000000&amp;amp;0&amp;amp;0655554+
!!1664490888*1*1*1*1*1*1*1*188800&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;000&amp;amp;08008*1*1966699*18008000&amp;amp;0&amp;amp;0*!!!!!+
!!!!!1*0008*080*!++!!!!100&amp;amp;00&amp;amp;008008000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;080&amp;amp;08*!!!1999*180800&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;15454+
!!!!!!1&amp;amp;00008945347243527494|     -180&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00000888*1*18*18*1*08000&amp;amp;00&amp;amp;00&amp;amp;15554+
!!!!!!0&amp;amp;000&amp;amp;144254673644697+             +0&amp;amp;00&amp;amp;000000800&amp;amp;088*000008800000&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;09354+
!!!!!1&amp;amp;0&amp;amp;0&amp;amp;0994595565969*12|                -1&amp;amp;00&amp;amp;0&amp;amp;00000&amp;amp;0&amp;amp;008888800080&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;1355+
!!!!!0&amp;amp;00&amp;amp;0&amp;amp;09*1*196*1*1*09664571|            -!196335421722356*0&amp;amp;0080&amp;amp;0&amp;amp;0&amp;amp;0000&amp;amp;0&amp;amp;08444+
166448&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0*18888888888808*165371|     +061|-+-!!+!!-++-+!!!19*1&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0644+
1999*1&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;008000000*+-+- -1*194322461+ -0891+--!!+!++!!!!!199*0000&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0644+
1*1*1*0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;1299|----!18*!161+-16275*189424*0*199569*1*18000000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0946+
1*18&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00000&amp;amp;0&amp;amp;0&amp;amp;164+!!-++!!18089*1646*147489*1908*1*1*1998088000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00969+
1*0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;088888880&amp;amp;0&amp;amp;0*19*!--+!1*000&amp;amp;0&amp;amp;0000080&amp;amp;000088088808888880800000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0*19+
188&amp;amp;0&amp;amp;0&amp;amp;00000888000&amp;amp;008&amp;amp;0*1376808888888888000000000&amp;amp;000000080008008&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;19*+
188&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;00000000&amp;amp;0&amp;amp;0*18&amp;amp;00000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;00000000000000&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;08*1+
180000000000&amp;amp;0&amp;amp;0088000088888*000008880000000000&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00*1+
1&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0080&amp;amp;0*1*1*1*1000&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0888+
1&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;080&amp;amp;0&amp;amp;00&amp;amp;0*199999*1*1800&amp;amp;00&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;00&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0000+
10&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;000&amp;amp;0&amp;amp;0*1*1*1*1*18880000800&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;000&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;0&amp;amp;000 &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;eval(parse(text=ascii))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;extension&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extension&lt;/h2&gt;
&lt;p&gt;Ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Could probably use error diffusion for a slightly better image given the limited palette&lt;/li&gt;
&lt;li&gt;Add some randomness to the next character selection and then generate
multiple images until you have an executable ascii image which evaluates
into the answer you want.
&lt;ul&gt;
&lt;li&gt;e.g. an ascii image of the greek letter pi which evaluates to &lt;code&gt;3.14&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Note: I’m either going to need a &lt;strong&gt;lot&lt;/strong&gt; of computing power, or a smart
approach. Genetic/evolutionary algos?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Changing the default arguments to a function</title>
      <link>https://coolbutuseless.github.io/2018/04/11/changing-the-default-arguments-to-a-function/</link>
      <pubDate>Wed, 11 Apr 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/11/changing-the-default-arguments-to-a-function/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-i-dont-like-the-default-arguments-of-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: I don’t like the default arguments of a function&lt;/h2&gt;
&lt;p&gt;Say I don’t like the default arguments of a particular function. What can I do about it?&lt;/p&gt;
&lt;p&gt;For example, 99.999% of the time, I’d be happier with &lt;code&gt;mean&lt;/code&gt; defaulting to &lt;code&gt;na.rm=TRUE&lt;/code&gt;. Instead I
get NAs when I don’t want, and I have to remember to call it and override the default &lt;code&gt;na.rm&lt;/code&gt; value.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# I usually forget to set `na.rm` on the first call
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA), na.rm=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://trinkerrstuff.wordpress.com/2014/08/19/hijacking-r-functions-changing-default-arguments-3/&#34;&gt;Trinker’s Experiments&lt;/a&gt; with the same idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;write-a-wrapper-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Write a wrapper function&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Write a wrapper function that has a different default&lt;/li&gt;
&lt;li&gt;Pros:
&lt;ul&gt;
&lt;li&gt;Easy&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Cons:
&lt;ul&gt;
&lt;li&gt;Have to remember to get the arguments the same as the original call&lt;/li&gt;
&lt;li&gt;Creates a new function in environment which masks the function in the package&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean.default &amp;lt;- function(x, trim=0, na.rm=TRUE, ...) {
  base::mean.default(x, trim, na.rm, ...)
}

mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-partial-function-using-purrrpartial&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a partial function using &lt;code&gt;purrr::partial()&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Similar to writing a wrapper function except more of the work is
done automatically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cons&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creates a new function in environment which masks the function in the package&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean.default &amp;lt;- purrr::partial(base::mean.default, na.rm=TRUE)

mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;update-the-formal-arguments-for-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Update the formal arguments for a function&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rewrite the formal arguments for the function&lt;/li&gt;
&lt;li&gt;See Hadley’s &lt;a href=&#34;http://adv-r.had.co.nz/Functions.html&#34;&gt;Advanced R&lt;/a&gt; for more on functions and formal arguments.&lt;/li&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;No need to change existing R code i.e. still calling the same function name&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Fiddly to implement&lt;/li&gt;
&lt;li&gt;Actually creates a new function in the global environment which masks the original &lt;code&gt;mean&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;This won’t change the behaviour when function is from a package and called via &lt;code&gt;::&lt;/code&gt; e.g. &lt;code&gt;base::mean.default()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;fargs                 &amp;lt;- formals(mean.default)
fargs$na.rm           &amp;lt;- TRUE
formals(mean.default) &amp;lt;- fargs

mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;base::mean.default(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;use-the-default-package&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use the &lt;code&gt;default&lt;/code&gt; package&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Nicer syntax than just manually hacking at &lt;code&gt;formals()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Actually creates a new function in the global environment which masks the original &lt;code&gt;mean&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;This won’t change the behaviour when function is from a package and called via &lt;code&gt;::&lt;/code&gt; e.g. &lt;code&gt;base::mean.default()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This won’t let you set an argument to have no default i.e. you can’t change &lt;code&gt;na.rm&lt;/code&gt; to have no default
such that it must always be specified when the function is called&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(default)
default(mean.default) &amp;lt;- list(na.rm=TRUE)

mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;base::mean.default(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;use-a-sledgehammer&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Use a sledgehammer&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I wrote a sledgehammer function to solve this problem with enough power to
corrupt all the functions in R if you really wanted to.&lt;/li&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;You can do a lot of evil with this function.&lt;/li&gt;
&lt;li&gt;This changes functions inside packages &lt;em&gt;in-situ&lt;/em&gt;, e.g. &lt;code&gt;base::mean.default()&lt;/code&gt; will
be changed in place within the namespace of the package.&lt;/li&gt;
&lt;li&gt;Works with locked environments&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;You can do a lot of evil with this function&lt;/li&gt;
&lt;li&gt;Unlocking and changing base R packages is probably frowned upon.&lt;/li&gt;
&lt;li&gt;Editing functions in-place within a package doesn’t always work e.g.
&lt;code&gt;stats::sd&lt;/code&gt; doesn’t get updated correctly with this method&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Change the formal arguments of a function
#&amp;#39;
#&amp;#39; If the function is specified within a package, then update the function
#&amp;#39; within the namespace of the package.
#&amp;#39;
#&amp;#39; @param function_name character name of function
#&amp;#39; @param package_name character name of package. Set this if you want the function 
#&amp;#39;                     to be updated within the package namespace.  If this is unset
#&amp;#39;                     then the changed function is placed in the specified environment
#&amp;#39; @param envir environment to place the function if package_name not set
#&amp;#39;
#&amp;#39; @return TRUE otherwise should throw an error
#&amp;#39;
#&amp;#39; @importFrom rlang dots_definitions f_rhs
#-----------------------------------------------------------------------------
update_function_arguments &amp;lt;- function(function_name, package_name=NULL, envir=parent.frame(), ...) {

  #---------------------------------------------------------------------------
  # rlang::dots_definitions() always captures empty values whereas
  # rlang::quos() drops an empty argument if it&amp;#39;s the last one.
  #---------------------------------------------------------------------------
  dots  &amp;lt;- rlang::dots_definitions(...)$dots

  #---------------------------------------------------------------------------
  # Get the named function and its formal arguments.
  # If `package_name` is defined, then get the function from within that
  # package, otherwise
  #---------------------------------------------------------------------------
  if (is.null(package_name)) {
    func &amp;lt;- get(function_name, envir = envir)
  } else {
    func  &amp;lt;- getFromNamespace(function_name, ns=package_name)
  }
  fargs &amp;lt;- formals(func)

  #---------------------------------------------------------------------------
  # For each named item in ..., set the formal argument
  #---------------------------------------------------------------------------
  for (i in seq(dots)) {
    argument_name &amp;lt;- names(dots)[i]
    fargs[argument_name] &amp;lt;- list(rlang::f_rhs(dots[[i]]))
  }

  #---------------------------------------------------------------------------
  # Update the function with new formal arguments
  #---------------------------------------------------------------------------
  formals(func) &amp;lt;- fargs

  #---------------------------------------------------------------------------
  # If no `package_name` is defined, then just assign function in .GlobalEnv.
  # Otherwise if `package_name` is set:
  #  - Get the package as an environment
  #  - Unlock the environment if it is locked
  #  - Assign the new function into the package
  #  - Re-lock the environment if it was initially locked
  #
  # This seems to mostly work. 
  #---------------------------------------------------------------------------
  if (is.null(package_name)) {
    assign(function_name, func, envir=envir)
  } else {
    package_env &amp;lt;- as.environment(paste0(&amp;#39;package:&amp;#39;, package_name))

    locked &amp;lt;- bindingIsLocked(function_name, package_env)
    if (locked) { unlockBinding(function_name, package_env) }

    package_env[[function_name]] &amp;lt;- func

    if (locked) { lockBinding(function_name, package_env) }
  }

  #---------------------------------------------------------------------------
  # Return quietly
  #---------------------------------------------------------------------------
  invisible(TRUE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=TRUE)
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;base::mean.default(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;removing-the-default-value-for-an-argument-to-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Removing the default value for an argument to a function&lt;/h2&gt;
&lt;p&gt;By using &lt;code&gt;rlang&lt;/code&gt; and &lt;code&gt;formals&lt;/code&gt; you can actually unset a default argument from a function.
This means that a funciton call now &lt;strong&gt;must&lt;/strong&gt; specify what was previously an assumed default.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=)
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA), na.rm=TRUE)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;maliciously-updating-default-arguments&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Maliciously updating default arguments&lt;/h2&gt;
&lt;p&gt;Being able to change default arguments is a dangerous power to hold!&lt;/p&gt;
&lt;p&gt;You can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;set defaults where there shouldn’t be&lt;/li&gt;
&lt;li&gt;set the argument to a meaningless value and watch the chaos ensue&lt;/li&gt;
&lt;li&gt;set the argument to an expression&lt;/li&gt;
&lt;li&gt;set the argument to generate a random value&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;slightly-evil-nonsensical-default-leads-to-idiotic-error&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Slightly evil: Nonsensical default leads to idiotic error&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=c(1, 3, 5))
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;slightly-evil-add-default-arguments-to-things-which-shouldnt-have-them&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Slightly evil: Add default arguments to things which shouldn’t have them&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, x = 1:4)
mean.default()  # mean of nothing!&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning in if (na.rm) x &amp;lt;- x[!is.na(x)]: the condition has length &amp;gt; 1 and only
## the first element will be used&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 2.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pure-evil-make-a-default-argument-dependent-on-another-variable&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pure evil: Make a default argument dependent on another variable&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=length(x) &amp;gt; 3)
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pure-evil-change-a-default-argument-to-be-set-randomly&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pure evil: Change a default argument to be set randomly&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, na.rm=rnorm(1) &amp;gt; 0.5)
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;pure-evil-change-a-default-argument-to-give-random-errors&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Pure evil: Change a default argument to give random errors&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;update_function_arguments(&amp;#39;mean.default&amp;#39;, &amp;#39;base&amp;#39;, 
                          na.rm=ifelse(rnorm(1)&amp;gt;0.5, stop(&amp;quot;My hovercraft is full of eels&amp;quot;, call.=FALSE), TRUE))
mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mean(c(1, 3, 5, NA))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] NA&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion-with-great-power-comes-great-responsibility&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion: With great power comes great responsibility&lt;/h2&gt;
&lt;p&gt;If you were putting together a list of things not to do in R, this would probably be on it.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Solving the 8 queens problem</title>
      <link>https://coolbutuseless.github.io/2018/04/10/solving-the-8-queens-problem/</link>
      <pubDate>Tue, 10 Apr 2018 17:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/10/solving-the-8-queens-problem/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction-to-the-8-queens-puzzle&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Introduction to the 8 queens puzzle&lt;/h1&gt;
&lt;p&gt;The eight queens puzzle is the problem of placing eight chess queens on an 8×8 chessboard so that no two queens threaten each other.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Eight_queens_puzzle&#34;&gt;wikipedia page&lt;/a&gt; is a good starting resource.&lt;/p&gt;
&lt;p&gt;This post contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A neat version of a recursive function for finding all solutions: &lt;code&gt;place_queen()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A manually minified version that fits in a tweet (including generating a plot)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;recursive-solution-in-r&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Recursive solution in R&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)

#-----------------------------------------------------------------------------
#&amp;#39; Try and place a queen given the queens we have on the board so far.
#&amp;#39;
#&amp;#39; This function calls itself iteratively for every valid placement of the
#&amp;#39; next queen. 
#&amp;#39;
#&amp;#39; @param queens A vector of integers representing the column placement 
#&amp;#39;               of queens so far. The index within this list
#&amp;#39;               is the row, and the value is the column.  
#&amp;#39;
#&amp;#39;  e.g. queens = c(1, 4, 7) corresponds to
#&amp;#39;                  
#&amp;#39;
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   |   |   |
#&amp;#39;  ---------------------------------
#&amp;#39;  |   |   |   |   |   |   | Q |   |    3rd row, 7th column
#&amp;#39;  --------------------------------- 
#&amp;#39;  |   |   |   | Q |   |   |   |   |    2nd row, 4th column
#&amp;#39;  ---------------------------------
#&amp;#39;  | Q |   |   |   |   |   |   |   |    1st row, 1st column
#&amp;#39;  ---------------------------------
#&amp;#39;
#&amp;#39;
#&amp;#39;
#&amp;#39;
#&amp;#39; @return a list of length 92. Each list element is a vector of 8 integers 
#&amp;#39;         i.e. a solution to the 8 queens problem
#-----------------------------------------------------------------------------
place_queen &amp;lt;- function(queens=c()) {
  # If there are 8 queens placed, then this must be a solution.
  if (length(queens) == 8) {
    return(list(queens))
  }
  
  # Figre out where a queen can be placed in the next row.
  # Drop all columns that have already been taken - since we 
  # can&amp;#39;t place a queen below an existing queen
  possible_placements &amp;lt;- setdiff(1:8, queens)
  
  # For each queen already on the board, find the diagonal 
  # positions that it can see in this row.
  diag_offsets &amp;lt;- seq.int(length(queens), 1)
  diags &amp;lt;- c(queens + diag_offsets, queens - diag_offsets)
  diags &amp;lt;- diags[diags &amp;gt; 0 &amp;amp; diags &amp;lt; 9]
  
  # Drop these diagonal columns from possible placements
  possible_placements &amp;lt;- setdiff(possible_placements, diags)
  
  # For each possible placement, try and place a queen
  possible_placements %&amp;gt;% 
    map(~place_queen(c(queens, .x))) %&amp;gt;%
    keep(~length(.x) &amp;gt; 0) %&amp;gt;%
    flatten()
}


#-----------------------------------------------------------------------------
#&amp;#39; Plot a single solution
#&amp;#39; @param queens a vector of 8 integers giving the column positions of 8 queens
#-----------------------------------------------------------------------------
plot_single_8queens &amp;lt;- function(queens) {
  queens_df &amp;lt;- data_frame(cols = queens, rows=1:8)
  board_df &amp;lt;- expand.grid(cols = 1:8, rows = 1:8) %&amp;gt;% 
    mutate(check = (cols + rows) %%2 == 1)
  
  ggplot(queens_df, aes(cols, rows)) + 
    geom_tile(data=board_df, aes(fill=check), colour=&amp;#39;black&amp;#39;) +
    geom_label(label=&amp;#39;Q&amp;#39;, fill=&amp;#39;lightblue&amp;#39;) + 
    theme_void() + 
    coord_equal() + 
    scale_fill_manual(values = c(&amp;#39;TRUE&amp;#39;=&amp;#39;white&amp;#39;, &amp;#39;FALSE&amp;#39;=&amp;#39;black&amp;#39;)) + 
    theme(
      legend.position = &amp;#39;none&amp;#39;
    ) + 
    labs(title = paste(&amp;quot;Queens&amp;quot;, deparse(as.numeric(queens))))
  
}


#-----------------------------------------------------------------------------
# Start with no queens placed and generate all solutions. Plot the first 2
#-----------------------------------------------------------------------------
solutions &amp;lt;- place_queen()&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;do.call(rbind, solutions) %&amp;gt;%
  as.data.frame() %&amp;gt;% 
  head(10) %&amp;gt;%
  knitr::kable(caption=&amp;quot;First 10 solutions (Each row is a solution)&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;First 10 solutions (Each row is a solution)&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;V1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V2&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V3&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V4&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V5&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V6&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V7&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;V8&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot_single_8queens(solutions[[1]])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: `data_frame()` is deprecated, use `tibble()`.
## This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-04-10-8-queens_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;plot_single_8queens(solutions[[2]])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-04-10-8-queens_files/figure-html/unnamed-chunk-3-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;div id=&#34;queens-solution-in-rstats-compacted-into-a-tweet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;8Queens solution in Rstats Compacted into a tweet&lt;/h2&gt;
&lt;p&gt;This tweet calculates all 92 solutions and plots them on a checkered board -
the bright blue squares on the board represent the locations of the queens.&lt;/p&gt;
&lt;p&gt;This solution is exactly 280 characters and fits in a tweet!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(tidyverse)
v=1:8
f=function(q){L=length(q)
if(L==8){q}else{flatten(map(setdiff(v,c(q,q+L:1,q-L:1)),~f(c(q,.x))))}}
s=data.frame(c=unlist(f(c())),r=v,x=rep(1:92,e=8),z=4)
b=mutate(crossing(c=v,r=v),z=(c+r)%%2)
g=geom_tile
ggplot(s,aes(r,c,fill=z))+g(d=b)+g()+facet_wrap(~x)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/8queens/8queens.png&#34; width=&#34;80%&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;extension&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Extension&lt;/h2&gt;
&lt;p&gt;Nothing else to do :)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Finding a length n needle in a haystack</title>
      <link>https://coolbutuseless.github.io/2018/04/03/finding-a-length-n-needle-in-a-haystack/</link>
      <pubDate>Tue, 03 Apr 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/04/03/finding-a-length-n-needle-in-a-haystack/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-find-index-of-a-short-vector-needle-inside-a-larger-vector-haystack&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Find index of a short vector (needle) inside a larger vector (haystack)&lt;/h2&gt;
&lt;p&gt;What’s a good way to find the location of a &lt;code&gt;needle&lt;/code&gt; in a &lt;code&gt;haystack&lt;/code&gt;?&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;haystack &amp;lt;- sample(0:12, size = 2000, replace = TRUE)
needle   &amp;lt;- c(2L, 10L, 8L) &lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;haystack&lt;/code&gt; may be large.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;needle&lt;/code&gt; is definitely a vector&lt;/li&gt;
&lt;li&gt;Only the index for the first occurrence of &lt;code&gt;needle&lt;/code&gt; within &lt;code&gt;haystack&lt;/code&gt; is needed&lt;/li&gt;
&lt;li&gt;Assuming that there is always at least 1 occurrence&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-1-for-loop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 1: &lt;code&gt;for&lt;/code&gt; loop&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Naively test every position in a for loop&lt;/li&gt;
&lt;li&gt;Advantage of this method over a vectorised approach, is that it can
terminate early i.e. as soon as a value is found&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;forloop_find &amp;lt;- function(needle, haystack) {
  n &amp;lt;- length(needle) - 1L
  for (i in seq(haystack)) {
    if (identical(haystack[i:(i+n)], needle)) {
      return(i)
    }
  }
}

forloop_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-2-vapply&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 2: &lt;code&gt;vapply&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;vapply_find &amp;lt;- function(needle, haystack) {
  n &amp;lt;- length(needle) - 1L
  which(vapply(seq(haystack), function(i) {identical(haystack[i:(i+n)], needle)}, FUN.VALUE = logical(1L)))[1L]
}

vapply_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-3-zoorollapply&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 3: &lt;code&gt;zoo::rollapply&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;rollapply_find &amp;lt;- function(needle, haystack) {
  which(zoo::rollapply(haystack, length(needle), identical, needle))[1L]
}

rollapply_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-4-stacked-lead-finding&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 4: stacked &lt;code&gt;lead()&lt;/code&gt; finding&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;for each item in the needle
&lt;ul&gt;
&lt;li&gt;shift the haystack and check for the needle element&lt;/li&gt;
&lt;li&gt;stack the shifted haystacks and sum them&lt;/li&gt;
&lt;li&gt;check where &lt;code&gt;sum == length(needle)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;lead_find &amp;lt;- function(needle, haystack) {
  v  &amp;lt;- haystack == needle[1]
  for (i in seq(2, length(needle))) {
    v &amp;lt;- v + (lead(haystack, i-1L) == needle[i])
  }
  
  which(v == length(needle))[1L]
}

lead_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-5-shift&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 5: &lt;code&gt;shift&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data.table::shift&lt;/code&gt; is a vectorised version of &lt;code&gt;dplyr::lead()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Adapted from user “Jaap” on &lt;a href=&#34;https://stackoverflow.com/questions/48660606/find-a-sequence-of-numbers-in-a-vector&#34;&gt;stackoverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;shift_find &amp;lt;- function(needle, haystack) {
  shifted_haystack &amp;lt;- data.table::shift(haystack, type=&amp;#39;lead&amp;#39;, 0:(length(needle)-1))
  
  v &amp;lt;- Map(&amp;#39;==&amp;#39;, shifted_haystack, needle)
  v &amp;lt;- Reduce(&amp;#39;+&amp;#39;, v)
  
  which(v == length(needle))[1]
}

shift_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-5-rcpp-for-loop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 5: Rcpp &lt;code&gt;for&lt;/code&gt; loop&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;update 2018-04-04
&lt;ul&gt;
&lt;li&gt;Shaved a few % points off the runtime by using the value of &lt;code&gt;j&lt;/code&gt; instead of an
explicit &lt;code&gt;match&lt;/code&gt; count.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(&amp;#39;int rcpp_find(NumericVector needle, NumericVector haystack) {
    int needle_length   = needle.size();
    int haystack_length = haystack.size();

    for (int i = 0; i &amp;lt; (haystack_length - needle_length); i++ ) {
        int j;
        for (j = 0; j &amp;lt; needle_length; j++ ) {
                if (needle[j] != haystack[i + j]) {
                    break;
                }
        }

        if (j == needle_length) {
            return(i+1);
        }
    }

    return(0);

    }&amp;#39;)


rcpp_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-6-pile-find-by-dmytro&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 6: &lt;code&gt;pile&lt;/code&gt; find (by &lt;a href=&#34;https://twitter.com/dmi3k&#34;&gt;dmytro&lt;/a&gt;)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/dmi3k&#34;&gt;dmytro&lt;/a&gt; on twitter offered this one.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;pile_find &amp;lt;- function(needle, haystack) { 
  index &amp;lt;- seq_along(haystack) 
  for (i in seq_along(needle)) { 
    pile &amp;lt;- haystack[index] 
    index &amp;lt;- index[pile==needle[i]] + 1L
  } 
  (index-length(needle))[1]
} 

pile_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-7-sieved-find-by-carroll_jono&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 7: Sieved find (by &lt;a href=&#34;https://twitter.com/carroll_jono&#34;&gt;carroll_jono&lt;/a&gt;)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/carroll_jono&#34;&gt;carroll_jono&lt;/a&gt; on twitter offered this one.&lt;/li&gt;
&lt;li&gt;This is the fastest of the pure-R methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sieved_find &amp;lt;- function(needle, haystack) { 
  sieved &amp;lt;- which(haystack == needle[1L]) 
  for (i in seq.int(1L, length(needle)-1L)) {
    sieved &amp;lt;- sieved[haystack[sieved + i] == needle[i + 1L]]
  }
  sieved[1L] 
}

sieved_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-8-coerce-to-string-and-use-grep&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 8: Coerce to string and use grep&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Convert each integer into a string e.g. &lt;code&gt;c(1, 2, 3)&lt;/code&gt; becomes “001.002.003”&lt;/li&gt;
&lt;li&gt;Current tests are with integers less than 1000, so I’m safe to use &lt;code&gt;%03i&lt;/code&gt; as a format string.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;grep_find &amp;lt;- function(needle, haystack) {
  expanded_width &amp;lt;- 4  # 3 digits plus a &amp;quot;.&amp;quot;
  res &amp;lt;- stringr::str_locate_all(paste(sprintf(&amp;quot;%03i&amp;quot;, haystack), collapse=&amp;quot;.&amp;quot;), paste(sprintf(&amp;quot;%03i&amp;quot;, needle), collapse=&amp;quot;.&amp;quot;))[[1]][,1][[1]]
  
  (res-1)/expanded_width + 1
}

grep_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-9-idomatic-c-solution-hrbrmstr&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 9: Idomatic C++ solution &lt;a href=&#34;https://twitter.com/hrbrmstr&#34;&gt;hrbrmstr&lt;/a&gt;&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;Rcpp::cppFunction(&amp;#39;int idiomaticrcpp_find(NumericVector needle, NumericVector haystack) {
  NumericVector::iterator it;
  it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end());
  int pos = it - haystack.begin() + 1;
  if (pos &amp;gt; haystack.size()) pos = -1;
  return(pos);
}&amp;#39;)

idiomaticrcpp_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;solution-10-rcpp-boyer-moore-jimhester&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution 10: Rcpp boyer-moore &lt;a href=&#34;https://twitter.com/jimhester_&#34;&gt;jimhester&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Boyer-Moore implementation in Rcpp by &lt;a href=&#34;https://twitter.com/jimhester_&#34;&gt;jimhester&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# https://gist.github.com/jimhester/2d02d63d0459d9fdadcf15e08c3afc0a
Rcpp::sourceCpp(&amp;quot;cache/2018-04-03-boyer-moore.cpp&amp;quot;)
boyermoorecpp_find(needle, haystack)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 931&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;needle-is-in-the-middle-of-the-haystack&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;needle&lt;/code&gt; is in the middle of the &lt;code&gt;haystack&lt;/code&gt;&lt;/h2&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-14&#34;&gt;Table 1: &lt;/span&gt;&lt;code&gt;needle&lt;/code&gt; in middle of &lt;code&gt;haystack&lt;/code&gt;. microbenchmark() timings for 1000 runs - times are in microseconds&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expr&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lq&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mean&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;uq&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;max&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;neval&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rollapply_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64622.974&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;67946.554&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;78132.17233&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;80610.9880&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;83993.7715&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;261446.362&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;vapply_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15304.346&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16611.288&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20492.53295&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17070.3485&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18881.6200&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47565.512&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;lead_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6057.255&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7833.419&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14920.53701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8950.0515&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18850.4280&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;199884.346&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;shift_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2809.894&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3108.799&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6250.15134&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3670.6565&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4361.3965&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;183883.048&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;forloop_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4768.181&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5269.440&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6790.98958&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5457.1060&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5717.7130&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29957.481&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;grep_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3844.324&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4002.460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4402.40560&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4065.0250&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4173.2350&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;184611.679&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pile_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;86.056&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;97.890&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;289.28966&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;102.9325&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;109.6500&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21766.544&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sieved_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41.337&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;53.283&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;75.26908&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;57.4095&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;63.0490&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7256.632&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rcpp_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16.063&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22.517&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.00685&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27.7005&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31.9475&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5173.280&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;idiomaticrcpp_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.401&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20.561&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;98.40539&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25.3500&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29.7495&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20635.513&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boyermoorecpp_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13.654&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23.306&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;86.19733&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28.1015&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32.6330&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23749.599&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-04-03-finding-a-length-n-needle-in-a-haystack_files/figure-html/unnamed-chunk-14-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;needle-is-very-close-to-beginning-of-haystack&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;needle&lt;/code&gt; is very close to beginning of &lt;code&gt;haystack&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;for loop&lt;/code&gt; and &lt;code&gt;rcpp&lt;/code&gt; are the only methods to benefit from a &lt;code&gt;needle&lt;/code&gt; that is thought to be at the beginning
of the &lt;code&gt;haystack&lt;/code&gt; i.e. they can both return early as soon as they find match.&lt;/p&gt;
&lt;p&gt;When the needle is close to the beginning of the haystack, then the searching time is very short, and the &lt;code&gt;for loop&lt;/code&gt;
is quite competitive with custom &lt;code&gt;Rcpp&lt;/code&gt; code.&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-16&#34;&gt;Table 2: &lt;/span&gt;&lt;code&gt;needle&lt;/code&gt; near start of &lt;code&gt;haystack&lt;/code&gt;. microbenchmark() timings for 1000 runs - times are in microseconds&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;expr&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lq&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mean&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;uq&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;max&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;neval&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;pile_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;71.184&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;126.9605&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;177.69453&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;138.3465&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;163.8710&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13695.14&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;sieved_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.268&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69.6190&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;83.41948&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;76.2080&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;89.6610&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;223.01&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;forloop_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23.804&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30.7580&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;53.60288&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34.7525&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45.3105&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11729.11&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;rcpp_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.483&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.9385&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;72.01494&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;53.3860&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;62.0890&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12677.34&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boyermoorecpp_find(needle, haystack)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16.315&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;51.0210&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;97.70492&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;56.7190&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;67.5945&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13618.62&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-04-03-finding-a-length-n-needle-in-a-haystack_files/figure-html/unnamed-chunk-16-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-04-03-finding-a-length-n-needle-in-a-haystack_files/figure-html/unnamed-chunk-19-1.png&#34; width=&#34;768&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Summary&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Rcpp&lt;/code&gt; is the fastest way. No real difference between my C-style of C++ and idiomatic C++&lt;/li&gt;
&lt;li&gt;Boyer-Moore in Rcpp no faster than a vanilla solution for current benchmark sizes&lt;/li&gt;
&lt;li&gt;For a pure &lt;code&gt;R&lt;/code&gt; solution, the &lt;code&gt;sieve_find()&lt;/code&gt; method is fastest and very competitive with &lt;code&gt;Rcpp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Assert condition over a code block</title>
      <link>https://coolbutuseless.github.io/2018/03/23/assert-condition-over-a-code-block/</link>
      <pubDate>Fri, 23 Mar 2018 05:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/23/assert-condition-over-a-code-block/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;assert-an-expression-is-unchanged-over-a-code-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Assert an expression is unchanged over a code block&lt;/h2&gt;
&lt;p&gt;Most (all?) testing packages in R are built around the idea of testing a value
at a particular moment in time e.g. “Check that &lt;code&gt;a == 2&lt;/code&gt; &lt;strong&gt;right now&lt;/strong&gt;”.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/22/assert-condition-over-a-code-block/&#34;&gt;prior post&lt;/a&gt; detailed a function to test an expected
&lt;em&gt;changed&lt;/em&gt; in value of a particular expression before &amp;amp; after some particular code is run. E.g. I might not know how long
a data.frame is, but I do know that it should grow by 2 rows during the execution of some function.&lt;/p&gt;
&lt;p&gt;This post shows a simplification of yesterday’s testing function which only tests that a value is unchanged over a block of code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;assert_unchanged&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;assert_unchanged()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The following code tests the validity of a statement over a code block.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;statement&lt;/code&gt; to test is of the form &lt;code&gt;[after] [logical operator] [before]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;E.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a == a + 1&lt;/code&gt; – when we expect the value of a to be incremented by 1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nrow(df) == nrow(df) - 3&lt;/code&gt; – when we expect 3 rows to be removed from the data.frame &lt;code&gt;df&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Check the evaluation of a statement is unchanged before/after a block of code
#&amp;#39; @param statement some expression to be evaludated e.g. `nrow(df)`
#&amp;#39; @param code code block to be evaluated
#&amp;#39; @return If statement is unchanged, return an `invisible(TRUE)`, otherwise
#&amp;#39;         raise an error
#-----------------------------------------------------------------------------
assert_unchanged &amp;lt;- function(statement, code) {

  # Capture the statement so we can manipulate it
  exp &amp;lt;- substitute(statement)

  # Evaluate in order
  #  - statement before the block
  #  - the actual code block
  #  - statement after the block
  before &amp;lt;- eval(exp)
  res    &amp;lt;- eval(code)
  after  &amp;lt;- eval(exp)

  # The statement passes if the `before` and `after` values are equal
  statement_passed &amp;lt;- identical(before, after)

  if (!statement_passed) {
    stop(&amp;quot;The following statement has changed value: &amp;quot;, deparse(exp), call.=FALSE)
  }

  invisible(TRUE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test that we can write a code block which passes the assertion i.e. expect that the length of &lt;code&gt;a&lt;/code&gt; remains unchanged, and it does.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a &amp;lt;- c(1, 2, 3)

assert_unchanged(
  length(a),  
  {
    a[1] &amp;lt;- 10
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test that we can write a code block which causes an error i.e. expect &lt;code&gt;b&lt;/code&gt; to remain unchanged, but it doesnt&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;b &amp;lt;- 2

assert_unchanged(
  b,  
  {
    b &amp;lt;- 3
  }
)

# Error: The following statement has changed value: b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Proof-of-concept seems plausible.&lt;/li&gt;
&lt;li&gt;Extensions
&lt;ul&gt;
&lt;li&gt;Be able to test multiple statements are unchanged over a code block. The call signature of such a
function is going to need thinking though i.e. is it more sensible to:
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Have a signature like &lt;code&gt;assert_unchanged(code, ...)&lt;/code&gt; which shifts the &lt;code&gt;code&lt;/code&gt; to be first followed
by a varying number of statements, or&lt;/li&gt;
&lt;li&gt;Have a call signature of &lt;code&gt;assert_unchanged(...)&lt;/code&gt; and automatically interpret the last item
in the argument list be interpreted as the code block, and the preceding arguments are
the tests? (This is similar to how &lt;code&gt;ensurer&lt;/code&gt; does some argument unpacking)&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;More checks needed to see that this behaves nicely when calling functions.&lt;/li&gt;
&lt;li&gt;More verbose error with the actual evaluated values of the before/after shown
e.g. “The following statement has changed value: b. ‘2’ =&amp;gt; ‘3’”&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Assert condition over a code block</title>
      <link>https://coolbutuseless.github.io/2018/03/22/assert-condition-over-a-code-block/</link>
      <pubDate>Thu, 22 Mar 2018 16:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/22/assert-condition-over-a-code-block/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;assert-a-logical-statement-over-a-code-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Assert a logical statement over a code block&lt;/h2&gt;
&lt;p&gt;Most (all?) testing packages in R are built around the idea of testing a value
at a particular moment in time e.g. “Check that &lt;code&gt;a == 2&lt;/code&gt; &lt;strong&gt;right now&lt;/strong&gt;”.&lt;/p&gt;
&lt;p&gt;This post proposes a way to test the expected
&lt;em&gt;change&lt;/em&gt; in value of a particular expression before &amp;amp; after some particular code is run. E.g. I might not know how long
a data.frame is, but I do know that it should grow by 2 rows during the execution of some function.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;quick-survey-of-testing-packages&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Quick survey of testing packages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=testthat&#34;&gt;&lt;code&gt;testthat&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Easy testing within packages and in scripts&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=ensurer&#34;&gt;&lt;code&gt;ensurer&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Doing interesting things with creating type safe functions and checking return values&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=assertr&#34;&gt;&lt;code&gt;assertr&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;A great &lt;a href=&#34;http://ropensci.org/&#34;&gt;ROpenSci&lt;/a&gt; package for testing within a pipe&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/package=checkmate&#34;&gt;&lt;code&gt;checkmate&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Great high-level checking functions meant for checking arguments at the top of a function call.&lt;/li&gt;
&lt;li&gt;Combines lots of standard checks into single calls to improve readability and reduce clutter.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;missing-test-type---testing-over-a-code-block&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Missing test type - testing over a code block&lt;/h2&gt;
&lt;p&gt;All the testing packages (AFAIK) offer testing of values &lt;strong&gt;at a single point in time&lt;/strong&gt; e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the value of this variable &lt;strong&gt;right now&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Is this variable NULL, &lt;strong&gt;right now&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, I sometimes want a comparison test of how a value has changed before/after a block of code.&lt;/p&gt;
&lt;p&gt;E.g. if you want to test that the length of the vector &lt;code&gt;a&lt;/code&gt; is unchanged after running a section of code, it would look something like:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;original_length &amp;lt;- length(a)
{
  ... block of code that does something with &amp;#39;a&amp;#39; ...
}
stopifnot(length(a) == original_length)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I will often write this type of code to sanity check that I hasn’t lost any rows from a data.frame during a complex
merge calculation - especially when there might be many corner cases I thought I’d already handled!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;assert_over&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;assert_over()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The following code tests the validity of a statement over a code block.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;statement&lt;/code&gt; to test is of the form &lt;code&gt;[after] [logical operator] [before]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;E.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a == a + 1&lt;/code&gt; – when we expect the value of a to be incremented by 1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nrow(df) == nrow(df) - 3&lt;/code&gt; – when we expect 3 rows to be removed from the data.frame &lt;code&gt;df&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Check the validity of a statement evaluated over a code block
#&amp;#39; @param statement [after expression] [logical operator] [before expression]
#&amp;#39;                  e.g.  `a == a + 1`
#&amp;#39; @param code code block to be evaluated
#&amp;#39; @return If statement passes, return an `invisible(TRUE)`, otherwise
#&amp;#39;         raise an error
#-----------------------------------------------------------------------------
assert_over &amp;lt;- function(statement, code) {

  # Capture the statement so we can manipulate it
  exp &amp;lt;- substitute(statement)

  # Check that it is a sane statement of the form:  [after] == [before] or similar
  stopifnot(length(exp) == 3)
  stopifnot(as.character(exp[[1]]) %in% c(&amp;#39;==&amp;#39;, &amp;#39;!=&amp;#39;, &amp;#39;&amp;gt;=&amp;#39;, &amp;#39;&amp;gt;&amp;#39;, &amp;#39;&amp;lt;&amp;#39;, &amp;#39;&amp;lt;=&amp;#39;))

  # Evaluate in order
  #  - the &amp;#39;before&amp;#39; side of the statement
  #  - the actual code block
  #  - the &amp;#39;after&amp;#39; side of the statement
  before &amp;lt;- eval(exp[[3]])
  res    &amp;lt;- eval(code)
  after  &amp;lt;- eval(exp[[2]])

  # The statement passes if the `before` and `after` values obey whatever 
  # logical argument the user provided
  statement_passed &amp;lt;- eval(as.call(list(exp[[1]], after, before)))

  if (!statement_passed) {
    stop(&amp;quot;The following statement is not true: &amp;quot;, deparse(exp), call.=FALSE)
  }

  invisible(TRUE)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test that we can write a code block which passes the assertion i.e. expect that the length of &lt;code&gt;a&lt;/code&gt; increases by 1, and it does.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;a &amp;lt;- c(1, 2, 3)

assert_over(
  length(a) == length(a) + 1,  
  {
    a &amp;lt;- c(a, 4)
  }
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Test that we can write a code block which causes an error i.e. expect &lt;code&gt;b&lt;/code&gt; to more than double in value, but it doesn’t.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;b &amp;lt;- 2

assert_over(
  b &amp;gt; 2 * b,  
  {
    b &amp;lt;- 3
  }
)

# Error: The following statement is not true: b &amp;gt; 2 * b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Proof-of-concept seems plausible.&lt;/li&gt;
&lt;li&gt;Extensions
&lt;ul&gt;
&lt;li&gt;Common special case is to test that a particular expression doesn’t change e.g. 
&lt;code&gt;nrow(df)&lt;/code&gt; is a constant. Write a similar function to do this i.e. &lt;code&gt;assert_unchanged(statement, code)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Be able to run multiple tests over a code block. The call signature of such a
function is going to need thinking though i.e. is it more sensible to:
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Have a signature like &lt;code&gt;assert_over(code, ...)&lt;/code&gt; which shifts the &lt;code&gt;code&lt;/code&gt; to be first followed
by a varying number of statements, or&lt;/li&gt;
&lt;li&gt;Have a call signature of &lt;code&gt;assert_over(...)&lt;/code&gt; and automatically interpret the last item
in the argument list be interpreted as the code block, and the preceding arguments are
the tests? (This is similar to how &lt;code&gt;ensurer&lt;/code&gt; does some argument unpacking)&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;More checks needed to see that this behaves nicely when calling functions, or for more complex statements.&lt;/li&gt;
&lt;li&gt;More verbose error with the actual evaluated values of the before/after shown
e.g. “Error expecting b &amp;gt; 2 * b, but 3 &amp;gt; 4 is not true”&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Body modification part 5: Adding runtime check of function return value</title>
      <link>https://coolbutuseless.github.io/2018/03/21/body-modification-part-5-adding-runtime-check-of-function-return-value/</link>
      <pubDate>Wed, 21 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/21/body-modification-part-5-adding-runtime-check-of-function-return-value/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-can-i-augment-an-existing-function-with-checking-code-for-its-return-value&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Can I augment an existing function with checking code for its return value?&lt;/h2&gt;
&lt;p&gt;I’m still experimenting with function body modification, and I’ve downscaled my ambitions and thought about what a type check helper should look like.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.github.io/2018/03/20/body-modification-part-4-adding-runtime-checks-to-an-existing-function/&#34;&gt;Yesterday’s post&lt;/a&gt; showed
that a simple function could be used to add checks to an existing function.&lt;/p&gt;
&lt;p&gt;This post is about writing a function to add a check for the return value of a function.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-function-to-be-checked&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example function to be checked&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;calc_value &amp;lt;- function(a=1L, b=2, c=3) {
  (a + b) / c
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;check_return_value&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;check_return_value()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The function for adding checks to another function is shown below.&lt;/p&gt;
&lt;p&gt;It operates by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;taking a function as its first argument&lt;/li&gt;
&lt;li&gt;all subsequent arguments are interpreted as boolean statements for checking the return value with the name &lt;code&gt;res&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create a code block combining all these tests&lt;/li&gt;
&lt;li&gt;create a complete call to the function with the result captured in &lt;code&gt;res&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create a new function that calls the original function, then checks the return value for any errors before returning it&lt;/li&gt;
&lt;li&gt;return the augmented version of the function&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; add checks for the return value of a function
#&amp;#39;
#&amp;#39; @param fun existing function passed in a symbol
#&amp;#39; @param ... list of checks to add for the result of the function assigned to `res`
#&amp;#39;
#&amp;#39; @return new function (with the same function signature as `fun`) with tests
#&amp;#39;         added for the return value
#-----------------------------------------------------------------------------
check_return_value &amp;lt;- function(fun, ...) {
  
  # Capture all the tests and turn each one into a stopifnot() call
  checks &amp;lt;- rlang::exprs(...)
  for (i in seq(checks)) {
    checks[[i]] &amp;lt;- bquote(stopifnot(isTRUE(.(checks[[i]]))))
  }
  
  # Bind all these checks into a single block
  checks &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, splice(checks))
  
  # Create a call to the function
  fun_sym     &amp;lt;- rlang::enexpr(fun)
  call_to_fun &amp;lt;- rlang::call2(fun_sym, splice(syms(names(formals(fun)))))
  
  # Concatentate the call to the function with the checks
  new_body &amp;lt;- bquote({
    res &amp;lt;- .(call_to_fun)
    .(checks)
    return(res)
  })
  
  # create and return the new function
  rlang::new_function(args = formals(fun), body = new_body)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;calc_value_checked_return &amp;lt;- check_return_value(calc_value, !is_na(res))

calc_value_checked_return&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function (a = 1L, b = 2, c = 3) 
## {
##     res &amp;lt;- calc_value(a, b, c)
##     {
##         stopifnot(isTRUE(!is_na(res)))
##     }
##     return(res)
## }
## &amp;lt;environment: 0x7fa4a6a31880&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;gt; calc_value_checked_return()
[1] 1

&amp;gt; calc_value_checked_return(b = NA)  # the result of the calculation will be NA
Error: isTRUE(!is_na(res)) is not TRUE

&amp;gt; calc_value_checked_return(c = 0) # this will cause a divide by zero error -&amp;gt; Inf
[1] Inf&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;check_args&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;check_args()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As per yesterday’s post, a function can also have its &lt;em&gt;arguments&lt;/em&gt; checked. Yesterday’s &lt;code&gt;add_checks()&lt;/code&gt; function
has been renamed to &lt;code&gt;check_args()&lt;/code&gt; and repeated here.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; add checks to an existing function and return a new function
#&amp;#39;
#&amp;#39; @param fun existing function passed in a symbol
#&amp;#39; @param ... list of checks to add in front of function body
#&amp;#39;
#&amp;#39; @return new function (with the same function signature as `fun`) and the same
#&amp;#39;         body as `fun` with a block of tests inserted at the start of the function
#-----------------------------------------------------------------------------
check_args &amp;lt;- function(fun, ...) {
  
  # Capture all the tests and turn each one into a stopifnot() call
  checks &amp;lt;- rlang::exprs(...)
  for (i in seq(checks)) {
    checks[[i]] &amp;lt;- bquote(stopifnot(isTRUE(.(checks[[i]]))))
  }
  
  # Bind all these checks into a single block
  checks &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, splice(checks))
  
  # Concatentate the test block with the original body
  new_body &amp;lt;- bquote({
    .(checks)
    .(body(fun))
  })
  
  # create and return the new function
  rlang::new_function(args = formals(fun), body = new_body)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now add a check to ensure that the argument &lt;code&gt;c&lt;/code&gt; is never 0. This is in addition to the checks for the return value of the function as a whole.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;calc_value_checked_args_and_return &amp;lt;- check_args(calc_value_checked_return, c != 0)
calc_value_checked_args_and_return&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function (a = 1L, b = 2, c = 3) 
## {
##     {
##         stopifnot(isTRUE(c != 0))
##     }
##     {
##         res &amp;lt;- calc_value(a, b, c)
##         {
##             stopifnot(isTRUE(!is_na(res)))
##         }
##         return(res)
##     }
## }
## &amp;lt;environment: 0x7fa4a5b4d4e8&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;gt; calc_value_checked_args_and_return()
[1] 1

&amp;gt; calc_value_checked_args_and_return(b = NA) # An error should be raised because of an NA return value
Error: isTRUE(!is_na(res)) is not TRUE

&amp;gt; calc_value_checked_args_and_return(c = 0) # An error should be raised because `c` should never be 0
Error: isTRUE(c != 0) is not TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A combination of &lt;code&gt;check_args()&lt;/code&gt; and &lt;code&gt;check_return_value()&lt;/code&gt; means that assertions about the arguments to a function
and the return value from a function can be checked for types, and these checks can be added to the original function to
produce a new function&lt;/li&gt;
&lt;li&gt;These functions aren’t currently pipe-friendly because of the way the &lt;code&gt;fun&lt;/code&gt; argument is used and the way piping with &lt;code&gt;%&amp;gt;%&lt;/code&gt; uses &lt;code&gt;.&lt;/code&gt; for
argument representation. Ideally the functions should work like:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;new_func &amp;lt;- calc_value %&amp;gt;% 
  check_return_value(!is.na(res)) %&amp;gt;% 
  check_args(c != 0)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Body modification part 4: Adding runtime checks to an existing function</title>
      <link>https://coolbutuseless.github.io/2018/03/20/body-modification-part-4-adding-runtime-checks-to-an-existing-function/</link>
      <pubDate>Tue, 20 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/20/body-modification-part-4-adding-runtime-checks-to-an-existing-function/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-can-i-augment-an-existing-function-with-checking-code-for-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Can I augment an existing function with checking code for a function?&lt;/h2&gt;
&lt;p&gt;I’m still experimenting with function body modification, and I’ve downscaled my ambitions and thought about what a type check helper should look like.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/18/body-modification-part-2-automatically-creating-type-checks-for-a-function/&#34;&gt;first attempt&lt;/a&gt; worked, but in a very roundabout fashion and had holes big enough to drive a truck through.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/19/body-modification-part-3-syntax-for-body-modification/function-wrapping/&#34;&gt;previous post&lt;/a&gt; showed that the code to apply a function to another can get very obscure (and unreadable!). Keeping it simple makes it easier to understand and reason about.&lt;/p&gt;
&lt;p&gt;I’ve decided for my purposes, functions-which-modify-functions should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Be very R-like, and avoid introducing new syntax (via infix operators or overloading the assignment operator) just for the sake of it.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;memoise::memoise()&lt;/code&gt; as a reasonable template for how they are called.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why write a function to add checks to another function at all?&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;To learn about functions.&lt;/li&gt;
&lt;li&gt;The original function may be in a package or not easily editable for other reasons.&lt;/li&gt;
&lt;li&gt;You want to avoid manually writing a wrapper that calls the original function, and also avoid having to ensure the function signatures match.&lt;/li&gt;
&lt;li&gt;You want to avoid writing all the boilerplate checks at the top of a function (for clarity)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s really only Point 1 that is motivating me for now.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example-function-to-be-checked&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example function to be checked&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;orig_func &amp;lt;- function(a = 1L, b = 2, c=&amp;#39;hello&amp;#39;, ...) {
  cat(c, a+b, &amp;quot;\n&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;add_checks&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;add_checks()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The function for adding checks to another function is shown below.&lt;/p&gt;
&lt;p&gt;It operates by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;taking a function as its first argument&lt;/li&gt;
&lt;li&gt;all subsequent arguments are interpreted as boolean statements for checking the arguments&lt;/li&gt;
&lt;li&gt;create a code block combining all these tests&lt;/li&gt;
&lt;li&gt;add this code block above the body of the original function&lt;/li&gt;
&lt;li&gt;return the augmented version of the function&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; add checks to an existing function and return a new function
#&amp;#39;
#&amp;#39; @param fun existing function passed in a symbol
#&amp;#39; @param ... list of checks to add in front of function body
#&amp;#39;
#&amp;#39; @return new function (with the same function signature as `fun`) and the same
#&amp;#39;         body as `fun` with a block of tests inserted at the start of the function
#-----------------------------------------------------------------------------
add_checks &amp;lt;- function(fun, ...) {
  
  # Capture all the tests and turn each one into a stopifnot() call
  checks &amp;lt;- rlang::exprs(...)
  for (i in seq(checks)) {
    checks[[i]] &amp;lt;- bquote(stopifnot(isTRUE(.(checks[[i]]))))
  }
  
  # Bind all these checks into a single block
  checks &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, splice(checks))
  
  # Concatentate the test block with the original body
  new_body &amp;lt;- bquote({
    .(checks)
    .(body(fun))
  })
  
  # create and return the new function
  rlang::new_function(args = formals(fun), body = new_body)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following code creates an enhanced version of &lt;code&gt;orig_func()&lt;/code&gt; which tests the following before execution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a is an integer&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b&lt;/code&gt; is non-negative&lt;/li&gt;
&lt;li&gt;No more than 2 non-captured arguments are absorbed into the &lt;code&gt;...&lt;/code&gt; construct&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;new_func &amp;lt;- add_checks(orig_func, is_integer(a), b &amp;gt;= 0,  length(list(...)) &amp;lt; 3)
new_func&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function (a = 1L, b = 2, c = &amp;quot;hello&amp;quot;, ...) 
## {
##     {
##         stopifnot(isTRUE(is_integer(a)))
##         stopifnot(isTRUE(b &amp;gt;= 0))
##         stopifnot(isTRUE(length(list(...)) &amp;lt; 3))
##     }
##     {
##         cat(c, a + b, &amp;quot;\n&amp;quot;)
##     }
## }
## &amp;lt;environment: 0x7f88f5422400&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;new_func()
new_func(a = 1.1)
new_func(b = -1)
new_func(a = 1L, d = 1, e = 1, f=1)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;gt; new_func()
hello 3 

&amp;gt; new_func(a = 1.1)
Error: is_integer(a) is not TRUE

&amp;gt; new_func(b = -1)
Error: b &amp;gt;= 0 is not TRUE

&amp;gt; new_func(a = 1L, d = 1, e = 1, f=1)
Error: length(list(...)) &amp;lt; 3 is not TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This is much less insane than the first attempt at adding checks to an existing function&lt;/li&gt;
&lt;li&gt;Extensions to this idea:
&lt;ul&gt;
&lt;li&gt;Output more informative error messages e.g. include the function name in the stop message.&lt;/li&gt;
&lt;li&gt;Add verification that the result of each test is a single, non-missing, non-NA boolean value.&lt;/li&gt;
&lt;li&gt;Don’t just exit at the first error - instead, display all possible errors before stopping execution.&lt;/li&gt;
&lt;li&gt;Write a similar function to check the return value of a function e.g. &lt;code&gt;add_return_value_check()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Body modification part 3: Syntax for body modification/function wrapping</title>
      <link>https://coolbutuseless.github.io/2018/03/19/body-modification-part-3-syntax-for-body-modification/function-wrapping/</link>
      <pubDate>Mon, 19 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/19/body-modification-part-3-syntax-for-body-modification/function-wrapping/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;The prior experiment on &lt;a href=&#34;https://coolbutuseless.github.io/&#34;&gt;generating automatic runtime tests&lt;/a&gt; and the
&lt;a href=&#34;https://github.com/smbache/ensurer&#34;&gt;&lt;code&gt;ensurer&lt;/code&gt; package&lt;/a&gt; used different methods of trying to wrap the original
function so that it could be augmented with tests. What other ways are possible/sensible?&lt;/p&gt;
&lt;p&gt;Python has solved this problem with &lt;a href=&#34;https://wiki.python.org/moin/PythonDecorators&#34;&gt;decorators&lt;/a&gt; - they’re pretty neat, and look great.&lt;/p&gt;
&lt;p&gt;None of what follows is neat, and all of these are going to be a lot of work for no real benefit other than seeing how they operate!&lt;/p&gt;
&lt;div id=&#34;original-function-and-expected-function-after-modification&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Original function and Expected function after modification&lt;/h2&gt;
&lt;div id=&#34;original-function&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Original Function&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;orig_func &amp;lt;- function() {print(&amp;quot;Goodbye&amp;quot;)}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;expected-function-after-modification&#34; class=&#34;section level3&#34;&gt;
&lt;h3&gt;Expected function after modification&lt;/h3&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;function() {
  { print(&amp;quot;Hello&amp;quot;) }
  { print(&amp;quot;Goodbye&amp;quot;) }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-1-function-which-takes-a-function-and-returns-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea 1: Function which takes a function and returns a function&lt;/h2&gt;
&lt;p&gt;This is the easiest case to write and the easiest to understand. It’s how most(?)
functions which modify another function are called e.g. &lt;code&gt;memoise::memoise()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Helper function to add new content to the start and end of a function.
#-----------------------------------------------------------------------------
add_print &amp;lt;- function(fun, new_prefix={print(&amp;quot;Hello&amp;quot;)}) {
  body(fun) &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, substitute(new_prefix), body(fun))
  fun
}

modify_function &amp;lt;- function(fun) {
  add_print(fun)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;modify_function(orig_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function () 
## {
##     {
##         print(&amp;quot;Hello&amp;quot;)
##     }
##     {
##         print(&amp;quot;Goodbye&amp;quot;)
##     }
## }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-2-two-functions---meta-function-creator-and-an-infix-operator&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea 2: Two functions - meta-function creator and an infix operator&lt;/h2&gt;
&lt;p&gt;This ends up being so convoluted, I wonder why I ever thought of doing it.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;generate an empty function with the right call signature then add the new &lt;code&gt;print()&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;rlang::new_function()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;add the original body to this with a custom infix operator&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Replase the body of the given `fun` with the concatenation of 
# body1 and body2
#-----------------------------------------------------------------------------
`%add_body%` &amp;lt;- function(fun, new_body) {
  body(fun) &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, body(fun), substitute(new_body))
  fun
}


rlang::new_function(args=alist(), body=quote({print(&amp;quot;hello&amp;quot;)})) %add_body% {
  print(&amp;quot;Goodbye&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function () 
## {
##     {
##         print(&amp;quot;hello&amp;quot;)
##     }
##     {
##         print(&amp;quot;Goodbye&amp;quot;)
##     }
## }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-3-function-which-takes-entire-original-function-body-as-an-argument&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea 3: Function which takes entire original function body as an argument&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;ensurer&lt;/code&gt; package does something similar to this - but much more nicely!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;modify_function2 &amp;lt;- function(args, prefix_body=quote({print(&amp;quot;hello&amp;quot;)}), new_body) {
  total_body &amp;lt;- bquote({
    .(prefix_body)
    .(new_body)
  })
  rlang::new_function(args, body=total_body)
}

modify_function2(args=alist(), new_body = quote({print(&amp;quot;Goodbye&amp;quot;)}))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function () 
## {
##     {
##         print(&amp;quot;hello&amp;quot;)
##     }
##     {
##         print(&amp;quot;Goodbye&amp;quot;)
##     }
## }
## &amp;lt;environment: 0x7ffbc5e37338&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-4-overriding-the-assignment-operator-attempt-1&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea 4: Overriding the assignment operator: Attempt 1&lt;/h2&gt;
&lt;p&gt;I thought this would work, but you can’t actually do this if the symbol &lt;code&gt;f&lt;/code&gt; doesn’t
currently exist yet!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;`modify_function3&amp;lt;-` &amp;lt;- function(fun, value) {
  # do something to the fun
}

modify_function3(f) &amp;lt;- orig_func&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;gt; modify_function3(f) &amp;lt;- orig_func
Error in modify_function3(f) &amp;lt;- orig_func : object &amp;#39;f&amp;#39; not found&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;idea-4-overloading-the-assignment-operator-attempt-2---the-pmatchbind-approach&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idea 4: Overloading the assignment operator: Attempt 2 - the &lt;code&gt;pmatch::bind()&lt;/code&gt; approach&lt;/h2&gt;
&lt;p&gt;I borrowed this idea from &lt;a href=&#34;https://twitter.com/thomasmailund&#34;&gt;Thomas Mailund&lt;/a&gt;’s &lt;a href=&#34;https://github.com/mailund/pmatch&#34;&gt;&lt;code&gt;pmatch&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By using the “subset assignment” operator &lt;code&gt;[&amp;lt;-&lt;/code&gt; and a dummy class, we can delay the evaluation of the function name we want to assign to.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;modify_function3 &amp;lt;- structure(NA, class = &amp;quot;modifier&amp;quot;)

`[&amp;lt;-.modifier` &amp;lt;- function(dummy, funcname, value) {
  funcname &amp;lt;- as.character(substitute(funcname)) 
  assign(funcname, add_print(value), pos = .GlobalEnv)  # sorry!
}

modify_function3[new_func3] &amp;lt;- orig_func

new_func3&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## function () 
## {
##     {
##         print(&amp;quot;Hello&amp;quot;)
##     }
##     {
##         print(&amp;quot;Goodbye&amp;quot;)
##     }
## }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I’ve found some really stupid ways to go about doing function modification.&lt;/li&gt;
&lt;li&gt;Nothing is anywhere as neat as a python decorator.&lt;/li&gt;
&lt;li&gt;Keeping it simple seems to be the nicest solution i.e.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;orig_func &amp;lt;- function() { something }
new_func  &amp;lt;- modify_func(orig_func)&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Overloading the assignment operator has possibilities though:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;modified_func[new_func] &amp;lt;- orig_func&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Body modification part 2: Automatically creating type checks for a function</title>
      <link>https://coolbutuseless.github.io/2018/03/18/body-modification-part-2-automatically-creating-type-checks-for-a-function/</link>
      <pubDate>Sun, 18 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/18/body-modification-part-2-automatically-creating-type-checks-for-a-function/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-can-i-automatically-create-type-checking-code-for-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Can I automatically create type checking code for a function?&lt;/h2&gt;
&lt;p&gt;This post is mainly scratching an itch to learn about some function internals. I want to
work out a way to have R generate all the type checks for a given function given some shorter
definition.&lt;/p&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://mypy-lang.org/&#34;&gt;mypy - optional static typing for python&lt;/a&gt; recently popped up on twitter and got me thinking about types in R.&lt;/li&gt;
&lt;li&gt;I know there’s type checking in the &lt;a href=&#34;https://github.com/smbache/ensurer&#34;&gt;ensurer package&lt;/a&gt;, but I wanted to attempt this without
any prior implementation clouding my learning, so I didn’t look at this until after I made something.&lt;/li&gt;
&lt;li&gt;There are numerous packages to help with asserting a value is of a particlar type, but you have to write them all manually which I’m
aiming to avoid.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;design-decisions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Design decisions&lt;/h2&gt;
&lt;p&gt;Basic ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ability to specify single assertions on a variable only (for simplicity).&lt;/li&gt;
&lt;li&gt;Not every argument has to be typed.&lt;/li&gt;
&lt;li&gt;Support default values for an argument e.g. &lt;code&gt;a=1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Need the solution to be incremental to an existing function call.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two user-facing functions needed:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;&lt;code&gt;typed_function&lt;/code&gt;: A function to take an augmented argument list and create a function which tests the arguments according to that specification&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%+body%&lt;/code&gt;: A function to merge the checking function into the beginning of the users function&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;type-specification&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Type specification&lt;/h2&gt;
&lt;p&gt;Since I’m keeping this simple, type checking is specified by naming a boolean function to check the argument, and it will dangle off the
end of a current argument in the function definition. Some examples:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a = 1L ~ is_integer)
f &amp;lt;- function(name ~ is_character)
f &amp;lt;- function(a = 1L ~ is_integer, b = 2, c = 3 ~ is_double)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make things easier, I’m going to rely on &lt;code&gt;rlang&lt;/code&gt;’s suite of testing functions e.g. &lt;code&gt;is_integer&lt;/code&gt;, &lt;code&gt;is_character&lt;/code&gt; etc&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;result&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Result&lt;/h2&gt;
&lt;p&gt;The code is included at the end of this post in an appendix. Warning: it’s not pretty.&lt;/p&gt;
&lt;p&gt;To create a typed function, the syntax is:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- typed_function(argument list) %+body% { body of function }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A simple example - the original function definition:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function(a = 1L, b, c=&amp;#39;cool&amp;#39;) {
  cat(c, a+b, &amp;quot;\n&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Augment the function definition to include type checking&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- typed_function(a = 1L ~ is_integer, b ~ is_integer, c = &amp;#39;cool&amp;#39; ~ is_character) %+body% {
  cat(c, a+b, &amp;quot;\n&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting function has a section of checks added to the beginning&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;function (a = 1L, b, c = &amp;quot;cool&amp;quot;) 
{
    {
        stopifnot(!is_missing(a))
        stopifnot(is_integer(a))
        stopifnot(!is_missing(b))
        stopifnot(is_integer(b))
        stopifnot(!is_missing(c))
        stopifnot(is_character(c))
    }
    {
        cat(c, a + b, &amp;quot;\n&amp;quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resulting function in action, and throwing errors all over the place when the types don’t match&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f()
f(b = 1)
f(b = 2L)
f(b = 2L, c = 3)
f(b = 2L, c = &amp;#39;rstats&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;&amp;gt; f()
Error: !is_missing(b) is not TRUE
&amp;gt; f(b = 1)
Error: is_integer(b) is not TRUE
&amp;gt; f(b = 2L)
cool 3 
&amp;gt; f(b = 2L, c = 3)
Error: is_character(c) is not TRUE
&amp;gt; f(b = 2L, c = &amp;#39;rstats&amp;#39;)
rstats 3 &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It works!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;comparison-to-ensurer&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Comparison to &lt;code&gt;ensurer&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;After hacking together my idea, I looked at the &lt;a href=&#34;https://github.com/smbache/ensurer&#34;&gt;ensurer package&lt;/a&gt;
which also offers the (experimental)
ability to create type safe functions. You’ll need to install from github for this
functionality.&lt;/p&gt;
&lt;p&gt;An example of an &lt;code&gt;ensurer&lt;/code&gt; call to create a function with type checking&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;f &amp;lt;- function_(a ~ integer, b ~ character: &amp;quot;Hello, World!&amp;quot;, {
  rep(b, a)
})&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;function (a, b = &amp;quot;Hello, World!&amp;quot;) 
{
    type_integer(a)
    type_character(b)
    {
        rep(b, a)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Comparison:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I like the use of &lt;code&gt;function_()&lt;/code&gt; as the name.&lt;/li&gt;
&lt;li&gt;It might seem confusing putting the actual body inside the function call? Maybe. I don’t think there’s a
good solution. I don’t think my use of &lt;code&gt;%+body%&lt;/code&gt; is any clearer.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ensurer&lt;/code&gt; goes to the trouble of defining its own type checking primitives, whereas I rely on &lt;code&gt;rlang&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;I prefer that my specification keeps the layout for defining an argument and puts the type checking stuff after the regular stuff i.e.
I think &lt;code&gt;a = 1 ~ is_double&lt;/code&gt; is slightly clearer than &lt;code&gt;a ~ double : 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It sort of works, but I don’t think this idea is worth pursuing. The cure seems worse than the disease.&lt;/li&gt;
&lt;li&gt;I learnt quite a bit about functions.&lt;/li&gt;
&lt;li&gt;Possible extensions:
&lt;ul&gt;
&lt;li&gt;support other types - at the moment can only really process basic numeric/integers/characters because of the way
the &lt;code&gt;alist()&lt;/code&gt; is constructed&lt;/li&gt;
&lt;li&gt;add a way to type check the return value of a function&lt;/li&gt;
&lt;li&gt;support the &lt;code&gt;...&lt;/code&gt; argument&lt;/li&gt;
&lt;li&gt;support multiple checks for each variable e.g. &lt;code&gt;a = 1 ~ is_double &amp;amp; is_non_zero&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix---the-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix - the code&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Unpack a list element containing type information about an argument
#&amp;#39;
#&amp;#39; @param l an argument to `typed_function` e.g `a = 1 ~ is_integer`
#&amp;#39;
#&amp;#39; @return a single element list containing a list containing the name, value and boolean test function
#-----------------------------------------------------------------------------
unpack_arg &amp;lt;- function(l) {
  stopifnot(length(l) == 1)
  has_outer_name &amp;lt;- !is.null(names(l)) &amp;amp;&amp;amp; names(l) != &amp;#39;&amp;#39;
  raw_value      &amp;lt;- l[[1]]
  has_type       &amp;lt;- is.call(raw_value) &amp;amp;&amp;amp; raw_value[[1]] == &amp;#39;~&amp;#39;
  if (has_outer_name &amp;amp;&amp;amp; has_type) {
    name  &amp;lt;- names(l)
    value &amp;lt;- raw_value[[2]]
    type  &amp;lt;- raw_value[[3]]
  } else if (has_outer_name &amp;amp;&amp;amp; !has_type) {
    name  &amp;lt;- names(l)
    value &amp;lt;- raw_value
    type  &amp;lt;- NULL
  } else if (!has_outer_name &amp;amp;&amp;amp; has_type) {
    name  &amp;lt;- as.character(raw_value[[2]])
    value &amp;lt;- &amp;quot;..NULL..&amp;quot;
    type  &amp;lt;- raw_value[[3]]
  } else if (!has_outer_name &amp;amp;&amp;amp; !has_type) {
    name  &amp;lt;- as.character(raw_value)
    value &amp;lt;- &amp;quot;..NULL..&amp;quot;
    type  &amp;lt;- NULL
  } else {
    stop(&amp;quot;Shouldn&amp;#39;t happen&amp;quot;)
  }

  list(
    list(
      name  = name,
      value = value,
      type  = type
    )
  )
}


#-----------------------------------------------------------------------------
#&amp;#39; Create a character representation of an argument to `alist()` for a single argument
#&amp;#39;
#&amp;#39;
#&amp;#39; @param unpacked_arg a list containing the name, value and boolean test function
#&amp;#39;
#&amp;#39; @return A text representation of an argument to pass to `alist()`
#-----------------------------------------------------------------------------
create_alist_argument &amp;lt;- function(unpacked_arg) {
  if (identical(unpacked_arg$value, &amp;quot;..NULL..&amp;quot;)) {
    paste0(unpacked_arg$name, &amp;#39;=&amp;#39;)
  } else {
    if (is.integer(unpacked_arg$value)) {
      paste0(unpacked_arg$name, &amp;#39;=&amp;#39;, unpacked_arg$value, &amp;#39;L&amp;#39;)
    } else if (is.character(unpacked_arg$value)) {
      paste0(unpacked_arg$name, &amp;#39;= &amp;quot;&amp;#39;, unpacked_arg$value, &amp;#39;&amp;quot;&amp;#39;)
    } else {
      paste0(unpacked_arg$name, &amp;#39;=&amp;#39;, unpacked_arg$value)
    }
  }
}


#-----------------------------------------------------------------------------
#&amp;#39; Create a list of formals for a function.
#&amp;#39;
#&amp;#39; This is a wrapper around the `alist()` command
#&amp;#39;
#&amp;#39; @param unpacked_args a list of argument info, containing one list for each
#&amp;#39;                      argument consisting of a list containing the name, value and boolean test function
#&amp;#39;
#&amp;#39; @return A set of formal arguments created by `alist()`
#-----------------------------------------------------------------------------
create_formals &amp;lt;- function(unpacked_args) {
  alist_args    &amp;lt;- unpacked_args %&amp;gt;% map_chr(create_alist_argument)
  alist_command &amp;lt;- sprintf(&amp;quot;alist(%s)&amp;quot;, paste(alist_args, collapse=&amp;quot;, &amp;quot;))
  eval(parse(text = alist_command))
}






#-----------------------------------------------------------------------------
#&amp;#39; Create a type assertion for the given `typed_arg`
#&amp;#39;
#&amp;#39; @param typed_arg a list containing the name, value and boolean function to test argument
#&amp;#39;
#&amp;#39; @return code to test whether the argument passes the given boolean function
#-----------------------------------------------------------------------------
create_type_assertion &amp;lt;- function(typed_arg) {
  func_name &amp;lt;- as.character(typed_arg$type)
  if (!exists(func_name)) {
    stop(&amp;quot;Check function not found: &amp;quot;, func_name)
  }

  func_sym &amp;lt;- as.name(func_name)
  arg_sym  &amp;lt;- as.name(typed_arg$name)

  bquote({
    stopifnot(!is_missing(.(arg_sym)))
    stopifnot(.(func_sym)(.(arg_sym)))
  })
}




#-----------------------------------------------------------------------------
#&amp;#39; Create a function consisting of checks based upon the arguments
#&amp;#39;
#&amp;#39; @param ... named arguments of the form:
#&amp;#39;   -    a
#&amp;#39;   -    a = [default value]
#&amp;#39;   -    a                   ~ [boolean func]
#&amp;#39;   -    a = [default value] ~ [boolean func]
#&amp;#39;
#&amp;#39; Boolean functions are best taken from `rlang` e.g. `rlang::is_integer`
#&amp;#39;
#&amp;#39; e.g.   typed_function(a = 1 ~ is_double, b ~ is_list)
#&amp;#39;
#&amp;#39; @return a function with the formal arguments used to call `typed_function`
#&amp;#39;         whose body only contains functions for checking those arguments
#&amp;#39;         against the specified boolean functions
#-----------------------------------------------------------------------------
typed_function &amp;lt;- function(...) {

  # Use the ... arguments to create a list of information
  # about each argument i.e. name, type,
  ll            &amp;lt;- exprs(...)
  arg_infos     &amp;lt;- ll %&amp;gt;% purrr::lmap(unpack_arg)
  args          &amp;lt;- create_formals(arg_infos)

  # Create a list of commands to check each of the arguments that
  # has type information
  body_calls &amp;lt;- arg_infos %&amp;gt;%
    discard(~is.null(.x$type)) %&amp;gt;%
    map(create_type_assertion) %&amp;gt;%
    map(rlang::call_args) %&amp;gt;%
    flatten()

  # Create the checking function and give it a body and formal arguments
  check_func          &amp;lt;- function() {}
  body(check_func)    &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, splice(body_calls))
  formals(check_func) &amp;lt;- args

  check_func
}



#-----------------------------------------------------------------------------
#&amp;#39; Append body contents to an existing function
#&amp;#39;
#&amp;#39; @param fun a function
#&amp;#39; @param new_body new content to be appended to existing body
#-----------------------------------------------------------------------------
`%+body%` &amp;lt;- function(fun, this_body) {
  body(fun) &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, body(fun), substitute(this_body))
  fun
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Body modification: Injecting new content into a function</title>
      <link>https://coolbutuseless.github.io/2018/03/16/body-modification-injecting-new-content-into-a-function/</link>
      <pubDate>Fri, 16 Mar 2018 06:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/16/body-modification-injecting-new-content-into-a-function/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-can-the-contents-of-2-functions-be-merged-into-a-single-function-using-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: Can the contents of 2 functions be merged into a single function using R?&lt;/h2&gt;
&lt;p&gt;A function consists of 3 things:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;formal arguments&lt;/li&gt;
&lt;li&gt;body&lt;/li&gt;
&lt;li&gt;environment&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The body of a function can be&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fetched using &lt;code&gt;body()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;set using &lt;code&gt;body&amp;lt;-()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these functions for manipulating bodies, can the contents of two functions be merged into a single function using R?&lt;br /&gt;
And can the resulting function’s body look neat?&lt;/p&gt;
&lt;p&gt;Edit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2018-03-18&lt;/strong&gt; The use of &lt;code&gt;[[-1]]&lt;/code&gt; to remove the call to &lt;code&gt;{&lt;/code&gt; from the function bodies wasn’t really a general solution. Besides being hard to interpret, it failed when the function body was more complex than a single command. Switched to using &lt;code&gt;rlang::call_args()&lt;/code&gt; instead. Thanks to &lt;a href=&#34;http://twitter.com/hadleywickham&#34;&gt;hadley&lt;/a&gt; for pointing out the problem here.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2018-03-18&lt;/strong&gt; When constructing a call using &lt;code&gt;as.call()&lt;/code&gt;, the first item in the list argument is a function. This may be specified as either the actual function, or the name/symbol for that function. It turns out that using the symbol for &lt;code&gt;{&lt;/code&gt; rather than &lt;code&gt;get(&#39;{&#39;)&lt;/code&gt; results in a tidier representation. Thanks to &lt;a href=&#34;http://twitter.com/hadleywickham&#34;&gt;hadley&lt;/a&gt; for pointing out the problem here.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;my-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My Functions&lt;/h2&gt;
&lt;p&gt;The goal is to merge the following 2 functions, &lt;code&gt;s()&lt;/code&gt; and &lt;code&gt;t()&lt;/code&gt; into a single function called &lt;code&gt;newf()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;s &amp;lt;- function() {print(&amp;quot;hello&amp;quot;)}
t &amp;lt;- function() {
  print(&amp;quot;there&amp;quot;)
  print(&amp;quot;#rstats&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expected body of the combined function after the above 2 functions are merged:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf &amp;lt;- function() 
{
  print(&amp;quot;hello&amp;quot;)
  print(&amp;quot;there&amp;quot;)
  print(&amp;quot;#rstats&amp;quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;body-hacking-1-basic-way-to-set-a-new-body&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Body hacking 1: Basic way to set a new body&lt;/h2&gt;
&lt;p&gt;With the &lt;code&gt;body&amp;lt;-()&lt;/code&gt; function, you can insert the body/content of a function after it’s been created.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf       &amp;lt;- function() {}
body(newf) &amp;lt;- quote(print(&amp;quot;hello&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;newf &amp;lt;- function () 
print(&amp;quot;hello&amp;quot;) &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;body-hacking-2-merge-the-2-function-bodies-together&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Body hacking 2: Merge the 2 function bodies together&lt;/h2&gt;
&lt;p&gt;Merge the 2 bodies into a single &lt;code&gt;call&lt;/code&gt; to &lt;code&gt;{&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf       &amp;lt;- function() {}
body(newf) &amp;lt;- as.call(list(get(&amp;#39;{&amp;#39;), body(s), body(t)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;newf &amp;lt;- function () 
.Primitive(&amp;quot;{&amp;quot;)({
    print(&amp;quot;hello&amp;quot;)
}, {
    print(&amp;quot;there&amp;quot;)
    print(&amp;quot;#rstats&amp;quot;)
}) &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;newf()&lt;/code&gt; function looks a bit ugly, but it works!&lt;/p&gt;
&lt;p&gt;This looks much better if I build the &lt;code&gt;as.call&lt;/code&gt; with the function defined by the &lt;em&gt;symbol&lt;/em&gt; for &lt;code&gt;{&lt;/code&gt; rather than
pulling in the actual function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf       &amp;lt;- function() {}
body(newf) &amp;lt;- as.call(list(as.name(&amp;#39;{&amp;#39;), body(s), body(t)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;newf &amp;lt;- function () 
{
    {
        print(&amp;quot;hello&amp;quot;)
    }
    {
        print(&amp;quot;there&amp;quot;)
        print(&amp;quot;#rstats&amp;quot;)
    }
} &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;body-hacking-3---use-rlang&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Body hacking 3 - use &lt;code&gt;rlang&lt;/code&gt;!&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;rlang::call2&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf        &amp;lt;- function() {}
body(newf) &amp;lt;- rlang::call2(&amp;#39;{&amp;#39;, body(s), body(t))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;newf &amp;lt;- function () 
{
    {
        print(&amp;quot;hello&amp;quot;)
    }
    {
        print(&amp;quot;there&amp;quot;)
        print(&amp;quot;#rstats&amp;quot;)
    }
} &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This construction is a little simpler to read.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;body-hacking-4-use-rlangcall_args&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Body hacking 4: use &lt;code&gt;rlang::call_args&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Strip the outer &lt;code&gt;{&lt;/code&gt; call from each body before merging into a new call. Do this
using &lt;code&gt;rlang::call_args()&lt;/code&gt; to just retain the arguments to the outer &lt;code&gt;{&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;newf       &amp;lt;- function() {}
body(newf) &amp;lt;- as.call(c(
  list(as.name(&amp;#39;{&amp;#39;)), 
  rlang::call_args(body(s)), 
  rlang::call_args(body(t))
))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;newf &amp;lt;- function () 
{
    print(&amp;quot;hello&amp;quot;)
    print(&amp;quot;there&amp;quot;)
    print(&amp;quot;#rstats&amp;quot;)
} &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Yes, you can edit the content of functions.&lt;/li&gt;
&lt;li&gt;Yes, you can merge the contents of 2 functions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Base R split has issues - Part 3 more idiosyncrasies</title>
      <link>https://coolbutuseless.github.io/2018/03/15/base-r-split-has-issues-part-3-more-idiosyncrasies/</link>
      <pubDate>Thu, 15 Mar 2018 06:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/15/base-r-split-has-issues-part-3-more-idiosyncrasies/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;base-r-split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R &lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;My prior post on &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;tidyverse split-apply-combined&lt;/a&gt; ended with me favouring &lt;code&gt;split + map_dfr&lt;/code&gt; as a replacement for &lt;code&gt;group_by + do&lt;/code&gt;. In prior posts I saw:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of splitting variables - (see &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues---part-1-runtime/&#34;&gt;post&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of groups within each variable - (see &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues---part-1-runtime/&#34;&gt;post&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;split()&lt;/code&gt; recycles splitting variables and silent dropping of all &lt;code&gt;NA&lt;/code&gt; levels (see &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues---part-2-idiosyncrasies/&#34;&gt;post&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the process of working on my &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/07/chop-a-tidyverse-style-split/&#34;&gt;pull request for &lt;code&gt;chop()&lt;/code&gt;&lt;/a&gt; I found I had even more issues with &lt;code&gt;split()&lt;/code&gt;. These are pretty minor, but still (imo) weird.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;order-of-split-output-seems-wrong&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Order of &lt;code&gt;split()&lt;/code&gt; output seems &lt;em&gt;wrong&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;split()&lt;/code&gt; creates groups by cycling through the values of the first variable first, then the second variable, and so on.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;names(split(mtcars, list(mtcars$cyl, mtcars$am)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;4.0&amp;quot; &amp;quot;6.0&amp;quot; &amp;quot;8.0&amp;quot; &amp;quot;4.1&amp;quot; &amp;quot;6.1&amp;quot; &amp;quot;8.1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, I would have expected the first variable to be considered somehow the “most important” (most significant bit?) and
for it to cycle the slowest/least, i.e.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;4.0&amp;quot; &amp;quot;4.1&amp;quot; &amp;quot;6.0&amp;quot; &amp;quot;6.1&amp;quot; &amp;quot;8.0&amp;quot; &amp;quot;8.1&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also expected &lt;code&gt;nest()&lt;/code&gt; to order the groups logically, but it seems it produces the nested data.frame in the order in which the variables appear in the original data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  group_by(cyl, am) %&amp;gt;% 
  nest()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 3
## # Groups:   cyl, am [6]
##     cyl    am           data
##   &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;list&amp;lt;df[,9]&amp;gt;&amp;gt;
## 1     6     1        [3 × 9]
## 2     4     1        [8 × 9]
## 3     6     0        [4 × 9]
## 4     8     0       [12 × 9]
## 5     4     0        [3 × 9]
## 6     8     1        [2 × 9]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is this unordered output a conscious decision for &lt;code&gt;nest()&lt;/code&gt;? Or was it a lazy decision to just not bother reorganising the output? Does anyone &lt;em&gt;require&lt;/em&gt; the groups to be in the originally presented order?&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;split-can-do-na-levels-with-a-bit-of-work&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;split()&lt;/code&gt; &lt;em&gt;can&lt;/em&gt; do NA levels (with a bit of work)&lt;/h2&gt;
&lt;p&gt;If a splitting factor has any &lt;code&gt;NA&lt;/code&gt; values, &lt;code&gt;split()&lt;/code&gt; will usually just silently ignore these values.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- data_frame(x=factor(c(1, 2, NA)), y=letters[1:3], z=101:103)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: `data_frame()` is deprecated, use `tibble()`.
## This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 3 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 1     a       101
## 2 2     b       102
## 3 &amp;lt;NA&amp;gt;  c       103&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;split(test_df, test_df$x)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
## # A tibble: 1 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 1     a       101
## 
## $`2`
## # A tibble: 1 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 2     b       102&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if you go to the effort to not exclude &lt;code&gt;NA&lt;/code&gt; values from the factor levels, then &lt;code&gt;split()&lt;/code&gt; will keep all levels in the output!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- data_frame(x=factor(c(1, 2, NA), exclude = c()), y=letters[1:3], z=101:103)
split(test_df, test_df$x)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
## # A tibble: 1 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 1     a       101
## 
## $`2`
## # A tibble: 1 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 2     b       102
## 
## $&amp;lt;NA&amp;gt;
## # A tibble: 1 x 3
##   x     y         z
##   &amp;lt;fct&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1 &amp;lt;NA&amp;gt;  c       103&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was surprised to find out that rather than generating a character string “NA” for the name of the list element, &lt;code&gt;split()&lt;/code&gt; has actually given me a real &lt;code&gt;NA&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;is.na(names(split(test_df, test_df$x)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] FALSE FALSE  TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if you split on 2 variables, only 1 of which has a factor &lt;code&gt;NA&lt;/code&gt; level, then it will not create any NA labels. So in the case of a single variable with an NA level, you get an actual &lt;code&gt;NA&lt;/code&gt; as a list label, but for mutiple variables, the NA is converted to character.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;names(split(test_df, list(test_df$x, test_df$y)))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;1.a&amp;quot;  &amp;quot;2.a&amp;quot;  &amp;quot;NA.a&amp;quot; &amp;quot;1.b&amp;quot;  &amp;quot;2.b&amp;quot;  &amp;quot;NA.b&amp;quot; &amp;quot;1.c&amp;quot;  &amp;quot;2.c&amp;quot;  &amp;quot;NA.c&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Today I learned you can have an actual &lt;code&gt;NA&lt;/code&gt; value as the name of a list or data.frame column.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>geom_cat()</title>
      <link>https://coolbutuseless.github.io/2018/03/08/geom_cat/</link>
      <pubDate>Thu, 08 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/08/geom_cat/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Some test plots in order to get borders and font-sizes correct for large (A0) plan printing from &lt;code&gt;ggplot&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is printed on &lt;a href=&#34;http://www.dupont.com/products-and-services/fabrics-fibers-nonwovens/protective-fabrics/brands/tyvek.html&#34;&gt;tyvek&lt;/a&gt; which
is made of woven &lt;a href=&#34;https://en.wikipedia.org/wiki/High-density_polyethylene&#34;&gt;HDPE&lt;/a&gt; - it’s untearable, machine washable, and totally kicks arse.&lt;/p&gt;
&lt;div id=&#34;geom_cat-theme_bw&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_cat() + theme_bw()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/geom-cat/geom-cat-theme-bw.jpg&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;geom_cat-scale_x_continuousexpandcarpet&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;geom_cat() + scale_x_continuous(expand=&#39;carpet&#39;)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/geom-cat/geom-cat-expand.jpg&#34;&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>`chop()`: A tidyverse-style `split()`</title>
      <link>https://coolbutuseless.github.io/2018/03/07/chop-a-tidyverse-style-split/</link>
      <pubDate>Wed, 07 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/07/chop-a-tidyverse-style-split/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;tidyverse-split-the-journey-to-the-pull-request&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;tidyverse &lt;code&gt;split()&lt;/code&gt;: The journey to the pull request&lt;/h2&gt;
&lt;p&gt;Last week &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;I searched for a replacement for &lt;code&gt;group_by + do&lt;/code&gt;&lt;/a&gt;,
and this ended with &lt;code&gt;split + map_dfr&lt;/code&gt; being my favourite alternative. Conceptually it was the most compact representation of the idea (just 2 commands) and avoided
a the extra work that seemed necessary to nest a data.frame and operate on the nested data.&lt;/p&gt;
&lt;p&gt;I then looked more closely at the &lt;code&gt;split()&lt;/code&gt; function, in particular
&lt;a href=&#34;&#34;&gt;the runtime characteristics&lt;/a&gt; and
&lt;a href=&#34;&#34;&gt;its idioscrasies&lt;/a&gt; and noted that in the Base R &lt;code&gt;split()&lt;/code&gt; function:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;runtime is quadratic in number of splitting variables - &lt;strong&gt;something nobody ever wants&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;runtime is quadratic in number of groups within each variable - &lt;strong&gt;something nobody ever wants&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;the splitting variable gets recycled if it’s not as long as the data.frame being split - &lt;strong&gt;something nobody ever wants&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;values corresponding to NA values of the split variable are completely dropped from the data - &lt;strong&gt;something nobody ever wants&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After seeing these problems, I sketched out a tidyverse version of &lt;code&gt;split()&lt;/code&gt;, which I called &lt;code&gt;cleave_by&lt;/code&gt;, and &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/04/cleave_by-a-tidyverse-style-split/&#34;&gt;wrote a post about how it solved some of &lt;code&gt;split()&#39;s&lt;/code&gt; issues&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;http://www.twitter.com/hadleywickham&#34;&gt;hadleywickham&lt;/a&gt; suggested that I submit the code to the &lt;code&gt;tidyr&lt;/code&gt; package. So I tidied the code, and renamed the function to &lt;code&gt;chop()&lt;/code&gt; and &lt;a href=&#34;https://github.com/tidyverse/tidyr/pull/434&#34;&gt;opened a pull request&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The rest of this post briefly shows how &lt;code&gt;chop() + map_dfr()&lt;/code&gt; is a workable replacement for &lt;code&gt;group_by() + do()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;cleave_by-tidied-up-chop&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cleave_by()&lt;/code&gt; tidied up =&amp;gt; &lt;code&gt;chop()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://www.twitter.com/gshotwell&#34;&gt;gshotwell&lt;/a&gt; suggested that &lt;code&gt;cleave_by()&lt;/code&gt; ought to
respect any groupings on the data.frame and
&lt;a href=&#34;http://www.twitter.com/hadleywickham&#34;&gt;hadleywickham&lt;/a&gt; suggested that the behaviour should
probably be similar to &lt;code&gt;tidyr::nest()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With that in mind, I rewrote &lt;code&gt;cleave_by()&lt;/code&gt; to be more &lt;code&gt;nest()&lt;/code&gt;-like, and renamed it to &lt;code&gt;chop()&lt;/code&gt; (as no-one really liked the verb &lt;code&gt;cleave&lt;/code&gt;
and I wasn’t attached to it either).&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(rlang)

chop &amp;lt;- function(data, ...) {

  chop_vars &amp;lt;- unname(tidyselect::vars_select(names(data), ...))

  # Only use group vars if no chop vars specified
  if (is_empty(chop_vars)) {
    chop_vars &amp;lt;- dplyr::group_vars(data)
  }

  data &amp;lt;- dplyr::ungroup(data)   # Same as nest() - chopped data frames are ungrouped.
  data &amp;lt;- dplyr::as_tibble(data) # Ensure we consistently return a list of tibbles

  if (is_empty(chop_vars) || nrow(data) == 0) {
    return(list(data))
  }

  idx &amp;lt;- dplyr::group_indices(data, !!! syms(chop_vars))

  unname(split(data, idx))
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;using-chop-map_dfr-to-replace-group_by-do&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Using &lt;code&gt;chop() + map_dfr()&lt;/code&gt; to replace &lt;code&gt;group_by() + do()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In the following (very simplified!) application of &lt;strong&gt;split-apply-combine&lt;/strong&gt;, I show how &lt;code&gt;group_by() + do()&lt;/code&gt; and
&lt;code&gt;chop() + map_dfr()&lt;/code&gt; can be used
to apply &lt;code&gt;complex_func()&lt;/code&gt; to &lt;code&gt;mtcars&lt;/code&gt; subsetted into groups by the value of &lt;code&gt;cyl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;chop() + map_dfr()&lt;/code&gt; turns out to be a tiny bit simpler than &lt;code&gt;group_by() + do()&lt;/code&gt; as there is no need for the final ungrouping (which can be disasterous if you ever forget to do it!)&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  select(mpg, cyl, disp) %&amp;gt;%
  group_by(cyl) %&amp;gt;%
  do(complex_func(.)) %&amp;gt;%
  ungroup()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 32 x 4
##      mpg   cyl  disp new_value        
##    &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;            
##  1  22.8     4 108   cyl plus one is 5
##  2  24.4     4 147.  cyl plus one is 5
##  3  22.8     4 141.  cyl plus one is 5
##  4  32.4     4  78.7 cyl plus one is 5
##  5  30.4     4  75.7 cyl plus one is 5
##  6  33.9     4  71.1 cyl plus one is 5
##  7  21.5     4 120.  cyl plus one is 5
##  8  27.3     4  79   cyl plus one is 5
##  9  26       4 120.  cyl plus one is 5
## 10  30.4     4  95.1 cyl plus one is 5
## # … with 22 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;%
  select(mpg, cyl, disp) %&amp;gt;%
  chop(cyl) %&amp;gt;%
  map_dfr(complex_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 32 x 4
##      mpg   cyl  disp new_value        
##    &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;            
##  1  22.8     4 108   cyl plus one is 5
##  2  24.4     4 147.  cyl plus one is 5
##  3  22.8     4 141.  cyl plus one is 5
##  4  32.4     4  78.7 cyl plus one is 5
##  5  30.4     4  75.7 cyl plus one is 5
##  6  33.9     4  71.1 cyl plus one is 5
##  7  21.5     4 120.  cyl plus one is 5
##  8  27.3     4  79   cyl plus one is 5
##  9  26       4 120.  cyl plus one is 5
## 10  30.4     4  95.1 cyl plus one is 5
## # … with 22 more rows&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A case for a tidyverse &lt;code&gt;split()&lt;/code&gt; has been made.&lt;/li&gt;
&lt;li&gt;The code has been written.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&#34;https://github.com/tidyverse/tidyr/pull/434&#34;&gt;pull request&lt;/a&gt; has been opened.&lt;/li&gt;
&lt;li&gt;Now I wait…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>`cleave_by()`: A tidyverse-style `split()`</title>
      <link>https://coolbutuseless.github.io/2018/03/04/cleave_by-a-tidyverse-style-split/</link>
      <pubDate>Sun, 04 Mar 2018 17:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/04/cleave_by-a-tidyverse-style-split/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;my-issues-with-split-in-base-r&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;My issues with &lt;code&gt;split()&lt;/code&gt; in base R&lt;/h2&gt;
&lt;p&gt;My prior post on &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;tidyverse split-apply-combined&lt;/a&gt; ended with me favouring &lt;code&gt;split + map_dfr&lt;/code&gt; as a replacement for &lt;code&gt;group_by + do&lt;/code&gt;.&lt;br /&gt;
In subsequent posts I looked at
&lt;a href=&#34;&#34;&gt;the runtime of the split function&lt;/a&gt; and
&lt;a href=&#34;&#34;&gt;the idioscrasies of the split function&lt;/a&gt; and saw the following for the Base R &lt;code&gt;split()&lt;/code&gt; function:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;runtime is quadratic in number of splitting variables&lt;/li&gt;
&lt;li&gt;runtime is quadratic in number of groups within each variable&lt;/li&gt;
&lt;li&gt;the splitting variable gets recycled if it’s not as long as the data.frame being split&lt;/li&gt;
&lt;li&gt;NA levels are dropped from the data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Points [1] and [2] mean that &lt;code&gt;split()&lt;/code&gt; really slows down as soon as your data grouping becomes moderately complex.&lt;/p&gt;
&lt;p&gt;Point [3] means that it’s easy to shoot yourself in the foot and split the data incorrectly.&lt;/p&gt;
&lt;p&gt;Point [4] means that &lt;code&gt;split()&lt;/code&gt; will just throw away data that happens to have a level value of &lt;code&gt;NA&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-is-there-no-split-function-in-the-tidyverse&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why is there no &lt;code&gt;split&lt;/code&gt; function in the tidyverse?&lt;/h2&gt;
&lt;p&gt;According to &lt;a href=&#34;https://github.com/tidyverse/purrr/issues/274&#34;&gt;Hadley on github&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A function that acts rowwise on a data frame doesn’t seem like it should live in purrr.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div id=&#34;cleave_by---a-tidyverse-style-version-ofsplit&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cleave_by()&lt;/code&gt; - a tidyverse-style version of&lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This is an experiment to create a tidyverse-split &lt;code&gt;split()&lt;/code&gt; which
avoids the problems listed above. If possible (and with as little work as possible) I want a tidyverse-style split function which&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;keeps runtimes linear in the number of variables&lt;/li&gt;
&lt;li&gt;keeps runtimes linear with respect to the number of groups within each variable.&lt;/li&gt;
&lt;li&gt;avoids the recyling of any splitting variable&lt;/li&gt;
&lt;li&gt;keeps NA levels&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Since I am simply writing a wrapper around the base &lt;code&gt;split()&lt;/code&gt; function, I’m never going to be faster than it for simple grouping examples. This is
because I’m always doing more work upfront which is not necessary for a small number of grouping variables, and only pays off once the number of groups/levels gets
bigger.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; tidy version of the base `split()` function
#&amp;#39;
#&amp;#39; @param df data.frame to split
#&amp;#39; @param ... unquoted column names from the &amp;#39;df&amp;#39; data.frame to specify 
#&amp;#39;            the splitting groups
#&amp;#39;
#&amp;#39; @return list of data.frames, one for each group
#-----------------------------------------------------------------------------
cleave_by &amp;lt;- function(df, ...) {
  stopifnot(inherits(df, &amp;quot;data.frame&amp;quot;))
  
  # use tidyeval to get the names ready for dplyr
  grouping &amp;lt;- quos(...)
  
  # Calculate a single number to represent each group
  group_index &amp;lt;- df %&amp;gt;%
    group_by(!!!grouping) %&amp;gt;%
    group_indices()
  
  # do the split by this single group_index variable and return it
  split(df, group_index)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;mtcars %&amp;gt;% cleave_by(am, vs)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## 
## $`2`
##                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230       22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280       19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C      17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## 
## $`3`
##                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Ford Pantera L 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino   19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora  15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## 
## $`4`
##                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Volvo 142E     21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;cleave_by-keeps-na-levels&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cleave_by()&lt;/code&gt; keeps NA levels&lt;/h2&gt;
&lt;p&gt;Creating the groups within &lt;code&gt;cleave_by()&lt;/code&gt; uses &lt;code&gt;dplyr::group_by&lt;/code&gt; + &lt;code&gt;group_indices&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As both of these functions are aware of (and retain) NA values, using them to create the group labels
means that we keep NA levels within a splitting variable.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- data_frame(a=c(1, 1, 1, 2, 2, 3, NA, NA), b=1:8)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: `data_frame()` is deprecated, use `tibble()`.
## This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df %&amp;gt;%
  cleave_by(a)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
## # A tibble: 3 x 2
##       a     b
##   &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
## 1     1     1
## 2     1     2
## 3     1     3
## 
## $`2`
## # A tibble: 2 x 2
##       a     b
##   &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
## 1     2     4
## 2     2     5
## 
## $`3`
## # A tibble: 1 x 2
##       a     b
##   &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
## 1     3     6
## 
## $`4`
## # A tibble: 2 x 2
##       a     b
##   &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;
## 1    NA     7
## 2    NA     8&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;cleave_by-avoids-factor-recycling&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;cleave_by()&lt;/code&gt; avoids factor recycling&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;split()&lt;/code&gt; allows the user to pass in any splitting variable, and in cases where there is a
length mismatch with the number of rows in the original data.frame, it will recycle the values.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;cleave_by()&lt;/code&gt;, because we’re using column names of the data.frame to specify the splitting variable, it is
always guaranteed to be the same length as the data.frame itself.&lt;/p&gt;
&lt;p&gt;Thus, any recycling of the splitting variable is completely avoided.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;compare-runtimes-for-increasing-number-of-splitting-variables.-cleave_by-vs-split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compare runtimes for increasing number of splitting variables. &lt;code&gt;cleave_by()&lt;/code&gt; vs &lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As seen in the graph below, &lt;code&gt;cleave_by()&lt;/code&gt; runtimes appear linear with respect to the number of splitting variables, however it does start at a higher baseline time than &lt;code&gt;split()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- create_test_df(cols=10, rows=10, levels_per_var=2)  # See appendix for &amp;#39;create_test_df&amp;#39;

bench &amp;lt;- microbenchmark(
  times = 40,
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;                              )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;                         )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;                    )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;               )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;          )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;f&amp;#39;     )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;f&amp;#39;, &amp;#39;g&amp;#39;)]),
  cleave_by(test_df, a),
  cleave_by(test_df, a, b),
  cleave_by(test_df, a, b, c),
  cleave_by(test_df, a, b, c, d),
  cleave_by(test_df, a, b, c, d, e),
  cleave_by(test_df, a, b, c, d, e, f),
  cleave_by(test_df, a, b, c, d, e, f, g)
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-03-04-tidyverse-cleave-by_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;compare-runtimes-for-increasing-number-of-levels-within-grouping-variables.-cleave_by-vs-split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Compare runtimes for increasing number of levels within grouping variables. &lt;code&gt;cleave_by()&lt;/code&gt; vs &lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As seen in the graph below, &lt;code&gt;cleave_by()&lt;/code&gt; runtimes appear linear with respect to the number of levels within grouping variables, however it does start at a higher baseline time than &lt;code&gt;split()&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df2  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 2)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df3  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 3)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df4  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 4)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df5  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 5)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df6  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 6)  # See appendix for &amp;#39;create_test_df&amp;#39;

bench &amp;lt;- microbenchmark(
  split(test_df2 , test_df2[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df3 , test_df3[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df4 , test_df4[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df5 , test_df5[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df6 , test_df6[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  cleave_by(test_df2, a, b, c),
  cleave_by(test_df3, a, b, c),
  cleave_by(test_df4, a, b, c),
  cleave_by(test_df5, a, b, c),
  cleave_by(test_df6, a, b, c)
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-03-04-tidyverse-cleave-by_files/figure-html/unnamed-chunk-10-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Does &lt;code&gt;cleave_by()&lt;/code&gt; work?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;keeps runtimes linear in the number of variables
&lt;ul&gt;
&lt;li&gt;Goal met - the runtime increases linearly not quadratically. &lt;strong&gt;But&lt;/strong&gt; from a higher baseline&lt;/li&gt;
&lt;li&gt;The higher baseline is because of the grouping prep-work which is always done&lt;/li&gt;
&lt;li&gt;This prep-work only pays off when there are more than 4 grouping variables&lt;/li&gt;
&lt;li&gt;Would &lt;code&gt;Rcpp&lt;/code&gt; help here?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;keeps runtimes linear with respect to the number of groups within each variable.
&lt;ul&gt;
&lt;li&gt;Goal met - the runtime increases linearly not quadratically. &lt;strong&gt;But&lt;/strong&gt; from a higher baseline&lt;/li&gt;
&lt;li&gt;The higher baseline is because of the grouping prep-work which is always done&lt;/li&gt;
&lt;li&gt;This prep-work pays off very quickly, and for test dataset &lt;code&gt;cleave_by&lt;/code&gt; has
the advantage over &lt;code&gt;split()&lt;/code&gt; for 4 or more levels per splitting variable.&lt;/li&gt;
&lt;li&gt;Would &lt;code&gt;Rcpp&lt;/code&gt; help here?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Avoids the recyling of any splitting variable
&lt;ul&gt;
&lt;li&gt;Goal met.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;By only allowing column names to be passed in, if the column name is
valid, then the factor length will &lt;em&gt;always&lt;/em&gt; be the same as the data.frame
length and there will never be value recycling&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;keeps NA levels
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dplyr::group_by&lt;/code&gt; + &lt;code&gt;group_indices&lt;/code&gt; are both aware of (and keep) NA values.
Using them to create the group labels means that NA levels within a splitting
variable are kept.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Future&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Would some C++ (via Rcpp) help speed up the baseline case at all?&lt;/li&gt;
&lt;li&gt;Some corner cases to test for:
&lt;ul&gt;
&lt;li&gt;What should be done with factor columns with empty levels?&lt;/li&gt;
&lt;li&gt;What about data.frames with zero rows or zero cols?&lt;/li&gt;
&lt;li&gt;Can you &lt;code&gt;cleave_by()&lt;/code&gt; using a list-column as the splitting variable?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)

#-----------------------------------------------------------------------------
#&amp;#39; Create a test data set
#&amp;#39;
#&amp;#39; @param cols how many columns?
#&amp;#39; @param rows how many rows?
#&amp;#39; @param levels_per_col how many distinct levels for each variable/column?
#&amp;#39;
#-----------------------------------------------------------------------------
create_test_df &amp;lt;- function(cols, rows, levels_per_var) {
  data_source &amp;lt;- letters[seq(levels_per_var)]
  
  create_column &amp;lt;- function(...) {sample(data_source, size = rows, replace = TRUE)}
  letters[seq(cols)] %&amp;gt;% 
    set_names(letters[seq(cols)]) %&amp;gt;%
    purrr::map_dfc(create_column) 
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Base R split has issues - Part 2 idiosyncrasies</title>
      <link>https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-2-idiosyncrasies/</link>
      <pubDate>Sun, 04 Mar 2018 14:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-2-idiosyncrasies/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;base-r-split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R &lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;My prior post on &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;tidyverse split-apply-combined&lt;/a&gt; ended with me favouring &lt;code&gt;split + map_dfr&lt;/code&gt; as a replacement for &lt;code&gt;group_by + do&lt;/code&gt;. In this post I look at some idioscrasies of the split function from Base R.&lt;/p&gt;
&lt;p&gt;The main 2 gotchas with base R &lt;code&gt;split()&lt;/code&gt;:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;the splitting variable gets recycled if it’s not as long as the data.frame being split&lt;/li&gt;
&lt;li&gt;NA levels are dropped from the data&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div id=&#34;idiosyncrasy-1-the-splitting-variable-gets-recycled-if-its-not-long-enough&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idiosyncrasy 1: the splitting variable gets recycled if it’s not long enough&lt;/h2&gt;
&lt;p&gt;If trying to &lt;code&gt;split()&lt;/code&gt; a data.frame, the splitting factor needs to be the same length
as the data.frame.&lt;/p&gt;
&lt;p&gt;If the splitting factor is shorter than the data, then &lt;code&gt;split()&lt;/code&gt; will assume (foolishly!) that
you want to keep re-cycling through the factor to make up as many rows as necessary.
&lt;strong&gt;Almost nobody ever wants this behaviour!!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;R is nice enough to produce a warning about a length mismatch, but will do it for you anyway.&lt;/p&gt;
&lt;p&gt;In the following example, note how the data is split alternately group 1 or 2, as &lt;code&gt;split()&lt;/code&gt;
keeps cycling through the &lt;code&gt;bad_factor&lt;/code&gt; variable until it has finished processing the data.frame.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- data.frame(a = letters[1:6], good_factor=c(1, 1, 1, 1, 2, 2))

bad_factor &amp;lt;- c(1, 2)

split(test_df, bad_factor)  # oops I&amp;#39;ve used bad_factor by mistake!&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
##   a good_factor
## 1 a           1
## 3 c           1
## 5 e           2
## 
## $`2`
##   a good_factor
## 2 b           1
## 4 d           1
## 6 f           2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;idiosyncrasy-2-na-levels-are-dropped-from-the-data&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Idiosyncrasy 2: NA levels are dropped from the data&lt;/h2&gt;
&lt;p&gt;It’s very unlikely I want to throw away data unless I make a specific request to do so e.g. using &lt;code&gt;keep&lt;/code&gt; or &lt;code&gt;filter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;split()&lt;/code&gt; assumes that you &lt;em&gt;never&lt;/em&gt; want to keep an &lt;code&gt;NA&lt;/code&gt; level and just drops it during the splitting process.&lt;/p&gt;
&lt;p&gt;In the following example, ideally I want &lt;strong&gt;3&lt;/strong&gt; groups representing the 3 levels within &lt;code&gt;good_factor&lt;/code&gt;, i.e. 1, 2, and NA. However,
split just throws away all the data where &lt;code&gt;good_factor&lt;/code&gt; is NA.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- data.frame(a = letters[1:6], good_factor=c(1, 1, 2, 2, NA, NA))
split(test_df, test_df$good_factor)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## $`1`
##   a good_factor
## 1 a           1
## 2 b           1
## 
## $`2`
##   a good_factor
## 3 c           2
## 4 d           2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Base R split has issues - Part 1 runtime</title>
      <link>https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-1-runtime/</link>
      <pubDate>Sun, 04 Mar 2018 12:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/04/base-r-split-has-issues-part-1-runtime/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;base-r-split&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R &lt;code&gt;split()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;My prior post on &lt;a href=&#34;https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by---do/&#34;&gt;tidyverse split-apply-combined&lt;/a&gt; ended with me favouring &lt;code&gt;split + map_dfr&lt;/code&gt; as a replacement for &lt;code&gt;group_by + do&lt;/code&gt;. In this post I benchmark the runtime of base R &lt;code&gt;split()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the runtime graphs which follow, it seems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of splitting variables&lt;/li&gt;
&lt;li&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of groups within each variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neither of these is a good thing – a doubling in the number of splitting variables, or a doubling of levels within a splitting variable would increase runtimes by ~4x (modulo the baseline runtime)&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;base-r-split-runtime-is-quadratic-in-number-of-splitting-variables&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of splitting variables&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df &amp;lt;- create_test_df(cols=10, rows=10, levels_per_var=2)  # See appendix for &amp;#39;create_test_df&amp;#39;

bench &amp;lt;- microbenchmark(
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;                         )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;                    )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;               )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;          )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;     )]),
  split(test_df, test_df[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;f&amp;#39;)])
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-03-04-base-r-split-1_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;base-r-split-runtime-is-quadratic-in-number-of-groups-within-each-variable&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Base R &lt;code&gt;split()&lt;/code&gt; runtime is quadratic in number of groups within each variable&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;test_df2  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 2)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df3  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 3)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df4  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 4)  # See appendix for &amp;#39;create_test_df&amp;#39;
test_df5  &amp;lt;- create_test_df(cols=4, rows=40, levels_per_var= 5)  # See appendix for &amp;#39;create_test_df&amp;#39;

bench &amp;lt;- microbenchmark(
  split(test_df2 , test_df2[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df3 , test_df3[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df4 , test_df4[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)]),
  split(test_df5 , test_df5[, c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)])
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-03-04-base-r-split-1_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;set.seed(1)

#-----------------------------------------------------------------------------
#&amp;#39; Create a test data set
#&amp;#39;
#&amp;#39; @param cols how many columns?
#&amp;#39; @param rows how many rows?
#&amp;#39; @param levels_per_col how many distinct levels for each variable/column?
#&amp;#39;
#-----------------------------------------------------------------------------
create_test_df &amp;lt;- function(cols, rows, levels_per_var) {
  data_source &amp;lt;- letters[seq(levels_per_var)]
  
  create_column &amp;lt;- function(...) {sample(data_source, size = rows, replace = TRUE)}
  letters[seq(cols)] %&amp;gt;% 
    set_names(letters[seq(cols)]) %&amp;gt;%
    purrr::map_dfc(create_column) 
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Split-Apply-Combine: My search for a replacement for &#39;group_by &#43; do&#39;</title>
      <link>https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by-do/</link>
      <pubDate>Sat, 03 Mar 2018 07:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/03/03/split-apply-combine-my-search-for-a-replacement-for-group_by-do/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I currently process a lot of data a single entity at a time, but have a data.frame representing
multiple entities as input.&lt;/p&gt;
&lt;p&gt;I have specialist functions that do a lot of work on the data.frame for a single entity, so I
want to split the original data.frame into multiple data.frames containing just one entity each and then process them one at a time.&lt;/p&gt;
&lt;p&gt;This is a classic case of &lt;strong&gt;split-apply-combine&lt;/strong&gt;, as outlined &lt;a href=&#34;https://www.jstatsoft.org/article/view/v040i01/v40i01.pdf&#34;&gt;Hadley Wickham’s JStatSoft paper (pdf)&lt;/a&gt; and &lt;a href=&#34;https://speakerdeck.com/jennybc/ubc-stat545-split-apply-combine-intro&#34;&gt;Jenny Bryan’s Stat545 notes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Currently I uses &lt;code&gt;dplyr&lt;/code&gt; &lt;strong&gt;group_by&lt;/strong&gt; then &lt;strong&gt;do&lt;/strong&gt; to achieve, this.&lt;/p&gt;
&lt;p&gt;But as of 2016, &lt;code&gt;dplyr::do()&lt;/code&gt; is “basically deprecated” according to Hadley Wickham on Twitter:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/ijlyttle?ref_src=twsrc%5Etfw&#34;&gt;@ijlyttle&lt;/a&gt; btw dplyr::do() is now basically deprecated in favour of the purrr approach&lt;/p&gt;&amp;mdash; Hadley Wickham (@hadleywickham) &lt;a href=&#34;https://twitter.com/hadleywickham/status/719542847045636096?ref_src=twsrc%5Etfw&#34;&gt;April 11, 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;p&gt;On a more recent &lt;a href=&#34;https://community.rstudio.com/t/should-i-move-away-from-do-and-rowwise/2857&#34;&gt;community.rstudio.com thread&lt;/a&gt;, Hadley expanded:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;do() is definitely going away in the long term, but I’m not yet sure we have comprehensive alternative solutions to all problems that do() solves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;(Also “going away” means that we won’t make improvements to it and we won’t mention it in documentation and tutorials, but the code will continue to exist for a number of years)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Given that the original tweet was from 2 years ago, and I’m &lt;strong&gt;still&lt;/strong&gt; using &lt;em&gt;group_by/do&lt;/em&gt;, it’s time I start searching for a usable “purrr approach” that suits my needs.&lt;/p&gt;
&lt;p&gt;If there are tidyverse options I haven’t yet discovered, please let me know on &lt;a href=&#34;http://twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;!&lt;/p&gt;
&lt;div id=&#34;TOC&#34;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---prehistoric-times---split-lapply-do.callrbind-...&#34;&gt;Split-Apply-Combine - Prehistoric times - &lt;code&gt;split&lt;/code&gt;, &lt;code&gt;lapply&lt;/code&gt;, &lt;code&gt;do.call(rbind, …)&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---stone-age-with-plyr---plyrddply&#34;&gt;Split-Apply-Combine - Stone Age with plyr - &lt;code&gt;plyr::ddply&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---early-tidyverse-era---group_by-do&#34;&gt;Split-Apply-Combine - Early tidyverse era - &lt;code&gt;group_by&lt;/code&gt;, &lt;code&gt;do&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---early-mid-tidyverse-era-group_by-by_slice&#34;&gt;Split-Apply-Combine - Early-mid tidyverse era &lt;code&gt;group_by&lt;/code&gt; &amp;amp; &lt;code&gt;by_slice&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---current-era-tidyverse-group_by-nest-mutatemap&#34;&gt;Split-Apply-Combine - Current era tidyverse: &lt;code&gt;group_by&lt;/code&gt;, &lt;code&gt;nest&lt;/code&gt;, &lt;code&gt;mutate(map())&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#split-apply-combine---tidyversebase-hybrid-split-map_dfr&#34;&gt;Split-Apply-Combine - tidyverse/base hybrid: &lt;code&gt;split&lt;/code&gt;, &lt;code&gt;map_dfr&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&#34;#summary-table&#34;&gt;Summary Table&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;the-test-data---big_df&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The test data - &lt;code&gt;big_df&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;My data is always in a single data.frame, with information for multiple entities contained within it. There is always 1 or more indexing variables to identify, group or split the data.&lt;/p&gt;
&lt;p&gt;The test data used here (&lt;code&gt;big_df&lt;/code&gt;) is just a small subset of the &lt;code&gt;mtcars&lt;/code&gt; data set.&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-2&#34;&gt;Table 1: &lt;/span&gt;&lt;code&gt;big_df&lt;/code&gt; data.frame. This is just a cutdown version of &lt;strong&gt;mtcars&lt;/strong&gt; Using &lt;strong&gt;cyl&lt;/strong&gt; as an explicit &lt;strong&gt;ID&lt;/strong&gt; column&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;the-complex-function-to-run-on-the-data.frame-for-each-entity&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;The complex function to run on the data.frame for each entity&lt;/h2&gt;
&lt;p&gt;This is a (dummy) function to run on the data.frame for each entity.&lt;/p&gt;
&lt;p&gt;This function is usually quite complex and consists of multiple processing steps to produce a result.&lt;/p&gt;
&lt;p&gt;I am also interested in whether or not this inner function has access to the ID of the entity i.e. the grouping variable. The &lt;code&gt;dplyr::do()&lt;/code&gt; approach does have access to the grouping variable, but other methods may not.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;complex_func &amp;lt;- function(df) {
  df$N           &amp;lt;- nrow(df)
  df$func_has_ID &amp;lt;- &amp;#39;ID&amp;#39; %in% colnames(df)
  df
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---prehistoric-times---split-lapply-do.callrbind-...&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Prehistoric times - &lt;code&gt;split&lt;/code&gt;, &lt;code&gt;lapply&lt;/code&gt;, &lt;code&gt;do.call(rbind, ...)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In the dark ages before &lt;code&gt;dplyr&lt;/code&gt; and pipes, the code looked like this.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;split_df       &amp;lt;- split(big_df, big_df$ID)
result_list_df &amp;lt;- lapply(split_df, complex_func)
result_df      &amp;lt;- do.call(rbind, result_list_df)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-5&#34;&gt;Table 2: &lt;/span&gt;Prehistoric (pre-dply) with base R&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; contains the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---stone-age-with-plyr---plyrddply&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Stone Age with plyr - &lt;code&gt;plyr::ddply&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;One &lt;code&gt;plyr&lt;/code&gt; function call to do the split, apply and combine. Hasn’t been updated since 2016. C&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;result_df &amp;lt;- plyr::ddply(big_df, &amp;quot;ID&amp;quot;, complex_func)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-7&#34;&gt;Table 3: &lt;/span&gt;plyr!!&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---early-tidyverse-era---group_by-do&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Early tidyverse era - &lt;code&gt;group_by&lt;/code&gt;, &lt;code&gt;do&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In the early days of the tidyverse, the &lt;code&gt;group_by/do&lt;/code&gt; approach was the way to go, and is the way I still write most of the code for split-apply-combine situations.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;result_df &amp;lt;- big_df %&amp;gt;%
  group_by(ID) %&amp;gt;%
  do(complex_func(.)) %&amp;gt;%
  ungroup() &lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-9&#34;&gt;Table 4: &lt;/span&gt;Standard dplyr approach: group_by() then do()&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; contains the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;li&gt;Explicit &lt;code&gt;ungroup()&lt;/code&gt; required to remove grouping variable from result&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---early-mid-tidyverse-era-group_by-by_slice&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Early-mid tidyverse era &lt;code&gt;group_by&lt;/code&gt; &amp;amp; &lt;code&gt;by_slice&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;For a brief moment in time, &lt;code&gt;purrr&lt;/code&gt; had a &lt;code&gt;by_slice()&lt;/code&gt; function which offered the same features as &lt;code&gt;dplyr::do()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This function was then relegated to &lt;code&gt;purrrlyr&lt;/code&gt; as it wasn’t quite &lt;code&gt;purrr&lt;/code&gt; and it wasn’t quite &lt;code&gt;dplyr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href=&#34;https://github.com/hadley/purrrlyr/blob/master/NEWS.md&#34;&gt;purrrlyr NEWS file&lt;/a&gt; functions in this packages are
unlikely to be updated, so using them would be probably be a mistake. This example is included for posterity.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;result_df &amp;lt;- big_df %&amp;gt;%
  group_by(ID) %&amp;gt;%
  purrrlyr::by_slice(~complex_func(.x), .collate = &amp;#39;rows&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-11&#34;&gt;Table 5: &lt;/span&gt;Results of the using the soon-to-be-dead(?) purrrly &lt;strong&gt;by_slice&lt;/strong&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; &lt;em&gt;does &lt;strong&gt;not&lt;/strong&gt; contain&lt;/em&gt; the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;li&gt;resulting data.frame does not have any grouping variables, and therefore no explicit &lt;code&gt;ungroup()&lt;/code&gt; is required&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://github.com/hadley/purrrlyr/blob/master/NEWS.md&#34;&gt;purrrlyr NEWS.md&lt;/a&gt; file does however offer the advice that instead of &lt;code&gt;by_slice&lt;/code&gt;, the preferred method is a combination
of &lt;code&gt;tidyr::nest()&lt;/code&gt; and &lt;code&gt;dplyr::mutate()&lt;/code&gt; using an inner &lt;code&gt;purrr::map&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---current-era-tidyverse-group_by-nest-mutatemap&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Current era tidyverse: &lt;code&gt;group_by&lt;/code&gt;, &lt;code&gt;nest&lt;/code&gt;, &lt;code&gt;mutate(map())&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The current suggested route in the tidyverse is to nest the data, and then operate on the list column by mutating it via &lt;code&gt;purrr::map&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;result_df &amp;lt;- big_df %&amp;gt;%
  group_by(ID) %&amp;gt;%
  nest() %&amp;gt;%
  mutate(data = purrr::map(data, complex_func)) %&amp;gt;%
  unnest()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Warning: `cols` is now required.
## Please use `cols = c(data)`&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-13&#34;&gt;Table 6: &lt;/span&gt;Current accepted practice: group_by, nest, mutate(map()&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; &lt;em&gt;does &lt;strong&gt;not&lt;/strong&gt; contain&lt;/em&gt; the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;li&gt;an explicit &lt;code&gt;unnest&lt;/code&gt; is required at the end to get the data back in its original form&lt;/li&gt;
&lt;li&gt;having to both mutate &lt;strong&gt;and&lt;/strong&gt; map seems an extra step over all other methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---tidyversebase-hybrid-split-map_dfr&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - tidyverse/base hybrid: &lt;code&gt;split&lt;/code&gt;, &lt;code&gt;map_dfr&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This hybrid approach uses &lt;code&gt;split()&lt;/code&gt; to create a list of data.frames, and then uses &lt;code&gt;map_dfr&lt;/code&gt; to map a function over each
data.frame and then combine (by rows) into a single data.frame.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;result_df &amp;lt;- big_df %&amp;gt;%
  split(.$ID) %&amp;gt;%
  purrr::map_dfr(complex_func) &lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-15&#34;&gt;Table 7: &lt;/span&gt;Hybrid base R/tidyverse approach&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This seems pretty compact - except for the very un-tidyverse &lt;code&gt;split(.$ID)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; contains the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;li&gt;No explicit ungrouping required.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;split-apply-combine---alternative-universe-data.table&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Split-Apply-Combine - Alternative universe &lt;code&gt;data.table&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Update: &lt;a href=&#34;http://twitter.com/summersgillmatt&#34;&gt;MattSummersgill&lt;/a&gt; and &lt;a href=&#34;http://twitter.com/michael_chirico&#34;&gt;michael_chirico&lt;/a&gt; suggested using &lt;code&gt;data.table&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This doesn’t really fit within the scope of my search (I’m definitely in the tidyverse ecosystem), but it’s included for the sake of comparison.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(data.table)
setDT(big_df)
result_df &amp;lt;- big_df[, complex_func(.SD), by = .(this_ID = ID), .SDcols=colnames(big_df)]&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-17&#34;&gt;Table 8: &lt;/span&gt;Alterate universe approach with &lt;code&gt;data.table&lt;/code&gt;&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;right&#34;&gt;this_ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;ID&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mpg&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;disp&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;N&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;func_has_ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;225&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;460&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18.7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14.3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;360&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15.0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;301&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data.frame passed to &lt;code&gt;complex_func()&lt;/code&gt; contains the &lt;strong&gt;ID&lt;/strong&gt; variable&lt;/li&gt;
&lt;li&gt;No explicit ungrouping required.&lt;/li&gt;
&lt;li&gt;Without being immersed in day-to-day use of &lt;code&gt;data.table&lt;/code&gt; this solution is a little opaque to me.&lt;/li&gt;
&lt;li&gt;There are issues around how &lt;code&gt;data.table&lt;/code&gt; handles the ID column. Calling it one way gave &lt;strong&gt;2&lt;/strong&gt; ID columns
in the result I’ve explicitly set a new grouping variable name to avoid this.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;summary-table&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary Table&lt;/h2&gt;
&lt;p&gt;Below is a summary table on how the split-apply-combine is achieved for various implementations.&lt;/p&gt;
&lt;p&gt;A blank entry means that the action of split, apply or combine is handled by the previous entry.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;Method&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Split&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Apply&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Combine&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Group var available in applied function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Prehistoric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;split&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lapply&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;do.call(rbind)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Stone Age&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;plyr::ddply&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Early Tidyverse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::group_by&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::do&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::ungroup&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Early-Mid Tidyverse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::group_by&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;purrrlyr::by_slice&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Current Era Tidyverse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::group_by + tidyr::nest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dplyr::mutate + purrr::map&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tidyr::unnest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Hybrid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;split&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;purrr::map_dfr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Alternate Universe&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.table&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;My aim is to find a replacement for &lt;code&gt;group_by/do&lt;/code&gt; now that &lt;code&gt;dplyr::do()&lt;/code&gt; is “basically deprecated”.&lt;/p&gt;
&lt;p&gt;I looked at a number of tidyverse/tidyr/purrr replacements for &lt;code&gt;do()&lt;/code&gt; - if you know of a technique I
missed, please let me know on &lt;a href=&#34;http://twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My &lt;strong&gt;least favourite&lt;/strong&gt; technique is to use current era tidyverse with &lt;code&gt;nest/mutate/map/unnest&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;I find it too verbose with a high cognitive overhead&lt;/li&gt;
&lt;li&gt;have to nest and unnest then operate on a new &lt;code&gt;data&lt;/code&gt; list-column&lt;/li&gt;
&lt;li&gt;the nested data.frame has a new data.frame column list which &lt;strong&gt;doesn’t&lt;/strong&gt; contain the grouping variable&lt;/li&gt;
&lt;li&gt;applying the function to the data.frame subsets requires a &lt;code&gt;mutate&lt;/code&gt; &lt;strong&gt;AND&lt;/strong&gt; a &lt;code&gt;map&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Favourite replacement&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;tidyverse/base hybrid with &lt;code&gt;split/map_dfr&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;short and sweet.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;No need for &lt;code&gt;purrr::map&lt;/code&gt; within a &lt;code&gt;mutate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;No need for &lt;code&gt;dplyr::do()&lt;/code&gt; syntax with the &lt;code&gt;.&lt;/code&gt; e.g. &lt;code&gt;complex_func(.)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Outstanding issue&lt;/strong&gt;: Why isn’t there a &lt;code&gt;purrr&lt;/code&gt; version of the base function &lt;code&gt;split&lt;/code&gt;? According to &lt;a href=&#34;https://github.com/tidyverse/purrr/issues/274&#34;&gt;Hadley on github&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A function that acts rowwise on a data frame doesn’t seem like it should live in purrr.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next step: Make my own tidyverse &lt;code&gt;split_by&lt;/code&gt;?&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>The &#39;ggplot2pipes&#39; package</title>
      <link>https://coolbutuseless.github.io/2018/02/27/the-ggplot2pipes-package/</link>
      <pubDate>Tue, 27 Feb 2018 15:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/27/the-ggplot2pipes-package/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;p&gt;Sometimes it doesn’t feel like a project (no matter how small!) is completed until there’s a package for it.&lt;/p&gt;
&lt;p&gt;I wrapped up my previous post on &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/25/using-ggplot-with-pipes/&#34;&gt;using pipes with ggplot2&lt;/a&gt; into the &lt;a href=&#34;https://github.com/coolbutuseless/ggplot2pipes&#34;&gt;ggplot2pipes&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ggplot2pipes&lt;/code&gt; is a package for creating pipe-enabled versions of &lt;code&gt;ggplot2&lt;/code&gt; functions.&lt;/li&gt;
&lt;li&gt;You can find it on &lt;a href=&#34;https://github.com/coolbutuseless/ggplot2pipes&#34;&gt;github&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install: &lt;code&gt;devtools::install_github(&#34;coolbutuseless/ggplot2pipes&#34;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This supercedes the pipify package from 2015.&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;basic-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Basic Usage&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Call &lt;code&gt;init_ggplot2_pipes()&lt;/code&gt; to create all the pipe-enabled functions.
&lt;ul&gt;
&lt;li&gt;This will create a version of the ggplot function prefixed with “add_”, e.g. the function &lt;code&gt;geom_point()&lt;/code&gt; becomes the pipe-enabled function called &lt;code&gt;add_geom_point()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Use the new functions with dplyr/magrittr pipes&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(dplyr)
library(ggplot2)
library(ggplot2pipes)

init_ggplot2_pipes()

ggplot(mtcars) %&amp;gt;%
  add_geom_line(aes(mpg, wt)) %&amp;gt;%
  add_labs(title=&amp;quot;hello&amp;quot;) %&amp;gt;%
  add_theme_bw() %&amp;gt;%
  add_facet_wrap(~am)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-27-ggplot2-with-pipes_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;advanced-usage&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Advanced Usage&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The list of functions which are pipe-enabled is controlled by the regular expression argument &lt;code&gt;func_regex&lt;/code&gt;. By default this captures most geoms and stats and a few other core things.&lt;/li&gt;
&lt;li&gt;The default prefix for the new pipe-enabled functions is &lt;code&gt;add_&lt;/code&gt;, but you can change this with the &lt;code&gt;prefix&lt;/code&gt; argument. Note that the &lt;code&gt;prefix&lt;/code&gt; can even be set to the empty string if you want to try evil/confusing things like:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;init_ggplot2_pipes(prefix=&amp;#39;&amp;#39;)

ggplot(mtcars) %&amp;gt;%
  geom_line(aes(mpg, wt)) %&amp;gt;%
  labs(title=&amp;quot;hello&amp;quot;) %&amp;gt;%
  theme_bw() %&amp;gt;%
  facet_wrap(~am)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Using ggplot with pipes</title>
      <link>https://coolbutuseless.github.io/2018/02/25/using-ggplot-with-pipes/</link>
      <pubDate>Sun, 25 Feb 2018 17:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/25/using-ggplot-with-pipes/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;I want to add pipes to ALL THE THINGS.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ggplot2&lt;/code&gt; is a thing&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ggplot2&lt;/code&gt; doesn’t use pipes&lt;/li&gt;
&lt;li&gt;Add pipe support to &lt;code&gt;ggplot2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Write a blog post.&lt;/li&gt;
&lt;li&gt;???&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note: for keen followers, this is a rehash of my hack that was the &lt;code&gt;pipify&lt;/code&gt; package.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;ggplot-without-pipes.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;ggplot without pipes. :(&lt;/h2&gt;
&lt;p&gt;Using the &lt;code&gt;+&lt;/code&gt; character is soooo early 2010’s.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) +
  geom_point(aes(mpg, cyl))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-25-magrittr-pipes-with-ggplot_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-add_geom_point-as-a-pipe-able-geom_point&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create &lt;code&gt;add_geom_point&lt;/code&gt; as a pipe-able &lt;code&gt;geom_point&lt;/code&gt; :)&lt;/h2&gt;
&lt;p&gt;Let’s write a wrapper around &lt;code&gt;geom_point&lt;/code&gt; so that I can use it in a pipe&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; A wrapper around &amp;#39;geom_point&amp;#39; that is pipe-aware
#&amp;#39;
#&amp;#39; @param lhs the left-hand side of the addition e.g. &amp;quot;ggplot(mtcars)&amp;quot;
#&amp;#39; @param ... the arguments to be passed to the &amp;#39;geom_point&amp;#39; function
#-----------------------------------------------------------------------------
add_geom_point &amp;lt;- function(lhs, ...) {
  `+`(lhs, geom_point(...))
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) %&amp;gt;%
  add_geom_point(aes(mpg, cyl))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-25-magrittr-pipes-with-ggplot_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-pipe-able-versions-of-any-ggplot2-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create pipe-able versions of any ggplot2 function&lt;/h2&gt;
&lt;p&gt;Instead of writing all the wrappers for all the gglot functions manually,
I wrote a function to create a pipe-aware function out of a plus-aware function.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Create a pipe-aware func from any plus-aware function 
#&amp;#39;
#&amp;#39; Assigns the new function in the global environemnt
#&amp;#39;
#&amp;#39; @param plus_aware_func_name character. e.g. &amp;quot;geom_point&amp;quot;
#&amp;#39;
#-----------------------------------------------------------------------------
create_pipe_aware_func &amp;lt;- function(plus_aware_func_name) {
  pipe_aware_func_name &amp;lt;- paste0(&amp;quot;add_&amp;quot;, plus_aware_func_name)
    
  assign(
    pipe_aware_func_name,
    function(lhs, ...) {
      func &amp;lt;- get(plus_aware_func_name)
      `+`(lhs, func(...))
    },
    envir = globalenv()
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use this function to create &lt;code&gt;add_geom_line()&lt;/code&gt; and use it.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_pipe_aware_func(&amp;quot;geom_line&amp;quot;)  # This will create &amp;#39;add_geom_line()&amp;#39; in the global environment

ggplot(mtcars) %&amp;gt;%
  add_geom_point(aes(mpg, cyl)) %&amp;gt;%
  add_geom_line(aes(mpg, cyl))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-25-magrittr-pipes-with-ggplot_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;create-add_-as-pipe-able-versions-of-all-ggplot-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create &lt;code&gt;add_*&lt;/code&gt; as pipe-able versions of all ggplot functions :) :) :)&lt;/h2&gt;
&lt;p&gt;Now that I can generate a pipe-aware function for a single ggplot function, I’ll
do the whole of the ggplot package:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Find all ggplot2 function names of interest&lt;/li&gt;
&lt;li&gt;Create pipe-aware wrapper function for each one&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ls(&amp;#39;package:ggplot2&amp;#39;) %&amp;gt;%
  purrr::keep(~is.function(get(.x))) %&amp;gt;%
  purrr::keep(~grepl(&amp;#39;^(geom_|scale_|stat_|coord_|annot|xlim|ylim|theme_|facet_)&amp;#39;, .x)) %&amp;gt;%
  purrr::walk(create_pipe_aware_func)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(mtcars) %&amp;gt;%
  add_geom_point(aes(mpg, cyl, colour=as.factor(am))) %&amp;gt;%
  add_facet_grid(~vs) %&amp;gt;%
  add_theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-25-magrittr-pipes-with-ggplot_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;evil-version&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Evil version&lt;/h2&gt;
&lt;p&gt;And now instead of adding the &lt;code&gt;add_&lt;/code&gt; prefix in front of the function names, just
mask the original ggplot2 functions in the global environment and use the original
function names with pipes.&lt;/p&gt;
&lt;p&gt;Note: This will break in all sorts of wonderful ways!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Create a pipe-aware func from any plus-aware function 
#&amp;#39;
#&amp;#39; Creates the pipe-aware function of the same name in the global environment
#&amp;#39;
#&amp;#39; @param plus_aware_func_name character. e.g. &amp;quot;geom_point&amp;quot;
#&amp;#39;
#-----------------------------------------------------------------------------
create_pipe_aware_func_evil &amp;lt;- function(plus_aware_func_name) {
  assign(
    plus_aware_func_name,
    function(lhs, ...) {
      func &amp;lt;- get(plus_aware_func_name, envir = as.environment(&amp;#39;package:ggplot2&amp;#39;))
      `+`(lhs, func(...))
    },
    pos = globalenv()
  )
}


ls(&amp;#39;package:ggplot2&amp;#39;) %&amp;gt;%
  purrr::keep(~is.function(get(.x))) %&amp;gt;%
  purrr::keep(~grepl(&amp;#39;^(geom_|stat_|coord_|annot|xlim|ylim|theme_|facet_)&amp;#39;, .x)) %&amp;gt;%
  purrr::walk(create_pipe_aware_func_evil)


ggplot(mtcars) %&amp;gt;%
  geom_point(aes(mpg, cyl, colour=as.factor(am))) %&amp;gt;%
  facet_grid(~vs) %&amp;gt;%
  theme_bw()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-25-magrittr-pipes-with-ggplot_files/figure-html/unnamed-chunk-8-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;A solution to a problem that nobody really has.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Customing ggplots created within functions</title>
      <link>https://coolbutuseless.github.io/2018/02/24/customing-ggplots-created-within-functions/</link>
      <pubDate>Sat, 24 Feb 2018 08:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/24/customing-ggplots-created-within-functions/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;I often need to create complicated plots within a function.&lt;/p&gt;
&lt;p&gt;A dataset is passed in to the function, then I do some data transformation and then
create a multilayered/complicated plot.&lt;/p&gt;
&lt;p&gt;I then set up the plot to have good default colours, aesthetics etc.&lt;/p&gt;
&lt;p&gt;However sooner or later, I’ll want to override the defaults or
add some extra styling.&lt;/p&gt;
&lt;p&gt;This post details how these plotting functions start and how they end up.&lt;/p&gt;
&lt;p&gt;I’m also keen to hear how others approach this problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example---start&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - start&lt;/h2&gt;
&lt;p&gt;The following illustrates the idea - a plot created within a function.&lt;/p&gt;
&lt;p&gt;As you can see, I’ve customised the presentation perfectly(!) and hard-coded the colour and size of the points.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_super_plot &amp;lt;- function() {
  ggplot(mtcars) + 
    geom_line(aes(mpg, wt, group=cyl)) +
    geom_point(aes(mpg, wt), colour=&amp;#39;blue&amp;#39;, size=2) 
}
create_super_plot()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-24-customising-ggplot-in-functions_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example---round-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - round 2&lt;/h2&gt;
&lt;p&gt;Now that I have this perfect plot all wrapped in a function, I realise I need
to customise it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I want to change the colour of the lines&lt;/li&gt;
&lt;li&gt;I want to change the colour of the points&lt;/li&gt;
&lt;li&gt;I want larger points&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I adapt the function to take these as arguments…&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_super_plot &amp;lt;- function(line_colour=&amp;#39;black&amp;#39;, point_colour=&amp;#39;blue&amp;#39;, point_size=3) {
  ggplot(mtcars) + 
    geom_line(aes(mpg, wt, group=cyl), colour=line_colour) +
    geom_point(aes(mpg, wt), colour=point_colour, size=point_size) 
}

create_super_plot(point_colour=&amp;#39;red&amp;#39;, point_size = 10)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-24-customising-ggplot-in-functions_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;example---round-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example - round 3&lt;/h2&gt;
&lt;p&gt;After using the function for a while, and adding customisation possiblities as I
need them, I end up with the following code - where there is now an option for every single
aesthetic for every single geom!&lt;/p&gt;
&lt;p&gt;This is unwieldy, and gets worse if there are more geoms or multiples of the same geom on the same plot.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_super_plot &amp;lt;- function(
  point_shape   = 19,
  point_colour  = &amp;#39;blue&amp;#39;, 
  point_size    = 1.5,
  point_fill    = NA,
  point_alpha   = NA,
  point_stroke  = 0.5,
  line_colour   = &amp;#39;black&amp;#39;,
  line_size     = 0.5,
  line_linetype = 1,
  line_alpha    = NA
  ) {
  ggplot(mtcars) + 
    geom_line(mapping   = aes(mpg, wt, group=cyl), 
              colour    = line_colour,
              size      = line_size,
              linetype  = line_linetype,
              alpha     = line_alpha) +
    geom_point(mapping = aes(mpg, wt), 
               shape   = point_shape,
               colour  = point_colour, 
               size    = point_size,
               fill    = point_fill,
               alpha   = point_alpha,
               stroke  = point_stroke) 
}

create_super_plot(point_colour=&amp;#39;red&amp;#39;, point_size = 10)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-24-customising-ggplot-in-functions_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution!&lt;/h2&gt;
&lt;p&gt;My workaround has been to define some helper functions which are just wrappers around
ggplot geoms.&lt;/p&gt;
&lt;p&gt;The user arguments to the geom are supplied in a list called &lt;code&gt;aes_override&lt;/code&gt;, and
when calling the actual geom, these user arguments override the default arguments.&lt;/p&gt;
&lt;p&gt;This means that we no longer have to specify every single aesthetic for every single geom in the outer function call!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;geom_point_ &amp;lt;- function(..., aes_override=list()) {
  args &amp;lt;- modifyList(list(...), aes_override)
  do.call(geom_point, args)
}

geom_line_ &amp;lt;- function(..., aes_override=list()) {
  args &amp;lt;- modifyList(list(...), aes_override)
  do.call(geom_line, args)
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_super_plot &amp;lt;- function(line_aes=list(), point_aes=list()) {
  ggplot(mtcars) + 
    geom_line_ (mapping = aes(mpg, wt, group=cyl), aes_override = line_aes ) +
    geom_point_(mapping = aes(mpg, wt           ), aes_override = point_aes) 
}

create_super_plot(point_aes = list(colour=&amp;#39;red&amp;#39;, size=10))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-24-customising-ggplot-in-functions_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;solution---bonus-features-i-can-also-override-the-variable-mapping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Solution - bonus features: I can also override the variable mapping!&lt;/h2&gt;
&lt;p&gt;As well as being able to override the static aesthetics, you can also
override any aesthetic mapping (although it can be a bit trickier).&lt;/p&gt;
&lt;p&gt;Here I change the default line mapping from &lt;code&gt;group=cyl&lt;/code&gt; to &lt;code&gt;colour=cyl&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;create_super_plot(
  point_aes = list(colour=&amp;#39;red&amp;#39;, size=10),
  line_aes  = list(mapping=aes(mpg, wt, colour=as.factor(cyl)))
)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-24-customising-ggplot-in-functions_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;is-there-a-better-way&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Is there a better way?&lt;/h2&gt;
&lt;p&gt;It seems like there should be a better way to do this. Is there?&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Overlapping lines</title>
      <link>https://coolbutuseless.github.io/2018/02/20/overlapping-lines/</link>
      <pubDate>Tue, 20 Feb 2018 17:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/20/overlapping-lines/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;overlapping-lines-for-interesting-image-effect&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Overlapping lines for interesting image effect&lt;/h2&gt;
&lt;p&gt;While convex hulls can produce some interesting results (See parts
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/15/chull/&#34;&gt;1&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/16/convex-hulls-part-2/&#34;&gt;2&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-3/&#34;&gt;3&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-4/&#34;&gt;4&lt;/a&gt;
)
they’re expensive to compute relative to just drawing lines.&lt;/p&gt;
&lt;p&gt;The same idea using lines is 1000x faster and the results are just as good:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sample points from the image (with darker pixels having a higher probability of being sampled)&lt;/li&gt;
&lt;li&gt;Find the distance between successive points and filter out line segments which are too long&lt;/li&gt;
&lt;li&gt;Draw a single poly-line connecting all the remaining points&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;final-image-using-lines-rather-than-convex-hulls&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Final image using lines rather than convex hulls&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/line-mona/anim4.gif&#34; width=&#34;80%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;



&lt;/div&gt;
&lt;div id=&#34;code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Read a jpg file using image magick and scale it and convert to greyscale
#-----------------------------------------------------------------------------
filename &amp;lt;- &amp;#39;data/mona.jpg&amp;#39;
im &amp;lt;- magick::image_read(filename) %&amp;gt;%
  magick::image_convert(type=&amp;#39;grayscale&amp;#39;) %&amp;gt;%
  magick::image_scale(geometry=&amp;quot;75%&amp;quot;) %&amp;gt;%
  magick::image_flip()

#-----------------------------------------------------------------------------
# Extract just the numeric matrix representing the image.
#-----------------------------------------------------------------------------
m &amp;lt;- magick::as_EBImage(im)@.Data


#-----------------------------------------------------------------------------
# Set up plot configuration
#-----------------------------------------------------------------------------
par(mar = c(0, 0, 0, 0))

xlim          &amp;lt;- c(0, dim(m)[1])
ylim          &amp;lt;- c(0, dim(m)[2])
width         &amp;lt;- 4
height        &amp;lt;- 6
dpi           &amp;lt;- 200


#-----------------------------------------------------------------------------
# how many objects in each frame?
#-----------------------------------------------------------------------------
nobjects_ &amp;lt;- c(
  seq(    2,     20 - 1,     1),
  seq(   20,    200 - 1,    10),
  seq(  200,   2000 - 1,   100),
  seq( 2000,  50000 - 1,  1000),
  seq(50000,  90000 - 1,  5000),
  seq(90000, 100000    ,   500)
)


#-----------------------------------------------------------------------------
# What alpha level for each frame?  The more objects there are,
# the lower the alpha to ensure the overlap looks good.
#-----------------------------------------------------------------------------
col_ &amp;lt;- nobjects_ %&amp;gt;% purrr::map_dbl(~1 - (log10(.x)/5 - log10(1.9)/5)^0.2) %&amp;gt;%
  purrr::map_chr(~gray(0, .x))


#-----------------------------------------------------------------------------
# Sample all the points necessary for the maximum nobjects and include
# a 10x factor since I know I&amp;#39;m going to filter out lots of the generated points
#-----------------------------------------------------------------------------
all_indices &amp;lt;- sample(seq(m), size = 10 * max(nobjects_ + 10), prob = (1-m)^2, replace = TRUE)
all_points  &amp;lt;- arrayInd(all_indices, .dim=dim(m))


#-----------------------------------------------------------------------------
# Now filter the successive points so that it&amp;#39;s biased towards shorter 
# line segments
#-----------------------------------------------------------------------------
max_dist &amp;lt;- sqrt(nrow(m)^2 + ncol(m)^2)

pts &amp;lt;- as.data.frame(all_points) %&amp;gt;% 
  as.tbl() %&amp;gt;%
  set_names(c(&amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;)) %&amp;gt;%
  mutate(
    val  = 1 - m[all_indices]
  )

for (i in 1:20) {
  pts %&amp;lt;&amp;gt;% mutate(
    dist = sqrt((x - lead(x))^2 + (y - lead(y))^2),
    sdist = dist/max_dist,
    keep  = val &amp;gt; 2.5 * sdist
  )
  
  pts %&amp;lt;&amp;gt;% filter(
    is.na(keep) | keep
  )
}

  
  
#-----------------------------------------------------------------------------
# Draw each frame
#-----------------------------------------------------------------------------
for (i in seq(nobjects_)) {
  nobjects &amp;lt;- nobjects_[i]
  col      &amp;lt;- col_[i]
  
  plot_points &amp;lt;- pts[seq(1+nobjects),c(&amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;)]
  
  #-----------------------------------------------------------------------------
  # Plot lines and save
  #-----------------------------------------------------------------------------
  plot_filename &amp;lt;- sprintf(&amp;quot;plot//mona2/plot_%06i.png&amp;quot;, nobjects)
  withr::with_png(plot_filename, width=width*dpi, height=height*dpi, {
    plot(1, type=&amp;quot;n&amp;quot;, xlab=&amp;quot;&amp;quot;, ylab=&amp;quot;&amp;quot;, xlim=xlim, ylim=ylim, asp=1, ann=FALSE,
         axes = FALSE, frame.plot = FALSE)
    
    lines(plot_points, col=col)
  })
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Convex Hulls part 4</title>
      <link>https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-4/</link>
      <pubDate>Sun, 18 Feb 2018 07:45:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-4/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;messing-around-with-chull&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Messing around with &lt;code&gt;chull&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned previously (
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/15/chull/&#34;&gt;1&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/16/convex-hulls-part-2/&#34;&gt;2&lt;/a&gt;,
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-3/&#34;&gt;3&lt;/a&gt;
)
I’m attempting to use &lt;code&gt;chull()&lt;/code&gt; to create some stuff.&lt;/p&gt;
&lt;p&gt;I had though that using convex hulls would give me some nicer medium-scale circular artefacts in
the image, but that didn’t occur.&lt;/p&gt;
&lt;p&gt;Instead, just using the random points sampled from the image to draw a very long line was sufficient to produce an almost
equivalent image (and about 1000x faster as well!)&lt;/p&gt;
&lt;p&gt;The new line scheme is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a large number of points somehow&lt;/li&gt;
&lt;li&gt;Sample points from the image (with darker pixels having a higher probability of being sampled)&lt;/li&gt;
&lt;li&gt;Draw the line connecting all these points&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;final-image-using-lines-rather-than-convex-hulls&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Final image using lines rather than convex hulls&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/line-mona/plot_100000.jpg&#34; width=&#34;45%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/line-mona/anim.gif&#34; width=&#34;45%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;




&lt;/div&gt;
&lt;div id=&#34;code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Read a jpg file using image magick and scale it and convert to greyscale
#-----------------------------------------------------------------------------
filename &amp;lt;- &amp;#39;data/mona.jpg&amp;#39;
im &amp;lt;- magick::image_read(filename) %&amp;gt;%
  magick::image_convert(type=&amp;#39;grayscale&amp;#39;) %&amp;gt;%
  magick::image_scale(geometry=&amp;quot;75%&amp;quot;) %&amp;gt;%
  magick::image_flip()

#-----------------------------------------------------------------------------
# Extract just the numeric matrix representing the image.
#-----------------------------------------------------------------------------
m &amp;lt;- magick::as_EBImage(im)@.Data


#-----------------------------------------------------------------------------
# Set up plot configuration
#-----------------------------------------------------------------------------
par(mar = c(0, 0, 0, 0))

xlim          &amp;lt;- c(0, dim(m)[1])
ylim          &amp;lt;- c(0, dim(m)[2])
w             &amp;lt;- 4
h             &amp;lt;- 6
dpi           &amp;lt;- 150


#-----------------------------------------------------------------------------
# Choose random points, but weighted by the &amp;#39;opposite&amp;#39; of their colour value
# i.e. Prefer to choose the darker points over the lighter points.
#-----------------------------------------------------------------------------
# nobjects &amp;lt;-    300; col &amp;lt;- &amp;#39;#000000ff&amp;#39;
nobjects &amp;lt;- 100000; col &amp;lt;- &amp;#39;#00000002&amp;#39;

plot_indices &amp;lt;- sample(seq(m), size = nobjects, prob = (1-m)^2, replace = TRUE)
plot_points  &amp;lt;- arrayInd(plot_indices, .dim=dim(m))


#-----------------------------------------------------------------------------
# Plot lines and save
#-----------------------------------------------------------------------------
plot_filename &amp;lt;- sprintf(&amp;quot;plot/plot_%06i.png&amp;quot;, nobjects)
withr::with_png(plot_filename, width=w*dpi, height=h*dpi, {
  plot(1, type=&amp;quot;n&amp;quot;, xlab=&amp;quot;&amp;quot;, ylab=&amp;quot;&amp;quot;, xlim=xlim, ylim=ylim, asp=1, ann=FALSE,
       axes = FALSE, frame.plot = FALSE)
  
    lines(plot_points, col=col)
})&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Convex Hulls part 3</title>
      <link>https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-3/</link>
      <pubDate>Sun, 18 Feb 2018 07:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/18/convex-hulls-part-3/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;messing-around-with-chull&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Messing around with &lt;code&gt;chull&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/15/chull/&#34;&gt;yesterday&lt;/a&gt;, I’m using &lt;code&gt;chull()&lt;/code&gt; to create some stuff.&lt;/p&gt;
&lt;p&gt;The basic scheme is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a large number of points somehow&lt;/li&gt;
&lt;li&gt;Repeat the following until done:
&lt;ul&gt;
&lt;li&gt;Take a small subset of the points&lt;/li&gt;
&lt;li&gt;Draw the convex hull around them.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Extra filtering was done to reject some of the generated convex hulls, i.e.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reject those with a large area, as I wanted to use smaller, local hulls&lt;/li&gt;
&lt;li&gt;Reject those with “bad” circularity. i.e. when the ratio of convex hull area to bounding box area was too low&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s what happens when a recognizable image is used as a point source.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;creation-of-mona-lisa-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creation of Mona Lisa image&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-mona/plot_04_00000300.jpg&#34; width=&#34;30%&#34; style=&#34;float: left;&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-mona/plot_04_00003000.jpg&#34; width=&#34;30%&#34; style=&#34;float: left;&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-mona/plot_04_00030000.jpg&#34; width=&#34;30%&#34; style=&#34;float: left;&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-mona/plot_04_00100000.jpg&#34; width=&#34;30%&#34; style=&#34;float: left;&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-mona/plot_04_00150000.jpg&#34; width=&#34;30%&#34; style=&#34;float: left;&#34;/&gt;&lt;/p&gt;
&lt;div style=&#34;clear: both;&#34;&gt;


&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>convex hulls part 2</title>
      <link>https://coolbutuseless.github.io/2018/02/16/convex-hulls-part-2/</link>
      <pubDate>Fri, 16 Feb 2018 05:30:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/16/convex-hulls-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;messing-around-with-chull&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Messing around with &lt;code&gt;chull&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;As mentioned &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/15/chull/&#34;&gt;yesterday&lt;/a&gt;, I’m using &lt;code&gt;chull()&lt;/code&gt; to create some stuff.&lt;/p&gt;
&lt;p&gt;The basic scheme is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a large number of points somehow&lt;/li&gt;
&lt;li&gt;Repeat until done:
&lt;ul&gt;
&lt;li&gt;Take a small subset of the points&lt;/li&gt;
&lt;li&gt;Draw the convex hull around them.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of tweaked random point fields, here’s what happens when a recognizable image is used as a point source.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;mona-lisa&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Mona Lisa&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/plot.jpg&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/plot 13.jpg&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;girl-with-a-pearl-earring&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Girl with a Pearl Earring&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/plot 9.jpg&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>chull()</title>
      <link>https://coolbutuseless.github.io/2018/02/15/chull/</link>
      <pubDate>Thu, 15 Feb 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/15/chull/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;messing-around-with-chull&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Messing around with &lt;code&gt;chull&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Taking a break from whitelisting/sandboxing and malicous users.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;chull()&lt;/code&gt; to create some stuff.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a large number of points somehow&lt;/li&gt;
&lt;li&gt;Repeat until done:
&lt;ul&gt;
&lt;li&gt;Take a small subset of the points&lt;/li&gt;
&lt;li&gt;Draw the convex hull around them.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/art1.jpg&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/art2.jpg&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/art3.jpg&#34;/&gt;
&lt;img src=&#34;https://coolbutuseless.github.io/img/chull-glitch/art4.jpg&#34;/&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Evaluating R code from potentially malicious sources Part 4</title>
      <link>https://coolbutuseless.github.io/2018/02/13/evaluating-r-code-from-potentially-malicious-sources-part-4/</link>
      <pubDate>Tue, 13 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/13/evaluating-r-code-from-potentially-malicious-sources-part-4/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;which-of-the-functions-from-the-base-r-package-would-you-let-a-malicious-user-run&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Which of the functions from the &lt;code&gt;base&lt;/code&gt; R package would you let a malicious user run?&lt;/h2&gt;
&lt;p&gt;There are 1301 functions in the &lt;code&gt;base&lt;/code&gt; package version 3.6.1.&lt;/p&gt;
&lt;p&gt;What functions would you want to prevent a malicious user from running?&lt;/p&gt;
&lt;p&gt;This post is going doing a (very rough) first pass over what’s in the &lt;code&gt;base&lt;/code&gt; package and do some (lazy, half-arsed!) classification of some
functions into &lt;strong&gt;safe(?)&lt;/strong&gt; and &lt;strong&gt;unsafe(?)&lt;/strong&gt;. Note the presence of the &lt;strong&gt;(?)&lt;/strong&gt; to indicate that I’m just roughing out some classifications here
and I’m not actually assuming any function is perfectly safe or unsafe!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;reasons-for-not-letting-someone-access-a-function&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Reasons for not letting someone access a function&lt;/h2&gt;
&lt;p&gt;I would like to restrict access to functions as I’d like to restrict access to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My resources
&lt;ul&gt;
&lt;li&gt;CPU&lt;/li&gt;
&lt;li&gt;RAM&lt;/li&gt;
&lt;li&gt;Filesystem&lt;/li&gt;
&lt;li&gt;Network&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;My information
&lt;ul&gt;
&lt;li&gt;Files&lt;/li&gt;
&lt;li&gt;Other objects in the R environment&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-access-the-system&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which access the system&lt;/h2&gt;
&lt;p&gt;Lots of functions to access the underlying system that R is running on. Most seem to have &lt;strong&gt;sys&lt;/strong&gt; in their name.
The key culprit is &lt;code&gt;system&lt;/code&gt; which is the holy grail of unsafe functions.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;sys_funcs &amp;lt;- grep(&amp;#39;(sys)&amp;#39;, base_funcs, ignore.case = TRUE, value = TRUE)
sys_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;.First.sys&amp;quot;       &amp;quot;R_system_version&amp;quot; &amp;quot;sys.call&amp;quot;         &amp;quot;sys.calls&amp;quot;       
 [5] &amp;quot;Sys.chmod&amp;quot;        &amp;quot;Sys.Date&amp;quot;         &amp;quot;sys.frame&amp;quot;        &amp;quot;sys.frames&amp;quot;      
 [9] &amp;quot;sys.function&amp;quot;     &amp;quot;Sys.getenv&amp;quot;       &amp;quot;Sys.getlocale&amp;quot;    &amp;quot;Sys.getpid&amp;quot;      
[13] &amp;quot;Sys.glob&amp;quot;         &amp;quot;Sys.info&amp;quot;         &amp;quot;sys.load.image&amp;quot;   &amp;quot;Sys.localeconv&amp;quot;  
[17] &amp;quot;sys.nframe&amp;quot;       &amp;quot;sys.on.exit&amp;quot;      &amp;quot;sys.parent&amp;quot;       &amp;quot;sys.parents&amp;quot;     
[21] &amp;quot;Sys.readlink&amp;quot;     &amp;quot;sys.save.image&amp;quot;   &amp;quot;Sys.setenv&amp;quot;       &amp;quot;Sys.setFileTime&amp;quot; 
[25] &amp;quot;Sys.setlocale&amp;quot;    &amp;quot;Sys.sleep&amp;quot;        &amp;quot;sys.source&amp;quot;       &amp;quot;sys.status&amp;quot;      
[29] &amp;quot;Sys.time&amp;quot;         &amp;quot;Sys.timezone&amp;quot;     &amp;quot;Sys.umask&amp;quot;        &amp;quot;Sys.unsetenv&amp;quot;    
[33] &amp;quot;Sys.which&amp;quot;        &amp;quot;system&amp;quot;           &amp;quot;system.file&amp;quot;      &amp;quot;system.time&amp;quot;     
[37] &amp;quot;system2&amp;quot;         &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-appear-to-access-the-filesystem-based-upon-their-name&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which appear to access the filesystem based upon their name&lt;/h2&gt;
&lt;p&gt;If the function name contains &lt;code&gt;file&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;write&lt;/code&gt; then you can be pretty sure it’s going to hit the filesystem.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;file_funcs &amp;lt;- grep(&amp;#39;(file|read|write|save|load|conn)&amp;#39;, base_funcs, ignore.case = TRUE, value = TRUE)
file_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;.readRDS&amp;quot;             &amp;quot;.saveRDS&amp;quot;             &amp;quot;autoload&amp;quot;            
 [4] &amp;quot;autoloader&amp;quot;           &amp;quot;bzfile&amp;quot;               &amp;quot;close.connection&amp;quot;    
 [7] &amp;quot;close.srcfile&amp;quot;        &amp;quot;close.srcfilealias&amp;quot;   &amp;quot;closeAllConnections&amp;quot; 
[10] &amp;quot;dyn.load&amp;quot;             &amp;quot;dyn.unload&amp;quot;           &amp;quot;env.profile&amp;quot;         
[13] &amp;quot;file&amp;quot;                 &amp;quot;file.access&amp;quot;          &amp;quot;file.append&amp;quot;         
[16] &amp;quot;file.choose&amp;quot;          &amp;quot;file.copy&amp;quot;            &amp;quot;file.create&amp;quot;         
[19] &amp;quot;file.exists&amp;quot;          &amp;quot;file.info&amp;quot;            &amp;quot;file.link&amp;quot;           
[22] &amp;quot;file.mode&amp;quot;            &amp;quot;file.mtime&amp;quot;           &amp;quot;file.path&amp;quot;           
[25] &amp;quot;file.remove&amp;quot;          &amp;quot;file.rename&amp;quot;          &amp;quot;file.show&amp;quot;           
[28] &amp;quot;file.size&amp;quot;            &amp;quot;file.symlink&amp;quot;         &amp;quot;flush.connection&amp;quot;    
[31] &amp;quot;getAllConnections&amp;quot;    &amp;quot;getConnection&amp;quot;        &amp;quot;getLoadedDLLs&amp;quot;       
[34] &amp;quot;gzfile&amp;quot;               &amp;quot;is.loaded&amp;quot;            &amp;quot;isNamespaceLoaded&amp;quot;   
[37] &amp;quot;lazyLoad&amp;quot;             &amp;quot;lazyLoadDBexec&amp;quot;       &amp;quot;lazyLoadDBfetch&amp;quot;     
[40] &amp;quot;library.dynam.unload&amp;quot; &amp;quot;list.files&amp;quot;           &amp;quot;load&amp;quot;                
[43] &amp;quot;loadedNamespaces&amp;quot;     &amp;quot;loadingNamespaceInfo&amp;quot; &amp;quot;loadNamespace&amp;quot;       
[46] &amp;quot;memory.profile&amp;quot;       &amp;quot;nullfile&amp;quot;             &amp;quot;open.connection&amp;quot;     
[49] &amp;quot;open.srcfile&amp;quot;         &amp;quot;open.srcfilealias&amp;quot;    &amp;quot;open.srcfilecopy&amp;quot;    
[52] &amp;quot;parseNamespaceFile&amp;quot;   &amp;quot;print.connection&amp;quot;     &amp;quot;print.srcfile&amp;quot;       
[55] &amp;quot;rawConnection&amp;quot;        &amp;quot;rawConnectionValue&amp;quot;   &amp;quot;read.dcf&amp;quot;            
[58] &amp;quot;readBin&amp;quot;              &amp;quot;readChar&amp;quot;             &amp;quot;readline&amp;quot;            
[61] &amp;quot;readLines&amp;quot;            &amp;quot;readRDS&amp;quot;              &amp;quot;readRenviron&amp;quot;        
[64] &amp;quot;save&amp;quot;                 &amp;quot;save.image&amp;quot;           &amp;quot;saveRDS&amp;quot;             
[67] &amp;quot;seek.connection&amp;quot;      &amp;quot;showConnections&amp;quot;      &amp;quot;socketConnection&amp;quot;    
[70] &amp;quot;srcfile&amp;quot;              &amp;quot;srcfilealias&amp;quot;         &amp;quot;srcfilecopy&amp;quot;         
[73] &amp;quot;summary.connection&amp;quot;   &amp;quot;summary.srcfile&amp;quot;      &amp;quot;sys.load.image&amp;quot;      
[76] &amp;quot;Sys.readlink&amp;quot;         &amp;quot;sys.save.image&amp;quot;       &amp;quot;Sys.setFileTime&amp;quot;     
[79] &amp;quot;system.file&amp;quot;          &amp;quot;tempfile&amp;quot;             &amp;quot;textConnection&amp;quot;      
[82] &amp;quot;textConnectionValue&amp;quot;  &amp;quot;truncate.connection&amp;quot;  &amp;quot;unloadNamespace&amp;quot;     
[85] &amp;quot;write&amp;quot;                &amp;quot;write.dcf&amp;quot;            &amp;quot;writeBin&amp;quot;            
[88] &amp;quot;writeChar&amp;quot;            &amp;quot;writeLines&amp;quot;           &amp;quot;xzfile&amp;quot;              &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-appear-to-access-the-filesystem-based-upon-their-arguments&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which appear to access the filesystem based upon their arguments&lt;/h2&gt;
&lt;p&gt;There are also functions which take a filename or a connection, which means they also access
the filesystem.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;file2_funcs &amp;lt;- formal_arg_names %&amp;gt;% 
  keep(~any(c(&amp;#39;file&amp;#39;, &amp;#39;filename&amp;#39;, &amp;#39;open&amp;#39;, &amp;#39;con&amp;#39;) %in% .x)) %&amp;gt;%
  names()

file2_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;.getRequiredPackages&amp;quot; &amp;quot;bzfile&amp;quot;               &amp;quot;cat&amp;quot;                 
 [4] &amp;quot;close&amp;quot;                &amp;quot;close.connection&amp;quot;     &amp;quot;close.srcfile&amp;quot;       
 [7] &amp;quot;close.srcfilealias&amp;quot;   &amp;quot;dget&amp;quot;                 &amp;quot;dput&amp;quot;                
[10] &amp;quot;dump&amp;quot;                 &amp;quot;fifo&amp;quot;                 &amp;quot;file&amp;quot;                
[13] &amp;quot;flush&amp;quot;                &amp;quot;flush.connection&amp;quot;     &amp;quot;gzcon&amp;quot;               
[16] &amp;quot;gzfile&amp;quot;               &amp;quot;isatty&amp;quot;               &amp;quot;isIncomplete&amp;quot;        
[19] &amp;quot;isOpen&amp;quot;               &amp;quot;isSeekable&amp;quot;           &amp;quot;load&amp;quot;                
[22] &amp;quot;open&amp;quot;                 &amp;quot;open.connection&amp;quot;      &amp;quot;open.srcfile&amp;quot;        
[25] &amp;quot;open.srcfilealias&amp;quot;    &amp;quot;open.srcfilecopy&amp;quot;     &amp;quot;parse&amp;quot;               
[28] &amp;quot;pipe&amp;quot;                 &amp;quot;rawConnection&amp;quot;        &amp;quot;rawConnectionValue&amp;quot;  
[31] &amp;quot;read.dcf&amp;quot;             &amp;quot;readBin&amp;quot;              &amp;quot;readChar&amp;quot;            
[34] &amp;quot;readLines&amp;quot;            &amp;quot;readRDS&amp;quot;              &amp;quot;save&amp;quot;                
[37] &amp;quot;save.image&amp;quot;           &amp;quot;saveRDS&amp;quot;              &amp;quot;scan&amp;quot;                
[40] &amp;quot;seek&amp;quot;                 &amp;quot;seek.connection&amp;quot;      &amp;quot;sink&amp;quot;                
[43] &amp;quot;socketConnection&amp;quot;     &amp;quot;source&amp;quot;               &amp;quot;srcfile&amp;quot;             
[46] &amp;quot;srcfilealias&amp;quot;         &amp;quot;srcfilecopy&amp;quot;          &amp;quot;sys.source&amp;quot;          
[49] &amp;quot;textConnection&amp;quot;       &amp;quot;textConnectionValue&amp;quot;  &amp;quot;truncate&amp;quot;            
[52] &amp;quot;truncate.connection&amp;quot;  &amp;quot;unz&amp;quot;                  &amp;quot;url&amp;quot;                 
[55] &amp;quot;write&amp;quot;                &amp;quot;write.dcf&amp;quot;            &amp;quot;writeBin&amp;quot;            
[58] &amp;quot;writeChar&amp;quot;            &amp;quot;writeLines&amp;quot;           &amp;quot;xzfile&amp;quot;              &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-appear-to-access-package-internals-based-upon-their-arguments&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which appear to access package internals based upon their arguments&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;internal_funcs &amp;lt;- formal_arg_names %&amp;gt;% 
  keep(~any(c(&amp;#39;package&amp;#39;, &amp;#39;lib.loc&amp;#39;, &amp;#39;useImports&amp;#39;, &amp;#39;handlers&amp;#39;) %in% .x)) %&amp;gt;%
  names()
internal_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;.Defunct&amp;quot;              &amp;quot;.Deprecated&amp;quot;           &amp;quot;.getRequiredPackages&amp;quot; 
 [4] &amp;quot;.getRequiredPackages2&amp;quot; &amp;quot;.packages&amp;quot;             &amp;quot;autoload&amp;quot;             
 [7] &amp;quot;autoloader&amp;quot;            &amp;quot;find.package&amp;quot;          &amp;quot;library&amp;quot;              
[10] &amp;quot;library.dynam&amp;quot;         &amp;quot;loadNamespace&amp;quot;         &amp;quot;packageHasNamespace&amp;quot;  
[13] &amp;quot;packageNotFoundError&amp;quot;  &amp;quot;parseNamespaceFile&amp;quot;    &amp;quot;path.package&amp;quot;         
[16] &amp;quot;registerS3methods&amp;quot;     &amp;quot;require&amp;quot;               &amp;quot;requireNamespace&amp;quot;     
[19] &amp;quot;system.file&amp;quot;           &amp;quot;taskCallbackManager&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-appear-to-access-r-internals-based-upon-their-name&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which appear to access R internals based upon their name&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;internal2_funcs &amp;lt;- grep(&amp;#39;(gc)&amp;#39;, base_funcs, ignore.case = TRUE, value = TRUE)
internal2_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;gc&amp;quot;               &amp;quot;gc.time&amp;quot;          &amp;quot;gcinfo&amp;quot;           &amp;quot;gctorture&amp;quot;       
[5] &amp;quot;gctorture2&amp;quot;       &amp;quot;warningCondition&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-change-the-global-state.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which change the global state.&lt;/h2&gt;
&lt;p&gt;An example of a function which can change global state even when evaluated within a restricted environment is &lt;code&gt;graphcis::par&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I haven’t gone looking in the &lt;code&gt;base&lt;/code&gt; package for similar.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;unsafe-functions-those-which-start-with-a-.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Unsafe(?) functions: Those which start with a &lt;code&gt;.&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I have no idea what most of these are for!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dot_funcs &amp;lt;- grep(&amp;#39;^\\.&amp;#39;, base_funcs, ignore.case = TRUE, value = TRUE)
dot_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;.__H__.cbind&amp;quot;            &amp;quot;.__H__.rbind&amp;quot;           
 [3] &amp;quot;...elt&amp;quot;                  &amp;quot;...length&amp;quot;              
 [5] &amp;quot;..getNamespace&amp;quot;          &amp;quot;.amatch_bounds&amp;quot;         
 [7] &amp;quot;.amatch_costs&amp;quot;           &amp;quot;.bincode&amp;quot;               
 [9] &amp;quot;.C&amp;quot;                      &amp;quot;.cache_class&amp;quot;           
[11] &amp;quot;.Call&amp;quot;                   &amp;quot;.Call.graphics&amp;quot;         
[13] &amp;quot;.col&amp;quot;                    &amp;quot;.colMeans&amp;quot;              
[15] &amp;quot;.colSums&amp;quot;                &amp;quot;.Date&amp;quot;                  
[17] &amp;quot;.decode_numeric_version&amp;quot; &amp;quot;.Defunct&amp;quot;               
[19] &amp;quot;.deparseOpts&amp;quot;            &amp;quot;.Deprecated&amp;quot;            
[21] &amp;quot;.detach&amp;quot;                 &amp;quot;.difftime&amp;quot;              
[23] &amp;quot;.doSortWrap&amp;quot;             &amp;quot;.doTrace&amp;quot;               
[25] &amp;quot;.doWrap&amp;quot;                 &amp;quot;.dynLibs&amp;quot;               
[27] &amp;quot;.encode_numeric_version&amp;quot; &amp;quot;.expand_R_libs_env_var&amp;quot; 
[29] &amp;quot;.External&amp;quot;               &amp;quot;.External.graphics&amp;quot;     
[31] &amp;quot;.External2&amp;quot;              &amp;quot;.find.package&amp;quot;          
[33] &amp;quot;.First.sys&amp;quot;              &amp;quot;.format.zeros&amp;quot;          
[35] &amp;quot;.Fortran&amp;quot;                &amp;quot;.getNamespace&amp;quot;          
[37] &amp;quot;.getNamespaceInfo&amp;quot;       &amp;quot;.getRequiredPackages&amp;quot;   
[39] &amp;quot;.getRequiredPackages2&amp;quot;   &amp;quot;.gt&amp;quot;                    
[41] &amp;quot;.gtn&amp;quot;                    &amp;quot;.handleSimpleError&amp;quot;     
[43] &amp;quot;.Internal&amp;quot;               &amp;quot;.isMethodsDispatchOn&amp;quot;   
[45] &amp;quot;.isOpen&amp;quot;                 &amp;quot;.kappa_tri&amp;quot;             
[47] &amp;quot;.kronecker&amp;quot;              &amp;quot;.libPaths&amp;quot;              
[49] &amp;quot;.make_numeric_version&amp;quot;   &amp;quot;.makeMessage&amp;quot;           
[51] &amp;quot;.mapply&amp;quot;                 &amp;quot;.maskedMsg&amp;quot;             
[53] &amp;quot;.mergeExportMethods&amp;quot;     &amp;quot;.mergeImportMethods&amp;quot;    
[55] &amp;quot;.NotYetImplemented&amp;quot;      &amp;quot;.NotYetUsed&amp;quot;            
[57] &amp;quot;.OptRequireMethods&amp;quot;      &amp;quot;.packages&amp;quot;              
[59] &amp;quot;.packageStartupMessage&amp;quot;  &amp;quot;.path.package&amp;quot;          
[61] &amp;quot;.POSIXct&amp;quot;                &amp;quot;.POSIXlt&amp;quot;               
[63] &amp;quot;.Primitive&amp;quot;              &amp;quot;.primTrace&amp;quot;             
[65] &amp;quot;.primUntrace&amp;quot;            &amp;quot;.readRDS&amp;quot;               
[67] &amp;quot;.rmpkg&amp;quot;                  &amp;quot;.row&amp;quot;                   
[69] &amp;quot;.row_names_info&amp;quot;         &amp;quot;.rowMeans&amp;quot;              
[71] &amp;quot;.rowNamesDF&amp;lt;-&amp;quot;           &amp;quot;.rowSums&amp;quot;               
[73] &amp;quot;.saveRDS&amp;quot;                &amp;quot;.Script&amp;quot;                
[75] &amp;quot;.set_row_names&amp;quot;          &amp;quot;.signalSimpleWarning&amp;quot;   
[77] &amp;quot;.standard_regexps&amp;quot;       &amp;quot;.subset&amp;quot;                
[79] &amp;quot;.subset2&amp;quot;                &amp;quot;.TAOCP1997init&amp;quot;         
[81] &amp;quot;.traceback&amp;quot;              &amp;quot;.tryResumeInterrupt&amp;quot;    
[83] &amp;quot;.valid.factor&amp;quot;          &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;whats-left&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What’s left?&lt;/h2&gt;
&lt;p&gt;After this triage of ‘unsafe’ funcs, there’s still over 1061 functions still to go!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;safe-functions-as.-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Safe(?) functions: &lt;code&gt;as.*&lt;/code&gt; functions&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;as_funcs &amp;lt;- grep(&amp;#39;^as\\.&amp;#39;, leftover_funcs, ignore.case = TRUE, value = TRUE)
as_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;  [1] &amp;quot;as.array&amp;quot;                      &amp;quot;as.array.default&amp;quot;             
  [3] &amp;quot;as.call&amp;quot;                       &amp;quot;as.character&amp;quot;                 
  [5] &amp;quot;as.character.condition&amp;quot;        &amp;quot;as.character.Date&amp;quot;            
  [7] &amp;quot;as.character.default&amp;quot;          &amp;quot;as.character.error&amp;quot;           
  [9] &amp;quot;as.character.factor&amp;quot;           &amp;quot;as.character.hexmode&amp;quot;         
 [11] &amp;quot;as.character.numeric_version&amp;quot;  &amp;quot;as.character.octmode&amp;quot;         
 [13] &amp;quot;as.character.POSIXt&amp;quot;           &amp;quot;as.character.srcref&amp;quot;          
 [15] &amp;quot;as.complex&amp;quot;                    &amp;quot;as.data.frame&amp;quot;                
 [17] &amp;quot;as.data.frame.array&amp;quot;           &amp;quot;as.data.frame.AsIs&amp;quot;           
 [19] &amp;quot;as.data.frame.character&amp;quot;       &amp;quot;as.data.frame.complex&amp;quot;        
 [21] &amp;quot;as.data.frame.data.frame&amp;quot;      &amp;quot;as.data.frame.Date&amp;quot;           
 [23] &amp;quot;as.data.frame.default&amp;quot;         &amp;quot;as.data.frame.difftime&amp;quot;       
 [25] &amp;quot;as.data.frame.factor&amp;quot;          &amp;quot;as.data.frame.integer&amp;quot;        
 [27] &amp;quot;as.data.frame.list&amp;quot;            &amp;quot;as.data.frame.logical&amp;quot;        
 [29] &amp;quot;as.data.frame.matrix&amp;quot;          &amp;quot;as.data.frame.model.matrix&amp;quot;   
 [31] &amp;quot;as.data.frame.noquote&amp;quot;         &amp;quot;as.data.frame.numeric&amp;quot;        
 [33] &amp;quot;as.data.frame.numeric_version&amp;quot; &amp;quot;as.data.frame.ordered&amp;quot;        
 [35] &amp;quot;as.data.frame.POSIXct&amp;quot;         &amp;quot;as.data.frame.POSIXlt&amp;quot;        
 [37] &amp;quot;as.data.frame.raw&amp;quot;             &amp;quot;as.data.frame.table&amp;quot;          
 [39] &amp;quot;as.data.frame.ts&amp;quot;              &amp;quot;as.data.frame.vector&amp;quot;         
 [41] &amp;quot;as.Date&amp;quot;                       &amp;quot;as.Date.character&amp;quot;            
 [43] &amp;quot;as.Date.default&amp;quot;               &amp;quot;as.Date.factor&amp;quot;               
 [45] &amp;quot;as.Date.numeric&amp;quot;               &amp;quot;as.Date.POSIXct&amp;quot;              
 [47] &amp;quot;as.Date.POSIXlt&amp;quot;               &amp;quot;as.difftime&amp;quot;                  
 [49] &amp;quot;as.double&amp;quot;                     &amp;quot;as.double.difftime&amp;quot;           
 [51] &amp;quot;as.double.POSIXlt&amp;quot;             &amp;quot;as.environment&amp;quot;               
 [53] &amp;quot;as.expression&amp;quot;                 &amp;quot;as.expression.default&amp;quot;        
 [55] &amp;quot;as.factor&amp;quot;                     &amp;quot;as.function&amp;quot;                  
 [57] &amp;quot;as.function.default&amp;quot;           &amp;quot;as.hexmode&amp;quot;                   
 [59] &amp;quot;as.integer&amp;quot;                    &amp;quot;as.list&amp;quot;                      
 [61] &amp;quot;as.list.data.frame&amp;quot;            &amp;quot;as.list.Date&amp;quot;                 
 [63] &amp;quot;as.list.default&amp;quot;               &amp;quot;as.list.environment&amp;quot;          
 [65] &amp;quot;as.list.factor&amp;quot;                &amp;quot;as.list.function&amp;quot;             
 [67] &amp;quot;as.list.numeric_version&amp;quot;       &amp;quot;as.list.POSIXct&amp;quot;              
 [69] &amp;quot;as.list.POSIXlt&amp;quot;               &amp;quot;as.logical&amp;quot;                   
 [71] &amp;quot;as.logical.factor&amp;quot;             &amp;quot;as.matrix&amp;quot;                    
 [73] &amp;quot;as.matrix.data.frame&amp;quot;          &amp;quot;as.matrix.default&amp;quot;            
 [75] &amp;quot;as.matrix.noquote&amp;quot;             &amp;quot;as.matrix.POSIXlt&amp;quot;            
 [77] &amp;quot;as.name&amp;quot;                       &amp;quot;as.null&amp;quot;                      
 [79] &amp;quot;as.null.default&amp;quot;               &amp;quot;as.numeric&amp;quot;                   
 [81] &amp;quot;as.numeric_version&amp;quot;            &amp;quot;as.octmode&amp;quot;                   
 [83] &amp;quot;as.ordered&amp;quot;                    &amp;quot;as.package_version&amp;quot;           
 [85] &amp;quot;as.pairlist&amp;quot;                   &amp;quot;as.POSIXct&amp;quot;                   
 [87] &amp;quot;as.POSIXct.Date&amp;quot;               &amp;quot;as.POSIXct.default&amp;quot;           
 [89] &amp;quot;as.POSIXct.numeric&amp;quot;            &amp;quot;as.POSIXct.POSIXlt&amp;quot;           
 [91] &amp;quot;as.POSIXlt&amp;quot;                    &amp;quot;as.POSIXlt.character&amp;quot;         
 [93] &amp;quot;as.POSIXlt.Date&amp;quot;               &amp;quot;as.POSIXlt.default&amp;quot;           
 [95] &amp;quot;as.POSIXlt.factor&amp;quot;             &amp;quot;as.POSIXlt.numeric&amp;quot;           
 [97] &amp;quot;as.POSIXlt.POSIXct&amp;quot;            &amp;quot;as.qr&amp;quot;                        
 [99] &amp;quot;as.raw&amp;quot;                        &amp;quot;as.single&amp;quot;                    
[101] &amp;quot;as.single.default&amp;quot;             &amp;quot;as.symbol&amp;quot;                    
[103] &amp;quot;as.table&amp;quot;                      &amp;quot;as.table.default&amp;quot;             
[105] &amp;quot;as.vector&amp;quot;                     &amp;quot;as.vector.factor&amp;quot;             &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;safe-functions-apply-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Safe(?) functions: &lt;code&gt;*apply&lt;/code&gt; functions&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;apply_funcs &amp;lt;- grep(&amp;#39;apply&amp;#39;, leftover_funcs, ignore.case = TRUE, value = TRUE)
apply_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;apply&amp;quot;  &amp;quot;eapply&amp;quot; &amp;quot;lapply&amp;quot; &amp;quot;mapply&amp;quot; &amp;quot;rapply&amp;quot; &amp;quot;sapply&amp;quot; &amp;quot;tapply&amp;quot; &amp;quot;vapply&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;safe-functions-print.-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Safe(?) functions: &lt;code&gt;print.*&lt;/code&gt; functions&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;print_funcs &amp;lt;- grep(&amp;#39;^print&amp;#39;, leftover_funcs, ignore.case = TRUE, value = TRUE)
print_funcs&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;print&amp;quot;                       &amp;quot;print.AsIs&amp;quot;                 
 [3] &amp;quot;print.by&amp;quot;                    &amp;quot;print.condition&amp;quot;            
 [5] &amp;quot;print.data.frame&amp;quot;            &amp;quot;print.Date&amp;quot;                 
 [7] &amp;quot;print.default&amp;quot;               &amp;quot;print.difftime&amp;quot;             
 [9] &amp;quot;print.Dlist&amp;quot;                 &amp;quot;print.DLLInfo&amp;quot;              
[11] &amp;quot;print.DLLInfoList&amp;quot;           &amp;quot;print.DLLRegisteredRoutines&amp;quot;
[13] &amp;quot;print.eigen&amp;quot;                 &amp;quot;print.factor&amp;quot;               
[15] &amp;quot;print.function&amp;quot;              &amp;quot;print.hexmode&amp;quot;              
[17] &amp;quot;print.libraryIQR&amp;quot;            &amp;quot;print.listof&amp;quot;               
[19] &amp;quot;print.NativeRoutineList&amp;quot;     &amp;quot;print.noquote&amp;quot;              
[21] &amp;quot;print.numeric_version&amp;quot;       &amp;quot;print.octmode&amp;quot;              
[23] &amp;quot;print.packageInfo&amp;quot;           &amp;quot;print.POSIXct&amp;quot;              
[25] &amp;quot;print.POSIXlt&amp;quot;               &amp;quot;print.proc_time&amp;quot;            
[27] &amp;quot;print.restart&amp;quot;               &amp;quot;print.rle&amp;quot;                  
[29] &amp;quot;print.simple.list&amp;quot;           &amp;quot;print.srcref&amp;quot;               
[31] &amp;quot;print.summary.table&amp;quot;         &amp;quot;print.summary.warnings&amp;quot;     
[33] &amp;quot;print.summaryDefault&amp;quot;        &amp;quot;print.table&amp;quot;                
[35] &amp;quot;print.warnings&amp;quot;             &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;assign-funcs&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;assign funcs&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;[[&amp;lt;-&amp;quot;                    &amp;quot;[[&amp;lt;-.data.frame&amp;quot;        
 [3] &amp;quot;[[&amp;lt;-.factor&amp;quot;             &amp;quot;[[&amp;lt;-.numeric_version&amp;quot;   
 [5] &amp;quot;[[&amp;lt;-.POSIXlt&amp;quot;            &amp;quot;[&amp;lt;-&amp;quot;                    
 [7] &amp;quot;[&amp;lt;-.data.frame&amp;quot;          &amp;quot;[&amp;lt;-.Date&amp;quot;               
 [9] &amp;quot;[&amp;lt;-.factor&amp;quot;              &amp;quot;[&amp;lt;-.numeric_version&amp;quot;    
[11] &amp;quot;[&amp;lt;-.POSIXct&amp;quot;             &amp;quot;[&amp;lt;-.POSIXlt&amp;quot;            
[13] &amp;quot;@&amp;lt;-&amp;quot;                     &amp;quot;&amp;lt;-&amp;quot;                     
[15] &amp;quot;&amp;lt;&amp;lt;-&amp;quot;                     &amp;quot;$&amp;lt;-&amp;quot;                    
[17] &amp;quot;$&amp;lt;-.data.frame&amp;quot;          &amp;quot;attr&amp;lt;-&amp;quot;                 
[19] &amp;quot;attributes&amp;lt;-&amp;quot;            &amp;quot;body&amp;lt;-&amp;quot;                 
[21] &amp;quot;class&amp;lt;-&amp;quot;                 &amp;quot;colnames&amp;lt;-&amp;quot;             
[23] &amp;quot;comment&amp;lt;-&amp;quot;               &amp;quot;diag&amp;lt;-&amp;quot;                 
[25] &amp;quot;dim&amp;lt;-&amp;quot;                   &amp;quot;dimnames&amp;lt;-&amp;quot;             
[27] &amp;quot;dimnames&amp;lt;-.data.frame&amp;quot;   &amp;quot;Encoding&amp;lt;-&amp;quot;             
[29] &amp;quot;environment&amp;lt;-&amp;quot;           &amp;quot;formals&amp;lt;-&amp;quot;              
[31] &amp;quot;is.na&amp;lt;-&amp;quot;                 &amp;quot;is.na&amp;lt;-.default&amp;quot;        
[33] &amp;quot;is.na&amp;lt;-.factor&amp;quot;          &amp;quot;is.na&amp;lt;-.numeric_version&amp;quot;
[35] &amp;quot;length&amp;lt;-&amp;quot;                &amp;quot;length&amp;lt;-.Date&amp;quot;          
[37] &amp;quot;length&amp;lt;-.difftime&amp;quot;       &amp;quot;length&amp;lt;-.factor&amp;quot;        
[39] &amp;quot;length&amp;lt;-.POSIXct&amp;quot;        &amp;quot;length&amp;lt;-.POSIXlt&amp;quot;       
[41] &amp;quot;levels&amp;lt;-&amp;quot;                &amp;quot;levels&amp;lt;-.factor&amp;quot;        
[43] &amp;quot;mode&amp;lt;-&amp;quot;                  &amp;quot;mostattributes&amp;lt;-&amp;quot;       
[45] &amp;quot;names&amp;lt;-&amp;quot;                 &amp;quot;names&amp;lt;-.POSIXlt&amp;quot;        
[47] &amp;quot;oldClass&amp;lt;-&amp;quot;              &amp;quot;parent.env&amp;lt;-&amp;quot;           
[49] &amp;quot;regmatches&amp;lt;-&amp;quot;            &amp;quot;row.names&amp;lt;-&amp;quot;            
[51] &amp;quot;row.names&amp;lt;-.data.frame&amp;quot;  &amp;quot;row.names&amp;lt;-.default&amp;quot;    
[53] &amp;quot;rownames&amp;lt;-&amp;quot;              &amp;quot;split&amp;lt;-&amp;quot;                
[55] &amp;quot;split&amp;lt;-.data.frame&amp;quot;      &amp;quot;split&amp;lt;-.default&amp;quot;        
[57] &amp;quot;storage.mode&amp;lt;-&amp;quot;          &amp;quot;substr&amp;lt;-&amp;quot;               
[59] &amp;quot;substring&amp;lt;-&amp;quot;             &amp;quot;units&amp;lt;-&amp;quot;                
[61] &amp;quot;units&amp;lt;-.difftime&amp;quot;       &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;non-alpha-funcs&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Non-alpha funcs&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt; [1] &amp;quot;-&amp;quot;                  &amp;quot;-.Date&amp;quot;             &amp;quot;-.POSIXt&amp;quot;          
 [4] &amp;quot;:&amp;quot;                  &amp;quot;::&amp;quot;                 &amp;quot;:::&amp;quot;               
 [7] &amp;quot;!&amp;quot;                  &amp;quot;!.hexmode&amp;quot;          &amp;quot;!.octmode&amp;quot;         
[10] &amp;quot;!=&amp;quot;                 &amp;quot;(&amp;quot;                  &amp;quot;[&amp;quot;                 
[13] &amp;quot;[.AsIs&amp;quot;             &amp;quot;[.data.frame&amp;quot;       &amp;quot;[.Date&amp;quot;            
[16] &amp;quot;[.difftime&amp;quot;         &amp;quot;[.Dlist&amp;quot;            &amp;quot;[.DLLInfoList&amp;quot;     
[19] &amp;quot;[.factor&amp;quot;           &amp;quot;[.hexmode&amp;quot;          &amp;quot;[.listof&amp;quot;          
[22] &amp;quot;[.noquote&amp;quot;          &amp;quot;[.numeric_version&amp;quot;  &amp;quot;[.octmode&amp;quot;         
[25] &amp;quot;[.POSIXct&amp;quot;          &amp;quot;[.POSIXlt&amp;quot;          &amp;quot;[.simple.list&amp;quot;     
[28] &amp;quot;[.table&amp;quot;            &amp;quot;[.warnings&amp;quot;         &amp;quot;[[&amp;quot;                
[31] &amp;quot;[[.data.frame&amp;quot;      &amp;quot;[[.Date&amp;quot;            &amp;quot;[[.factor&amp;quot;         
[34] &amp;quot;[[.numeric_version&amp;quot; &amp;quot;[[.POSIXct&amp;quot;         &amp;quot;[[.POSIXlt&amp;quot;        
[37] &amp;quot;{&amp;quot;                  &amp;quot;@&amp;quot;                  &amp;quot;*&amp;quot;                 
[40] &amp;quot;*.difftime&amp;quot;         &amp;quot;/&amp;quot;                  &amp;quot;/.difftime&amp;quot;        
[43] &amp;quot;&amp;amp;&amp;quot;                  &amp;quot;&amp;amp;.hexmode&amp;quot;          &amp;quot;&amp;amp;.octmode&amp;quot;         
[46] &amp;quot;&amp;amp;&amp;amp;&amp;quot;                 &amp;quot;%*%&amp;quot;                &amp;quot;%/%&amp;quot;               
[49] &amp;quot;%%&amp;quot;                 &amp;quot;%in%&amp;quot;               &amp;quot;%o%&amp;quot;               
[52] &amp;quot;%x%&amp;quot;                &amp;quot;^&amp;quot;                  &amp;quot;+&amp;quot;                 
[55] &amp;quot;+.Date&amp;quot;             &amp;quot;+.POSIXt&amp;quot;           &amp;quot;&amp;lt;&amp;quot;                 
[58] &amp;quot;&amp;lt;=&amp;quot;                 &amp;quot;=&amp;quot;                  &amp;quot;==&amp;quot;                
[61] &amp;quot;&amp;gt;&amp;quot;                  &amp;quot;&amp;gt;=&amp;quot;                 &amp;quot;|&amp;quot;                 
[64] &amp;quot;|.hexmode&amp;quot;          &amp;quot;|.octmode&amp;quot;          &amp;quot;||&amp;quot;                
[67] &amp;quot;~&amp;quot;                  &amp;quot;$&amp;quot;                  &amp;quot;$.DLLInfo&amp;quot;         
[70] &amp;quot;$.package_version&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;functions-which-seem-safe&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Functions which seem safe(?)&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;math_funcs &amp;lt;- c(&amp;#39;sin&amp;#39;, &amp;#39;cos&amp;#39;, &amp;#39;tan&amp;#39;, 
                &amp;#39;acos&amp;#39;, &amp;#39;asin&amp;#39;, &amp;#39;atan&amp;#39;, &amp;#39;atan2&amp;#39;,
                &amp;#39;sinpi&amp;#39;, &amp;#39;cospi&amp;#39;, &amp;#39;tanpi&amp;#39;,
                &amp;#39;exp&amp;#39;, &amp;#39;expm1&amp;#39;, 
                &amp;#39;log&amp;#39;, &amp;#39;logb&amp;#39;, &amp;#39;log10&amp;#39;, &amp;#39;log2&amp;#39;)

object_funcs &amp;lt;- c(&amp;#39;logical&amp;#39;, &amp;#39;as.logical&amp;#39;, &amp;#39;is.logical&amp;#39;, 
                  &amp;#39;integer&amp;#39;, &amp;#39;as.integer&amp;#39;, &amp;#39;is.integer&amp;#39;, 
                  &amp;#39;numeric&amp;#39;, &amp;#39;as.numeric&amp;#39;, &amp;#39;is.numeric&amp;#39;, 
                  &amp;#39;double&amp;#39; , &amp;#39;as.double&amp;#39; , &amp;#39;is.double&amp;#39; ,
                  &amp;#39;single&amp;#39; , &amp;#39;as.single&amp;#39; , &amp;#39;is.single&amp;#39;, 
                  &amp;#39;complex&amp;#39;, &amp;#39;as.complex&amp;#39;, &amp;#39;is.complex&amp;#39;,
                  &amp;#39;structure&amp;#39;, 
                  &amp;#39;c&amp;#39;, &amp;#39;list&amp;#39;, &amp;#39;data.frame&amp;#39;, &amp;#39;complex&amp;#39;)

complex_funcs &amp;lt;- c(&amp;#39;Re&amp;#39;, &amp;#39;Im&amp;#39;, &amp;#39;Mod&amp;#39;, &amp;#39;Arg&amp;#39;, &amp;#39;Conj&amp;#39;)

seq_funcs &amp;lt;- c(&amp;#39;:&amp;#39;, &amp;#39;seq&amp;#39;, &amp;#39;seq.int&amp;#39;, &amp;#39;seq_along&amp;#39;, &amp;#39;seq_len&amp;#39;)


plot_funcs &amp;lt;- c(&amp;#39;plot&amp;#39;, &amp;#39;points&amp;#39;, &amp;#39;lines&amp;#39;, &amp;#39;title&amp;#39;, &amp;#39;legend&amp;#39;, &amp;#39;points.formula&amp;#39;)

flow_control_funcs &amp;lt;- c(&amp;#39;if&amp;#39;, &amp;#39;for&amp;#39;, &amp;#39;while&amp;#39;, &amp;#39;repeat&amp;#39;, &amp;#39;break&amp;#39;, &amp;#39;next&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So many functions. So many ways for a malicious user to abuse the system.&lt;/p&gt;
&lt;p&gt;And this was only the &lt;code&gt;base&lt;/code&gt; package!&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-sandboxrs-list-of-blacklisted-functions-from-base&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Appendix: &lt;code&gt;sandboxr&lt;/code&gt;’s list of blacklisted functions from &lt;code&gt;base&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;For comparison, the &lt;code&gt;sandboxR&lt;/code&gt; package contains some blacklists for various core R packages.&lt;/p&gt;
&lt;p&gt;Here is its &lt;a href=&#34;https://github.com/Rapporter/sandboxR/blob/r-3.0.0/R/blacklist.R&#34;&gt;list of functions it blacklists from the base package&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Part 3: Evaluating R code from potentially malicious sources</title>
      <link>https://coolbutuseless.github.io/2018/02/12/part-3-evaluating-r-code-from-potentially-malicious-sources/</link>
      <pubDate>Mon, 12 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/12/part-3-evaluating-r-code-from-potentially-malicious-sources/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;tldr-shiny-app&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;TLDR: Shiny app&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://coolbutuseless.shinyapps.io/shiny-safe-eval/&#34;&gt;Shiny app using safe(?) evalation of R code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please try and tell me if you break it or make it do something unsafe …&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;evaluating-r-code-from-potentially-malicious-sources---part-3&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Evaluating R code from potentially malicious sources - part 3&lt;/h2&gt;
&lt;p&gt;As mentioned in
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/10/evaluating-r-code-from-potentially-malicious-sources/&#34;&gt;Part 1&lt;/a&gt;, and
&lt;a href=&#34;https://coolbutuseless.github.io/2018/02/11/evaluating-r-code-from-potentially-malicious-sources-part-2/&#34;&gt;Part 2&lt;/a&gt;
I’m looking into the idea of running R code which may originate from potentially malicious sources e.g. 
code from a web interface, or a database or even a tweet!&lt;/p&gt;
&lt;p&gt;My most recent idea to safely execute code is to:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create an empty environment&lt;/li&gt;
&lt;li&gt;Copy the whitelisted functions into it
&lt;ul&gt;
&lt;li&gt;Lots of control available here e.g. you could whitelist &lt;code&gt;mean&lt;/code&gt; and &lt;code&gt;mean.default&lt;/code&gt; but not
include &lt;code&gt;mean.difftime&lt;/code&gt; so that ordinary numeric means are possible, but not of difftime objects&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Do all evaluation within this environment - any calls to non-whitelisted functions will cause an error&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this post I want to describe the following:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;What is the purpose/context of executing this (potentially malicious) code?&lt;/li&gt;
&lt;li&gt;What does it mean to be ‘safe’?&lt;/li&gt;
&lt;li&gt;What functions can/can’t be whitelisted?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I know this is dangerous and quite probably a fool’s quest.&lt;/li&gt;
&lt;li&gt;I want to run this in the current process and use the result i.e. no remote sandboxes or docker images.&lt;/li&gt;
&lt;li&gt;If this is impossible, or there’s an actual way to do this, or a better way of thinking of the problem, I’m keen to hear it!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ping me on &lt;a href=&#34;http://www.twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;context-of-running-possibly-malicious-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Context of running (possibly malicious) code&lt;/h2&gt;
&lt;p&gt;Broadly speaking the code to be run is either:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;The entire language.
&lt;ul&gt;
&lt;li&gt;No language restrictions&lt;/li&gt;
&lt;li&gt;Limited access to filesystem and other system resources e.g. &lt;a href=&#34;https://cran.r-project.org/web/packages/RAppArmor/index.html&#34;&gt;RAppArmor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Some useful subset of the language
&lt;ul&gt;
&lt;li&gt;Access to only the necessary approved (whitelisted) functions&lt;/li&gt;
&lt;li&gt;No restrictions on the environment in which the R interpreter itself runs&lt;/li&gt;
&lt;li&gt;Restriction of access to system resources is by including/excluding functions in the whitelist. i.e. If you do not wish to grant file
reading, then don’t include any functions that the user could direct to read a file.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you are looking to safely evaluate the entire R language in a safe environment, then &lt;a href=&#34;https://cran.r-project.org/web/packages/RAppArmor/index.html&#34;&gt;RAppArmor&lt;/a&gt;
is definitely where you should be reading, not here :)&lt;/p&gt;
&lt;p&gt;I am interested in useful subsets of the language for specific purposes. The current use case that sparked this quest is to: &lt;strong&gt;Allow only the &lt;em&gt;creation&lt;/em&gt; of R objects e.g. scalars, vectors, lists and data.frames&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This arose out of my desire to serialise/deserialise R objects to YAML (as discussed &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/07/yaml-vs-jsonlite-vs-rjsonio/&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-does-it-mean-to-be-safe-in-this-context&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What does it mean to be ‘safe’ in this context?&lt;/h2&gt;
&lt;p&gt;The specific purpose for safe evaluation is that I want to &lt;strong&gt;Allow only the &lt;em&gt;creation&lt;/em&gt; of R objects e.g. scalars, vectors, lists and data.frames&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Wanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User should be able to create an object&lt;/li&gt;
&lt;li&gt;Nothing else&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unwanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calculations&lt;/li&gt;
&lt;li&gt;Assigning variables&lt;/li&gt;
&lt;li&gt;System calls&lt;/li&gt;
&lt;li&gt;Excessive CPU usage&lt;/li&gt;
&lt;li&gt;Excessive memory usage&lt;/li&gt;
&lt;li&gt;Access to filesystem, network, keyboard etc.&lt;/li&gt;
&lt;li&gt;Pretty much everything else&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;what-functions-can-be-whitelisted-what-functions-cant&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What functions can be whitelisted? What functions can’t?&lt;/h2&gt;
&lt;p&gt;An actual dive into what functions are, in general, safe for a malicious user to run will have to wait for another post (sorry!).&lt;/p&gt;
&lt;p&gt;For this very simple case of only allowing for the creation of objects the whitelist is quite small&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;whitelist &amp;lt;- c(
  &amp;#39;structure&amp;#39;,
  &amp;#39;c&amp;#39;, 
  &amp;#39;list&amp;#39;, 
  &amp;#39;data.frame&amp;#39;,
  &amp;#39;matrix&amp;#39;
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;code-i-want-to-be-able-to-run&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code I want to be able to run&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# User should be allowed to create all these objects
#-----------------------------------------------------------------------------
r_objects = list(
  null                     = &amp;quot;NULL&amp;quot;,
  empty_list               = &amp;quot;list()&amp;quot;,
  list                     = &amp;quot;list(a=1, b=&amp;#39;hello&amp;#39;)&amp;quot;,
  `NA`                     = &amp;quot;NA&amp;quot;,
  numeric_NA               = &amp;quot;NA_real_&amp;quot;,
  integer_NA               = &amp;quot;NA_integer_&amp;quot;,
  character_NA             = &amp;quot;NA_character_&amp;quot;,
  
  boolean                  = &amp;quot;TRUE&amp;quot;,
  numeric                  = &amp;quot;12.3&amp;quot;,
  integer                  = &amp;quot;1L&amp;quot;,
  character                = &amp;quot;&amp;#39;hello&amp;#39;&amp;quot;,
  
  boolean_vec              = &amp;quot;c(TRUE, FALSE, FALSE)&amp;quot;,
  numeric_vec              = &amp;quot;c(1.23, 4.56)&amp;quot;,
  integer_vec              = &amp;quot;c(1L, 5L, 3L)&amp;quot;,
  character_vec            = &amp;quot;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)&amp;quot;,
  
  boolean_named_vec        = &amp;quot;c(a=TRUE, b=FALSE, c=FALSE)&amp;quot;,
  numeric_named_vec        = &amp;quot;c(a=1.23, b=4.56)&amp;quot;,
  integer_named_vec        = &amp;quot;c(a=1L, b=5L, c=3L)&amp;quot;,
  character_named_vec      = &amp;quot;c(a=&amp;#39;a&amp;#39;, b=&amp;#39;b&amp;#39;, c=&amp;#39;c&amp;#39;)&amp;quot;,
  
  boolean_vec_with_na      = &amp;quot;c(TRUE, FALSE, NA)&amp;quot;,
  numeric_vec_with_na      = &amp;quot;c(1.23, NA)&amp;quot;,
  integer_vec_with_na      = &amp;quot;c(1L, 2L, NA)&amp;quot;,
  character_vec_with_na    = &amp;quot;c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, NA)&amp;quot;,
  
  boolean_list             = &amp;quot;list(TRUE, FALSE, FALSE)&amp;quot;,
  numeric_list             = &amp;quot;list(1.23, 4.56)&amp;quot;,
  integer_list             = &amp;quot;list(1L, 5L, 3L)&amp;quot;,
  character_list           = &amp;quot;list(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;)&amp;quot;,
  
  boolean_list_with_null   = &amp;quot;list(TRUE, FALSE, NULL)&amp;quot;,
  numeric_list_with_null   = &amp;quot;list(1.23, NULL)&amp;quot;,
  integer_list_with_null   = &amp;quot;list(1L, 5L, NULL)&amp;quot;,
  character_list_with_null = &amp;quot;list(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, NULL)&amp;quot;,
  
  boolean_named_list       = &amp;quot;list(a=TRUE, b=FALSE, c=FALSE)&amp;quot;,
  numeric_named_list       = &amp;quot;list(a=1.23, b=4.56)&amp;quot;,
  integer_named_list       = &amp;quot;list(a=1L, b=5L, c=3L)&amp;quot;,
  character_named_list     = &amp;quot;list(a=&amp;#39;a&amp;#39;, b=&amp;#39;b&amp;#39;, c=&amp;#39;c&amp;#39;)&amp;quot;,
  
  boolean_matrix           = &amp;quot;matrix(TRUE, nrow=2, ncol=2)&amp;quot;,
  numeric_matrix           = &amp;quot;matrix(1.2 , nrow=2, ncol=2)&amp;quot;,
  integer_matrix           = &amp;quot;matrix(1L  , nrow=2, ncol=2)&amp;quot;,
  character_matrix         = &amp;quot;matrix(&amp;#39;a&amp;#39; , nrow=2, ncol=2)&amp;quot;,
  
  data.frame               = &amp;quot;data.frame(a=1L, b=2.1, c=&amp;#39;c&amp;#39;, stringsAsFactors = FALSE)&amp;quot;
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;code-that-should-not-run&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Code that should not run&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# If my purpose is only creating objects, then all of these are unsafe
#-----------------------------------------------------------------------------
unsafe_commands &amp;lt;- list(
  &amp;quot;2 * 3&amp;quot;,                     # Calculations
  &amp;quot;a &amp;lt;- 1&amp;quot;,                    # Assigning variables
  &amp;quot;system(&amp;#39;echo bad stuff&amp;#39;)&amp;quot;,  # System calls
  &amp;quot;list.files(&amp;#39;.&amp;#39;)&amp;quot;,           # File system access
  &amp;quot;lm(mpg ~ cyl, mtcars)&amp;quot;      # Any computation
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;safe_eval-command&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;safe_eval&lt;/code&gt; command&lt;/h2&gt;
&lt;p&gt;As described in the &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/11/evaluating-r-code-from-potentially-malicious-sources-part-2/&#34;&gt;Part 2&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create an empty environment and add the whitelisted functions to it.&lt;/li&gt;
&lt;li&gt;evaluate the code in that environment&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Safely evaluate code by only allowing access to whitelisted functions.
#&amp;#39;
#&amp;#39; @param code character string containing the code
#&amp;#39; @param whitelist character vector of names of functions which are allowed
#&amp;#39;                  to be called by the code
#&amp;#39;
#&amp;#39; @return the results of the evaluation (wrapped up in purrr::safely)
#-----------------------------------------------------------------------------
safe_eval &amp;lt;- function(code, whitelist) {
  envir &amp;lt;- rlang::new_environment()
  whitelist %&amp;gt;% 
    purrr::walk(function(x) {envir[[x]] &amp;lt;- get(x)})
  
  safely_eval &amp;lt;- purrr::safely(eval)
  
  safely_eval(parse(text=code), envir=envir)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-an-object-works&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating an object works&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;safe_eval(&amp;quot;list(a=1, b=&amp;#39;banana&amp;#39;)&amp;quot;, whitelist)$result&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;$a
[1] 1

$b
[1] &amp;quot;banana&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;creating-all-the-objects-from-my-test-list-results-in-no-errors&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Creating all the objects from my test list results in no errors&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;res &amp;lt;- r_objects %&amp;gt;% 
  purrr::map(~safe_eval(.x, whitelist))

# There are no errors!  All of this code ran without a hitch
errors &amp;lt;- res %&amp;gt;% purrr::keep(~!is.null(.x$error))
stopifnot(length(errors) == 0)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;any-attempt-at-a-forbidden-function-causes-an-error&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Any attempt at a forbidden function causes an error&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Get an error or &amp;#39;could not find function&amp;#39; for all the things i haven&amp;#39;t explicitly allowed
safe_eval(&amp;quot;2 * 3&amp;quot;                   , whitelist)$error
&amp;lt;simpleError in 2 * 3: could not find function &amp;quot;*&amp;quot;&amp;gt;
safe_eval(&amp;quot;a &amp;lt;- 1&amp;quot;                  , whitelist)$error
&amp;lt;simpleError in a &amp;lt;- 1: could not find function &amp;quot;&amp;lt;-&amp;quot;&amp;gt;
safe_eval(&amp;quot;system(&amp;#39;echo bad stuff&amp;#39;)&amp;quot;, whitelist)$error
&amp;lt;simpleError in system(&amp;quot;echo bad stuff&amp;quot;): could not find function &amp;quot;system&amp;quot;&amp;gt;
safe_eval(&amp;quot;list.files(&amp;#39;.&amp;#39;)&amp;quot;         , whitelist)$error
&amp;lt;simpleError in list.files(&amp;quot;.&amp;quot;): could not find function &amp;quot;list.files&amp;quot;&amp;gt;
safe_eval(&amp;quot;lm(mpg ~ cyl, mtcars)&amp;quot;   , whitelist)$error
&amp;lt;simpleError in lm(mpg ~ cyl, mtcars): could not find function &amp;quot;lm&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;For the code execution context of “Allow creation of objects”, an environment consisting of
whitelisted functions seems to be able to ensure safe evaluation of code.&lt;/p&gt;
&lt;p&gt;This means that (with the add of some wrapper code) I could ensure safe deserialisation of most built-in object types
with a better guarantee of re-creating the original object than the &lt;code&gt;yaml&lt;/code&gt; package offers.&lt;/p&gt;
&lt;p&gt;Have a look at the &lt;a href=&#34;https://coolbutuseless.shinyapps.io/shiny-safe-eval/&#34;&gt;Shiny app using this safe(?) evalation of R code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you manage to do something ‘unsafe’ please let me know!&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Evaluating R code from potentially malicious sources part 2</title>
      <link>https://coolbutuseless.github.io/2018/02/11/evaluating-r-code-from-potentially-malicious-sources-part-2/</link>
      <pubDate>Sun, 11 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/11/evaluating-r-code-from-potentially-malicious-sources-part-2/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;evaluating-r-code-from-potentially-malicious-sources---part-2&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Evaluating R code from potentially malicious sources - part 2&lt;/h2&gt;
&lt;p&gt;As mentioned in &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/10/evaluating-r-code-from-potentially-malicious-sources/&#34;&gt;Part 1&lt;/a&gt;, I’m looking into the idea of running R code which may originate from potentially malicious sources e.g. 
code from a web interface, or a database or even a tweet!&lt;/p&gt;
&lt;p&gt;My idea after yesterday’s post was to evaluate the code one expression at a time and check the function signature of any calls to ensure nothing had been renamed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For each expression:
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Identify the functions (and their signatures) in the supplied code&lt;/li&gt;
&lt;li&gt;Check them against a whitelist of functions/signatures that are allowed to run&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I know this is dangerous and quite probably a fool’s quest.&lt;/li&gt;
&lt;li&gt;I want to run this in the current process and use the result i.e. no remote sandboxes or docker images.&lt;/li&gt;
&lt;li&gt;If this is impossible, or there’s an actual way to do this, or a better way of thinking of the problem, I’m keen to hear it!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ping me on &lt;a href=&#34;http://www.twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-this-current-idea-wont-work.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why this current idea won’t work.&lt;/h2&gt;
&lt;p&gt;This idea of trying to catch functions as they are called to ensure they are in the
whitelist just won’t work. There are too many ways for a user to corrupt a whitelisted function name
within an expression that will be way to hard to detect and prevent.&lt;/p&gt;
&lt;p&gt;The reason for this is: expressions are tricky.&lt;/p&gt;
&lt;p&gt;The following 2 snippets of code are each a single expression, meaning that if I was stepping through the code and
only evaluating a single expression at a time, these would constitute a single step.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;parse(text = &amp;quot;a &amp;lt;- 1;&amp;quot;) %&amp;gt;% length()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;parse(text = &amp;#39;if (isTRUE(zz &amp;lt;- system) || (mean(&amp;quot;echo bad stuff&amp;quot;))) {print(a)}&amp;#39;) %&amp;gt;% length()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I check the second expression for function calls I get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;if&amp;quot;     &amp;quot;||&amp;quot;     &amp;quot;isTRUE&amp;quot; &amp;quot;&amp;lt;-&amp;quot;     &amp;quot;(&amp;quot;      &amp;quot;mean&amp;quot;   &amp;quot;{&amp;quot;      &amp;quot;print&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the malicious user has successfully re-cast the name &lt;code&gt;mean&lt;/code&gt; to point to the &lt;code&gt;system&lt;/code&gt; call and called it, all within a single expression.&lt;/p&gt;
&lt;p&gt;This is bad, and
I can’t see a way to prevent this without re-writing R’s internal evaluation scheme and interrupting each and every function call
in order to check it is what it says it is.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;environments-to-the-rescue&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Environments to the rescue!&lt;/h2&gt;
&lt;p&gt;My idea so far was to have a standard R environment (with all base functions in it) and try and limit a
user’s access so they can only call functions I have in a whitelist.&lt;/p&gt;
&lt;p&gt;I now think that inverting my idea is the solution i.e. have an environment with only the
whitelisted functions available and don’t restrict a user’s access &lt;em&gt;in that environment&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;How this will work:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Create an empty environment&lt;/li&gt;
&lt;li&gt;Copy the whitelisted functions into it
&lt;ul&gt;
&lt;li&gt;Lots of control available here e.g. you could whitelist &lt;code&gt;mean&lt;/code&gt; and &lt;code&gt;mean.default&lt;/code&gt; but not
include &lt;code&gt;mean.difftime&lt;/code&gt; so that ordinary numeric means are possible, but not of difftime objects&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Do all evaluation within this environment&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# 1. Create the environment with just whitelisted functions
#-----------------------------------------------------------------------------
envir     &amp;lt;- rlang::new_environment()

#-----------------------------------------------------------------------------
# 2. Copy the whitelisted functions into this environment
#-----------------------------------------------------------------------------
whitelist &amp;lt;- c(&amp;#39;structure&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;list&amp;#39;, &amp;#39;mean&amp;#39;, &amp;#39;+&amp;#39;, &amp;#39;-&amp;#39;, &amp;#39;*&amp;#39;, &amp;#39;/&amp;#39;, &amp;#39;if&amp;#39;, &amp;#39;||&amp;#39;, &amp;#39;isTRUE&amp;#39;, &amp;#39;&amp;lt;-&amp;#39;, &amp;#39;mean.default&amp;#39;)
whitelist %&amp;gt;% 
  purrr::walk(function(x) {envir[[x]] &amp;lt;- get(x)})

#-----------------------------------------------------------------------------
#&amp;#39; 3. Evaluate code within this environment
#-----------------------------------------------------------------------------
eval(parse(text=&amp;quot;mean(c(1, 2, 3))&amp;quot;), envir = envir)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] 2&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Trying to call a function not in the environment fails
#-----------------------------------------------------------------------------
testthat::expect_error(
  eval(parse(text=&amp;quot;system(&amp;#39;echo bad stuff&amp;#39;)&amp;quot;), envir = envir),
  &amp;#39;could not find function &amp;quot;system&amp;quot;&amp;#39;
)

#-----------------------------------------------------------------------------
#&amp;#39; Trying to use a variable to point to a function not in the environment fails
#-----------------------------------------------------------------------------
testthat::expect_error(
  eval(parse(text=&amp;quot;mean &amp;lt;- system; mean(&amp;#39;bad stuff happens&amp;#39;)&amp;quot;), envir = envir),
  &amp;quot;object &amp;#39;system&amp;#39; not found&amp;quot;
)


#-----------------------------------------------------------------------------
#&amp;#39; Trying to use a variable to point to a function not in the environment fails
#&amp;#39; Even this malicious code fails as the &amp;#39;system&amp;#39; function just isn&amp;#39;t in the
#&amp;#39; environment at all, so there&amp;#39;s no way to call it!
#-----------------------------------------------------------------------------
testthat::expect_error(
eval(parse(text = &amp;#39;if (isTRUE(zz &amp;lt;- system) || (mean(&amp;quot;echo bad stuff&amp;quot;))) {print(a)}&amp;#39;), envir=envir),
  &amp;quot;object &amp;#39;system&amp;#39; not found&amp;quot;
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;summary&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;It appears that using &lt;code&gt;eval()&lt;/code&gt; wih a carefully crafted environment consisting of
only whitelisted functions should be my way forward in evaluating R code from possibly
malicious sources.&lt;/p&gt;
&lt;p&gt;The next question is: &lt;em&gt;What functions are safe to add to the whitelist?&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Evaluating R code from potentially malicious sources</title>
      <link>https://coolbutuseless.github.io/2018/02/10/evaluating-r-code-from-potentially-malicious-sources/</link>
      <pubDate>Sat, 10 Feb 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/10/evaluating-r-code-from-potentially-malicious-sources/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;evaluating-r-code-from-potentially-malicious-sources&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Evaluating R code from potentially malicious sources&lt;/h2&gt;
&lt;p&gt;I’m looking into the idea of running R code which may originate from potentially malicious sources e.g. 
code from a web interface, or a database or even a tweet!&lt;/p&gt;
&lt;p&gt;If we allow user input of R code, eventually someone is going to try &lt;code&gt;system(&#34;rm -rf /&#34;)&lt;/code&gt; or something equally
dangerous, so I would like to forbid the use of &lt;code&gt;system&lt;/code&gt; while still allowing the use of
&lt;code&gt;mean&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;c()&lt;/code&gt; etc.&lt;/p&gt;
&lt;p&gt;Ignoring other considerations (like limiting runtime of the code) my idea consists of 2 parts:&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Identify the functions in the supplied code&lt;/li&gt;
&lt;li&gt;Check them against a whitelist of functions that are allowed to run&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I know this is dangerous&lt;/li&gt;
&lt;li&gt;I want to run this in the current process and use the result i.e. no remote sandboxes or docker images.&lt;/li&gt;
&lt;li&gt;If this is impossible, or there’s an actual way to do this, or a better way of thinking of the problem, I’m keen to hear it!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ping me on &lt;a href=&#34;http://www.twitter.com/coolbutuseless&#34;&gt;twitter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-approach-for-identifying-function-names-in-r-code&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive Approach for identifying function names in R code&lt;/h2&gt;
&lt;p&gt;A naive approach for identifying functions in an expression is just to get all the &lt;em&gt;names&lt;/em&gt;
in the expression and all the &lt;em&gt;variables&lt;/em&gt; in the expression and
find the difference.&lt;/p&gt;
&lt;p&gt;i.e. the items which are &lt;em&gt;names&lt;/em&gt; but not &lt;em&gt;variables&lt;/em&gt; must be &lt;em&gt;functions&lt;/em&gt;!&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;expr &amp;lt;- parse(text=&amp;quot;a &amp;lt;- 1:5; mean(a);&amp;quot;)

all.names(expr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot;   &amp;quot;a&amp;quot;    &amp;quot;:&amp;quot;    &amp;quot;mean&amp;quot; &amp;quot;a&amp;quot;   &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;all.vars(expr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;a&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# These should be the function names!
setdiff(all.names(expr), all.vars(expr))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot;   &amp;quot;:&amp;quot;    &amp;quot;mean&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This seems to work and gives all the function calls in the given code.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;why-the-naive-approach-fails&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Why the naive Approach fails…&lt;/h2&gt;
&lt;p&gt;The naive approach failes because a function can be easily assigned to a variable and then called.&lt;/p&gt;
&lt;p&gt;This means that a &lt;code&gt;name&lt;/code&gt; in an expression can easily be a &lt;em&gt;variable&lt;/em&gt; which represents a &lt;em&gt;function&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In the following code, &lt;code&gt;myfunc&lt;/code&gt; is a variable which contains a function, so it
is not classified as being a function name under the naive scheme.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;expr &amp;lt;- parse(text=&amp;quot;a &amp;lt;- 1:5; myfunc = mean; myfunc(a);&amp;quot;)

all.names(expr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot;     &amp;quot;a&amp;quot;      &amp;quot;:&amp;quot;      &amp;quot;=&amp;quot;      &amp;quot;myfunc&amp;quot; &amp;quot;mean&amp;quot;   &amp;quot;myfunc&amp;quot; &amp;quot;a&amp;quot;     &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;all.vars(expr)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;a&amp;quot;      &amp;quot;myfunc&amp;quot; &amp;quot;mean&amp;quot;  &lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;# Hoping to get all the function names - but &amp;#39;myfunc&amp;#39; and &amp;#39;mean&amp;#39; are both missing
setdiff(all.names(expr), all.vars(expr))&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot; &amp;quot;:&amp;quot;  &amp;quot;=&amp;quot; &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;a-more-rigorous-approach-for-identifying-function-names-in-r-code-i.e.-what-hadley-suggests&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;A more rigorous approach for identifying function names in R code (i.e. what hadley suggests!)&lt;/h2&gt;
&lt;p&gt;In Hadley Wickham’s &lt;a href=&#34;http://adv-r.had.co.nz/Expressions.html&#34;&gt;Advanced R&lt;/a&gt; book, the chapter on &lt;strong&gt;Expressions&lt;/strong&gt;
suggests that walking the Abstract Syntax Tree (AST) with a recursive function the way to properly
determine things about an expression.&lt;/p&gt;
&lt;p&gt;So I’ve taken &lt;a href=&#34;http://adv-r.had.co.nz/Expressions.html#ast-funs&#34;&gt;hadley’s example code&lt;/a&gt; and tweaked it for my needs.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; find all function calls in an expression
#&amp;#39;
#&amp;#39; Adapted from: @hadley&amp;#39;s http://adv-r.had.co.nz/Expressions.html
#&amp;#39;
#&amp;#39; @param x expression
#&amp;#39;
#&amp;#39; @return a character vector of function names
#-----------------------------------------------------------------------------
find_calls &amp;lt;- function(x) {
  calls &amp;lt;- c()
  
  if (is.call(x)) {
    # Call recurse_call recursively
    this_call &amp;lt;- as.character(x[[1]])
    sub_calls &amp;lt;- purrr::flatten_chr(lapply(x[-1], find_calls))
    calls     &amp;lt;- c(this_call, sub_calls)
  } else if (is.pairlist(x)) {
    stop(&amp;quot;Pairlists not allowed&amp;quot;)
  } 
  
  calls
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the function &lt;code&gt;find_calls&lt;/code&gt; is for a &lt;em&gt;single&lt;/em&gt; expression, use &lt;code&gt;purrr&lt;/code&gt; to map the function over a vector of &lt;em&gt;multiple&lt;/em&gt; expressions
and get all function names.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;exprs &amp;lt;- parse(text=&amp;quot;a &amp;lt;- 1:5; myfunc = mean; myfunc(a);&amp;quot;)

exprs %&amp;gt;%
  purrr::map(find_calls) %&amp;gt;% 
  purrr::flatten_chr()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot;     &amp;quot;:&amp;quot;      &amp;quot;=&amp;quot;      &amp;quot;myfunc&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we have now correctly identified &lt;code&gt;myfunc&lt;/code&gt; as a function, but not that it is really just calling &lt;code&gt;mean&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;naive-method-for-whitelisting-functions&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Naive method for whitelisting functions&lt;/h2&gt;
&lt;p&gt;Now that we can identify function names in R code, can we enforce a whitelist?&lt;/p&gt;
&lt;p&gt;I.e. Can safe/unsafe functions be detected by just comparing all the function names in the given
code against a list of whitelisted functions?&lt;/p&gt;
&lt;p&gt;TLDR: No.&lt;/p&gt;
&lt;p&gt;A variable with the name of a whitelisted function can easily
be made to point to an unsafe function. So in the example below, if the whitelisted functions
include &lt;code&gt;mean&lt;/code&gt; (which is pretty safe to call), a malicous user could simply have the name &lt;code&gt;mean&lt;/code&gt;
point to the &lt;code&gt;system&lt;/code&gt; function and proceed to wreak havok.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;exprs &amp;lt;- parse(text=&amp;quot;mean &amp;lt;- system; mean(&amp;#39;echo bad stuff happens&amp;#39;);&amp;quot;)

exprs %&amp;gt;%
  purrr::map(find_calls) %&amp;gt;% 
  purrr::flatten_chr()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;&amp;lt;-&amp;quot;   &amp;quot;mean&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have only identified that a function named &lt;code&gt;mean&lt;/code&gt; has been called, but are totally ignorant of the fact that this is really
a &lt;code&gt;system&lt;/code&gt; call.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;next-idea-compare-function-signatures-not-just-function-names&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Next idea: compare function signatures not just function names&lt;/h2&gt;
&lt;p&gt;Even being able to get all function calls and compare against a whitelist isn’t enough
to make it safe to evaluate R code from a possibly malicious source.&lt;/p&gt;
&lt;p&gt;My next idea is not just to compare function &lt;em&gt;names&lt;/em&gt;, but to actually compare function &lt;em&gt;signatures&lt;/em&gt;
at each step of the evaluation i.e. for each expression:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;find the function names&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get()&lt;/code&gt; the functions from the working environment and calculate a function signature e.g sha1 digest&lt;/li&gt;
&lt;li&gt;compare the function name and signature against a known list of function names/signatures&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>YAML vs jsonlite vs RJSONIO</title>
      <link>https://coolbutuseless.github.io/2018/02/07/yaml-vs-jsonlite-vs-rjsonio/</link>
      <pubDate>Wed, 07 Feb 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/07/yaml-vs-jsonlite-vs-rjsonio/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;comparison-of-r-object-encoding-with-yaml-jsonlist-and-rjsonio&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Comparison of R object encoding with YAML, jsonlist and RJSONIO&lt;/h1&gt;
&lt;p&gt;As described in a &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/03/yaml-vs-json-for-saving-human-readable-r-objects--tldr-use-yaml/&#34;&gt;prior post&lt;/a&gt; I need to save some configuration objects from R into human-readable, human-editable format.&lt;/p&gt;
&lt;p&gt;I’d previously decided that YAML was the best for my purposes, but I recently discovered that YAML and jsonlite won’t keep the names of a named vector, whereas RJSONIO will.&lt;/p&gt;
&lt;p&gt;In response to this discovery, I’ve decided to check a large number of standard R object types output by the three packages (&lt;code&gt;yaml&lt;/code&gt;, &lt;code&gt;jsonlite&lt;/code&gt; and &lt;code&gt;RJSONIO&lt;/code&gt;) to get a better picture of their strengths and weaknesses.&lt;/p&gt;
&lt;p&gt;Below, I set up a list of all the object I want to test and then test each package encoding/decoding the object and then comparing it to the original.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;set-up-the-format-specification-and-the-list-of-r-objects-to-test&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Set up the format specification and the list of R objects to test&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# 3 formats and their encode/decode functions
#-----------------------------------------------------------------------------
format &amp;lt;- list(
  jsonlite = list(
    encode = jsonlite::toJSON,
    decode = jsonlite::fromJSON
  ),
  RJSONIO = list(
    encode = RJSONIO::toJSON,
    decode = RJSONIO::fromJSON
  ),
  yaml = list(
    encode = yaml::as.yaml,
    decode = yaml::yaml.load
  )
)


#-----------------------------------------------------------------------------
# List of different R objects
#-----------------------------------------------------------------------------
r_objects = list(
  
  null                    = NULL,
  empty_list              = list(),
  list                    = list(a=1, b=&amp;#39;hello&amp;#39;),
  `NA`                    = NA,
  numeric_NA              = NA_real_,
  integer_NA              = NA_integer_,
  character_NA            = NA_character_,
  
  boolean                 = TRUE,
  numeric                 = 12.3,
  integer                 = 1L,
  character               = &amp;#39;hello&amp;#39;,
  
  boolean_vec             = c(TRUE, FALSE, FALSE),
  numeric_vec             = c(1.23, 4.56),
  integer_vec             = c(1L, 5L, 3L),
  character_vec           = c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;),
  
  boolean_named_vec       = c(a=TRUE, b=FALSE, c=FALSE),
  numeric_named_vec       = c(a=1.23, b=4.56),
  integer_named_vec       = c(a=1L, b=5L, c=3L),
  character_named_vec     = c(a=&amp;#39;a&amp;#39;, b=&amp;#39;b&amp;#39;, c=&amp;#39;c&amp;#39;),
  
  boolean_vec_with_na     = c(TRUE, FALSE, NA),
  numeric_vec_with_na     = c(1.23, NA),
  integer_vec_with_na     = c(1L, 2L, NA),
  character_vec_with_na   = c(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, NA),
  
  boolean_list            = list(TRUE, FALSE, FALSE),
  numeric_list            = list(1.23, 4.56),
  integer_list            = list(1L, 5L, 3L),
  character_list          = list(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;),
  
  boolean_list_with_null   = list(TRUE, FALSE, NULL),
  numeric_list_with_null   = list(1.23, NULL),
  integer_list_with_null   = list(1L, 5L, NULL),
  character_list_with_null = list(&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, NULL),
  
  boolean_named_list      = list(a=TRUE, b=FALSE, c=FALSE),
  numeric_named_list      = list(a=1.23, b=4.56),
  integer_named_list      = list(a=1L, b=5L, c=3L),
  character_named_list    = list(a=&amp;#39;a&amp;#39;, b=&amp;#39;b&amp;#39;, c=&amp;#39;c&amp;#39;),
  
  boolean_matrix          = matrix(TRUE, nrow=2, ncol=2),
  numeric_matrix          = matrix(1.2 , nrow=2, ncol=2),
  integer_matrix          = matrix(1L  , nrow=2, ncol=2),
  character_matrix        = matrix(&amp;#39;a&amp;#39; , nrow=2, ncol=2),
  
  data.frame              = data.frame(a=1L, b=2.1, c=&amp;#39;c&amp;#39;, stringsAsFactors = FALSE)
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;test-each-format-encodingdecoding-each-r-object&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Test each format encoding/decoding each R object&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Capture a string representation of an object
#-----------------------------------------------------------------------------
cap &amp;lt;- function(x) {
  deparse(x, control = c(&amp;quot;keepInteger&amp;quot;, &amp;quot;keepNA&amp;quot;))
}


sanitize &amp;lt;- function(x) {
  x &amp;lt;- gsub(&amp;quot;\\.\\.\\.&amp;quot;, &amp;#39;&amp;#39;, x)
  x &amp;lt;- gsub(&amp;quot;\n&amp;quot;, &amp;quot;\\\\\\\\n&amp;quot;, stringr::str_trim(x))
  x
}

#-----------------------------------------------------------------------------
# encode/decode the given r object using the given format
#-----------------------------------------------------------------------------
test_encode_decode &amp;lt;- function(format_name, r_object_name) {
  encode      &amp;lt;- format[[format_name]]$encode
  decode      &amp;lt;- format[[format_name]]$decode
  
  
  original_object &amp;lt;- r_objects[[r_object_name]]
  encoded_object  &amp;lt;- encode(original_object)
  decoded_object  &amp;lt;- decode(encoded_object)
  
  data_frame(
    format                 = format_name,
    name                   = r_object_name,
    original               = cap(original_object),
    decoded                = cap(decoded_object),
    original_class         = class(original_object),
    decoded_class          = class(decoded_object),
    identical              = identical(original_object, decoded_object),
    encoded_representation = sanitize(encoded_object)
  )
}


#-----------------------------------------------------------------------------
# Generate all results
#-----------------------------------------------------------------------------
all_results &amp;lt;- dplyr::bind_rows(
  names(r_objects) %&amp;gt;% purrr::map(~test_encode_decode(&amp;#39;yaml&amp;#39;    , .x)) %&amp;gt;% bind_rows() %&amp;gt;% as.data.frame(),
  names(r_objects) %&amp;gt;% purrr::map(~test_encode_decode(&amp;#39;jsonlite&amp;#39;, .x)) %&amp;gt;% bind_rows() %&amp;gt;% as.data.frame(),
  names(r_objects) %&amp;gt;% purrr::map(~test_encode_decode(&amp;#39;RJSONIO&amp;#39; , .x)) %&amp;gt;% bind_rows() %&amp;gt;% as.data.frame()
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;all_results %&amp;lt;&amp;gt;% mutate(
  name = factor(name, levels = unique(name))
) %&amp;gt;% arrange(name, format)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;results&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Results&lt;/h1&gt;
&lt;p&gt;The list of all results is at the end of this post in the appendix.&lt;/p&gt;
&lt;p&gt;On a raw count, &lt;code&gt;yaml&lt;/code&gt; has the most number of decoded objects identical to the original.&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-3&#34;&gt;Table 1: &lt;/span&gt;Count of identical decoded objects by format&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;format&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;FALSE&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;TRUE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-4&#34;&gt;Table 2: &lt;/span&gt;Comparison of formats: was the decoded object using this package identical to the original&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;jsonlite&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;RJSONIO&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;yaml&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;empty_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;boolean_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;numeric_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;integer_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;character_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Y&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div id=&#34;notes&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Notes&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;YAML seems to have the best support for the basic types (i.e. the first 10 R objects tested)&lt;/li&gt;
&lt;li&gt;All formats convert an unnamed list of a single type (e.g. all numerics) into a vector&lt;/li&gt;
&lt;li&gt;Named vectors are only supported by RJSONIO&lt;/li&gt;
&lt;li&gt;Only jsonlite seems to support matrices&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion?&lt;/h1&gt;
&lt;p&gt;It depends.&lt;/p&gt;
&lt;p&gt;YAML still the best for my purposes.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-all-results&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appendix: All results&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;knitr::kable(all_results, caption=&amp;quot;All results&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-5&#34;&gt;Table 3: &lt;/span&gt;All results&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;format&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;original&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;decoded&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;original_class&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;decoded_class&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;identical&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;encoded_representation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;empty_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;empty_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;AsIs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;empty_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list()&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{“a”:[1],“b”:[“hello”]}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: 1,\n“b”: “hello” \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, “hello”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: 1.0\nb: hello&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[null]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.na&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_real_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“NA”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_real_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_real_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_real_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.na.real&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_integer_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“NA”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_integer_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_integer_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_integer_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.na.integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_character_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[null]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_character_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_character_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA_character_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.na.character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[true]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ true ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[12.3]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 12.3 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1L&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1L&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1L&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1L&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1L&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“hello”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ “hello” ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;“hello”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hello&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[true,false,false]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ true, false, false ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- no\n- no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1.23,4.56]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 1.23, 4.56 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.23\n- 4.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1,5,3]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1, 5, 3)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 1, 5, 3 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 5\n- 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“a”,“b”,“c”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ “a”, “b”, “c” ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- b\n- c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[true,false,false]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: true,\n“b”: false,\n“c”: false \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- no\n- no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1.23,4.56]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: 1.23,\n“b”: 4.56 \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.23\n- 4.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1,5,3]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1, 5, 3)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: 1,\n “b”: 5,\n “c”: 3 \n }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 5\n- 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“a”,“b”,“c”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: “a”,\n“b”: “b”,\n“c”: “c” \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_vec&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- b\n- c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[true,false,null]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ true, false, null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- no\n- .na&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1.23,“NA”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 1.23, null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.23\n- .na.real&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 2L, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 2L, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[1,2,“NA”]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 2L, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, 2, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ 1, 2, null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 2L, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 2L, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 2\n- .na.integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[“a”,“b”,null]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ “a”, “b”, null ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_vec_with_na&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, NA)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- b\n- .na.character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[true],[false],[false]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n true,\nfalse,\nfalse \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- no\n- no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1.23],[4.56]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n 1.23,\n 4.56 \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.23\n- 4.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1],[5],[3]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1, 5, 3)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n 1,\n5,\n3 \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 5\n- 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[“a”],[“b”],[“c”]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n “a”,\n“b”,\n“c” \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- b\n- c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, list())&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[true],[false],{}]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n true,\nfalse,\nnull \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- no\n- ~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, list())&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1.23],{}]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n 1.23,\nnull \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.23\n- ~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, list())&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1],[5],{}]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, 5, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n 1,\n5,\nnull \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 5\n- ~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, list())&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[“a”],[“b”],{}]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[\n “a”,\n“b”,\nnull \n]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_list_with_null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, NULL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- b\n- ~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{“a”:[true],“b”:[false],“c”:[false]}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: true,\n“b”: false,\n“c”: false \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(TRUE, FALSE, FALSE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: yes\nb: no\nc: no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{“a”:[1.23],“b”:[4.56]}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: 1.23,\n“b”: 4.56 \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1.23, 4.56)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: 1.23\nb: 4.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{“a”:[1],“b”:[5],“c”:[3]}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1, 5, 3)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: 1,\n“b”: 5,\n“c”: 3 \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 5L, 3L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: 1\nb: 5\nc: 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{“a”:[“a”],“b”:[“b”],“c”:[“c”]}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: “a”,\n“b”: “b”,\n“c”: “c” \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_named_list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(“a”, “b”, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: a\nb: b\nc: c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, TRUE, TRUE, TRUE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, TRUE, TRUE, TRUE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[true,true],[true,true]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, TRUE, TRUE, TRUE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(c(TRUE, TRUE), c(TRUE, TRUE))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ [ true, true ],\n[ true, true ] ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;boolean_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, TRUE, TRUE, TRUE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(TRUE, TRUE, TRUE, TRUE)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;logical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- yes\n- yes\n- yes\n- yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.2, 1.2, 1.2, 1.2)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.2, 1.2, 1.2, 1.2)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1.2,1.2],[1.2,1.2]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.2, 1.2, 1.2, 1.2)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(c(1.2, 1.2), c(1.2, 1.2))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ [ 1.2, 1.2 ],\n[ 1.2, 1.2 ] ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.2, 1.2, 1.2, 1.2)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1.2, 1.2, 1.2, 1.2)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;numeric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1.2\n- 1.2\n- 1.2\n- 1.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 1L, 1L, 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 1L, 1L, 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[1,1],[1,1]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 1L, 1L, 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(c(1, 1), c(1, 1))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ [ 1, 1 ],\n[ 1, 1 ] ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 1L, 1L, 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(1L, 1L, 1L, 1L)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;integer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- 1\n- 1\n- 1\n- 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “a”, “a”, “a”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “a”, “a”, “a”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[[“a”,“a”],[“a”,“a”]]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “a”, “a”, “a”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(c(“a”, “a”), c(“a”, “a”))&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[ [ “a”, “a” ],\n[ “a”, “a” ] ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character_matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “a”, “a”, “a”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;c(“a”, “a”, “a”, “a”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;matrix&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;character&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;- a\n- a\n- a\n- a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;jsonlite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[{“a”:1,“b”:2.1,“c”:“c”}]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;RJSONIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{\n “a”: [ 1 ],\n“b”: [ 2.1 ],\n“c”: [ “c” ] \n}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;yaml&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list(1L, 2.1, “c”)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data.frame&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a: 1\nb: 2.1\nc: c&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>`blogdown` rss feed of full articles</title>
      <link>https://coolbutuseless.github.io/2018/02/07/blogdown-rss-feed-of-full-articles/</link>
      <pubDate>Wed, 07 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/07/blogdown-rss-feed-of-full-articles/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;rss-setup-in-blogdown&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;RSS Setup in Blogdown&lt;/h2&gt;
&lt;p&gt;By default, &lt;strong&gt;blogdown&lt;/strong&gt; in Rstats includes an RSS feed which is limited to just the first snippet from each article.&lt;/p&gt;
&lt;p&gt;For some RSS aggregators, it’s probably nicer to have a full article showing up in the feed.&lt;/p&gt;
&lt;ol style=&#34;list-style-type: decimal&#34;&gt;
&lt;li&gt;Ensure you have a full &lt;code&gt;baseURL&lt;/code&gt; in your &lt;code&gt;config.toml&lt;/code&gt; e.g. &lt;code&gt;baseURL = &#34;https://coolbutuseless.github.io/&#34;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ensure you have an &lt;code&gt;rss.xml&lt;/code&gt; file
&lt;ul&gt;
&lt;li&gt;by default I think blogdown just uses the hugo’s internal &lt;code&gt;rss.xml&lt;/code&gt; representation, but we need an actual file to modify&lt;/li&gt;
&lt;li&gt;Copy the rss configuration from &lt;a href=&#34;https://gohugo.io/templates/rss/#the-embedded-rss-xml&#34;&gt;hugo’s embedded rss template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;put this in a file at &lt;code&gt;[your blog]/layouts/rss.xml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Change the rss feed to be full content rather than summary
&lt;ul&gt;
&lt;li&gt;Find the line which says: &lt;code&gt;&amp;lt;description&amp;gt;{{ .Summary | html }}&amp;lt;/description&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Change it to: &lt;code&gt;&amp;lt;description&amp;gt;{{ .Content | html }}&amp;lt;/description&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Put a limit on the number of articles which show up in your RSS feed
&lt;ul&gt;
&lt;li&gt;By default I think the RSS feed includes every post you’ve ever written.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;rssLimit = 10&lt;/code&gt; to your &lt;code&gt;config.toml&lt;/code&gt; file to limit the number of articles in the feed (untested)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/rss/#the-embedded-rss-xml&#34;&gt;the rss template that’s embedded in hugo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/templates/rss/&#34;&gt;hugo template rss information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://randomgeekery.org/2017/09/15/full-content-hugo-feeds/&#34;&gt;full feed rss&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>`dithr` package for error diffusion dithering in R</title>
      <link>https://coolbutuseless.github.io/2018/02/05/dithr-package-for-error-diffusion-dithering-in-r/</link>
      <pubDate>Mon, 05 Feb 2018 16:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/05/dithr-package-for-error-diffusion-dithering-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I made a simple package to encapsulate the &lt;a href=&#34;https://coolbutuseless.github.io/2018/02/04/error-diffusion-dithering-in-r/&#34;&gt;dithering code from yesterday’s post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The package is called &lt;code&gt;dithr&lt;/code&gt; and is available on &lt;a href=&#34;https://github.com/coolbutuseless/dithr&#34;&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The code expects a numeric matrix (all values in the range [0, 1]) as input and provides a matrix as output
with &lt;em&gt;only&lt;/em&gt; 0 and 1 values. It includes 10 pre-defined diffusion matrices in &lt;code&gt;dithr::diffusion_matrix&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At the moment it’s not really very user friendly, mostly because dealing with image data in R can be a bit of a pain.&lt;br /&gt;
There’s probably a great set of image packages out there I haven’t discovered yet! (let me know!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intallation&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;devtools::install_github(&amp;#39;coolbutuseless/dithr&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/magick/index.html&#34;&gt;magick&lt;/a&gt; - for image preparation&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bioconductor.org/packages/release/bioc/html/EBImage.html&#34;&gt;EBImage&lt;/a&gt; - easiest(?) way to get image data out of &lt;code&gt;magick&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To Do&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serpentine error diffusion (i.e. alternating traversal direction every row)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;create-a-ggplot-and-save-it-as-a-png&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Create a ggplot and save it as a PNG&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;p &amp;lt;-  ggplot(iris) + 
  geom_histogram(aes(Sepal.Length, fill=Species), bins=10) + 
  scale_fill_brewer() +
  theme_bw() + 
  theme(legend.position=&amp;#39;none&amp;#39;)

ggsave(&amp;quot;hist.png&amp;quot;, width=6, height=4, units = &amp;#39;in&amp;#39;, dpi = 100)

p&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-05-dithr-package_files/figure-html/unnamed-chunk-2-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;load-the-image-and-convert-to-a-matrix&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Load the image and convert to a matrix&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;im &amp;lt;- magick::image_read(&amp;#39;hist.png&amp;#39;) %&amp;gt;%
  magick::image_convert(type=&amp;#39;grayscale&amp;#39;) %&amp;gt;%
  magick::image_scale(geometry=&amp;quot;75%&amp;quot;)

m &amp;lt;- magick::as_EBImage(im)@.Data

dithr::plot_matrix(m)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-05-dithr-package_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dither-matrix-using-floyd-steinberg.&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dither matrix using floyd steinberg.&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dithered_matrix &amp;lt;- dithr::dither(m, edm = dithr::diffusion_matrix$floyd_steinberg)


dithr::plot_matrix(dithered_matrix)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-05-dithr-package_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;dithered-pie-chart-atkinson-dithering&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Dithered pie chart (Atkinson dithering)&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Create and save pie chart
#-----------------------------------------------------------------------------
p &amp;lt;-  ggplot(iris) + 
  geom_bar(aes(1, fill=Species)) +
  coord_polar(theta=&amp;#39;y&amp;#39;) +
  scale_fill_viridis_d() + 
  theme_bw() +
  theme(legend.position=&amp;#39;none&amp;#39;)

ggsave(&amp;quot;pie.png&amp;quot;, width=6, height=4, units = &amp;#39;in&amp;#39;, dpi = 100)

#-----------------------------------------------------------------------------
# Load and prepare image
#-----------------------------------------------------------------------------
im &amp;lt;- magick::image_read(&amp;#39;pie.png&amp;#39;) %&amp;gt;%
  magick::image_convert(type=&amp;#39;grayscale&amp;#39;) 

#-----------------------------------------------------------------------------
# Extract matrix data
#-----------------------------------------------------------------------------
m &amp;lt;- magick::as_EBImage(im)@.Data


#-----------------------------------------------------------------------------
# Dither
#-----------------------------------------------------------------------------
dithered_matrix &amp;lt;- dithr::dither(m, edm = dithr::diffusion_matrix$atkinson)
dithr::plot_matrix(dithered_matrix)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-05-dithr-package_files/figure-html/unnamed-chunk-5-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>Error Diffusion Dithering in R</title>
      <link>https://coolbutuseless.github.io/2018/02/04/error-diffusion-dithering-in-r/</link>
      <pubDate>Sun, 04 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/04/error-diffusion-dithering-in-r/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;introduction&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I wanted to experiment with some dithering algorithms within R, but I also wanted complete control of the error diffusion.&lt;/p&gt;
&lt;p&gt;After reading &lt;a href=&#34;http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/&#34;&gt;Tanner Helland’s articale on dithering&lt;/a&gt;,
I decided to implement some generic dithering code in order to experiment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Packages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/magick/index.html&#34;&gt;magick&lt;/a&gt; - for image preparation&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bioconductor.org/packages/release/bioc/html/EBImage.html&#34;&gt;EBImage&lt;/a&gt; - easiest(?) way to get image data out of &lt;code&gt;magick&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To Do&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serpentine error diffusion (i.e. alternating traversal direction every row)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;original-image&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Original Image&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Using imagemagick to load and convert the image to grayscale
#-----------------------------------------------------------------------------
im &amp;lt;- magick::image_read(&amp;quot;../../static/img/dithering/Portal_Companion_Cube.jpg&amp;quot;) %&amp;gt;%
  magick::image_convert(type = &amp;#39;grayscale&amp;#39;) %&amp;gt;% 
  magick::image_scale(geometry=&amp;quot;50%&amp;quot;)
  

#-----------------------------------------------------------------------------
# Extract the matrix of values
#-----------------------------------------------------------------------------
m &amp;lt;- magick::as_EBImage(im)@.Data

#-----------------------------------------------------------------------------
# Show the original image
#-----------------------------------------------------------------------------
plot(EBImage::as.Image(m), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-1-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;floyd-steinberg-dither&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Floyd Steinberg dither&lt;/h2&gt;
&lt;p&gt;For dithering a grayscale image (values 0 to 255) down to a binary image,
each pixel is considered in turn such that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the pixel is set to 0 or 255 - depending which is closer to the current value.&lt;/li&gt;
&lt;li&gt;the difference between this current value and the new set value is the error.&lt;/li&gt;
&lt;li&gt;distribute this error among the surrounding pixels.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are plenty of good tutorials about the mechanics of dithering, but I thought
I’d try my hand at visualising what’s going on:&lt;/p&gt;
&lt;embed src=&#34;https://coolbutuseless.github.io/img/dithering/floyd.svg&#34; type=&#34;image/svg+xml&#34; /&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Floyd Steinberg error diffusion matrix.
# The position of the NA indicates the position of the current pixel.
# The other values indicate the fraction of the error distributed to that
# pixel
#-----------------------------------------------------------------------------
floyd_steinberg &amp;lt;- matrix(
  c(0, NA, 7, 
    3,  5, 1), 
  ncol=3, byrow = TRUE) / 16

dithered_matrix &amp;lt;- dither(m, floyd_steinberg)
plot(EBImage::as.Image(dithered_matrix), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-3-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;jarvis-judice-and-ninke-dithering&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Jarvis, Judice, and Ninke Dithering&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
# Jarvis Judice Ninke
#-----------------------------------------------------------------------------
jarvis_judice_ninke &amp;lt;- matrix(
  c(0, 0, NA, 7, 5,
    3, 5,  7, 5, 3, 
    1, 3,  5, 3, 1), 
  ncol=5, byrow = TRUE) / 48

dithered_matrix &amp;lt;- dither(m, jarvis_judice_ninke)
plot(EBImage::as.Image(dithered_matrix), interpolate = FALSE)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix---the-dither-function&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appendix - the &lt;code&gt;dither()&lt;/code&gt; function&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;#-----------------------------------------------------------------------------
#&amp;#39; Add a border of zeros around a matrix
#&amp;#39;
#&amp;#39; @param m matrix
#&amp;#39; @param border border width
#-----------------------------------------------------------------------------
expand_matrix &amp;lt;- function(m, border) {
  em &amp;lt;- matrix(0, nrow = nrow(m) + 2*border, ncol=ncol(m) + 2*border)
  em[border + seq(nrow(m)), border + seq(ncol(m))] &amp;lt;- m
  em
}


#-----------------------------------------------------------------------------
#&amp;#39; Dither a numeric matrix 
#&amp;#39;
#&amp;#39; @param m numeric matrix with all values in the range [0, 1]
#&amp;#39; @param edm the error diffusion matrix
#&amp;#39;
#&amp;#39; @return numeric matrix with dithering. all values are 0 or 1.
#-----------------------------------------------------------------------------
dither &amp;lt;- function(m, edm, threshold = 0.5) {
  
  #---------------------------------------------------------------------------
  # Expand the matrix so we don&amp;#39;t have to worry about edge conditions
  #---------------------------------------------------------------------------
  border &amp;lt;- max(dim(edm))
  em     &amp;lt;- expand_matrix(m, border = border)
  
  #---------------------------------------------------------------------------
  # Set up the error diffusion matrix and associated variables
  #---------------------------------------------------------------------------
  stopifnot(sum(is.na(edm)) == 1) # should be 1 NA to nominate current pixel position
  edm_w           &amp;lt;- ncol(edm)
  edm_h           &amp;lt;- nrow(edm)
  edm_xoff        &amp;lt;- which(is.na(edm[1, ])) - 1
  edm[is.na(edm)] &amp;lt;- 0
  
  #---------------------------------------------------------------------------
  # Loop over all pixels in the matrix
  #---------------------------------------------------------------------------
  for (row in seq(border, nrow(em) - border)) {
    
    #-------------------------------------------------------------------------
    # To which part of the matrix is the error diffusion matrix to be applied?
    #-------------------------------------------------------------------------
    ed_rows  &amp;lt;- row:(row+edm_h - 1)
    ed_cols  &amp;lt;- (border - edm_xoff):(border - edm_xoff + edm_w - 1)
    
    for (col in seq(border, ncol(em) - border)) {
      
      
      #-----------------------------------------------------------------------
      # For the current position, push it to zero or 1 and 
      # calculate the error
      #-----------------------------------------------------------------------
      val &amp;lt;- em[row, col]
      if (val &amp;lt; threshold) {
        error &amp;lt;- val
        em[row, col] &amp;lt;- 0
      } else {
        error &amp;lt;- val - 1
        em[row, col] &amp;lt;- 1
      }
      
      #-----------------------------------------------------------------------
      # Distribute the error to the surrounding pixels
      #-----------------------------------------------------------------------
      em[ed_rows, ed_cols] &amp;lt;-  em[ed_rows, ed_cols] + edm * error
      
      #-----------------------------------------------------------------------
      # slide the diffusion matrix position one pixel to the right
      #-----------------------------------------------------------------------
      ed_cols &amp;lt;- ed_cols + 1
    }
  }
  
  #---------------------------------------------------------------------------
  # Return the subset of the expanded matrix which corresponds to the
  # original matrix
  #---------------------------------------------------------------------------
  em[border + seq(nrow(m)), border + seq(ncol(m))]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;appendix-other-error-diffusion-matrices&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Appendix: Other error diffusion matrices&lt;/h1&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;edms &amp;lt;- list(
#-----------------------------------------------------------------------------
# 1-d Error Diffusion (only pushes error forwards to the next pixel) 
#-----------------------------------------------------------------------------
one_d = matrix(
  c(NA, 1), 
  ncol=2, byrow = TRUE),


#-----------------------------------------------------------------------------
# Floyd Steinberg 
#-----------------------------------------------------------------------------
floyd_steinberg = matrix(
  c(0, NA, 7, 
    3,  5, 1), 
  ncol=3, byrow = TRUE) / 16,


#-----------------------------------------------------------------------------
# Fake Floyd Steinberg 
#-----------------------------------------------------------------------------
fake_floyd_steinberg = matrix(
  c(NA, 3, 
    3 , 2), 
  ncol=2, byrow = TRUE) / 8,


#-----------------------------------------------------------------------------
# Stucki
#-----------------------------------------------------------------------------
stucki = matrix(
  c(0, 0, NA, 8, 4,
    2, 4, 8 , 4, 2, 
    1, 2, 4 , 2, 1), 
  ncol=5, byrow = TRUE) / 42,


#-----------------------------------------------------------------------------
# Burkes
#-----------------------------------------------------------------------------
burkes = matrix(
  c(0, 0, NA, 8, 4,
    2, 4,  8, 4, 2), 
  ncol=5, byrow = TRUE) / 32,


#-----------------------------------------------------------------------------
# Atkinson
#-----------------------------------------------------------------------------
atkinson = matrix(
  c(0, NA, 1, 1,
    1,  1, 1, 0, 
    0,  1, 0, 0), 
  ncol=4, byrow = TRUE) / 8,


#-----------------------------------------------------------------------------
# Jarvis Judice Ninke
#-----------------------------------------------------------------------------
jarvis_judice_ninke = matrix(
  c(0, 0, NA, 7, 5,
    3, 5,  7, 5, 3, 
    1, 3,  5, 3, 1), 
  ncol=5, byrow = TRUE) / 48,


#-----------------------------------------------------------------------------
# Sierra
#-----------------------------------------------------------------------------
sierra = matrix(
  c(0, 0, NA, 5, 3,
    2, 4,  5, 4, 2, 
    0, 2,  3, 2, 0), 
  ncol=5, byrow = TRUE) / 32,


#-----------------------------------------------------------------------------
# Two-row Sierra
#-----------------------------------------------------------------------------
two_row_sierra = matrix(
  c(0, 0, NA, 4, 3,
    1, 2,  3, 2, 1), 
  ncol=5, byrow = TRUE) / 16,


#-----------------------------------------------------------------------------
# Sierra Lite
#-----------------------------------------------------------------------------
sierra_lite = matrix(
  c(0, NA, 2, 
    1,  1, 0),
  ncol=3, byrow = TRUE) / 4
)&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&#34;one-d&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;one d&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;floyd-steinberg&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;floyd steinberg&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-2.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;fake-floyd-steinberg&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;fake floyd steinberg&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-3.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;stucki&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;stucki&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-4.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;burkes&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;burkes&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-5.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;atkinson&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;atkinson&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-6.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;jarvis-judice-ninke&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;jarvis judice ninke&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-7.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sierra&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;sierra&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-8.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;two-row-sierra&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;two row sierra&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-9.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;sierra-lite&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;sierra lite&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://coolbutuseless.github.io/post/2018-02-04-dithering_files/figure-html/unnamed-chunk-7-10.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>YAML vs JSON for saving human-readable R objects  (TLDR: Use YAML)</title>
      <link>https://coolbutuseless.github.io/2018/02/03/yaml-vs-json-for-saving-human-readable-r-objects-tldr-use-yaml/</link>
      <pubDate>Sat, 03 Feb 2018 08:00:00 +1000</pubDate>
      
      <guid>https://coolbutuseless.github.io/2018/02/03/yaml-vs-json-for-saving-human-readable-r-objects-tldr-use-yaml/</guid>
      <description>
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/jquery/jquery.min.js&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;https://coolbutuseless.github.io/rmarkdown-libs/elevate-section-attrs/elevate-section-attrs.js&#34;&gt;&lt;/script&gt;


&lt;div id=&#34;problem-serialization-of-r-list-objects-to-a-human-readableeditable-file&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Problem: serialization of R &lt;code&gt;list&lt;/code&gt; objects to a human readable/editable file&lt;/h2&gt;
&lt;p&gt;I often use R &lt;code&gt;list&lt;/code&gt; objects for storing configuration information within shiny apps. These are used to define multiple
configuration sets and are usually saved to file. I then want to be able to edit the objects on the filesystem with a text editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What’s a good file format for saving R &lt;code&gt;list&lt;/code&gt; objects to file such that they’re easily editable?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;has an R package I can use&lt;/li&gt;
&lt;li&gt;easy to read and edit the saved data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not Criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;interoperability with other software&lt;/li&gt;
&lt;li&gt;transmission over a network&lt;/li&gt;
&lt;li&gt;saving to a database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RDS - even though there’s an &lt;code&gt;ascii&lt;/code&gt; option to &lt;code&gt;saveRDS&lt;/code&gt; it doesn’t save anything that’s human parseable&lt;/li&gt;
&lt;li&gt;CSV - Never going to be able to save nested &lt;code&gt;list&lt;/code&gt; data (with &lt;code&gt;NULL&lt;/code&gt; values!) to a CSV without a whole lot of pre- and post- data transformation&lt;/li&gt;
&lt;li&gt;YAML - worth a look.&lt;/li&gt;
&lt;li&gt;JSON - worth a look.&lt;/li&gt;
&lt;li&gt;XML - hand editing XML nodes in a text file seems like a good way to shoot yourself in the foot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Actual contenders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://json.org&#34;&gt;JSON&lt;/a&gt; - Packages: &lt;a href=&#34;https://cran.r-project.org/web/packages/RJSONIO/index.html&#34;&gt;RJSONIO&lt;/a&gt;, &lt;a href=&#34;https://cran.r-project.org/web/packages/jsonlite/index.html&#34;&gt;jsonlite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://yaml.org&#34;&gt;YAML&lt;/a&gt; - Package: &lt;a href=&#34;https://cran.r-project.org/web/packages/yaml/index.html&#34;&gt;YAML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;example-r-list-object&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Example R list object&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colour_scheme &amp;lt;- list(
  plain = list(
    top         = &amp;#39;black&amp;#39;,
    bottom      = &amp;#39;black&amp;#39;,
    size        = 1,
    angle       = 45.0,
    sub_options = list(),
    border      = NULL,
    tune        = NA
  ),
  fancy = list(
    top         = &amp;#39;red&amp;#39;,
    bottom      = &amp;#39;blue&amp;#39;,
    size        = 5,
    angle       = 17.5,
    sub_options = list(pieces_of_flair = c(0, 37)),
    border      = &amp;#39;cursive&amp;#39;,
    tune        = &amp;#39;adagio&amp;#39;
  )
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;jsonlite-json-encoding-the-r-list&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;jsonlite&lt;/code&gt;: JSON encoding the R list&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colour_scheme_json &amp;lt;- jsonlite::toJSON(colour_scheme, pretty=TRUE) 
colour_scheme_json&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;plain&amp;quot;: {
    &amp;quot;top&amp;quot;: [&amp;quot;black&amp;quot;],
    &amp;quot;bottom&amp;quot;: [&amp;quot;black&amp;quot;],
    &amp;quot;size&amp;quot;: [1],
    &amp;quot;angle&amp;quot;: [45],
    &amp;quot;sub_options&amp;quot;: [],
    &amp;quot;border&amp;quot;: {},
    &amp;quot;tune&amp;quot;: [null]
  },
  &amp;quot;fancy&amp;quot;: {
    &amp;quot;top&amp;quot;: [&amp;quot;red&amp;quot;],
    &amp;quot;bottom&amp;quot;: [&amp;quot;blue&amp;quot;],
    &amp;quot;size&amp;quot;: [5],
    &amp;quot;angle&amp;quot;: [17.5],
    &amp;quot;sub_options&amp;quot;: {
      &amp;quot;pieces_of_flair&amp;quot;: [0, 37]
    },
    &amp;quot;border&amp;quot;: [&amp;quot;cursive&amp;quot;],
    &amp;quot;tune&amp;quot;: [&amp;quot;adagio&amp;quot;]
  }
} &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;jsonlite-restoring-the-r-list-from-json&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;jsonlite&lt;/code&gt;: Restoring the R list from JSON&lt;/h2&gt;
&lt;p&gt;When the R object is recreated from the JSON, the result is not identical to the
original data.&lt;/p&gt;
&lt;p&gt;This is because the original &lt;code&gt;border = NULL&lt;/code&gt; in the data was represented in JSON as
an empty list. Upon restoration, the R object contains &lt;code&gt;border = list()&lt;/code&gt; instead of the
required &lt;code&gt;NULL&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;restored_json &amp;lt;- jsonlite::fromJSON(colour_scheme_json)
identical(colour_scheme, restored_json)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rjsonio-json-encoding-the-r-list&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;RJSONIO&lt;/code&gt;: JSON encoding the R list&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colour_scheme_json2 &amp;lt;- RJSONIO::toJSON(colour_scheme, pretty=TRUE) 
cat(colour_scheme_json2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{
    &amp;quot;plain&amp;quot; : {
        &amp;quot;top&amp;quot; : &amp;quot;black&amp;quot;,
        &amp;quot;bottom&amp;quot; : &amp;quot;black&amp;quot;,
        &amp;quot;size&amp;quot; : 1,
        &amp;quot;angle&amp;quot; : 45,
        &amp;quot;sub_options&amp;quot; : [],
        &amp;quot;border&amp;quot; : null,
        &amp;quot;tune&amp;quot; : null
    },
    &amp;quot;fancy&amp;quot; : {
        &amp;quot;top&amp;quot; : &amp;quot;red&amp;quot;,
        &amp;quot;bottom&amp;quot; : &amp;quot;blue&amp;quot;,
        &amp;quot;size&amp;quot; : 5,
        &amp;quot;angle&amp;quot; : 17.5,
        &amp;quot;sub_options&amp;quot; : {
            &amp;quot;pieces_of_flair&amp;quot; : [
                0,
                37
            ]
        },
        &amp;quot;border&amp;quot; : &amp;quot;cursive&amp;quot;,
        &amp;quot;tune&amp;quot; : &amp;quot;adagio&amp;quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;rjsonio-restoring-the-r-list-from-json&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;&lt;code&gt;RJSONIO&lt;/code&gt;: Restoring the R list from JSON&lt;/h2&gt;
&lt;p&gt;When the R object is recreated from the JSON, the result is not identical to the
original data.&lt;/p&gt;
&lt;p&gt;This is because the original &lt;code&gt;tune = NA&lt;/code&gt; in the data was represented in JSON as
a null. Upon restoration, the R object contains &lt;code&gt;tune=NULL&lt;/code&gt; instead of the
required &lt;code&gt;NA&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RJSONIO&lt;/code&gt; allows you to specify how &lt;code&gt;NAs&lt;/code&gt; are encoded, but there does not seem to be
a direct representation of &lt;code&gt;NA&lt;/code&gt; in the JSON format.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;restored_json2 &amp;lt;- RJSONIO::fromJSON(colour_scheme_json2)
identical(colour_scheme, restored_json2)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] FALSE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;yaml-encoding-the-r-list&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;YAML encoding the R list&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;colour_scheme_yaml &amp;lt;- yaml::as.yaml(colour_scheme) 
cat(colour_scheme_yaml)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;plain:
  top: black
  bottom: black
  size: 1.0
  angle: 45.0
  sub_options: []
  border: ~
  tune: .na
fancy:
  top: red
  bottom: blue
  size: 5.0
  angle: 17.5
  sub_options:
    pieces_of_flair:
    - 0.0
    - 37.0
  border: cursive
  tune: adagio&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;restoring-the-r-list-from-yaml&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Restoring the R list from YAML&lt;/h2&gt;
&lt;p&gt;When the R object is recreated from the YAML, the result is identical to the
original data.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;restored_yaml &amp;lt;- yaml::yaml.load(colour_scheme_yaml)
identical(colour_scheme, restored_yaml)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] TRUE&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;named-vectors-and-named-lists&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Named Vectors and Named lists&lt;/h2&gt;
&lt;p&gt;Both &lt;code&gt;jsonlite&lt;/code&gt; and &lt;code&gt;yaml&lt;/code&gt; convert a named vector into a plain array i.e. the names are stripped.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RJSONIO&lt;/code&gt; saves a named vector as a map (meaning that names are kept) but as a side effect, restoring a map with only
a single primitive datatype produces a vector and not a list.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;named_vec   &amp;lt;-    c(a=1, b=2, c=3)
named_list  &amp;lt;- list(a=1, b=2, c=3)
named_list2 &amp;lt;- list(a=1, b=&amp;#39;cat&amp;#39;)

yaml::as.yaml(named_vec)     %&amp;gt;% cat()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;- 1.0
- 2.0
- 3.0&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;jsonlite::toJSON(named_vec)  %&amp;gt;% cat()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1,2,3]&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;RJSONIO::toJSON(named_vec)   %&amp;gt;% cat()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{
 &amp;quot;a&amp;quot;:        1,
&amp;quot;b&amp;quot;:        2,
&amp;quot;c&amp;quot;:        3 
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;RJSONIO::toJSON(named_list)  %&amp;gt;% cat()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{
 &amp;quot;a&amp;quot;:        1,
&amp;quot;b&amp;quot;:        2,
&amp;quot;c&amp;quot;:        3 
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;RJSONIO::toJSON(named_vec)   %&amp;gt;% RJSONIO::fromJSON() %&amp;gt;% class()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;numeric&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;RJSONIO::toJSON(named_list)  %&amp;gt;% RJSONIO::fromJSON() %&amp;gt;% class()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;numeric&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;RJSONIO::toJSON(named_list2) %&amp;gt;% RJSONIO::fromJSON() %&amp;gt;% class()&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[1] &amp;quot;list&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;comparison&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Comparison&lt;/h2&gt;
&lt;p&gt;A table comparing the representations in YAML and JSON is shown below.&lt;/p&gt;
&lt;table&gt;
&lt;caption&gt;&lt;span id=&#34;tab:unnamed-chunk-9&#34;&gt;Table 1: &lt;/span&gt;Comparison&lt;/caption&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;JSON (jsonlite)&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;JSON (RJSONIO)&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;YAML&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;strings &amp;amp; names&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;quoted&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;quoted&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unquoted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;single value&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;arrays []&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as is&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;as is&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;vector&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;arrays []&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;arrays []&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;one-value-per-line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;{}&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;null&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;~&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[null]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;null (or user defined)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.na&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;whitespace&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;not significant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;not significant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;used for indentation and syntax. No TABs allowed!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td&gt;named vector&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;names kept&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;names lost&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;names lost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td&gt;restored list&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;not identical!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;not identical&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;identical&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;The YAML representation when restored to an R object is identical to the original R list.&lt;br /&gt;
The JSON restoration is not idential to the original data.&lt;/li&gt;
&lt;li&gt;The representations of &lt;code&gt;NULL&lt;/code&gt; and &lt;code&gt;NA&lt;/code&gt; values are “not like R” in both formats&lt;/li&gt;
&lt;li&gt;JSON’s quoting of all names and strings seems needlessly labour-intensive&lt;/li&gt;
&lt;li&gt;YAML’s whitespace usage for indentation and structure will be familiar to Python users&lt;/li&gt;
&lt;li&gt;YAML’s pickiness of “No TABs only spaces!” could be an issue. Need to ensure text editor
always replaces TABs with spaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;verdict&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Verdict&lt;/h2&gt;
&lt;p&gt;YAML.&lt;/p&gt;
&lt;p&gt;Reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;restored object is identical to original list&lt;/li&gt;
&lt;li&gt;more lightweight - no quoting of strings or names. Single values are not represented as short arrays.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NULL&lt;/code&gt; and &lt;code&gt;NA&lt;/code&gt; representation are a teeny tiny bit closer to how I’d think about them in R&lt;/li&gt;
&lt;li&gt;Familiarity with Python means I’m OK with whitespace being signficant.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&#34;updates&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Updates&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2018-02-03 10:00 - &lt;a href=&#34;http://www.twitter.com/heyaudy&#34;&gt;heyaudy&lt;/a&gt; gave some helpful feedback that the actual JSON output is dependent upon which package I use, and
that &lt;a href=&#34;https://cran.r-project.org/web/packages/RJSONIO/index.html&#34;&gt;RJSONIO&lt;/a&gt; handles single values and NULLs better than &lt;code&gt;jsonlite&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description>

    </item>
    
    <item>
      <title>About</title>
      <link>https://coolbutuseless.github.io/about/</link>
      <pubDate>Mon, 01 Jan 2018 08:00:00 +0000</pubDate>
      
      <guid>https://coolbutuseless.github.io/about/</guid>
      <description>&lt;p&gt;Mostly blogging about the R programming language.  Other topics which may arise: birds, urban design, cycling.&lt;/p&gt;
&lt;p&gt;Thanks to the &lt;a href=&#34;https://github.com/rstudio/blogdown&#34;&gt;blogdown package&lt;/a&gt; for making this blog possible using R&lt;/p&gt;
&lt;p&gt;All code appearing on this blog is licensed under MIT unless otherwise specified. See &lt;a href=&#34;https://coolbutuseless.github.io/license/&#34;&gt;License&lt;/a&gt;&lt;/p&gt;
</description>

    </item>
    
    <item>
      <title>License</title>
      <link>https://coolbutuseless.github.io/license/</link>
      <pubDate>Mon, 01 Jan 2018 08:00:00 +0000</pubDate>
      
      <guid>https://coolbutuseless.github.io/license/</guid>
      <description>&lt;p&gt;All code appearing on this blog is licensed under MIT unless otherwise specified.&lt;/p&gt;
&lt;p&gt;MIT License&lt;/p&gt;
&lt;p&gt;Copyright (c) 2018,2019,2020 &lt;a href=&#34;mailto:mikefc@coolbutuseless.com&#34;&gt;mikefc@coolbutuseless.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &amp;ldquo;Software&amp;rdquo;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:&lt;/p&gt;
&lt;p&gt;The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.&lt;/p&gt;
&lt;p&gt;THE SOFTWARE IS PROVIDED &amp;ldquo;AS IS&amp;rdquo;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.&lt;/p&gt;
</description>

    </item>
    
  </channel>
</rss>

