|
import * as math from '../../../math'; |
|
import * as is from '../../../is'; |
|
import * as util from '../../../util'; |
|
|
|
var BRp = {}; |
|
|
|
BRp.arrowShapeWidth = 0.3; |
|
|
|
BRp.registerArrowShapes = function(){ |
|
var arrowShapes = this.arrowShapes = {}; |
|
var renderer = this; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var bbCollide = function( x, y, size, angle, translation, edgeWidth, padding ){ |
|
var x1 = translation.x - size / 2 - padding; |
|
var x2 = translation.x + size / 2 + padding; |
|
var y1 = translation.y - size / 2 - padding; |
|
var y2 = translation.y + size / 2 + padding; |
|
|
|
var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2); |
|
|
|
return inside; |
|
}; |
|
|
|
var transform = function( x, y, size, angle, translation ){ |
|
var xRotated = x * Math.cos( angle ) - y * Math.sin( angle ); |
|
var yRotated = x * Math.sin( angle ) + y * Math.cos( angle ); |
|
|
|
var xScaled = xRotated * size; |
|
var yScaled = yRotated * size; |
|
|
|
var xTranslated = xScaled + translation.x; |
|
var yTranslated = yScaled + translation.y; |
|
|
|
return { |
|
x: xTranslated, |
|
y: yTranslated |
|
}; |
|
}; |
|
|
|
var transformPoints = function( pts, size, angle, translation ){ |
|
var retPts = []; |
|
|
|
for( var i = 0; i < pts.length; i += 2 ){ |
|
var x = pts[ i ]; |
|
var y = pts[ i + 1]; |
|
|
|
retPts.push( transform( x, y, size, angle, translation ) ); |
|
} |
|
|
|
return retPts; |
|
}; |
|
|
|
var pointsToArr = function( pts ){ |
|
var ret = []; |
|
|
|
for( var i = 0; i < pts.length; i++ ){ |
|
var p = pts[ i ]; |
|
|
|
ret.push( p.x, p.y ); |
|
} |
|
|
|
return ret; |
|
}; |
|
|
|
var standardGap = function( edge ) { |
|
return edge.pstyle( 'width' ).pfValue * edge.pstyle( 'arrow-scale' ).pfValue * 2; |
|
}; |
|
|
|
var defineArrowShape = function( name, defn ){ |
|
if( is.string( defn ) ){ |
|
defn = arrowShapes[ defn ]; |
|
} |
|
|
|
arrowShapes[ name ] = util.extend( { |
|
name: name, |
|
|
|
points: [ |
|
-0.15, -0.3, |
|
0.15, -0.3, |
|
0.15, 0.3, |
|
-0.15, 0.3 |
|
], |
|
|
|
collide: function( x, y, size, angle, translation, padding ){ |
|
var points = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); |
|
var inside = math.pointInsidePolygonPoints( x, y, points ); |
|
|
|
return inside; |
|
}, |
|
|
|
roughCollide: bbCollide, |
|
|
|
draw: function( context, size, angle, translation ){ |
|
var points = transformPoints( this.points, size, angle, translation ); |
|
|
|
renderer.arrowShapeImpl( 'polygon' )( context, points ); |
|
}, |
|
|
|
spacing: function( edge ){ |
|
return 0; |
|
}, |
|
|
|
gap: standardGap |
|
}, defn ); |
|
}; |
|
|
|
defineArrowShape( 'none', { |
|
collide: util.falsify, |
|
|
|
roughCollide: util.falsify, |
|
|
|
draw: util.noop, |
|
|
|
spacing: util.zeroify, |
|
|
|
gap: util.zeroify |
|
} ); |
|
|
|
defineArrowShape( 'triangle', { |
|
points: [ |
|
-0.15, -0.3, |
|
0, 0, |
|
0.15, -0.3 |
|
] |
|
} ); |
|
|
|
defineArrowShape( 'arrow', 'triangle' ); |
|
|
|
defineArrowShape( 'triangle-backcurve', { |
|
points: arrowShapes[ 'triangle' ].points, |
|
|
|
controlPoint: [ 0, -0.15 ], |
|
|
|
roughCollide: bbCollide, |
|
|
|
draw: function( context, size, angle, translation, edgeWidth ){ |
|
var ptsTrans = transformPoints( this.points, size, angle, translation ); |
|
var ctrlPt = this.controlPoint; |
|
var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation ); |
|
|
|
renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans ); |
|
}, |
|
|
|
gap: function( edge ) { |
|
return standardGap(edge) * 0.8; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'triangle-tee', { |
|
points: [ |
|
0, 0, |
|
0.15, -0.3, |
|
-0.15, -0.3, |
|
0, 0 |
|
], |
|
|
|
pointsTee: [ |
|
-0.15, -0.4, |
|
-0.15, -0.5, |
|
0.15, -0.5, |
|
0.15, -0.4 |
|
], |
|
|
|
collide: function( x, y, size, angle, translation, edgeWidth, padding ){ |
|
var triPts = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); |
|
var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2 * padding, angle, translation ) ); |
|
|
|
var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts ); |
|
|
|
return inside; |
|
}, |
|
|
|
draw: function( context, size, angle, translation, edgeWidth ){ |
|
var triPts = transformPoints( this.points, size, angle, translation ); |
|
var teePts = transformPoints( this.pointsTee, size, angle, translation ); |
|
|
|
renderer.arrowShapeImpl( this.name )( context, triPts, teePts ); |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'circle-triangle', { |
|
radius: 0.15, |
|
pointsTr: [0, -0.15, 0.15, -0.45, -0.15, -0.45, 0, -0.15], |
|
collide: function collide(x, y, size, angle, translation, edgeWidth, padding) { |
|
var t = translation; |
|
var circleInside = Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2 * padding) * this.radius, 2); |
|
var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation)); |
|
return math.pointInsidePolygonPoints(x, y, triPts) || circleInside; |
|
}, |
|
draw: function draw(context, size, angle, translation, edgeWidth) { |
|
var triPts = transformPoints(this.pointsTr, size, angle, translation); |
|
renderer.arrowShapeImpl(this.name)(context, triPts, translation.x, translation.y, this.radius * size); |
|
}, |
|
spacing: function spacing(edge) { |
|
return renderer.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.radius; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'triangle-cross', { |
|
points: [ |
|
0, 0, |
|
0.15, -0.3, |
|
-0.15, -0.3, |
|
0, 0 |
|
], |
|
|
|
baseCrossLinePts: [ |
|
-0.15, -0.4, |
|
-0.15, -0.4, |
|
0.15, -0.4, |
|
0.15, -0.4 |
|
], |
|
|
|
crossLinePts: function( size, edgeWidth ){ |
|
|
|
var p = this.baseCrossLinePts.slice(); |
|
var shiftFactor = edgeWidth / size; |
|
var y0 = 3; |
|
var y1 = 5; |
|
|
|
p[y0] = p[y0] - shiftFactor; |
|
p[y1] = p[y1] - shiftFactor; |
|
|
|
return p; |
|
}, |
|
|
|
collide: function( x, y, size, angle, translation, edgeWidth, padding ){ |
|
var triPts = pointsToArr( transformPoints( this.points, size + 2 * padding, angle, translation ) ); |
|
var teePts = pointsToArr( transformPoints( this.crossLinePts( size, edgeWidth ), size + 2 * padding, angle, translation ) ); |
|
var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts ); |
|
|
|
return inside; |
|
}, |
|
|
|
draw: function( context, size, angle, translation, edgeWidth ){ |
|
var triPts = transformPoints( this.points, size, angle, translation ); |
|
var crossLinePts = transformPoints( this.crossLinePts( size, edgeWidth ), size, angle, translation ); |
|
|
|
renderer.arrowShapeImpl( this.name )( context, triPts, crossLinePts ); |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'vee', { |
|
points: [ |
|
-0.15, -0.3, |
|
0, 0, |
|
0.15, -0.3, |
|
0, -0.15 |
|
], |
|
|
|
gap: function( edge ){ |
|
return standardGap(edge) * 0.525; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'circle', { |
|
radius: 0.15, |
|
|
|
collide: function( x, y, size, angle, translation, edgeWidth, padding ){ |
|
var t = translation; |
|
var inside = ( Math.pow( t.x - x, 2 ) + Math.pow( t.y - y, 2 ) <= Math.pow( (size + 2 * padding) * this.radius, 2 ) ); |
|
|
|
return inside; |
|
}, |
|
|
|
draw: function( context, size, angle, translation, edgeWidth ){ |
|
renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size ); |
|
}, |
|
|
|
spacing: function( edge ){ |
|
return renderer.getArrowWidth( edge.pstyle( 'width' ).pfValue, edge.pstyle( 'arrow-scale' ).value ) |
|
* this.radius; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'tee', { |
|
points: [ |
|
-0.15, 0, |
|
-0.15, -0.1, |
|
0.15, -0.1, |
|
0.15, 0 |
|
], |
|
|
|
spacing: function( edge ){ |
|
return 1; |
|
}, |
|
|
|
gap: function( edge ){ |
|
return 1; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'square', { |
|
points: [ |
|
-0.15, 0.00, |
|
0.15, 0.00, |
|
0.15, -0.3, |
|
-0.15, -0.3 |
|
] |
|
} ); |
|
|
|
defineArrowShape( 'diamond', { |
|
points: [ |
|
-0.15, -0.15, |
|
0, -0.3, |
|
0.15, -0.15, |
|
0, 0 |
|
], |
|
|
|
gap: function( edge ){ |
|
return edge.pstyle( 'width' ).pfValue * edge.pstyle( 'arrow-scale' ).value; |
|
} |
|
} ); |
|
|
|
defineArrowShape( 'chevron', { |
|
points: [ |
|
0, 0, |
|
-0.15, -0.15, |
|
-0.1, -0.2, |
|
0, -0.1, |
|
0.1, -0.2, |
|
0.15, -0.15 |
|
], |
|
|
|
gap: function( edge ){ |
|
return 0.95 * edge.pstyle( 'width' ).pfValue * edge.pstyle( 'arrow-scale' ).value; |
|
} |
|
} ); |
|
|
|
}; |
|
|
|
export default BRp; |