summaryrefslogtreecommitdiffstats
path: root/src/PointArray.js
blob: aa5f84a39c3a5c6e63254925a33ade6d61393dac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Poly points array
SVG.PointArray = function (array, fallback) {
  SVG.Array.call(this, array, fallback || [[0, 0]])
}

// Inherit from SVG.Array
SVG.PointArray.prototype = new SVG.Array()
SVG.PointArray.prototype.constructor = SVG.PointArray

SVG.extend(SVG.PointArray, {
  // Convert array to string
  toString: function () {
    // convert to a poly point string
    for (var i = 0, il = this.value.length, array = []; i < il; i++) {
      array.push(this.value[i].join(','))
    }

    return array.join(' ')
  },

  toArray: function () {
    return this.value.reduce(function (prev, curr) {
      return [].concat.call(prev, curr)
    }, [])
  },

  // Convert array to line object
  toLine: function () {
    return {
      x1: this.value[0][0],
      y1: this.value[0][1],
      x2: this.value[1][0],
      y2: this.value[1][1]
    }
  },

  // Get morphed array at given position
  at: function (pos) {
    // make sure a destination is defined
    if (!this.destination) return this

    // generate morphed point string
    for (var i = 0, il = this.value.length, array = []; i < il; i++) {
      array.push([
        this.value[i][0] + (this.destination[i][0] - this.value[i][0]) * pos,
        this.value[i][1] + (this.destination[i][1] - this.value[i][1]) * pos
      ])
    }

    return new SVG.PointArray(array)
  },

  // Parse point string and flat array
  parse: function (array) {
    var points = []

    array = array.valueOf()

    // if it is an array
    if (Array.isArray(array)) {
      // and it is not flat, there is no need to parse it
      if (Array.isArray(array[0])) {
        return array
      }
    } else { // Else, it is considered as a string
      // parse points
      array = array.trim().split(SVG.regex.delimiter).map(parseFloat)
    }

    // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints
    // Odd number of coordinates is an error. In such cases, drop the last odd coordinate.
    if (array.length % 2 !== 0) array.pop()

    // wrap points in two-tuples and parse points as floats
    for (var i = 0, len = array.length; i < len; i = i + 2) {
      points.push([ array[i], array[i + 1] ])
    }

    return points
  },

  // Move point string
  move: function (x, y) {
    var box = this.bbox()

    // get relative offset
    x -= box.x
    y -= box.y

    // move every point
    if (!isNaN(x) && !isNaN(y)) {
      for (var i = this.value.length - 1; i >= 0; i--) {
        this.value[i] = [this.value[i][0] + x, this.value[i][1] + y]
      }
    }

    return this
  },
  // Resize poly string
  size: function (width, height) {
    var i
    var box = this.bbox()

    // recalculate position of all points according to new size
    for (i = this.value.length - 1; i >= 0; i--) {
      if (box.width) this.value[i][0] = ((this.value[i][0] - box.x) * width) / box.width + box.x
      if (box.height) this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y
    }

    return this
  },

  // Get bounding box of points
  bbox: function () {
    var maxX = -Infinity
    var maxY = -Infinity
    var minX = Infinity
    var minY = Infinity
    this.value.forEach(function (el) {
      maxX = Math.max(el[0], maxX)
      maxY = Math.max(el[1], maxY)
      minX = Math.min(el[0], minX)
      minY = Math.min(el[1], minY)
    })
    return {x: minX, y: minY, width: maxX - minX, height: maxY - minY}
  }
})