11'use strict' ;
22
33var Lib = require ( '../../lib' ) ;
4+ var Axes = require ( '../../plots/cartesian/axes' ) ;
5+ var isNumeric = require ( 'fast-isnumeric' ) ;
6+ var BADNUM = require ( '../../constants/numerical' ) . BADNUM ;
7+ var scatterCalc = require ( '../scatter/calc' ) ;
48
59/**
610 * Main calculation function for scatterquiver trace
711 * Creates calcdata with arrow path data for each vector
812 */
913module . exports = function calc ( gd , trace ) {
10- var x = trace . x ;
11- var y = trace . y ;
12- var u = trace . u ;
13- var v = trace . v ;
14- var scale = trace . scale ;
15- var arrowScale = trace . arrow_scale ;
16- var angle = trace . angle ;
17- var scaleRatio = trace . scaleratio ;
18-
19- // Create calcdata - one complete arrow per entry
20- var calcdata = [ ] ;
21- var len = x . length ;
22-
14+ // Map x/y through axes so category/date values become numeric calcdata
15+ var xa = trace . _xA = Axes . getFromId ( gd , trace . xaxis || 'x' , 'x' ) ;
16+ var ya = trace . _yA = Axes . getFromId ( gd , trace . yaxis || 'y' , 'y' ) ;
17+
18+ var xVals = xa . makeCalcdata ( trace , 'x' ) ;
19+ var yVals = ya . makeCalcdata ( trace , 'y' ) ;
20+
21+ // u/v are read in plot using the original trace arrays via cdi.i
22+
23+ var len = Math . min ( xVals . length , yVals . length ) ;
24+ trace . _length = len ;
25+ var cd = new Array ( len ) ;
26+
2327 for ( var i = 0 ; i < len ; i ++ ) {
24- // Calculate arrow components
25- var dx = u [ i ] * scale * ( scaleRatio || 1 ) ;
26- var dy = v [ i ] * scale ;
27- var barbLen = Math . sqrt ( dx * dx / ( scaleRatio || 1 ) + dy * dy ) ;
28- var arrowLen = barbLen * arrowScale ;
29- var barbAng = Math . atan2 ( dy , dx / ( scaleRatio || 1 ) ) ;
30-
31- var ang1 = barbAng + angle ;
32- var ang2 = barbAng - angle ;
33-
34- var endX = x [ i ] + dx ;
35- var endY = y [ i ] + dy ;
36-
37- var point1X = endX - arrowLen * Math . cos ( ang1 ) * ( scaleRatio || 1 ) ;
38- var point1Y = endY - arrowLen * Math . sin ( ang1 ) ;
39- var point2X = endX - arrowLen * Math . cos ( ang2 ) * ( scaleRatio || 1 ) ;
40- var point2Y = endY - arrowLen * Math . sin ( ang2 ) ;
41-
42- // Create complete arrow as one path: shaft + arrow head
43- var arrowPath = [
44- { x : x [ i ] , y : y [ i ] , i : i } , // Start point
45- { x : endX , y : endY , i : i } , // End of shaft
46- { x : point1X , y : point1Y , i : i } , // Arrow head point 1
47- { x : endX , y : endY , i : i } , // Back to end
48- { x : point2X , y : point2Y , i : i } // Arrow head point 2
49- ] ;
50-
51- calcdata . push ( arrowPath ) ;
28+ var cdi = cd [ i ] = { i : i } ;
29+ var xValid = isNumeric ( xVals [ i ] ) ;
30+ var yValid = isNumeric ( yVals [ i ] ) ;
31+
32+ if ( xValid && yValid ) {
33+ cdi . x = xVals [ i ] ;
34+ cdi . y = yVals [ i ] ;
35+ } else {
36+ cdi . x = BADNUM ;
37+ cdi . y = BADNUM ;
38+ }
39+
40+ // No additional props; keep minimal to avoid collisions with generic fields (e.g. `v`)
5241 }
5342
54- return calcdata ;
43+ // Ensure axes are expanded and categories registered like scatter traces do
44+ scatterCalc . calcAxisExpansion ( gd , trace , xa , ya , xVals , yVals ) ;
45+
46+ return cd ;
5547} ;
0 commit comments