cytoscape
Advanced tools
Comparing version 3.28.1 to 3.29.0
{ | ||
"name": "cytoscape", | ||
"version": "3.28.1", | ||
"version": "3.29.0", | ||
"license": "MIT", | ||
@@ -34,2 +34,9 @@ "description": "Graph theory (a.k.a. network) library for analysis and visualisation", | ||
"main": "dist/cytoscape.cjs.js", | ||
"module": "dist/cytoscape.esm.js", | ||
"exports": { | ||
".": { | ||
"import": "./dist/cytoscape.esm.js", | ||
"require": "./dist/cytoscape.cjs.js" | ||
} | ||
}, | ||
"unpkg": "dist/cytoscape.min.js", | ||
@@ -93,2 +100,3 @@ "jsdelivr": "dist/cytoscape.min.js", | ||
"handlebars": "^4.7.6", | ||
"heap": "^0.2.7", | ||
"highlight.js": "^10.0.0", | ||
@@ -98,2 +106,3 @@ "http-server": "^0.12.3", | ||
"livereload": "^0.9.1", | ||
"lodash": "^4.17.21", | ||
"marked": "^4.0.10", | ||
@@ -106,7 +115,3 @@ "mocha": "^7.1.2", | ||
"rollup-plugin-terser": "^5.3.0" | ||
}, | ||
"dependencies": { | ||
"heap": "^0.2.6", | ||
"lodash": "^4.17.21" | ||
} | ||
} |
@@ -11,3 +11,3 @@ <img style="width: 200px; height: 200px;" src="https://raw.githubusercontent.com/cytoscape/cytoscape.js/unstable/documentation/img/cytoscape-logo.png" width="200" height="200"> | ||
[![Automated tests](https://github.com/cytoscape/cytoscape.js/actions/workflows/tests.yml/badge.svg)](https://github.com/cytoscape/cytoscape.js/actions/workflows/tests.yml) | ||
[![Extensions](https://img.shields.io/badge/Extensions-68-brightgreen.svg)](https://js.cytoscape.org/#extensions) | ||
[![Extensions](https://img.shields.io/badge/Extensions-70-brightgreen.svg)](https://js.cytoscape.org/#extensions) | ||
[![Cloudflare](https://img.shields.io/badge/Powered%20by-Cloudflare-orange.svg)](https://cloudflare.com) | ||
@@ -14,0 +14,0 @@ |
@@ -96,5 +96,5 @@ import nodeResolve from '@rollup/plugin-node-resolve'; | ||
output: { file: 'build/cytoscape.cjs.js', format: 'cjs' }, | ||
external: isExternal, | ||
plugins: [ | ||
nodeResolve(), | ||
commonjs({ include: '**/node_modules/**' }), | ||
BABEL ? babel(getBabelOptions()) : {}, | ||
@@ -109,5 +109,5 @@ replace(envVariables), | ||
output: { file: 'build/cytoscape.esm.js', format: 'es' }, | ||
external: isExternal, | ||
plugins: [ | ||
nodeResolve(), | ||
commonjs({ include: '**/node_modules/**' }), | ||
BABEL ? babel(getBabelOptions()) : {}, | ||
@@ -114,0 +114,0 @@ replace(envVariables), |
@@ -614,3 +614,3 @@ import * as is from '../../is'; | ||
curveStyle === 'bezier' || curveStyle === 'unbundled-bezier' | ||
|| curveStyle === 'segments' || curveStyle === 'taxi' | ||
|| curveStyle.endsWith('segments') || curveStyle.endsWith('taxi') | ||
){ | ||
@@ -626,2 +626,4 @@ let pts; | ||
case 'taxi': | ||
case 'round-segments': | ||
case 'round-taxi': | ||
pts = rstyle.linePts; | ||
@@ -628,0 +630,0 @@ break; |
@@ -137,2 +137,4 @@ import * as math from '../../../../math'; | ||
var pos = node.position(); | ||
var cornerRadius = node.pstyle('corner-radius').value === 'auto' ? 'auto' : node.pstyle('corner-radius').pfValue; | ||
var rs = node._private.rscratch; | ||
@@ -147,3 +149,3 @@ if( | ||
if( | ||
shape.checkPoint( x, y, 0, width, height, pos.x, pos.y ) | ||
shape.checkPoint( x, y, 0, width, height, pos.x, pos.y, cornerRadius, rs ) | ||
){ | ||
@@ -150,0 +152,0 @@ addEle( node, 0 ); |
@@ -76,6 +76,8 @@ import * as math from '../../../../math'; | ||
dispY = ( pts[ i2 + 1] - pts[ i1 + 1] ); | ||
} else if( rs.isRound ){ | ||
dispX = rs.midVector[1]; | ||
dispY = -rs.midVector[0]; | ||
} else { | ||
var i2 = pts.length / 2 - 1; | ||
var i1 = i2 - 2; | ||
var i3 = i2 + 2; | ||
@@ -133,3 +135,3 @@ dispX = ( pts[ i2 ] - pts[ i1 ] ); | ||
// already ok | ||
} else { | ||
} else if( !rs.isRound ){ | ||
var i2 = pts.length / 2 - 1; | ||
@@ -136,0 +138,0 @@ var i3 = i2 + 2; |
@@ -5,2 +5,3 @@ import * as math from '../../../../math'; | ||
import Map from '../../../../map'; | ||
import {getRoundCorner} from "../../../../round"; | ||
@@ -121,6 +122,13 @@ let BRp = {}; | ||
const segmentDs = edge.pstyle( 'segment-distances' ); | ||
const segmentRs = edge.pstyle( 'segment-radii' ); | ||
const segmentTs = edge.pstyle( 'radius-type' ); | ||
const segmentsN = Math.min( segmentWs.pfValue.length, segmentDs.pfValue.length ); | ||
const lastRadius = segmentRs.pfValue[ segmentRs.pfValue.length - 1 ]; | ||
const lastRadiusType = segmentTs.pfValue[ segmentTs.pfValue.length - 1 ]; | ||
rs.edgeType = 'segments'; | ||
rs.segpts = []; | ||
rs.radii = []; | ||
rs.isArcRadius = []; | ||
@@ -145,2 +153,5 @@ for( let s = 0; s < segmentsN; s++ ){ | ||
); | ||
rs.radii.push( segmentRs.pfValue[ s ] !== undefined ? segmentRs.pfValue[ s ] : lastRadius ); | ||
rs.isArcRadius.push( (segmentTs.pfValue[ s ] !== undefined ? segmentTs.pfValue[ s ] : lastRadiusType) === 'arc-radius' ); | ||
} | ||
@@ -462,2 +473,9 @@ | ||
} | ||
if (rs.isRound) { | ||
const radius = edge.pstyle( 'taxi-radius' ).value; | ||
const isArcRadius = edge.pstyle( 'radius-type' ).value[0] === 'arc-radius'; | ||
rs.radii = new Array( rs.segpts.length / 2 ).fill( radius ); | ||
rs.isArcRadius = new Array( rs.segpts.length / 2 ).fill( isArcRadius ); | ||
} | ||
}; | ||
@@ -470,3 +488,3 @@ | ||
if( rs.edgeType === 'bezier' ){ | ||
const { srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape } = pairInfo; | ||
const { srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape, srcCornerRadius, tgtCornerRadius, srcRs, tgtRs } = pairInfo; | ||
@@ -517,3 +535,3 @@ let badStart = !is.number( rs.startX ) || !is.number( rs.startY ); | ||
cpProj.y, | ||
0 | ||
0, srcCornerRadius, srcRs | ||
); | ||
@@ -557,3 +575,3 @@ | ||
cpProj.y, | ||
0 | ||
0, tgtCornerRadius, tgtRs | ||
); | ||
@@ -627,2 +645,19 @@ | ||
if( rs.isRound ){ | ||
rs.roundCorners = []; | ||
for( let i = 2; i + 3 < rs.allpts.length; i += 2 ){ | ||
let radius = rs.radii[ (i / 2) - 1]; | ||
let isArcRadius = rs.isArcRadius[ (i / 2) - 1 ]; | ||
rs.roundCorners.push( | ||
getRoundCorner( | ||
{x: rs.allpts[i - 2], y: rs.allpts[i - 1]}, | ||
{x: rs.allpts[i], y: rs.allpts[i + 1], radius}, | ||
{x: rs.allpts[i + 2], y: rs.allpts[i + 3]}, | ||
radius, isArcRadius | ||
) | ||
); | ||
} | ||
} | ||
if( rs.segpts.length % 4 === 0 ){ | ||
@@ -636,5 +671,22 @@ let i2 = rs.segpts.length / 2; | ||
let i1 = rs.segpts.length / 2 - 1; | ||
if( !rs.isRound ){ | ||
rs.midX = rs.segpts[ i1 ]; | ||
rs.midY = rs.segpts[ i1 + 1 ]; | ||
} else { | ||
let point = {x: rs.segpts[i1], y: rs.segpts[i1 + 1]}; | ||
const corner = rs.roundCorners[i1 / 2]; | ||
rs.midX = rs.segpts[ i1 ]; | ||
rs.midY = rs.segpts[ i1 + 1]; | ||
let v = [ | ||
point.x - corner.cx, | ||
point.y - corner.cy | ||
]; | ||
const factor = corner.radius / Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2)); | ||
v = v.map(c => c * factor); | ||
rs.midX = corner.cx + v[0]; | ||
rs.midY = corner.cy + v[1]; | ||
rs.midVector = v; | ||
} | ||
} | ||
@@ -709,3 +761,3 @@ | ||
let edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments' || curveStyle === 'straight' || curveStyle === 'straight-triangle' || curveStyle === 'taxi'; | ||
let edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle.endsWith('segments') || curveStyle === 'straight' || curveStyle === 'straight-triangle' || curveStyle.endsWith('taxi'); | ||
let edgeIsBezier = curveStyle === 'unbundled-bezier' || curveStyle === 'bezier'; | ||
@@ -780,2 +832,8 @@ let src = _p.source; | ||
let srcCornerRadius = pairInfo.srcCornerRadius = src.pstyle('corner-radius').value === 'auto' ? 'auto' : src.pstyle('corner-radius').pfValue; | ||
let tgtCornerRadius = pairInfo.tgtCornerRadius = tgt.pstyle('corner-radius').value === 'auto' ? 'auto' : tgt.pstyle('corner-radius').pfValue; | ||
let tgtRs = pairInfo.tgtRs = tgt._private.rscratch; | ||
let srcRs = pairInfo.srcRs = src._private.rscratch; | ||
pairInfo.dirCounts = { | ||
@@ -796,3 +854,3 @@ 'north': 0, | ||
const curveStyle = edge.pstyle( 'curve-style' ).value; | ||
const edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments' || curveStyle === 'taxi'; | ||
const edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle.endsWith('segments') || curveStyle.endsWith('taxi'); | ||
@@ -810,3 +868,3 @@ // whether the normalised pair order is the reverse of the edge's src-tgt order | ||
tgtPos.x, tgtPos.y, | ||
0 | ||
0, srcCornerRadius, srcRs | ||
); | ||
@@ -821,3 +879,3 @@ | ||
srcPos.x, srcPos.y, | ||
0 | ||
0, tgtCornerRadius, tgtRs | ||
); | ||
@@ -863,4 +921,4 @@ | ||
!is.number(l) | ||
|| tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y ) | ||
|| srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y ) | ||
|| tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y, tgtCornerRadius, tgtRs ) | ||
|| srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y, srcCornerRadius, srcRs ) | ||
); | ||
@@ -907,2 +965,4 @@ | ||
rs.isRound = curveStyle.startsWith('round'); | ||
if( | ||
@@ -918,6 +978,6 @@ hasCompounds && | ||
} else if( curveStyle === 'segments' ){ | ||
} else if( curveStyle.endsWith( 'segments' )){ | ||
this.findSegmentsPoints(edge, passedPairInfo); | ||
} else if( curveStyle === 'taxi' ){ | ||
} else if( curveStyle.endsWith( 'taxi' )){ | ||
this.findTaxiPoints(edge, passedPairInfo); | ||
@@ -924,0 +984,0 @@ |
@@ -11,2 +11,3 @@ import * as math from '../../../../math'; | ||
let h = node.outerHeight(); | ||
let rs = node._private.rscratch; | ||
@@ -47,3 +48,3 @@ if( prop.value.length === 2 ){ | ||
p[0], p[1], | ||
0 | ||
0, node.pstyle('corner-radius').value === 'auto' ? 'auto' : node.pstyle('corner-radius').pfValue, rs | ||
); | ||
@@ -69,2 +70,5 @@ } | ||
let srcRs = source._private.rscratch; | ||
let tgtRs = target._private.rscratch; | ||
let curveStyle = edge.pstyle('curve-style').value; | ||
@@ -85,5 +89,8 @@ | ||
let srcManEndptVal = overrideEndpts ? 'outside-to-node' : srcManEndpt.value; | ||
let srcCornerRadius = source.pstyle('corner-radius').value === 'auto' ? 'auto' : source.pstyle('corner-radius').pfValue; | ||
let tgtManEndpt = edge.pstyle('target-endpoint'); | ||
let tgtManEndptVal = overrideEndpts ? 'outside-to-node' : tgtManEndpt.value; | ||
let tgtCornerRadius = target.pstyle('corner-radius').value === 'auto' ? 'auto' : target.pstyle('corner-radius').pfValue; | ||
rs.srcManEndpt = srcManEndpt; | ||
@@ -132,3 +139,3 @@ rs.tgtManEndpt = tgtManEndpt; | ||
p1_i[1], | ||
0 | ||
0, tgtCornerRadius, tgtRs | ||
); | ||
@@ -225,3 +232,3 @@ | ||
p2_i[1], | ||
0 | ||
0, srcCornerRadius, srcRs | ||
); | ||
@@ -228,0 +235,0 @@ |
import * as math from '../../../math'; | ||
import * as round from "../../../round"; | ||
@@ -13,7 +14,7 @@ var BRp = {}; | ||
draw: function( context, centerX, centerY, width, height ){ | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( 'polygon', context, centerX, centerY, width, height, this.points ); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
return math.polygonIntersectLine( | ||
@@ -29,3 +30,3 @@ x, y, | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY ){ | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY, cornerRadius ){ | ||
return math.pointInsidePolygon( x, y, this.points, | ||
@@ -44,7 +45,7 @@ centerX, centerY, width, height, [0, -1], padding ) | ||
draw: function( context, centerX, centerY, width, height ){ | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
return math.intersectLineEllipse( | ||
@@ -59,3 +60,3 @@ x, y, | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY ){ | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY, cornerRadius ){ | ||
return math.checkInEllipse( x, y, width, height, centerX, centerY, padding ); | ||
@@ -68,41 +69,50 @@ } | ||
// Pre-compute control points | ||
// Since these points depend on the radius length (which in turns depend on the width/height of the node) we will only pre-compute | ||
// the unit vectors. | ||
// For simplicity the layout will be: | ||
// [ p0, UnitVectorP0P1, p1, UniVectorP1P2, ..., pn, UnitVectorPnP0 ] | ||
const allPoints = new Array( points.length * 2 ); | ||
return ( this.nodeShapes[ name ] = { | ||
renderer: this, | ||
for ( let i = 0; i < points.length / 2; i++ ){ | ||
const sourceIndex = i * 2; | ||
let destIndex; | ||
if (i < points.length / 2 - 1) { | ||
destIndex = (i + 1) * 2; | ||
} else { | ||
destIndex = 0; | ||
} | ||
name: name, | ||
allPoints[ i * 4 ] = points[ sourceIndex ]; | ||
allPoints[ i * 4 + 1 ] = points[ sourceIndex + 1 ]; | ||
points: points, | ||
const xDest = points[ destIndex ] - points[ sourceIndex ]; | ||
const yDest = points[ destIndex + 1] - points[ sourceIndex + 1 ]; | ||
const norm = Math.sqrt(xDest * xDest + yDest * yDest); | ||
getOrCreateCorners: function (centerX, centerY, width, height, cornerRadius, rs, field) { | ||
if( rs[field] !== undefined && rs[field + '-cx'] === centerX && rs [field + '-cy'] === centerY ){ | ||
return rs[field]; | ||
} | ||
allPoints[ i * 4 + 2 ] = xDest / norm; | ||
allPoints[ i * 4 + 3 ] = yDest / norm; | ||
} | ||
rs[field] = new Array( points.length / 2 ); | ||
rs[field + '-cx'] = centerX; | ||
rs[field + '-cy'] = centerY; | ||
const halfW = width / 2; | ||
const halfH = height / 2; | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundPolygonRadius( width, height ) : cornerRadius; | ||
const p = new Array( points.length / 2 ); | ||
return ( this.nodeShapes[ name ] = { | ||
renderer: this, | ||
for ( let i = 0; i < points.length / 2; i++ ){ | ||
p[i] = { | ||
x: centerX + halfW * points[ i * 2 ], | ||
y: centerY + halfH * points[ i * 2 + 1 ] | ||
}; | ||
} | ||
name: name, | ||
let i, p1, p2, p3, len = p.length; | ||
points: allPoints, | ||
p1 = p[ len - 1 ]; | ||
// for each point | ||
for( i = 0; i < len; i++ ){ | ||
p2 = p[ (i) % len ]; | ||
p3 = p[ (i + 1) % len ]; | ||
rs[ field ][ i ] = round.getRoundCorner( p1, p2, p3, cornerRadius ); | ||
draw: function( context, centerX, centerY, width, height ){ | ||
this.renderer.nodeShapeImpl( 'round-polygon', context, centerX, centerY, width, height, this.points ); | ||
p1 = p2; | ||
p2 = p3; | ||
} | ||
return rs[ field ]; | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
draw: function( context, centerX, centerY, width, height, cornerRadius , rs){ | ||
this.renderer.nodeShapeImpl( 'round-polygon', context, centerX, centerY, width, height, this.points, this.getOrCreateCorners( centerX, centerY, width, height, cornerRadius, rs, 'drawCorners' )); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius, rs ){ | ||
return math.roundPolygonIntersectLine( | ||
@@ -114,9 +124,9 @@ x, y, | ||
width, height, | ||
padding ) | ||
padding, this.getOrCreateCorners( nodeX, nodeY, width, height, cornerRadius, rs, 'corners' ) ) | ||
; | ||
}, | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY ){ | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY, cornerRadius, rs ){ | ||
return math.pointInsideRoundPolygon( x, y, this.points, | ||
centerX, centerY, width, height) | ||
centerX, centerY, width, height, this.getOrCreateCorners( centerX, centerY, width, height, cornerRadius, rs, 'corners' ) ) | ||
; | ||
@@ -135,7 +145,7 @@ } | ||
draw: function( context, centerX, centerY, width, height ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height, this.points, cornerRadius ); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
return math.roundRectangleIntersectLine( | ||
@@ -146,3 +156,3 @@ x, y, | ||
width, height, | ||
padding ) | ||
padding, cornerRadius ) | ||
; | ||
@@ -152,5 +162,7 @@ }, | ||
checkPoint: function( | ||
x, y, padding, width, height, centerX, centerY ){ | ||
var cornerRadius = math.getRoundRectangleRadius( width, height ); | ||
x, y, padding, width, height, centerX, centerY, cornerRadius ){ | ||
let halfWidth = width / 2; | ||
let halfHeight = height / 2; | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundRectangleRadius( width, height ) : cornerRadius; | ||
cornerRadius = Math.min(halfWidth, halfHeight, cornerRadius); | ||
var diam = cornerRadius * 2; | ||
@@ -173,4 +185,4 @@ | ||
diam, diam, | ||
centerX - width / 2 + cornerRadius, | ||
centerY - height / 2 + cornerRadius, | ||
centerX - halfWidth + cornerRadius, | ||
centerY - halfHeight + cornerRadius, | ||
padding ) ){ | ||
@@ -184,4 +196,4 @@ | ||
diam, diam, | ||
centerX + width / 2 - cornerRadius, | ||
centerY - height / 2 + cornerRadius, | ||
centerX + halfWidth - cornerRadius, | ||
centerY - halfHeight + cornerRadius, | ||
padding ) ){ | ||
@@ -195,4 +207,4 @@ | ||
diam, diam, | ||
centerX + width / 2 - cornerRadius, | ||
centerY + height / 2 - cornerRadius, | ||
centerX + halfWidth - cornerRadius, | ||
centerY + halfHeight - cornerRadius, | ||
padding ) ){ | ||
@@ -206,4 +218,4 @@ | ||
diam, diam, | ||
centerX - width / 2 + cornerRadius, | ||
centerY + height / 2 - cornerRadius, | ||
centerX - halfWidth + cornerRadius, | ||
centerY + halfHeight - cornerRadius, | ||
padding ) ){ | ||
@@ -229,8 +241,8 @@ | ||
draw: function( context, centerX, centerY, width, height ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height, null, cornerRadius); | ||
}, | ||
generateCutTrianglePts: function( width, height, centerX, centerY ){ | ||
var cl = this.cornerLength; | ||
generateCutTrianglePts: function( width, height, centerX, centerY, cornerRadius ){ | ||
var cl = cornerRadius === 'auto' ? this.cornerLength : cornerRadius; | ||
var hh = height / 2; | ||
@@ -252,4 +264,4 @@ var hw = width / 2; | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
var cPts = this.generateCutTrianglePts( width + 2*padding, height+2*padding, nodeX, nodeY ); | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
var cPts = this.generateCutTrianglePts( width + 2*padding, height+2*padding, nodeX, nodeY, cornerRadius ); | ||
var pts = [].concat.apply([], | ||
@@ -263,6 +275,7 @@ [cPts.topLeft.splice(0, 4), cPts.topRight.splice(0, 4), | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY ){ | ||
checkPoint: function( x, y, padding, width, height, centerX, centerY, cornerRadius ){ | ||
const cl = cornerRadius === 'auto' ? this.cornerLength : cornerRadius; | ||
// Check hBox | ||
if( math.pointInsidePolygon( x, y, this.points, | ||
centerX, centerY, width, height - 2 * this.cornerLength, [0, -1], padding ) ){ | ||
centerX, centerY, width, height - 2 * cl, [0, -1], padding ) ){ | ||
return true; | ||
@@ -273,3 +286,3 @@ } | ||
if( math.pointInsidePolygon( x, y, this.points, | ||
centerX, centerY, width - 2 * this.cornerLength, height, [0, -1], padding ) ){ | ||
centerX, centerY, width - 2 * cl, height, [0, -1], padding ) ){ | ||
return true; | ||
@@ -295,7 +308,7 @@ } | ||
draw: function( context, centerX, centerY, width, height ){ | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
// use two fixed t values for the bezier curve approximation | ||
@@ -364,3 +377,3 @@ | ||
checkPoint: function( | ||
x, y, padding, width, height, centerX, centerY ){ | ||
x, y, padding, width, height, centerX, centerY, cornerRadius){ | ||
@@ -446,7 +459,7 @@ var curveConstants = math.getBarrelCurveConstants( width, height ); | ||
draw: function( context, centerX, centerY, width, height ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height ); | ||
draw: function( context, centerX, centerY, width, height, cornerRadius ){ | ||
this.renderer.nodeShapeImpl( this.name, context, centerX, centerY, width, height, this.points, cornerRadius ); | ||
}, | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){ | ||
intersectLine: function( nodeX, nodeY, width, height, x, y, padding, cornerRadius ){ | ||
var topStartX = nodeX - ( width / 2 + padding ); | ||
@@ -468,3 +481,3 @@ var topStartY = nodeY - ( height / 2 + padding ); | ||
width, height, | ||
padding ) | ||
padding, cornerRadius ) | ||
; | ||
@@ -474,5 +487,5 @@ }, | ||
checkPoint: function( | ||
x, y, padding, width, height, centerX, centerY ){ | ||
x, y, padding, width, height, centerX, centerY, cornerRadius ){ | ||
var cornerRadius = math.getRoundRectangleRadius( width, height ); | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundRectangleRadius( width, height ) : cornerRadius; | ||
var diam = 2 * cornerRadius; | ||
@@ -479,0 +492,0 @@ |
/* global Path2D */ | ||
import * as util from '../../../util'; | ||
import {drawPreparedRoundCorner} from "../../../round"; | ||
@@ -209,8 +210,19 @@ let CRp = {}; | ||
case 'straight': | ||
case 'segments': | ||
case 'haystack': | ||
for( let i = 2; i + 1 < pts.length; i += 2 ){ | ||
for( let i = 2; i + 1 < pts.length; i += 2 ) { | ||
context.lineTo( pts[ i ], pts[ i + 1] ); | ||
} | ||
break; | ||
case 'segments': | ||
if (rs.isRound) { | ||
for( let corner of rs.roundCorners ){ | ||
drawPreparedRoundCorner(context, corner); | ||
} | ||
context.lineTo( pts[ pts.length - 2 ], pts[ pts.length - 1] ); | ||
} else { | ||
for( let i = 2; i + 1 < pts.length; i += 2 ) { | ||
context.lineTo( pts[ i ], pts[ i + 1] ); | ||
} | ||
} | ||
break; | ||
} | ||
@@ -217,0 +229,0 @@ } |
@@ -37,2 +37,4 @@ import * as util from '../../../util'; | ||
var smooth = getIndexedStyle( node, 'background-image-smoothing', 'value', index ); | ||
var cornerRadius = node.pstyle('corner-radius').value; | ||
if (cornerRadius !== 'auto') cornerRadius = node.pstyle('corner-radius').pfValue; | ||
@@ -156,3 +158,4 @@ var imgW = img.width || img.cachedW; | ||
nodeX, nodeY, | ||
nodeTW, nodeTH ); | ||
nodeTW, nodeTH, | ||
cornerRadius, rs ); | ||
@@ -175,3 +178,3 @@ context.clip(); | ||
nodeX, nodeY, | ||
nodeTW, nodeTH ); | ||
nodeTW, nodeTH, cornerRadius, rs); | ||
@@ -178,0 +181,0 @@ context.translate( x, y ); |
/* global Path2D */ | ||
import * as is from '../../../is'; | ||
import { expandPolygon, joinLines } from '../../../math'; | ||
import {expandPolygon, joinLines} from '../../../math'; | ||
import * as util from '../../../util'; | ||
import * as round from "../../../round"; | ||
import * as math from "../../../math"; | ||
@@ -77,2 +79,7 @@ let CRp = {}; | ||
let borderStyle = node.pstyle('border-style').value; | ||
let borderJoin = node.pstyle('border-join').value; | ||
let borderCap = node.pstyle('border-cap').value; | ||
let borderPosition = node.pstyle('border-position').value; | ||
let borderPattern = node.pstyle('border-dash-pattern').pfValue; | ||
let borderOffset = node.pstyle('border-dash-offset').pfValue; | ||
let borderOpacity = node.pstyle('border-opacity').value * eleOpacity; | ||
@@ -84,5 +91,5 @@ let outlineWidth = node.pstyle('outline-width').pfValue; | ||
let outlineOffset = node.pstyle('outline-offset').value; | ||
let cornerRadius = node.pstyle('corner-radius').value; | ||
if (cornerRadius !== 'auto') cornerRadius = node.pstyle('corner-radius').pfValue; | ||
context.lineJoin = 'miter'; // so borders are square with the node shape | ||
let setupShapeColor = ( bgOpy = bgOpacity ) => { | ||
@@ -109,3 +116,4 @@ r.eleFillStyle( context, node, bgOpy ); | ||
'' + height, | ||
'' + width | ||
'' + width, | ||
'' + cornerRadius | ||
); | ||
@@ -127,3 +135,3 @@ | ||
return { | ||
path, | ||
path, | ||
cacheHit | ||
@@ -161,3 +169,3 @@ }; | ||
nodeWidth, | ||
nodeHeight ); | ||
nodeHeight, cornerRadius, rs ); | ||
} | ||
@@ -172,3 +180,3 @@ | ||
let drawImages = ( nodeOpacity = eleOpacity, inside = true ) => { | ||
let drawImages = ( nodeOpacity = eleOpacity, inside = true ) => { | ||
let prevBging = _p.backgrounding; | ||
@@ -209,3 +217,3 @@ let totalCompleted = 0; | ||
nodeWidth, | ||
nodeHeight ); | ||
nodeHeight, cornerRadius, rs ); | ||
} | ||
@@ -235,3 +243,4 @@ } | ||
context.lineWidth = borderWidth; | ||
context.lineCap = 'butt'; | ||
context.lineCap = borderCap; | ||
context.lineJoin = borderJoin; | ||
@@ -245,3 +254,4 @@ if( context.setLineDash ){ // for very outofdate browsers | ||
case 'dashed': | ||
context.setLineDash( [ 4, 2 ] ); | ||
context.setLineDash( borderPattern ); | ||
context.lineDashOffset = borderOffset; | ||
break; | ||
@@ -256,6 +266,22 @@ | ||
if( usePaths ){ | ||
context.stroke( path ); | ||
if ( borderPosition !== 'center') { | ||
context.save(); | ||
context.lineWidth *= 2; | ||
if (borderPosition === 'inside') { | ||
usePaths ? context.clip(path) : context.clip(); | ||
} else { | ||
const region = new Path2D(); | ||
region.rect( | ||
-nodeWidth / 2 - borderWidth, | ||
-nodeHeight / 2 - borderWidth, | ||
nodeWidth + 2 * borderWidth, | ||
nodeHeight + 2 * borderWidth | ||
); | ||
region.addPath(path); | ||
context.clip(region, 'evenodd'); | ||
} | ||
usePaths ? context.stroke(path) : context.stroke(); | ||
context.restore(); | ||
} else { | ||
context.stroke(); | ||
usePaths ? context.stroke(path) : context.stroke(); | ||
} | ||
@@ -317,8 +343,12 @@ | ||
let shape = r.getNodeShape( node ); | ||
let scaleX = (nodeWidth + borderWidth + (outlineWidth + outlineOffset)) / nodeWidth; | ||
let scaleY = (nodeHeight + borderWidth + (outlineWidth + outlineOffset)) / nodeHeight; | ||
let bWidth = borderWidth; | ||
if( borderPosition === 'inside' ) bWidth = 0; | ||
if( borderPosition === 'outside' ) bWidth *= 2; | ||
let scaleX = (nodeWidth + bWidth + (outlineWidth + outlineOffset)) / nodeWidth; | ||
let scaleY = (nodeHeight + bWidth + (outlineWidth + outlineOffset)) / nodeHeight; | ||
let sWidth = nodeWidth * scaleX; | ||
let sHeight = nodeHeight * scaleY; | ||
let points = r.nodeShapes[ shape ].points; | ||
@@ -337,3 +367,3 @@ let path; | ||
} else if ([ | ||
'round-diamond', 'round-heptagon', 'round-hexagon', 'round-octagon', | ||
'round-diamond', 'round-heptagon', 'round-hexagon', 'round-octagon', | ||
'round-pentagon', 'round-polygon', 'round-triangle', 'round-tag' | ||
@@ -344,18 +374,19 @@ ].includes(shape)) { | ||
let offsetY = 0; | ||
if (shape === 'round-diamond') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * 1.4; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * 1.4; | ||
} else if (shape === 'round-heptagon') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * 1.075; | ||
offsetY = -(borderWidth/2 + outlineOffset + outlineWidth) / 35; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * 1.075; | ||
offsetY = -(bWidth/2 + outlineOffset + outlineWidth) / 35; | ||
} else if (shape === 'round-hexagon') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * 1.12; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * 1.12; | ||
} else if (shape === 'round-pentagon') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * 1.13; | ||
offsetY = -(borderWidth/2 + outlineOffset + outlineWidth) / 15; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * 1.13; | ||
offsetY = -(bWidth/2 + outlineOffset + outlineWidth) / 15; | ||
} else if (shape === 'round-tag') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * 1.12; | ||
offsetX = (borderWidth/2 + outlineWidth + outlineOffset) * .07; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * 1.12; | ||
offsetX = (bWidth/2 + outlineWidth + outlineOffset) * .07; | ||
} else if (shape === 'round-triangle') { | ||
sMult = (borderWidth + outlineOffset + outlineWidth) * (Math.PI/2); | ||
offsetY = -(borderWidth + outlineOffset/2 + outlineWidth) / Math.PI; | ||
sMult = (bWidth + outlineOffset + outlineWidth) * (Math.PI/2); | ||
offsetY = -(bWidth + outlineOffset/2 + outlineWidth) / Math.PI; | ||
} | ||
@@ -365,24 +396,58 @@ | ||
scaleX = (nodeWidth + sMult)/nodeWidth; | ||
scaleY = (nodeHeight + sMult)/nodeHeight; | ||
sWidth = nodeWidth * scaleX; | ||
if ( ! ['round-hexagon', 'round-tag'].includes(shape) ) { | ||
scaleY = (nodeHeight + sMult)/nodeHeight; | ||
sHeight = nodeHeight * scaleY; | ||
} | ||
} | ||
r.drawRoundPolygonPath(path || context, npos.x + offsetX, npos.y + offsetY, nodeWidth * scaleX, nodeHeight * scaleY, points); | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundPolygonRadius( sWidth, sHeight ) : cornerRadius; | ||
const halfW = sWidth / 2; | ||
const halfH = sHeight / 2; | ||
const radius = cornerRadius + ( bWidth + outlineWidth + outlineOffset ) / 2; | ||
const p = new Array( points.length / 2 ); | ||
const corners = new Array( points.length / 2 ); | ||
for ( let i = 0; i < points.length / 2; i++ ){ | ||
p[i] = { | ||
x: npos.x + offsetX + halfW * points[ i * 2 ], | ||
y: npos.y + offsetY + halfH * points[ i * 2 + 1 ] | ||
}; | ||
} | ||
let i, p1, p2, p3, len = p.length; | ||
p1 = p[ len - 1 ]; | ||
// for each point | ||
for( i = 0; i < len; i++ ){ | ||
p2 = p[ (i) % len ]; | ||
p3 = p[ (i + 1) % len ]; | ||
corners[ i ] = round.getRoundCorner( p1, p2, p3, radius ); | ||
p1 = p2; | ||
p2 = p3; | ||
} | ||
r.drawRoundPolygonPath(path || context, npos.x + offsetX, npos.y + offsetY, nodeWidth * scaleX, nodeHeight * scaleY, points, corners ); | ||
} else if (['roundrectangle', 'round-rectangle'].includes(shape)) { | ||
r.drawRoundRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight); | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundRectangleRadius( sWidth, sHeight ) : cornerRadius; | ||
r.drawRoundRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight, cornerRadius + ( bWidth + outlineWidth + outlineOffset ) / 2 ); | ||
} else if (['cutrectangle', 'cut-rectangle'].includes(shape)) { | ||
r.drawCutRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight); | ||
cornerRadius = cornerRadius === 'auto' ? math.getCutRectangleCornerLength( sWidth, sHeight ) : cornerRadius; | ||
r.drawCutRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight, null ,cornerRadius + ( bWidth + outlineWidth + outlineOffset ) / 4 ); | ||
} else if (['bottomroundrectangle', 'bottom-round-rectangle'].includes(shape)) { | ||
r.drawBottomRoundRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight); | ||
cornerRadius = cornerRadius === 'auto' ? math.getRoundRectangleRadius( sWidth, sHeight ) : cornerRadius; | ||
r.drawBottomRoundRectanglePath(path || context, npos.x, npos.y, sWidth, sHeight, cornerRadius + ( bWidth + outlineWidth + outlineOffset ) / 2 ); | ||
} else if (shape === "barrel") { | ||
r.drawBarrelPath(path || context, npos.x, npos.y, sWidth, sHeight); | ||
} else if (shape.startsWith("polygon") || ['rhomboid', 'right-rhomboid', 'round-tag', 'tag', 'vee'].includes(shape)) { | ||
let pad = (borderWidth + outlineWidth + outlineOffset) / nodeWidth; | ||
let pad = (bWidth + outlineWidth + outlineOffset) / nodeWidth; | ||
points = joinLines(expandPolygon(points, pad)); | ||
r.drawPolygonPath(path || context, npos.x, npos.y, nodeWidth, nodeHeight, points); | ||
} else { | ||
let pad = (borderWidth + outlineWidth + outlineOffset) / nodeWidth; | ||
let pad = (bWidth + outlineWidth + outlineOffset) / nodeWidth; | ||
points = joinLines(expandPolygon(points, -pad)); | ||
r.drawPolygonPath(path || context, npos.x, npos.y, nodeWidth, nodeHeight, points); | ||
} | ||
if( usePaths ){ | ||
@@ -395,3 +460,3 @@ context.stroke( path ); | ||
if( outlineStyle === 'double' ){ | ||
context.lineWidth = borderWidth / 3; | ||
context.lineWidth = bWidth / 3; | ||
@@ -474,3 +539,3 @@ let gco = context.globalCompositeOperation; | ||
drawImages(eleOpacity, false); | ||
darken(); | ||
@@ -508,3 +573,4 @@ | ||
let color = node.pstyle( `${overlayOrUnderlay}-color` ).value; | ||
var shape = node.pstyle( `${overlayOrUnderlay}-shape` ).value; | ||
let shape = node.pstyle( `${overlayOrUnderlay}-shape` ).value; | ||
let radius = node.pstyle( `${overlayOrUnderlay}-corner-radius` ).value; | ||
@@ -528,3 +594,4 @@ if( opacity > 0 ){ | ||
nodeWidth + padding * 2, | ||
nodeHeight + padding * 2 | ||
nodeHeight + padding * 2, | ||
radius | ||
); | ||
@@ -531,0 +598,0 @@ |
import * as math from '../../../math'; | ||
import * as round from '../../../round'; | ||
@@ -24,40 +25,4 @@ var CRp = {}; | ||
CRp.drawRoundPolygonPath = function( | ||
context, x, y, width, height, points ){ | ||
const halfW = width / 2; | ||
const halfH = height / 2; | ||
const cornerRadius = math.getRoundPolygonRadius( width, height ); | ||
if( context.beginPath ){ context.beginPath(); } | ||
for ( let i = 0; i < points.length / 4; i++ ){ | ||
let sourceUv, destUv; | ||
if ( i === 0 ) { | ||
sourceUv = points.length - 2; | ||
} else { | ||
sourceUv = i * 4 - 2; | ||
} | ||
destUv = i * 4 + 2; | ||
const px = x + halfW * points[ i * 4 ]; | ||
const py = y + halfH * points[ i * 4 + 1 ]; | ||
const cosTheta = (-points[ sourceUv ] * points[ destUv ] - points[ sourceUv + 1 ] * points[ destUv + 1]); | ||
const offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2); | ||
const cp0x = px - offset * points[ sourceUv ]; | ||
const cp0y = py - offset * points[ sourceUv + 1 ]; | ||
const cp1x = px + offset * points[ destUv ]; | ||
const cp1y = py + offset * points[ destUv + 1 ]; | ||
if (i === 0) { | ||
context.moveTo( cp0x, cp0y ); | ||
} else { | ||
context.lineTo( cp0x, cp0y ); | ||
} | ||
context.arcTo( px, py, cp1x, cp1y, cornerRadius ); | ||
} | ||
context, x, y, width, height, points, corners ){ | ||
corners.forEach( corner => round.drawPreparedRoundCorner( context, corner ) ); | ||
context.closePath(); | ||
@@ -68,7 +33,7 @@ }; | ||
CRp.drawRoundRectanglePath = function( | ||
context, x, y, width, height ){ | ||
context, x, y, width, height, radius){ | ||
var halfWidth = width / 2; | ||
var halfHeight = height / 2; | ||
var cornerRadius = math.getRoundRectangleRadius( width, height ); | ||
var cornerRadius = radius === 'auto' ? math.getRoundRectangleRadius( width, height ) : Math.min(radius, halfHeight, halfWidth); | ||
@@ -95,7 +60,7 @@ if( context.beginPath ){ context.beginPath(); } | ||
CRp.drawBottomRoundRectanglePath = function( | ||
context, x, y, width, height ){ | ||
context, x, y, width, height, radius){ | ||
var halfWidth = width / 2; | ||
var halfHeight = height / 2; | ||
var cornerRadius = math.getRoundRectangleRadius( width, height ); | ||
var cornerRadius = radius === 'auto' ? math.getRoundRectangleRadius( width, height ) : radius; | ||
@@ -119,7 +84,7 @@ if( context.beginPath ){ context.beginPath(); } | ||
CRp.drawCutRectanglePath = function( | ||
context, x, y, width, height ){ | ||
context, x, y, width, height, points, corners ){ | ||
var halfWidth = width / 2; | ||
var halfHeight = height / 2; | ||
var cornerLength = math.getCutRectangleCornerLength(); | ||
var cornerLength = corners === 'auto' ? math.getCutRectangleCornerLength() : corners; | ||
@@ -126,0 +91,0 @@ if( context.beginPath ){ context.beginPath(); } |
var CRp = {}; | ||
CRp.nodeShapeImpl = function( name, context, centerX, centerY, width, height, points ){ | ||
CRp.nodeShapeImpl = function( name, context, centerX, centerY, width, height, points, corners ){ | ||
switch( name ){ | ||
@@ -10,12 +10,12 @@ case 'ellipse': | ||
case 'round-polygon': | ||
return this.drawRoundPolygonPath(context, centerX, centerY, width, height, points ); | ||
return this.drawRoundPolygonPath(context, centerX, centerY, width, height, points, corners ); | ||
case 'roundrectangle': | ||
case 'round-rectangle': | ||
return this.drawRoundRectanglePath( context, centerX, centerY, width, height ); | ||
return this.drawRoundRectanglePath( context, centerX, centerY, width, height, corners ); | ||
case 'cutrectangle': | ||
case 'cut-rectangle': | ||
return this.drawCutRectanglePath( context, centerX, centerY, width, height ); | ||
return this.drawCutRectanglePath( context, centerX, centerY, width, height, points, corners ); | ||
case 'bottomroundrectangle': | ||
case 'bottom-round-rectangle': | ||
return this.drawBottomRoundRectanglePath( context, centerX, centerY, width, height ); | ||
return this.drawBottomRoundRectanglePath( context, centerX, centerY, width, height, corners ); | ||
case 'barrel': | ||
@@ -22,0 +22,0 @@ return this.drawBarrelPath( context, centerX, centerY, width, height ); |
125
src/math.js
@@ -374,8 +374,10 @@ export const arePositionsSame = ( p1, p2 ) => | ||
export const roundRectangleIntersectLine = ( x, y, nodeX, nodeY, width, height, padding ) => { | ||
export const roundRectangleIntersectLine = ( x, y, nodeX, nodeY, width, height, padding, radius = 'auto' ) => { | ||
let cornerRadius = getRoundRectangleRadius( width, height ); | ||
let cornerRadius = radius === 'auto' ? getRoundRectangleRadius( width, height ) : radius; | ||
let halfWidth = width / 2; | ||
let halfHeight = height / 2; | ||
cornerRadius = Math.min(cornerRadius, halfWidth, halfHeight); | ||
const doWidth = cornerRadius !== halfWidth, doHeight = cornerRadius !== halfHeight; | ||
@@ -386,3 +388,3 @@ // Check intersections with straight line segments | ||
// Top segment, left to right | ||
{ | ||
if( doWidth ){ | ||
let topStartX = nodeX - halfWidth + cornerRadius - padding; | ||
@@ -402,3 +404,3 @@ let topStartY = nodeY - halfHeight - padding; | ||
// Right segment, top to bottom | ||
{ | ||
if( doHeight ){ | ||
let rightStartX = nodeX + halfWidth + padding; | ||
@@ -418,3 +420,3 @@ let rightStartY = nodeY - halfHeight + cornerRadius - padding; | ||
// Bottom segment, left to right | ||
{ | ||
if( doWidth ){ | ||
let bottomStartX = nodeX - halfWidth + cornerRadius - padding; | ||
@@ -434,3 +436,3 @@ let bottomStartY = nodeY + halfHeight + padding; | ||
// Left segment, top to bottom | ||
{ | ||
if( doHeight ){ | ||
let leftStartX = nodeX - halfWidth - padding; | ||
@@ -816,45 +818,14 @@ let leftStartY = nodeY - halfHeight + cornerRadius - padding; | ||
export const pointInsideRoundPolygon = ( x, y, basePoints, centerX, centerY, width, height ) => { | ||
const cutPolygonPoints = new Array( basePoints.length); | ||
const halfW = width / 2; | ||
const halfH = height / 2; | ||
const cornerRadius = getRoundPolygonRadius(width, height); | ||
const squaredCornerRadius = cornerRadius * cornerRadius; | ||
export const pointInsideRoundPolygon = (x, y, basePoints, centerX, centerY, width, height, corners) => { | ||
const cutPolygonPoints = new Array( basePoints.length * 2 ); | ||
for ( let i = 0; i < basePoints.length / 4; i++ ){ | ||
let sourceUv, destUv; | ||
if ( i === 0 ) { | ||
sourceUv = basePoints.length - 2; | ||
} else { | ||
sourceUv = i * 4 - 2; | ||
} | ||
destUv = i * 4 + 2; | ||
for( let i = 0; i < corners.length; i++ ){ | ||
let corner = corners[i]; | ||
cutPolygonPoints[i * 4 + 0] = corner.startX; | ||
cutPolygonPoints[i * 4 + 1] = corner.startY; | ||
cutPolygonPoints[i * 4 + 2] = corner.stopX; | ||
cutPolygonPoints[i * 4 + 3] = corner.stopY; | ||
const px = centerX + halfW * basePoints[ i * 4 ]; | ||
const py = centerY + halfH * basePoints[ i * 4 + 1 ]; | ||
const cosTheta = (-basePoints[ sourceUv ] * basePoints[ destUv ] - basePoints[ sourceUv + 1 ] * basePoints[ destUv + 1]); | ||
const offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2); | ||
const cp0x = px - offset * basePoints[ sourceUv ]; | ||
const cp0y = py - offset * basePoints[ sourceUv + 1 ]; | ||
const cp1x = px + offset * basePoints[ destUv ]; | ||
const cp1y = py + offset * basePoints[ destUv + 1 ]; | ||
cutPolygonPoints[ i * 4] = cp0x; | ||
cutPolygonPoints[ i * 4 + 1] = cp0y; | ||
cutPolygonPoints[ i * 4 + 2] = cp1x; | ||
cutPolygonPoints[ i * 4 + 3] = cp1y; | ||
let orthx = basePoints[ sourceUv + 1 ]; | ||
let orthy = -basePoints[ sourceUv ]; | ||
const cosAlpha = orthx * basePoints[ destUv ] + orthy * basePoints [ destUv + 1 ]; | ||
if (cosAlpha < 0) { | ||
orthx *= -1; | ||
orthy *= -1; | ||
} | ||
const cx = cp0x + orthx * cornerRadius; | ||
const cy = cp0y + orthy * cornerRadius; | ||
const squaredDistance = Math.pow(cx - x, 2) + Math.pow(cy - y, 2); | ||
if (squaredDistance <= squaredCornerRadius) { | ||
const squaredDistance = Math.pow(corner.cx - x, 2 ) + Math.pow(corner.cy - y, 2 ); | ||
if( squaredDistance <= Math.pow( corner.radius, 2 ) ){ | ||
return true; | ||
@@ -1206,59 +1177,25 @@ } | ||
export const roundPolygonIntersectLine = ( x, y, basePoints, centerX, centerY, width, height, padding ) => { | ||
export const roundPolygonIntersectLine = ( x, y, basePoints, centerX, centerY, width, height, padding, corners ) => { | ||
let intersections = []; | ||
let intersection; | ||
let lines = new Array(basePoints.length); | ||
const halfW = width / 2; | ||
const halfH = height / 2; | ||
const cornerRadius = getRoundPolygonRadius(width, height); | ||
let lines = new Array(basePoints.length * 2); | ||
for ( let i = 0; i < basePoints.length / 4; i++ ){ | ||
let sourceUv, destUv; | ||
if ( i === 0 ) { | ||
sourceUv = basePoints.length - 2; | ||
} else { | ||
sourceUv = i * 4 - 2; | ||
} | ||
destUv = i * 4 + 2; | ||
const px = centerX + halfW * basePoints[ i * 4 ]; | ||
const py = centerY + halfH * basePoints[ i * 4 + 1 ]; | ||
const cosTheta = (-basePoints[ sourceUv ] * basePoints[ destUv ] - basePoints[ sourceUv + 1 ] * basePoints[ destUv + 1]); | ||
const offset = cornerRadius / Math.tan(Math.acos(cosTheta) / 2); | ||
const cp0x = px - offset * basePoints[ sourceUv ]; | ||
const cp0y = py - offset * basePoints[ sourceUv + 1 ]; | ||
const cp1x = px + offset * basePoints[ destUv ]; | ||
const cp1y = py + offset * basePoints[ destUv + 1 ]; | ||
corners.forEach( (corner, i) => { | ||
if (i === 0) { | ||
lines[basePoints.length - 2] = cp0x; | ||
lines[basePoints.length - 1] = cp0y; | ||
lines[lines.length - 2] = corner.startX; | ||
lines[lines.length - 1] = corner.startY; | ||
} else { | ||
lines[i * 4 - 2] = cp0x; | ||
lines[i * 4 - 1] = cp0y; | ||
lines[i * 4 - 2] = corner.startX; | ||
lines[i * 4 - 1] = corner.startY; | ||
} | ||
lines[i * 4] = cp1x; | ||
lines[i * 4 + 1] = cp1y; | ||
lines[i * 4] = corner.stopX; | ||
lines[i * 4 + 1] = corner.stopY; | ||
let orthx = basePoints[ sourceUv + 1 ]; | ||
let orthy = -basePoints[ sourceUv ]; | ||
const cosAlpha = orthx * basePoints[ destUv ] + orthy * basePoints [ destUv + 1 ]; | ||
if (cosAlpha < 0) { | ||
orthx *= -1; | ||
orthy *= -1; | ||
} | ||
intersection = intersectLineCircle(x, y, centerX, centerY, corner.cx, corner.cy, corner.radius); | ||
const cx = cp0x + orthx * cornerRadius; | ||
const cy = cp0y + orthy * cornerRadius; | ||
intersection = intersectLineCircle(x, y, centerX, centerY, cx, cy, cornerRadius); | ||
if( intersection.length !== 0 ){ | ||
intersections.push( intersection[0], intersection[1] ); | ||
if (intersection.length !== 0) { | ||
intersections.push(intersection[0], intersection[1]); | ||
} | ||
} | ||
}); | ||
@@ -1265,0 +1202,0 @@ for( let i = 0; i < lines.length / 4; i++ ) { |
@@ -60,4 +60,7 @@ import * as util from '../util'; | ||
lineCap: { enums: [ 'butt', 'round', 'square' ] }, | ||
linePosition: { enums: [ 'center', 'inside', 'outside' ] }, | ||
lineJoin: { enums: [ 'round', 'bevel', 'miter' ] }, | ||
borderStyle: { enums: [ 'solid', 'dotted', 'dashed', 'double' ] }, | ||
curveStyle: { enums: [ 'bezier', 'unbundled-bezier', 'haystack', 'segments', 'straight', 'straight-triangle', 'taxi' ] }, | ||
curveStyle: { enums: [ 'bezier', 'unbundled-bezier', 'haystack', 'segments', 'straight', 'straight-triangle', 'taxi', 'round-segments', 'round-taxi' ] }, | ||
radiusType: { enums: [ 'arc-radius', 'influence-radius' ] , multiple: true }, | ||
fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' }, | ||
@@ -77,2 +80,3 @@ fontStyle: { enums: [ 'italic', 'normal', 'oblique' ] }, | ||
overlayShape: { enums: [ 'roundrectangle', 'round-rectangle', 'ellipse' ] }, | ||
cornerRadius: { number: true, min: 0, units: 'px|em', implicitUnits: 'px', enums: ['auto'] }, | ||
compoundIncludeLabels: { enums: [ 'include', 'exclude' ] }, | ||
@@ -255,3 +259,4 @@ arrowShape: { enums: [ 'tee', 'triangle', 'triangle-tee', 'circle-triangle', 'triangle-cross', 'triangle-backcurve', 'vee', 'square', 'circle', 'diamond', 'chevron', 'none' ] }, | ||
{ name: 'overlay-opacity', type: t.zeroOneNumber, triggersBounds: diff.zeroNonZero }, | ||
{ name: 'overlay-shape', type: t.overlayShape, triggersBounds: diff.any } | ||
{ name: 'overlay-shape', type: t.overlayShape, triggersBounds: diff.any }, | ||
{ name: 'overlay-corner-radius', type: t.cornerRadius } | ||
]; | ||
@@ -263,3 +268,4 @@ | ||
{ name: 'underlay-opacity', type: t.zeroOneNumber, triggersBounds: diff.zeroNonZero }, | ||
{ name: 'underlay-shape', type: t.overlayShape, triggersBounds: diff.any } | ||
{ name: 'underlay-shape', type: t.overlayShape, triggersBounds: diff.any }, | ||
{ name: 'underlay-corner-radius', type: t.cornerRadius } | ||
]; | ||
@@ -287,2 +293,3 @@ | ||
{ name: 'shape-polygon-points', type: t.polygonPointList, triggersBounds: diff.any }, | ||
{ name: 'corner-radius', type: t.cornerRadius}, | ||
{ name: 'background-color', type: t.color }, | ||
@@ -304,3 +311,8 @@ { name: 'background-fill', type: t.fill }, | ||
{ name: 'border-width', type: t.size, triggersBounds: diff.any }, | ||
{ name: 'border-style', type: t.borderStyle } | ||
{ name: 'border-style', type: t.borderStyle }, | ||
{ name: 'border-cap', type: t.lineCap }, | ||
{ name: 'border-join', type: t.lineJoin }, | ||
{ name: 'border-dash-pattern', type: t.numbers }, | ||
{ name: 'border-dash-offset', type: t.number }, | ||
{ name: 'border-position', type: t.linePosition }, | ||
]; | ||
@@ -365,5 +377,8 @@ | ||
{ name: 'segment-weights', type: t.numbers, triggersBounds: diff.any }, | ||
{ name: 'segment-radii', type: t.numbers, triggersBounds: diff.any }, | ||
{ name: 'radius-type', type: t.radiusType, triggersBounds: diff.any }, | ||
{ name: 'taxi-turn', type: t.bidirectionalSizeMaybePercent, triggersBounds: diff.any }, | ||
{ name: 'taxi-turn-min-distance', type: t.size, triggersBounds: diff.any }, | ||
{ name: 'taxi-direction', type: t.axisDirection, triggersBounds: diff.any }, | ||
{ name: 'taxi-radius', type: t.number, triggersBounds: diff.any }, | ||
{ name: 'edge-distances', type: t.edgeDistances, triggersBounds: diff.any }, | ||
@@ -500,2 +515,5 @@ { name: 'arrow-scale', type: t.positiveNumber, triggersBounds: diff.any }, | ||
{ name: 'control-point-weight', pointsTo: 'control-point-weights' }, | ||
{ name: 'segment-distance', pointsTo: 'segment-distances' }, | ||
{ name: 'segment-weight', pointsTo: 'segment-weights' }, | ||
{ name: 'segment-radius', pointsTo: 'segment-radii' }, | ||
{ name: 'edge-text-rotation', pointsTo: 'text-rotation' }, | ||
@@ -612,2 +630,3 @@ { name: 'padding-left', pointsTo: 'padding' }, | ||
'overlay-shape': 'round-rectangle', | ||
'overlay-corner-radius': 'auto', | ||
'underlay-opacity': 0, | ||
@@ -617,2 +636,3 @@ 'underlay-color': '#000', | ||
'underlay-shape': 'round-rectangle', | ||
'underlay-corner-radius': 'auto', | ||
'transition-property': 'none', | ||
@@ -648,2 +668,7 @@ 'transition-duration': 0, | ||
'border-style': 'solid', | ||
'border-dash-pattern': [ 4, 2 ], | ||
'border-dash-offset': 0, | ||
'border-cap': 'butt', | ||
'border-join': 'miter', | ||
'border-position': 'center', | ||
'outline-color': '#999', | ||
@@ -658,2 +683,3 @@ 'outline-opacity': 1, | ||
'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1', | ||
'corner-radius': 'auto', | ||
'bounds-expansion': 0, | ||
@@ -712,3 +738,6 @@ | ||
'segment-distances': 20, | ||
'segment-radii': 15, | ||
'radius-type': 'arc-radius', | ||
'taxi-turn': '50%', | ||
'taxi-radius': 15, | ||
'taxi-turn-min-distance': 10, | ||
@@ -715,0 +744,0 @@ 'taxi-direction': 'auto', |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4620356
0
188
118018
29
- Removedheap@^0.2.6
- Removedlodash@^4.17.21
- Removedheap@0.2.7(transitive)
- Removedlodash@4.17.21(transitive)