@@ -39,18 +39,19 @@ var handleOutline = require('./handle_outline');
39
39
var clearOutlineControllers = handleOutline . clearOutlineControllers ;
40
40
var clearSelect = handleOutline . clearSelect ;
41
41
42
- function recordPositions ( polygonsOut , polygonsIn ) {
42
+ function recordPositions ( polygonsOut , polygonsIn ) { // copy & clean (i.e. skip duplicates)
43
43
for ( var i = 0 ; i < polygonsIn . length ; i ++ ) {
44
44
polygonsOut [ i ] = [ ] ;
45
45
var len = polygonsIn [ i ] . length ;
46
- for ( var j = 0 ; j < len ; j ++ ) {
46
+ for ( var newJ = 0 , j = 0 ; j < len ; j ++ ) {
47
47
// skip close points
48
- if ( dist ( polygonsIn [ i ] [ j ] , polygonsIn [ i ] [ ( j + 1 ) % len ] ) < 1 ) continue ;
48
+ if ( j > 0 && dist ( polygonsIn [ i ] [ j ] , polygonsIn [ i ] [ ( j + 1 ) % len ] ) < 1 ) continue ;
49
49
50
- polygonsOut [ i ] . push ( [
51
- polygonsIn [ i ] [ j ] [ 0 ] ,
52
- polygonsIn [ i ] [ j ] [ 1 ]
53
- ] ) ;
50
+ polygonsOut [ i ] [ newJ ] = [ ] ;
51
+ for ( var k = 0 ; k < polygonsIn [ i ] [ newJ ] . length ; k ++ ) {
52
+ polygonsOut [ i ] [ newJ ] [ k ] = polygonsIn [ i ] [ j ] [ k ] ;
53
+ }
54
+ newJ ++ ;
54
55
}
55
56
}
56
57
return polygonsOut ;
@@ -90,16 +91,8 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
90
91
91
92
if ( isDrawMode ) gd . _fullLayout . _drawing = true ;
92
93
93
- var paths = [ ] ;
94
- for ( var k = 0 ; k < polygons . length ; k ++ ) {
95
- // create outline path
96
- paths . push (
97
- providePath ( polygons [ k ] , isOpenMode )
98
- ) ;
99
- }
100
-
101
94
// make outline
102
- outlines . attr ( 'd' , writePaths ( paths , isOpenMode ) ) ;
95
+ outlines . attr ( 'd' , writePaths ( polygons , isOpenMode ) ) ;
103
96
104
97
// add controllers
105
98
var rVertexController = MINSELECT * 1.5 ; // bigger vertex buttons
@@ -127,8 +120,8 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
127
120
function moveVertexController ( dx , dy ) {
128
121
if ( ! polygons . length ) return ;
129
122
130
- var x0 = copyPolygons [ indexI ] [ indexJ ] [ 0 ] ;
131
- var y0 = copyPolygons [ indexI ] [ indexJ ] [ 1 ] ;
123
+ var x0 = copyPolygons [ indexI ] [ indexJ ] [ 1 ] ;
124
+ var y0 = copyPolygons [ indexI ] [ indexJ ] [ 2 ] ;
132
125
133
126
var cell = polygons [ indexI ] ;
134
127
var len = cell . length ;
@@ -139,29 +132,29 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
139
132
// move other corners of rectangle
140
133
var pos = cell [ q ] ;
141
134
142
- if ( pos [ 0 ] === cell [ indexJ ] [ 0 ] ) {
143
- pos [ 0 ] = x0 + dx ;
135
+ if ( pos [ 1 ] === cell [ indexJ ] [ 1 ] ) {
136
+ pos [ 1 ] = x0 + dx ;
144
137
}
145
138
146
- if ( pos [ 1 ] === cell [ indexJ ] [ 1 ] ) {
147
- pos [ 1 ] = y0 + dy ;
139
+ if ( pos [ 2 ] === cell [ indexJ ] [ 2 ] ) {
140
+ pos [ 2 ] = y0 + dy ;
148
141
}
149
142
}
150
143
// move the corner
151
- cell [ indexJ ] [ 0 ] = x0 + dx ;
152
- cell [ indexJ ] [ 1 ] = y0 + dy ;
144
+ cell [ indexJ ] [ 1 ] = x0 + dx ;
145
+ cell [ indexJ ] [ 2 ] = y0 + dy ;
153
146
154
147
if ( ! pointsShapeRectangle ( cell ) ) {
155
148
// reject result to rectangles with ensure areas
156
149
for ( var j = 0 ; j < len ; j ++ ) {
157
- for ( var k = 0 ; k < 2 ; k ++ ) {
150
+ for ( var k = 0 ; k < 3 ; k ++ ) {
158
151
cell [ j ] [ k ] = copyPolygons [ indexI ] [ j ] [ k ] ;
159
152
}
160
153
}
161
154
}
162
155
} else { // other polylines
163
- cell [ indexJ ] [ 0 ] = x0 + dx ;
164
- cell [ indexJ ] [ 1 ] = y0 + dy ;
156
+ cell [ indexJ ] [ 1 ] = x0 + dx ;
157
+ cell [ indexJ ] [ 2 ] = y0 + dy ;
165
158
}
166
159
167
160
redraw ( ) ;
@@ -211,10 +204,10 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
211
204
var maxY ;
212
205
if ( onRect ) {
213
206
// compute bounding box
214
- minX = calcMin ( cell , 0 ) ;
215
- minY = calcMin ( cell , 1 ) ;
216
- maxX = calcMax ( cell , 0 ) ;
217
- maxY = calcMax ( cell , 1 ) ;
207
+ minX = calcMin ( cell , 1 ) ;
208
+ minY = calcMin ( cell , 2 ) ;
209
+ maxX = calcMax ( cell , 1 ) ;
210
+ maxY = calcMax ( cell , 2 ) ;
218
211
}
219
212
220
213
vertexDragOptions [ i ] = [ ] ;
@@ -228,8 +221,8 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
228
221
continue ;
229
222
}
230
223
231
- var x = cell [ j ] [ 0 ] ;
232
- var y = cell [ j ] [ 1 ] ;
224
+ var x = cell [ j ] [ 1 ] ;
225
+ var y = cell [ j ] [ 2 ] ;
233
226
234
227
var rIcon = 3 ;
235
228
var button = g . append ( onRect ? 'rect' : 'circle' )
@@ -301,11 +294,11 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
301
294
302
295
for ( var i = 0 ; i < polygons . length ; i ++ ) {
303
296
for ( var j = 0 ; j < polygons [ i ] . length ; j ++ ) {
304
- var x0 = copyPolygons [ i ] [ j ] [ 0 ] ;
305
- var y0 = copyPolygons [ i ] [ j ] [ 1 ] ;
297
+ var x0 = copyPolygons [ i ] [ j ] [ 1 ] ;
298
+ var y0 = copyPolygons [ i ] [ j ] [ 2 ] ;
306
299
307
- polygons [ i ] [ j ] [ 0 ] = x0 + dx ;
308
- polygons [ i ] [ j ] [ 1 ] = y0 + dy ;
300
+ polygons [ i ] [ j ] [ 1 ] = x0 + dx ;
301
+ polygons [ i ] [ j ] [ 2 ] = y0 + dy ;
309
302
}
310
303
}
311
304
}
@@ -344,14 +337,25 @@ function displayOutlines(polygonsIn, outlines, dragOptions, nCalls) {
344
337
}
345
338
}
346
339
347
- function providePath ( cell , isOpenMode ) {
348
- return cell . join ( 'L' ) + (
349
- isOpenMode ? '' : 'L' + cell [ 0 ]
350
- ) ;
351
- }
352
-
353
- function writePaths ( paths , isOpenMode ) {
354
- return paths . length > 0 ? 'M' + paths . join ( 'M' ) + ( isOpenMode ? '' : 'Z' ) : 'M0,0Z' ;
340
+ function writePaths ( polygons , isOpenMode ) {
341
+ var nI = polygons . length ;
342
+ if ( ! nI ) return 'M0,0Z' ;
343
+
344
+ var str = '' ;
345
+ for ( var i = 0 ; i < nI ; i ++ ) {
346
+ var nJ = polygons [ i ] . length ;
347
+ for ( var j = 0 ; j < nJ ; j ++ ) {
348
+ var nK = polygons [ i ] [ j ] . length ;
349
+ for ( var k = 0 ; k < nK ; k ++ ) {
350
+ str += polygons [ i ] [ j ] [ k ] ;
351
+ if ( k > 0 && k < nK - 1 ) {
352
+ str += ',' ;
353
+ }
354
+ }
355
+ }
356
+ if ( ! isOpenMode ) str += 'Z' ;
357
+ }
358
+ return str ;
355
359
}
356
360
357
361
function readPaths ( str , plotinfo , size , isActiveShape ) {
@@ -378,6 +382,7 @@ function readPaths(str, plotinfo, size, isActiveShape) {
378
382
var newPos = [ ] ;
379
383
380
384
var c = cmd [ i ] [ 0 ] ;
385
+ var w = c ;
381
386
switch ( c ) {
382
387
case 'M' :
383
388
newPoly ( ) ;
@@ -396,18 +401,21 @@ function readPaths(str, plotinfo, size, isActiveShape) {
396
401
break ;
397
402
398
403
case 'H' :
404
+ w = 'L' ; // convert to line
399
405
x = + cmd [ i ] [ 1 ] ;
400
406
newPos . push ( [ x , y ] ) ;
401
407
402
408
break ;
403
409
404
410
case 'V' :
411
+ w = 'L' ; // convert to line
405
412
y = + cmd [ i ] [ 1 ] ;
406
413
newPos . push ( [ x , y ] ) ;
407
414
408
415
break ;
409
416
410
417
case 'A' :
418
+ w = 'L' ; // convert to line (for now)
411
419
var rx = + cmd [ i ] [ 1 ] ;
412
420
var ry = + cmd [ i ] [ 2 ] ;
413
421
if ( ! + cmd [ i ] [ 4 ] ) {
@@ -438,21 +446,25 @@ function readPaths(str, plotinfo, size, isActiveShape) {
438
446
439
447
if ( ! plotinfo || ! ( plotinfo . xaxis && plotinfo . yaxis ) ) {
440
448
polys [ n ] . push ( [
449
+ w ,
441
450
x ,
442
451
y
443
452
] ) ;
444
453
} else if ( plotinfo . domain ) {
445
454
polys [ n ] . push ( [
455
+ w ,
446
456
plotinfo . domain . x [ 0 ] + x / size . w ,
447
457
plotinfo . domain . y [ 1 ] - y / size . h
448
458
] ) ;
449
459
} else if ( isActiveShape === false ) {
450
460
polys [ n ] . push ( [
461
+ w ,
451
462
p2r ( plotinfo . xaxis , x - plotinfo . xaxis . _offset ) ,
452
463
p2r ( plotinfo . yaxis , y - plotinfo . yaxis . _offset )
453
464
] ) ;
454
465
} else {
455
466
polys [ n ] . push ( [
467
+ w ,
456
468
p2r ( plotinfo . xaxis , x ) ,
457
469
p2r ( plotinfo . yaxis , y )
458
470
] ) ;
@@ -470,8 +482,8 @@ function fixDatesOnPaths(path, xaxis, yaxis) {
470
482
if ( ! xIsDate && ! yIsDate ) return path ;
471
483
472
484
for ( var i = 0 ; i < path . length ; i ++ ) {
473
- if ( xIsDate ) path [ i ] [ 0 ] = path [ i ] [ 0 ] . replace ( ' ' , '_' ) ;
474
- if ( yIsDate ) path [ i ] [ 1 ] = path [ i ] [ 1 ] . replace ( ' ' , '_' ) ;
485
+ if ( xIsDate ) path [ i ] [ 1 ] = path [ i ] [ 1 ] . replace ( ' ' , '_' ) ;
486
+ if ( yIsDate ) path [ i ] [ 2 ] = path [ i ] [ 2 ] . replace ( ' ' , '_' ) ;
475
487
}
476
488
477
489
return path ;
@@ -482,8 +494,8 @@ function almostEq(a, b) {
482
494
}
483
495
484
496
function dist ( a , b ) {
485
- var dx = b [ 0 ] - a [ 0 ] ;
486
- var dy = b [ 1 ] - a [ 1 ] ;
497
+ var dx = b [ 1 ] - a [ 1 ] ;
498
+ var dy = b [ 2 ] - a [ 2 ] ;
487
499
return Math . sqrt (
488
500
dx * dx +
489
501
dy * dy
@@ -509,7 +521,7 @@ function calcMax(cell, dim) {
509
521
function pointsShapeRectangle ( cell , len ) {
510
522
if ( ! len ) len = cell . length ;
511
523
if ( len !== 4 ) return false ;
512
- for ( var j = 0 ; j < 2 ; j ++ ) {
524
+ for ( var j = 1 ; j < 3 ; j ++ ) {
513
525
var e01 = cell [ 0 ] [ j ] - cell [ 1 ] [ j ] ;
514
526
var e32 = cell [ 3 ] [ j ] - cell [ 2 ] [ j ] ;
515
527
@@ -522,8 +534,8 @@ function pointsShapeRectangle(cell, len) {
522
534
523
535
// N.B. rotated rectangles are not valid rects since rotation is not supported in shapes for now.
524
536
if (
525
- ! almostEq ( cell [ 0 ] [ 0 ] , cell [ 1 ] [ 0 ] ) &&
526
- ! almostEq ( cell [ 0 ] [ 0 ] , cell [ 3 ] [ 0 ] )
537
+ ! almostEq ( cell [ 0 ] [ 1 ] , cell [ 1 ] [ 1 ] ) &&
538
+ ! almostEq ( cell [ 0 ] [ 1 ] , cell [ 3 ] [ 1 ] )
527
539
) return false ;
528
540
529
541
// reject cases with zero area
@@ -650,23 +662,24 @@ function addNewShapes(outlines, dragOptions) {
650
662
}
651
663
var isOpenMode = openMode ( dragmode ) ;
652
664
653
- var newShapes = [ ] ;
654
665
var polygons = readPaths ( d , plotinfo , gd . _fullLayout . _size , isActiveShape ) ;
655
666
if ( isOpenMode ) {
656
667
var last = polygons [ 0 ] . length - 1 ;
657
668
if ( // ensure first and last positions are not the same on an open path
658
- polygons [ 0 ] [ 0 ] [ 0 ] === polygons [ 0 ] [ last ] [ 0 ] &&
659
- polygons [ 0 ] [ 0 ] [ 1 ] === polygons [ 0 ] [ last ] [ 1 ]
669
+ polygons [ 0 ] [ 0 ] [ 1 ] === polygons [ 0 ] [ last ] [ 1 ] &&
670
+ polygons [ 0 ] [ 0 ] [ 2 ] === polygons [ 0 ] [ last ] [ 2 ]
660
671
) {
661
672
polygons [ 0 ] . pop ( ) ;
662
673
}
663
674
}
675
+
676
+ var newShapes = [ ] ;
664
677
for ( var i = 0 ; i < polygons . length ; i ++ ) {
665
678
var cell = polygons [ i ] ;
666
679
var len = cell . length ;
667
680
if (
668
- cell [ 0 ] [ 0 ] === cell [ len - 1 ] [ 0 ] &&
669
- cell [ 0 ] [ 1 ] === cell [ len - 1 ] [ 1 ]
681
+ cell [ 0 ] [ 1 ] === cell [ len - 1 ] [ 1 ] &&
682
+ cell [ 0 ] [ 2 ] === cell [ len - 1 ] [ 2 ]
670
683
) {
671
684
len -= 1 ;
672
685
}
@@ -697,29 +710,29 @@ function addNewShapes(outlines, dragOptions) {
697
710
pointsShapeRectangle ( cell , len ) // should pass len here which is equal to cell.length - 1 i.e. because of the closing point
698
711
) {
699
712
shape . type = 'rect' ;
700
- shape . x0 = cell [ 0 ] [ 0 ] ;
701
- shape . y0 = cell [ 0 ] [ 1 ] ;
702
- shape . x1 = cell [ 2 ] [ 0 ] ;
703
- shape . y1 = cell [ 2 ] [ 1 ] ;
713
+ shape . x0 = cell [ 0 ] [ 1 ] ;
714
+ shape . y0 = cell [ 0 ] [ 2 ] ;
715
+ shape . x1 = cell [ 2 ] [ 1 ] ;
716
+ shape . y1 = cell [ 2 ] [ 2 ] ;
704
717
} else if (
705
718
dragmode === 'linedraw'
706
719
) {
707
720
shape . type = 'line' ;
708
- shape . x0 = cell [ 0 ] [ 0 ] ;
709
- shape . y0 = cell [ 0 ] [ 1 ] ;
710
- shape . x1 = cell [ 1 ] [ 0 ] ;
711
- shape . y1 = cell [ 1 ] [ 1 ] ;
721
+ shape . x0 = cell [ 0 ] [ 1 ] ;
722
+ shape . y0 = cell [ 0 ] [ 2 ] ;
723
+ shape . x1 = cell [ 1 ] [ 1 ] ;
724
+ shape . y1 = cell [ 1 ] [ 2 ] ;
712
725
} else if (
713
726
dragmode === 'ellipsedraw' &&
714
727
( isActiveShape === false || pointsShapeEllipse ( cell , len ) ) // should pass len here which is equal to cell.length - 1 i.e. because of the closing point
715
728
) {
716
729
shape . type = 'circle' ; // an ellipse!
717
730
var pos = { } ;
718
731
if ( isActiveShape === false ) {
719
- var x0 = ( cell [ i090 ] [ 0 ] + cell [ i270 ] [ 0 ] ) / 2 ;
720
- var y0 = ( cell [ i000 ] [ 1 ] + cell [ i180 ] [ 1 ] ) / 2 ;
721
- var rx = ( cell [ i270 ] [ 0 ] - cell [ i090 ] [ 0 ] + cell [ i180 ] [ 0 ] - cell [ i000 ] [ 0 ] ) / 2 ;
722
- var ry = ( cell [ i270 ] [ 1 ] - cell [ i090 ] [ 1 ] + cell [ i180 ] [ 1 ] - cell [ i000 ] [ 1 ] ) / 2 ;
732
+ var x0 = ( cell [ i090 ] [ 1 ] + cell [ i270 ] [ 1 ] ) / 2 ;
733
+ var y0 = ( cell [ i000 ] [ 2 ] + cell [ i180 ] [ 2 ] ) / 2 ;
734
+ var rx = ( cell [ i270 ] [ 1 ] - cell [ i090 ] [ 1 ] + cell [ i180 ] [ 1 ] - cell [ i000 ] [ 1 ] ) / 2 ;
735
+ var ry = ( cell [ i270 ] [ 2 ] - cell [ i090 ] [ 2 ] + cell [ i180 ] [ 2 ] - cell [ i000 ] [ 2 ] ) / 2 ;
723
736
pos = ellipseOver ( {
724
737
x0 : x0 ,
725
738
y0 : y0 ,
@@ -728,10 +741,10 @@ function addNewShapes(outlines, dragOptions) {
728
741
} ) ;
729
742
} else {
730
743
pos = ellipseOver ( {
731
- x0 : ( cell [ i000 ] [ 0 ] + cell [ i180 ] [ 0 ] ) / 2 ,
732
- y0 : ( cell [ i000 ] [ 1 ] + cell [ i180 ] [ 1 ] ) / 2 ,
733
- x1 : cell [ i045 ] [ 0 ] ,
734
- y1 : cell [ i045 ] [ 1 ]
744
+ x0 : ( cell [ i000 ] [ 1 ] + cell [ i180 ] [ 1 ] ) / 2 ,
745
+ y0 : ( cell [ i000 ] [ 2 ] + cell [ i180 ] [ 2 ] ) / 2 ,
746
+ x1 : cell [ i045 ] [ 1 ] ,
747
+ y1 : cell [ i045 ] [ 2 ]
735
748
} ) ;
736
749
}
737
750
@@ -745,9 +758,7 @@ function addNewShapes(outlines, dragOptions) {
745
758
fixDatesOnPaths ( cell , xaxis , yaxis ) ;
746
759
}
747
760
748
- shape . path = writePaths ( [
749
- providePath ( cell , isOpenMode )
750
- ] , isOpenMode ) ;
761
+ shape . path = writePaths ( [ cell ] , isOpenMode ) ;
751
762
}
752
763
753
764
newShapes . push ( shape ) ;
0 commit comments