Greasy Fork

Greasy Fork is available in English.

GeometrizeLib

Turn your images into geometric primitives!

当前为 2025-06-28 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/521159/1615514/GeometrizeLib.js

(function ($hx_exports, $global, worker_code) {
  "use strict";
  $hx_exports["geometrize"] = $hx_exports["geometrize"] || {};
  $hx_exports["geometrize"]["bitmap"] = $hx_exports["geometrize"]["bitmap"] || {};
  $hx_exports["geometrize"]["exporter"] = $hx_exports["geometrize"]["exporter"] || {};
  $hx_exports["geometrize"]["runner"] = $hx_exports["geometrize"]["runner"] || {};
  $hx_exports["geometrize"]["shape"] = $hx_exports["geometrize"]["shape"] || {};
  function $extend(from, fields) {
    var proto = Object.create(from);
    for (var name in fields) proto[name] = fields[name];
    if (fields.toString !== Object.prototype.toString) proto.toString = fields.toString;
    return proto;
  }
  var CanvasTools = function () {};
  CanvasTools.__name__ = true;
  CanvasTools.downScaleCanvas = function (cv, scale) {
    if (scale <= 0.0 || scale >= 1.0) {
      throw haxe_Exception.thrown("Scale must be a positive number < 1");
    }
    var sqScale = scale * scale;
    var sw = cv.width;
    var sh = cv.height;
    var tw = (sw * scale) | 0;
    var th = (sh * scale) | 0;
    var sx = 0;
    var sy = 0;
    var sIndex = 0;
    var tx = 0;
    var ty = 0;
    var yIndex = 0;
    var tIndex = 0;
    var tX = 0;
    var tY = 0;
    var w = 0.0;
    var nw = 0.0;
    var wx = 0.0;
    var nwx = 0.0;
    var wy = 0.0;
    var nwy = 0.0;
    var crossX = false;
    var crossY = false;
    var sBuffer = cv.getContext("2d").getImageData(0, 0, sw, sh).data;
    var this1 = new Float32Array(3 * tw * th);
    var tBuffer = this1;
    var sR = 0.0;
    var sG = 0.0;
    var sB = 0.0;
    while (sy < sh) {
      ty = (sy * scale) | 0;
      tY = ty | 0;
      yIndex = (3 * tY * tw) | 0;
      crossY = tY != ((ty + scale) | 0);
      if (crossY) {
        wy = tY + 1 - ty;
        nwy = ty + scale - tY - 1;
      }
      sx = 0;
      while (sx < sw) {
        tx = (sx * scale) | 0;
        tX = tx | 0;
        tIndex = (yIndex + tX * 3) | 0;
        crossX = tX != Math.floor(tx + scale);
        if (crossX) {
          wx = tX + 1 - tx;
          nwx = (tx + scale - tX - 1) | 0;
        }
        sR = sBuffer[sIndex];
        sG = sBuffer[sIndex + 1];
        sB = sBuffer[sIndex + 2];
        if (!crossX && !crossY) {
          tBuffer[tIndex] += sR * sqScale;
          tBuffer[tIndex + 1] += sG * sqScale;
          tBuffer[tIndex + 2] += sB * sqScale;
        } else if (crossX && !crossY) {
          w = wx * scale;
          tBuffer[tIndex] += sR * w;
          tBuffer[tIndex + 1] += sG * w;
          tBuffer[tIndex + 2] += sB * w;
          nw = nwx * scale;
          tBuffer[tIndex + 3] += sR * nw;
          tBuffer[tIndex + 4] += sG * nw;
          tBuffer[tIndex + 5] += sB * nw;
        } else if (crossY && !crossX) {
          w = wy * scale;
          tBuffer[tIndex] += sR * w;
          tBuffer[tIndex + 1] += sG * w;
          tBuffer[tIndex + 2] += sB * w;
          nw = nwy * scale;
          tBuffer[tIndex + 3 * tw] += sR * nw;
          tBuffer[tIndex + 3 * tw + 1] += sG * nw;
          tBuffer[tIndex + 3 * tw + 2] += sB * nw;
        } else {
          w = wx * wy;
          tBuffer[tIndex] += sR * w;
          tBuffer[tIndex + 1] += sG * w;
          tBuffer[tIndex + 2] += sB * w;
          nw = nwx * wy;
          tBuffer[tIndex + 3] += sR * nw;
          tBuffer[tIndex + 4] += sG * nw;
          tBuffer[tIndex + 5] += sB * nw;
          nw = wx * nwy;
          tBuffer[tIndex + 3 * tw] += sR * nw;
          tBuffer[tIndex + 3 * tw + 1] += sG * nw;
          tBuffer[tIndex + 3 * tw + 2] += sB * nw;
          nw = nwx * nwy;
          tBuffer[tIndex + 3 * tw + 3] += sR * nw;
          tBuffer[tIndex + 3 * tw + 4] += sG * nw;
          tBuffer[tIndex + 3 * tw + 5] += sB * nw;
        }
        sIndex += 4;
        ++sx;
      }
      ++sy;
    }
    var result = window.document.createElement("canvas");
    result.width = tw;
    result.height = th;
    var resultContext = result.getContext("2d");
    var resultImage = resultContext.getImageData(0, 0, tw, th);
    var tByteBuffer = resultImage.data;
    var pxIndex = 0;
    sIndex = 0;
    tIndex = 0;
    while (pxIndex < tw * th) {
      tByteBuffer[tIndex] = Math.ceil(tBuffer[sIndex]);
      tByteBuffer[tIndex + 1] = Math.ceil(tBuffer[sIndex + 1]);
      tByteBuffer[tIndex + 2] = Math.ceil(tBuffer[sIndex + 2]);
      tByteBuffer[tIndex + 3] = 255;
      sIndex += 3;
      tIndex += 4;
      ++pxIndex;
    }
    resultContext.putImageData(resultImage, 0, 0);
    return result;
  };
  var GeometrizeWorkerInterface = function () {
    var _gthis = this;
    // this.worker = new Worker("js/geometrize_worker.js");
    // this.worker = new Worker("https://www.samcodes.co.uk/project/geometrize-haxe-web/js/geometrize_worker.js");
    // this.worker = new Worker("/userscripts/geometrize_worker.js");
    this.worker = new Worker(window.URL.createObjectURL(new Blob([worker_code], { type: "text/javascript" })));
    console.log(this.worker);
    this.worker.onmessage = function (message) {
      _gthis.onMessage(message.data);
    };
  };
  GeometrizeWorkerInterface.__name__ = true;
  GeometrizeWorkerInterface.prototype = {
    postMessage: function (message) {
      this.worker.postMessage(message);
    },
    terminate: function () {
      this.worker.terminate();
    },
    onMessage: function (message) {},
  };
  var HxOverrides = function () {};
  HxOverrides.__name__ = true;
  HxOverrides.remove = function (a, obj) {
    var i = a.indexOf(obj);
    if (i == -1) {
      return false;
    }
    a.splice(i, 1);
    return true;
  };
  HxOverrides.now = function () {
    return Date.now();
  };
  var Main = function () {
    this.targetImage = null;
    this.shapeJsonData = [];
    this.shapeSvgData = [];
    this.shapeMutationsPerStep = 100;
    this.candidateShapesPerStep = 50;
    this.initialBackgroundOpacity = 255;
    this.shapeOpacity = 128;
    this.shapeTypes = geometrize_ArraySet.create([5, 6]);
    this.maxInputImageSize = 768;
    window.addEventListener("GeometrizeInitialize", $bind(this, this.onWindowLoaded));
    // window.onload = $bind(this, this.onWindowLoaded);
  };
  Main.__name__ = true;
  Main.main = function () {
    var main = new Main();
  };
  Main.prototype = {
    get_shapeCount: function () {
      return this.shapeSvgData.length;
    },
    get_maxShapeCountLimit: function () {
      var text = Main.maxShapesCapTextEdit.value;
      var value = Std.parseInt(text);
      if (value != null) {
        return value;
      }
      return 3000;
    },
    set_maxShapeCountLimit: function (limit) {
      Main.maxShapesCapTextEdit.value = limit == null ? "null" : "" + limit;
      return limit;
    },
    onWindowLoaded: function () {
      var _gthis = this;
      Main.runPauseButton = window.document.getElementById("runpausebutton");
      Main.stepButton = window.document.getElementById("stepbutton");
      Main.openImageFileInput = window.document.getElementById("openimageinput");
      Main.randomImageButton = window.document.getElementById("randomimagebutton");
      Main.resetButton = window.document.getElementById("resetbutton");
      Main.saveImageButton = window.document.getElementById("saveimagebutton");
      Main.saveSvgButton = window.document.getElementById("savesvgbutton");
      Main.saveJsonButton = window.document.getElementById("savejsonbutton");
      Main.rectanglesCheckbox = window.document.getElementById("rectangles");
      Main.rotatedRectanglesCheckbox = window.document.getElementById("rotatedrectangles");
      Main.trianglesCheckbox = window.document.getElementById("triangles");
      Main.ellipsesCheckbox = window.document.getElementById("ellipses");
      Main.rotatedEllipsesCheckbox = window.document.getElementById("rotatedellipses");
      Main.circlesCheckbox = window.document.getElementById("circles");
      Main.linesCheckbox = window.document.getElementById("lines");
      Main.quadraticBeziersCheckbox = window.document.getElementById("quadraticbeziers");
      Main.shapeOpacitySlider = window.document.getElementById("shapeopacity");
      Main.initialBackgroundOpacitySlider = window.document.getElementById("initialbackgroundopacity");
      Main.randomShapesPerStepSlider = window.document.getElementById("randomshapesperstep");
      Main.shapeMutationsPerStepSlider = window.document.getElementById("shapemutationsperstep");
      Main.shapesAddedText = window.document.getElementById("shapesaddedtext");
      Main.maxShapesCapTextEdit = window.document.getElementById("maxshapescaptextedit");
      Main.currentSvgContainer = window.document.getElementById("currentsvgcontainer");
      Main.sampleImagesContainer = window.document.getElementById("sampleimages");
      Main.defaultImageElement = window.document.getElementById("defaultimage");

      _gthis.shapeOpacity = 255;
      _gthis.initialBackgroundOpacity = 0;
      var _gthis1 = this;
      Main.runPauseButton.addEventListener(
        "click",
        function () {
          _gthis1.set_running(!_gthis1.running);
        },
        false
      );
      Main.openImageFileInput.addEventListener(
        "change",
        function (e) {
          if (Main.openImageFileInput.files == null || Main.openImageFileInput.files.length == 0) {
            return;
          }
          var file = Main.openImageFileInput.files[0];
          var fileReader = new FileReader();
          fileReader.onload = function (e) {
            var image = new Image();
            image.onload = function (e) {
              var canvas = _gthis1.imageToCanvas(image);
              while (canvas.width > _gthis1.maxInputImageSize || canvas.height > _gthis1.maxInputImageSize) canvas = CanvasTools.downScaleCanvas(canvas, 0.5);
              _gthis1.targetImage = _gthis1.canvasToBitmap(canvas);
              _gthis1.onTargetImageChanged();
            };
            image.src = fileReader.result;
          };
          fileReader.readAsDataURL(file);
          Main.openImageFileInput.files = null;
        },
        false
      );
      Main.stepButton.addEventListener(
        "click",
        function () {
          _gthis1.stepRunner();
        },
        false
      );
      Main.randomImageButton.addEventListener(
        "click",
        function () {
          var image = new Image();
          image.onload = function () {
            Main.sampleImagesContainer.appendChild(image);
            var _gthis = _gthis1;
            var tmp = _gthis1.imageToCanvas(image);
            _gthis1.targetImage = _gthis.canvasToBitmap(tmp);
            _gthis1.onTargetImageChanged();
          };
          var tmp = Main.imagesToGeometrize;
          var tmp1 = Math.floor(Math.random() * Main.imagesToGeometrize.length);
          image.src = tmp[tmp1];
        },
        false
      );
      Main.resetButton.addEventListener(
        "click",
        function () {
          _gthis1.targetImage = _gthis1.targetImage;
          _gthis1.onTargetImageChanged();
        },
        false
      );
      Main.saveImageButton.addEventListener(
        "click",
        function (e) {
          var svgData = "data:image/svg+xml;base64," + window.btoa(_gthis1.makeSvgData());
          var svgImage = new Image();
          svgImage.onload = function () {
            var canvas = _gthis1.imageToCanvas(svgImage);
            if (canvas.msToBlob != null) {
              var blob = canvas.msToBlob();
              var navigator = window.navigator;
              navigator.msSaveBlob(blob, "geometrized_image.png");
            } else {
              var data = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
              var tempLink = window.document.createElement("a");
              tempLink.href = data;
              tempLink.download = "geometrized_image.png";
              window.document.body.appendChild(tempLink);
              tempLink.click();
              window.document.body.removeChild(tempLink);
            }
          };
          svgImage.setAttribute("src", svgData);
        },
        false
      );
      var saveBlob = function (data, dataType, filename, anchor) {
        var blob = new Blob([data], { type: dataType });
        var navigator = window.navigator;
        if (navigator.msSaveBlob != null) {
          navigator.msSaveBlob(blob, filename);
        } else {
          var dataUrl = URL.createObjectURL(blob);
          anchor.download = filename;
          anchor.href = dataUrl;
        }
      };
      Main.saveSvgButton.addEventListener(
        "click",
        function (e) {
          saveBlob(Main.currentSvgContainer.innerHTML, "image/svg+xml;charset=utf-8", "geometrized_svg.svg", Main.saveSvgButton);
        },
        false
      );
      Main.saveJsonButton.addEventListener(
        "click",
        function (e) {
          saveBlob("[\r\n" + _gthis1.shapeJsonData.join(",\r\n") + "\r\n]", "data:text/json;charset=utf-8", "geometrized_json.json", Main.saveJsonButton);
        },
        false
      );
      var setShapeOption = function (option, enable) {
        if (enable) {
          geometrize_ArraySet.add(_gthis1.shapeTypes, option);
        } else {
          HxOverrides.remove(_gthis1.shapeTypes, option);
        }
      };
      Main.rectanglesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(0, Main.rectanglesCheckbox.checked);
        },
        false
      );
      Main.rotatedRectanglesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(1, Main.rotatedRectanglesCheckbox.checked);
        },
        false
      );
      Main.trianglesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(2, Main.trianglesCheckbox.checked);
        },
        false
      );
      Main.ellipsesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(3, Main.ellipsesCheckbox.checked);
        },
        false
      );
      Main.rotatedEllipsesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(4, Main.rotatedEllipsesCheckbox.checked);
        },
        false
      );
      Main.circlesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(5, Main.circlesCheckbox.checked);
        },
        false
      );
      Main.linesCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(6, Main.linesCheckbox.checked);
        },
        false
      );
      Main.quadraticBeziersCheckbox.addEventListener(
        "click",
        function () {
          setShapeOption(7, Main.quadraticBeziersCheckbox.checked);
        },
        false
      );
      this.set_maxShapeCountLimit(1000);
      if (this.worker != null) {
        this.worker.terminate();
      }
      this.worker = new GeometrizeWorkerInterface();
      this.worker.onMessage = $bind(this, this.onWorkerMessageReceived);
      // this.targetImage = this.createDefaultBitmap();
      // this.onTargetImageChanged();
      this.set_running(false);

      globalThis["geometrize"] = this;
    },
    createTooltips: function (slider) {
      var tipHandles = slider.getElementsByClassName("noUi-handle");
      var _g = 0;
      var _g1 = tipHandles.length;
      while (_g < _g1) {
        var i = _g++;
        var div = window.document.createElement("div");
        div.className += "tooltip";
        tipHandles[i].appendChild(div);
        this.updateTooltips(slider, i, 0);
      }
    },
    updateTooltips: function (slider, handleIdx, value) {
      var tipHandles = slider.getElementsByClassName("noUi-handle");
      tipHandles[handleIdx].innerHTML = "<span class='tooltip'>" + (value == null ? "null" : "" + value) + "</span>";
    },
    checkStopConditions: function () {
      if (this.get_shapeCount() >= this.get_maxShapeCountLimit()) {
        this.set_running(false);
      }
    },
    stepRunner: function () {
      var options = {
        shapeTypes: this.shapeTypes.length == 0 ? [2] : geometrize_ArraySet.toArray(this.shapeTypes),
        alpha: this.shapeOpacity | 0,
        candidateShapesPerStep: this.candidateShapesPerStep,
        shapeMutationsPerStep: this.shapeMutationsPerStep,
      };
      this.worker.postMessage({ id: "should_step", data: options });
    },
    onWorkerMessageReceived: function (message) {
      switch (message.id) {
        case "did_set_target_image":
          break;
        case "did_step":
          this.shapeJsonData.push(message.jsonData);
          this.appendSvgShapeData(message.svgData);
          this.checkStopConditions();
          break;
      }
      if (this.running) {
        this.stepRunner();
      }
    },
    appendSvgShapeData: function (data) {
      this.shapeSvgData.push(data);
      var tmp = this.get_shapeCount();
      Main.shapesAddedText.innerHTML = Std.string(tmp);
      var data = this.makeSvgData();
      this.setSvgElement(data);
    },
    setSvgElement: function (svgCode) {
      Main.currentSvgContainer.innerHTML = svgCode;
    },
    canvasToBitmap: function (canvas) {
      var context = canvas.getContext("2d", null);
      var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
      var bytesData = new haxe_io_Bytes(new ArrayBuffer(imageData.data.length));
      var _g = 0;
      var _g1 = bytesData.length;
      while (_g < _g1) {
        var i = _g++;
        bytesData.b[i] = imageData.data[i];
      }
      var w = canvas.width;
      var h = canvas.height;
      var bitmap = new geometrize_bitmap_Bitmap();
      if (bytesData == null) {
        throw haxe_Exception.thrown("FAIL: bytes != null");
      }
      var actual = bytesData.length;
      var expected = w * h * 4;
      if (actual != expected) {
        throw haxe_Exception.thrown("FAIL: values are not equal (expected: " + expected + ", actual: " + actual + ")");
      }
      bitmap.width = w;
      bitmap.height = h;
      var this1 = new Array((bytesData.length / 4) | 0);
      bitmap.data = this1;
      var i = 0;
      var x = 0;
      while (i < bytesData.length) {
        var red = bytesData.b[i];
        var green = bytesData.b[i + 1];
        var blue = bytesData.b[i + 2];
        var alpha = bytesData.b[i + 3];
        bitmap.data[x] =
          ((red < 0 ? 0 : red > 255 ? 255 : red) << 24) +
          ((green < 0 ? 0 : green > 255 ? 255 : green) << 16) +
          ((blue < 0 ? 0 : blue > 255 ? 255 : blue) << 8) +
          (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha);
        i += 4;
        ++x;
      }
      var bitmap1 = bitmap;
      return bitmap1;
    },
    imageToCanvas: function (image) {
      var canvas = window.document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      var context = canvas.getContext("2d", null);
      context.drawImage(image, 0, 0);
      return canvas;
    },
    createDefaultBitmap: function () {
      return this.canvasToBitmap(this.imageToCanvas(Main.defaultImageElement));
    },
    onTargetImageChanged: function () {
      var backgroundColor = geometrize_Util.getAverageImageColor(this.targetImage);
      var red = ((((backgroundColor >> 24) & 255) * this.initialBackgroundOpacity) / 255.0) | 0;
      var green = ((((backgroundColor >> 16) & 255) * this.initialBackgroundOpacity) / 255.0) | 0;
      var blue = ((((backgroundColor >> 8) & 255) * this.initialBackgroundOpacity) / 255.0) | 0;
      var alpha = this.initialBackgroundOpacity | 0;
      var premultipliedColor =
        ((red < 0 ? 0 : red > 255 ? 255 : red) << 24) +
        ((green < 0 ? 0 : green > 255 ? 255 : green) << 16) +
        ((blue < 0 ? 0 : blue > 255 ? 255 : blue) << 8) +
        (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha);
      var backgroundRect = new geometrize_shape_Rectangle(this.targetImage.width, this.targetImage.height);
      backgroundRect.x1 = 0;
      backgroundRect.y1 = 0;
      backgroundRect.x2 = this.targetImage.width - 1;
      backgroundRect.y2 = this.targetImage.height - 1;
      this.shapeSvgData = [];
      this.shapeJsonData = [];
      this.appendSvgShapeData(geometrize_exporter_SvgExporter.exportShape({ score: 0.0, color: premultipliedColor, shape: backgroundRect }));
      this.shapeJsonData.push(
        geometrize_exporter_ShapeJsonExporter.exportShape({
          score: 0.0,
          color: premultipliedColor,
          shape: backgroundRect,
        })
      );
      if (this.worker != null) {
        this.worker.terminate();
      }
      this.worker = new GeometrizeWorkerInterface();
      this.worker.onMessage = $bind(this, this.onWorkerMessageReceived);
      this.worker.postMessage({ id: "should_set_target_image", data: this.targetImage });
      if (this.running) {
        this.stepRunner();
      }
    },
    makeSvgData: function () {
      return (
        geometrize_exporter_SvgExporter.getSvgPrelude() +
        geometrize_exporter_SvgExporter.getSvgNodeOpen(this.targetImage.width, this.targetImage.height) +
        Std.string(this.shapeSvgData) +
        geometrize_exporter_SvgExporter.getSvgNodeClose()
      );
    },
    set_running: function (running) {
      // Main.runPauseButton.innerHTML = running ? "<h2>Pause</h2>" : "<h2>Run</h2>";
      var wasRunning = this.running;
      this.running = running;
      if (!wasRunning && this.running) {
        this.stepRunner();
      }
      return this.running;
    },
  };
  Math.__name__ = true;
  var Std = function () {};
  Std.__name__ = true;
  Std.string = function (s) {
    return js_Boot.__string_rec(s, "");
  };
  Std.parseInt = function (x) {
    if (x != null) {
      var _g = 0;
      var _g1 = x.length;
      while (_g < _g1) {
        var i = _g++;
        var c = x.charCodeAt(i);
        if (c <= 8 || (c >= 14 && c != 32 && c != 45)) {
          var nc = x.charCodeAt(i + 1);
          var v = parseInt(x, nc == 120 || nc == 88 ? 16 : 10);
          if (isNaN(v)) {
            return null;
          } else {
            return v;
          }
        }
      }
    }
    return null;
  };
  Std.random = function (x) {
    if (x <= 0) {
      return 0;
    } else {
      return Math.floor(Math.random() * x);
    }
  };
  var StringTools = function () {};
  StringTools.__name__ = true;
  StringTools.replace = function (s, sub, by) {
    return s.split(sub).join(by);
  };
  var UInt = {};
  UInt.toFloat = function (this1) {
    var int = this1;
    if (int < 0) {
      return 4294967296.0 + int;
    } else {
      return int + 0.0;
    }
  };
  var geometrize_ArraySet = {};
  geometrize_ArraySet.create = function (array) {
    if (array == null) {
      var this1 = [];
      return this1;
    }
    return geometrize_ArraySet.toSet(array);
  };
  geometrize_ArraySet.add = function (this1, element) {
    if (element == null) {
      throw haxe_Exception.thrown("FAIL: element != null");
    }
    if (geometrize_ArraySet.contains(this1, element)) {
      return false;
    }
    this1.push(element);
    return true;
  };
  geometrize_ArraySet.contains = function (this1, element) {
    var _g = 0;
    while (_g < this1.length) {
      var i = this1[_g];
      ++_g;
      if (i == element) {
        return true;
      }
    }
    return false;
  };
  geometrize_ArraySet.toArray = function (this1) {
    return this1.slice();
  };
  geometrize_ArraySet.toSet = function (array) {
    var this1 = [];
    var set = this1;
    var _g = 0;
    while (_g < array.length) {
      var v = array[_g];
      ++_g;
      geometrize_ArraySet.add(set, v);
    }
    return set;
  };
  var geometrize_Core = function () {};
  geometrize_Core.__name__ = true;
  geometrize_Core.computeColor = function (target, current, lines, alpha) {
    if (target == null) {
      throw haxe_Exception.thrown("FAIL: target != null");
    }
    if (current == null) {
      throw haxe_Exception.thrown("FAIL: current != null");
    }
    if (lines == null) {
      throw haxe_Exception.thrown("FAIL: lines != null");
    }
    if (alpha < 0) {
      throw haxe_Exception.thrown("FAIL: alpha >= 0");
    }
    var totalRed = 0;
    var totalGreen = 0;
    var totalBlue = 0;
    var count = 0;
    var f = 65535 / alpha;
    var a = f | 0;
    var _g = 0;
    while (_g < lines.length) {
      var line = lines[_g];
      ++_g;
      var y = line.y;
      var _g1 = line.x1;
      var _g2 = line.x2 + 1;
      while (_g1 < _g2) {
        var x = _g1++;
        var t = target.data[target.width * y + x];
        var c = current.data[current.width * y + x];
        totalRed += (((t >> 24) & 255) - ((c >> 24) & 255)) * a + ((c >> 24) & 255) * 257;
        totalGreen += (((t >> 16) & 255) - ((c >> 16) & 255)) * a + ((c >> 16) & 255) * 257;
        totalBlue += (((t >> 8) & 255) - ((c >> 8) & 255)) * a + ((c >> 8) & 255) * 257;
        ++count;
      }
    }
    if (count == 0) {
      return 0;
    }
    var value = ((totalRed / count) | 0) >> 8;
    var r = value < 0 ? 0 : value > 255 ? 255 : value;
    var value = ((totalGreen / count) | 0) >> 8;
    var g = value < 0 ? 0 : value > 255 ? 255 : value;
    var value = ((totalBlue / count) | 0) >> 8;
    var b = value < 0 ? 0 : value > 255 ? 255 : value;
    return ((r < 0 ? 0 : r > 255 ? 255 : r) << 24) + ((g < 0 ? 0 : g > 255 ? 255 : g) << 16) + ((b < 0 ? 0 : b > 255 ? 255 : b) << 8) + (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha);
  };
  geometrize_Core.differenceFull = function (first, second) {
    if (first == null) {
      throw haxe_Exception.thrown("FAIL: first != null");
    }
    if (second == null) {
      throw haxe_Exception.thrown("FAIL: second != null");
    }
    if (first.width == 0) {
      throw haxe_Exception.thrown("FAIL: first.width != 0");
    }
    if (first.height == 0) {
      throw haxe_Exception.thrown("FAIL: first.height != 0");
    }
    if (second.width == 0) {
      throw haxe_Exception.thrown("FAIL: second.width != 0");
    }
    if (second.height == 0) {
      throw haxe_Exception.thrown("FAIL: second.height != 0");
    }
    var actual = first.width;
    var expected = second.width;
    if (actual != expected) {
      throw haxe_Exception.thrown("FAIL: values are not equal (expected: " + expected + ", actual: " + actual + ")");
    }
    var actual = first.height;
    var expected = second.height;
    if (actual != expected) {
      throw haxe_Exception.thrown("FAIL: values are not equal (expected: " + expected + ", actual: " + actual + ")");
    }
    var total = 0;
    var width = first.width;
    var height = first.height;
    var _g = 0;
    var _g1 = height;
    while (_g < _g1) {
      var y = _g++;
      var _g2 = 0;
      var _g3 = width;
      while (_g2 < _g3) {
        var x = _g2++;
        var f = first.data[first.width * y + x];
        var s = second.data[second.width * y + x];
        var dr = ((f >> 24) & 255) - ((s >> 24) & 255);
        var dg = ((f >> 16) & 255) - ((s >> 16) & 255);
        var db = ((f >> 8) & 255) - ((s >> 8) & 255);
        var da = (f & 255) - (s & 255);
        total += dr * dr + dg * dg + db * db + da * da;
      }
    }
    var result = Math.sqrt(total / (width * height * 4.0)) / 255;
    if (!isFinite(result)) {
      throw haxe_Exception.thrown("FAIL: Math.isFinite(result)");
    }
    return result;
  };
  geometrize_Core.differencePartial = function (target, before, after, score, lines) {
    if (target == null) {
      throw haxe_Exception.thrown("FAIL: target != null");
    }
    if (before == null) {
      throw haxe_Exception.thrown("FAIL: before != null");
    }
    if (after == null) {
      throw haxe_Exception.thrown("FAIL: after != null");
    }
    if (lines == null) {
      throw haxe_Exception.thrown("FAIL: lines != null");
    }
    if (lines.length == 0) {
      throw haxe_Exception.thrown("FAIL: lines.length != 0");
    }
    var width = target.width;
    var height = target.height;
    var rgbaCount = width * height * 4;
    var total = Math.pow(score * 255, 2) * rgbaCount;
    var _g = 0;
    while (_g < lines.length) {
      var line = lines[_g];
      ++_g;
      var y = line.y;
      var _g1 = line.x1;
      var _g2 = line.x2 + 1;
      while (_g1 < _g2) {
        var x = _g1++;
        var t = target.data[target.width * y + x];
        var b = before.data[before.width * y + x];
        var a = after.data[after.width * y + x];
        var dtbr = ((t >> 24) & 255) - ((b >> 24) & 255);
        var dtbg = ((t >> 16) & 255) - ((b >> 16) & 255);
        var dtbb = ((t >> 8) & 255) - ((b >> 8) & 255);
        var dtba = (t & 255) - (b & 255);
        var dtar = ((t >> 24) & 255) - ((a >> 24) & 255);
        var dtag = ((t >> 16) & 255) - ((a >> 16) & 255);
        var dtab = ((t >> 8) & 255) - ((a >> 8) & 255);
        var dtaa = (t & 255) - (a & 255);
        total -= dtbr * dtbr + dtbg * dtbg + dtbb * dtbb + dtba * dtba;
        total += dtar * dtar + dtag * dtag + dtab * dtab + dtaa * dtaa;
      }
    }
    var result = Math.sqrt(total / rgbaCount) / 255;
    if (!isFinite(result)) {
      throw haxe_Exception.thrown("FAIL: Math.isFinite(result)");
    }
    return result;
  };
  geometrize_Core.bestRandomState = function (shapes, alpha, n, target, current, buffer, lastScore) {
    var bestEnergy = 0;
    var bestState = null;
    var _g = 0;
    var _g1 = n;
    while (_g < _g1) {
      var i = _g++;
      var state = new geometrize_State(geometrize_shape_ShapeFactory.randomShapeOf(shapes, current.width, current.height), alpha, target, current, buffer);
      var energy = state.energy(lastScore);
      if (i == 0 || energy < bestEnergy) {
        bestEnergy = energy;
        bestState = state;
      }
    }
    return bestState;
  };
  geometrize_Core.bestHillClimbState = function (shapes, alpha, n, age, target, current, buffer, lastScore) {
    var state = geometrize_Core.bestRandomState(shapes, alpha, n, target, current, buffer, lastScore);
    state = geometrize_Core.hillClimb(state, age, lastScore);
    return state;
  };
  geometrize_Core.hillClimb = function (state, maxAge, lastScore) {
    if (state == null) {
      throw haxe_Exception.thrown("FAIL: state != null");
    }
    if (maxAge < 0) {
      throw haxe_Exception.thrown("FAIL: maxAge >= 0");
    }
    var state1 = state.clone();
    var bestState = state1.clone();
    var bestEnergy = state1.energy(lastScore);
    var age = 0;
    while (age < maxAge) {
      var undo = state1.mutate();
      var energy = state1.energy(lastScore);
      if (energy >= bestEnergy) {
        state1 = undo;
      } else {
        bestEnergy = energy;
        bestState = state1.clone();
        age = -1;
      }
      ++age;
    }
    return bestState;
  };
  geometrize_Core.energy = function (shape, alpha, target, current, buffer, score) {
    if (shape == null) {
      throw haxe_Exception.thrown("FAIL: shape != null");
    }
    if (target == null) {
      throw haxe_Exception.thrown("FAIL: target != null");
    }
    if (current == null) {
      throw haxe_Exception.thrown("FAIL: current != null");
    }
    if (buffer == null) {
      throw haxe_Exception.thrown("FAIL: buffer != null");
    }
    var lines = shape.rasterize();
    if (lines == null) {
      throw haxe_Exception.thrown("FAIL: lines != null");
    }
    if (lines.length == 0) {
      throw haxe_Exception.thrown("FAIL: lines.length != 0");
    }
    var color = geometrize_Core.computeColor(target, current, lines, alpha);
    geometrize_rasterizer_Rasterizer.copyLines(buffer, current, lines);
    geometrize_rasterizer_Rasterizer.drawLines(buffer, color, lines);
    return geometrize_Core.differencePartial(target, current, buffer, score, lines);
  };
  var geometrize_Model = function (target, backgroundColor) {
    if (target == null) {
      throw haxe_Exception.thrown("FAIL: target != null");
    }
    this.width = target.width;
    this.height = target.height;
    this.target = target;
    var w = target.width;
    var h = target.height;
    var bitmap = new geometrize_bitmap_Bitmap();
    bitmap.width = w;
    bitmap.height = h;
    var this1 = new Array(w * h);
    bitmap.data = this1;
    var i = 0;
    while (i < bitmap.data.length) {
      bitmap.data[i] = backgroundColor;
      ++i;
    }
    this.current = bitmap;
    var w = target.width;
    var h = target.height;
    var bitmap = new geometrize_bitmap_Bitmap();
    bitmap.width = w;
    bitmap.height = h;
    var this1 = new Array(w * h);
    bitmap.data = this1;
    var i = 0;
    while (i < bitmap.data.length) {
      bitmap.data[i] = backgroundColor;
      ++i;
    }
    this.buffer = bitmap;
    this.score = geometrize_Core.differenceFull(target, this.current);
  };
  geometrize_Model.__name__ = true;
  geometrize_Model.prototype = {
    step: function (shapeTypes, alpha, n, age) {
      var state = geometrize_Core.bestHillClimbState(shapeTypes, alpha, n, age, this.target, this.current, this.buffer, this.score);
      var results = [this.addShape(state.shape, state.alpha)];
      return results;
    },
    addShape: function (shape, alpha) {
      if (shape == null) {
        throw haxe_Exception.thrown("FAIL: shape != null");
      }
      var _this = this.current;
      var bitmap = new geometrize_bitmap_Bitmap();
      bitmap.width = _this.width;
      bitmap.height = _this.height;
      var this1 = new Array(_this.data.length);
      bitmap.data = this1;
      var _g = 0;
      var _g1 = _this.data.length;
      while (_g < _g1) {
        var i = _g++;
        bitmap.data[i] = _this.data[i];
      }
      var before = bitmap;
      var lines = shape.rasterize();
      var color = geometrize_Core.computeColor(this.target, this.current, lines, alpha);
      geometrize_rasterizer_Rasterizer.drawLines(this.current, color, lines);
      this.score = geometrize_Core.differencePartial(this.target, before, this.current, this.score, lines);
      var result = { score: this.score, color: color, shape: shape };
      return result;
    },
  };
  var geometrize_State = function (shape, alpha, target, current, buffer) {
    if (shape == null) {
      throw haxe_Exception.thrown("FAIL: shape != null");
    }
    this.shape = shape;
    this.alpha = alpha;
    this.score = -1;
    this.target = target;
    this.current = current;
    this.buffer = buffer;
  };
  geometrize_State.__name__ = true;
  geometrize_State.prototype = {
    energy: function (lastScore) {
      if (this.score < 0) {
        this.score = geometrize_Core.energy(this.shape, this.alpha, this.target, this.current, this.buffer, lastScore);
      }
      return this.score;
    },
    mutate: function () {
      var oldState = this.clone();
      this.shape.mutate();
      return oldState;
    },
    clone: function () {
      return new geometrize_State(this.shape.clone(), this.alpha, this.target, this.current, this.buffer);
    },
  };
  var geometrize_Util = function () {};
  geometrize_Util.__name__ = true;
  geometrize_Util.getAverageImageColor = function (image, alpha) {
    if (alpha == null) {
      alpha = 255;
    }
    if (image == null) {
      throw haxe_Exception.thrown("FAIL: image != null");
    }
    var totalRed = 0;
    var totalGreen = 0;
    var totalBlue = 0;
    var _g = 0;
    var _g1 = image.width;
    while (_g < _g1) {
      var x = _g++;
      var _g2 = 0;
      var _g3 = image.height;
      while (_g2 < _g3) {
        var y = _g2++;
        var pixel = image.data[image.width * y + x];
        totalRed += (pixel >> 24) & 255;
        totalGreen += (pixel >> 16) & 255;
        totalBlue += (pixel >> 8) & 255;
      }
    }
    var size = image.width * image.height;
    var red = (totalRed / size) | 0;
    var green = (totalGreen / size) | 0;
    var blue = (totalBlue / size) | 0;
    return (
      ((red < 0 ? 0 : red > 255 ? 255 : red) << 24) +
      ((green < 0 ? 0 : green > 255 ? 255 : green) << 16) +
      ((blue < 0 ? 0 : blue > 255 ? 255 : blue) << 8) +
      (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha)
    );
  };
  var geometrize_bitmap_Bitmap = ($hx_exports["geometrize"]["bitmap"]["Bitmap"] = function () {});
  geometrize_bitmap_Bitmap.__name__ = true;
  geometrize_bitmap_Bitmap.create = function (w, h, color) {
    var bitmap = new geometrize_bitmap_Bitmap();
    bitmap.width = w;
    bitmap.height = h;
    var this1 = new Array(w * h);
    bitmap.data = this1;
    var i = 0;
    while (i < bitmap.data.length) {
      bitmap.data[i] = color;
      ++i;
    }
    return bitmap;
  };
  geometrize_bitmap_Bitmap.createFromBytes = function (w, h, bytes) {
    var bitmap = new geometrize_bitmap_Bitmap();
    if (bytes == null) {
      throw haxe_Exception.thrown("FAIL: bytes != null");
    }
    var actual = bytes.length;
    var expected = w * h * 4;
    if (actual != expected) {
      throw haxe_Exception.thrown("FAIL: values are not equal (expected: " + expected + ", actual: " + actual + ")");
    }
    bitmap.width = w;
    bitmap.height = h;
    var this1 = new Array((bytes.length / 4) | 0);
    bitmap.data = this1;
    var i = 0;
    var x = 0;
    while (i < bytes.length) {
      var red = bytes.b[i];
      var green = bytes.b[i + 1];
      var blue = bytes.b[i + 2];
      var alpha = bytes.b[i + 3];
      bitmap.data[x] =
        ((red < 0 ? 0 : red > 255 ? 255 : red) << 24) +
        ((green < 0 ? 0 : green > 255 ? 255 : green) << 16) +
        ((blue < 0 ? 0 : blue > 255 ? 255 : blue) << 8) +
        (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha);
      i += 4;
      ++x;
    }
    return bitmap;
  };
  geometrize_bitmap_Bitmap.createFromByteArray = function (w, h, bytes) {
    var data = new haxe_io_Bytes(new ArrayBuffer(bytes.length));
    var i = 0;
    while (i < bytes.length) {
      data.b[i] = bytes[i];
      ++i;
    }
    var bitmap = new geometrize_bitmap_Bitmap();
    if (data == null) {
      throw haxe_Exception.thrown("FAIL: bytes != null");
    }
    var actual = data.length;
    var expected = w * h * 4;
    if (actual != expected) {
      throw haxe_Exception.thrown("FAIL: values are not equal (expected: " + expected + ", actual: " + actual + ")");
    }
    bitmap.width = w;
    bitmap.height = h;
    var this1 = new Array((data.length / 4) | 0);
    bitmap.data = this1;
    var i = 0;
    var x = 0;
    while (i < data.length) {
      var red = data.b[i];
      var green = data.b[i + 1];
      var blue = data.b[i + 2];
      var alpha = data.b[i + 3];
      bitmap.data[x] =
        ((red < 0 ? 0 : red > 255 ? 255 : red) << 24) +
        ((green < 0 ? 0 : green > 255 ? 255 : green) << 16) +
        ((blue < 0 ? 0 : blue > 255 ? 255 : blue) << 8) +
        (alpha < 0 ? 0 : alpha > 255 ? 255 : alpha);
      i += 4;
      ++x;
    }
    return bitmap;
  };
  geometrize_bitmap_Bitmap.prototype = {
    getPixel: function (x, y) {
      return this.data[this.width * y + x];
    },
    setPixel: function (x, y, color) {
      this.data[this.width * y + x] = color;
    },
    clone: function () {
      var bitmap = new geometrize_bitmap_Bitmap();
      bitmap.width = this.width;
      bitmap.height = this.height;
      var this1 = new Array(this.data.length);
      bitmap.data = this1;
      var _g = 0;
      var _g1 = this.data.length;
      while (_g < _g1) {
        var i = _g++;
        bitmap.data[i] = this.data[i];
      }
      return bitmap;
    },
    fill: function (color) {
      var idx = 0;
      while (idx < this.data.length) {
        this.data[idx] = (color >> 24) & 255;
        this.data[idx + 1] = (color >> 16) & 255;
        this.data[idx + 2] = (color >> 8) & 255;
        this.data[idx + 3] = color & 255;
        idx += 4;
      }
    },
    getBytes: function () {
      var bytes = new haxe_io_Bytes(new ArrayBuffer(this.data.length * 4));
      var i = 0;
      while (i < this.data.length) {
        var idx = i * 4;
        bytes.b[idx] = (this.data[i] >> 24) & 255;
        bytes.b[idx + 1] = (this.data[i] >> 16) & 255;
        bytes.b[idx + 2] = (this.data[i] >> 8) & 255;
        bytes.b[idx + 3] = this.data[i] & 255;
        ++i;
      }
      return bytes;
    },
  };
  var geometrize_exporter_ShapeJsonExporter = ($hx_exports["geometrize"]["exporter"]["ShapeJsonExporter"] = function () {});
  geometrize_exporter_ShapeJsonExporter.__name__ = true;
  geometrize_exporter_ShapeJsonExporter.export = function (shapes) {
    return "[\n" + geometrize_exporter_ShapeJsonExporter.exportShapes(shapes) + "\n]";
  };
  geometrize_exporter_ShapeJsonExporter.exportShapes = function (shapes) {
    var results = "";
    var _g = 0;
    var _g1 = shapes.length;
    while (_g < _g1) {
      var i = _g++;
      results += geometrize_exporter_ShapeJsonExporter.exportShape(shapes[i]);
      if (i != shapes.length - 1) {
        results += ",\n";
      }
    }
    return results;
  };
  geometrize_exporter_ShapeJsonExporter.exportShape = function (shape) {
    var result = "    {\n";
    var type = shape.shape.getType();
    var data = shape.shape.getRawShapeData();
    var color = shape.color;
    var score = shape.score;
    result += '        "type":' + type + ",\n";
    result += '        "data":' + "[";
    var _g = 0;
    var _g1 = data.length;
    while (_g < _g1) {
      var item = _g++;
      result += data[item];
      if (item <= data.length - 2) {
        result += ",";
      }
    }
    result += "],\n";
    result += '        "color":' + "[";
    result += ((color >> 24) & 255) + ",";
    result += ((color >> 16) & 255) + ",";
    result += ((color >> 8) & 255) + ",";
    result += color & 255;
    result += "],\n";
    result += '        "score":' + score + "\n";
    result += "    }";
    return result;
  };
  var geometrize_exporter_SvgExporter = ($hx_exports["geometrize"]["exporter"]["SvgExporter"] = function () {});
  geometrize_exporter_SvgExporter.__name__ = true;
  geometrize_exporter_SvgExporter.export = function (shapes, width, height) {
    var results = geometrize_exporter_SvgExporter.getSvgPrelude();
    results += geometrize_exporter_SvgExporter.getSvgNodeOpen(width, height);
    results += geometrize_exporter_SvgExporter.exportShapes(shapes);
    results += geometrize_exporter_SvgExporter.getSvgNodeClose();
    return results;
  };
  geometrize_exporter_SvgExporter.exportShapes = function (shapes) {
    var results = "";
    var _g = 0;
    var _g1 = shapes.length;
    while (_g < _g1) {
      var i = _g++;
      results += geometrize_exporter_SvgExporter.exportShape(shapes[i]);
      if (i != shapes.length - 1) {
        results += "\n";
      }
    }
    return results;
  };
  geometrize_exporter_SvgExporter.exportShape = function (shape) {
    return StringTools.replace(shape.shape.getSvgShapeData(), geometrize_exporter_SvgExporter.SVG_STYLE_HOOK, geometrize_exporter_SvgExporter.stylesForShape(shape));
  };
  geometrize_exporter_SvgExporter.getSvgPrelude = function () {
    return '<?xml version="1.0" standalone="no"?>\n';
  };
  geometrize_exporter_SvgExporter.getSvgNodeOpen = function (width, height) {
    return '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="100" height="100" viewbox="0 0 ' + width + ' ' + height + '">\n';
  };
  geometrize_exporter_SvgExporter.getSvgNodeClose = function () {
    return "</svg>";
  };
  geometrize_exporter_SvgExporter.stylesForShape = function (shape) {
    switch (shape.shape.getType()) {
      case 6:
      case 7:
        return geometrize_exporter_SvgExporter.strokeForColor(shape.color) + ' stroke-width="1" fill="none" ' + geometrize_exporter_SvgExporter.strokeOpacityForAlpha(shape.color & 255);
      default:
        return geometrize_exporter_SvgExporter.fillForColor(shape.color) + " " + geometrize_exporter_SvgExporter.fillOpacityForAlpha(shape.color & 255);
    }
  };
  geometrize_exporter_SvgExporter.rgbForColor = function (color) {
    return "rgb(" + ((color >> 24) & 255) + "," + ((color >> 16) & 255) + "," + ((color >> 8) & 255) + ")";
  };
  geometrize_exporter_SvgExporter.strokeForColor = function (color) {
    return 'stroke="' + geometrize_exporter_SvgExporter.rgbForColor(color) + '"';
  };
  geometrize_exporter_SvgExporter.fillForColor = function (color) {
    return 'fill="' + geometrize_exporter_SvgExporter.rgbForColor(color) + '"';
  };
  geometrize_exporter_SvgExporter.fillOpacityForAlpha = function (alpha) {
    return 'fill-opacity="' + alpha / 255.0 + '"';
  };
  geometrize_exporter_SvgExporter.strokeOpacityForAlpha = function (alpha) {
    return 'stroke-opacity="' + alpha / 255.0 + '"';
  };
  var geometrize_rasterizer_Rasterizer = function () {};
  geometrize_rasterizer_Rasterizer.__name__ = true;
  geometrize_rasterizer_Rasterizer.drawLines = function (image, c, lines) {
    if (image == null) {
      throw haxe_Exception.thrown("FAIL: image != null");
    }
    if (lines == null) {
      throw haxe_Exception.thrown("FAIL: lines != null");
    }
    var sr = (c >> 24) & 255;
    sr |= sr << 8;
    sr *= c & 255;
    sr = (sr / 255) | 0;
    var sg = (c >> 16) & 255;
    sg |= sg << 8;
    sg *= c & 255;
    sg = (sg / 255) | 0;
    var sb = (c >> 8) & 255;
    sb |= sb << 8;
    sb *= c & 255;
    sb = (sb / 255) | 0;
    var sa = c & 255;
    sa |= sa << 8;
    var _g = 0;
    while (_g < lines.length) {
      var line = lines[_g];
      ++_g;
      var y = line.y;
      var ma = 65535;
      var m = 65535;
      var as = (m - sa * (ma / m)) * 257;
      var a = as | 0;
      var _g1 = line.x1;
      var _g2 = line.x2 + 1;
      while (_g1 < _g2) {
        var x = _g1++;
        var d = image.data[image.width * y + x];
        var dr = (d >> 24) & 255;
        var dg = (d >> 16) & 255;
        var db = (d >> 8) & 255;
        var da = d & 255;
        var r = ((UInt.toFloat(dr * a + sr * ma) / UInt.toFloat(m)) | 0) >> 8;
        var g = ((UInt.toFloat(dg * a + sg * ma) / UInt.toFloat(m)) | 0) >> 8;
        var b = ((UInt.toFloat(db * a + sb * ma) / UInt.toFloat(m)) | 0) >> 8;
        var a1 = ((UInt.toFloat(da * a + sa * ma) / UInt.toFloat(m)) | 0) >> 8;
        image.data[image.width * y + x] =
          ((r < 0 ? 0 : r > 255 ? 255 : r) << 24) + ((g < 0 ? 0 : g > 255 ? 255 : g) << 16) + ((b < 0 ? 0 : b > 255 ? 255 : b) << 8) + (a1 < 0 ? 0 : a1 > 255 ? 255 : a1);
      }
    }
  };
  geometrize_rasterizer_Rasterizer.copyLines = function (destination, source, lines) {
    if (destination == null) {
      throw haxe_Exception.thrown("FAIL: destination != null");
    }
    if (source == null) {
      throw haxe_Exception.thrown("FAIL: source != null");
    }
    if (lines == null) {
      throw haxe_Exception.thrown("FAIL: lines != null");
    }
    var _g = 0;
    while (_g < lines.length) {
      var line = lines[_g];
      ++_g;
      var y = line.y;
      var _g1 = line.x1;
      var _g2 = line.x2 + 1;
      while (_g1 < _g2) {
        var x = _g1++;
        destination.data[destination.width * y + x] = source.data[source.width * y + x];
      }
    }
  };
  geometrize_rasterizer_Rasterizer.bresenham = function (x1, y1, x2, y2) {
    var dx = x2 - x1;
    var ix = (dx > 0 ? 1 : 0) - (dx < 0 ? 1 : 0);
    dx = (dx < 0 ? -dx : dx) << 1;
    var dy = y2 - y1;
    var iy = (dy > 0 ? 1 : 0) - (dy < 0 ? 1 : 0);
    dy = (dy < 0 ? -dy : dy) << 1;
    var points = [];
    points.push({ x: x1, y: y1 });
    if (dx >= dy) {
      var error = dy - (dx >> 1);
      while (x1 != x2) {
        if (error >= 0 && (error != 0 || ix > 0)) {
          error -= dx;
          y1 += iy;
        }
        error += dy;
        x1 += ix;
        points.push({ x: x1, y: y1 });
      }
    } else {
      var error = dx - (dy >> 1);
      while (y1 != y2) {
        if (error >= 0 && (error != 0 || iy > 0)) {
          error -= dy;
          x1 += ix;
        }
        error += dx;
        y1 += iy;
        points.push({ x: x1, y: y1 });
      }
    }
    return points;
  };
  geometrize_rasterizer_Rasterizer.scanlinesForPolygon = function (points) {
    var lines = [];
    var edges = [];
    var _g = 0;
    var _g1 = points.length;
    while (_g < _g1) {
      var i = _g++;
      var p1 = points[i];
      var p2 = i == points.length - 1 ? points[0] : points[i + 1];
      var p1p2 = geometrize_rasterizer_Rasterizer.bresenham(p1.x, p1.y, p2.x, p2.y);
      edges = edges.concat(p1p2);
    }
    var yToXs = new haxe_ds_IntMap();
    var _g = 0;
    while (_g < edges.length) {
      var point = edges[_g];
      ++_g;
      var s = yToXs.h[point.y];
      if (s != null) {
        geometrize_ArraySet.add(s, point.x);
      } else {
        s = geometrize_ArraySet.create();
        geometrize_ArraySet.add(s, point.x);
        yToXs.h[point.y] = s;
      }
    }
    var key = yToXs.keys();
    while (key.hasNext()) {
      var key1 = key.next();
      var a = geometrize_ArraySet.toArray(yToXs.h[key1]);
      var minMaxElements;
      if (a == null || a.length == 0) {
        minMaxElements = { x: 0, y: 0 };
      } else {
        var min = a[0];
        var max = a[0];
        var _g = 0;
        while (_g < a.length) {
          var value = a[_g];
          ++_g;
          if (min > value) {
            min = value;
          }
          if (max < value) {
            max = value;
          }
        }
        minMaxElements = { x: min, y: max };
      }
      lines.push(new geometrize_rasterizer_Scanline(key1, minMaxElements.x, minMaxElements.y));
    }
    return lines;
  };
  var geometrize_rasterizer_Scanline = function (y, x1, x2) {
    this.y = y;
    this.x1 = x1;
    this.x2 = x2;
  };
  geometrize_rasterizer_Scanline.__name__ = true;
  geometrize_rasterizer_Scanline.trim = function (scanlines, w, h) {
    if (scanlines == null) {
      throw haxe_Exception.thrown("FAIL: scanlines != null");
    }
    var w1 = w;
    var h1 = h;
    var f = function (line) {
      if (line.y < 0 || line.y >= h1 || line.x1 >= w1 || line.x2 < 0) {
        return false;
      } else {
        var value = line.x1;
        var max = w1 - 1;
        if (0 > max) {
          throw haxe_Exception.thrown("FAIL: min <= max");
        }
        line.x1 = value < 0 ? 0 : value > max ? max : value;
        var value = line.x2;
        var max = w1 - 1;
        if (0 > max) {
          throw haxe_Exception.thrown("FAIL: min <= max");
        }
        line.x2 = value < 0 ? 0 : value > max ? max : value;
        return line.x1 <= line.x2;
      }
    };
    var _g = [];
    var _g1 = 0;
    var _g2 = scanlines;
    while (_g1 < _g2.length) {
      var v = _g2[_g1];
      ++_g1;
      if (f(v)) {
        _g.push(v);
      }
    }
    return _g;
  };
  var geometrize_runner_ImageRunner = ($hx_exports["geometrize"]["runner"]["ImageRunner"] = function (inputImage, backgroundColor) {
    this.model = null;
    this.model = new geometrize_Model(inputImage, backgroundColor);
  });
  geometrize_runner_ImageRunner.__name__ = true;
  geometrize_runner_ImageRunner.prototype = {
    step: function (options) {
      var finalOptions_shapeTypes = options.shapeTypes != null && options.shapeTypes.length != 0 ? options.shapeTypes : geometrize_runner_Default.options.shapeTypes;
      var finalOptions_alpha = options.alpha != null ? options.alpha : geometrize_runner_Default.options.alpha;
      var finalOptions_candidateShapesPerStep = options.candidateShapesPerStep != null ? options.candidateShapesPerStep : geometrize_runner_Default.options.candidateShapesPerStep;
      var finalOptions_shapeMutationsPerStep = options.shapeMutationsPerStep != null ? options.shapeMutationsPerStep : geometrize_runner_Default.options.shapeMutationsPerStep;
      return this.model.step(finalOptions_shapeTypes, finalOptions_alpha, finalOptions_candidateShapesPerStep, finalOptions_shapeMutationsPerStep);
    },
    getImageData: function () {
      if (this.model == null) {
        throw haxe_Exception.thrown("FAIL: model != null");
      }
      return this.model.current;
    },
  };
  var geometrize_runner_Default = function () {};
  geometrize_runner_Default.__name__ = true;
  var geometrize_shape_Ellipse = function (xBound, yBound) {
    this.x = Std.random(xBound);
    this.y = Std.random(yBound);
    this.rx = Std.random(32) + 1;
    this.ry = Std.random(32) + 1;
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_Ellipse.__name__ = true;
  geometrize_shape_Ellipse.prototype = {
    rasterize: function () {
      var lines = [];
      var aspect = this.rx / this.ry;
      var w = this.xBound;
      var h = this.yBound;
      var _g = 0;
      var _g1 = this.ry;
      while (_g < _g1) {
        var dy = _g++;
        var y1 = this.y - dy;
        var y2 = this.y + dy;
        if ((y1 < 0 || y1 >= h) && (y2 < 0 || y2 >= h)) {
          continue;
        }
        var s = (Math.sqrt(this.ry * this.ry - dy * dy) * aspect) | 0;
        var x1 = this.x - s;
        var x2 = this.x + s;
        if (x1 < 0) {
          x1 = 0;
        }
        if (x2 >= w) {
          x2 = w - 1;
        }
        if (y1 >= 0 && y1 < h) {
          lines.push(new geometrize_rasterizer_Scanline(y1, x1, x2));
        }
        if (y2 >= 0 && y2 < h && dy > 0) {
          lines.push(new geometrize_rasterizer_Scanline(y2, x1, x2));
        }
      }
      return lines;
    },
    mutate: function () {
      var r = Std.random(3);
      switch (r) {
        case 0:
          var value = this.x + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x = value < 0 ? 0 : value > max ? max : value;
          var value = this.y + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.rx + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.rx = value < 1 ? 1 : value > max ? max : value;
          break;
        case 2:
          var value = this.ry + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.ry = value < 1 ? 1 : value > max ? max : value;
          break;
      }
    },
    clone: function () {
      var ellipse = new geometrize_shape_Ellipse(this.xBound, this.yBound);
      ellipse.x = this.x;
      ellipse.y = this.y;
      ellipse.rx = this.rx;
      ellipse.ry = this.ry;
      return ellipse;
    },
    getType: function () {
      return 3;
    },
    getRawShapeData: function () {
      return [this.x, this.y, this.rx, this.ry];
    },
    getSvgShapeData: function () {
      return '<ellipse cx="' + this.x + '" cy="' + this.y + '" rx="' + this.rx + '" ry="' + this.ry + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + " />";
    },
  };
  var geometrize_shape_Circle = function (xBound, yBound) {
    geometrize_shape_Ellipse.call(this, xBound, yBound);
    this.rx = Std.random(32) + 1;
    this.ry = this.rx;
  };
  geometrize_shape_Circle.__name__ = true;
  geometrize_shape_Circle.__super__ = geometrize_shape_Ellipse;
  geometrize_shape_Circle.prototype = $extend(geometrize_shape_Ellipse.prototype, {
    mutate: function () {
      var r = Std.random(2);
      switch (r) {
        case 0:
          var value = this.x + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x = value < 0 ? 0 : value > max ? max : value;
          var value = this.y + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.rx + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          var r = value < 1 ? 1 : value > max ? max : value;
          this.rx = r;
          this.ry = r;
          break;
      }
    },
    clone: function () {
      var circle = new geometrize_shape_Circle(this.xBound, this.yBound);
      circle.x = this.x;
      circle.y = this.y;
      circle.rx = this.rx;
      circle.ry = this.ry;
      return circle;
    },
    getType: function () {
      return 5;
    },
    getRawShapeData: function () {
      return [this.x, this.y, this.rx];
    },
    getSvgShapeData: function () {
      return '<circle cx="' + this.x + '" cy="' + this.y + '" r="' + this.rx + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + " />";
    },
  });
  var geometrize_shape_Line = function (xBound, yBound) {
    this.x1 = Std.random(xBound);
    this.y1 = Std.random(yBound);
    var value = this.x1 + Std.random(32) + 1;
    if (0 > xBound) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.x2 = value < 0 ? 0 : value > xBound ? xBound : value;
    var value = this.y1 + Std.random(32) + 1;
    if (0 > yBound) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.y2 = value < 0 ? 0 : value > yBound ? yBound : value;
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_Line.__name__ = true;
  geometrize_shape_Line.prototype = {
    rasterize: function () {
      var lines = [];
      var points = geometrize_rasterizer_Rasterizer.bresenham(this.x1, this.y1, this.x2, this.y2);
      var _g = 0;
      while (_g < points.length) {
        var point = points[_g];
        ++_g;
        lines.push(new geometrize_rasterizer_Scanline(point.y, point.x, point.x));
      }
      return geometrize_rasterizer_Scanline.trim(lines, this.xBound, this.yBound);
    },
    mutate: function () {
      var r = Std.random(4);
      switch (r) {
        case 0:
          var value = this.x1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x1 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y1 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.x2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x2 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y2 = value < 0 ? 0 : value > max ? max : value;
          break;
      }
    },
    clone: function () {
      var line = new geometrize_shape_Line(this.xBound, this.yBound);
      line.x1 = this.x1;
      line.y1 = this.y1;
      line.x2 = this.x2;
      line.y2 = this.y2;
      return line;
    },
    getType: function () {
      return 6;
    },
    getRawShapeData: function () {
      return [this.x1, this.y1, this.x2, this.y2];
    },
    getSvgShapeData: function () {
      return '<line x1="' + this.x1 + '" y1="' + this.y1 + '" x2="' + this.x2 + '" y2="' + this.y2 + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + " />";
    },
  };
  var geometrize_shape_QuadraticBezier = function (xBound, yBound) {
    var upper = xBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.x1 = Math.floor((upper + 1) * Math.random());
    var upper = yBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.y1 = Math.floor((upper + 1) * Math.random());
    var upper = xBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.cx = Math.floor((upper + 1) * Math.random());
    var upper = yBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.cy = Math.floor((upper + 1) * Math.random());
    var upper = xBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.x2 = Math.floor((upper + 1) * Math.random());
    var upper = yBound - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    this.y2 = Math.floor((upper + 1) * Math.random());
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_QuadraticBezier.__name__ = true;
  geometrize_shape_QuadraticBezier.prototype = {
    rasterize: function () {
      var lines = [];
      var points = [];
      var pointCount = 20;
      var _g = 0;
      var _g1 = pointCount - 1;
      while (_g < _g1) {
        var i = _g++;
        var t = i / pointCount;
        var tp = 1 - t;
        var x = (tp * (tp * this.x1 + t * this.cx) + t * (tp * this.cx + t * this.x2)) | 0;
        var y = (tp * (tp * this.y1 + t * this.cy) + t * (tp * this.cy + t * this.y2)) | 0;
        points.push({ x: x, y: y });
      }
      var _g = 0;
      var _g1 = points.length - 1;
      while (_g < _g1) {
        var i = _g++;
        var p0 = points[i];
        var p1 = points[i + 1];
        var pts = geometrize_rasterizer_Rasterizer.bresenham(p0.x, p0.y, p1.x, p1.y);
        var _g2 = 0;
        while (_g2 < pts.length) {
          var point = pts[_g2];
          ++_g2;
          if (lines.length > 0) {
            var lastLine = lines[lines.length - 1];
            if (lastLine.y == point.y && lastLine.x1 == point.x && lastLine.x2 == point.x) {
              continue;
            }
          }
          lines.push(new geometrize_rasterizer_Scanline(point.y, point.x, point.x));
        }
      }
      return geometrize_rasterizer_Scanline.trim(lines, this.xBound, this.yBound);
    },
    mutate: function () {
      var r = Math.floor(3 * Math.random());
      switch (r) {
        case 0:
          var value = this.cx + (-8 + Math.floor(17 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.cx = value < 0 ? 0 : value > max ? max : value;
          var value = this.cy + (-8 + Math.floor(17 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.cy = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.x1 + (-8 + Math.floor(17 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x1 = value < 1 ? 1 : value > max ? max : value;
          var value = this.y1 + (-8 + Math.floor(17 * Math.random()));
          var max = this.yBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y1 = value < 1 ? 1 : value > max ? max : value;
          break;
        case 2:
          var value = this.x2 + (-8 + Math.floor(17 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x2 = value < 1 ? 1 : value > max ? max : value;
          var value = this.y2 + (-8 + Math.floor(17 * Math.random()));
          var max = this.yBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y2 = value < 1 ? 1 : value > max ? max : value;
          break;
      }
    },
    clone: function () {
      var bezier = new geometrize_shape_QuadraticBezier(this.xBound, this.yBound);
      bezier.cx = this.cx;
      bezier.cy = this.cy;
      bezier.x1 = this.x1;
      bezier.y1 = this.y1;
      bezier.x2 = this.x2;
      bezier.y2 = this.y2;
      return bezier;
    },
    getType: function () {
      return 7;
    },
    getRawShapeData: function () {
      return [this.x1, this.y1, this.cx, this.cy, this.x2, this.y2];
    },
    getSvgShapeData: function () {
      return '<path d="M' + this.x1 + " " + this.y1 + " Q " + this.cx + " " + this.cy + " " + this.x2 + " " + this.y2 + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + " />";
    },
  };
  var geometrize_shape_Rectangle = function (xBound, yBound) {
    this.x1 = Std.random(xBound);
    this.y1 = Std.random(yBound);
    var value = this.x1 + Std.random(32) + 1;
    var max = xBound - 1;
    if (0 > max) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.x2 = value < 0 ? 0 : value > max ? max : value;
    var value = this.y1 + Std.random(32) + 1;
    var max = yBound - 1;
    if (0 > max) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.y2 = value < 0 ? 0 : value > max ? max : value;
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_Rectangle.__name__ = true;
  geometrize_shape_Rectangle.prototype = {
    rasterize: function () {
      var lines = [];
      var first = this.y1;
      var second = this.y2;
      var yMin = first < second ? first : second;
      var first = this.y1;
      var second = this.y2;
      var yMax = first > second ? first : second;
      if (yMin == yMax) {
        var first = this.x1;
        var second = this.x2;
        var first1 = this.x1;
        var second1 = this.x2;
        lines.push(new geometrize_rasterizer_Scanline(yMin, first < second ? first : second, first1 > second1 ? first1 : second1));
      } else {
        var _g = yMin;
        var _g1 = yMax;
        while (_g < _g1) {
          var y = _g++;
          var first = this.x1;
          var second = this.x2;
          var first1 = this.x1;
          var second1 = this.x2;
          lines.push(new geometrize_rasterizer_Scanline(y, first < second ? first : second, first1 > second1 ? first1 : second1));
        }
      }
      return lines;
    },
    mutate: function () {
      var r = Std.random(2);
      switch (r) {
        case 0:
          var value = this.x1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x1 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y1 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.x2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x2 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y2 = value < 0 ? 0 : value > max ? max : value;
          break;
      }
    },
    clone: function () {
      var rectangle = new geometrize_shape_Rectangle(this.xBound, this.yBound);
      rectangle.x1 = this.x1;
      rectangle.y1 = this.y1;
      rectangle.x2 = this.x2;
      rectangle.y2 = this.y2;
      return rectangle;
    },
    getType: function () {
      return 0;
    },
    getRawShapeData: function () {
      var first = this.x1;
      var second = this.x2;
      var first1 = this.y1;
      var second1 = this.y2;
      var first2 = this.x1;
      var second2 = this.x2;
      var first3 = this.y1;
      var second3 = this.y2;
      return [first < second ? first : second, first1 < second1 ? first1 : second1, first2 > second2 ? first2 : second2, first3 > second3 ? first3 : second3];
    },
    getSvgShapeData: function () {
      var first = this.x1;
      var second = this.x2;
      var first1 = this.y1;
      var second1 = this.y2;
      var first2 = this.x1;
      var second2 = this.x2;
      var first3 = this.x1;
      var second3 = this.x2;
      var first4 = this.y1;
      var second4 = this.y2;
      var first5 = this.y1;
      var second5 = this.y2;
      return (
        '<rect x="' +
        (first < second ? first : second) +
        '" y="' +
        (first1 < second1 ? first1 : second1) +
        '" width="' +
        ((first2 > second2 ? first2 : second2) - (first3 < second3 ? first3 : second3)) +
        '" height="' +
        ((first4 > second4 ? first4 : second4) - (first5 < second5 ? first5 : second5)) +
        '" ' +
        geometrize_exporter_SvgExporter.SVG_STYLE_HOOK +
        " />"
      );
    },
  };
  var geometrize_shape_RotatedEllipse = function (xBound, yBound) {
    this.x = Std.random(xBound);
    this.y = Std.random(yBound);
    this.rx = Std.random(32) + 1;
    this.ry = Std.random(32) + 1;
    this.angle = Std.random(360);
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_RotatedEllipse.__name__ = true;
  geometrize_shape_RotatedEllipse.prototype = {
    rasterize: function () {
      var pointCount = 20;
      var points = [];
      var rads = this.angle * (Math.PI / 180.0);
      var c = Math.cos(rads);
      var s = Math.sin(rads);
      var _g = 0;
      var _g1 = pointCount;
      while (_g < _g1) {
        var i = _g++;
        var rot = (360.0 / pointCount) * i * (Math.PI / 180.0);
        var crx = this.rx * Math.cos(rot);
        var cry = this.ry * Math.sin(rot);
        var tx = (crx * c - cry * s + this.x) | 0;
        var ty = (crx * s + cry * c + this.y) | 0;
        points.push({ x: tx, y: ty });
      }
      return geometrize_rasterizer_Scanline.trim(geometrize_rasterizer_Rasterizer.scanlinesForPolygon(points), this.xBound, this.yBound);
    },
    mutate: function () {
      var r = Std.random(4);
      switch (r) {
        case 0:
          var value = this.x + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x = value < 0 ? 0 : value > max ? max : value;
          var value = this.y + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.rx + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.rx = value < 1 ? 1 : value > max ? max : value;
          break;
        case 2:
          var value = this.ry + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (1 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.ry = value < 1 ? 1 : value > max ? max : value;
          break;
        case 3:
          var value = this.angle + (-4 + Math.floor(9 * Math.random()));
          this.angle = value < 0 ? 0 : value > 360 ? 360 : value;
          break;
      }
    },
    clone: function () {
      var ellipse = new geometrize_shape_RotatedEllipse(this.xBound, this.yBound);
      ellipse.x = this.x;
      ellipse.y = this.y;
      ellipse.rx = this.rx;
      ellipse.ry = this.ry;
      ellipse.angle = this.angle;
      return ellipse;
    },
    getType: function () {
      return 4;
    },
    getRawShapeData: function () {
      return [this.x, this.y, this.rx, this.ry, this.angle];
    },
    getSvgShapeData: function () {
      var s = '<g transform="translate(' + this.x + " " + this.y + ") rotate(" + this.angle + ") scale(" + this.rx + " " + this.ry + ')">';
      s += '<ellipse cx="' + 0 + '" cy="' + 0 + '" rx="' + 1 + '" ry="' + 1 + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + " />";
      s += "</g>";
      return s;
    },
  };
  var geometrize_shape_RotatedRectangle = function (xBound, yBound) {
    this.x1 = Std.random(xBound);
    this.y1 = Std.random(yBound);
    var value = this.x1 + Std.random(32) + 1;
    if (0 > xBound) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.x2 = value < 0 ? 0 : value > xBound ? xBound : value;
    var value = this.y1 + Std.random(32) + 1;
    if (0 > yBound) {
      throw haxe_Exception.thrown("FAIL: min <= max");
    }
    this.y2 = value < 0 ? 0 : value > yBound ? yBound : value;
    this.angle = Math.floor(361 * Math.random());
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_RotatedRectangle.__name__ = true;
  geometrize_shape_RotatedRectangle.prototype = {
    rasterize: function () {
      var first = this.x1;
      var second = this.x2;
      var xm1 = first < second ? first : second;
      var first = this.x1;
      var second = this.x2;
      var xm2 = first > second ? first : second;
      var first = this.y1;
      var second = this.y2;
      var ym1 = first < second ? first : second;
      var first = this.y1;
      var second = this.y2;
      var ym2 = first > second ? first : second;
      var cx = ((xm1 + xm2) / 2) | 0;
      var cy = ((ym1 + ym2) / 2) | 0;
      var ox1 = xm1 - cx;
      var ox2 = xm2 - cx;
      var oy1 = ym1 - cy;
      var oy2 = ym2 - cy;
      var rads = (this.angle * Math.PI) / 180.0;
      var c = Math.cos(rads);
      var s = Math.sin(rads);
      var ulx = (ox1 * c - oy1 * s + cx) | 0;
      var uly = (ox1 * s + oy1 * c + cy) | 0;
      var blx = (ox1 * c - oy2 * s + cx) | 0;
      var bly = (ox1 * s + oy2 * c + cy) | 0;
      var urx = (ox2 * c - oy1 * s + cx) | 0;
      var ury = (ox2 * s + oy1 * c + cy) | 0;
      var brx = (ox2 * c - oy2 * s + cx) | 0;
      var bry = (ox2 * s + oy2 * c + cy) | 0;
      return geometrize_rasterizer_Scanline.trim(
        geometrize_rasterizer_Rasterizer.scanlinesForPolygon([
          { x: ulx, y: uly },
          { x: urx, y: ury },
          { x: brx, y: bry },
          { x: blx, y: bly },
        ]),
        this.xBound,
        this.yBound
      );
    },
    mutate: function () {
      var r = Std.random(3);
      switch (r) {
        case 0:
          var value = this.x1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x1 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y1 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.x2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x2 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y2 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 2:
          var value = this.angle + (-4 + Math.floor(9 * Math.random()));
          this.angle = value < 0 ? 0 : value > 360 ? 360 : value;
          break;
      }
    },
    clone: function () {
      var rectangle = new geometrize_shape_RotatedRectangle(this.xBound, this.yBound);
      rectangle.x1 = this.x1;
      rectangle.y1 = this.y1;
      rectangle.x2 = this.x2;
      rectangle.y2 = this.y2;
      rectangle.angle = this.angle;
      return rectangle;
    },
    getType: function () {
      return 1;
    },
    getRawShapeData: function () {
      var first = this.x1;
      var second = this.x2;
      var first1 = this.y1;
      var second1 = this.y2;
      var first2 = this.x1;
      var second2 = this.x2;
      var first3 = this.y1;
      var second3 = this.y2;
      return [first < second ? first : second, first1 < second1 ? first1 : second1, first2 > second2 ? first2 : second2, first3 > second3 ? first3 : second3, this.angle];
    },
    getSvgShapeData: function () {
      var first = this.x1;
      var second = this.x2;
      var xm1 = first < second ? first : second;
      var first = this.x1;
      var second = this.x2;
      var xm2 = first > second ? first : second;
      var first = this.y1;
      var second = this.y2;
      var ym1 = first < second ? first : second;
      var first = this.y1;
      var second = this.y2;
      var ym2 = first > second ? first : second;
      var cx = ((xm1 + xm2) / 2) | 0;
      var cy = ((ym1 + ym2) / 2) | 0;
      var ox1 = xm1 - cx;
      var ox2 = xm2 - cx;
      var oy1 = ym1 - cy;
      var oy2 = ym2 - cy;
      var rads = (this.angle * Math.PI) / 180.0;
      var c = Math.cos(rads);
      var s = Math.sin(rads);
      var ulx = (ox1 * c - oy1 * s + cx) | 0;
      var uly = (ox1 * s + oy1 * c + cy) | 0;
      var blx = (ox1 * c - oy2 * s + cx) | 0;
      var bly = (ox1 * s + oy2 * c + cy) | 0;
      var urx = (ox2 * c - oy1 * s + cx) | 0;
      var ury = (ox2 * s + oy1 * c + cy) | 0;
      var brx = (ox2 * c - oy2 * s + cx) | 0;
      var bry = (ox2 * s + oy2 * c + cy) | 0;
      var points = [
        { x: ulx, y: uly },
        { x: urx, y: ury },
        { x: brx, y: bry },
        { x: blx, y: bly },
      ];
      var s = '<polygon points="';
      var _g = 0;
      var _g1 = points.length;
      while (_g < _g1) {
        var i = _g++;
        s += points[i].x + " " + points[i].y;
        if (i != points.length - 1) {
          s += " ";
        }
      }
      s += '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + "/>";
      return s;
    },
  };
  var geometrize_shape_ShapeFactory = function () {};
  geometrize_shape_ShapeFactory.__name__ = true;
  geometrize_shape_ShapeFactory.create = function (type, xBound, yBound) {
    switch (type) {
      case 0:
        return new geometrize_shape_Rectangle(xBound, yBound);
      case 1:
        return new geometrize_shape_RotatedRectangle(xBound, yBound);
      case 2:
        return new geometrize_shape_Triangle(xBound, yBound);
      case 3:
        return new geometrize_shape_Ellipse(xBound, yBound);
      case 4:
        return new geometrize_shape_RotatedEllipse(xBound, yBound);
      case 5:
        return new geometrize_shape_Circle(xBound, yBound);
      case 6:
        return new geometrize_shape_Line(xBound, yBound);
      case 7:
        return new geometrize_shape_QuadraticBezier(xBound, yBound);
    }
  };
  geometrize_shape_ShapeFactory.randomShapeOf = function (types, xBound, yBound) {
    if (!(types != null && types.length > 0)) {
      throw haxe_Exception.thrown("FAIL: a != null && a.length > 0");
    }
    var upper = types.length - 1;
    if (0 > upper) {
      throw haxe_Exception.thrown("FAIL: lower <= upper");
    }
    return geometrize_shape_ShapeFactory.create(types[Math.floor((upper + 1) * Math.random())], xBound, yBound);
  };
  var geometrize_shape_ShapeTypes = ($hx_exports["geometrize"]["shape"]["ShapeTypes"] = function () {});
  geometrize_shape_ShapeTypes.__name__ = true;
  var geometrize_shape_Triangle = function (xBound, yBound) {
    this.x1 = Std.random(xBound);
    this.y1 = Std.random(yBound);
    this.x2 = this.x1 + (-16 + Math.floor(33 * Math.random()));
    this.y2 = this.y1 + (-16 + Math.floor(33 * Math.random()));
    this.x3 = this.x1 + (-16 + Math.floor(33 * Math.random()));
    this.y3 = this.y1 + (-16 + Math.floor(33 * Math.random()));
    this.xBound = xBound;
    this.yBound = yBound;
  };
  geometrize_shape_Triangle.__name__ = true;
  geometrize_shape_Triangle.prototype = {
    rasterize: function () {
      return geometrize_rasterizer_Scanline.trim(
        geometrize_rasterizer_Rasterizer.scanlinesForPolygon([
          { x: this.x1, y: this.y1 },
          { x: this.x2, y: this.y2 },
          { x: this.x3, y: this.y3 },
        ]),
        this.xBound,
        this.yBound
      );
    },
    mutate: function () {
      var r = Std.random(3);
      switch (r) {
        case 0:
          var value = this.x1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x1 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y1 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y1 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 1:
          var value = this.x2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x2 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y2 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y2 = value < 0 ? 0 : value > max ? max : value;
          break;
        case 2:
          var value = this.x3 + (-16 + Math.floor(33 * Math.random()));
          var max = this.xBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.x3 = value < 0 ? 0 : value > max ? max : value;
          var value = this.y3 + (-16 + Math.floor(33 * Math.random()));
          var max = this.yBound - 1;
          if (0 > max) {
            throw haxe_Exception.thrown("FAIL: min <= max");
          }
          this.y3 = value < 0 ? 0 : value > max ? max : value;
          break;
      }
    },
    clone: function () {
      var triangle = new geometrize_shape_Triangle(this.xBound, this.yBound);
      triangle.x1 = this.x1;
      triangle.y1 = this.y1;
      triangle.x2 = this.x2;
      triangle.y2 = this.y2;
      triangle.x3 = this.x3;
      triangle.y3 = this.y3;
      return triangle;
    },
    getType: function () {
      return 2;
    },
    getRawShapeData: function () {
      return [this.x1, this.y1, this.x2, this.y2, this.x3, this.y3];
    },
    getSvgShapeData: function () {
      return '<polygon points="' + this.x1 + "," + this.y1 + " " + this.x2 + "," + this.y2 + " " + this.x3 + "," + this.y3 + '" ' + geometrize_exporter_SvgExporter.SVG_STYLE_HOOK + "/>";
    },
  };
  var haxe_Exception = function (message, previous, native) {
    Error.call(this, message);
    this.message = message;
    this.__previousException = previous;
    this.__nativeException = native != null ? native : this;
  };
  haxe_Exception.__name__ = true;
  haxe_Exception.thrown = function (value) {
    if (value instanceof haxe_Exception) {
      return value.get_native();
    } else if (value instanceof Error) {
      return value;
    } else {
      var e = new haxe_ValueException(value);
      return e;
    }
  };
  haxe_Exception.__super__ = Error;
  haxe_Exception.prototype = $extend(Error.prototype, {
    get_native: function () {
      return this.__nativeException;
    },
  });
  var haxe_ValueException = function (value, previous, native) {
    haxe_Exception.call(this, String(value), previous, native);
    this.value = value;
  };
  haxe_ValueException.__name__ = true;
  haxe_ValueException.__super__ = haxe_Exception;
  haxe_ValueException.prototype = $extend(haxe_Exception.prototype, {});
  var haxe_ds_IntMap = function () {
    this.h = {};
  };
  haxe_ds_IntMap.__name__ = true;
  haxe_ds_IntMap.prototype = {
    keys: function () {
      var a = [];
      for (var key in this.h) if (this.h.hasOwnProperty(key)) a.push(+key);
      return new haxe_iterators_ArrayIterator(a);
    },
  };
  var haxe_io_Bytes = function (data) {
    this.length = data.byteLength;
    this.b = new Uint8Array(data);
    this.b.bufferValue = data;
    data.hxBytes = this;
    data.bytes = this.b;
  };
  haxe_io_Bytes.__name__ = true;
  var haxe_iterators_ArrayIterator = function (array) {
    this.current = 0;
    this.array = array;
  };
  haxe_iterators_ArrayIterator.__name__ = true;
  haxe_iterators_ArrayIterator.prototype = {
    hasNext: function () {
      return this.current < this.array.length;
    },
    next: function () {
      return this.array[this.current++];
    },
  };
  var js_Boot = function () {};
  js_Boot.__name__ = true;
  js_Boot.__string_rec = function (o, s) {
    if (o == null) {
      return "null";
    }
    if (s.length >= 5) {
      return "<...>";
    }
    var t = typeof o;
    if (t == "function" && (o.__name__ || o.__ename__)) {
      t = "object";
    }
    switch (t) {
      case "function":
        return "<function>";
      case "object":
        if (o instanceof Array) {
          var str = "[";
          s += "\t";
          var _g = 0;
          var _g1 = o.length;
          while (_g < _g1) {
            var i = _g++;
            str += (i > 0 ? "," : "") + js_Boot.__string_rec(o[i], s);
          }
          str += "]";
          return str;
        }
        var tostr;
        try {
          tostr = o.toString;
        } catch (_g) {
          return "???";
        }
        if (tostr != null && tostr != Object.toString && typeof tostr == "function") {
          var s2 = o.toString();
          if (s2 != "[object Object]") {
            return s2;
          }
        }
        var str = "{\n";
        s += "\t";
        var hasp = o.hasOwnProperty != null;
        var k = null;
        for (k in o) {
          if (hasp && !o.hasOwnProperty(k)) {
            continue;
          }
          if (k == "prototype" || k == "__class__" || k == "__super__" || k == "__interfaces__" || k == "__properties__") {
            continue;
          }
          if (str.length != 2) {
            str += ", \n";
          }
          str += s + k + " : " + js_Boot.__string_rec(o[k], s);
        }
        s = s.substring(1);
        str += "\n" + s + "}";
        return str;
      case "string":
        return o;
      default:
        return String(o);
    }
  };
  var $_;
  function $bind(o, m) {
    if (m == null) return null;
    if (m.__id__ == null) m.__id__ = $global.$haxeUID++;
    var f;
    if (o.hx__closures__ == null) o.hx__closures__ = {};
    else f = o.hx__closures__[m.__id__];
    if (f == null) {
      f = m.bind(o);
      o.hx__closures__[m.__id__] = f;
    }
    return f;
  }
  $global.$haxeUID |= 0;
  if (typeof performance != "undefined" ? typeof performance.now == "function" : false) {
    HxOverrides.now = performance.now.bind(performance);
  }
  String.__name__ = true;
  Array.__name__ = true;
  js_Boot.__toStr = {}.toString;
  Main.imagesToGeometrize = [];
  geometrize_exporter_SvgExporter.SVG_STYLE_HOOK = "::svg_style_hook::";
  geometrize_runner_Default.options = {
    shapeTypes: [5, 6],
    candidateShapesPerStep: 50,
    shapeMutationsPerStep: 100,
    alpha: 255,
  };
  geometrize_shape_ShapeTypes.RECTANGLE = 0;
  geometrize_shape_ShapeTypes.ROTATED_RECTANGLE = 1;
  geometrize_shape_ShapeTypes.TRIANGLE = 2;
  geometrize_shape_ShapeTypes.ELLIPSE = 3;
  geometrize_shape_ShapeTypes.ROTATED_ELLIPSE = 4;
  geometrize_shape_ShapeTypes.CIRCLE = 5;
  geometrize_shape_ShapeTypes.LINE = 6;
  geometrize_shape_ShapeTypes.QUADRATIC_BEZIER = 7;
  Main.main();
})(
  typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this,
  typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this,
  `!function(t,r){"use strict";function n(t,r){var n=Object.create(t);for(var h in r)n[h]=r[h];return r.toString!==Object.prototype.toString&&(n.toString=r.toString),n}t.geometrize=t.geometrize||{},t.geometrize.bitmap=t.geometrize.bitmap||{},t.geometrize.exporter=t.geometrize.exporter||{},t.geometrize.runner=t.geometrize.runner||{},t.geometrize.shape=t.geometrize.shape||{};var h=function(){};h.prototype={messageHandler:function(t){if(null!=t&&null!=t.data){var r=t.data;switch(r.id){case"should_set_target_image":var n=r.data;this.runner=new p(n,f.getAverageImageColor(n)),this.postMessage({id:"did_set_target_image"});break;case"should_step":var h=r.data,i=this.runner.step(h),a=c.exportShapes(i),o=y.exportShapes(i);this.postMessage({id:"did_step",svgData:a,jsonData:o});break}}},postMessage:function(t){}};var i=function(){};i.random=function(t){return t<=0?0:Math.floor(Math.random()*t)};var a=function(){};a.replace=function(t,r,n){return t.split(r).join(n)};var o={toFloat:function(t){return t<0?4294967296+t:t+0}},e={create:function(t){if(null==t){return[]}return e.toSet(t)},add:function(t,r){if(null==r)throw _.thrown("FAIL: element != null");return!e.contains(t,r)&&(t.push(r),!0)},contains:function(t,r){for(var n=0;n<t.length;){var h=t[n];if(++n,h==r)return!0}return!1},toArray:function(t){return t.slice()},toSet:function(t){for(var r=[],n=0;n<t.length;){var h=t[n];++n,e.add(r,h)}return r}},s=function(){};s.computeColor=function(t,r,n,h){if(null==t)throw _.thrown("FAIL: target != null");if(null==r)throw _.thrown("FAIL: current != null");if(null==n)throw _.thrown("FAIL: lines != null");if(h<0)throw _.thrown("FAIL: alpha >= 0");for(var i=0,a=0,o=0,e=0,s=0|65535/h,u=0;u<n.length;){var l=n[u];++u;for(var f=l.y,x=l.x1,y=l.x2+1;x<y;){var c=x++,d=t.data[t.width*f+c],w=r.data[r.width*f+c];i+=((d>>24&255)-(w>>24&255))*s+257*(w>>24&255),a+=((d>>16&255)-(w>>16&255))*s+257*(w>>16&255),o+=((d>>8&255)-(w>>8&255))*s+257*(w>>8&255),++e}}if(0==e)return 0;var p,m=(p=(i/e|0)>>8)<0?0:p>255?255:p,g=(p=(a/e|0)>>8)<0?0:p>255?255:p,v=(p=(o/e|0)>>8)<0?0:p>255?255:p;return((m<0?0:m>255?255:m)<<24)+((g<0?0:g>255?255:g)<<16)+((v<0?0:v>255?255:v)<<8)+(h<0?0:h>255?255:h)},s.differenceFull=function(t,r){if(null==t)throw _.thrown("FAIL: first != null");if(null==r)throw _.thrown("FAIL: second != null");if(0==t.width)throw _.thrown("FAIL: first.width != 0");if(0==t.height)throw _.thrown("FAIL: first.height != 0");if(0==r.width)throw _.thrown("FAIL: second.width != 0");if(0==r.height)throw _.thrown("FAIL: second.height != 0");var n,h;if((n=t.width)!=(h=r.width))throw _.thrown("FAIL: values are not equal (expected: "+h+", actual: "+n+")");if((n=t.height)!=(h=r.height))throw _.thrown("FAIL: values are not equal (expected: "+h+", actual: "+n+")");for(var i=0,a=t.width,o=t.height,e=0,s=o;e<s;)for(var u=e++,l=0,f=a;l<f;){var x=l++,y=t.data[t.width*u+x],c=r.data[r.width*u+x],d=(y>>24&255)-(c>>24&255),w=(y>>16&255)-(c>>16&255),p=(y>>8&255)-(c>>8&255),m=(255&y)-(255&c);i+=d*d+w*w+p*p+m*m}var g=Math.sqrt(i/(a*o*4))/255;if(!isFinite(g))throw _.thrown("FAIL: Math.isFinite(result)");return g},s.differencePartial=function(t,r,n,h,i){if(null==t)throw _.thrown("FAIL: target != null");if(null==r)throw _.thrown("FAIL: before != null");if(null==n)throw _.thrown("FAIL: after != null");if(null==i)throw _.thrown("FAIL: lines != null");if(0==i.length)throw _.thrown("FAIL: lines.length != 0");for(var a=t.width*t.height*4,o=Math.pow(255*h,2)*a,e=0;e<i.length;){var s=i[e];++e;for(var u=s.y,l=s.x1,f=s.x2+1;l<f;){var x=l++,y=t.data[t.width*u+x],c=r.data[r.width*u+x],d=n.data[n.width*u+x],w=(y>>24&255)-(c>>24&255),p=(y>>16&255)-(c>>16&255),m=(y>>8&255)-(c>>8&255),g=(255&y)-(255&c),v=(y>>24&255)-(d>>24&255),F=(y>>16&255)-(d>>16&255),M=(y>>8&255)-(d>>8&255),A=(255&y)-(255&d);o-=w*w+p*p+m*m+g*g,o+=v*v+F*F+M*M+A*A}}var L=Math.sqrt(o/a)/255;if(!isFinite(L))throw _.thrown("FAIL: Math.isFinite(result)");return L},s.bestRandomState=function(t,r,n,h,i,a,o){for(var e=0,s=null,u=0,f=n;u<f;){var x=u++,y=new l(S.randomShapeOf(t,i.width,i.height),r,h,i,a),c=y.energy(o);(0==x||c<e)&&(e=c,s=y)}return s},s.bestHillClimbState=function(t,r,n,h,i,a,o,e){var u=s.bestRandomState(t,r,n,i,a,o,e);return u=s.hillClimb(u,h,e)},s.hillClimb=function(t,r,n){if(null==t)throw _.thrown("FAIL: state != null");if(r<0)throw _.thrown("FAIL: maxAge >= 0");for(var h=t.clone(),i=h.clone(),a=h.energy(n),o=0;o<r;){var e=h.mutate(),s=h.energy(n);s>=a?h=e:(a=s,i=h.clone(),o=-1),++o}return i},s.energy=function(t,r,n,h,i,a){if(null==t)throw _.thrown("FAIL: shape != null");if(null==n)throw _.thrown("FAIL: target != null");if(null==h)throw _.thrown("FAIL: current != null");if(null==i)throw _.thrown("FAIL: buffer != null");var o=t.rasterize();if(null==o)throw _.thrown("FAIL: lines != null");if(0==o.length)throw _.thrown("FAIL: lines.length != 0");var e=s.computeColor(n,h,o,r);return d.copyLines(i,h,o),d.drawLines(i,e,o),s.differencePartial(n,h,i,a,o)};var u=function(t,r){if(null==t)throw _.thrown("FAIL: target != null");this.width=t.width,this.height=t.height,this.target=t;var n=t.width,h=t.height;(o=new x).width=n,o.height=h;var i=new Array(n*h);o.data=i;for(var a=0;a<o.data.length;)o.data[a]=r,++a;this.current=o;var o;n=t.width,h=t.height;(o=new x).width=n,o.height=h;i=new Array(n*h);o.data=i;for(a=0;a<o.data.length;)o.data[a]=r,++a;this.buffer=o,this.score=s.differenceFull(t,this.current)};u.prototype={step:function(t,r,n,h){var i=s.bestHillClimbState(t,r,n,h,this.target,this.current,this.buffer,this.score);return[this.addShape(i.shape,i.alpha)]},addShape:function(t,r){if(null==t)throw _.thrown("FAIL: shape != null");var n=this.current,h=new x;h.width=n.width,h.height=n.height;var i=new Array(n.data.length);h.data=i;for(var a=0,o=n.data.length;a<o;){var e=a++;h.data[e]=n.data[e]}var u=h,l=t.rasterize(),f=s.computeColor(this.target,this.current,l,r);return d.drawLines(this.current,f,l),this.score=s.differencePartial(this.target,u,this.current,this.score,l),{score:this.score,color:f,shape:t}}};var l=function(t,r,n,h,i){if(null==t)throw _.thrown("FAIL: shape != null");this.shape=t,this.alpha=r,this.score=-1,this.target=n,this.current=h,this.buffer=i};l.prototype={energy:function(t){return this.score<0&&(this.score=s.energy(this.shape,this.alpha,this.target,this.current,this.buffer,t)),this.score},mutate:function(){var t=this.clone();return this.shape.mutate(),t},clone:function(){return new l(this.shape.clone(),this.alpha,this.target,this.current,this.buffer)}};var f=function(){};f.getAverageImageColor=function(t,r){if(null==r&&(r=255),null==t)throw _.thrown("FAIL: image != null");for(var n=0,h=0,i=0,a=0,o=t.width;a<o;)for(var e=a++,s=0,u=t.height;s<u;){var l=s++,f=t.data[t.width*l+e];n+=f>>24&255,h+=f>>16&255,i+=f>>8&255}var x=t.width*t.height,y=n/x|0,c=h/x|0,d=i/x|0;return((y<0?0:y>255?255:y)<<24)+((c<0?0:c>255?255:c)<<16)+((d<0?0:d>255?255:d)<<8)+(r<0?0:r>255?255:r)};var x=t.geometrize.bitmap.Bitmap=function(){};x.create=function(t,r,n){var h=new x;h.width=t,h.height=r;var i=new Array(t*r);h.data=i;for(var a=0;a<h.data.length;)h.data[a]=n,++a;return h},x.createFromBytes=function(t,r,n){var h=new x;if(null==n)throw _.thrown("FAIL: bytes != null");var i=n.length,a=t*r*4;if(i!=a)throw _.thrown("FAIL: values are not equal (expected: "+a+", actual: "+i+")");h.width=t,h.height=r;var o=new Array(n.length/4|0);h.data=o;for(var e=0,s=0;e<n.length;){var u=n.b[e],l=n.b[e+1],f=n.b[e+2],y=n.b[e+3];h.data[s]=((u<0?0:u>255?255:u)<<24)+((l<0?0:l>255?255:l)<<16)+((f<0?0:f>255?255:f)<<8)+(y<0?0:y>255?255:y),e+=4,++s}return h},x.createFromByteArray=function(t,r,n){for(var h=new T(new ArrayBuffer(n.length)),i=0;i<n.length;)h.b[i]=n[i],++i;var a=new x;if(null==h)throw _.thrown("FAIL: bytes != null");var o=h.length,e=t*r*4;if(o!=e)throw _.thrown("FAIL: values are not equal (expected: "+e+", actual: "+o+")");a.width=t,a.height=r;var s=new Array(h.length/4|0);a.data=s;i=0;for(var u=0;i<h.length;){var l=h.b[i],f=h.b[i+1],y=h.b[i+2],c=h.b[i+3];a.data[u]=((l<0?0:l>255?255:l)<<24)+((f<0?0:f>255?255:f)<<16)+((y<0?0:y>255?255:y)<<8)+(c<0?0:c>255?255:c),i+=4,++u}return a},x.prototype={getPixel:function(t,r){return this.data[this.width*r+t]},setPixel:function(t,r,n){this.data[this.width*r+t]=n},clone:function(){var t=new x;t.width=this.width,t.height=this.height;var r=new Array(this.data.length);t.data=r;for(var n=0,h=this.data.length;n<h;){var i=n++;t.data[i]=this.data[i]}return t},fill:function(t){for(var r=0;r<this.data.length;)this.data[r]=t>>24&255,this.data[r+1]=t>>16&255,this.data[r+2]=t>>8&255,this.data[r+3]=255&t,r+=4},getBytes:function(){for(var t=new T(new ArrayBuffer(4*this.data.length)),r=0;r<this.data.length;){var n=4*r;t.b[n]=this.data[r]>>24&255,t.b[n+1]=this.data[r]>>16&255,t.b[n+2]=this.data[r]>>8&255,t.b[n+3]=255&this.data[r],++r}return t}};var y=t.geometrize.exporter.ShapeJsonExporter=function(){};y.export=function(t){return"[\\n"+y.exportShapes(t)+"\\n]"},y.exportShapes=function(t){for(var r="",n=0,h=t.length;n<h;){var i=n++;r+=y.exportShape(t[i]),i!=t.length-1&&(r+=",\\n")}return r},y.exportShape=function(t){var r="    {\\n",n=t.shape.getType(),h=t.shape.getRawShapeData(),i=t.color,a=t.score;r+='        "type":'+n+",\\n",r+='        "data":[';for(var o=0,e=h.length;o<e;){var s=o++;r+=h[s],s<=h.length-2&&(r+=",")}return r+="],\\n",r+='        "color":[',r+=(i>>24&255)+",",r+=(i>>16&255)+",",r+=(i>>8&255)+",",r+=255&i,r+="],\\n",r+='        "score":'+a+"\\n",r+="    }"};var c=t.geometrize.exporter.SvgExporter=function(){};c.export=function(t,r,n){var h=c.getSvgPrelude();return h+=c.getSvgNodeOpen(r,n),h+=c.exportShapes(t),h+=c.getSvgNodeClose()},c.exportShapes=function(t){for(var r="",n=0,h=t.length;n<h;){var i=n++;r+=c.exportShape(t[i]),i!=t.length-1&&(r+="\\n")}return r},c.exportShape=function(t){return a.replace(t.shape.getSvgShapeData(),c.SVG_STYLE_HOOK,c.stylesForShape(t))},c.getSvgPrelude=function(){return'<?xml version="1.0" standalone="no"?>\\n'},c.getSvgNodeOpen=function(t,r){return'<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="'+t+'" height="'+r+'">\\n'},c.getSvgNodeClose=function(){return"</svg>"},c.stylesForShape=function(t){switch(t.shape.getType()){case 6:case 7:return c.strokeForColor(t.color)+' stroke-width="1" fill="none" '+c.strokeOpacityForAlpha(255&t.color);default:return c.fillForColor(t.color)+" "+c.fillOpacityForAlpha(255&t.color)}},c.rgbForColor=function(t){return"rgb("+(t>>24&255)+","+(t>>16&255)+","+(t>>8&255)+")"},c.strokeForColor=function(t){return'stroke="'+c.rgbForColor(t)+'"'},c.fillForColor=function(t){return'fill="'+c.rgbForColor(t)+'"'},c.fillOpacityForAlpha=function(t){return'fill-opacity="'+t/255+'"'},c.strokeOpacityForAlpha=function(t){return'stroke-opacity="'+t/255+'"'};var d=function(){};d.drawLines=function(t,r,n){if(null==t)throw _.thrown("FAIL: image != null");if(null==n)throw _.thrown("FAIL: lines != null");var h=r>>24&255;h|=h<<8,h=(h*=255&r)/255|0;var i=r>>16&255;i|=i<<8,i=(i*=255&r)/255|0;var a=r>>8&255;a|=a<<8,a=(a*=255&r)/255|0;var e=255&r;e|=e<<8;for(var s=0;s<n.length;){var u=n[s];++s;for(var l=u.y,f=65535,x=65535,y=0|257*(x-1*e),c=u.x1,d=u.x2+1;c<d;){var w=c++,p=t.data[t.width*l+w],m=p>>24&255,g=p>>16&255,v=p>>8&255,F=255&p,M=(o.toFloat(m*y+h*f)/o.toFloat(x)|0)>>8,A=(o.toFloat(g*y+i*f)/o.toFloat(x)|0)>>8,L=(o.toFloat(v*y+a*f)/o.toFloat(x)|0)>>8,I=(o.toFloat(F*y+e*f)/o.toFloat(x)|0)>>8;t.data[t.width*l+w]=((M<0?0:M>255?255:M)<<24)+((A<0?0:A>255?255:A)<<16)+((L<0?0:L>255?255:L)<<8)+(I<0?0:I>255?255:I)}}},d.copyLines=function(t,r,n){if(null==t)throw _.thrown("FAIL: destination != null");if(null==r)throw _.thrown("FAIL: source != null");if(null==n)throw _.thrown("FAIL: lines != null");for(var h=0;h<n.length;){var i=n[h];++h;for(var a=i.y,o=i.x1,e=i.x2+1;o<e;){var s=o++;t.data[t.width*a+s]=r.data[r.width*a+s]}}},d.bresenham=function(t,r,n,h){var i=n-t,a=(i>0?1:0)-(i<0?1:0);i=(i<0?-i:i)<<1;var o=h-r,e=(o>0?1:0)-(o<0?1:0);o=(o<0?-o:o)<<1;var s=[];if(s.push({x:t,y:r}),i>=o)for(var u=o-(i>>1);t!=n;)u>=0&&(0!=u||a>0)&&(u-=i,r+=e),u+=o,t+=a,s.push({x:t,y:r});else for(u=i-(o>>1);r!=h;)u>=0&&(0!=u||e>0)&&(u-=o,t+=a),u+=i,r+=e,s.push({x:t,y:r});return s},d.scanlinesForPolygon=function(t){for(var r=[],n=[],h=0,i=t.length;h<i;){var a=h++,o=t[a],s=a==t.length-1?t[0]:t[a+1],u=d.bresenham(o.x,o.y,s.x,s.y);n=n.concat(u)}var l=new E;for(h=0;h<n.length;){var f=n[h];++h;var x=l.h[f.y];null!=x?e.add(x,f.x):(x=e.create(),e.add(x,f.x),l.h[f.y]=x)}for(var y=l.keys();y.hasNext();){var c,p=y.next(),m=e.toArray(l.h[p]);if(null==m||0==m.length)c={x:0,y:0};else{var g=m[0],v=m[0];for(h=0;h<m.length;){var F=m[h];++h,g>F&&(g=F),v<F&&(v=F)}c={x:g,y:v}}r.push(new w(p,c.x,c.y))}return r};var w=function(t,r,n){this.y=t,this.x1=r,this.x2=n};w.trim=function(t,r,n){if(null==t)throw _.thrown("FAIL: scanlines != null");for(var h=r,i=n,a=function(t){if(t.y<0||t.y>=i||t.x1>=h||t.x2<0)return!1;var r=t.x1;if(0>(n=h-1))throw _.thrown("FAIL: min <= max");t.x1=r<0?0:r>n?n:r;var n;r=t.x2;if(0>(n=h-1))throw _.thrown("FAIL: min <= max");return t.x2=r<0?0:r>n?n:r,t.x1<=t.x2},o=[],e=0,s=t;e<s.length;){var u=s[e];++e,a(u)&&o.push(u)}return o};var p=t.geometrize.runner.ImageRunner=function(t,r){this.model=null,this.model=new u(t,r)};p.prototype={step:function(t){var r=null!=t.shapeTypes&&0!=t.shapeTypes.length?t.shapeTypes:m.options.shapeTypes,n=null!=t.alpha?t.alpha:m.options.alpha,h=null!=t.candidateShapesPerStep?t.candidateShapesPerStep:m.options.candidateShapesPerStep,i=null!=t.shapeMutationsPerStep?t.shapeMutationsPerStep:m.options.shapeMutationsPerStep;return this.model.step(r,n,h,i)},getImageData:function(){if(null==this.model)throw _.thrown("FAIL: model != null");return this.model.current}};var m=function(){},g=function(t,r){this.x=i.random(t),this.y=i.random(r),this.rx=i.random(32)+1,this.ry=i.random(32)+1,this.xBound=t,this.yBound=r};g.prototype={rasterize:function(){for(var t=[],r=this.rx/this.ry,n=this.xBound,h=this.yBound,i=0,a=this.ry;i<a;){var o=i++,e=this.y-o,s=this.y+o;if(!(e<0||e>=h)||!(s<0||s>=h)){var u=Math.sqrt(this.ry*this.ry-o*o)*r|0,l=this.x-u,f=this.x+u;l<0&&(l=0),f>=n&&(f=n-1),e>=0&&e<h&&t.push(new w(e,l,f)),s>=0&&s<h&&o>0&&t.push(new w(s,l,f))}}return t},mutate:function(){switch(i.random(3)){case 0:var t=this.x+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x=t<0?0:t>r?r:t;t=this.y+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y=t<0?0:t>r?r:t;break;case 1:t=this.rx+(-16+Math.floor(33*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.rx=t<1?1:t>r?r:t;break;case 2:var r;t=this.ry+(-16+Math.floor(33*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.ry=t<1?1:t>r?r:t;break}},clone:function(){var t=new g(this.xBound,this.yBound);return t.x=this.x,t.y=this.y,t.rx=this.rx,t.ry=this.ry,t},getType:function(){return 3},getRawShapeData:function(){return[this.x,this.y,this.rx,this.ry]},getSvgShapeData:function(){return'<ellipse cx="'+this.x+'" cy="'+this.y+'" rx="'+this.rx+'" ry="'+this.ry+'" '+c.SVG_STYLE_HOOK+" />"}};var v=function(t,r){g.call(this,t,r),this.rx=i.random(32)+1,this.ry=this.rx};v.__super__=g,v.prototype=n(g.prototype,{mutate:function(){switch(n=i.random(2)){case 0:var t=this.x+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x=t<0?0:t>r?r:t;t=this.y+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y=t<0?0:t>r?r:t;break;case 1:var r;t=this.rx+(-16+Math.floor(33*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");var n=t<1?1:t>r?r:t;this.rx=n,this.ry=n;break}},clone:function(){var t=new v(this.xBound,this.yBound);return t.x=this.x,t.y=this.y,t.rx=this.rx,t.ry=this.ry,t},getType:function(){return 5},getRawShapeData:function(){return[this.x,this.y,this.rx]},getSvgShapeData:function(){return'<circle cx="'+this.x+'" cy="'+this.y+'" r="'+this.rx+'" '+c.SVG_STYLE_HOOK+" />"}});var F=function(t,r){this.x1=i.random(t),this.y1=i.random(r);var n=this.x1+i.random(32)+1;if(0>t)throw _.thrown("FAIL: min <= max");this.x2=n<0?0:n>t?t:n;n=this.y1+i.random(32)+1;if(0>r)throw _.thrown("FAIL: min <= max");this.y2=n<0?0:n>r?r:n,this.xBound=t,this.yBound=r};F.prototype={rasterize:function(){for(var t=[],r=d.bresenham(this.x1,this.y1,this.x2,this.y2),n=0;n<r.length;){var h=r[n];++n,t.push(new w(h.y,h.x,h.x))}return w.trim(t,this.xBound,this.yBound)},mutate:function(){switch(i.random(4)){case 0:var t=this.x1+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x1=t<0?0:t>r?r:t;t=this.y1+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y1=t<0?0:t>r?r:t;break;case 1:t=this.x2+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x2=t<0?0:t>r?r:t;var r;t=this.y2+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y2=t<0?0:t>r?r:t;break}},clone:function(){var t=new F(this.xBound,this.yBound);return t.x1=this.x1,t.y1=this.y1,t.x2=this.x2,t.y2=this.y2,t},getType:function(){return 6},getRawShapeData:function(){return[this.x1,this.y1,this.x2,this.y2]},getSvgShapeData:function(){return'<line x1="'+this.x1+'" y1="'+this.y1+'" x2="'+this.x2+'" y2="'+this.y2+'" '+c.SVG_STYLE_HOOK+" />"}};var M=function(t,r){var n;if(0>(n=t-1))throw _.thrown("FAIL: lower <= upper");if(this.x1=Math.floor((n+1)*Math.random()),0>(n=r-1))throw _.thrown("FAIL: lower <= upper");if(this.y1=Math.floor((n+1)*Math.random()),0>(n=t-1))throw _.thrown("FAIL: lower <= upper");if(this.cx=Math.floor((n+1)*Math.random()),0>(n=r-1))throw _.thrown("FAIL: lower <= upper");if(this.cy=Math.floor((n+1)*Math.random()),0>(n=t-1))throw _.thrown("FAIL: lower <= upper");if(this.x2=Math.floor((n+1)*Math.random()),0>(n=r-1))throw _.thrown("FAIL: lower <= upper");this.y2=Math.floor((n+1)*Math.random()),this.xBound=t,this.yBound=r};M.prototype={rasterize:function(){for(var t=[],r=[],n=0,h=19;n<h;){var i=(s=n++)/20,a=1-i,o=a*(a*this.x1+i*this.cx)+i*(a*this.cx+i*this.x2)|0,e=a*(a*this.y1+i*this.cy)+i*(a*this.cy+i*this.y2)|0;r.push({x:o,y:e})}for(n=0,h=r.length-1;n<h;)for(var s,u=r[s=n++],l=r[s+1],f=d.bresenham(u.x,u.y,l.x,l.y),x=0;x<f.length;){var y=f[x];if(++x,t.length>0){var c=t[t.length-1];if(c.y==y.y&&c.x1==y.x&&c.x2==y.x)continue}t.push(new w(y.y,y.x,y.x))}return w.trim(t,this.xBound,this.yBound)},mutate:function(){switch(Math.floor(3*Math.random())){case 0:var t=this.cx+(-8+Math.floor(17*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.cx=t<0?0:t>r?r:t;t=this.cy+(-8+Math.floor(17*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.cy=t<0?0:t>r?r:t;break;case 1:t=this.x1+(-8+Math.floor(17*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x1=t<1?1:t>r?r:t;t=this.y1+(-8+Math.floor(17*Math.random()));if(1>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y1=t<1?1:t>r?r:t;break;case 2:t=this.x2+(-8+Math.floor(17*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x2=t<1?1:t>r?r:t;var r;t=this.y2+(-8+Math.floor(17*Math.random()));if(1>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y2=t<1?1:t>r?r:t;break}},clone:function(){var t=new M(this.xBound,this.yBound);return t.cx=this.cx,t.cy=this.cy,t.x1=this.x1,t.y1=this.y1,t.x2=this.x2,t.y2=this.y2,t},getType:function(){return 7},getRawShapeData:function(){return[this.x1,this.y1,this.cx,this.cy,this.x2,this.y2]},getSvgShapeData:function(){return'<path d="M'+this.x1+" "+this.y1+" Q "+this.cx+" "+this.cy+" "+this.x2+" "+this.y2+'" '+c.SVG_STYLE_HOOK+" />"}};var A=function(t,r){this.x1=i.random(t),this.y1=i.random(r);var n=this.x1+i.random(32)+1;if(0>(h=t-1))throw _.thrown("FAIL: min <= max");this.x2=n<0?0:n>h?h:n;var h;n=this.y1+i.random(32)+1;if(0>(h=r-1))throw _.thrown("FAIL: min <= max");this.y2=n<0?0:n>h?h:n,this.xBound=t,this.yBound=r};A.prototype={rasterize:function(){var t=[],r=(h=this.y1)<(i=this.y2)?h:i,n=(h=this.y1)>(i=this.y2)?h:i;if(r==n){var h=this.x1,i=this.x2,a=this.x1,o=this.x2;t.push(new w(r,h<i?h:i,a>o?a:o))}else for(var e=r,s=n;e<s;){var u=e++;h=this.x1,i=this.x2,a=this.x1,o=this.x2;t.push(new w(u,h<i?h:i,a>o?a:o))}return t},mutate:function(){switch(i.random(2)){case 0:var t=this.x1+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x1=t<0?0:t>r?r:t;t=this.y1+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y1=t<0?0:t>r?r:t;break;case 1:t=this.x2+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x2=t<0?0:t>r?r:t;var r;t=this.y2+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y2=t<0?0:t>r?r:t;break}},clone:function(){var t=new A(this.xBound,this.yBound);return t.x1=this.x1,t.y1=this.y1,t.x2=this.x2,t.y2=this.y2,t},getType:function(){return 0},getRawShapeData:function(){var t=this.x1,r=this.x2,n=this.y1,h=this.y2,i=this.x1,a=this.x2,o=this.y1,e=this.y2;return[t<r?t:r,n<h?n:h,i>a?i:a,o>e?o:e]},getSvgShapeData:function(){var t=this.x1,r=this.x2,n=this.y1,h=this.y2,i=this.x1,a=this.x2,o=this.x1,e=this.x2,s=this.y1,u=this.y2,l=this.y1,f=this.y2;return'<rect x="'+(t<r?t:r)+'" y="'+(n<h?n:h)+'" width="'+((i>a?i:a)-(o<e?o:e))+'" height="'+((s>u?s:u)-(l<f?l:f))+'" '+c.SVG_STYLE_HOOK+" />"}};var L=function(t,r){this.x=i.random(t),this.y=i.random(r),this.rx=i.random(32)+1,this.ry=i.random(32)+1,this.angle=i.random(360),this.xBound=t,this.yBound=r};L.prototype={rasterize:function(){for(var t=[],r=this.angle*(Math.PI/180),n=Math.cos(r),h=Math.sin(r),i=0;i<20;){var a=18*i++*(Math.PI/180),o=this.rx*Math.cos(a),e=this.ry*Math.sin(a),s=o*n-e*h+this.x|0,u=o*h+e*n+this.y|0;t.push({x:s,y:u})}return w.trim(d.scanlinesForPolygon(t),this.xBound,this.yBound)},mutate:function(){switch(i.random(4)){case 0:var t=this.x+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x=t<0?0:t>r?r:t;t=this.y+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y=t<0?0:t>r?r:t;break;case 1:t=this.rx+(-16+Math.floor(33*Math.random()));if(1>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.rx=t<1?1:t>r?r:t;break;case 2:var r;t=this.ry+(-16+Math.floor(33*Math.random()));if(1>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.ry=t<1?1:t>r?r:t;break;case 3:t=this.angle+(-4+Math.floor(9*Math.random()));this.angle=t<0?0:t>360?360:t;break}},clone:function(){var t=new L(this.xBound,this.yBound);return t.x=this.x,t.y=this.y,t.rx=this.rx,t.ry=this.ry,t.angle=this.angle,t},getType:function(){return 4},getRawShapeData:function(){return[this.x,this.y,this.rx,this.ry,this.angle]},getSvgShapeData:function(){var t='<g transform="translate('+this.x+" "+this.y+") rotate("+this.angle+") scale("+this.rx+" "+this.ry+')">';return t+='<ellipse cx="0" cy="0" rx="1" ry="1" '+c.SVG_STYLE_HOOK+" />",t+="</g>"}};var I=function(t,r){this.x1=i.random(t),this.y1=i.random(r);var n=this.x1+i.random(32)+1;if(0>t)throw _.thrown("FAIL: min <= max");this.x2=n<0?0:n>t?t:n;n=this.y1+i.random(32)+1;if(0>r)throw _.thrown("FAIL: min <= max");this.y2=n<0?0:n>r?r:n,this.angle=Math.floor(361*Math.random()),this.xBound=t,this.yBound=r};I.prototype={rasterize:function(){var t,r,n=(t=this.x1)<(r=this.x2)?t:r,h=(t=this.x1)>(r=this.x2)?t:r,i=(t=this.y1)<(r=this.y2)?t:r,a=(t=this.y1)>(r=this.y2)?t:r,o=(n+h)/2|0,e=(i+a)/2|0,s=n-o,u=h-o,l=i-e,f=a-e,x=this.angle*Math.PI/180,y=Math.cos(x),c=Math.sin(x),p=s*y-l*c+o|0,m=s*c+l*y+e|0,g=s*y-f*c+o|0,v=s*c+f*y+e|0,F=u*y-l*c+o|0,M=u*c+l*y+e|0,A=u*y-f*c+o|0,L=u*c+f*y+e|0;return w.trim(d.scanlinesForPolygon([{x:p,y:m},{x:F,y:M},{x:A,y:L},{x:g,y:v}]),this.xBound,this.yBound)},mutate:function(){switch(i.random(3)){case 0:var t=this.x1+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x1=t<0?0:t>r?r:t;t=this.y1+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y1=t<0?0:t>r?r:t;break;case 1:t=this.x2+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x2=t<0?0:t>r?r:t;var r;t=this.y2+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y2=t<0?0:t>r?r:t;break;case 2:t=this.angle+(-4+Math.floor(9*Math.random()));this.angle=t<0?0:t>360?360:t;break}},clone:function(){var t=new I(this.xBound,this.yBound);return t.x1=this.x1,t.y1=this.y1,t.x2=this.x2,t.y2=this.y2,t.angle=this.angle,t},getType:function(){return 1},getRawShapeData:function(){var t=this.x1,r=this.x2,n=this.y1,h=this.y2,i=this.x1,a=this.x2,o=this.y1,e=this.y2;return[t<r?t:r,n<h?n:h,i>a?i:a,o>e?o:e,this.angle]},getSvgShapeData:function(){for(var t,r,n=(t=this.x1)<(r=this.x2)?t:r,h=(t=this.x1)>(r=this.x2)?t:r,i=(t=this.y1)<(r=this.y2)?t:r,a=(t=this.y1)>(r=this.y2)?t:r,o=(n+h)/2|0,e=(i+a)/2|0,s=n-o,u=h-o,l=i-e,f=a-e,x=this.angle*Math.PI/180,y=Math.cos(x),d=[{x:s*y-l*(w=Math.sin(x))+o|0,y:s*w+l*y+e|0},{x:u*y-l*w+o|0,y:u*w+l*y+e|0},{x:u*y-f*w+o|0,y:u*w+f*y+e|0},{x:s*y-f*w+o|0,y:s*w+f*y+e|0}],w='<polygon points="',p=0,m=d.length;p<m;){var g=p++;w+=d[g].x+" "+d[g].y,g!=d.length-1&&(w+=" ")}return w+='" '+c.SVG_STYLE_HOOK+"/>"}};var S=function(){};S.create=function(t,r,n){switch(t){case 0:return new A(r,n);case 1:return new I(r,n);case 2:return new b(r,n);case 3:return new g(r,n);case 4:return new L(r,n);case 5:return new v(r,n);case 6:return new F(r,n);case 7:return new M(r,n)}},S.randomShapeOf=function(t,r,n){if(!(null!=t&&t.length>0))throw _.thrown("FAIL: a != null && a.length > 0");var h=t.length-1;if(0>h)throw _.thrown("FAIL: lower <= upper");return S.create(t[Math.floor((h+1)*Math.random())],r,n)};var B=t.geometrize.shape.ShapeTypes=function(){},b=function(t,r){this.x1=i.random(t),this.y1=i.random(r),this.x2=this.x1+(-16+Math.floor(33*Math.random())),this.y2=this.y1+(-16+Math.floor(33*Math.random())),this.x3=this.x1+(-16+Math.floor(33*Math.random())),this.y3=this.y1+(-16+Math.floor(33*Math.random())),this.xBound=t,this.yBound=r};b.prototype={rasterize:function(){return w.trim(d.scanlinesForPolygon([{x:this.x1,y:this.y1},{x:this.x2,y:this.y2},{x:this.x3,y:this.y3}]),this.xBound,this.yBound)},mutate:function(){switch(i.random(3)){case 0:var t=this.x1+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x1=t<0?0:t>r?r:t;t=this.y1+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y1=t<0?0:t>r?r:t;break;case 1:t=this.x2+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x2=t<0?0:t>r?r:t;t=this.y2+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y2=t<0?0:t>r?r:t;break;case 2:t=this.x3+(-16+Math.floor(33*Math.random()));if(0>(r=this.xBound-1))throw _.thrown("FAIL: min <= max");this.x3=t<0?0:t>r?r:t;var r;t=this.y3+(-16+Math.floor(33*Math.random()));if(0>(r=this.yBound-1))throw _.thrown("FAIL: min <= max");this.y3=t<0?0:t>r?r:t;break}},clone:function(){var t=new b(this.xBound,this.yBound);return t.x1=this.x1,t.y1=this.y1,t.x2=this.x2,t.y2=this.y2,t.x3=this.x3,t.y3=this.y3,t},getType:function(){return 2},getRawShapeData:function(){return[this.x1,this.y1,this.x2,this.y2,this.x3,this.y3]},getSvgShapeData:function(){return'<polygon points="'+this.x1+","+this.y1+" "+this.x2+","+this.y2+" "+this.x3+","+this.y3+'" '+c.SVG_STYLE_HOOK+"/>"}};var _=function(t,r,n){Error.call(this,t),this.message=t,this.__previousException=r,this.__nativeException=null!=n?n:this};_.thrown=function(t){return t instanceof _?t.get_native():t instanceof Error?t:new k(t)},_.__super__=Error,_.prototype=n(Error.prototype,{get_native:function(){return this.__nativeException}});var k=function(t,r,n){_.call(this,String(t),r,n),this.value=t};k.__super__=_,k.prototype=n(_.prototype,{});var E=function(){this.h={}};E.prototype={keys:function(){var t=[];for(var r in this.h)this.h.hasOwnProperty(r)&&t.push(+r);return new O(t)}};var T=function(t){this.length=t.byteLength,this.b=new Uint8Array(t),this.b.bufferValue=t,t.hxBytes=this,t.bytes=this.b},O=function(t){this.current=0,this.array=t};O.prototype={hasNext:function(){return this.current<this.array.length},next:function(){return this.array[this.current++]}},onmessage=h.prototype.messageHandler,c.SVG_STYLE_HOOK="::svg_style_hook::",m.options={shapeTypes:[2],candidateShapesPerStep:50,shapeMutationsPerStep:100,alpha:128},B.RECTANGLE=0,B.ROTATED_RECTANGLE=1,B.TRIANGLE=2,B.ELLIPSE=3,B.ROTATED_ELLIPSE=4,B.CIRCLE=5,B.LINE=6,B.QUADRATIC_BEZIER=7}("undefined"!=typeof exports?exports:"undefined"!=typeof window?window:"undefined"!=typeof self?self:this);`
);