shapecaptcha
Version:
1,570 lines (1,525 loc) • 96 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["ShapeCaptcha"] = factory();
else
root["ShapeCaptcha"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 3);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = {
getContainer: function getContainer(selector) {
if (!selector) {
return document.body;
}
var container = document.querySelector(selector);
return container ? container : document.body;
},
getSizes: function getSizes(container, ctx, text1) {
var fontFamily = this.options.font;
var width = void 0,
height = void 0;
if (container === document.body) {
width = window.innerWidth - 4;
height = window.innerHeight - 4;
} else {
var bcr = container.getBoundingClientRect();
width = bcr.width;
height = bcr.height;
}
var f1 = 0.05;
var font1 = Math.round(height * f1);
ctx.font = font1 + 'px ' + fontFamily;
while (ctx.measureText(text1).width > width) {
f1 *= 0.95;
font1 = Math.round(height * f1);
ctx.font = font1 + 'px ' + fontFamily;
}
var text2 = this.options.helperText;
var f2 = 0.03;
var font2 = Math.round(height * f2);
if (text2) {
ctx.font = font2 + 'px ' + fontFamily;
while (ctx.measureText(text2).width > width) {
f2 *= 0.95;
font2 = Math.round(height * f2);
ctx.font = font2 + 'px ' + fontFamily;
}
}
var text1Y = text2 ? Math.round(height * 0.07) : Math.round(height * 0.1);
return {
width: width,
height: height,
explanation: {
height: Math.round(height * 0.2),
font1: font1,
font2: font2,
text1Y: text1Y,
text2Y: Math.round(height * 0.15)
}
};
},
checkResults: function checkResults(shapes, task) {
var res = shapes.reduce(function (acc, item) {
acc[item.shape] -= 1;
return acc;
}, Object.assign({}, task));
return Object.keys(res).every(function (key) {
return res[key] === 0;
});
},
drawTaskText: function drawTaskText(ctx, text) {
var fontFamily = this.options.font;
var s = this.sizes.explanation;
if (this.options.textBgColor) {
ctx.fillStyle = this.options.textBgColor;
ctx.fillRect(0, 0, ctx.canvas.width, s.height);
}
ctx.textAlign = 'center';
ctx.fillStyle = this.options.textColor;
ctx.font = s.font1 + 'px ' + fontFamily;
ctx.fillText(text, ctx.canvas.width / 2, s.text1Y);
if (this.options.helperText) {
ctx.font = s.font2 + 'px ' + fontFamily;
ctx.fillText(this.options.helperText, ctx.canvas.width / 2, s.text2Y);
}
},
getRandItemSet: function getRandItemSet(n) {
var items = ['circle', 'triangle', 'square'];
var result = this.shuffle(items).reduce(function (acc, item, idx) {
var total = Object.keys(acc).reduce(function (sum, key) {
sum += acc[key];
return sum;
}, 0);
var rest = n - total;
if (idx === 2) {
acc[item] = rest;
} else {
acc[item] = Math.ceil(Math.random() * rest);
}
return acc;
}, {});
return result;
},
getText: function getText(obj) {
var text = Object.keys(obj).reduce(function (str, key) {
if (obj[key]) {
if (obj[key] === 1) {
str += ' a ' + key + ',';
} else {
str += ' ' + obj[key] + ' ' + key + 's,';
}
}
return str;
}, 'Please draw');
return text.replace(/,$/, '.').replace(/,(?=[^,]*$)/, ' and');
},
shuffle: function shuffle(arr) {
var i = arr.length,
randi = void 0;
while (i) {
randi = Math.floor(Math.random() * i--);
arr[i] = [arr[randi], arr[randi] = arr[i]][0];
}
return arr;
},
drawDots: function drawDots(ctx, dots, color) {
ctx.strokeStyle = color;
ctx.beginPath();
dots.forEach(function (dot, i) {
if (i) {
ctx.lineTo(dot.x, dot.y);
} else {
ctx.moveTo(dot.x, dot.y);
}
});
ctx.stroke();
},
getPathData: function getPathData(dots) {
var shape = void 0;
try {
shape = this.shapeDetector.spot(dots);
} catch (e) {
shape = null;
}
return {
shape: shape,
dots: dots
};
},
getPointerPos: function getPointerPos(e) {
var bcr = e.target.getBoundingClientRect();
return {
x: e.pageX - bcr.left - window.scrollX,
y: e.pageY - bcr.top - window.scrollY
};
}
};
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = resolver;
function resolver(resolve, reject) {
var container = this.getContainer(this.options.container);
var self = this;
var shapes = [];
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var delay = this.options.timeout ? this.options.timeout * 1000 : 3600000;
var timer = setTimeout(function () {
container.removeChild(canvas);
canvas = null;
reject('time out!');
}, delay);
var shape = [];
var task = this.getRandItemSet(this.options.items);
var taskText = this.getText(task);
this.sizes = this.getSizes(container, ctx, taskText);
canvas.width = this.sizes.width;
canvas.height = this.sizes.height;
if (!this.options.container) {
canvas.style.marginTop = window.scrollY + 'px';
canvas.style.marginLeft = window.scrollX + 'px';
}
container.appendChild(canvas);
drawScene(ctx);
canvas.addEventListener('mousedown', setListeners);
function setListeners(e) {
e.target.addEventListener('mouseup', onMouseUp);
e.target.addEventListener('mousemove', onMouseMove);
}
function removeListeners(e) {
e.target.removeEventListener('mouseup', onMouseUp);
e.target.removeEventListener('mousemove', onMouseMove);
}
function onMouseUp(e) {
removeListeners(e);
var pathData = self.getPathData(shape);
if (pathData.shape !== null) {
proccessData(pathData);
} else {
drawScene(ctx);
}
shape = [];
}
function proccessData(data) {
var len = shapes.filter(function (item) {
return item.shape === data.shape;
}).length;
if (task[data.shape] && task[data.shape] > len) {
shapes.push(data);
}
var done = self.checkResults(shapes, task);
drawScene(ctx, done);
if (done) {
container.removeChild(canvas);
canvas = null;
clearTimeout(timer);
resolve();
}
}
function drawScene(ctx, done) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
self.drawTaskText(ctx, taskText);
if (self.options.bgColor) {
ctx.fillStyle = self.options.bgColor;
ctx.fillRect(0, self.sizes.explanation.height, canvas.width, canvas.height);
}
ctx.lineWidth = done ? self.options.successLineWidth : self.options.drawLineWidth;
if (shapes.length) {
shapes.forEach(function (item) {
self.drawDots(ctx, item.dots, self.options.acceptColor);
});
}
}
function onMouseMove(e) {
var dot = self.getPointerPos(e);
shape.push(dot);
self.drawDots(ctx, shape, self.options.drawColor);
}
}
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Stroke = function () {
function Stroke(squareSize, nbSamplePoints, points, name) {
_classCallCheck(this, Stroke);
this.squareSize = squareSize;
this.nbSamplePoints = nbSamplePoints;
this.points = points;
this.name = name;
this.processStroke();
}
_createClass(Stroke, [{
key: 'getDistance',
value: function getDistance(a, b) {
var dx = b.x - a.x;
var dy = b.y - a.y;
return Math.hypot(dx, dy);
}
}, {
key: 'processStroke',
value: function processStroke() {
this.points = this.resample();
this.setCentroid();
this.points = this.rotateBy(-this.indicativeAngle());
this.points = this.scaleToSquare();
this.setCentroid();
this.points = this.translateToOrigin();
return this;
}
}, {
key: 'resample',
value: function resample() {
var interval = this.strokeLength() / (this.nbSamplePoints - 1);
var newPoints = [this.points[0]];
var distance = 0;
for (var i = 1; i < this.points.length; i++) {
var localDistance = this.getDistance(this.points[i - 1], this.points[i]);
if (distance + localDistance >= interval) {
var q = {
x: this.points[i - 1].x + (interval - distance) / localDistance * (this.points[i].x - this.points[i - 1].x),
y: this.points[i - 1].y + (interval - distance) / localDistance * (this.points[i].y - this.points[i - 1].y)
};
newPoints.push(q);
this.points.splice(i, 0, q);
distance = 0;
} else {
distance += localDistance;
}
}
if (newPoints.length === this.nbSamplePoints - 1) {
newPoints.push(this.points[this.points.length - 1]);
}
return newPoints;
}
}, {
key: 'rotateBy',
value: function rotateBy(angle) {
var _this = this;
var cos = Math.cos(angle);
var sin = Math.sin(angle);
return this.points.map(function (point) {
return {
x: (point.x - _this.c.x) * cos - (point.y - _this.c.y) * sin + _this.c.x,
y: (point.x - _this.c.x) * sin + (point.y - _this.c.y) * cos + _this.c.y
};
});
}
}, {
key: 'scaleToSquare',
value: function scaleToSquare() {
var _this2 = this;
var box = {
minX: +Infinity,
maxX: -Infinity,
minY: +Infinity,
maxY: -Infinity
};
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = this.points[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var point = _step.value;
box.minX = Math.min(box.minX, point.x);
box.minY = Math.min(box.minY, point.y);
box.maxX = Math.max(box.maxX, point.x);
box.maxY = Math.max(box.maxY, point.y);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
box.width = box.maxX - box.minX;
box.height = box.maxY - box.minY;
return this.points.map(function (point) {
return {
x: point.x * (_this2.squareSize / box.width),
y: point.y * (_this2.squareSize / box.height)
};
});
}
}, {
key: 'translateToOrigin',
value: function translateToOrigin() {
var _this3 = this;
var _origin = {
x: 0,
y: 0
};
return this.points.map(function (point) {
return {
x: point.x + _origin.x - _this3.c.x,
y: point.y + _origin.y - _this3.c.y
};
});
}
}, {
key: 'setCentroid',
value: function setCentroid() {
this.c = this.points.reduce(function (acc, point) {
acc.x += point.x;
acc.y += point.y;
return acc;
}, {
x: 0,
y: 0
});
this.c.x /= this.points.length;
this.c.y /= this.points.length;
}
}, {
key: 'indicativeAngle',
value: function indicativeAngle() {
return Math.atan2(this.c.y - this.points[0].y, this.c.x - this.points[0].x);
}
}, {
key: 'strokeLength',
value: function strokeLength() {
var _this4 = this;
return this.points.reduce(function (acc, point, i, arr) {
if (i > 0) {
acc += _this4.getDistance(arr[i - 1], point);
}
return acc;
}, 0);
}
}, {
key: 'distanceAtBestAngle',
value: function distanceAtBestAngle(pattern) {
var _phi = 0.5 * (-1 + Math.sqrt(5));
var deg2Rad = function deg2Rad(d) {
return d * Math.PI / 180;
};
var _angleRange = deg2Rad(45);
var _anglePrecision = deg2Rad(2);
var a = -_angleRange;
var b = _angleRange;
var x1 = _phi * a + (1 - _phi) * b;
var f1 = this.distanceAtAngle(pattern, x1);
var x2 = (1 - _phi) * a + _phi * b;
var f2 = this.distanceAtAngle(pattern, x2);
while (Math.abs(b - a) > _anglePrecision) {
if (f1 < f2) {
b = x2;
x2 = x1;
f2 = f1;
x1 = _phi * a + (1 - _phi) * b;
f1 = this.distanceAtAngle(pattern, x1);
} else {
a = x1;
x1 = x2;
f1 = f2;
x2 = (1 - _phi) * a + _phi * b;
f2 = this.distanceAtAngle(pattern, x2);
}
}
return Math.min(f1, f2);
}
}, {
key: 'distanceAtAngle',
value: function distanceAtAngle(pattern, angle) {
var _this5 = this;
var strokePoints = this.rotateBy(angle);
var d = strokePoints.reduce(function (acc, point, i) {
acc += _this5.getDistance(point, pattern.points[i]);
return acc;
}, 0);
return d / strokePoints.length;
}
}]);
return Stroke;
}();
var ShapeDetector = function () {
function ShapeDetector() {
var _this6 = this;
_classCallCheck(this, ShapeDetector);
var defaultShapes = [{
points: [{
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 367.95938301086414,
y: 315.39375686645496
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}],
name: 'triangle'
}, {
points: [{
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 367.95938301086414,
y: 315.39375686645496
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}],
name: 'triangle'
}, {
points: [{
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 367.95938301086414,
y: 315.39375686645496
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}],
name: 'triangle'
}, {
points: [{
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 367.9593830108641,
y: 315.39375686645496
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 420.52500915527327
}],
name: 'triangle'
}, {
points: [{
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 367.9593830108641,
y: 315.39375686645496
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}],
name: 'triangle'
}, {
points: [{
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 262.8281307220458,
y: 175.2187538146972
}, {
x: 245.30625534057606,
y: 210.26250457763663
}, {
x: 227.78437995910636,
y: 245.30625534057606
}, {
x: 210.26250457763663,
y: 280.3500061035155
}, {
x: 192.7406291961669,
y: 315.39375686645496
}, {
x: 175.2187538146972,
y: 350.4375076293944
}, {
x: 157.69687843322748,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 403.00313377380354,
y: 385.4812583923338
}, {
x: 385.4812583923338,
y: 350.4375076293944
}, {
x: 367.9593830108641,
y: 315.39375686645496
}, {
x: 350.4375076293944,
y: 280.3500061035155
}, {
x: 332.9156322479247,
y: 245.30625534057606
}, {
x: 315.39375686645496,
y: 210.26250457763663
}, {
x: 297.87188148498524,
y: 175.2187538146972
}, {
x: 280.3500061035155,
y: 140.17500305175776
}],
name: 'triangle'
}, {
points: [{
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 175.2187538146972,
y: 140.17500305175776
}, {
x: 210.26250457763663,
y: 140.17500305175776
}, {
x: 245.30625534057606,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 315.39375686645496,
y: 140.17500305175776
}, {
x: 350.4375076293944,
y: 140.17500305175776
}, {
x: 385.4812583923338,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 175.2187538146972
}, {
x: 420.52500915527327,
y: 210.26250457763663
}, {
x: 420.52500915527327,
y: 245.30625534057606
}, {
x: 420.52500915527327,
y: 280.3500061035155
}, {
x: 420.52500915527327,
y: 315.39375686645496
}, {
x: 420.52500915527327,
y: 350.4375076293944
}, {
x: 420.52500915527327,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 350.4375076293944
}, {
x: 140.17500305175776,
y: 315.39375686645496
}, {
x: 140.17500305175776,
y: 280.3500061035155
}, {
x: 140.17500305175776,
y: 245.30625534057606
}, {
x: 140.17500305175776,
y: 210.26250457763663
}, {
x: 140.17500305175776,
y: 175.2187538146972
}, {
x: 140.17500305175776,
y: 140.17500305175776
}],
name: 'square'
}, {
points: [{
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 175.2187538146972
}, {
x: 420.52500915527327,
y: 210.26250457763663
}, {
x: 420.52500915527327,
y: 245.30625534057606
}, {
x: 420.52500915527327,
y: 280.3500061035155
}, {
x: 420.52500915527327,
y: 315.39375686645496
}, {
x: 420.52500915527327,
y: 350.4375076293944
}, {
x: 420.52500915527327,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 350.4375076293944
}, {
x: 140.17500305175776,
y: 315.39375686645496
}, {
x: 140.17500305175776,
y: 280.3500061035155
}, {
x: 140.17500305175776,
y: 245.30625534057606
}, {
x: 140.17500305175776,
y: 210.26250457763663
}, {
x: 140.17500305175776,
y: 175.2187538146972
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 175.2187538146972,
y: 140.17500305175776
}, {
x: 210.26250457763663,
y: 140.17500305175776
}, {
x: 245.30625534057606,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 315.39375686645496,
y: 140.17500305175776
}, {
x: 350.4375076293944,
y: 140.17500305175776
}, {
x: 385.4812583923338,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}],
name: 'square'
}, {
points: [{
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 350.4375076293944
}, {
x: 140.17500305175776,
y: 315.39375686645496
}, {
x: 140.17500305175776,
y: 280.3500061035155
}, {
x: 140.17500305175776,
y: 245.30625534057606
}, {
x: 140.17500305175776,
y: 210.26250457763663
}, {
x: 140.17500305175776,
y: 175.2187538146972
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 175.2187538146972,
y: 140.17500305175776
}, {
x: 210.26250457763663,
y: 140.17500305175776
}, {
x: 245.30625534057606,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 315.39375686645496,
y: 140.17500305175776
}, {
x: 350.4375076293944,
y: 140.17500305175776
}, {
x: 385.4812583923338,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 175.2187538146972
}, {
x: 420.52500915527327,
y: 210.26250457763663
}, {
x: 420.52500915527327,
y: 245.30625534057606
}, {
x: 420.52500915527327,
y: 280.3500061035155
}, {
x: 420.52500915527327,
y: 315.39375686645496
}, {
x: 420.52500915527327,
y: 350.4375076293944
}, {
x: 420.52500915527327,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}],
name: 'square'
}, {
points: [{
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 385.4812583923338
}, {
x: 140.17500305175776,
y: 350.4375076293944
}, {
x: 140.17500305175776,
y: 315.39375686645496
}, {
x: 140.17500305175776,
y: 280.3500061035155
}, {
x: 140.17500305175776,
y: 245.30625534057606
}, {
x: 140.17500305175776,
y: 210.26250457763663
}, {
x: 140.17500305175776,
y: 175.2187538146972
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 140.17500305175776,
y: 140.17500305175776
}, {
x: 175.2187538146972,
y: 140.17500305175776
}, {
x: 210.26250457763663,
y: 140.17500305175776
}, {
x: 245.30625534057606,
y: 140.17500305175776
}, {
x: 280.3500061035155,
y: 140.17500305175776
}, {
x: 315.39375686645496,
y: 140.17500305175776
}, {
x: 350.4375076293944,
y: 140.17500305175776
}, {
x: 385.4812583923338,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 140.17500305175776
}, {
x: 420.52500915527327,
y: 175.2187538146972
}, {
x: 420.52500915527327,
y: 210.26250457763663
}, {
x: 420.52500915527327,
y: 245.30625534057606
}, {
x: 420.52500915527327,
y: 280.3500061035155
}, {
x: 420.52500915527327,
y: 315.39375686645496
}, {
x: 420.52500915527327,
y: 350.4375076293944
}, {
x: 420.52500915527327,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 140.17500305175776,
y: 420.52500915527327
}],
name: 'square'
}, {
points: [{
x: 140.17500305175776,
y: 420.52500915527327
}, {
x: 175.2187538146972,
y: 420.52500915527327
}, {
x: 210.26250457763663,
y: 420.52500915527327
}, {
x: 245.30625534057606,
y: 420.52500915527327
}, {
x: 280.3500061035155,
y: 420.52500915527327
}, {
x: 315.39375686645496,
y: 420.52500915527327
}, {
x: 350.4375076293944,
y: 420.52500915527327
}, {
x: 385.4812583923338,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 420.52500915527327
}, {
x: 420.52500915527327,
y: 385.4812583923338
}, {
x: 420.52500915527327,
y: 350.4375076293944
}, {
x: 420.52500915527327,
y: 315.39375686645496
}, {
x: 420.52500915527327,
y: 280.3500061035155
},