import { modelLogger as logger } from '../configuration/LoggerConfig'
/**
* Stroke symbol
* @typedef {Object} Stroke
* @property {String} type=stroke Symbol type, 'stroke' for stroke
* @property {String} pointerType=undefined Pointer type
* @property {Number} pointerId=undefined Pointer id
* @property {Array<Number>} x=[] X coordinates
* @property {Array<Number>} y=[] Y coordinates
* @property {Array<Number>} t=[] Timestamps matching x,y coordinates
* @property {Array<Number>} p=[] Pressure
* @property {Array<Number>} l=[] Length from origin
* @property {Number} width=0 (for rendering) Pen/brush width
* @property {String} color=undefined (for rendering) Pen/brush color
*/
/**
* pointerEvents symbol
* @typedef {Object} pointerEvents
* @property {String} type=pointerEvents Symbol type, 'pointerEvents' for pointerEvents
* @property {Boolean} processGestures=False indicates if the gestures have to be processed
* @property {Array<Stroke>} events=[] the events to process
*/
function computeDistance (x, y, xArray, yArray, lastIndexPoint) {
const distance = Math.sqrt(Math.pow((y - yArray[lastIndexPoint - 1]), 2) + Math.pow((x - xArray[lastIndexPoint - 1]), 2))
return isNaN(distance) ? 0 : distance
}
function computeLength (x, y, xArray, yArray, lArray, lastIndexPoint) {
const length = lArray[lastIndexPoint - 1] + computeDistance(x, y, xArray, yArray, lastIndexPoint)
return isNaN(length) ? 0 : length
}
function computePressure (x, y, xArray, yArray, lArray, lastIndexPoint) {
let ratio = 1.0
const distance = computeDistance(x, y, xArray, yArray, lastIndexPoint)
const length = computeLength(x, y, xArray, yArray, lArray, lastIndexPoint)
if (length === 0) {
ratio = 0.5
} else if (distance === length) {
ratio = 1.0
} else if (distance < 10) {
ratio = 0.2 + Math.pow(0.1 * distance, 0.4)
} else if (distance > length - 10) {
ratio = 0.2 + Math.pow(0.1 * (length - distance), 0.4)
}
const pressure = ratio * Math.max(0.1, 1.0 - (0.1 * Math.sqrt(distance)))
return isNaN(parseFloat(pressure)) ? 0.5 : pressure
}
function filterPointByAcquisitionDelta (x, y, xArray, yArray, width) {
const delta = (2 + (width / 4))
let ret = false
if (xArray.length === 0 || yArray.length === 0 || Math.abs(xArray[xArray.length - 1] - x) >= delta || Math.abs(yArray[yArray.length - 1] - y) >= delta) {
ret = true
}
return ret
}
/**
* Create a new stroke
* @param {Object} properties Properties to be applied to the stroke.
* @return {Stroke} New stroke with properties for quadratics draw
*/
export function createStrokeComponent (properties) {
const defaultStroke = {
type: 'stroke',
x: [],
y: [],
t: [],
p: [],
l: [],
width: 0
}
return Object.assign({}, defaultStroke, properties)
}
/**
* Get a JSON copy of a stroke by filtering its properties
* @param {Stroke} stroke Current stroke
* @return {{x: Array<Number>, y: Array<Number>, t: Array<Number>}} Simplified stroke object
*/
export function toJSON (stroke) {
return { x: stroke.x, y: stroke.y, t: stroke.t, pointerType: stroke.pointerType }
}
/**
* Mutate a stroke by adding a point to it.
* @param {Stroke} stroke Current stroke
* @param {{x: Number, y: Number, t: Number}} point Point to add
* @return {Stroke} Updated stroke
*/
export function addPoint (stroke, point) {
const strokeReference = stroke
if (filterPointByAcquisitionDelta(point.x, point.y, strokeReference.x, strokeReference.y, strokeReference.width)) {
strokeReference.x.push(point.x)
strokeReference.y.push(point.y)
strokeReference.t.push(point.t)
strokeReference.p.push(computePressure(point.x, point.y, strokeReference.x, strokeReference.y, strokeReference.l, strokeReference.x.length - 1))
strokeReference.l.push(computeLength(point.x, point.y, strokeReference.x, strokeReference.y, strokeReference.l, strokeReference.x.length - 1))
} else {
logger.trace('ignore filtered point', point)
}
return strokeReference
}
/**
* Slice a stroke and return the sliced part of it
* @param {Stroke} stroke Current stroke
* @param {Number} [start=0] Zero-based index at which to begin extraction
* @param {Number} [end=length] Zero-based index at which to end extraction
* @return {Stroke} Sliced stroke
*/
export function slice (stroke, start = 0, end = stroke.x.length) {
const slicedStroke = createStrokeComponent({ color: stroke.color, width: stroke.width })
for (let i = start; i < end; i++) {
addPoint(slicedStroke, {
x: stroke.x[i],
y: stroke.y[i],
t: stroke.t[i]
})
}
return slicedStroke
}
/**
* Extract point by index
* @param {Stroke} stroke Current stroke
* @param {Number} index Zero-based index
* @return {{x: Number, y: Number, t: Number, p: Number, l: Number}} Point with properties for quadratics draw
*/
export function getPointByIndex (stroke, index) {
let point
if (index !== undefined && index >= 0 && index < stroke.x.length) {
point = {
x: stroke.x[index],
y: stroke.y[index],
t: stroke.t[index],
p: stroke.p[index],
l: stroke.l[index]
}
}
return point
}