import * as StrokeComponent from '../../../model/StrokeComponent'
import { computeLinksPoints, computeMiddlePoint, computeAxeAngle } from '../../QuadraticUtils'
/**
* Get info
* @return {StrokerInfo} Information about this stroker
*/
export function getInfo () {
return {
type: 'svg',
name: 'quadratic'
}
}
function renderArc (context, center, radius) {
const svgPath = [
`M ${center.x},${center.y}`,
`m ${-radius},0`,
`a ${radius},${radius} 0 1 0 ${radius * 2},0`,
`a ${radius},${radius} 0 1 0 ${-(radius * 2)},0`
].join(' ')
return svgPath
}
function renderLine (context, begin, end, width) {
const linkPoints1 = computeLinksPoints(begin, computeAxeAngle(begin, end), width)
const linkPoints2 = computeLinksPoints(end, computeAxeAngle(begin, end), width)
const svgPath = [
`M ${linkPoints1[0].x},${linkPoints1[0].y}`,
`L ${linkPoints2[0].x},${linkPoints2[0].y}`,
`L ${linkPoints2[1].x},${linkPoints2[1].y}`,
`L ${linkPoints1[1].x},${linkPoints1[1].y}`
].join(' ')
return svgPath
}
function renderFinal (context, begin, end, width) {
const ARCSPLIT = 6
const angle = computeAxeAngle(begin, end)
const linkPoints = computeLinksPoints(end, angle, width)
const parts = [`M ${linkPoints[0].x},${linkPoints[0].y}`]
for (let i = 1; i <= ARCSPLIT; i++) {
const newAngle = angle - (i * (Math.PI / ARCSPLIT))
parts.push(`L ${end.x - (end.p * width * Math.sin(newAngle))},${end.y + (end.p * width * Math.cos(newAngle))}`)
}
const svgPath = parts.join(' ')
return svgPath
}
function renderQuadratic (context, begin, end, ctrl, width) {
const linkPoints1 = computeLinksPoints(begin, computeAxeAngle(begin, ctrl), width)
const linkPoints2 = computeLinksPoints(end, computeAxeAngle(ctrl, end), width)
const linkPoints3 = computeLinksPoints(ctrl, computeAxeAngle(begin, end), width)
const svgPath = [
`M ${linkPoints1[0].x},${linkPoints1[0].y}`,
`Q ${linkPoints3[0].x},${linkPoints3[0].y} ${linkPoints2[0].x},${linkPoints2[0].y}`,
`L ${linkPoints2[1].x},${linkPoints2[1].y}`,
`Q ${linkPoints3[1].x},${linkPoints3[1].y} ${linkPoints1[1].x},${linkPoints1[1].y}`
].join(' ')
return svgPath
}
const buildSVGPath = (context, stroke) => {
const length = stroke.x.length
const width = stroke.width
const firstPoint = StrokeComponent.getPointByIndex(stroke, 0)
const nbquadratics = length - 2
const parts = []
if (length < 3) {
parts.push(renderArc(context, firstPoint, width * 0.6))
} else {
parts.push(renderArc(context, firstPoint, width * firstPoint.p))
parts.push(renderLine(context, firstPoint, computeMiddlePoint(firstPoint, StrokeComponent.getPointByIndex(stroke, 1)), width))
for (let i = 0; i < nbquadratics; i++) {
parts.push(renderQuadratic(context, computeMiddlePoint(StrokeComponent.getPointByIndex(stroke, i), StrokeComponent.getPointByIndex(stroke, i + 1)), computeMiddlePoint(StrokeComponent.getPointByIndex(stroke, i + 1), StrokeComponent.getPointByIndex(stroke, i + 2)), StrokeComponent.getPointByIndex(stroke, i + 1), width))
}
parts.push(renderLine(context, computeMiddlePoint(StrokeComponent.getPointByIndex(stroke, length - 2), StrokeComponent.getPointByIndex(stroke, length - 1)), StrokeComponent.getPointByIndex(stroke, length - 1), width))
parts.push(renderFinal(context, StrokeComponent.getPointByIndex(stroke, length - 2), StrokeComponent.getPointByIndex(stroke, length - 1), width))
}
return parts.join(' ')
}
/**
* Draw a stroke on a svg tag, using quadratics
* @param {Object} context Current rendering context
* @param {Stroke} stroke Current stroke to be drawn
*/
export function drawStroke (context, stroke) {
const svgPath = buildSVGPath(context, stroke)
context
.attr('color', stroke.color)
.style('fill', stroke.color)
.style('stroke', 'transparent')
.classed('pending-stroke', true)
.attr('d', `${svgPath}Z`)
}
export function drawErasingStroke (context, stroke) {
stroke.width = 20
const svgPath = buildSVGPath(context, stroke)
context
.style('fill', 'grey')
.style('stroke', 'transparent')
.style('opacity', '0.2')
.style('shadowBlur', '5')
.classed('erasing-stroke', true)
.attr('d', `${svgPath}Z`)
}