Index: imaps-frontend/node_modules/svg-pathdata/src/SVGPathData.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/SVGPathData.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/SVGPathData.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,90 @@
+import { encodeSVGPath } from "./SVGPathDataEncoder";
+import { SVGPathDataParser } from "./SVGPathDataParser";
+import { SVGPathDataTransformer } from "./SVGPathDataTransformer";
+import { TransformableSVG } from "./TransformableSVG";
+import { SVGCommand } from "./types";
+
+export class SVGPathData extends TransformableSVG {
+  commands: SVGCommand[];
+  constructor(content: string | SVGCommand[]) {
+    super();
+    if ("string" === typeof content) {
+      this.commands = SVGPathData.parse(content);
+    } else {
+      this.commands = content;
+    }
+  }
+
+  encode() {
+    return SVGPathData.encode(this.commands);
+  }
+
+  getBounds() {
+    const boundsTransform = SVGPathDataTransformer.CALCULATE_BOUNDS();
+
+    this.transform(boundsTransform);
+    return boundsTransform;
+  }
+
+  transform(
+    transformFunction: (input: SVGCommand) => SVGCommand | SVGCommand[],
+  ) {
+    const newCommands = [];
+
+    for (const command of this.commands) {
+      const transformedCommand = transformFunction(command);
+
+      if (Array.isArray(transformedCommand)) {
+        newCommands.push(...transformedCommand);
+      } else {
+        newCommands.push(transformedCommand);
+      }
+    }
+    this.commands = newCommands;
+    return this;
+  }
+
+  static encode(commands: SVGCommand[]) {
+    return encodeSVGPath(commands);
+      }
+
+  static parse(path: string) {
+    const parser = new SVGPathDataParser();
+    const commands: SVGCommand[] = [];
+    parser.parse(path, commands);
+    parser.finish(commands);
+    return commands;
+  }
+
+  static readonly CLOSE_PATH: 1 = 1;
+  static readonly MOVE_TO: 2 = 2;
+  static readonly HORIZ_LINE_TO: 4 = 4;
+  static readonly VERT_LINE_TO: 8 = 8;
+  static readonly LINE_TO: 16 = 16;
+  static readonly CURVE_TO: 32 = 32;
+  static readonly SMOOTH_CURVE_TO: 64 = 64;
+  static readonly QUAD_TO: 128 = 128;
+  static readonly SMOOTH_QUAD_TO: 256 = 256;
+  static readonly ARC: 512 = 512;
+  static readonly LINE_COMMANDS = SVGPathData.LINE_TO | SVGPathData.HORIZ_LINE_TO | SVGPathData.VERT_LINE_TO;
+  static readonly DRAWING_COMMANDS = SVGPathData.HORIZ_LINE_TO | SVGPathData.VERT_LINE_TO | SVGPathData.LINE_TO |
+  SVGPathData.CURVE_TO | SVGPathData.SMOOTH_CURVE_TO | SVGPathData.QUAD_TO |
+  SVGPathData.SMOOTH_QUAD_TO | SVGPathData.ARC;
+}
+
+export const COMMAND_ARG_COUNTS = {
+    [SVGPathData.MOVE_TO]: 2,
+    [SVGPathData.LINE_TO]: 2,
+    [SVGPathData.HORIZ_LINE_TO]: 1,
+    [SVGPathData.VERT_LINE_TO]: 1,
+    [SVGPathData.CLOSE_PATH]: 0,
+    [SVGPathData.QUAD_TO]: 4,
+    [SVGPathData.SMOOTH_QUAD_TO]: 2,
+    [SVGPathData.CURVE_TO]: 6,
+    [SVGPathData.SMOOTH_CURVE_TO]: 4,
+    [SVGPathData.ARC]: 7,
+};
+
+export {encodeSVGPath} from "./SVGPathDataEncoder";
+export {SVGPathDataParser} from "./SVGPathDataParser";
+export {SVGPathDataTransformer} from "./SVGPathDataTransformer";
Index: imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataEncoder.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataEncoder.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataEncoder.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,62 @@
+import { SVGPathData } from "./SVGPathData";
+import { SVGCommand } from "./types";
+
+// Encode SVG PathData
+// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
+
+// Private consts : Char groups
+const WSP = " ";
+
+export function encodeSVGPath(commands: SVGCommand | SVGCommand[]) {
+  let str = "";
+
+  if (!Array.isArray(commands)) {
+    commands = [commands];
+  }
+  for (let i = 0; i < commands.length; i++) {
+    const command = commands[i];
+    if (command.type === SVGPathData.CLOSE_PATH) {
+      str += "z";
+    } else if (command.type === SVGPathData.HORIZ_LINE_TO) {
+      str += (command.relative ? "h" : "H") +
+        command.x;
+    } else if (command.type === SVGPathData.VERT_LINE_TO) {
+      str += (command.relative ? "v" : "V") +
+        command.y;
+    } else if (command.type === SVGPathData.MOVE_TO) {
+      str += (command.relative ? "m" : "M") +
+        command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.LINE_TO) {
+      str += (command.relative ? "l" : "L") +
+        command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.CURVE_TO) {
+      str += (command.relative ? "c" : "C") +
+        command.x1 + WSP + command.y1 +
+        WSP + command.x2 + WSP + command.y2 +
+        WSP + command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.SMOOTH_CURVE_TO) {
+      str += (command.relative ? "s" : "S") +
+        command.x2 + WSP + command.y2 +
+        WSP + command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.QUAD_TO) {
+      str += (command.relative ? "q" : "Q") +
+        command.x1 + WSP + command.y1 +
+        WSP + command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.SMOOTH_QUAD_TO) {
+      str += (command.relative ? "t" : "T") +
+        command.x + WSP + command.y;
+    } else if (command.type === SVGPathData.ARC) {
+      str += (command.relative ? "a" : "A") +
+        command.rX + WSP + command.rY +
+        WSP + command.xRot +
+        WSP + (+command.lArcFlag) + WSP + (+command.sweepFlag) +
+        WSP + command.x + WSP + command.y;
+    } else {
+      // Unknown command
+      throw new Error(
+        `Unexpected command type "${ (command as any).type}" at index ${i}.`);
+    }
+  }
+
+  return str;
+}
Index: imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataParser.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataParser.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataParser.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,290 @@
+// Parse SVG PathData
+// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
+import { COMMAND_ARG_COUNTS, SVGPathData } from "./SVGPathData";
+import { TransformableSVG } from "./TransformableSVG";
+import { SVGCommand, TransformFunction } from "./types";
+// Private consts : Char groups
+const isWhiteSpace = (c: string) =>
+  " " === c || "\t" === c || "\r" === c || "\n" === c;
+const isDigit = (c: string) =>
+  "0".charCodeAt(0) <= c.charCodeAt(0) && c.charCodeAt(0) <= "9".charCodeAt(0);
+const COMMANDS = "mMzZlLhHvVcCsSqQtTaA";
+
+export class SVGPathDataParser extends TransformableSVG {
+  private curNumber: string = "";
+  private curCommandType: SVGCommand["type"] | -1 = -1;
+  private curCommandRelative = false;
+  private canParseCommandOrComma = true;
+  private curNumberHasExp = false;
+  private curNumberHasExpDigits = false;
+  private curNumberHasDecimal = false;
+  private curArgs: number[] = [];
+
+  constructor() {
+    super();
+  }
+
+  finish(commands: SVGCommand[] = []) {
+    this.parse(" ", commands);
+    // Adding residual command
+    if (0 !== this.curArgs.length || !this.canParseCommandOrComma) {
+      throw new SyntaxError("Unterminated command at the path end.");
+    }
+    return commands;
+  }
+
+  parse(str: string, commands: SVGCommand[] = []) {
+    const finishCommand = (command: SVGCommand) => {
+      commands.push(command);
+      this.curArgs.length = 0;
+      this.canParseCommandOrComma = true;
+    };
+
+    for (let i = 0; i < str.length; i++) {
+      const c = str[i];
+      // White spaces parsing
+      const isAArcFlag = this.curCommandType === SVGPathData.ARC &&
+        (this.curArgs.length === 3 || this.curArgs.length === 4) &&
+        this.curNumber.length === 1 &&
+        (this.curNumber === "0" || this.curNumber === "1");
+      const isEndingDigit = isDigit(c) && (
+        (this.curNumber === "0" && c === "0") ||
+        isAArcFlag
+      );
+
+      if (
+        isDigit(c) &&
+        !isEndingDigit
+      ) {
+        this.curNumber += c;
+        this.curNumberHasExpDigits = this.curNumberHasExp;
+        continue;
+      }
+      if ("e" === c || "E" === c) {
+        this.curNumber += c;
+        this.curNumberHasExp = true;
+        continue;
+      }
+      if (
+        ("-" === c || "+" === c) &&
+        this.curNumberHasExp &&
+        !this.curNumberHasExpDigits
+      ) {
+        this.curNumber += c;
+        continue;
+      }
+      // if we already have a ".", it means we are starting a new number
+      if ("." === c && !this.curNumberHasExp && !this.curNumberHasDecimal && !isAArcFlag) {
+        this.curNumber += c;
+        this.curNumberHasDecimal = true;
+        continue;
+      }
+
+      // New number
+      if (this.curNumber && -1 !== this.curCommandType) {
+        const val = Number(this.curNumber);
+        if (isNaN(val)) {
+          throw new SyntaxError(`Invalid number ending at ${i}`);
+        }
+        if (this.curCommandType === SVGPathData.ARC) {
+          if (0 === this.curArgs.length || 1 === this.curArgs.length) {
+            if (0 > val) {
+              throw new SyntaxError(
+                `Expected positive number, got "${val}" at index "${i}"`,
+              );
+            }
+          } else if (3 === this.curArgs.length || 4 === this.curArgs.length) {
+            if ("0" !== this.curNumber && "1" !== this.curNumber) {
+              throw new SyntaxError(
+                `Expected a flag, got "${this.curNumber}" at index "${i}"`,
+              );
+            }
+          }
+        }
+        this.curArgs.push(val);
+        if (this.curArgs.length === COMMAND_ARG_COUNTS[this.curCommandType]) {
+          if (SVGPathData.HORIZ_LINE_TO === this.curCommandType) {
+            finishCommand({
+              type: SVGPathData.HORIZ_LINE_TO,
+              relative: this.curCommandRelative,
+              x: val,
+            });
+          } else if (SVGPathData.VERT_LINE_TO === this.curCommandType) {
+            finishCommand({
+              type: SVGPathData.VERT_LINE_TO,
+              relative: this.curCommandRelative,
+              y: val,
+            });
+            // Move to / line to / smooth quadratic curve to commands (x, y)
+          } else if (
+            this.curCommandType === SVGPathData.MOVE_TO ||
+            this.curCommandType === SVGPathData.LINE_TO ||
+            this.curCommandType === SVGPathData.SMOOTH_QUAD_TO
+          ) {
+            finishCommand({
+              type: this.curCommandType,
+              relative: this.curCommandRelative,
+              x: this.curArgs[0],
+              y: this.curArgs[1],
+            } as SVGCommand);
+            // Switch to line to state
+            if (SVGPathData.MOVE_TO === this.curCommandType) {
+              this.curCommandType = SVGPathData.LINE_TO;
+            }
+          } else if (this.curCommandType === SVGPathData.CURVE_TO) {
+            finishCommand({
+              type: SVGPathData.CURVE_TO,
+              relative: this.curCommandRelative,
+              x1: this.curArgs[0],
+              y1: this.curArgs[1],
+              x2: this.curArgs[2],
+              y2: this.curArgs[3],
+              x: this.curArgs[4],
+              y: this.curArgs[5],
+            });
+          } else if (this.curCommandType === SVGPathData.SMOOTH_CURVE_TO) {
+            finishCommand({
+              type: SVGPathData.SMOOTH_CURVE_TO,
+              relative: this.curCommandRelative,
+              x2: this.curArgs[0],
+              y2: this.curArgs[1],
+              x: this.curArgs[2],
+              y: this.curArgs[3],
+            });
+          } else if (this.curCommandType === SVGPathData.QUAD_TO) {
+            finishCommand({
+              type: SVGPathData.QUAD_TO,
+              relative: this.curCommandRelative,
+              x1: this.curArgs[0],
+              y1: this.curArgs[1],
+              x: this.curArgs[2],
+              y: this.curArgs[3],
+            });
+          } else if (this.curCommandType === SVGPathData.ARC) {
+            finishCommand({
+              type: SVGPathData.ARC,
+              relative: this.curCommandRelative,
+              rX: this.curArgs[0],
+              rY: this.curArgs[1],
+              xRot: this.curArgs[2],
+              lArcFlag: this.curArgs[3] as 0 | 1,
+              sweepFlag: this.curArgs[4] as 0 | 1,
+              x: this.curArgs[5],
+              y: this.curArgs[6],
+            });
+          }
+        }
+        this.curNumber = "";
+        this.curNumberHasExpDigits = false;
+        this.curNumberHasExp = false;
+        this.curNumberHasDecimal = false;
+        this.canParseCommandOrComma = true;
+      }
+      // Continue if a white space or a comma was detected
+      if (isWhiteSpace(c)) {
+        continue;
+      }
+      if ("," === c && this.canParseCommandOrComma) {
+        // L 0,0, H is not valid:
+        this.canParseCommandOrComma = false;
+        continue;
+      }
+      // if a sign is detected, then parse the new number
+      if ("+" === c || "-" === c || "." === c) {
+        this.curNumber = c;
+        this.curNumberHasDecimal = "." === c;
+        continue;
+      }
+      // if a 0 is detected, then parse the new number
+      if (isEndingDigit) {
+        this.curNumber = c;
+        this.curNumberHasDecimal = false;
+        continue;
+      }
+
+      // Adding residual command
+      if (0 !== this.curArgs.length) {
+        throw new SyntaxError(`Unterminated command at index ${i}.`);
+      }
+      if (!this.canParseCommandOrComma) {
+        throw new SyntaxError(
+          `Unexpected character "${c}" at index ${i}. Command cannot follow comma`,
+        );
+      }
+      this.canParseCommandOrComma = false;
+      // Detecting the next command
+      if ("z" === c || "Z" === c) {
+        commands.push({
+          type: SVGPathData.CLOSE_PATH,
+        });
+        this.canParseCommandOrComma = true;
+        this.curCommandType = -1;
+        continue;
+        // Horizontal move to command
+      } else if ("h" === c || "H" === c) {
+        this.curCommandType = SVGPathData.HORIZ_LINE_TO;
+        this.curCommandRelative = "h" === c;
+        // Vertical move to command
+      } else if ("v" === c || "V" === c) {
+        this.curCommandType = SVGPathData.VERT_LINE_TO;
+        this.curCommandRelative = "v" === c;
+        // Move to command
+      } else if ("m" === c || "M" === c) {
+        this.curCommandType = SVGPathData.MOVE_TO;
+        this.curCommandRelative = "m" === c;
+        // Line to command
+      } else if ("l" === c || "L" === c) {
+        this.curCommandType = SVGPathData.LINE_TO;
+        this.curCommandRelative = "l" === c;
+        // Curve to command
+      } else if ("c" === c || "C" === c) {
+        this.curCommandType = SVGPathData.CURVE_TO;
+        this.curCommandRelative = "c" === c;
+        // Smooth curve to command
+      } else if ("s" === c || "S" === c) {
+        this.curCommandType = SVGPathData.SMOOTH_CURVE_TO;
+        this.curCommandRelative = "s" === c;
+        // Quadratic bezier curve to command
+      } else if ("q" === c || "Q" === c) {
+        this.curCommandType = SVGPathData.QUAD_TO;
+        this.curCommandRelative = "q" === c;
+        // Smooth quadratic bezier curve to command
+      } else if ("t" === c || "T" === c) {
+        this.curCommandType = SVGPathData.SMOOTH_QUAD_TO;
+        this.curCommandRelative = "t" === c;
+        // Elliptic arc command
+      } else if ("a" === c || "A" === c) {
+        this.curCommandType = SVGPathData.ARC;
+        this.curCommandRelative = "a" === c;
+      } else {
+        throw new SyntaxError(`Unexpected character "${c}" at index ${i}.`);
+      }
+    }
+    return commands;
+  }
+  /**
+   * Return a wrapper around this parser which applies the transformation on parsed commands.
+   */
+  transform(transform: TransformFunction) {
+    const result = Object.create(this, {
+      parse: {
+        value(chunk: string, commands: SVGCommand[] = []) {
+          const parsedCommands = Object.getPrototypeOf(this).parse.call(
+            this,
+            chunk,
+          );
+          for (const c of parsedCommands) {
+            const cT = transform(c);
+            if (Array.isArray(cT)) {
+              commands.push(...cT);
+            } else {
+              commands.push(cT);
+            }
+          }
+          return commands;
+        },
+      },
+    });
+    return result as this;
+  }
+}
Index: imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataTransformer.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataTransformer.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/SVGPathDataTransformer.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,620 @@
+// Transform SVG PathData
+// http://www.w3.org/TR/SVG/paths.html#PathDataBNF
+
+import { a2c, annotateArcCommand, arcAt, assertNumbers, bezierAt, bezierRoot,
+  intersectionUnitCircleLine } from "./mathUtils";
+import { SVGPathData } from "./SVGPathData";
+import { SVGCommand, TransformFunction } from "./types";
+
+export namespace SVGPathDataTransformer {
+  // Predefined transforming functions
+  // Rounds commands values
+  export function ROUND(roundVal = 1e13) {
+    assertNumbers(roundVal);
+    function rf(val: number) { return Math.round(val * roundVal) / roundVal; }
+    return function round(command: any) {
+      if ("undefined" !== typeof command.x1) {
+        command.x1 = rf(command.x1);
+      }
+      if ("undefined" !== typeof command.y1) {
+        command.y1 = rf(command.y1);
+      }
+
+      if ("undefined" !== typeof command.x2) {
+        command.x2 = rf(command.x2);
+      }
+      if ("undefined" !== typeof command.y2) {
+        command.y2 = rf(command.y2);
+      }
+
+      if ("undefined" !== typeof command.x) {
+        command.x = rf(command.x);
+      }
+      if ("undefined" !== typeof command.y) {
+        command.y = rf(command.y);
+      }
+
+      if ("undefined" !== typeof command.rX) {
+        command.rX = rf(command.rX);
+      }
+      if ("undefined" !== typeof command.rY) {
+        command.rY = rf(command.rY);
+      }
+
+      return command;
+    };
+  }
+  // Relative to absolute commands
+  export function TO_ABS() {
+    return INFO((command, prevX, prevY) => {
+      if (command.relative) {
+        // x1/y1 values
+        if ("undefined" !== typeof command.x1) {
+          command.x1 += prevX;
+        }
+        if ("undefined" !== typeof command.y1) {
+          command.y1 += prevY;
+        }
+        // x2/y2 values
+        if ("undefined" !== typeof command.x2) {
+          command.x2 += prevX;
+        }
+        if ("undefined" !== typeof command.y2) {
+          command.y2 += prevY;
+        }
+        // Finally x/y values
+        if ("undefined" !== typeof command.x) {
+          command.x += prevX;
+        }
+        if ("undefined" !== typeof command.y) {
+          command.y += prevY;
+        }
+        command.relative = false;
+      }
+      return command;
+    });
+  }
+  // Absolute to relative commands
+  export function TO_REL() {
+    return INFO((command, prevX, prevY) => {
+      if (!command.relative) {
+        // x1/y1 values
+        if ("undefined" !== typeof command.x1) {
+          command.x1 -= prevX;
+        }
+        if ("undefined" !== typeof command.y1) {
+          command.y1 -= prevY;
+        }
+        // x2/y2 values
+        if ("undefined" !== typeof command.x2) {
+          command.x2 -= prevX;
+        }
+        if ("undefined" !== typeof command.y2) {
+          command.y2 -= prevY;
+        }
+        // Finally x/y values
+        if ("undefined" !== typeof command.x) {
+          command.x -= prevX;
+        }
+        if ("undefined" !== typeof command.y) {
+          command.y -= prevY;
+        }
+        command.relative = true;
+      }
+      return command;
+    });
+  }
+  // Convert H, V, Z and A with rX = 0 to L
+  export function NORMALIZE_HVZ(normalizeZ = true, normalizeH = true, normalizeV = true) {
+    return INFO((command, prevX, prevY, pathStartX, pathStartY) => {
+      if (isNaN(pathStartX) && !(command.type & SVGPathData.MOVE_TO)) {
+        throw new Error("path must start with moveto");
+      }
+      if (normalizeH && command.type & SVGPathData.HORIZ_LINE_TO) {
+        command.type = SVGPathData.LINE_TO;
+        command.y = command.relative ? 0 : prevY;
+      }
+      if (normalizeV && command.type & SVGPathData.VERT_LINE_TO) {
+        command.type = SVGPathData.LINE_TO;
+        command.x = command.relative ? 0 : prevX;
+      }
+      if (normalizeZ && command.type & SVGPathData.CLOSE_PATH) {
+        command.type = SVGPathData.LINE_TO;
+        command.x = command.relative ? pathStartX - prevX : pathStartX;
+        command.y = command.relative ? pathStartY - prevY : pathStartY;
+      }
+      if (command.type & SVGPathData.ARC && (0 === command.rX || 0 === command.rY)) {
+        command.type = SVGPathData.LINE_TO;
+        delete command.rX;
+        delete command.rY;
+        delete command.xRot;
+        delete command.lArcFlag;
+        delete command.sweepFlag;
+      }
+      return command;
+    });
+  }
+  /*
+   * Transforms smooth curves and quads to normal curves and quads (SsTt to CcQq)
+   */
+  export function NORMALIZE_ST() {
+    let prevCurveC2X = NaN;
+    let prevCurveC2Y = NaN;
+    let prevQuadCX = NaN;
+    let prevQuadCY = NaN;
+
+    return INFO((command, prevX, prevY) => {
+      if (command.type & SVGPathData.SMOOTH_CURVE_TO) {
+        command.type = SVGPathData.CURVE_TO;
+        prevCurveC2X = isNaN(prevCurveC2X) ? prevX : prevCurveC2X;
+        prevCurveC2Y = isNaN(prevCurveC2Y) ? prevY : prevCurveC2Y;
+        command.x1 = command.relative ? prevX - prevCurveC2X : 2 * prevX - prevCurveC2X;
+        command.y1 = command.relative ? prevY - prevCurveC2Y : 2 * prevY - prevCurveC2Y;
+      }
+      if (command.type & SVGPathData.CURVE_TO) {
+        prevCurveC2X = command.relative ? prevX + command.x2 : command.x2;
+        prevCurveC2Y = command.relative ? prevY + command.y2 : command.y2;
+      } else {
+        prevCurveC2X = NaN;
+        prevCurveC2Y = NaN;
+      }
+      if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
+        command.type = SVGPathData.QUAD_TO;
+        prevQuadCX = isNaN(prevQuadCX) ? prevX : prevQuadCX;
+        prevQuadCY = isNaN(prevQuadCY) ? prevY : prevQuadCY;
+        command.x1 = command.relative ? prevX - prevQuadCX : 2 * prevX - prevQuadCX;
+        command.y1 = command.relative ? prevY - prevQuadCY : 2 * prevY - prevQuadCY;
+      }
+      if (command.type & SVGPathData.QUAD_TO) {
+        prevQuadCX = command.relative ? prevX + command.x1 : command.x1;
+        prevQuadCY = command.relative ? prevY + command.y1 : command.y1;
+      } else {
+        prevQuadCX = NaN;
+        prevQuadCY = NaN;
+      }
+
+      return command;
+    });
+  }
+  /*
+   * A quadratic bézier curve can be represented by a cubic bézier curve which has
+   * the same end points as the quadratic and both control points in place of the
+   * quadratic"s one.
+   *
+   * This transformer replaces QqTt commands with Cc commands respectively.
+   * This is useful for reading path data into a system which only has a
+   * representation for cubic curves.
+   */
+  export function QT_TO_C() {
+    let prevQuadX1 = NaN;
+    let prevQuadY1 = NaN;
+
+    return INFO((command, prevX, prevY) => {
+      if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
+        command.type = SVGPathData.QUAD_TO;
+        prevQuadX1 = isNaN(prevQuadX1) ? prevX : prevQuadX1;
+        prevQuadY1 = isNaN(prevQuadY1) ? prevY : prevQuadY1;
+        command.x1 = command.relative ? prevX - prevQuadX1 : 2 * prevX - prevQuadX1;
+        command.y1 = command.relative ? prevY - prevQuadY1 : 2 * prevY - prevQuadY1;
+      }
+      if (command.type & SVGPathData.QUAD_TO) {
+        prevQuadX1 = command.relative ? prevX + command.x1 : command.x1;
+        prevQuadY1 = command.relative ? prevY + command.y1 : command.y1;
+        const x1 = command.x1;
+        const y1 = command.y1;
+
+        command.type = SVGPathData.CURVE_TO;
+        command.x1 = ((command.relative ? 0 : prevX) + x1 * 2) / 3;
+        command.y1 = ((command.relative ? 0 : prevY) + y1 * 2) / 3;
+        command.x2 = (command.x + x1 * 2) / 3;
+        command.y2 = (command.y + y1 * 2) / 3;
+      } else {
+        prevQuadX1 = NaN;
+        prevQuadY1 = NaN;
+      }
+
+      return command;
+    });
+  }
+  export function INFO(
+    f: (command: any, prevXAbs: number, prevYAbs: number,
+        pathStartXAbs: number, pathStartYAbs: number) => any | any[]) {
+    let prevXAbs = 0;
+    let prevYAbs = 0;
+    let pathStartXAbs = NaN;
+    let pathStartYAbs = NaN;
+
+    return function transform(command: any) {
+      if (isNaN(pathStartXAbs) && !(command.type & SVGPathData.MOVE_TO)) {
+        throw new Error("path must start with moveto");
+      }
+
+      const result = f(command, prevXAbs, prevYAbs, pathStartXAbs, pathStartYAbs);
+
+      if (command.type & SVGPathData.CLOSE_PATH) {
+        prevXAbs = pathStartXAbs;
+        prevYAbs = pathStartYAbs;
+      }
+
+      if ("undefined" !== typeof command.x) {
+        prevXAbs = (command.relative ? prevXAbs + command.x : command.x);
+      }
+      if ("undefined" !== typeof command.y) {
+        prevYAbs = (command.relative ? prevYAbs + command.y : command.y);
+      }
+
+      if (command.type & SVGPathData.MOVE_TO) {
+        pathStartXAbs = prevXAbs;
+        pathStartYAbs = prevYAbs;
+      }
+
+      return result;
+    };
+  }
+  /*
+   * remove 0-length segments
+   */
+  export function SANITIZE(EPS = 0) {
+    assertNumbers(EPS);
+    let prevCurveC2X = NaN;
+    let prevCurveC2Y = NaN;
+    let prevQuadCX = NaN;
+    let prevQuadCY = NaN;
+
+    return INFO((command, prevX, prevY, pathStartX, pathStartY) => {
+      const abs = Math.abs;
+      let skip = false;
+      let x1Rel = 0;
+      let y1Rel = 0;
+
+      if (command.type & SVGPathData.SMOOTH_CURVE_TO) {
+        x1Rel = isNaN(prevCurveC2X) ? 0 : prevX - prevCurveC2X;
+        y1Rel = isNaN(prevCurveC2Y) ? 0 : prevY - prevCurveC2Y;
+      }
+      if (command.type & (SVGPathData.CURVE_TO | SVGPathData.SMOOTH_CURVE_TO)) {
+        prevCurveC2X = command.relative ? prevX + command.x2 : command.x2;
+        prevCurveC2Y = command.relative ? prevY + command.y2 : command.y2;
+      } else {
+        prevCurveC2X = NaN;
+        prevCurveC2Y = NaN;
+      }
+      if (command.type & SVGPathData.SMOOTH_QUAD_TO) {
+        prevQuadCX = isNaN(prevQuadCX) ? prevX : 2 * prevX - prevQuadCX;
+        prevQuadCY = isNaN(prevQuadCY) ? prevY : 2 * prevY - prevQuadCY;
+      } else if (command.type & SVGPathData.QUAD_TO) {
+        prevQuadCX = command.relative ? prevX + command.x1 : command.x1;
+        prevQuadCY = command.relative ? prevY + command.y1 : command.y2;
+      } else {
+        prevQuadCX = NaN;
+        prevQuadCY = NaN;
+      }
+
+      if (command.type & SVGPathData.LINE_COMMANDS ||
+        command.type & SVGPathData.ARC && (0 === command.rX || 0 === command.rY || !command.lArcFlag) ||
+        command.type & SVGPathData.CURVE_TO || command.type & SVGPathData.SMOOTH_CURVE_TO ||
+        command.type & SVGPathData.QUAD_TO || command.type & SVGPathData.SMOOTH_QUAD_TO) {
+        const xRel = "undefined" === typeof command.x ? 0 :
+          (command.relative ? command.x : command.x - prevX);
+        const yRel = "undefined" === typeof command.y ? 0 :
+          (command.relative ? command.y : command.y - prevY);
+
+        x1Rel = !isNaN(prevQuadCX) ? prevQuadCX - prevX :
+          "undefined" === typeof command.x1 ? x1Rel :
+            command.relative ? command.x :
+              command.x1 - prevX;
+        y1Rel = !isNaN(prevQuadCY) ? prevQuadCY - prevY :
+          "undefined" === typeof command.y1 ? y1Rel :
+            command.relative ? command.y :
+              command.y1 - prevY;
+
+        const x2Rel = "undefined" === typeof command.x2 ? 0 :
+          (command.relative ? command.x : command.x2 - prevX);
+        const y2Rel = "undefined" === typeof command.y2 ? 0 :
+          (command.relative ? command.y : command.y2 - prevY);
+
+        if (abs(xRel) <= EPS && abs(yRel) <= EPS &&
+          abs(x1Rel) <= EPS && abs(y1Rel) <= EPS &&
+          abs(x2Rel) <= EPS && abs(y2Rel) <= EPS) {
+          skip = true;
+        }
+      }
+
+      if (command.type & SVGPathData.CLOSE_PATH) {
+        if (abs(prevX - pathStartX) <= EPS && abs(prevY - pathStartY) <= EPS) {
+          skip = true;
+        }
+      }
+
+      return skip ? [] : command;
+    });
+  }
+  // SVG Transforms : http://www.w3.org/TR/SVGTiny12/coords.html#TransformList
+  // Matrix : http://apike.ca/prog_svg_transform.html
+  // a c e
+  // b d f
+  export function MATRIX(a: number, b: number, c: number, d: number, e: number, f: number) {
+    assertNumbers(a, b, c, d, e, f);
+
+    return INFO((command, prevX, prevY, pathStartX) => {
+      const origX1 = command.x1;
+      const origX2 = command.x2;
+      // if isNaN(pathStartX), then this is the first command, which is ALWAYS an
+      // absolute MOVE_TO, regardless what the relative flag says
+      const comRel = command.relative && !isNaN(pathStartX);
+      const x = "undefined" !== typeof command.x ? command.x : (comRel ? 0 : prevX);
+      const y = "undefined" !== typeof command.y ? command.y : (comRel ? 0 : prevY);
+
+      if (command.type & SVGPathData.HORIZ_LINE_TO && 0 !== b) {
+        command.type = SVGPathData.LINE_TO;
+        command.y = command.relative ? 0 : prevY;
+      }
+      if (command.type & SVGPathData.VERT_LINE_TO && 0 !== c) {
+        command.type = SVGPathData.LINE_TO;
+        command.x = command.relative ? 0 : prevX;
+      }
+
+      if ("undefined" !== typeof command.x) {
+        command.x = (command.x * a) + (y * c) + (comRel ? 0 : e);
+      }
+      if ("undefined" !== typeof command.y) {
+        command.y = (x * b) + command.y * d + (comRel ? 0 : f);
+      }
+      if ("undefined" !== typeof command.x1) {
+        command.x1 = command.x1 * a + command.y1 * c + (comRel ? 0 : e);
+      }
+      if ("undefined" !== typeof command.y1) {
+        command.y1 = origX1 * b + command.y1 * d + (comRel ? 0 : f);
+      }
+      if ("undefined" !== typeof command.x2) {
+        command.x2 = command.x2 * a + command.y2 * c + (comRel ? 0 : e);
+      }
+      if ("undefined" !== typeof command.y2) {
+        command.y2 = origX2 * b + command.y2 * d + (comRel ? 0 : f);
+      }
+      function sqr(x: number) { return x * x; }
+      const det = a * d - b * c;
+
+      if ("undefined" !== typeof command.xRot) {
+        // Skip if this is a pure translation
+        if (1 !== a || 0 !== b || 0 !== c || 1 !== d) {
+          // Special case for singular matrix
+          if (0 === det) {
+            // In the singular case, the arc is compressed to a line. The actual geometric image of the original
+            // curve under this transform possibly extends beyond the starting and/or ending points of the segment, but
+            // for simplicity we ignore this detail and just replace this command with a single line segment.
+            delete command.rX;
+            delete command.rY;
+            delete command.xRot;
+            delete command.lArcFlag;
+            delete command.sweepFlag;
+            command.type = SVGPathData.LINE_TO;
+          } else {
+            // Convert to radians
+            const xRot = command.xRot * Math.PI / 180;
+
+            // Convert rotated ellipse to general conic form
+            // x0^2/rX^2 + y0^2/rY^2 - 1 = 0
+            // x0 = x*cos(xRot) + y*sin(xRot)
+            // y0 = -x*sin(xRot) + y*cos(xRot)
+            // --> A*x^2 + B*x*y + C*y^2 - 1 = 0, where
+            const sinRot = Math.sin(xRot);
+            const cosRot = Math.cos(xRot);
+            const xCurve = 1 / sqr(command.rX);
+            const yCurve = 1 / sqr(command.rY);
+            const A = sqr(cosRot) * xCurve + sqr(sinRot) * yCurve;
+            const B = 2 * sinRot * cosRot * (xCurve - yCurve);
+            const C = sqr(sinRot) * xCurve + sqr(cosRot) * yCurve;
+
+            // Apply matrix to A*x^2 + B*x*y + C*y^2 - 1 = 0
+            // x1 = a*x + c*y
+            // y1 = b*x + d*y
+            //      (we can ignore e and f, since pure translations don"t affect the shape of the ellipse)
+            // --> A1*x1^2 + B1*x1*y1 + C1*y1^2 - det^2 = 0, where
+            const A1 = A * d * d - B * b * d + C * b * b;
+            const B1 = B * (a * d + b * c) - 2 * (A * c * d + C * a * b);
+            const C1 = A * c * c - B * a * c + C * a * a;
+
+            // Unapply newXRot to get back to axis-aligned ellipse equation
+            // x1 = x2*cos(newXRot) - y2*sin(newXRot)
+            // y1 = x2*sin(newXRot) + y2*cos(newXRot)
+            // A1*x1^2 + B1*x1*y1 + C1*y1^2 - det^2 =
+            //   x2^2*(A1*cos(newXRot)^2 + B1*sin(newXRot)*cos(newXRot) + C1*sin(newXRot)^2)
+            //   + x2*y2*(2*(C1 - A1)*sin(newXRot)*cos(newXRot) + B1*(cos(newXRot)^2 - sin(newXRot)^2))
+            //   + y2^2*(A1*sin(newXRot)^2 - B1*sin(newXRot)*cos(newXRot) + C1*cos(newXRot)^2)
+            //   (which must have the same zeroes as)
+            // x2^2/newRX^2 + y2^2/newRY^2 - 1
+            //   (so we have)
+            // 2*(C1 - A1)*sin(newXRot)*cos(newXRot) + B1*(cos(newXRot)^2 - sin(newXRot)^2) = 0
+            // (A1 - C1)*sin(2*newXRot) = B1*cos(2*newXRot)
+            // 2*newXRot = atan2(B1, A1 - C1)
+            const newXRot = ((Math.atan2(B1, A1 - C1) + Math.PI) % Math.PI) / 2;
+            // For any integer n, (atan2(B1, A1 - C1) + n*pi)/2 is a solution to the above; incrementing n just swaps
+            // the x and y radii computed below (since that"s what rotating an ellipse by pi/2 does).  Choosing the
+            // rotation between 0 and pi/2 eliminates the ambiguity and leads to more predictable output.
+
+            // Finally, we get newRX and newRY from the same-zeroes relationship that gave us newXRot
+            const newSinRot = Math.sin(newXRot);
+            const newCosRot = Math.cos(newXRot);
+
+            command.rX = Math.abs(det) /
+              Math.sqrt(A1 * sqr(newCosRot) + B1 * newSinRot * newCosRot + C1 * sqr(newSinRot));
+            command.rY = Math.abs(det) /
+              Math.sqrt(A1 * sqr(newSinRot) - B1 * newSinRot * newCosRot + C1 * sqr(newCosRot));
+            command.xRot = newXRot * 180 / Math.PI;
+          }
+        }
+      }
+      // sweepFlag needs to be inverted when mirroring shapes
+      // see http://www.itk.ilstu.edu/faculty/javila/SVG/SVG_drawing1/elliptical_curve.htm
+      // m 65,10 a 50,25 0 1 0 50,25
+      // M 65,60 A 50,25 0 1 1 115,35
+      if ("undefined" !== typeof command.sweepFlag && 0 > det) {
+        command.sweepFlag = +!command.sweepFlag;
+      }
+      return command;
+    });
+  }
+  export function ROTATE(a: number, x = 0, y = 0) {
+    assertNumbers(a, x, y);
+    const sin = Math.sin(a);
+    const cos = Math.cos(a);
+
+    return MATRIX(cos, sin, -sin, cos, x - x * cos + y * sin, y - x * sin - y * cos);
+  }
+  export function TRANSLATE(dX: number, dY = 0) {
+    assertNumbers(dX, dY);
+    return MATRIX(1, 0, 0, 1, dX, dY);
+  }
+  export function SCALE(dX: number, dY = dX) {
+    assertNumbers(dX, dY);
+    return MATRIX(dX, 0, 0, dY, 0, 0);
+  }
+  export function SKEW_X(a: number) {
+    assertNumbers(a);
+    return MATRIX(1, 0, Math.atan(a), 1, 0, 0);
+  }
+  export function SKEW_Y(a: number) {
+    assertNumbers(a);
+    return MATRIX(1, Math.atan(a), 0, 1, 0, 0);
+  }
+  export function X_AXIS_SYMMETRY(xOffset = 0) {
+    assertNumbers(xOffset);
+    return MATRIX(-1, 0, 0, 1, xOffset, 0);
+  }
+  export function Y_AXIS_SYMMETRY(yOffset = 0) {
+    assertNumbers(yOffset);
+    return MATRIX(1, 0, 0, -1, 0, yOffset);
+  }
+  // Convert arc commands to curve commands
+  export function A_TO_C() {
+    return INFO((command, prevX, prevY) => {
+      if (SVGPathData.ARC === command.type) {
+        return a2c(command, command.relative ? 0 : prevX, command.relative ? 0 : prevY);
+      }
+      return command;
+    });
+  }
+  // @see annotateArcCommand
+  export function ANNOTATE_ARCS() {
+    return INFO((c, x1, y1) => {
+      if (c.relative) {
+        x1 = 0;
+        y1 = 0;
+      }
+      if (SVGPathData.ARC === c.type) {
+        annotateArcCommand(c, x1, y1);
+      }
+      return c;
+    });
+  }
+  export function CLONE() {
+    return (c: SVGCommand) => {
+      const result = {} as SVGCommand;
+      // tslint:disable-next-line
+      for (const key in c) {
+        result[key as keyof SVGCommand] = c[key as keyof SVGCommand];
+      }
+      return result;
+    };
+  }
+  // @see annotateArcCommand
+  export function CALCULATE_BOUNDS() {
+    const clone = CLONE();
+    const toAbs = TO_ABS();
+    const qtToC = QT_TO_C();
+    const normST = NORMALIZE_ST();
+    const f: TransformFunction & {minX: number, maxX: number, minY: number, maxY: number} =
+        INFO((command, prevXAbs, prevYAbs) => {
+      const c = normST(qtToC(toAbs(clone(command))));
+      function fixX(absX: number) {
+        if (absX > f.maxX) { f.maxX = absX; }
+        if (absX < f.minX) { f.minX = absX; }
+      }
+      function fixY(absY: number) {
+        if (absY > f.maxY) { f.maxY = absY; }
+        if (absY < f.minY) { f.minY = absY; }
+      }
+      if (c.type & SVGPathData.DRAWING_COMMANDS) {
+        fixX(prevXAbs);
+        fixY(prevYAbs);
+      }
+      if (c.type & SVGPathData.HORIZ_LINE_TO) {
+        fixX(c.x);
+      }
+      if (c.type & SVGPathData.VERT_LINE_TO) {
+        fixY(c.y);
+      }
+      if (c.type & SVGPathData.LINE_TO) {
+        fixX(c.x);
+        fixY(c.y);
+      }
+      if (c.type & SVGPathData.CURVE_TO) {
+        // add start and end points
+        fixX(c.x);
+        fixY(c.y);
+        const xDerivRoots = bezierRoot(prevXAbs, c.x1, c.x2, c.x);
+
+        for (const derivRoot of xDerivRoots) {
+          if (0 < derivRoot && 1 > derivRoot) {
+            fixX(bezierAt(prevXAbs, c.x1, c.x2, c.x, derivRoot));
+          }
+        }
+        const yDerivRoots = bezierRoot(prevYAbs, c.y1, c.y2, c.y);
+
+        for (const derivRoot of yDerivRoots) {
+          if (0 < derivRoot && 1 > derivRoot) {
+            fixY(bezierAt(prevYAbs, c.y1, c.y2, c.y, derivRoot));
+          }
+        }
+      }
+      if (c.type & SVGPathData.ARC) {
+        // add start and end points
+        fixX(c.x);
+        fixY(c.y);
+        annotateArcCommand(c, prevXAbs, prevYAbs);
+        // p = cos(phi) * xv + sin(phi) * yv
+        // dp = -sin(phi) * xv + cos(phi) * yv = 0
+        const xRotRad = c.xRot / 180 * Math.PI;
+        // points on ellipse for phi = 0° and phi = 90°
+        const x0 = Math.cos(xRotRad) * c.rX;
+        const y0 = Math.sin(xRotRad) * c.rX;
+        const x90 = -Math.sin(xRotRad) * c.rY;
+        const y90 = Math.cos(xRotRad) * c.rY;
+
+        // annotateArcCommand returns phi1 and phi2 such that -180° < phi1 < 180° and phi2 is smaller or greater
+        // depending on the sweep flag. Calculate phiMin, phiMax such that -180° < phiMin < 180° and phiMin < phiMax
+        const [phiMin, phiMax] = c.phi1 < c.phi2 ?
+          [c.phi1, c.phi2] :
+          (-180 > c.phi2 ? [c.phi2 + 360, c.phi1 + 360] : [c.phi2, c.phi1]);
+        const normalizeXiEta = ([xi, eta]: [number, number]) => {
+          const phiRad = Math.atan2(eta, xi);
+          const phi = phiRad * 180 / Math.PI;
+
+          return phi < phiMin ? phi + 360 : phi;
+        };
+        // xi = cos(phi), eta = sin(phi)
+
+        const xDerivRoots = intersectionUnitCircleLine(x90, -x0, 0).map(normalizeXiEta);
+        for (const derivRoot of xDerivRoots) {
+          if (derivRoot > phiMin && derivRoot < phiMax) {
+            fixX(arcAt(c.cX, x0, x90, derivRoot));
+          }
+        }
+
+        const yDerivRoots = intersectionUnitCircleLine(y90, -y0, 0).map(normalizeXiEta);
+        for (const derivRoot of yDerivRoots) {
+          if (derivRoot > phiMin && derivRoot < phiMax) {
+            fixY(arcAt(c.cY, y0, y90, derivRoot));
+          }
+        }
+      }
+      return command;
+    }) as any;
+
+    f.minX = Infinity;
+    f.maxX = -Infinity;
+    f.minY = Infinity;
+    f.maxY = -Infinity;
+    return f;
+  }
+}
Index: imaps-frontend/node_modules/svg-pathdata/src/TransformableSVG.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/TransformableSVG.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/TransformableSVG.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,74 @@
+import { SVGPathDataTransformer } from "./SVGPathDataTransformer";
+import { TransformFunction } from "./types";
+
+export abstract class TransformableSVG {
+  round(x?: number) {
+    return this.transform(SVGPathDataTransformer.ROUND(x));
+  }
+
+  toAbs() {
+    return this.transform(SVGPathDataTransformer.TO_ABS());
+  }
+
+  toRel() {
+    return this.transform(SVGPathDataTransformer.TO_REL());
+  }
+
+  normalizeHVZ(a?: boolean, b?: boolean, c?: boolean) {
+    return this.transform(SVGPathDataTransformer.NORMALIZE_HVZ(a, b, c));
+  }
+
+  normalizeST() {
+    return this.transform(SVGPathDataTransformer.NORMALIZE_ST());
+  }
+
+  qtToC() {
+    return this.transform(SVGPathDataTransformer.QT_TO_C());
+  }
+
+  aToC() {
+    return this.transform(SVGPathDataTransformer.A_TO_C());
+  }
+
+  sanitize(eps?: number) {
+    return this.transform(SVGPathDataTransformer.SANITIZE(eps));
+  }
+
+  translate(x: number, y?: number) {
+    return this.transform(SVGPathDataTransformer.TRANSLATE(x, y));
+  }
+
+  scale(x: number, y?: number) {
+    return this.transform(SVGPathDataTransformer.SCALE(x, y));
+  }
+
+  rotate(a: number, x?: number, y?: number) {
+    return this.transform(SVGPathDataTransformer.ROTATE(a, x, y));
+  }
+
+  matrix(a: number, b: number, c: number, d: number, e: number, f: number) {
+    return this.transform(SVGPathDataTransformer.MATRIX(a, b, c, d, e, f));
+  }
+
+  skewX(a: number) {
+    return this.transform(SVGPathDataTransformer.SKEW_X(a));
+  }
+
+  skewY(a: number) {
+    return this.transform(SVGPathDataTransformer.SKEW_Y(a));
+  }
+
+  xSymmetry(xOffset?: number) {
+    return this.transform(SVGPathDataTransformer.X_AXIS_SYMMETRY(xOffset));
+  }
+
+  ySymmetry(yOffset?: number) {
+    return this.transform(SVGPathDataTransformer.Y_AXIS_SYMMETRY(yOffset));
+  }
+
+  annotateArcs() {
+    return this.transform(SVGPathDataTransformer.ANNOTATE_ARCS());
+  }
+
+  abstract transform(transformFunction: TransformFunction): this;
+}
Index: imaps-frontend/node_modules/svg-pathdata/src/mathUtils.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/mathUtils.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/mathUtils.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,200 @@
+import { SVGPathData } from "./SVGPathData";
+import { CommandA, CommandC } from "./types";
+
+export function rotate([x, y]: [number, number], rad: number) {
+  return [
+    x * Math.cos(rad) - y * Math.sin(rad),
+    x * Math.sin(rad) + y * Math.cos(rad),
+  ];
+}
+
+const DEBUG_CHECK_NUMBERS = true;
+export function assertNumbers(...numbers: number[]) {
+  if (DEBUG_CHECK_NUMBERS) {
+    for (let i = 0; i < numbers.length; i++) {
+      if ("number" !== typeof numbers[i]) {
+        throw new Error(
+          `assertNumbers arguments[${i}] is not a number. ${typeof numbers[i]} == typeof ${numbers[i]}`);
+      }
+    }
+  }
+  return true;
+}
+
+const PI = Math.PI;
+
+/**
+ * https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+ * Fixes rX and rY.
+ * Ensures lArcFlag and sweepFlag are 0 or 1
+ * Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
+ * Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true
+ */
+export function annotateArcCommand(c: CommandA, x1: number, y1: number) {
+  c.lArcFlag = (0 === c.lArcFlag) ? 0 : 1;
+  c.sweepFlag = (0 === c.sweepFlag) ? 0 : 1;
+  // tslint:disable-next-line
+  let {rX, rY, x, y} = c;
+
+  rX = Math.abs(c.rX);
+  rY = Math.abs(c.rY);
+  const [x1_, y1_] = rotate([(x1 - x) / 2, (y1 - y) / 2], -c.xRot / 180 * PI);
+  const testValue = Math.pow(x1_, 2) / Math.pow(rX, 2) + Math.pow(y1_, 2) / Math.pow(rY, 2);
+
+  if (1 < testValue) {
+    rX *= Math.sqrt(testValue);
+    rY *= Math.sqrt(testValue);
+  }
+  c.rX = rX;
+  c.rY = rY;
+  const c_ScaleTemp = (Math.pow(rX, 2) * Math.pow(y1_, 2) + Math.pow(rY, 2) * Math.pow(x1_, 2));
+  const c_Scale = (c.lArcFlag !== c.sweepFlag ? 1 : -1) *
+    Math.sqrt(Math.max(0, (Math.pow(rX, 2) * Math.pow(rY, 2) - c_ScaleTemp) / c_ScaleTemp));
+  const cx_ = rX * y1_ / rY * c_Scale;
+  const cy_ = -rY * x1_ / rX * c_Scale;
+  const cRot = rotate([cx_, cy_], c.xRot / 180 * PI);
+
+  c.cX = cRot[0] + (x1 + x) / 2;
+  c.cY = cRot[1] + (y1 + y) / 2;
+  c.phi1 = Math.atan2((y1_ - cy_) / rY, (x1_ - cx_) / rX);
+  c.phi2 = Math.atan2((-y1_ - cy_) / rY, (-x1_ - cx_) / rX);
+  if (0 === c.sweepFlag && c.phi2 > c.phi1) {
+    c.phi2 -= 2 * PI;
+  }
+  if (1 === c.sweepFlag && c.phi2 < c.phi1) {
+    c.phi2 += 2 * PI;
+  }
+  c.phi1 *= 180 / PI;
+  c.phi2 *= 180 / PI;
+}
+
+/**
+ * Solves a quadratic system of equations of the form
+ *      a * x + b * y = c
+ *      x² + y² = 1
+ * This can be understood as the intersection of the unit circle with a line.
+ *      => y = (c - a x) / b
+ *      => x² + (c - a x)² / b² = 1
+ *      => x² b² + c² - 2 c a x + a² x² = b²
+ *      => (a² + b²) x² - 2 a c x + (c² - b²) = 0
+ */
+export function intersectionUnitCircleLine(a: number, b: number, c: number): [number, number][] {
+  assertNumbers(a, b, c);
+  // cf. pqFormula
+  const termSqr = a * a + b * b - c * c;
+
+  if (0 > termSqr) {
+    return [];
+  } else if (0 === termSqr) {
+    return [
+      [
+        (a * c) / (a * a + b * b),
+        (b * c) / (a * a + b * b)]];
+  }
+  const term = Math.sqrt(termSqr);
+
+  return [
+    [
+      (a * c + b * term) / (a * a + b * b),
+      (b * c - a * term) / (a * a + b * b)],
+    [
+      (a * c - b * term) / (a * a + b * b),
+      (b * c + a * term) / (a * a + b * b)]];
+
+}
+
+export const DEG = Math.PI / 180;
+
+export function lerp(a: number, b: number, t: number) {
+  return (1 - t) * a + t * b;
+}
+
+export function arcAt(c: number, x1: number, x2: number, phiDeg: number) {
+  return c + Math.cos(phiDeg / 180 * PI) * x1 + Math.sin(phiDeg / 180 * PI) * x2;
+}
+
+export function bezierRoot(x0: number, x1: number, x2: number, x3: number) {
+  const EPS = 1e-6;
+  const x01 = x1 - x0;
+  const x12 = x2 - x1;
+  const x23 = x3 - x2;
+  const a = 3 * x01 + 3 * x23 - 6 * x12;
+  const b = (x12 - x01) * 6;
+  const c = 3 * x01;
+  // solve a * t² + b * t + c = 0
+
+  if (Math.abs(a) < EPS) {
+    // equivalent to b * t + c =>
+    return [-c / b];
+  }
+  return pqFormula(b / a, c / a, EPS);
+
+}
+
+export function bezierAt(x0: number, x1: number, x2: number, x3: number, t: number) {
+  // console.log(x0, y0, x1, y1, x2, y2, x3, y3, t)
+  const s = 1 - t;
+  const c0 = s * s * s;
+  const c1 = 3 * s * s * t;
+  const c2 = 3 * s * t * t;
+  const c3 = t * t * t;
+
+  return x0 * c0 + x1 * c1 + x2 * c2 + x3 * c3;
+}
+
+function pqFormula(p: number, q: number, PRECISION = 1e-6) {
+  // 4 times the discriminant:in
+  const discriminantX4 = p * p / 4 - q;
+
+  if (discriminantX4 < -PRECISION) {
+    return [];
+  } else if (discriminantX4 <= PRECISION) {
+    return [-p / 2];
+  }
+  const root = Math.sqrt(discriminantX4);
+
+  return [-(p / 2) - root, -(p / 2) + root];
+
+}
+
+export function a2c(arc: CommandA, x0: number, y0: number): CommandC[] {
+  if (!arc.cX) {
+    annotateArcCommand(arc, x0, y0);
+  }
+
+  const phiMin = Math.min(arc.phi1!, arc.phi2!), phiMax = Math.max(arc.phi1!, arc.phi2!), deltaPhi = phiMax - phiMin;
+  const partCount = Math.ceil(deltaPhi / 90 );
+
+  const result: CommandC[] = new Array(partCount);
+  let prevX = x0, prevY = y0;
+  for (let i = 0; i < partCount; i++) {
+    const phiStart = lerp(arc.phi1!, arc.phi2!, i / partCount);
+    const phiEnd = lerp(arc.phi1!, arc.phi2!, (i + 1) / partCount);
+    const deltaPhi = phiEnd - phiStart;
+    const f = 4 / 3 * Math.tan(deltaPhi * DEG / 4);
+    // x1/y1, x2/y2 and x/y coordinates on the unit circle for phiStart/phiEnd
+    const [x1, y1] = [
+      Math.cos(phiStart * DEG) - f * Math.sin(phiStart * DEG),
+      Math.sin(phiStart * DEG) + f * Math.cos(phiStart * DEG)];
+    const [x, y] = [Math.cos(phiEnd * DEG), Math.sin(phiEnd * DEG)];
+    const [x2, y2] = [x + f * Math.sin(phiEnd * DEG), y - f * Math.cos(phiEnd * DEG)];
+    result[i] = {relative: arc.relative, type: SVGPathData.CURVE_TO } as any;
+    const transform = (x: number, y: number) => {
+      const [xTemp, yTemp] = rotate([x * arc.rX, y * arc.rY], arc.xRot);
+      return [arc.cX! + xTemp, arc.cY! + yTemp];
+    };
+    [result[i].x1, result[i].y1] = transform(x1, y1);
+    [result[i].x2, result[i].y2] = transform(x2, y2);
+    [result[i].x, result[i].y] = transform(x, y);
+    if (arc.relative) {
+      result[i].x1 -= prevX;
+      result[i].y1 -= prevY;
+      result[i].x2 -= prevX;
+      result[i].y2 -= prevY;
+      result[i].x -= prevX;
+      result[i].y -= prevY;
+    }
+    [prevX, prevY] = [result[i].x, result[i].y];
+  }
+  return result;
+}
Index: imaps-frontend/node_modules/svg-pathdata/src/types.ts
===================================================================
--- imaps-frontend/node_modules/svg-pathdata/src/types.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/node_modules/svg-pathdata/src/types.ts	(revision 79a03170cdde4e801d12257ee86723774970427b)
@@ -0,0 +1,41 @@
+import { SVGPathData } from "./SVGPathData";
+
+export type CommandM = { relative: boolean, type: typeof SVGPathData.MOVE_TO, x: number, y: number };
+export type CommandL = { relative: boolean, type: typeof SVGPathData.LINE_TO, x: number, y: number };
+export type CommandH = { relative: boolean, type: typeof SVGPathData.HORIZ_LINE_TO, x: number };
+export type CommandV = { relative: boolean, type: typeof SVGPathData.VERT_LINE_TO, y: number };
+export type CommandZ = { type: typeof SVGPathData.CLOSE_PATH };
+export type CommandQ = {
+    relative: boolean;
+    type: typeof SVGPathData.QUAD_TO;
+    x1: number;
+    y1: number;
+    x: number;
+    y: number;
+};
+export type CommandT = { relative: boolean, type: typeof SVGPathData.SMOOTH_QUAD_TO, x: number, y: number };
+export type CommandC = {
+    relative: boolean,
+    type: typeof SVGPathData.CURVE_TO,
+    x1: number, y1: number,
+    x2: number, y2: number,
+    x: number, y: number };
+export type CommandS = {
+    relative: boolean;
+    type: typeof SVGPathData.SMOOTH_CURVE_TO;
+    x2: number;
+    y2: number;
+    x: number;
+    y: number;
+};
+export type CommandA = {
+    relative: boolean,
+    type: typeof SVGPathData.ARC,
+    rX: number, rY: number,
+    xRot: number, sweepFlag: 0 | 1, lArcFlag: 0 | 1,
+    x: number, y: number
+    cX?: number, cY?: number, phi1?: number, phi2?: number};
+export type SVGCommand = CommandM | CommandL | CommandH | CommandV | CommandZ | CommandQ |
+    CommandT | CommandC | CommandS | CommandA;
+
+export type TransformFunction = (input: SVGCommand) => SVGCommand | SVGCommand[];
